kdecore Library API Documentation

kkeyserver_x11.cpp

00001 #include <config.h> 00002 00003 #include <qnamespace.h> 00004 #include <qwindowdefs.h> 00005 00006 #ifdef Q_WS_X11 // Only compile this module if we're compiling for X11 00007 00008 #include "kkeyserver_x11.h" 00009 #include "kkeynative.h" 00010 #include "kshortcut.h" 00011 00012 #include <kconfig.h> 00013 #include <kdebug.h> 00014 #include <kglobal.h> 00015 #include <klocale.h> 00016 00017 #define XK_MISCELLANY 00018 #define XK_XKB_KEYS 00019 #include <X11/X.h> 00020 #include <X11/Xlib.h> 00021 #include <X11/Xutil.h> 00022 #include <X11/keysymdef.h> 00023 00024 namespace KKeyServer 00025 { 00026 00027 //--------------------------------------------------------------------- 00028 // Data Structures 00029 //--------------------------------------------------------------------- 00030 00031 struct Mod 00032 { 00033 int m_mod; 00034 }; 00035 00036 //--------------------------------------------------------------------- 00037 // Array Structures 00038 //--------------------------------------------------------------------- 00039 00040 struct ModInfo 00041 { 00042 KKey::ModFlag mod; 00043 int modQt; 00044 uint modX; 00045 const char* psName; 00046 QString sLabel; 00047 }; 00048 00049 struct SymVariation 00050 { 00051 uint sym, symVariation; 00052 bool bActive; 00053 }; 00054 00055 struct SymName 00056 { 00057 uint sym; 00058 const char* psName; 00059 }; 00060 00061 struct TransKey { 00062 int keySymQt; 00063 uint keySymX; 00064 }; 00065 00066 //--------------------------------------------------------------------- 00067 // Arrays 00068 //--------------------------------------------------------------------- 00069 00070 static ModInfo g_rgModInfo[KKey::MOD_FLAG_COUNT] = 00071 { 00072 { KKey::SHIFT, Qt::SHIFT, ShiftMask, I18N_NOOP("Shift"), QString() }, 00073 { KKey::CTRL, Qt::CTRL, ControlMask, I18N_NOOP("Ctrl"), QString() }, 00074 { KKey::ALT, Qt::ALT, Mod1Mask, I18N_NOOP("Alt"), QString() }, 00075 { KKey::WIN, KKey::QtWIN, Mod4Mask, I18N_NOOP("Win"), QString() } 00076 }; 00077 00078 static SymVariation g_rgSymVariation[] = 00079 { 00080 { '/', XK_KP_Divide, false }, 00081 { '*', XK_KP_Multiply, false }, 00082 { '-', XK_KP_Subtract, false }, 00083 { '+', XK_KP_Add, false }, 00084 { XK_Return, XK_KP_Enter, false }, 00085 { 0, 0, false } 00086 }; 00087 00088 // Special Names List 00089 static const SymName g_rgSymNames[] = { 00090 { XK_ISO_Left_Tab, "Backtab" }, 00091 { XK_BackSpace, I18N_NOOP("Backspace") }, 00092 { XK_Sys_Req, I18N_NOOP("SysReq") }, 00093 { XK_Caps_Lock, I18N_NOOP("CapsLock") }, 00094 { XK_Num_Lock, I18N_NOOP("NumLock") }, 00095 { XK_Scroll_Lock, I18N_NOOP("ScrollLock") }, 00096 { XK_Prior, I18N_NOOP("PageUp") }, 00097 { XK_Next, I18N_NOOP("PageDown") }, 00098 #ifdef sun 00099 { XK_F11, I18N_NOOP("Stop") }, 00100 { XK_F12, I18N_NOOP("Again") }, 00101 { XK_F13, I18N_NOOP("Props") }, 00102 { XK_F14, I18N_NOOP("Undo") }, 00103 { XK_F15, I18N_NOOP("Front") }, 00104 { XK_F16, I18N_NOOP("Copy") }, 00105 { XK_F17, I18N_NOOP("Open") }, 00106 { XK_F18, I18N_NOOP("Paste") }, 00107 { XK_F19, I18N_NOOP("Find") }, 00108 { XK_F20, I18N_NOOP("Cut") }, 00109 { XK_F22, I18N_NOOP("Print") }, 00110 #endif 00111 { 0, 0 } 00112 }; 00113 00114 // TODO: Add Mac key names list: Key_Backspace => "Delete", Key_Delete => "Del" 00115 00116 // These are the X equivalents to the Qt keycodes 0x1000 - 0x1026 00117 static const TransKey g_rgQtToSymX[] = 00118 { 00119 { Qt::Key_Escape, XK_Escape }, 00120 { Qt::Key_Tab, XK_Tab }, 00121 { Qt::Key_Backtab, XK_ISO_Left_Tab }, 00122 { Qt::Key_Backspace, XK_BackSpace }, 00123 { Qt::Key_Return, XK_Return }, 00124 { Qt::Key_Enter, XK_KP_Enter }, 00125 { Qt::Key_Insert, XK_Insert }, 00126 { Qt::Key_Delete, XK_Delete }, 00127 { Qt::Key_Pause, XK_Pause }, 00128 #ifdef sun 00129 { Qt::Key_Print, XK_F22 }, 00130 #else 00131 { Qt::Key_Print, XK_Print }, 00132 #endif 00133 { Qt::Key_SysReq, XK_Sys_Req }, 00134 { Qt::Key_Home, XK_Home }, 00135 { Qt::Key_End, XK_End }, 00136 { Qt::Key_Left, XK_Left }, 00137 { Qt::Key_Up, XK_Up }, 00138 { Qt::Key_Right, XK_Right }, 00139 { Qt::Key_Down, XK_Down }, 00140 { Qt::Key_Prior, XK_Prior }, 00141 { Qt::Key_Next, XK_Next }, 00142 //{ Qt::Key_Shift, 0 }, 00143 //{ Qt::Key_Control, 0 }, 00144 //{ Qt::Key_Meta, 0 }, 00145 //{ Qt::Key_Alt, 0 }, 00146 { Qt::Key_CapsLock, XK_Caps_Lock }, 00147 { Qt::Key_NumLock, XK_Num_Lock }, 00148 { Qt::Key_ScrollLock, XK_Scroll_Lock }, 00149 { Qt::Key_F1, XK_F1 }, 00150 { Qt::Key_F2, XK_F2 }, 00151 { Qt::Key_F3, XK_F3 }, 00152 { Qt::Key_F4, XK_F4 }, 00153 { Qt::Key_F5, XK_F5 }, 00154 { Qt::Key_F6, XK_F6 }, 00155 { Qt::Key_F7, XK_F7 }, 00156 { Qt::Key_F8, XK_F8 }, 00157 { Qt::Key_F9, XK_F9 }, 00158 { Qt::Key_F10, XK_F10 }, 00159 { Qt::Key_F11, XK_F11 }, 00160 { Qt::Key_F12, XK_F12 }, 00161 { Qt::Key_F13, XK_F13 }, 00162 { Qt::Key_F14, XK_F14 }, 00163 { Qt::Key_F15, XK_F15 }, 00164 { Qt::Key_F16, XK_F16 }, 00165 { Qt::Key_F17, XK_F17 }, 00166 { Qt::Key_F18, XK_F18 }, 00167 { Qt::Key_F19, XK_F19 }, 00168 { Qt::Key_F20, XK_F20 }, 00169 { Qt::Key_F21, XK_F21 }, 00170 { Qt::Key_F22, XK_F22 }, 00171 { Qt::Key_F23, XK_F23 }, 00172 { Qt::Key_F24, XK_F24 }, 00173 { Qt::Key_F25, XK_F25 }, 00174 { Qt::Key_F26, XK_F26 }, 00175 { Qt::Key_F27, XK_F27 }, 00176 { Qt::Key_F28, XK_F28 }, 00177 { Qt::Key_F29, XK_F29 }, 00178 { Qt::Key_F30, XK_F30 }, 00179 { Qt::Key_F31, XK_F31 }, 00180 { Qt::Key_F32, XK_F32 }, 00181 { Qt::Key_F33, XK_F33 }, 00182 { Qt::Key_F34, XK_F34 }, 00183 { Qt::Key_F35, XK_F35 }, 00184 { Qt::Key_Super_L, XK_Super_L }, 00185 { Qt::Key_Super_R, XK_Super_R }, 00186 { Qt::Key_Menu, XK_Menu }, 00187 { Qt::Key_Hyper_L, XK_Hyper_L }, 00188 { Qt::Key_Hyper_R, XK_Hyper_R }, 00189 { Qt::Key_Help, XK_Help }, 00190 //{ Qt::Key_Direction_L, XK_Direction_L }, These keys don't exist in X11 00191 //{ Qt::Key_Direction_R, XK_Direction_R }, 00192 00193 { '/', XK_KP_Divide }, 00194 { '*', XK_KP_Multiply }, 00195 { '-', XK_KP_Subtract }, 00196 { '+', XK_KP_Add }, 00197 { Qt::Key_Return, XK_KP_Enter } 00198 #if QT_VERSION >= 0x030100 00199 00200 // the next lines are taken from XFree > 4.0 (X11/XF86keysyms.h), defining some special 00201 // multimedia keys. They are included here as not every system has them. 00202 #define XF86XK_Standby 0x1008FF10 00203 #define XF86XK_AudioLowerVolume 0x1008FF11 00204 #define XF86XK_AudioMute 0x1008FF12 00205 #define XF86XK_AudioRaiseVolume 0x1008FF13 00206 #define XF86XK_AudioPlay 0x1008FF14 00207 #define XF86XK_AudioStop 0x1008FF15 00208 #define XF86XK_AudioPrev 0x1008FF16 00209 #define XF86XK_AudioNext 0x1008FF17 00210 #define XF86XK_HomePage 0x1008FF18 00211 #define XF86XK_Calculator 0x1008FF1D 00212 #define XF86XK_Mail 0x1008FF19 00213 #define XF86XK_Start 0x1008FF1A 00214 #define XF86XK_Search 0x1008FF1B 00215 #define XF86XK_AudioRecord 0x1008FF1C 00216 #define XF86XK_Back 0x1008FF26 00217 #define XF86XK_Forward 0x1008FF27 00218 #define XF86XK_Stop 0x1008FF28 00219 #define XF86XK_Refresh 0x1008FF29 00220 #define XF86XK_Favorites 0x1008FF30 00221 #define XF86XK_AudioPause 0x1008FF31 00222 #define XF86XK_AudioMedia 0x1008FF32 00223 #define XF86XK_MyComputer 0x1008FF33 00224 #define XF86XK_OpenURL 0x1008FF38 00225 #define XF86XK_Launch0 0x1008FF40 00226 #define XF86XK_Launch1 0x1008FF41 00227 #define XF86XK_Launch2 0x1008FF42 00228 #define XF86XK_Launch3 0x1008FF43 00229 #define XF86XK_Launch4 0x1008FF44 00230 #define XF86XK_Launch5 0x1008FF45 00231 #define XF86XK_Launch6 0x1008FF46 00232 #define XF86XK_Launch7 0x1008FF47 00233 #define XF86XK_Launch8 0x1008FF48 00234 #define XF86XK_Launch9 0x1008FF49 00235 #define XF86XK_LaunchA 0x1008FF4A 00236 #define XF86XK_LaunchB 0x1008FF4B 00237 #define XF86XK_LaunchC 0x1008FF4C 00238 #define XF86XK_LaunchD 0x1008FF4D 00239 #define XF86XK_LaunchE 0x1008FF4E 00240 #define XF86XK_LaunchF 0x1008FF4F 00241 // end of XF86keysyms.h 00242 , 00243 { Qt::Key_Standby, XF86XK_Standby }, 00244 { Qt::Key_VolumeDown, XF86XK_AudioLowerVolume }, 00245 { Qt::Key_VolumeMute, XF86XK_AudioMute }, 00246 { Qt::Key_VolumeUp, XF86XK_AudioRaiseVolume }, 00247 { Qt::Key_MediaPlay, XF86XK_AudioPlay }, 00248 { Qt::Key_MediaStop, XF86XK_AudioStop }, 00249 { Qt::Key_MediaPrev, XF86XK_AudioPrev }, 00250 { Qt::Key_MediaNext, XF86XK_AudioNext }, 00251 { Qt::Key_HomePage, XF86XK_HomePage }, 00252 { Qt::Key_LaunchMail, XF86XK_Mail }, 00253 { Qt::Key_Search, XF86XK_Search }, 00254 { Qt::Key_MediaRecord, XF86XK_AudioRecord }, 00255 { Qt::Key_LaunchMedia, XF86XK_AudioMedia }, 00256 { Qt::Key_Launch1, XF86XK_Calculator }, 00257 { Qt::Key_Back, XF86XK_Back }, 00258 { Qt::Key_Forward, XF86XK_Forward }, 00259 { Qt::Key_Stop, XF86XK_Stop }, 00260 { Qt::Key_Refresh, XF86XK_Refresh }, 00261 { Qt::Key_Favorites, XF86XK_Favorites }, 00262 { Qt::Key_Launch0, XF86XK_MyComputer }, 00263 { Qt::Key_OpenUrl, XF86XK_OpenURL }, 00264 { Qt::Key_Launch2, XF86XK_Launch0 }, 00265 { Qt::Key_Launch3, XF86XK_Launch1 }, 00266 { Qt::Key_Launch4, XF86XK_Launch2 }, 00267 { Qt::Key_Launch5, XF86XK_Launch3 }, 00268 { Qt::Key_Launch6, XF86XK_Launch4 }, 00269 { Qt::Key_Launch7, XF86XK_Launch5 }, 00270 { Qt::Key_Launch8, XF86XK_Launch6 }, 00271 { Qt::Key_Launch9, XF86XK_Launch7 }, 00272 { Qt::Key_LaunchA, XF86XK_Launch8 }, 00273 { Qt::Key_LaunchB, XF86XK_Launch9 }, 00274 { Qt::Key_LaunchC, XF86XK_LaunchA }, 00275 { Qt::Key_LaunchD, XF86XK_LaunchB }, 00276 { Qt::Key_LaunchE, XF86XK_LaunchC }, 00277 { Qt::Key_LaunchF, XF86XK_LaunchD }, 00278 #endif 00279 }; 00280 00281 //--------------------------------------------------------------------- 00282 // Initialization 00283 //--------------------------------------------------------------------- 00284 static bool g_bInitializedMods, g_bInitializedVariations, g_bInitializedKKeyLabels; 00285 static bool g_bMacLabels; 00286 static uint g_modXNumLock, g_modXScrollLock; 00287 00288 bool initializeMods() 00289 { 00290 XModifierKeymap* xmk = XGetModifierMapping( qt_xdisplay() ); 00291 00292 g_rgModInfo[3].modX = g_modXNumLock = g_modXScrollLock = 0; 00293 00294 int min_keycode, max_keycode; 00295 int keysyms_per_keycode = 0; 00296 XDisplayKeycodes( qt_xdisplay(), &min_keycode, &max_keycode ); 00297 XFree( XGetKeyboardMapping( qt_xdisplay(), min_keycode, 1, &keysyms_per_keycode )); 00298 // Qt assumes that Alt is always Mod1Mask, so start at Mod2Mask. 00299 for( int i = Mod2MapIndex; i < 8; i++ ) { 00300 uint mask = (1 << i); 00301 uint keySymX = NoSymbol; 00302 // This used to be only XKeycodeToKeysym( ... , 0 ), but that fails with XFree4.3.99 00303 // and X.org R6.7 , where for some reason only ( ... , 1 ) works. I have absolutely no 00304 // idea what the problem is, but searching all posibilities until something valid is 00305 // found fixes the problem. 00306 for( int j = 0; j < xmk->max_keypermod && keySymX == NoSymbol; ++j ) 00307 for( int k = 0; k < keysyms_per_keycode && keySymX == NoSymbol; ++k ) 00308 keySymX = XKeycodeToKeysym( qt_xdisplay(), xmk->modifiermap[xmk->max_keypermod * i + j], k ); 00309 switch( keySymX ) { 00310 case XK_Num_Lock: g_modXNumLock = mask; break; // Normally Mod2Mask 00311 case XK_Super_L: 00312 case XK_Super_R: g_rgModInfo[3].modX = mask; break; // Win key, Normally Mod4Mask 00313 case XK_Meta_L: 00314 case XK_Meta_R: if( !g_rgModInfo[3].modX ) g_rgModInfo[3].modX = mask; break; // Win alternate 00315 case XK_Scroll_Lock: g_modXScrollLock = mask; break; // Normally Mod5Mask 00316 } 00317 } 00318 00319 XFreeModifiermap( xmk ); 00320 00321 //KConfigGroupSaver cgs( KGlobal::config(), "Keyboard" ); 00322 // read in mod that win should be attached to 00323 00324 g_bInitializedMods = true; 00325 00326 kdDebug(125) << "KKeyServer::initializeMods(): Win Mod = 0x" << QString::number(g_rgModInfo[3].modX, 16) << endl; 00327 return true; 00328 } 00329 00330 static void initializeVariations() 00331 { 00332 for( int i = 0; g_rgSymVariation[i].sym != 0; i++ ) 00333 g_rgSymVariation[i].bActive = (XKeysymToKeycode( qt_xdisplay(), g_rgSymVariation[i].symVariation ) != 0); 00334 g_bInitializedVariations = true; 00335 } 00336 00337 static void intializeKKeyLabels() 00338 { 00339 KConfigGroupSaver cgs( KGlobal::config(), "Keyboard" ); 00340 g_rgModInfo[0].sLabel = KGlobal::config()->readEntry( "Label Shift", i18n(g_rgModInfo[0].psName) ); 00341 g_rgModInfo[1].sLabel = KGlobal::config()->readEntry( "Label Ctrl", i18n(g_rgModInfo[1].psName) ); 00342 g_rgModInfo[2].sLabel = KGlobal::config()->readEntry( "Label Alt", i18n(g_rgModInfo[2].psName) ); 00343 g_rgModInfo[3].sLabel = KGlobal::config()->readEntry( "Label Win", i18n(g_rgModInfo[3].psName) ); 00344 g_bMacLabels = (g_rgModInfo[2].sLabel == "Command"); 00345 g_bInitializedKKeyLabels = true; 00346 } 00347 00348 //--------------------------------------------------------------------- 00349 // class Mod 00350 //--------------------------------------------------------------------- 00351 00352 /*void Mod::init( const QString& s ) 00353 { 00354 00355 }*/ 00356 00357 //--------------------------------------------------------------------- 00358 // class Sym 00359 //--------------------------------------------------------------------- 00360 00361 bool Sym::initQt( int keyQt ) 00362 { 00363 int symQt = keyQt & 0xffff; 00364 00365 if( (keyQt & Qt::UNICODE_ACCEL) || symQt < 0x1000 ) { 00366 m_sym = QChar(symQt).lower().unicode(); 00367 return true; 00368 } 00369 00370 for( uint i = 0; i < sizeof(g_rgQtToSymX)/sizeof(TransKey); i++ ) { 00371 if( g_rgQtToSymX[i].keySymQt == symQt ) { 00372 m_sym = g_rgQtToSymX[i].keySymX; 00373 return true; 00374 } 00375 } 00376 00377 m_sym = 0; 00378 if( symQt != Qt::Key_Shift && symQt != Qt::Key_Control && symQt != Qt::Key_Alt && 00379 symQt != Qt::Key_Meta && symQt != Qt::Key_Direction_L && symQt != Qt::Key_Direction_R ) 00380 kdDebug(125) << "Sym::initQt( " << QString::number(keyQt,16) << " ): failed to convert key." << endl; 00381 return false; 00382 } 00383 00384 bool Sym::init( const QString& s ) 00385 { 00386 // If it's a single character, get unicode value. 00387 if( s.length() == 1 ) { 00388 m_sym = s[0].lower().unicode(); 00389 return true; 00390 } 00391 00392 // Look up in special names list 00393 for( int i = 0; g_rgSymNames[i].sym != 0; i++ ) { 00394 if( qstricmp( s.latin1(), g_rgSymNames[i].psName ) == 0 ) { 00395 m_sym = g_rgSymNames[i].sym; 00396 return true; 00397 } 00398 } 00399 00400 // search X list: 's' as is, all lower, first letter in caps 00401 m_sym = XStringToKeysym( s.latin1() ); 00402 if( !m_sym ) { 00403 m_sym = XStringToKeysym( s.lower().latin1() ); 00404 if( !m_sym ) { 00405 QString s2 = s; 00406 s2[0] = s2[0].upper(); 00407 m_sym = XStringToKeysym( s2.latin1() ); 00408 } 00409 } 00410 00411 return m_sym != 0; 00412 } 00413 00414 int Sym::qt() const 00415 { 00416 if( m_sym < 0x1000 ) { 00417 if( m_sym >= 'a' && m_sym <= 'z' ) 00418 return QChar(m_sym).upper(); 00419 return m_sym; 00420 } 00421 if( m_sym < 0x3000 ) 00422 return m_sym | Qt::UNICODE_ACCEL; 00423 00424 for( uint i = 0; i < sizeof(g_rgQtToSymX)/sizeof(TransKey); i++ ) 00425 if( g_rgQtToSymX[i].keySymX == m_sym ) 00426 return g_rgQtToSymX[i].keySymQt; 00427 return Qt::Key_unknown; 00428 } 00429 00430 QString Sym::toString( bool bUserSpace ) const 00431 { 00432 if( m_sym == 0 ) 00433 return QString::null; 00434 00435 // If it's a unicode character, 00436 else if( m_sym < 0x3000 ) { 00437 QChar c = QChar(m_sym).upper(); 00438 // Print all non-space characters directly when output is user-visible. 00439 // Otherwise only print alphanumeric latin1 characters directly (A,B,C,1,2,3). 00440 if( (c.latin1() && c.isLetterOrNumber()) 00441 || (bUserSpace && !c.isSpace()) ) 00442 return c; 00443 } 00444 00445 // Look up in special names list 00446 for( int i = 0; g_rgSymNames[i].sym != 0; i++ ) { 00447 if( m_sym == g_rgSymNames[i].sym ) 00448 return bUserSpace ? i18n(g_rgSymNames[i].psName) : QString(g_rgSymNames[i].psName); 00449 } 00450 00451 // Get X-name 00452 QString s = XKeysymToString( m_sym ); 00453 capitalizeKeyname( s ); 00454 return bUserSpace ? i18n("QAccel", s.latin1()) : s; 00455 } 00456 00457 QString Sym::toStringInternal() const { return toString( false ); } 00458 QString Sym::toString() const { return toString( true ); } 00459 00460 uint Sym::getModsRequired() const 00461 { 00462 uint mod = 0; 00463 00464 // FIXME: This might not be true on all keyboard layouts! 00465 if( m_sym == XK_Sys_Req ) return KKey::ALT; 00466 if( m_sym == XK_Break ) return KKey::CTRL; 00467 00468 if( m_sym < 0x3000 ) { 00469 QChar c(m_sym); 00470 if( c.isLetter() && c.lower() != c.upper() && m_sym == c.upper().unicode() ) 00471 return KKey::SHIFT; 00472 } 00473 00474 uchar code = XKeysymToKeycode( qt_xdisplay(), m_sym ); 00475 if( code ) { 00476 // need to check index 0 before the others, so that a null-mod 00477 // can take precedence over the others, in case the modified 00478 // key produces the same symbol. 00479 if( m_sym == XKeycodeToKeysym( qt_xdisplay(), code, 0 ) ) 00480 ; 00481 else if( m_sym == XKeycodeToKeysym( qt_xdisplay(), code, 1 ) ) 00482 mod = KKey::SHIFT; 00483 else if( m_sym == XKeycodeToKeysym( qt_xdisplay(), code, 2 ) ) 00484 mod = KKeyServer::MODE_SWITCH; 00485 else if( m_sym == XKeycodeToKeysym( qt_xdisplay(), code, 3 ) ) 00486 mod = KKey::SHIFT | KKeyServer::MODE_SWITCH; 00487 } 00488 00489 return mod; 00490 } 00491 00492 uint Sym::getSymVariation() const 00493 { 00494 if( !g_bInitializedVariations ) 00495 initializeVariations(); 00496 00497 for( int i = 0; g_rgSymVariation[i].sym != 0; i++ ) 00498 if( g_rgSymVariation[i].sym == m_sym && g_rgSymVariation[i].bActive ) 00499 return g_rgSymVariation[i].symVariation; 00500 return 0; 00501 } 00502 00503 void Sym::capitalizeKeyname( QString& s ) 00504 { 00505 s[0] = s[0].upper(); 00506 int len = s.length(); 00507 if( s.endsWith( "left" ) ) s[len-4] = 'L'; 00508 else if( s.endsWith( "right" ) ) s[len-5] = 'R'; 00509 else if( s == "Sysreq" ) s[len-3] = 'R'; 00510 } 00511 00512 //--------------------------------------------------------------------- 00513 // Public functions 00514 //--------------------------------------------------------------------- 00515 00516 uint modX( KKey::ModFlag mod ) 00517 { 00518 if( mod == KKey::WIN && !g_bInitializedMods ) 00519 initializeMods(); 00520 00521 for( uint i = 0; i < KKey::MOD_FLAG_COUNT; i++ ) { 00522 if( g_rgModInfo[i].mod == mod ) 00523 return g_rgModInfo[i].modX; 00524 } 00525 return 0; 00526 } 00527 00528 bool keyboardHasWinKey() { if( !g_bInitializedMods ) { initializeMods(); } return g_rgModInfo[3].modX != 0; } 00529 uint modXShift() { return ShiftMask; } 00530 uint modXLock() { return LockMask; } 00531 uint modXCtrl() { return ControlMask; } 00532 uint modXAlt() { return Mod1Mask; } 00533 uint modXNumLock() { if( !g_bInitializedMods ) { initializeMods(); } return g_modXNumLock; } 00534 uint modXWin() { if( !g_bInitializedMods ) { initializeMods(); } return g_rgModInfo[3].modX; } 00535 uint modXScrollLock() { if( !g_bInitializedMods ) { initializeMods(); } return g_modXScrollLock; } 00536 00537 uint accelModMaskX() 00538 { 00539 if( !g_bInitializedMods ) 00540 initializeMods(); 00541 return ShiftMask | ControlMask | Mod1Mask | g_rgModInfo[3].modX; 00542 } 00543 00544 bool keyQtToSym( int keyQt, uint& keySym ) 00545 { 00546 Sym sym; 00547 if( sym.initQt( keyQt ) ) { 00548 keySym = sym.m_sym; 00549 return true; 00550 } else 00551 return false; 00552 } 00553 00554 bool keyQtToMod( int keyQt, uint& mod ) 00555 { 00556 mod = 0; 00557 00558 if( keyQt & Qt::SHIFT ) mod |= KKey::SHIFT; 00559 if( keyQt & Qt::CTRL ) mod |= KKey::CTRL; 00560 if( keyQt & Qt::ALT ) mod |= KKey::ALT; 00561 if( keyQt & Qt::META ) mod |= KKey::WIN; 00562 00563 return true; 00564 } 00565 00566 bool symToKeyQt( uint keySym, int& keyQt ) 00567 { 00568 Sym sym( keySym ); 00569 keyQt = sym.qt(); 00570 return (keyQt != Qt::Key_unknown); 00571 } 00572 00573 bool modToModQt( uint mod, int& modQt ) 00574 { 00575 modQt = 0; 00576 for( int i = 0; i < KKey::MOD_FLAG_COUNT; i++ ) { 00577 if( mod & g_rgModInfo[i].mod ) { 00578 if( !g_rgModInfo[i].modQt ) { 00579 modQt = 0; 00580 return false; 00581 } 00582 modQt |= g_rgModInfo[i].modQt; 00583 } 00584 } 00585 return true; 00586 } 00587 00588 bool modToModX( uint mod, uint& modX ) 00589 { 00590 if( !g_bInitializedMods ) 00591 initializeMods(); 00592 00593 modX = 0; 00594 for( int i = 0; i < KKey::MOD_FLAG_COUNT; i++ ) { 00595 if( mod & g_rgModInfo[i].mod ) { 00596 if( !g_rgModInfo[i].modX ) { 00597 kdDebug(125) << "Invalid modifier flag." << endl; 00598 modX = 0; 00599 return false; 00600 } 00601 modX |= g_rgModInfo[i].modX; 00602 } 00603 } 00604 // TODO: document 0x2000 flag 00605 if( mod & 0x2000 ) 00606 modX |= 0x2000; 00607 return true; 00608 } 00609 00610 bool modXToModQt( uint modX, int& modQt ) 00611 { 00612 if( !g_bInitializedMods ) 00613 initializeMods(); 00614 00615 modQt = 0; 00616 for( int i = 0; i < KKey::MOD_FLAG_COUNT; i++ ) { 00617 if( modX & g_rgModInfo[i].modX ) { 00618 if( !g_rgModInfo[i].modQt ) { 00619 modQt = 0; 00620 return false; 00621 } 00622 modQt |= g_rgModInfo[i].modQt; 00623 } 00624 } 00625 return true; 00626 } 00627 00628 bool modXToMod( uint modX, uint& mod ) 00629 { 00630 if( !g_bInitializedMods ) 00631 initializeMods(); 00632 00633 mod = 0; 00634 for( int i = 0; i < KKey::MOD_FLAG_COUNT; i++ ) { 00635 if( modX & g_rgModInfo[i].modX ) 00636 mod |= g_rgModInfo[i].mod; 00637 } 00638 return true; 00639 } 00640 00641 bool codeXToSym( uchar codeX, uint modX, uint& sym ) 00642 { 00643 XKeyPressedEvent event; 00644 00645 event.type = KeyPress; 00646 event.display = qt_xdisplay(); 00647 event.state = modX; 00648 event.keycode = codeX; 00649 00650 XLookupString( &event, 0, 0, (KeySym*) &sym, 0 ); 00651 return true; 00652 } 00653 00654 static QString modToString( uint mod, bool bUserSpace ) 00655 { 00656 if( bUserSpace && !g_bInitializedKKeyLabels ) 00657 intializeKKeyLabels(); 00658 00659 QString s; 00660 for( int i = KKey::MOD_FLAG_COUNT-1; i >= 0; i-- ) { 00661 if( mod & g_rgModInfo[i].mod ) { 00662 if( !s.isEmpty() ) 00663 s += '+'; 00664 s += (bUserSpace) 00665 ? g_rgModInfo[i].sLabel 00666 : QString(g_rgModInfo[i].psName); 00667 } 00668 } 00669 return s; 00670 } 00671 00672 QString modToStringInternal( uint mod ) { return modToString( mod, false ); } 00673 QString modToStringUser( uint mod ) { return modToString( mod, true ); } 00674 00675 /*void keySymModToKeyX( uint sym, uint mod, unsigned char *pKeyCodeX, uint *pKeySymX, uint *pKeyModX ) 00676 { 00677 ... 00678 uint keySymQt; 00679 uint keySymX = 0; 00680 unsigned char keyCodeX = 0; 00681 uint keyModX = 0; 00682 00683 const char *psKeySym = 0; 00684 00685 if( !g_bInitialized ) 00686 Initialize(); 00687 00688 // Get code of just the primary key 00689 keySymQt = keyCombQt & 0xffff; 00690 00691 // If unicode value beneath 0x1000 (special Qt codes begin thereafter), 00692 if( keySymQt < 0x1000 ) { 00693 // For reasons unbeknownst to me, Qt converts 'a-z' to 'A-Z'. 00694 // So convert it back to lowercase if SHIFT isn't held down. 00695 if( keySymQt >= Qt::Key_A && keySymQt <= Qt::Key_Z && !(keyCombQt & Qt::SHIFT) ) 00696 keySymQt = tolower( keySymQt ); 00697 keySymX = keySymQt; 00698 } 00699 // Else, special key (e.g. Delete, F1, etc.) 00700 else { 00701 for( int i = 0; i < NB_KEYS; i++ ) { 00702 if( keySymQt == (uint) KKEYS[i].code ) { 00703 psKeySym = KKEYS[i].name; 00704 //kdDebug(125) << " symbol found: \"" << psKeySym << "\"" << endl; 00705 break; 00706 } 00707 } 00708 00709 // Get X key symbol. Only works if Qt name is same as X name. 00710 if( psKeySym ) { 00711 QString sKeySym = psKeySym; 00712 00713 // Check for lower-case equalent first because most 00714 // X11 names are all lower-case. 00715 keySymX = XStringToKeysym( sKeySym.lower().ascii() ); 00716 if( keySymX == 0 ) 00717 keySymX = XStringToKeysym( psKeySym ); 00718 } 00719 00720 if( keySymX == 0 ) 00721 keySymX = getSymXEquiv( keySymQt ); 00722 } 00723 00724 if( keySymX != 0 ) { 00725 // Get X keyboard code 00726 keyCodeX = XKeysymToKeycode( qt_xdisplay(), keySymX ); 00727 // Add ModeSwitch modifier bit, if necessary 00728 keySymXMods( keySymX, 0, &keyModX ); 00729 00730 // Get X modifier flags 00731 for( int i = 0; i < MOD_KEYS; i++ ) { 00732 if( keyCombQt & g_aModKeys[i].keyModMaskQt ) { 00733 if( g_aModKeys[i].keyModMaskX ) 00734 keyModX |= g_aModKeys[i].keyModMaskX; 00735 // Qt key calls for a modifier which the current 00736 // X modifier map doesn't support. 00737 else { 00738 keySymX = 0; 00739 keyCodeX = 0; 00740 keyModX = 0; 00741 break; 00742 } 00743 } 00744 } 00745 } 00746 00747 // Take care of complications: 00748 // The following keys will not have been correctly interpreted, 00749 // because their shifted values are not activated with the 00750 // Shift key, but rather something else. They are also 00751 // defined twice under different keycodes. 00752 // keycode 111 & 92: Print Sys_Req -> Sys_Req = Alt+Print 00753 // keycode 110 & 114: Pause Break -> Break = Ctrl+Pause 00754 if( (keyCodeX == 92 || keyCodeX == 111) && 00755 XKeycodeToKeysym( qt_xdisplay(), 92, 0 ) == XK_Print && 00756 XKeycodeToKeysym( qt_xdisplay(), 111, 0 ) == XK_Print ) 00757 { 00758 // If Alt is pressed, then we need keycode 92, keysym XK_Sys_Req 00759 if( keyModX & keyModXAlt() ) { 00760 keyCodeX = 92; 00761 keySymX = XK_Sys_Req; 00762 } 00763 // Otherwise, keycode 111, keysym XK_Print 00764 else { 00765 keyCodeX = 111; 00766 keySymX = XK_Print; 00767 } 00768 } 00769 else if( (keyCodeX == 110 || keyCodeX == 114) && 00770 XKeycodeToKeysym( qt_xdisplay(), 110, 0 ) == XK_Pause && 00771 XKeycodeToKeysym( qt_xdisplay(), 114, 0 ) == XK_Pause ) 00772 { 00773 if( keyModX & keyModXCtrl() ) { 00774 keyCodeX = 114; 00775 keySymX = XK_Break; 00776 } else { 00777 keyCodeX = 110; 00778 keySymX = XK_Pause; 00779 } 00780 } 00781 00782 if( pKeySymX ) *pKeySymX = keySymX; 00783 if( pKeyCodeX ) *pKeyCodeX = keyCodeX; 00784 if( pKeyModX ) *pKeyModX = keyModX; 00785 }*/ 00786 00787 //--------------------------------------------------------------------- 00788 // Key 00789 //--------------------------------------------------------------------- 00790 00791 bool Key::init( const KKey& key, bool bQt ) 00792 { 00793 if( bQt ) { 00794 m_code = CODE_FOR_QT; 00795 m_sym = key.keyCodeQt(); 00796 } else { 00797 KKeyNative keyNative( key ); 00798 *this = keyNative; 00799 } 00800 return true; 00801 } 00802 00803 KKey Key::key() const 00804 { 00805 if( m_code == CODE_FOR_QT ) 00806 return KKey( keyCodeQt() ); 00807 else { 00808 uint mod; 00809 modXToMod( m_mod, mod ); 00810 return KKey( m_sym, mod ); 00811 } 00812 } 00813 00814 Key& Key::operator =( const KKeyNative& key ) 00815 { 00816 m_code = key.code(); m_mod = key.mod(); m_sym = key.sym(); 00817 return *this; 00818 } 00819 00820 int Key::compare( const Key& b ) const 00821 { 00822 if( m_code == CODE_FOR_QT ) 00823 return m_sym - b.m_sym; 00824 if( m_sym != b.m_sym ) return m_sym - b.m_sym; 00825 if( m_mod != b.m_mod ) return m_mod - b.m_mod; 00826 return m_code - b.m_code; 00827 } 00828 00829 //--------------------------------------------------------------------- 00830 // Variations 00831 //--------------------------------------------------------------------- 00832 00833 // TODO: allow for sym to have variations, such as Plus => { Plus, KP_Add } 00834 void Variations::init( const KKey& key, bool bQt ) 00835 { 00836 if( key.isNull() ) { 00837 m_nVariations = 0; 00838 return; 00839 } 00840 00841 m_nVariations = 1; 00842 m_rgkey[0] = KKeyNative(key); 00843 uint symVar = Sym(key.sym()).getSymVariation(); 00844 if( symVar ) { 00845 uint modReq = Sym(m_rgkey[0].sym()).getModsRequired(); 00846 uint modReqVar = Sym(symVar).getModsRequired(); 00847 // If 'key' doesn't require any mods that are inherent in 00848 // the primary key but not required for the alternate, 00849 if( (key.modFlags() & modReq) == (key.modFlags() & modReqVar) ) { 00850 m_rgkey[1] = KKeyNative(KKey(symVar, key.modFlags())); 00851 m_nVariations = 2; 00852 } 00853 } 00854 00855 if( bQt ) { 00856 uint nVariations = 0; 00857 for( uint i = 0; i < m_nVariations; i++ ) { 00858 int keyQt = KKeyNative( m_rgkey[i].code(), m_rgkey[i].mod(), m_rgkey[i].sym() ).keyCodeQt(); 00859 if( keyQt ) 00860 m_rgkey[nVariations++].setKeycodeQt( keyQt ); 00861 } 00862 m_nVariations = nVariations; 00863 00864 // Two different native codes may produce a single 00865 // Qt code. Search for duplicates. 00866 for( uint i = 1; i < m_nVariations; i++ ) { 00867 for( uint j = 0; j < i; j++ ) { 00868 // If key is already present in list, then remove it. 00869 if( m_rgkey[i].keyCodeQt() == m_rgkey[j].keyCodeQt() ) { 00870 for( uint k = i; k < m_nVariations - 1; k++ ) 00871 m_rgkey[k].setKeycodeQt( m_rgkey[k+1].keyCodeQt() ); 00872 m_nVariations--; 00873 i--; 00874 break; 00875 } 00876 } 00877 } 00878 } 00879 } 00880 00881 } // end of namespace KKeyServer block 00882 00883 // FIXME: This needs to be moved to kshortcut.cpp, and create a 00884 // KKeyServer::method which it will call. 00885 // Alt+SysReq => Alt+Print 00886 // Ctrl+Shift+Plus => Ctrl+Plus (en) 00887 // Ctrl+Shift+Equal => Ctrl+Plus 00888 // Ctrl+Pause => Ctrl+Break 00889 void KKey::simplify() 00890 { 00891 if( m_sym == XK_Sys_Req ) { 00892 m_sym = XK_Print; 00893 m_mod |= ALT; 00894 } else if( m_sym == XK_ISO_Left_Tab ) { 00895 m_sym = XK_Tab; 00896 m_mod |= SHIFT; 00897 } else { 00898 // Shift+Equal => Shift+Plus (en) 00899 m_sym = KKeyNative(*this).sym(); 00900 } 00901 00902 // If this is a letter, don't remove any modifiers. 00903 if( m_sym < 0x3000 && QChar(m_sym).isLetter() ) 00904 m_sym = QChar(m_sym).lower().unicode(); 00905 00906 // Remove modifers from modifier list which are implicit in the symbol. 00907 // Ex. Shift+Plus => Plus (en) 00908 m_mod &= ~KKeyServer::Sym(m_sym).getModsRequired(); 00909 } 00910 00911 #endif // Q_WS_X11
KDE Logo
This file is part of the documentation for kdecore Library Version 3.2.3.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Mon Aug 30 22:53:31 2004 by doxygen 1.3.8 written by Dimitri van Heesch, © 1997-2003