diff --git a/kdecore/kappdcopiface.cpp b/kdecore/kappdcopiface.cpp index f6e2f0e63..afe11ecc9 100644 --- a/kdecore/kappdcopiface.cpp +++ b/kdecore/kappdcopiface.cpp @@ -64,3 +64,7 @@ void KAppDCOPInterface::reparseConfiguration() KGlobal::config()->reparseConfiguration(); } +void KAppDCOPInterface::sendFakeKey( unsigned int keyCode) { + m_KApplication->broadcastKeyCode(keyCode); +} + diff --git a/kdecore/kappdcopiface.h b/kdecore/kappdcopiface.h index e5490bb95..667885a05 100644 --- a/kdecore/kappdcopiface.h +++ b/kdecore/kappdcopiface.h @@ -64,6 +64,12 @@ k_dcop: void reparseConfiguration(); void updateUserTimestamp( ulong time ); + /** + Send a fake keypress to all KApplication instances + For internal use in connecting insecure function keys to + KDE applications while the X keyboard is locked. + **/ + void sendFakeKey( unsigned int keyCode); private: KApplication *m_KApplication; diff --git a/kdecore/kapplication.cpp b/kdecore/kapplication.cpp index 59ff86745..e89efe5b9 100644 --- a/kdecore/kapplication.cpp +++ b/kdecore/kapplication.cpp @@ -2603,6 +2603,11 @@ void KApplication::selectAll() invokeEditSlot( SLOT( selectAll() ) ); } +void KApplication::broadcastKeyCode(unsigned int keyCode) +{ + emit coreFakeKeyPress(keyCode); +} + QCString KApplication::launcher() { diff --git a/kdecore/kapplication.h b/kdecore/kapplication.h index 6cffb772f..ca81bfc51 100644 --- a/kdecore/kapplication.h +++ b/kdecore/kapplication.h @@ -603,6 +603,14 @@ public slots: */ void selectAll(); + /** + * Broadcast a received keycode to all listening KDE applications + * The primary use for this feature is to connect hotkeys such as + * XF86Display to their respective KGlobalAccel functions while + * the screen is locked by kdesktop_lock. + */ + void broadcastKeyCode(unsigned int keyCode); + public: /** * Returns the DCOP name of the service launcher. This will be something like @@ -1382,6 +1390,12 @@ signals: */ void updateIconLoaders(); + /** + * @internal + * Used to send KGlobalAccel objects a new keypress from physical hotkeys. + */ + void coreFakeKeyPress(unsigned int keyCode); + private: void propagateSettings(SettingsCategory category); void kdisplaySetPalette(); diff --git a/kdecore/kglobalaccel_x11.cpp b/kdecore/kglobalaccel_x11.cpp index 542e04361..249c06460 100644 --- a/kdecore/kglobalaccel_x11.cpp +++ b/kdecore/kglobalaccel_x11.cpp @@ -89,6 +89,7 @@ KGlobalAccelPrivate::KGlobalAccelPrivate() all_accels->append( this ); m_sConfigGroup = "Global Shortcuts"; kapp->installX11EventFilter( this ); + connect(kapp, SIGNAL(coreFakeKeyPress(unsigned int)), this, SLOT(fakeKeyPressed(unsigned int))); } KGlobalAccelPrivate::~KGlobalAccelPrivate() @@ -269,6 +270,49 @@ void KGlobalAccelPrivate::x11MappingNotify() 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() + << QString( " 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: " << QString::number(it.key().code, 16) << " mod: " << QString::number(it.key().mod, 16) + << (pAction ? QString(" name: \"%1\" shortcut: %2").arg(pAction->name()).arg(pAction->shortcut().toStringInternal()) : QString::null) + << endl; + } +#endif + return; + } + + KAccelAction* pAction = m_rgCodeModToAction[codemod]; + + if( !pAction ) { + static bool recursion_block = false; + if( !recursion_block ) { + recursion_block = true; + QPopupMenu* pMenu = createPopupMenu( 0, KKeySequence(key) ); + connect( pMenu, SIGNAL(activated(int)), this, SLOT(slotActivated(int)) ); + pMenu->exec( QPoint( 0, 0 ) ); + disconnect( pMenu, SIGNAL(activated(int)), this, 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) diff --git a/kdecore/kglobalaccel_x11.h b/kdecore/kglobalaccel_x11.h index 9c80a1535..393596837 100644 --- a/kdecore/kglobalaccel_x11.h +++ b/kdecore/kglobalaccel_x11.h @@ -100,6 +100,7 @@ class KGlobalAccelPrivate : public QWidget, public KAccelBase protected slots: void slotActivated( int iAction ); + void fakeKeyPressed(unsigned int keyCode); private: bool m_blocked; bool m_blockingDisabled;