diff options
Diffstat (limited to 'kdecore/kglobalaccel_x11.cpp')
-rw-r--r-- | kdecore/kglobalaccel_x11.cpp | 441 |
1 files changed, 0 insertions, 441 deletions
diff --git a/kdecore/kglobalaccel_x11.cpp b/kdecore/kglobalaccel_x11.cpp deleted file mode 100644 index c2f7a3829..000000000 --- a/kdecore/kglobalaccel_x11.cpp +++ /dev/null @@ -1,441 +0,0 @@ -/* This file is part of the KDE libraries - Copyright (C) 2001,2002 Ellis Whitehead <ellis@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., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. -*/ - -#include "config.h" - -#include <tqwindowdefs.h> -#ifdef Q_WS_X11 - -#include "kglobalaccel_x11.h" -#include "kglobalaccel.h" -#include "kkeyserver_x11.h" - -#include <tqpopupmenu.h> -#include <tqregexp.h> -#include <tqwidget.h> -#include <tqmetaobject.h> -#include <tqucomextra_p.h> -#include <kapplication.h> -#include <kdebug.h> -#include <kkeynative.h> - -#ifdef Q_WS_X11 -#include <kxerrorhandler.h> -#endif - -#include <X11/X.h> -#include <X11/Xlib.h> -#include <X11/keysym.h> -#include <fixx11h.h> - -extern "C" { - static int XGrabErrorHandler( Display *, XErrorEvent *e ) { - if ( e->error_code != BadAccess ) { - kdWarning() << "grabKey: got X error " << e->type << " instead of BadAccess\n"; - } - return 1; - } -} - -// g_keyModMaskXAccel -// mask of modifiers which can be used in shortcuts -// (meta, alt, ctrl, shift) -// g_keyModMaskXOnOrOff -// mask of modifiers where we don't care whether they are on or off -// (caps lock, num lock, scroll lock) -static uint g_keyModMaskXAccel = 0; -static uint g_keyModMaskXOnOrOff = 0; - -static void calculateGrabMasks() -{ - g_keyModMaskXAccel = KKeyServer::accelModMaskX(); - g_keyModMaskXOnOrOff = - KKeyServer::modXLock() | - KKeyServer::modXNumLock() | - KKeyServer::modXScrollLock() | - KKeyServer::modXModeSwitch(); - //kdDebug() << "g_keyModMaskXAccel = " << g_keyModMaskXAccel - // << "g_keyModMaskXOnOrOff = " << g_keyModMaskXOnOrOff << endl; -} - -//---------------------------------------------------- - -static TQValueList< KGlobalAccelPrivate* >* all_accels = 0; - -KGlobalAccelPrivate::KGlobalAccelPrivate() -: KAccelBase( KAccelBase::NATIVE_KEYS ) -, m_blocked( false ) -, m_blockingDisabled( false ) -, m_suspended( false ) -{ - if( all_accels == NULL ) - all_accels = new TQValueList< KGlobalAccelPrivate* >; - all_accels->append( this ); - m_sConfigGroup = "Global Shortcuts"; - kapp->installX11EventFilter( this ); - connect(kapp, TQT_SIGNAL(coreFakeKeyPress(unsigned int)), this, TQT_SLOT(fakeKeyPressed(unsigned int))); -} - -KGlobalAccelPrivate::~KGlobalAccelPrivate() -{ - // TODO: Need to release all grabbed keys if the main window is not shutting down. - //for( CodeModMap::ConstIterator it = m_rgCodeModToAction.begin(); it != m_rgCodeModToAction.end(); ++it ) { - // const CodeMod& codemod = it.key(); - //} - all_accels->remove( this ); - if( all_accels->count() == 0 ) { - delete all_accels; - all_accels = NULL; - } -} - -void KGlobalAccelPrivate::setEnabled( bool bEnable ) -{ - m_bEnabled = bEnable; - updateConnections(); -} - -void KGlobalAccelPrivate::blockShortcuts( bool block ) -{ - if( all_accels == NULL ) - return; - for( TQValueList< KGlobalAccelPrivate* >::ConstIterator it = all_accels->begin(); - it != all_accels->end(); - ++it ) { - if( (*it)->m_blockingDisabled ) - continue; - (*it)->m_blocked = block; - (*it)->updateConnections(); - } -} - -void KGlobalAccelPrivate::disableBlocking( bool block ) -{ - m_blockingDisabled = block; -} - -bool KGlobalAccelPrivate::isEnabledInternal() const -{ - return KAccelBase::isEnabled() && !m_blocked; -} - -// see #117169 - the bug is hard to reproduce, probably somewhere in X, testcase would be probably -// difficult to make, and so on - just don't release the grabs and only ignore the events instead -void KGlobalAccelPrivate::suspend( bool s ) -{ - m_suspended = s; -} - -bool KGlobalAccelPrivate::emitSignal( Signal ) -{ - return false; -} - -bool KGlobalAccelPrivate::connectKey( KAccelAction& action, const KKeyServer::Key& key ) - { return grabKey( key, true, &action ); } -bool KGlobalAccelPrivate::connectKey( const KKeyServer::Key& key ) - { return grabKey( key, true, 0 ); } -bool KGlobalAccelPrivate::disconnectKey( KAccelAction& action, const KKeyServer::Key& key ) - { return grabKey( key, false, &action ); } -bool KGlobalAccelPrivate::disconnectKey( const KKeyServer::Key& key ) - { return grabKey( key, false, 0 ); } - -bool KGlobalAccelPrivate::grabKey( const KKeyServer::Key& key, bool bGrab, KAccelAction* pAction ) -{ - if( !key.code() ) { - kdWarning(125) << "KGlobalAccelPrivate::grabKey( " << key.key().toStringInternal() << ", " << bGrab << ", \"" << (pAction ? pAction->name().latin1() : "(null)") << "\" ): Tried to grab key with null code." << endl; - return false; - } - - // Make sure that grab masks have been initialized. - if( g_keyModMaskXOnOrOff == 0 ) - calculateGrabMasks(); - - uchar keyCodeX = key.code(); - uint keyModX = key.mod() & g_keyModMaskXAccel; // Get rid of any non-relevant bits in mod - // HACK: make Alt+Print work - // only do this for the Xorg default keyboard keycodes, - // other mappings (e.g. evdev) don't need or want it - if( key.sym() == XK_Sys_Req && XKeycodeToKeysym( qt_xdisplay(), 111, 0 ) == XK_Print ) { - keyModX |= KKeyServer::modXAlt(); - keyCodeX = 111; - } - -#ifndef __osf__ -// this crashes under Tru64 so ..... - kdDebug(125) << TQString(TQString( "grabKey( key: '%1', bGrab: %2 ): keyCodeX: %3 keyModX: %4\n" ) - .arg( key.key().toStringInternal() ).arg( bGrab ) - .arg( keyCodeX, 0, 16 ).arg( keyModX, 0, 16 )); -#endif - if( !keyCodeX ) - return false; - -#ifdef Q_WS_X11 - KXErrorHandler handler( XGrabErrorHandler ); -#endif - // We'll have to grab 8 key modifier combinations in order to cover all - // combinations of CapsLock, NumLock, ScrollLock. - // Does anyone with more X-savvy know how to set a mask on qt_xrootwin so that - // the irrelevant bits are always ignored and we can just make one XGrabKey - // call per accelerator? -- ellis -#ifndef NDEBUG - TQString sDebug = TQString("\tcode: 0x%1 state: 0x%2 | ").arg(keyCodeX,0,16).arg(keyModX,0,16); -#endif - uint keyModMaskX = ~g_keyModMaskXOnOrOff; - for( uint irrelevantBitsMask = 0; irrelevantBitsMask <= 0xff; irrelevantBitsMask++ ) { - if( (irrelevantBitsMask & keyModMaskX) == 0 ) { -#ifndef NDEBUG - sDebug += TQString("0x%3, ").arg(irrelevantBitsMask, 0, 16); -#endif - if( bGrab ) - XGrabKey( qt_xdisplay(), keyCodeX, keyModX | irrelevantBitsMask, - qt_xrootwin(), True, GrabModeAsync, GrabModeSync ); - else - XUngrabKey( qt_xdisplay(), keyCodeX, keyModX | irrelevantBitsMask, qt_xrootwin() ); - } - } -#ifndef NDEBUG - kdDebug(125) << sDebug << endl; -#endif - - bool failed = false; - if( bGrab ) { -#ifdef Q_WS_X11 - failed = handler.error( true ); // sync now -#endif - // If grab failed, then ungrab any grabs that could possibly succeed - if( failed ) { - kdDebug(125) << "grab failed!\n"; - for( uint m = 0; m <= 0xff; m++ ) { - if(( m & keyModMaskX ) == 0 ) - XUngrabKey( qt_xdisplay(), keyCodeX, keyModX | m, qt_xrootwin() ); - } - } - } - if( !failed ) - { - CodeMod codemod; - codemod.code = keyCodeX; - codemod.mod = keyModX; - if( key.mod() & KKeyServer::MODE_SWITCH ) - codemod.mod |= KKeyServer::MODE_SWITCH; - - if( bGrab ) - m_rgCodeModToAction.insert( codemod, pAction ); - else - m_rgCodeModToAction.remove( codemod ); - } - return !failed; -} - -bool KGlobalAccelPrivate::x11Event( XEvent* pEvent ) -{ - //kdDebug(125) << "x11EventFilter( type = " << pEvent->type << " )" << endl; - switch( pEvent->type ) { - case MappingNotify: - XRefreshKeyboardMapping( &pEvent->xmapping ); - x11MappingNotify(); - return false; - case XKeyPress: - if( x11KeyPress( pEvent ) ) - return true; - default: - return TQWidget::x11Event( pEvent ); - } -} - -void KGlobalAccelPrivate::x11MappingNotify() -{ - kdDebug(125) << "KGlobalAccelPrivate::x11MappingNotify()" << endl; - // Maybe the X modifier map has been changed. - KKeyServer::initializeMods(); - calculateGrabMasks(); - // Do new XGrabKey()s. - updateConnections(); -} - -void KGlobalAccelPrivate::fakeKeyPressed(unsigned int keyCode) { - CodeMod codemod; - codemod.code = keyCode; - codemod.mod = 0; - - KKey key = (keyCode, 0); - - kdDebug(125) << "fakeKeyPressed: seek " << key.toStringInternal() - << TQString(TQString( " keyCodeX: %1 keyCode: %2 keyModX: %3" ) - .arg( codemod.code, 0, 16 ).arg( keyCode, 0, 16 ).arg( codemod.mod, 0, 16 )) << endl; - - // Search for which accelerator activated this event: - if( !m_rgCodeModToAction.contains( codemod ) ) { -#ifndef NDEBUG - for( CodeModMap::ConstIterator it = m_rgCodeModToAction.begin(); it != m_rgCodeModToAction.end(); ++it ) { - KAccelAction* pAction = *it; - kdDebug(125) << "\tcode: " << TQString::number(it.key().code, 16) << " mod: " << TQString::number(it.key().mod, 16) - << (pAction ? TQString(" name: \"%1\" shortcut: %2").tqarg(pAction->name()).tqarg(pAction->shortcut().toStringInternal()) : TQString()) - << endl; - } -#endif - return; - } - - KAccelAction* pAction = m_rgCodeModToAction[codemod]; - - if( !pAction ) { - static bool recursion_block = false; - if( !recursion_block ) { - recursion_block = true; - TQPopupMenu* pMenu = createPopupMenu( 0, KKeySequence(key) ); - connect( pMenu, TQT_SIGNAL(activated(int)), this, TQT_SLOT(slotActivated(int)) ); - pMenu->exec( TQPoint( 0, 0 ) ); - disconnect( pMenu, TQT_SIGNAL(activated(int)), this, TQT_SLOT(slotActivated(int))); - delete pMenu; - recursion_block = false; - } - } else if( !pAction->objSlotPtr() || !pAction->isEnabled() ) - return; - else - activate( pAction, KKeySequence(key) ); -} - -bool KGlobalAccelPrivate::x11KeyPress( const XEvent *pEvent ) -{ - // do not change this line unless you really really know what you are doing (Matthias) - if ( !TQWidget::keyboardGrabber() && !TQApplication::activePopupWidget() ) { - XUngrabKeyboard( qt_xdisplay(), pEvent->xkey.time ); - XFlush( qt_xdisplay()); // avoid X(?) bug - } - - if( !isEnabledInternal() || m_suspended ) - return false; - - CodeMod codemod; - codemod.code = pEvent->xkey.keycode; - codemod.mod = pEvent->xkey.state & (g_keyModMaskXAccel | KKeyServer::MODE_SWITCH); - - // If numlock is active and a keypad key is pressed, XOR the SHIFT state. - // e.g., KP_4 => Shift+KP_Left, and Shift+KP_4 => KP_Left. - if( pEvent->xkey.state & KKeyServer::modXNumLock() ) { - // TODO: what's the xor operator in c++? - uint sym = XKeycodeToKeysym( qt_xdisplay(), codemod.code, 0 ); - // If this is a keypad key, - if( sym >= XK_KP_Space && sym <= XK_KP_9 ) { - switch( sym ) { - // Leave the following keys unaltered - // FIXME: The proper solution is to see which keysyms don't change when shifted. - case XK_KP_Multiply: - case XK_KP_Add: - case XK_KP_Subtract: - case XK_KP_Divide: - break; - default: - if( codemod.mod & KKeyServer::modXShift() ) - codemod.mod &= ~KKeyServer::modXShift(); - else - codemod.mod |= KKeyServer::modXShift(); - } - } - } - - KKeyNative keyNative( pEvent ); - KKey key = keyNative; - - kdDebug(125) << "x11KeyPress: seek " << key.toStringInternal() - << TQString(TQString( " keyCodeX: %1 state: %2 keyModX: %3" ) - .arg( codemod.code, 0, 16 ).arg( pEvent->xkey.state, 0, 16 ).arg( codemod.mod, 0, 16 )) << endl; - - // Search for which accelerator activated this event: - if( !m_rgCodeModToAction.contains( codemod ) ) { -#ifndef NDEBUG - for( CodeModMap::ConstIterator it = m_rgCodeModToAction.begin(); it != m_rgCodeModToAction.end(); ++it ) { - KAccelAction* pAction = *it; - kdDebug(125) << "\tcode: " << TQString::number(it.key().code, 16) << " mod: " << TQString::number(it.key().mod, 16) - << (pAction ? TQString(" name: \"%1\" shortcut: %2").tqarg(pAction->name()).tqarg(pAction->shortcut().toStringInternal()) : TQString()) - << endl; - } -#endif - return false; - } - - KAccelAction* pAction = m_rgCodeModToAction[codemod]; - - if( !pAction ) { - static bool recursion_block = false; - if( !recursion_block ) { - recursion_block = true; - TQPopupMenu* pMenu = createPopupMenu( 0, KKeySequence(key) ); - connect( pMenu, TQT_SIGNAL(activated(int)), this, TQT_SLOT(slotActivated(int)) ); - pMenu->exec( TQPoint( 0, 0 ) ); - disconnect( pMenu, TQT_SIGNAL(activated(int)), this, TQT_SLOT(slotActivated(int))); - delete pMenu; - recursion_block = false; - } - } else if( !pAction->objSlotPtr() || !pAction->isEnabled() ) - return false; - else - activate( pAction, KKeySequence(key) ); - - return true; -} - -void KGlobalAccelPrivate::activate( KAccelAction* pAction, const KKeySequence& seq ) -{ - kdDebug(125) << "KGlobalAccelPrivate::activate( \"" << pAction->name() << "\" ) " << endl; - - TQRegExp rexPassIndex( "([ ]*int[ ]*)" ); - TQRegExp rexPassInfo( " TQString" ); - TQRegExp rexIndex( " ([0-9]+)$" ); - - // If the slot to be called accepts an integer index - // and an index is present at the end of the action's name, - // then send the slot the given index #. - if( rexPassIndex.search( pAction->methodSlotPtr() ) >= 0 && rexIndex.search( pAction->name() ) >= 0 ) { - int n = rexIndex.cap(1).toInt(); - kdDebug(125) << "Calling " << pAction->methodSlotPtr() << " int = " << n << endl; - int slot_id = pAction->objSlotPtr()->tqmetaObject()->findSlot( normalizeSignalSlot( pAction->methodSlotPtr() ).data() + 1, true ); - if( slot_id >= 0 ) { - TQUObject o[2]; - static_TQUType_int.set(o+1,n); - const_cast< TQObject* >( pAction->objSlotPtr())->qt_invoke( slot_id, o ); - } - } else if( rexPassInfo.search( pAction->methodSlotPtr() ) ) { - int slot_id = pAction->objSlotPtr()->tqmetaObject()->findSlot( normalizeSignalSlot( pAction->methodSlotPtr() ).data() + 1, true ); - if( slot_id >= 0 ) { - TQUObject o[4]; - static_TQUType_TQString.set(o+1,pAction->name()); - static_TQUType_TQString.set(o+2,pAction->label()); - static_TQUType_ptr.set(o+3,&seq); - const_cast< TQObject* >( pAction->objSlotPtr())->qt_invoke( slot_id, o ); - } - } else { - int slot_id = pAction->objSlotPtr()->tqmetaObject()->findSlot( normalizeSignalSlot( pAction->methodSlotPtr() ).data() + 1, true ); - if( slot_id >= 0 ) - const_cast< TQObject* >( pAction->objSlotPtr())->qt_invoke( slot_id, 0 ); - } -} - -void KGlobalAccelPrivate::slotActivated( int iAction ) -{ - KAccelAction* pAction = KAccelBase::actions().actionPtr( iAction ); - if( pAction ) - activate( pAction, KKeySequence() ); -} - -#include "kglobalaccel_x11.moc" - -#endif // !Q_WS_X11 |