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();
170 uchar keyCodeX = key.
code();
171 uint keyModX = key.
mod() & g_keyModMaskXAccel;
175 if( key.
sym() == XK_Sys_Req && XKeycodeToKeysym( qt_xdisplay(), 111, 0 ) == XK_Print ) {
182 kdDebug(125) << TQString(TQString(
"grabKey( key: '%1', bGrab: %2 ): keyCodeX: %3 keyModX: %4\n" )
184 .arg( keyCodeX, 0, 16 ).arg( keyModX, 0, 16 ));
198 TQString sDebug = TQString(
"\tcode: 0x%1 state: 0x%2 | ").arg(keyCodeX,0,16).arg(keyModX,0,16);
200 uint keyModMaskX = ~g_keyModMaskXOnOrOff;
201 for( uint irrelevantBitsMask = 0; irrelevantBitsMask <= 0xff; irrelevantBitsMask++ ) {
202 if( (irrelevantBitsMask & keyModMaskX) == 0 ) {
204 sDebug += TQString(
"0x%3, ").arg(irrelevantBitsMask, 0, 16);
207 XGrabKey( qt_xdisplay(), keyCodeX, keyModX | irrelevantBitsMask,
208 qt_xrootwin(), True, GrabModeAsync, GrabModeSync );
210 XUngrabKey( qt_xdisplay(), keyCodeX, keyModX | irrelevantBitsMask, qt_xrootwin() );
220 failed = handler.error(
true );
224 kdDebug(125) <<
"grab failed!\n";
225 for( uint m = 0; m <= 0xff; m++ ) {
226 if(( m & keyModMaskX ) == 0 )
227 XUngrabKey( qt_xdisplay(), keyCodeX, keyModX | m, qt_xrootwin() );
234 codemod.code = keyCodeX;
235 codemod.mod = keyModX;
236 if( key.
mod() & KKeyServer::MODE_SWITCH )
237 codemod.mod |= KKeyServer::MODE_SWITCH;
240 m_rgCodeModToAction.insert( codemod, pAction );
242 m_rgCodeModToAction.remove( codemod );
247 bool KGlobalAccelPrivate::x11Event( XEvent* pEvent )
250 switch( pEvent->type ) {
252 XRefreshKeyboardMapping( &pEvent->xmapping );
256 if( x11KeyPress( pEvent ) )
259 return TQWidget::x11Event( pEvent );
263 void KGlobalAccelPrivate::x11MappingNotify()
265 kdDebug(125) <<
"KGlobalAccelPrivate::x11MappingNotify()" <<
endl;
268 calculateGrabMasks();
273 void KGlobalAccelPrivate::fakeKeyPressed(
unsigned int keyCode) {
275 codemod.code = keyCode;
278 KKey key = (keyCode, 0);
281 << TQString(TQString(
" keyCodeX: %1 keyCode: %2 keyModX: %3" )
282 .arg( codemod.code, 0, 16 ).arg( keyCode, 0, 16 ).arg( codemod.mod, 0, 16 )) << endl;
285 if( !m_rgCodeModToAction.contains( codemod ) ) {
287 for( CodeModMap::ConstIterator it = m_rgCodeModToAction.begin(); it != m_rgCodeModToAction.end(); ++it ) {
288 KAccelAction* pAction = *it;
289 kdDebug(125) <<
"\tcode: " << TQString::number(it.key().code, 16) <<
" mod: " << TQString::number(it.key().mod, 16)
290 << (pAction ? TQString(
" name: \"%1\" shortcut: %2").arg(pAction->name()).arg(pAction->shortcut().toStringInternal()) : TQString())
297 KAccelAction* pAction = m_rgCodeModToAction[codemod];
300 static bool recursion_block =
false;
301 if( !recursion_block ) {
302 recursion_block =
true;
303 TQPopupMenu* pMenu = createPopupMenu( 0,
KKeySequence(key) );
304 connect( pMenu, TQT_SIGNAL(activated(
int)),
this, TQT_SLOT(slotActivated(
int)) );
305 pMenu->exec( TQPoint( 0, 0 ) );
306 disconnect( pMenu, TQT_SIGNAL(activated(
int)),
this, TQT_SLOT(slotActivated(
int)));
308 recursion_block =
false;
310 }
else if( !pAction->objSlotPtr() || !pAction->isEnabled() )
316 bool KGlobalAccelPrivate::x11KeyPress(
const XEvent *pEvent )
319 if ( !TQWidget::keyboardGrabber() && !TQApplication::activePopupWidget() ) {
320 XUngrabKeyboard( qt_xdisplay(), pEvent->xkey.time );
321 XFlush( qt_xdisplay());
324 if( !isEnabledInternal() || m_suspended )
328 codemod.code = pEvent->xkey.keycode;
329 codemod.mod = pEvent->xkey.state & (g_keyModMaskXAccel | KKeyServer::MODE_SWITCH);
335 uint sym = XKeycodeToKeysym( qt_xdisplay(), codemod.code, 0 );
337 if( sym >= XK_KP_Space && sym <= XK_KP_9 ) {
348 codemod.mod &= ~KKeyServer::modXShift();
356 KKey key = keyNative;
359 << TQString(TQString(
" keyCodeX: %1 state: %2 keyModX: %3" )
360 .arg( codemod.code, 0, 16 ).arg( pEvent->xkey.state, 0, 16 ).arg( codemod.mod, 0, 16 )) << endl;
363 if( !m_rgCodeModToAction.contains( codemod ) ) {
365 for( CodeModMap::ConstIterator it = m_rgCodeModToAction.begin(); it != m_rgCodeModToAction.end(); ++it ) {
366 KAccelAction* pAction = *it;
367 kdDebug(125) <<
"\tcode: " << TQString::number(it.key().code, 16) <<
" mod: " << TQString::number(it.key().mod, 16)
368 << (pAction ? TQString(
" name: \"%1\" shortcut: %2").arg(pAction->name()).arg(pAction->shortcut().toStringInternal()) : TQString())
375 KAccelAction* pAction = m_rgCodeModToAction[codemod];
378 static bool recursion_block =
false;
379 if( !recursion_block ) {
380 recursion_block =
true;
381 TQPopupMenu* pMenu = createPopupMenu( 0,
KKeySequence(key) );
382 connect( pMenu, TQT_SIGNAL(activated(
int)),
this, TQT_SLOT(slotActivated(
int)) );
383 pMenu->exec( TQPoint( 0, 0 ) );
384 disconnect( pMenu, TQT_SIGNAL(activated(
int)),
this, TQT_SLOT(slotActivated(
int)));
386 recursion_block =
false;
388 }
else if( !pAction->objSlotPtr() || !pAction->isEnabled() )
396 void KGlobalAccelPrivate::activate( KAccelAction* pAction,
const KKeySequence& seq )
398 kdDebug(125) <<
"KGlobalAccelPrivate::activate( \"" << pAction->name() <<
"\" ) " <<
endl;
400 TQRegExp rexPassIndex(
"([ ]*int[ ]*)" );
401 TQRegExp rexPassInfo(
" TQString" );
402 TQRegExp rexIndex(
" ([0-9]+)$" );
407 if( rexPassIndex.search( pAction->methodSlotPtr() ) >= 0 && rexIndex.search( pAction->name() ) >= 0 ) {
408 int n = rexIndex.cap(1).toInt();
409 kdDebug(125) <<
"Calling " << pAction->methodSlotPtr() <<
" int = " << n <<
endl;
410 int slot_id = pAction->objSlotPtr()->metaObject()->findSlot( normalizeSignalSlot( pAction->methodSlotPtr() ).data() + 1, true );
413 static_TQUType_int.set(o+1,n);
414 const_cast< TQObject*
>( pAction->objSlotPtr())->qt_invoke( slot_id, o );
416 }
else if( rexPassInfo.search( pAction->methodSlotPtr() ) ) {
417 int slot_id = pAction->objSlotPtr()->metaObject()->findSlot( normalizeSignalSlot( pAction->methodSlotPtr() ).data() + 1, true );
420 static_TQUType_TQString.set(o+1,pAction->name());
421 static_TQUType_TQString.set(o+2,pAction->label());
422 static_TQUType_ptr.set(o+3,&seq);
423 const_cast< TQObject*
>( pAction->objSlotPtr())->qt_invoke( slot_id, o );
426 int slot_id = pAction->objSlotPtr()->metaObject()->findSlot( normalizeSignalSlot( pAction->methodSlotPtr() ).data() + 1, true );
428 const_cast< TQObject*
>( pAction->objSlotPtr())->qt_invoke( slot_id, 0 );
432 void KGlobalAccelPrivate::slotActivated(
int iAction )
434 KAccelAction* pAction = KAccelBase::actions().actionPtr( iAction );
439 #include "kglobalaccel_x11.moc"