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 <kapplication.h>
36 #include <kkeynative.h>
39 #include <kxerrorhandler.h>
44 #include <X11/keysym.h>
48 static int XGrabErrorHandler( Display *, XErrorEvent *e ) {
49 if ( e->error_code != BadAccess ) {
50 kdWarning() <<
"grabKey: got X error " << e->type <<
" instead of BadAccess\n";
62 static uint g_keyModMaskXAccel = 0;
63 static uint g_keyModMaskXOnOrOff = 0;
65 static void calculateGrabMasks()
68 g_keyModMaskXOnOrOff =
79 static TQValueList< KGlobalAccelPrivate* >* all_accels = 0;
81 KGlobalAccelPrivate::KGlobalAccelPrivate()
82 : KAccelBase( KAccelBase::NATIVE_KEYS )
84 , m_blockingDisabled( false )
85 , m_suspended( false )
87 if( all_accels == NULL )
88 all_accels =
new TQValueList< KGlobalAccelPrivate* >;
89 all_accels->append(
this );
90 m_sConfigGroup =
"Global Shortcuts";
91 kapp->installX11EventFilter(
this );
92 connect(kapp, TQT_SIGNAL(coreFakeKeyPress(
unsigned int)),
this, TQT_SLOT(fakeKeyPressed(
unsigned int)));
95 KGlobalAccelPrivate::~KGlobalAccelPrivate()
101 all_accels->remove(
this );
102 if( all_accels->count() == 0 ) {
108 void KGlobalAccelPrivate::setEnabled(
bool bEnable )
110 m_bEnabled = bEnable;
114 void KGlobalAccelPrivate::blockShortcuts(
bool block )
116 if( all_accels == NULL )
118 for( TQValueList< KGlobalAccelPrivate* >::ConstIterator it = all_accels->begin();
119 it != all_accels->end();
121 if( (*it)->m_blockingDisabled )
123 (*it)->m_blocked = block;
124 (*it)->updateConnections();
128 void KGlobalAccelPrivate::disableBlocking(
bool block )
130 m_blockingDisabled = block;
133 bool KGlobalAccelPrivate::isEnabledInternal()
const
135 return KAccelBase::isEnabled() && !m_blocked;
140 void KGlobalAccelPrivate::suspend(
bool s )
145 bool KGlobalAccelPrivate::emitSignal( Signal )
150 bool KGlobalAccelPrivate::connectKey( KAccelAction& action,
const KKeyServer::Key& key )
151 {
return grabKey( key,
true, &action ); }
153 {
return grabKey( key,
true, 0 ); }
154 bool KGlobalAccelPrivate::disconnectKey( KAccelAction& action,
const KKeyServer::Key& key )
155 {
return grabKey( key,
false, &action ); }
157 {
return grabKey( key,
false, 0 ); }
159 bool KGlobalAccelPrivate::grabKey(
const KKeyServer::Key& key,
bool bGrab, KAccelAction* pAction )
162 kdWarning(125) <<
"KGlobalAccelPrivate::grabKey( " << key.
key().
toStringInternal() <<
", " << bGrab <<
", \"" << (pAction ? pAction->name().latin1() :
"(null)") <<
"\" ): Tried to grab key with null code." <<
endl;
167 if( g_keyModMaskXOnOrOff == 0 ) {
168 calculateGrabMasks();
171 uchar keyCodeX = key.
code();
172 uint keyModX = key.
mod() & g_keyModMaskXAccel;
176 if( key.
sym() == XK_Sys_Req && XKeycodeToKeysym( qt_xdisplay(), 111, 0 ) == XK_Print ) {
182 if ((key.
mod() & KKeyServer::MODE_SWITCH) && (!(g_keyModMaskXAccel & KKeyServer::MODE_SWITCH))) {
185 kdWarning(125) <<
"KGlobalAccelPrivate::grabKey( " << key.
key().
toStringInternal() <<
", " << bGrab <<
", \"" << (pAction ? pAction->name().latin1() :
"(null)") <<
"\" ): Tried to grab key requiring ISO_Level3_Shift (AltGr) sequence." <<
endl;
191 kdDebug(125) << TQString(TQString(
"grabKey( key: '%1', bGrab: %2 ): keyCodeX: %3 keyModX: %4\n" )
193 .arg( keyCodeX, 0, 16 ).arg( keyModX, 0, 16 ));
208 TQString sDebug = TQString(
"\tcode: 0x%1 state: 0x%2 | ").arg(keyCodeX,0,16).arg(keyModX,0,16);
210 uint keyModMaskX = ~g_keyModMaskXOnOrOff;
211 for( uint irrelevantBitsMask = 0; irrelevantBitsMask <= 0xff; irrelevantBitsMask++ ) {
212 if( (irrelevantBitsMask & keyModMaskX) == 0 ) {
214 sDebug += TQString(
"0x%3, ").arg(irrelevantBitsMask, 0, 16);
217 XGrabKey( qt_xdisplay(), keyCodeX, keyModX | irrelevantBitsMask,
218 qt_xrootwin(), True, GrabModeAsync, GrabModeSync );
220 XUngrabKey( qt_xdisplay(), keyCodeX, keyModX | irrelevantBitsMask, qt_xrootwin() );
230 failed = handler.error(
true );
234 kdDebug(125) <<
"grab failed!\n";
235 for( uint m = 0; m <= 0xff; m++ ) {
236 if(( m & keyModMaskX ) == 0 )
237 XUngrabKey( qt_xdisplay(), keyCodeX, keyModX | m, qt_xrootwin() );
244 codemod.code = keyCodeX;
245 codemod.mod = keyModX;
246 if( key.
mod() & KKeyServer::MODE_SWITCH )
247 codemod.mod |= KKeyServer::MODE_SWITCH;
250 m_rgCodeModToAction.insert( codemod, pAction );
252 m_rgCodeModToAction.remove( codemod );
257 bool KGlobalAccelPrivate::x11Event( XEvent* pEvent )
260 switch( pEvent->type ) {
262 XRefreshKeyboardMapping( &pEvent->xmapping );
266 if( x11KeyPress( pEvent ) ) {
270 return TQWidget::x11Event( pEvent );
274 void KGlobalAccelPrivate::x11MappingNotify()
276 kdDebug(125) <<
"KGlobalAccelPrivate::x11MappingNotify()" <<
endl;
279 calculateGrabMasks();
284 void KGlobalAccelPrivate::fakeKeyPressed(
unsigned int keyCode) {
286 codemod.code = keyCode;
289 KKey key(keyCode, 0);
291 kdDebug(125) <<
"fakeKeyPressed: seek " << key.toStringInternal()
292 << TQString(TQString(
" keyCodeX: %1 keyCode: %2 keyModX: %3" )
293 .arg( codemod.code, 0, 16 ).arg( keyCode, 0, 16 ).arg( codemod.mod, 0, 16 )) << endl;
296 if( !m_rgCodeModToAction.contains( codemod ) ) {
298 for( CodeModMap::ConstIterator it = m_rgCodeModToAction.begin(); it != m_rgCodeModToAction.end(); ++it ) {
299 KAccelAction* pAction = *it;
300 kdDebug(125) <<
"\tcode: " << TQString::number(it.key().code, 16) <<
" mod: " << TQString::number(it.key().mod, 16)
301 << (pAction ? TQString(
" name: \"%1\" shortcut: %2").arg(pAction->name()).arg(pAction->shortcut().toStringInternal()) : TQString())
308 KAccelAction* pAction = m_rgCodeModToAction[codemod];
311 static bool recursion_block =
false;
312 if( !recursion_block ) {
313 recursion_block =
true;
314 TQPopupMenu* pMenu = createPopupMenu( 0,
KKeySequence(key) );
315 connect( pMenu, TQT_SIGNAL(activated(
int)),
this, TQT_SLOT(slotActivated(
int)) );
316 pMenu->exec( TQPoint( 0, 0 ) );
317 disconnect( pMenu, TQT_SIGNAL(activated(
int)),
this, TQT_SLOT(slotActivated(
int)));
319 recursion_block =
false;
321 }
else if( !pAction->objSlotPtr() || !pAction->isEnabled() )
327 bool KGlobalAccelPrivate::x11KeyPress(
const XEvent *pEvent )
330 if ( !TQWidget::keyboardGrabber() && !TQApplication::activePopupWidget() ) {
331 XUngrabKeyboard( qt_xdisplay(), pEvent->xkey.time );
332 XFlush( qt_xdisplay());
335 if( !isEnabledInternal() || m_suspended ) {
340 codemod.code = pEvent->xkey.keycode;
341 codemod.mod = pEvent->xkey.state & (g_keyModMaskXAccel | KKeyServer::MODE_SWITCH);
347 uint sym = XKeycodeToKeysym( qt_xdisplay(), codemod.code, 0 );
349 if( sym >= XK_KP_Space && sym <= XK_KP_9 ) {
368 KKey key = keyNative;
371 << TQString(TQString(
" keyCodeX: %1 state: %2 keyModX: %3" )
372 .arg( codemod.code, 0, 16 ).arg( pEvent->xkey.state, 0, 16 ).arg( codemod.mod, 0, 16 )) << endl;
375 if( !m_rgCodeModToAction.contains( codemod ) ) {
377 for( CodeModMap::ConstIterator it = m_rgCodeModToAction.begin(); it != m_rgCodeModToAction.end(); ++it ) {
378 KAccelAction* pAction = *it;
379 kdDebug(125) <<
"\tcode: " << TQString::number(it.key().code, 16) <<
" mod: " << TQString::number(it.key().mod, 16)
380 << (pAction ? TQString(
" name: \"%1\" shortcut: %2").arg(pAction->name()).arg(pAction->shortcut().toStringInternal()) : TQString())
387 KAccelAction* pAction = m_rgCodeModToAction[codemod];
390 static bool recursion_block =
false;
391 if( !recursion_block ) {
392 recursion_block =
true;
393 TQPopupMenu* pMenu = createPopupMenu( 0,
KKeySequence(key) );
394 connect( pMenu, TQT_SIGNAL(activated(
int)),
this, TQT_SLOT(slotActivated(
int)) );
395 pMenu->exec( TQPoint( 0, 0 ) );
396 disconnect( pMenu, TQT_SIGNAL(activated(
int)),
this, TQT_SLOT(slotActivated(
int)));
398 recursion_block =
false;
400 }
else if( !pAction->objSlotPtr() || !pAction->isEnabled() )
408 void KGlobalAccelPrivate::activate( KAccelAction* pAction,
const KKeySequence& seq )
410 kdDebug(125) <<
"KGlobalAccelPrivate::activate( \"" << pAction->name() <<
"\" ) " <<
endl;
412 TQRegExp rexPassIndex(
"([ ]*int[ ]*)" );
413 TQRegExp rexPassInfo(
" TQString" );
414 TQRegExp rexIndex(
" ([0-9]+)$" );
419 if( rexPassIndex.search( pAction->methodSlotPtr() ) >= 0 && rexIndex.search( pAction->name() ) >= 0 ) {
420 int n = rexIndex.cap(1).toInt();
421 kdDebug(125) <<
"Calling " << pAction->methodSlotPtr() <<
" int = " << n <<
endl;
422 int slot_id = pAction->objSlotPtr()->metaObject()->findSlot( normalizeSignalSlot( pAction->methodSlotPtr() ).data() + 1, true );
425 static_TQUType_int.set(o+1,n);
426 const_cast< TQObject*
>( pAction->objSlotPtr())->qt_invoke( slot_id, o );
428 }
else if( rexPassInfo.search( pAction->methodSlotPtr() ) ) {
429 int slot_id = pAction->objSlotPtr()->metaObject()->findSlot( normalizeSignalSlot( pAction->methodSlotPtr() ).data() + 1, true );
432 static_TQUType_TQString.set(o+1,pAction->name());
433 static_TQUType_TQString.set(o+2,pAction->label());
434 static_TQUType_ptr.set(o+3,&seq);
435 const_cast< TQObject*
>( pAction->objSlotPtr())->qt_invoke( slot_id, o );
438 int slot_id = pAction->objSlotPtr()->metaObject()->findSlot( normalizeSignalSlot( pAction->methodSlotPtr() ).data() + 1, true );
440 const_cast< TQObject*
>( pAction->objSlotPtr())->qt_invoke( slot_id, 0 );
444 void KGlobalAccelPrivate::slotActivated(
int iAction )
446 KAccelAction* pAction = KAccelBase::actions().actionPtr( iAction );
451 #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.
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).
bool updateConnections()
Updates the connections of the accelerations after changing them.