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 <private/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, TQ_SIGNAL(coreFakeKeyPress(
unsigned int)),
this, TQ_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" )
193 .arg(
key.key().toStringInternal() ).arg( bGrab )
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;
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, TQ_SIGNAL(activated(
int)),
this, TQ_SLOT(slotActivated(
int)) );
317 pMenu->exec( TQPoint( 0, 0 ) );
318 disconnect( pMenu, TQ_SIGNAL(activated(
int)),
this, TQ_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 ) {
371 kdDebug(125) <<
"x11KeyPress: seek " <<
key.toStringInternal()
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, TQ_SIGNAL(activated(
int)),
this, TQ_SLOT(slotActivated(
int)) );
396 pMenu->exec( TQPoint( 0, 0 ) );
397 disconnect( pMenu, TQ_SIGNAL(activated(
int)),
this, TQ_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_QUType_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_QUType_TQString.set(o+1,pAction->name());
434 static_QUType_TQString.set(o+2,pAction->label());
435 static_QUType_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"
Representation of a key in the format native of the windowing system (eg.
A KKeySequence object holds a sequence of up to 4 keys.
A KKey object represents a single key with possible modifiers (Shift, Ctrl, Alt, Win).
This class simplifies handling of X errors.
kdbgstream kdWarning(int area=0)
Returns a warning stream.
kdbgstream kdDebug(int area=0)
Returns a debug stream.
kdbgstream & endl(kdbgstream &s)
Prints an "\n".
A collection of functions for the conversion of key presses and their modifiers from the window syste...
uint modXModeSwitch()
Returns the X11 Mode_switch modifier mask/flag.
uint modXShift()
Returns the X11 Shift modifier mask/flag.
uint modXNumLock()
Returns the X11 NumLock modifier mask/flag.
uint modXLock()
Returns the X11 Lock modifier mask/flag.
uint accelModMaskX()
Returns bitwise OR'ed mask containing Shift, Ctrl, Alt, and Win (if available).
uint modXAlt()
Returns the X11 Alt (Mod1) modifier mask/flag.
uint modXScrollLock()
Returns the X11 ScrollLock modifier mask/flag.
bool initializeMods()
TODO: please document.