📄 kglobalaccel.cpp
字号:
/* This file is part of the KDE libraries Copyright (C) 1998 Mark Donohoe <donohoe@kde.org>, Jani Jaakkola (jjaakkol@cs.helsinki.fi), Nicolas Hadacek <hadacek@via.ecp.fr> Matthias Ettrich (ettrich@kde.org) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.*/#include "kglobalaccel.h"#include <X11/X.h>#include <X11/Xlib.h>#include <X11/keysym.h>#include <string.h>#include <qkeycode.h>#include <qlayout.h>#include <qpainter.h>#include <qapplication.h>#include <qdrawutil.h>#include <qmessagebox.h>#include <kapp.h>// NOTE ABOUT CONFIGURATION CHANGES// Test if keys enabled because these keys have made X server grabsKGlobalAccel::KGlobalAccel(bool _do_not_grab) : QObject(), aKeyDict(100){ aAvailableId = 1; bEnabled = true; aGroup = "Global Keys"; do_not_grab =_do_not_grab;}KGlobalAccel::KGlobalAccel(QWidget * parent, const char * name, bool _do_not_grab) : QObject(parent, name), aKeyDict(100) { aAvailableId = 1; bEnabled = true; aGroup = "Global Keys"; do_not_grab =_do_not_grab;}KGlobalAccel::~KGlobalAccel(){ setEnabled( false );}void KGlobalAccel::clear(){ setEnabled( false ); aKeyDict.clear();}void KGlobalAccel::connectItem( const char * action, const QObject* receiver, const char* member, bool activate ){ KKeyEntry *pEntry = aKeyDict[ action ]; if ( !pEntry ) { QString str; str.sprintf( "KGlobalAccel : Cannot connect action %s"\ "which is not in the object dictionary", action ); warning( str ); return; } pEntry->receiver = receiver; pEntry->member = member; pEntry->aAccelId = aAvailableId; aAvailableId++; setItemEnabled( action, activate );}uint KGlobalAccel::count() const{ return aKeyDict.count();}uint KGlobalAccel::currentKey( const char * action ){ KKeyEntry *pEntry = aKeyDict[ action ]; if ( !pEntry ) return 0; else return pEntry->aCurrentKeyCode;}uint KGlobalAccel::defaultKey( const char * action ){ KKeyEntry *pEntry = aKeyDict[ action ]; if ( !pEntry ) return 0; else return pEntry->aDefaultKeyCode;}void KGlobalAccel::disconnectItem( const char * action, const QObject* /*receiver*/, const char* /*member*/ ){ KKeyEntry *pEntry = aKeyDict[ action ]; if ( !pEntry ) return; }const char * KGlobalAccel::findKey( int key ) const{ QDictIterator<KKeyEntry> aKeyIt( aKeyDict ); aKeyIt.toFirst();#define pE aKeyIt.current() while ( pE ) { if ( (unsigned int)key == pE->aCurrentKeyCode ) return aKeyIt.currentKey(); ++aKeyIt; }#undef pE return 0; }bool grabFailed;static int XGrabErrorHandler( Display *, XErrorEvent *e ) { if ( e->error_code != BadAccess ) { warning( "grabKey: got X error %d instead of BadAccess", e->type ); } grabFailed = true; return 0;}bool KGlobalAccel::grabKey( uint keysym, uint mod ) { // Most of this comes from kpanel/main.C // Copyright (C) 1996,97 Matthias Ettrich static int NumLockMask = 0; if (do_not_grab) return true; if (!keysym || !XKeysymToKeycode(qt_xdisplay(), keysym)) return false; if (!NumLockMask){ XModifierKeymap* xmk = XGetModifierMapping(qt_xdisplay()); int i; for (i=0; i<8; i++){ if (xmk->modifiermap[xmk->max_keypermod * i] == XKeysymToKeycode(qt_xdisplay(), XK_Num_Lock)) NumLockMask = (1<<i); } } grabFailed = false; // We wan't to catch only our own errors XSync(qt_xdisplay(),0); XErrorHandler savedErrorHandler=XSetErrorHandler(XGrabErrorHandler); XGrabKey(qt_xdisplay(), XKeysymToKeycode(qt_xdisplay(), keysym), mod, qt_xrootwin(), True, GrabModeAsync, GrabModeSync); XGrabKey(qt_xdisplay(), XKeysymToKeycode(qt_xdisplay(), keysym), mod | LockMask, qt_xrootwin(), True, GrabModeAsync, GrabModeSync); XGrabKey(qt_xdisplay(), XKeysymToKeycode(qt_xdisplay(), keysym), mod | NumLockMask, qt_xrootwin(), True, GrabModeAsync, GrabModeSync); XGrabKey(qt_xdisplay(), XKeysymToKeycode(qt_xdisplay(), keysym), mod | LockMask | NumLockMask, qt_xrootwin(), True, GrabModeAsync, GrabModeSync); XSync(qt_xdisplay(),0); XSetErrorHandler(savedErrorHandler); if (grabFailed) { // FIXME: ungrab all successfull grabs! //warning("Global grab failed!"); return false; } return true;}bool KGlobalAccel::insertItem( const char* descr, const char * action, uint keyCode, bool configurable ){ KKeyEntry *pEntry = aKeyDict[ action ]; if ( pEntry ) removeItem( action ); pEntry = new KKeyEntry; aKeyDict.insert( action, pEntry ); pEntry->aDefaultKeyCode = keyCode; pEntry->aCurrentKeyCode = keyCode; pEntry->bConfigurable = configurable; pEntry->bEnabled = false; pEntry->aAccelId = 0; pEntry->receiver = 0; pEntry->member = 0; pEntry->descr = descr; return TRUE;}bool KGlobalAccel::insertItem( const char* descr, const char * action, const char * keyCode, bool configurable ){ uint iKeyCode = stringToKey( keyCode ); return insertItem(descr, action, iKeyCode, configurable);}bool KGlobalAccel::isEnabled(){ return bEnabled;}bool KGlobalAccel::isItemEnabled( const char *action ){ KKeyEntry *pEntry = aKeyDict[ action ]; if ( !pEntry ) return false; else return pEntry->bEnabled;}QDict<KKeyEntry> KGlobalAccel::keyDict(){ return aKeyDict;}void KGlobalAccel::readSettings(){ QString s; //KConfig *pConfig = kapp->getConfig(); KConfig globalConfig;// this way we are certain to get the global stuff! KConfig *pConfig = &globalConfig; pConfig->setGroup( aGroup.data() ); QDictIterator<KKeyEntry> aKeyIt( aKeyDict ); aKeyIt.toFirst();#define pE aKeyIt.current() // first ungrab while ( pE ) { s = pConfig->readEntry( aKeyIt.currentKey() ); if ( pE->bEnabled ) { uint keysym = keyToXSym( pE->aCurrentKeyCode ); uint mod = keyToXMod( pE->aCurrentKeyCode ); ungrabKey( keysym, mod ); } ++aKeyIt; } // then grab aKeyIt.toFirst(); while ( pE ) { s = pConfig->readEntry( aKeyIt.currentKey() ); if ( s.isNull() ) pE->aConfigKeyCode = pE->aDefaultKeyCode; else pE->aConfigKeyCode = stringToKey( s.data() ); pE->aCurrentKeyCode = pE->aConfigKeyCode; if ( pE->bEnabled ) { uint keysym = keyToXSym( pE->aCurrentKeyCode ); uint mod = keyToXMod( pE->aCurrentKeyCode ); grabKey( keysym, mod ); } ++aKeyIt; }#undef pE} void KGlobalAccel::removeItem( const char * action ){ KKeyEntry *pEntry = aKeyDict[ action ]; if ( !pEntry ) return; if ( pEntry->aAccelId ) { } aKeyDict.remove( action );}void KGlobalAccel::setConfigGroup( const char *group ){ aGroup = group;}const char *KGlobalAccel::configGroup(){ return aGroup.data();}void KGlobalAccel::setEnabled( bool activate ){ QDictIterator<KKeyEntry> aKeyIt( aKeyDict ); aKeyIt.toFirst();#define pE aKeyIt.current() while ( pE ) { setItemEnabled( aKeyIt.currentKey(), activate ); ++aKeyIt; }#undef pE bEnabled = activate;}void KGlobalAccel::setItemEnabled( const char * action, bool activate ){ KKeyEntry *pEntry = aKeyDict[ action ]; if ( !pEntry ) { QString str; str.sprintf( "KGlobalAccel : cannont enable action %s"\ "which is not in the object dictionary", action ); warning( str ); return; } bool old = pEntry->bEnabled; pEntry->bEnabled = activate; if ( pEntry->bEnabled == old ) return; if ( pEntry->aCurrentKeyCode == 0 ) return; uint keysym = keyToXSym( pEntry->aCurrentKeyCode ); uint mod = keyToXMod( pEntry->aCurrentKeyCode ); if ( keysym == NoSymbol ) return; if ( pEntry->bEnabled ) { grabKey( keysym, mod ); } else { ungrabKey( keysym, mod ); } return;}bool KGlobalAccel::setKeyDict( QDict<KKeyEntry> nKeyDict ){ // ungrab all connected and enabled keys QDictIterator<KKeyEntry> *aKeyIt = new QDictIterator<KKeyEntry>( aKeyDict ); aKeyIt->toFirst();#define pE aKeyIt->current() while( pE ) { QString s; if ( pE->bEnabled ) { uint keysym = keyToXSym( pE->aCurrentKeyCode ); uint mod = keyToXMod( pE->aCurrentKeyCode ); ungrabKey( keysym, mod ); } ++*aKeyIt; }#undef pE // Clear the dictionary aKeyDict.clear(); // Insert the new items into the dictionary and reconnect if neccessary // Note also swap config and current key codes !!!!!! aKeyIt = new QDictIterator<KKeyEntry>( nKeyDict ); aKeyIt->toFirst();#define pE aKeyIt->current() KKeyEntry *pEntry; while( pE ) { pEntry = new KKeyEntry; aKeyDict.insert( aKeyIt->currentKey(), pEntry ); pEntry->aDefaultKeyCode = pE->aDefaultKeyCode; // Not we write config key code to current key code !! pEntry->aCurrentKeyCode = pE->aConfigKeyCode; pEntry->aConfigKeyCode = pE->aConfigKeyCode; pEntry->bConfigurable = pE->bConfigurable; pEntry->aAccelId = pE->aAccelId; pEntry->receiver = pE->receiver; pEntry->member = pE->member; pEntry->descr = pE->descr; // tanghus pEntry->bEnabled = pE->bEnabled; if ( pEntry->bEnabled ) { uint keysym = keyToXSym( pEntry->aCurrentKeyCode ); uint mod = keyToXMod( pEntry->aCurrentKeyCode ); grabKey( keysym, mod ); } ++*aKeyIt; }#undef pE delete aKeyIt; return true;}bool KGlobalAccel::ungrabKey( uint keysym, uint mod ) { // Most of this comes from kpanel/main.C // Copyright (C) 1996,97 Matthias Ettrich static int NumLockMask = 0; if (do_not_grab) return true; if (!keysym||!XKeysymToKeycode(qt_xdisplay(), keysym)) return false; if (!NumLockMask){ XModifierKeymap* xmk = XGetModifierMapping(qt_xdisplay()); int i; for (i=0; i<8; i++){ if (xmk->modifiermap[xmk->max_keypermod * i] == XKeysymToKeycode(qt_xdisplay(), XK_Num_Lock)) NumLockMask = (1<<i); } } grabFailed = false; // We wan't to catch only our own errors XSync(qt_xdisplay(),0); XErrorHandler savedErrorHandler=XSetErrorHandler(XGrabErrorHandler); XUngrabKey(qt_xdisplay(), XKeysymToKeycode(qt_xdisplay(), keysym), mod, qt_xrootwin()); XUngrabKey(qt_xdisplay(), XKeysymToKeycode(qt_xdisplay(), keysym), mod | LockMask, qt_xrootwin()); XUngrabKey(qt_xdisplay(), XKeysymToKeycode(qt_xdisplay(), keysym), mod | NumLockMask, qt_xrootwin()); XUngrabKey(qt_xdisplay(), XKeysymToKeycode(qt_xdisplay(), keysym), mod | LockMask | NumLockMask, qt_xrootwin()); XSync(qt_xdisplay(),0); XSetErrorHandler(savedErrorHandler); if (grabFailed) { // FIXME: ungrab all successfull grabs! //warning("Global grab failed!"); return false; } return true;}void KGlobalAccel::writeSettings(){ // KConfig *pConfig = kapp->getConfig(); KConfig globalConfig;// this way we are certain to get the global stuff! KConfig *pConfig = &globalConfig; pConfig->setGroup( aGroup.data() ); QDictIterator<KKeyEntry> aKeyIt( aKeyDict ); aKeyIt.toFirst(); while ( aKeyIt.current() ) { if ( aKeyIt.current()->bConfigurable ){ pConfig->writeEntry( aKeyIt.currentKey(), keyToString( aKeyIt.current()->aCurrentKeyCode), true, true); } ++aKeyIt; } pConfig->sync();}bool KGlobalAccel::x11EventFilter( const XEvent *event_ ) { if ( aKeyDict.isEmpty() ) return false; if ( event_->type != KeyPress ) return false; uint mod=event_->xkey.state & (ControlMask | ShiftMask | Mod1Mask); uint keysym= XKeycodeToKeysym(qt_xdisplay(), event_->xkey.keycode, 0); QDictIterator<KKeyEntry> *aKeyIt = new QDictIterator<KKeyEntry>( aKeyDict ); aKeyIt->toFirst();#define pE aKeyIt->current() while( pE ) { int kc = pE->aCurrentKeyCode; if ( mod == keyToXMod( kc ) && keysym == keyToXSym( kc ) ) { break; } ++*aKeyIt; } if ( !pE ) { return false; } if ( !pE ) { return false; } XAllowEvents(qt_xdisplay(), AsyncKeyboard, CurrentTime); XUngrabKeyboard(qt_xdisplay(), CurrentTime); XSync(qt_xdisplay(), false); connect( this, SIGNAL( activated() ), pE->receiver, pE->member); emit activated(); disconnect( this, SIGNAL( activated() ), pE->receiver, pE->member ); return true;}/*****************************************************************************/uint keyToXMod( uint keyCode ){ uint mod = 0; if ( keyCode == 0 ) return mod; if ( keyCode & SHIFT ) mod |= ShiftMask; if ( keyCode & CTRL ) mod |= ControlMask; if ( keyCode & ALT ) mod |= Mod1Mask; return mod;}uint keyToXSym( uint keyCode ){ char *toks[4], *next_tok; int nb_toks = 0; char sKey[200]; uint keysym = 0; QString s = keyToString( keyCode); strncpy(sKey, (const char *)s.data(), 200); if ( s.isEmpty() ) return keysym; next_tok = strtok( sKey, "+" ); if ( next_tok == 0L ) return 0; do { toks[nb_toks] = next_tok; nb_toks++; if ( nb_toks == 5 ) return 0; next_tok = strtok( 0L, "+" ); } while ( next_tok != 0L ); // Test for exactly one key (other tokens are accelerators) // Fill the keycode with infos bool keyFound = FALSE; for ( int i=0; i<nb_toks; i++ ) { if ( strcmp( toks[i], "SHIFT" ) != 0 && strcmp( toks[i], "CTRL" ) != 0 && strcmp( toks[i], "ALT" ) != 0 ) { if ( keyFound ) return 0; keyFound = TRUE; QString l = toks[i]; l = l.lower(); keysym = XStringToKeysym(l.data()); if (keysym == NoSymbol){ keysym = XStringToKeysym( toks[i] ); } if ( keysym == NoSymbol ) { return 0; } } } return keysym;}#include "kglobalaccel.moc"
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -