22#include <tqwindowdefs.h>
25#include "tdeglobalaccel_x11.h"
26#include "tdeglobalaccel.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";
63static uint g_keyModMaskXAccel = 0;
64static uint g_keyModMaskXOnOrOff = 0;
66static void calculateGrabMasks()
69 g_keyModMaskXOnOrOff =
80static TQValueList< TDEGlobalAccelPrivate* >* all_accels = 0;
82TDEGlobalAccelPrivate::TDEGlobalAccelPrivate()
83: TDEAccelBase( TDEAccelBase::NATIVE_KEYS )
85, m_blockingDisabled( false )
88 if( all_accels == NULL )
89 all_accels =
new TQValueList< TDEGlobalAccelPrivate* >;
90 all_accels->append(
this );
91 m_sConfigGroup =
"Global Shortcuts";
92 tdeApp->installX11EventFilter(
this );
93 connect(tdeApp, TQ_SIGNAL(coreFakeKeyPress(
unsigned int)),
this, TQ_SLOT(fakeKeyPressed(
unsigned int)));
96TDEGlobalAccelPrivate::~TDEGlobalAccelPrivate()
102 all_accels->remove(
this );
103 if( all_accels->count() == 0 ) {
109void TDEGlobalAccelPrivate::setEnabled(
bool bEnable )
111 m_bEnabled = bEnable;
115void 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();
129void TDEGlobalAccelPrivate::disableBlocking(
bool block )
131 m_blockingDisabled = block;
134bool TDEGlobalAccelPrivate::isEnabledInternal()
const
136 return TDEAccelBase::isEnabled() && !m_blocked;
141void TDEGlobalAccelPrivate::suspend(
bool s )
146bool TDEGlobalAccelPrivate::emitSignal( Signal )
151bool TDEGlobalAccelPrivate::connectKey( TDEAccelAction& action,
const KKeyServer::Key& key )
152 {
return grabKey( key,
true, &action ); }
154 {
return grabKey( key,
true, 0 ); }
155bool TDEGlobalAccelPrivate::disconnectKey( TDEAccelAction& action,
const KKeyServer::Key& key )
156 {
return grabKey( key,
false, &action ); }
158 {
return grabKey( key,
false, 0 ); }
160bool 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;
190 kdDebug(125) << TQString(TQString(
"grabKey( key: '%1', bGrab: %2 ): keyCodeX: %3 keyModX: %4\n" )
191 .arg(
key.key().toStringInternal() ).arg( bGrab )
192 .arg( keyCodeX, 0, 16 ).arg( keyModX, 0, 16 ));
206 TQString sDebug = TQString(
"\tcode: 0x%1 state: 0x%2 | ").arg(keyCodeX,0,16).arg(keyModX,0,16);
208 uint keyModMaskX = ~g_keyModMaskXOnOrOff;
209 for( uint irrelevantBitsMask = 0; irrelevantBitsMask <= 0xff; irrelevantBitsMask++ ) {
210 if( (irrelevantBitsMask & keyModMaskX) == 0 ) {
212 sDebug += TQString(
"0x%3, ").arg(irrelevantBitsMask, 0, 16);
215 XGrabKey( tqt_xdisplay(), keyCodeX, keyModX | irrelevantBitsMask,
216 tqt_xrootwin(), True, GrabModeAsync, GrabModeSync );
218 XUngrabKey( tqt_xdisplay(), keyCodeX, keyModX | irrelevantBitsMask, tqt_xrootwin() );
228 failed = handler.error(
true );
232 kdDebug(125) <<
"grab failed!\n";
233 for( uint m = 0; m <= 0xff; m++ ) {
234 if(( m & keyModMaskX ) == 0 )
235 XUngrabKey( tqt_xdisplay(), keyCodeX, keyModX | m, tqt_xrootwin() );
242 codemod.code = keyCodeX;
243 codemod.mod = keyModX;
244 if(
key.mod() & KKeyServer::MODE_SWITCH )
245 codemod.mod |= KKeyServer::MODE_SWITCH;
248 m_rgCodeModToAction.insert( codemod, pAction );
250 m_rgCodeModToAction.remove( codemod );
255bool TDEGlobalAccelPrivate::x11Event( XEvent* pEvent )
258 switch( pEvent->type ) {
260 XRefreshKeyboardMapping( &pEvent->xmapping );
264 if( x11KeyPress( pEvent ) ) {
268 return TQWidget::x11Event( pEvent );
272void TDEGlobalAccelPrivate::x11MappingNotify()
274 kdDebug(125) <<
"TDEGlobalAccelPrivate::x11MappingNotify()" <<
endl;
277 calculateGrabMasks();
282void TDEGlobalAccelPrivate::fakeKeyPressed(
unsigned int keyCode) {
284 codemod.code = keyCode;
289 kdDebug(125) <<
"fakeKeyPressed: seek " <<
key.toStringInternal()
290 << TQString(TQString(
" keyCodeX: %1 keyCode: %2 keyModX: %3" )
291 .arg( codemod.code, 0, 16 ).arg( keyCode, 0, 16 ).arg( codemod.mod, 0, 16 )) <<
endl;
294 if( !m_rgCodeModToAction.contains( codemod ) ) {
296 for( CodeModMap::ConstIterator it = m_rgCodeModToAction.begin(); it != m_rgCodeModToAction.end(); ++it ) {
297 TDEAccelAction* pAction = *it;
298 kdDebug(125) <<
"\tcode: " << TQString::number(it.key().code, 16) <<
" mod: " << TQString::number(it.key().mod, 16)
299 << (pAction ? TQString(
" name: \"%1\" shortcut: %2").arg(pAction->name()).arg(pAction->shortcut().toStringInternal()) : TQString())
306 TDEAccelAction* pAction = m_rgCodeModToAction[codemod];
309 static bool recursion_block =
false;
310 if( !recursion_block ) {
311 recursion_block =
true;
312 TQPopupMenu* pMenu = createPopupMenu( 0,
KKeySequence(key) );
313 connect( pMenu, TQ_SIGNAL(activated(
int)),
this, TQ_SLOT(slotActivated(
int)) );
314 pMenu->exec( TQPoint( 0, 0 ) );
315 disconnect( pMenu, TQ_SIGNAL(activated(
int)),
this, TQ_SLOT(slotActivated(
int)));
317 recursion_block =
false;
319 }
else if( !pAction->objSlotPtr() || !pAction->isEnabled() )
325bool TDEGlobalAccelPrivate::x11KeyPress(
const XEvent *pEvent )
328 if ( !TQWidget::keyboardGrabber() && !TQApplication::activePopupWidget() ) {
329 XUngrabKeyboard( tqt_xdisplay(), pEvent->xkey.time );
330 XFlush( tqt_xdisplay());
333 if( !isEnabledInternal() || m_suspended ) {
338 codemod.code = pEvent->xkey.keycode;
339 codemod.mod = pEvent->xkey.state & (g_keyModMaskXAccel | KKeyServer::MODE_SWITCH);
345 uint sym = XkbKeycodeToKeysym( tqt_xdisplay(), codemod.code, 0, 0 );
347 if( sym >= XK_KP_Space && sym <= XK_KP_9 ) {
368 kdDebug(125) <<
"x11KeyPress: seek " <<
key.toStringInternal()
369 << TQString(TQString(
" keyCodeX: %1 state: %2 keyModX: %3" )
370 .arg( codemod.code, 0, 16 ).arg( pEvent->xkey.state, 0, 16 ).arg( codemod.mod, 0, 16 )) <<
endl;
373 if( !m_rgCodeModToAction.contains( codemod ) ) {
375 for( CodeModMap::ConstIterator it = m_rgCodeModToAction.begin(); it != m_rgCodeModToAction.end(); ++it ) {
376 TDEAccelAction* pAction = *it;
377 kdDebug(125) <<
"\tcode: " << TQString::number(it.key().code, 16) <<
" mod: " << TQString::number(it.key().mod, 16)
378 << (pAction ? TQString(
" name: \"%1\" shortcut: %2").arg(pAction->name()).arg(pAction->shortcut().toStringInternal()) : TQString())
385 TDEAccelAction* pAction = m_rgCodeModToAction[codemod];
388 static bool recursion_block =
false;
389 if( !recursion_block ) {
390 recursion_block =
true;
391 TQPopupMenu* pMenu = createPopupMenu( 0,
KKeySequence(key) );
392 connect( pMenu, TQ_SIGNAL(activated(
int)),
this, TQ_SLOT(slotActivated(
int)) );
393 pMenu->exec( TQPoint( 0, 0 ) );
394 disconnect( pMenu, TQ_SIGNAL(activated(
int)),
this, TQ_SLOT(slotActivated(
int)));
396 recursion_block =
false;
398 }
else if( !pAction->objSlotPtr() || !pAction->isEnabled() )
406void TDEGlobalAccelPrivate::activate( TDEAccelAction* pAction,
const KKeySequence& seq )
408 kdDebug(125) <<
"TDEGlobalAccelPrivate::activate( \"" << pAction->name() <<
"\" ) " <<
endl;
410 TQRegExp rexPassIndex(
"([ ]*int[ ]*)" );
411 TQRegExp rexPassInfo(
" TQString" );
412 TQRegExp rexIndex(
" ([0-9]+)$" );
417 if( rexPassIndex.search( pAction->methodSlotPtr() ) >= 0 && rexIndex.search( pAction->name() ) >= 0 ) {
418 int n = rexIndex.cap(1).toInt();
419 kdDebug(125) <<
"Calling " << pAction->methodSlotPtr() <<
" int = " << n <<
endl;
420 int slot_id = pAction->objSlotPtr()->metaObject()->findSlot( normalizeSignalSlot( pAction->methodSlotPtr() ).data() + 1,
true );
423 static_QUType_int.set(o+1,n);
424 const_cast< TQObject*
>( pAction->objSlotPtr())->tqt_invoke( slot_id, o );
426 }
else if( rexPassInfo.search( pAction->methodSlotPtr() ) ) {
427 int slot_id = pAction->objSlotPtr()->metaObject()->findSlot( normalizeSignalSlot( pAction->methodSlotPtr() ).data() + 1, true );
430 static_QUType_TQString.set(o+1,pAction->name());
431 static_QUType_TQString.set(o+2,pAction->label());
432 static_QUType_ptr.set(o+3,&seq);
433 const_cast< TQObject*
>( pAction->objSlotPtr())->tqt_invoke( slot_id, o );
436 int slot_id = pAction->objSlotPtr()->metaObject()->findSlot( normalizeSignalSlot( pAction->methodSlotPtr() ).data() + 1, true );
438 const_cast< TQObject*
>( pAction->objSlotPtr())->tqt_invoke( slot_id, 0 );
442void TDEGlobalAccelPrivate::slotActivated(
int iAction )
444 TDEAccelAction* pAction = TDEAccelBase::actions().actionPtr( iAction );
449#include "tdeglobalaccel_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.