00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "kkeyserver_x11.h"
00024 #include "kshortcut.h"
00025
00026 #include <config.h>
00027
00028 #include <QtCore/QCOORD>
00029 #include <QtGui/QWidgetList>
00030 #include <QFlags>
00031
00032 #include <kconfig.h>
00033 #include <kdebug.h>
00034 #include <kglobal.h>
00035 #include <klocale.h>
00036
00037 #include <QX11Info>
00038 # define XK_MISCELLANY
00039 # define XK_XKB_KEYS
00040 # include <X11/X.h>
00041 # include <X11/Xlib.h>
00042 # include <X11/Xutil.h>
00043 # include <X11/keysymdef.h>
00044 # define X11_ONLY(arg) arg, //allows to omit an argument
00045
00046
00047 namespace KKeyServer
00048 {
00049
00050
00051
00052
00053
00054 struct Mod
00055 {
00056 int m_mod;
00057 };
00058
00059
00060
00061
00062
00063 struct X11ModInfo
00064 {
00065 int modQt;
00066 int modX;
00067 };
00068
00069 struct SymVariation
00070 {
00071 uint sym, symVariation;
00072 bool bActive;
00073 };
00074
00075 struct SymName
00076 {
00077 uint sym;
00078 const char* psName;
00079 };
00080
00081 struct TransKey {
00082 int keySymQt;
00083 uint keySymX;
00084 };
00085
00086
00087
00088
00089
00090 static X11ModInfo g_rgX11ModInfo[4] =
00091 {
00092 { Qt::SHIFT, X11_ONLY(ShiftMask) },
00093 { Qt::CTRL, X11_ONLY(ControlMask) },
00094 { Qt::ALT, X11_ONLY(Mod1Mask) },
00095 { Qt::META, X11_ONLY(Mod4Mask) }
00096 };
00097
00098
00099 static const SymName g_rgSymNames[] = {
00100 { XK_ISO_Left_Tab, "Backtab" },
00101 { XK_BackSpace, I18N_NOOP("Backspace") },
00102 { XK_Sys_Req, I18N_NOOP("SysReq") },
00103 { XK_Caps_Lock, I18N_NOOP("CapsLock") },
00104 { XK_Num_Lock, I18N_NOOP("NumLock") },
00105 { XK_Scroll_Lock, I18N_NOOP("ScrollLock") },
00106 { XK_Prior, I18N_NOOP("PageUp") },
00107 { XK_Next, I18N_NOOP("PageDown") },
00108 #ifdef sun
00109 { XK_F11, I18N_NOOP("Stop") },
00110 { XK_F12, I18N_NOOP("Again") },
00111 { XK_F13, I18N_NOOP("Props") },
00112 { XK_F14, I18N_NOOP("Undo") },
00113 { XK_F15, I18N_NOOP("Front") },
00114 { XK_F16, I18N_NOOP("Copy") },
00115 { XK_F17, I18N_NOOP("Open") },
00116 { XK_F18, I18N_NOOP("Paste") },
00117 { XK_F19, I18N_NOOP("Find") },
00118 { XK_F20, I18N_NOOP("Cut") },
00119 { XK_F22, I18N_NOOP("Print") },
00120 #endif
00121 { 0, 0 }
00122 };
00123
00124
00125 static const TransKey g_rgQtToSymX[] =
00126 {
00127 { Qt::Key_Escape, XK_Escape },
00128 { Qt::Key_Tab, XK_Tab },
00129 { Qt::Key_Backtab, XK_ISO_Left_Tab },
00130 { Qt::Key_Backspace, XK_BackSpace },
00131 { Qt::Key_Return, XK_Return },
00132 { Qt::Key_Enter, XK_KP_Enter },
00133 { Qt::Key_Insert, XK_Insert },
00134 { Qt::Key_Delete, XK_Delete },
00135 { Qt::Key_Pause, XK_Pause },
00136 #ifdef sun
00137 { Qt::Key_Print, XK_F22 },
00138 #else
00139 { Qt::Key_Print, XK_Print },
00140 #endif
00141 { Qt::Key_SysReq, XK_Sys_Req },
00142 { Qt::Key_Home, XK_Home },
00143 { Qt::Key_End, XK_End },
00144 { Qt::Key_Left, XK_Left },
00145 { Qt::Key_Up, XK_Up },
00146 { Qt::Key_Right, XK_Right },
00147 { Qt::Key_Down, XK_Down },
00148 { Qt::Key_PageUp, XK_Prior },
00149 { Qt::Key_PageDown, XK_Next },
00150
00151
00152
00153
00154 { Qt::Key_CapsLock, XK_Caps_Lock },
00155 { Qt::Key_NumLock, XK_Num_Lock },
00156 { Qt::Key_ScrollLock, XK_Scroll_Lock },
00157 { Qt::Key_F1, XK_F1 },
00158 { Qt::Key_F2, XK_F2 },
00159 { Qt::Key_F3, XK_F3 },
00160 { Qt::Key_F4, XK_F4 },
00161 { Qt::Key_F5, XK_F5 },
00162 { Qt::Key_F6, XK_F6 },
00163 { Qt::Key_F7, XK_F7 },
00164 { Qt::Key_F8, XK_F8 },
00165 { Qt::Key_F9, XK_F9 },
00166 { Qt::Key_F10, XK_F10 },
00167 { Qt::Key_F11, XK_F11 },
00168 { Qt::Key_F12, XK_F12 },
00169 { Qt::Key_F13, XK_F13 },
00170 { Qt::Key_F14, XK_F14 },
00171 { Qt::Key_F15, XK_F15 },
00172 { Qt::Key_F16, XK_F16 },
00173 { Qt::Key_F17, XK_F17 },
00174 { Qt::Key_F18, XK_F18 },
00175 { Qt::Key_F19, XK_F19 },
00176 { Qt::Key_F20, XK_F20 },
00177 { Qt::Key_F21, XK_F21 },
00178 { Qt::Key_F22, XK_F22 },
00179 { Qt::Key_F23, XK_F23 },
00180 { Qt::Key_F24, XK_F24 },
00181 { Qt::Key_F25, XK_F25 },
00182 { Qt::Key_F26, XK_F26 },
00183 { Qt::Key_F27, XK_F27 },
00184 { Qt::Key_F28, XK_F28 },
00185 { Qt::Key_F29, XK_F29 },
00186 { Qt::Key_F30, XK_F30 },
00187 { Qt::Key_F31, XK_F31 },
00188 { Qt::Key_F32, XK_F32 },
00189 { Qt::Key_F33, XK_F33 },
00190 { Qt::Key_F34, XK_F34 },
00191 { Qt::Key_F35, XK_F35 },
00192 { Qt::Key_Super_L, XK_Super_L },
00193 { Qt::Key_Super_R, XK_Super_R },
00194 { Qt::Key_Menu, XK_Menu },
00195 { Qt::Key_Hyper_L, XK_Hyper_L },
00196 { Qt::Key_Hyper_R, XK_Hyper_R },
00197 { Qt::Key_Help, XK_Help },
00198
00199
00200
00201 { '/', XK_KP_Divide },
00202 { '*', XK_KP_Multiply },
00203 { '-', XK_KP_Subtract },
00204 { '+', XK_KP_Add },
00205 { Qt::Key_Return, XK_KP_Enter }
00206
00207
00208
00209 #define XF86XK_Standby 0x1008FF10
00210 #define XF86XK_AudioLowerVolume 0x1008FF11
00211 #define XF86XK_AudioMute 0x1008FF12
00212 #define XF86XK_AudioRaiseVolume 0x1008FF13
00213 #define XF86XK_AudioPlay 0x1008FF14
00214 #define XF86XK_AudioStop 0x1008FF15
00215 #define XF86XK_AudioPrev 0x1008FF16
00216 #define XF86XK_AudioNext 0x1008FF17
00217 #define XF86XK_HomePage 0x1008FF18
00218 #define XF86XK_Calculator 0x1008FF1D
00219 #define XF86XK_Mail 0x1008FF19
00220 #define XF86XK_Start 0x1008FF1A
00221 #define XF86XK_Search 0x1008FF1B
00222 #define XF86XK_AudioRecord 0x1008FF1C
00223 #define XF86XK_Back 0x1008FF26
00224 #define XF86XK_Forward 0x1008FF27
00225 #define XF86XK_Stop 0x1008FF28
00226 #define XF86XK_Refresh 0x1008FF29
00227 #define XF86XK_Favorites 0x1008FF30
00228 #define XF86XK_AudioPause 0x1008FF31
00229 #define XF86XK_AudioMedia 0x1008FF32
00230 #define XF86XK_MyComputer 0x1008FF33
00231 #define XF86XK_OpenURL 0x1008FF38
00232 #define XF86XK_Launch0 0x1008FF40
00233 #define XF86XK_Launch1 0x1008FF41
00234 #define XF86XK_Launch2 0x1008FF42
00235 #define XF86XK_Launch3 0x1008FF43
00236 #define XF86XK_Launch4 0x1008FF44
00237 #define XF86XK_Launch5 0x1008FF45
00238 #define XF86XK_Launch6 0x1008FF46
00239 #define XF86XK_Launch7 0x1008FF47
00240 #define XF86XK_Launch8 0x1008FF48
00241 #define XF86XK_Launch9 0x1008FF49
00242 #define XF86XK_LaunchA 0x1008FF4A
00243 #define XF86XK_LaunchB 0x1008FF4B
00244 #define XF86XK_LaunchC 0x1008FF4C
00245 #define XF86XK_LaunchD 0x1008FF4D
00246 #define XF86XK_LaunchE 0x1008FF4E
00247 #define XF86XK_LaunchF 0x1008FF4F
00248
00249 ,
00250 { Qt::Key_Standby, XF86XK_Standby },
00251 { Qt::Key_VolumeDown, XF86XK_AudioLowerVolume },
00252 { Qt::Key_VolumeMute, XF86XK_AudioMute },
00253 { Qt::Key_VolumeUp, XF86XK_AudioRaiseVolume },
00254 { Qt::Key_MediaPlay, XF86XK_AudioPlay },
00255 { Qt::Key_MediaStop, XF86XK_AudioStop },
00256 { Qt::Key_MediaPrevious, XF86XK_AudioPrev },
00257 { Qt::Key_MediaNext, XF86XK_AudioNext },
00258 { Qt::Key_HomePage, XF86XK_HomePage },
00259 { Qt::Key_LaunchMail, XF86XK_Mail },
00260 { Qt::Key_Search, XF86XK_Search },
00261 { Qt::Key_MediaRecord, XF86XK_AudioRecord },
00262 { Qt::Key_LaunchMedia, XF86XK_AudioMedia },
00263 { Qt::Key_Launch1, XF86XK_Calculator },
00264 { Qt::Key_Back, XF86XK_Back },
00265 { Qt::Key_Forward, XF86XK_Forward },
00266 { Qt::Key_Stop, XF86XK_Stop },
00267 { Qt::Key_Refresh, XF86XK_Refresh },
00268 { Qt::Key_Favorites, XF86XK_Favorites },
00269 { Qt::Key_Launch0, XF86XK_MyComputer },
00270 { Qt::Key_OpenUrl, XF86XK_OpenURL },
00271 { Qt::Key_Launch2, XF86XK_Launch0 },
00272 { Qt::Key_Launch3, XF86XK_Launch1 },
00273 { Qt::Key_Launch4, XF86XK_Launch2 },
00274 { Qt::Key_Launch5, XF86XK_Launch3 },
00275 { Qt::Key_Launch6, XF86XK_Launch4 },
00276 { Qt::Key_Launch7, XF86XK_Launch5 },
00277 { Qt::Key_Launch8, XF86XK_Launch6 },
00278 { Qt::Key_Launch9, XF86XK_Launch7 },
00279 { Qt::Key_LaunchA, XF86XK_Launch8 },
00280 { Qt::Key_LaunchB, XF86XK_Launch9 },
00281 { Qt::Key_LaunchC, XF86XK_LaunchA },
00282 { Qt::Key_LaunchD, XF86XK_LaunchB },
00283 { Qt::Key_LaunchE, XF86XK_LaunchC },
00284 { Qt::Key_LaunchF, XF86XK_LaunchD },
00285 };
00286
00287
00288
00289
00290 #ifndef NDEBUG
00291 inline void checkDisplay()
00292 {
00293
00294 if ( !QX11Info::display() ) {
00295 kError() << "QX11Info::display() returns 0. I'm probably going to crash now." << endl;
00296 kError() << "If this is a KApplication initialized without GUI stuff, change it to be "
00297 "initialized with GUI stuff." << endl;
00298 }
00299 }
00300 #else // NDEBUG
00301 # define checkDisplay()
00302 #endif
00303
00304
00305
00306
00307
00308 static bool g_bInitializedMods;
00309 static uint g_modXNumLock, g_modXScrollLock, g_modXModeSwitch, g_alt_mask, g_meta_mask;
00310
00311 bool initializeMods()
00312 {
00313 checkDisplay();
00314 XModifierKeymap* xmk = XGetModifierMapping( QX11Info::display() );
00315
00316 g_rgX11ModInfo[3].modX = g_modXNumLock = g_modXScrollLock = g_modXModeSwitch = 0;
00317
00318 int min_keycode, max_keycode;
00319 int keysyms_per_keycode = 0;
00320
00321 XDisplayKeycodes( QX11Info::display(), &min_keycode, &max_keycode );
00322 XFree( XGetKeyboardMapping( QX11Info::display(), min_keycode, 1, &keysyms_per_keycode ));
00323
00324
00325 g_alt_mask = Mod1Mask;
00326 g_meta_mask = Mod4Mask;
00327
00328 for( int i = Mod1MapIndex; i < 8; i++ ) {
00329 uint mask = (1 << i);
00330 uint keySymX = NoSymbol;
00331
00332
00333
00334
00335
00336 for( int j = 0; j < xmk->max_keypermod && keySymX == NoSymbol; ++j )
00337 for( int k = 0; k < keysyms_per_keycode && keySymX == NoSymbol; ++k )
00338 keySymX = XKeycodeToKeysym( QX11Info::display(), xmk->modifiermap[xmk->max_keypermod * i + j], k );
00339 switch( keySymX ) {
00340 case XK_Alt_L:
00341 case XK_Alt_R: g_alt_mask = mask; break;
00342
00343 case XK_Super_L:
00344 case XK_Super_R: g_meta_mask = mask; break;
00345
00346 case XK_Meta_L:
00347 case XK_Meta_R: if( !g_meta_mask ) g_meta_mask = mask; break;
00348
00349 case XK_Num_Lock: g_modXNumLock = mask; break;
00350 case XK_Scroll_Lock: g_modXScrollLock = mask; break;
00351 case XK_Mode_switch: g_modXModeSwitch = mask; break;
00352 }
00353 }
00354
00355 g_rgX11ModInfo[3].modX = g_meta_mask;
00356 g_rgX11ModInfo[2].modX = g_alt_mask;
00357
00358 XFreeModifiermap( xmk );
00359
00360
00361
00362
00363 g_bInitializedMods = true;
00364
00365 kDebug(125) << "KKeyServer::initializeMods(): Win Mod = 0x" << QString::number(g_rgX11ModInfo[3].modX, 16);
00366 return true;
00367 }
00368
00369
00370
00371
00372
00373
00374
00375 uint modXShift() { return ShiftMask; }
00376 uint modXCtrl() { return ControlMask; }
00377 uint modXAlt() { if( !g_bInitializedMods ) { initializeMods(); } return g_alt_mask; }
00378 uint modXMeta() { if( !g_bInitializedMods ) { initializeMods(); } return g_meta_mask; }
00379
00380 uint modXNumLock() { if( !g_bInitializedMods ) { initializeMods(); } return g_modXNumLock; }
00381 uint modXLock() { return LockMask; }
00382 uint modXScrollLock() { if( !g_bInitializedMods ) { initializeMods(); } return g_modXScrollLock; }
00383 uint modXModeSwitch() { if( !g_bInitializedMods ) { initializeMods(); } return g_modXModeSwitch; }
00384
00385 bool keyboardHasMetaKey() { return modXMeta() != 0; }
00386
00387
00388 uint getModsRequired(uint sym)
00389 {
00390 uint mod = 0;
00391
00392
00393 if( sym == XK_Sys_Req ) return Qt::ALT;
00394 if( sym == XK_Break ) return Qt::CTRL;
00395
00396 if( sym < 0x3000 ) {
00397 QChar c(sym);
00398 if( c.isLetter() && c.toLower() != c.toUpper() && sym == c.toUpper().unicode() )
00399 return Qt::SHIFT;
00400 }
00401
00402 uchar code = XKeysymToKeycode( QX11Info::display(), sym );
00403 if( code ) {
00404
00405
00406
00407 if( sym == XKeycodeToKeysym( QX11Info::display(), code, 0 ) )
00408 ;
00409 else if( sym == XKeycodeToKeysym( QX11Info::display(), code, 1 ) )
00410 mod = Qt::SHIFT;
00411 else if( sym == XKeycodeToKeysym( QX11Info::display(), code, 2 ) )
00412 mod = MODE_SWITCH;
00413 else if( sym == XKeycodeToKeysym( QX11Info::display(), code, 3 ) )
00414 mod = Qt::SHIFT | MODE_SWITCH;
00415 }
00416 return mod;
00417 }
00418
00419 bool keyQtToCodeX( int keyQt, int* keyCode )
00420 {
00421 int sym;
00422 uint mod;
00423 keyQtToSymX(keyQt, &sym);
00424 keyQtToModX(keyQt, &mod);
00425
00426
00427
00428 uint modExtra = getModsRequired(sym);
00429
00430 if( !sym || !keyQtToModX( (keyQt & Qt::KeyboardModifierMask) | modExtra, &mod ) ) {
00431 *keyCode = 0;
00432 return false;
00433 }
00434
00435
00436
00437
00438
00439 if( sym == XK_Print && !(mod & Mod1Mask) &&
00440 XKeycodeToKeysym( QX11Info::display(), 111, 0 ) == XK_Print )
00441 *keyCode = 111;
00442 else if( sym == XK_Break || ((sym == XK_Pause && (mod & ControlMask)) &&
00443 XKeycodeToKeysym( QX11Info::display(), 114, 0 ) == XK_Pause) )
00444 *keyCode = 114;
00445 else
00446 *keyCode = XKeysymToKeycode( QX11Info::display(), sym );
00447
00448 return true;
00449 }
00450
00451 bool keyQtToSymX( int keyQt, int* keySym )
00452 {
00453 int symQt = keyQt & ~Qt::KeyboardModifierMask;
00454
00455 if( symQt < 0x1000 ) {
00456 *keySym = QChar(symQt).toUpper().unicode();
00457 return true;
00458 }
00459
00460
00461 for( uint i = 0; i < sizeof(g_rgQtToSymX)/sizeof(TransKey); i++ ) {
00462 if( g_rgQtToSymX[i].keySymQt == symQt ) {
00463 *keySym = g_rgQtToSymX[i].keySymX;
00464 return true;
00465 }
00466 }
00467
00468 *keySym = 0;
00469 if( symQt != Qt::Key_Shift && symQt != Qt::Key_Control && symQt != Qt::Key_Alt &&
00470 symQt != Qt::Key_Meta && symQt != Qt::Key_Direction_L && symQt != Qt::Key_Direction_R )
00471 kDebug(125) << "Sym::initQt( " << QString::number(keyQt,16) << " ): failed to convert key.";
00472 return false;
00473 }
00474
00475 bool symXToKeyQt( uint keySym, int* keyQt )
00476 {
00477 *keyQt = Qt::Key_unknown;
00478 if( keySym < 0x1000 ) {
00479 if( keySym >= 'a' && keySym <= 'z' )
00480 *keyQt = QChar(keySym).toUpper().unicode();
00481 else
00482 *keyQt = keySym;
00483 }
00484
00485 else if( keySym < 0x3000 )
00486 *keyQt = keySym;
00487
00488 else {
00489 for( uint i = 0; i < sizeof(g_rgQtToSymX)/sizeof(TransKey); i++ )
00490 if( g_rgQtToSymX[i].keySymX == keySym ) {
00491 *keyQt = g_rgQtToSymX[i].keySymQt;
00492 break;
00493 }
00494 }
00495
00496 return (*keyQt != Qt::Key_unknown);
00497 }
00498
00499
00500
00501
00502 bool keyQtToModX( int modQt, uint* modX )
00503 {
00504 if( !g_bInitializedMods )
00505 initializeMods();
00506
00507 *modX = 0;
00508 for( int i = 0; i < 4; i++ ) {
00509 if( modQt & g_rgX11ModInfo[i].modQt ) {
00510 *modX |= g_rgX11ModInfo[i].modX;
00511 continue;
00512 }
00513 }
00514 return true;
00515 }
00516
00517 bool modXToQt( uint modX, int* modQt )
00518 {
00519 if( !g_bInitializedMods )
00520 initializeMods();
00521
00522 *modQt = 0;
00523 for( int i = 0; i < 4; i++ ) {
00524 if( modX & g_rgX11ModInfo[i].modX ) {
00525 *modQt |= g_rgX11ModInfo[i].modQt;
00526 continue;
00527 }
00528 }
00529 return true;
00530 }
00531
00532
00533 bool codeXToSym( uchar codeX, uint modX, uint* sym )
00534 {
00535 KeySym keySym;
00536 XKeyPressedEvent event;
00537
00538 checkDisplay();
00539
00540 event.type = KeyPress;
00541 event.display = QX11Info::display();
00542 event.state = modX;
00543 event.keycode = codeX;
00544
00545 XLookupString( &event, 0, 0, &keySym, 0 );
00546 *sym = (uint) keySym;
00547 return true;
00548 }
00549
00550
00551 uint accelModMaskX()
00552 {
00553 return modXShift() | modXCtrl() | modXAlt() | modXMeta();
00554 }
00555
00556
00557 bool xEventToQt( XEvent* e, int* keyQt )
00558 {
00559 uchar keyCodeX = e->xkey.keycode;
00560 uint keyModX = e->xkey.state & (accelModMaskX() | MODE_SWITCH);
00561
00562 KeySym keySym;
00563 XLookupString( (XKeyEvent*) e, 0, 0, &keySym, 0 );
00564 uint keySymX = (uint)keySym;
00565
00566
00567
00568 if( e->xkey.state & modXNumLock() ) {
00569 uint sym = XKeycodeToKeysym( QX11Info::display(), keyCodeX, 0 );
00570
00571
00572 if( sym >= XK_KP_Space && sym <= XK_KP_9 ) {
00573 switch( sym ) {
00574
00575
00576 case XK_KP_Multiply:
00577 case XK_KP_Add:
00578 case XK_KP_Subtract:
00579 case XK_KP_Divide:
00580 break;
00581 default:
00582 if( keyModX & modXShift() )
00583 keyModX &= ~modXShift();
00584 else
00585 keyModX |= modXShift();
00586 }
00587 }
00588 }
00589
00590 int keyCodeQt;
00591 int keyModQt;
00592 symXToKeyQt(keySymX, &keyCodeQt);
00593 modXToQt(keyModX, &keyModQt);
00594
00595 *keyQt = keyCodeQt | keyModQt;
00596 return true;
00597 }
00598
00599
00600 }