22 #include <tqwindowdefs.h>
25 #include "kglobalaccel_x11.h"
26 #include "kglobalaccel.h"
27 #include "kkeyserver_x11.h"
29 #include <tqpopupmenu.h>
32 #include <tqmetaobject.h>
33 #include <tqucomextra_p.h>
34 #include <tdeapplication.h>
36 #include <kkeynative.h>
39 #include <kxerrorhandler.h>
44 #include <X11/XKBlib.h>
45 #include <X11/keysym.h>
49 static int XGrabErrorHandler( Display *, XErrorEvent *e ) {
50 if ( e->error_code != BadAccess ) {
51 kdWarning() <<
"grabKey: got X error " << e->type <<
" instead of BadAccess\n";
63 static uint g_keyModMaskXAccel = 0;
64 static uint g_keyModMaskXOnOrOff = 0;
66 static void calculateGrabMasks()
69 g_keyModMaskXOnOrOff =
80 static TQValueList< TDEGlobalAccelPrivate* >* all_accels = 0;
82 TDEGlobalAccelPrivate::TDEGlobalAccelPrivate()
83 : TDEAccelBase( TDEAccelBase::NATIVE_KEYS )
85 , m_blockingDisabled( false )
86 , m_suspended( false )
88 if( all_accels == NULL )
89 all_accels =
new TQValueList< TDEGlobalAccelPrivate* >;
90 all_accels->append(
this );
91 m_sConfigGroup =
"Global Shortcuts";
92 kapp->installX11EventFilter(
this );
93 connect(kapp, TQT_SIGNAL(coreFakeKeyPress(
unsigned int)),
this, TQT_SLOT(fakeKeyPressed(
unsigned int)));
96 TDEGlobalAccelPrivate::~TDEGlobalAccelPrivate()
102 all_accels->remove(
this );
103 if( all_accels->count() == 0 ) {
109 void TDEGlobalAccelPrivate::setEnabled(
bool bEnable )
111 m_bEnabled = bEnable;
115 void TDEGlobalAccelPrivate::blockShortcuts(
bool block )
117 if( all_accels == NULL )
119 for( TQValueList< TDEGlobalAccelPrivate* >::ConstIterator it = all_accels->begin();
120 it != all_accels->end();
122 if( (*it)->m_blockingDisabled )
124 (*it)->m_blocked = block;
125 (*it)->updateConnections();
129 void TDEGlobalAccelPrivate::disableBlocking(
bool block )
131 m_blockingDisabled = block;
134 bool TDEGlobalAccelPrivate::isEnabledInternal()
const
136 return TDEAccelBase::isEnabled() && !m_blocked;
141 void TDEGlobalAccelPrivate::suspend(
bool s )
146 bool TDEGlobalAccelPrivate::emitSignal( Signal )
151 bool TDEGlobalAccelPrivate::connectKey( TDEAccelAction& action,
const KKeyServer::Key& key )
152 {
return grabKey( key,
true, &action ); }
154 {
return grabKey( key,
true, 0 ); }
155 bool TDEGlobalAccelPrivate::disconnectKey( TDEAccelAction& action,
const KKeyServer::Key& key )
156 {
return grabKey( key,
false, &action ); }
157 bool TDEGlobalAccelPrivate::disconnectKey(
const KKeyServer::Key& key )
158 {
return grabKey( key,
false, 0 ); }
160 bool TDEGlobalAccelPrivate::grabKey(
const KKeyServer::Key& key,
bool bGrab, TDEAccelAction* pAction )
163 kdWarning(125) <<
"TDEGlobalAccelPrivate::grabKey( " << key.
key().
toStringInternal() <<
", " << bGrab <<
", \"" << (pAction ? pAction->name().latin1() :
"(null)") <<
"\" ): Tried to grab key with null code." <<
endl;
168 if( g_keyModMaskXOnOrOff == 0 ) {
169 calculateGrabMasks();
172 uchar keyCodeX = key.
code();
173 uint keyModX = key.
mod() & g_keyModMaskXAccel;
177 if( key.
sym() == XK_Sys_Req && XkbKeycodeToKeysym( tqt_xdisplay(), 111, 0, 0 ) == XK_Print ) {
183 if ((key.
mod() & KKeyServer::MODE_SWITCH) && (!(g_keyModMaskXAccel & KKeyServer::MODE_SWITCH))) {
186 kdWarning(125) <<
"TDEGlobalAccelPrivate::grabKey( " << key.
key().
toStringInternal() <<
", " << bGrab <<
", \"" << (pAction ? pAction->name().latin1() :
"(null)") <<
"\" ): Tried to grab key requiring ISO_Level3_Shift (AltGr) sequence." <<
endl;
192 kdDebug(125) << TQString(TQString(
"grabKey( key: '%1', bGrab: %2 ): keyCodeX: %3 keyModX: %4\n" )
194 .arg( keyCodeX, 0, 16 ).arg( keyModX, 0, 16 ));
209 TQString sDebug = TQString(
"\tcode: 0x%1 state: 0x%2 | ").arg(keyCodeX,0,16).arg(keyModX,0,16);
211 uint keyModMaskX = ~g_keyModMaskXOnOrOff;
212 for( uint irrelevantBitsMask = 0; irrelevantBitsMask <= 0xff; irrelevantBitsMask++ ) {
213 if( (irrelevantBitsMask & keyModMaskX) == 0 ) {
215 sDebug += TQString(
"0x%3, ").arg(irrelevantBitsMask, 0, 16);
218 XGrabKey( tqt_xdisplay(), keyCodeX, keyModX | irrelevantBitsMask,
219 tqt_xrootwin(), True, GrabModeAsync, GrabModeSync );
221 XUngrabKey( tqt_xdisplay(), keyCodeX, keyModX | irrelevantBitsMask, tqt_xrootwin() );
231 failed = handler.error(
true );
235 kdDebug(125) <<
"grab failed!\n";
236 for( uint m = 0; m <= 0xff; m++ ) {
237 if(( m & keyModMaskX ) == 0 )
238 XUngrabKey( tqt_xdisplay(), keyCodeX, keyModX | m, tqt_xrootwin() );
245 codemod.code = keyCodeX;
246 codemod.mod = keyModX;
247 if( key.
mod() & KKeyServer::MODE_SWITCH )
248 codemod.mod |= KKeyServer::MODE_SWITCH;
251 m_rgCodeModToAction.insert( codemod, pAction );
253 m_rgCodeModToAction.remove( codemod );
258 bool TDEGlobalAccelPrivate::x11Event( XEvent* pEvent )
261 switch( pEvent->type ) {
263 XRefreshKeyboardMapping( &pEvent->xmapping );
267 if( x11KeyPress( pEvent ) ) {
271 return TQWidget::x11Event( pEvent );
275 void TDEGlobalAccelPrivate::x11MappingNotify()
277 kdDebug(125) <<
"TDEGlobalAccelPrivate::x11MappingNotify()" <<
endl;
280 calculateGrabMasks();
285 void TDEGlobalAccelPrivate::fakeKeyPressed(
unsigned int keyCode) {
287 codemod.code = keyCode;
290 KKey key(keyCode, 0);
292 kdDebug(125) <<
"fakeKeyPressed: seek " << key.toStringInternal()
293 << TQString(TQString(
" keyCodeX: %1 keyCode: %2 keyModX: %3" )
294 .arg( codemod.code, 0, 16 ).arg( keyCode, 0, 16 ).arg( codemod.mod, 0, 16 )) << endl;
297 if( !m_rgCodeModToAction.contains( codemod ) ) {
299 for( CodeModMap::ConstIterator it = m_rgCodeModToAction.begin(); it != m_rgCodeModToAction.end(); ++it ) {
300 TDEAccelAction* pAction = *it;
301 kdDebug(125) <<
"\tcode: " << TQString::number(it.key().code, 16) <<
" mod: " << TQString::number(it.key().mod, 16)
302 << (pAction ? TQString(
" name: \"%1\" shortcut: %2").arg(pAction->name()).arg(pAction->shortcut().toStringInternal()) : TQString())
309 TDEAccelAction* pAction = m_rgCodeModToAction[codemod];
312 static bool recursion_block =
false;
313 if( !recursion_block ) {
314 recursion_block =
true;
315 TQPopupMenu* pMenu = createPopupMenu( 0,
KKeySequence(key) );
316 connect( pMenu, TQT_SIGNAL(activated(
int)),
this, TQT_SLOT(slotActivated(
int)) );
317 pMenu->exec( TQPoint( 0, 0 ) );
318 disconnect( pMenu, TQT_SIGNAL(activated(
int)),
this, TQT_SLOT(slotActivated(
int)));
320 recursion_block =
false;
322 }
else if( !pAction->objSlotPtr() || !pAction->isEnabled() )
328 bool TDEGlobalAccelPrivate::x11KeyPress(
const XEvent *pEvent )
331 if ( !TQWidget::keyboardGrabber() && !TQApplication::activePopupWidget() ) {
332 XUngrabKeyboard( tqt_xdisplay(), pEvent->xkey.time );
333 XFlush( tqt_xdisplay());
336 if( !isEnabledInternal() || m_suspended ) {
341 codemod.code = pEvent->xkey.keycode;
342 codemod.mod = pEvent->xkey.state & (g_keyModMaskXAccel | KKeyServer::MODE_SWITCH);
348 uint sym = XkbKeycodeToKeysym( tqt_xdisplay(), codemod.code, 0, 0 );
350 if( sym >= XK_KP_Space && sym <= XK_KP_9 ) {
369 KKey key = keyNative;
372 << TQString(TQString(
" keyCodeX: %1 state: %2 keyModX: %3" )
373 .arg( codemod.code, 0, 16 ).arg( pEvent->xkey.state, 0, 16 ).arg( codemod.mod, 0, 16 )) << endl;
376 if( !m_rgCodeModToAction.contains( codemod ) ) {
378 for( CodeModMap::ConstIterator it = m_rgCodeModToAction.begin(); it != m_rgCodeModToAction.end(); ++it ) {
379 TDEAccelAction* pAction = *it;
380 kdDebug(125) <<
"\tcode: " << TQString::number(it.key().code, 16) <<
" mod: " << TQString::number(it.key().mod, 16)
381 << (pAction ? TQString(
" name: \"%1\" shortcut: %2").arg(pAction->name()).arg(pAction->shortcut().toStringInternal()) : TQString())
388 TDEAccelAction* pAction = m_rgCodeModToAction[codemod];
391 static bool recursion_block =
false;
392 if( !recursion_block ) {
393 recursion_block =
true;
394 TQPopupMenu* pMenu = createPopupMenu( 0,
KKeySequence(key) );
395 connect( pMenu, TQT_SIGNAL(activated(
int)),
this, TQT_SLOT(slotActivated(
int)) );
396 pMenu->exec( TQPoint( 0, 0 ) );
397 disconnect( pMenu, TQT_SIGNAL(activated(
int)),
this, TQT_SLOT(slotActivated(
int)));
399 recursion_block =
false;
401 }
else if( !pAction->objSlotPtr() || !pAction->isEnabled() )
409 void TDEGlobalAccelPrivate::activate( TDEAccelAction* pAction,
const KKeySequence& seq )
411 kdDebug(125) <<
"TDEGlobalAccelPrivate::activate( \"" << pAction->name() <<
"\" ) " <<
endl;
413 TQRegExp rexPassIndex(
"([ ]*int[ ]*)" );
414 TQRegExp rexPassInfo(
" TQString" );
415 TQRegExp rexIndex(
" ([0-9]+)$" );
420 if( rexPassIndex.search( pAction->methodSlotPtr() ) >= 0 && rexIndex.search( pAction->name() ) >= 0 ) {
421 int n = rexIndex.cap(1).toInt();
422 kdDebug(125) <<
"Calling " << pAction->methodSlotPtr() <<
" int = " << n <<
endl;
423 int slot_id = pAction->objSlotPtr()->metaObject()->findSlot( normalizeSignalSlot( pAction->methodSlotPtr() ).data() + 1, true );
426 static_TQUType_int.set(o+1,n);
427 const_cast< TQObject*
>( pAction->objSlotPtr())->tqt_invoke( slot_id, o );
429 }
else if( rexPassInfo.search( pAction->methodSlotPtr() ) ) {
430 int slot_id = pAction->objSlotPtr()->metaObject()->findSlot( normalizeSignalSlot( pAction->methodSlotPtr() ).data() + 1, true );
433 static_TQUType_TQString.set(o+1,pAction->name());
434 static_TQUType_TQString.set(o+2,pAction->label());
435 static_TQUType_ptr.set(o+3,&seq);
436 const_cast< TQObject*
>( pAction->objSlotPtr())->tqt_invoke( slot_id, o );
439 int slot_id = pAction->objSlotPtr()->metaObject()->findSlot( normalizeSignalSlot( pAction->methodSlotPtr() ).data() + 1, true );
441 const_cast< TQObject*
>( pAction->objSlotPtr())->tqt_invoke( slot_id, 0 );
445 void TDEGlobalAccelPrivate::slotActivated(
int iAction )
447 TDEAccelAction* pAction = TDEAccelBase::actions().actionPtr( iAction );
452 #include "kglobalaccel_x11.moc"
KKey key() const
Converts this Key to a KKey.
A collection of functions for the conversion of key presses and their modifiers from the window syste...
uint modXNumLock()
Returns the X11 NumLock modifier mask/flag.
uint modXScrollLock()
Returns the X11 ScrollLock modifier mask/flag.
kdbgstream kdDebug(int area=0)
uint modXAlt()
Returns the X11 Alt (Mod1) modifier mask/flag.
uint modXModeSwitch()
Returns the X11 Mode_switch modifier mask/flag.
uint modXShift()
Returns the X11 Shift modifier mask/flag.
A KKeySequence object holds a sequence of up to 4 keys.
kdbgstream kdWarning(int area=0)
This class simplifies handling of X errors.
bool initializeMods()
TODO: please document.
uint sym() const
Returns the symbol of the key.
uint modXLock()
Returns the X11 Lock modifier mask/flag.
Representation of a key in the format native of the windowing system (eg.
A KKey object represents a single key with possible modifiers (Shift, Ctrl, Alt, Win).
TQString toStringInternal() const
Returns an untranslated text representation of the key in the form "modifier+key", suitable e.g.
uint mod() const
Returns the modifiers of the key.
bool updateConnections()
Updates the connections of the accelerations after changing them.
uint code() const
Returns the code of the key.
kdbgstream & endl(kdbgstream &s)
uint accelModMaskX()
Returns bitwise OR'ed mask containing Shift, Ctrl, Alt, and Win (if available).