KDEUI
kglobalaccel_x11.cpp
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "kglobalaccel_x11.h"
00021
00022 #include <config.h>
00023
00024 #include <QtGui/QWidgetList>
00025
00026 #include "kaction.h"
00027 #include "kdedglobalaccel.h"
00028 #include "kkeyserver_x11.h"
00029
00030 #include <kapplication.h>
00031 #include <kdebug.h>
00032
00033 #include <QtCore/QRegExp>
00034 #include <QtGui/QWidget>
00035 #include <QtCore/QMetaClassInfo>
00036 #include <QtGui/QMenu>
00037
00038 #include <kxerrorhandler.h>
00039
00040 #include <X11/X.h>
00041 #include <X11/Xlib.h>
00042 #include <X11/Xutil.h>
00043 #include <X11/keysym.h>
00044 #include <fixx11h.h>
00045
00046 extern "C" {
00047 static int XGrabErrorHandler( Display *, XErrorEvent *e ) {
00048 if ( e->error_code != BadAccess ) {
00049 kWarning() << "grabKey: got X error " << e->type << " instead of BadAccess\n";
00050 }
00051 return 1;
00052 }
00053 }
00054
00055
00056
00057
00058
00059
00060
00061 static uint g_keyModMaskXAccel = 0;
00062 static uint g_keyModMaskXOnOrOff = 0;
00063
00064 static void calculateGrabMasks()
00065 {
00066 g_keyModMaskXAccel = KKeyServer::accelModMaskX();
00067 g_keyModMaskXOnOrOff =
00068 KKeyServer::modXLock() |
00069 KKeyServer::modXNumLock() |
00070 KKeyServer::modXScrollLock() |
00071 KKeyServer::modXModeSwitch();
00072
00073
00074 }
00075
00076
00077
00078 KGlobalAccelImpl::KGlobalAccelImpl(KdedGlobalAccel *owner)
00079 : m_owner(owner)
00080 {
00081 calculateGrabMasks();
00082 }
00083
00084 bool KGlobalAccelImpl::grabKey( int keyQt, bool grab )
00085 {
00086 if( !keyQt ) {
00087 kWarning(125) << "Tried to grab key with null code.";
00088 return false;
00089 }
00090
00091 int keyCodeX;
00092 uint keyModX;
00093 KKeyServer::keyQtToCodeX(keyQt, &keyCodeX);
00094 KKeyServer::keyQtToModX(keyQt, &keyModX);
00095
00096 keyModX &= g_keyModMaskXAccel;
00097
00098
00099
00100
00101 if( keyCodeX == XK_Sys_Req && XKeycodeToKeysym( QX11Info::display(), 111, 0 ) == XK_Print ) {
00102 keyModX |= KKeyServer::modXAlt();
00103 keyCodeX = 111;
00104 }
00105
00106 if( !keyCodeX )
00107 return false;
00108
00109 kDebug(125) << "grabKey keyQt " << (keyQt & ~Qt::KeyboardModifierMask)
00110 << " mod " << (keyQt & Qt::KeyboardModifierMask) << " ( key: '" << QKeySequence(keyQt).toString()
00111 << "', grab: " << grab << " ): keyCodeX: " << keyCodeX << " keyModX: " << keyModX << endl;
00112
00113 KXErrorHandler handler( XGrabErrorHandler );
00114
00115
00116
00117
00118
00119
00120 #ifndef NDEBUG
00121 QString sDebug = QString("\tcode: 0x%1 state: 0x%2 | ").arg(keyCodeX,0,16).arg(keyModX,0,16);
00122 #endif
00123 uint keyModMaskX = ~g_keyModMaskXOnOrOff;
00124 for( uint irrelevantBitsMask = 0; irrelevantBitsMask <= 0xff; irrelevantBitsMask++ ) {
00125 if( (irrelevantBitsMask & keyModMaskX) == 0 ) {
00126 #ifndef NDEBUG
00127 sDebug += QString("0x%3, ").arg(irrelevantBitsMask, 0, 16);
00128 #endif
00129 if( grab )
00130 XGrabKey( QX11Info::display(), keyCodeX, keyModX | irrelevantBitsMask,
00131 QX11Info::appRootWindow(), True, GrabModeAsync, GrabModeSync );
00132 else
00133 XUngrabKey( QX11Info::display(), keyCodeX, keyModX | irrelevantBitsMask, QX11Info::appRootWindow() );
00134 }
00135 }
00136
00137 #ifndef NDEBUG
00138 kDebug(125) << sDebug;
00139 #endif
00140
00141 bool failed = false;
00142 if( grab ) {
00143 failed = handler.error( true );
00144 if( failed ) {
00145 kDebug(125) << "grab failed!\n";
00146 for( uint m = 0; m <= 0xff; m++ ) {
00147 if(( m & keyModMaskX ) == 0 )
00148 XUngrabKey( QX11Info::display(), keyCodeX, keyModX | m, QX11Info::appRootWindow() );
00149 }
00150 }
00151 }
00152
00153 return !failed;
00154 }
00155
00156 bool KGlobalAccelImpl::x11Event( XEvent* event )
00157 {
00158 switch( event->type ) {
00159 case MappingNotify:
00160 XRefreshKeyboardMapping(&event->xmapping);
00161 x11MappingNotify();
00162 return true;
00163
00164 case XKeyPress:
00165 if( x11KeyPress( event ) )
00166 return true;
00167 break;
00168 }
00169 return false;
00170 }
00171
00172 void KGlobalAccelImpl::x11MappingNotify()
00173 {
00174 kDebug(125) << "KGlobalAccelImpl::x11MappingNotify()";
00175
00176 uint oldKeyModMaskXAccel = g_keyModMaskXAccel;
00177 uint oldKeyModMaskXOnOrOff = g_keyModMaskXOnOrOff;
00178
00179 KKeyServer::initializeMods();
00180 calculateGrabMasks();
00181
00182 #if 0 //### investigate!
00183 if (oldKeyModMaskXAccel != g_keyModMaskXAccel || oldKeyModMaskXOnOrOff != g_keyModMaskXOnOrOff)
00184
00185 m_owner->regrabKeys();
00186 #endif
00187 }
00188
00189 bool KGlobalAccelImpl::x11KeyPress( const XEvent *pEvent )
00190 {
00191
00192
00193
00194
00195
00196
00197 if( !QWidget::keyboardGrabber() && !QApplication::activePopupWidget()) {
00198 XUngrabKeyboard( QX11Info::display(), pEvent->xkey.time );
00199 XFlush( QX11Info::display());
00200 }
00201
00202 uchar keyCodeX = pEvent->xkey.keycode;
00203 uint keyModX = pEvent->xkey.state & (g_keyModMaskXAccel | KKeyServer::MODE_SWITCH);
00204
00205 KeySym keySym;
00206 XLookupString( (XKeyEvent*) pEvent, 0, 0, &keySym, 0 );
00207 uint keySymX = (uint)keySym;
00208
00209
00210
00211 if( pEvent->xkey.state & KKeyServer::modXNumLock() ) {
00212 uint sym = XKeycodeToKeysym( QX11Info::display(), keyCodeX, 0 );
00213
00214 if( sym >= XK_KP_Space && sym <= XK_KP_9 ) {
00215 switch( sym ) {
00216
00217
00218 case XK_KP_Multiply:
00219 case XK_KP_Add:
00220 case XK_KP_Subtract:
00221 case XK_KP_Divide:
00222 break;
00223 default:
00224 keyModX ^= KKeyServer::modXShift();
00225 }
00226 }
00227 }
00228
00229 int keyCodeQt;
00230 int keyModQt;
00231 KKeyServer::symXToKeyQt(keySymX, &keyCodeQt);
00232 KKeyServer::modXToQt(keyModX, &keyModQt);
00233
00234 int keyQt = keyCodeQt | keyModQt;
00235
00236 kDebug(125) << "Qt " << keyQt << " [Key: " << keyCodeQt << " Mod: " << keyModQt << "] X [Key: " << keySymX << " Mod: " << keyModX << "]";
00237
00238
00239 if (m_owner->keyPressed(keyQt))
00240 return true;
00241
00242 return false;
00243 }
00244
00245 void KGlobalAccelImpl::setEnabled( bool enable )
00246 {
00247 if (enable) {
00248 kapp->installX11EventFilter( this );
00249 } else
00250 kapp->removeX11EventFilter( this );
00251 }
00252
00253
00254 #include "kglobalaccel_x11.moc"