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 
00029 
00030 
00031 struct Mod
00032 {
00033     int m_mod;
00034 };
00035 
00036 
00037 
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 
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 
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 
00115 
00116 
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     
00143     
00144     
00145     
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     
00191     
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 
00201 
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 
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 
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     
00295     for( int i = Mod2MapIndex; i < 8; i++ ) {
00296         uint mask = (1 << i);
00297         uint keySymX = XKeycodeToKeysym( qt_xdisplay(), xmk->modifiermap[xmk->max_keypermod * i], 0 );
00298         switch( keySymX ) {
00299             case XK_Num_Lock:    g_modXNumLock = mask; break;     
00300             case XK_Super_L:
00301             case XK_Super_R:     g_rgModInfo[3].modX = mask; break; 
00302             case XK_Meta_L:
00303             case XK_Meta_R:      if( !g_rgModInfo[3].modX ) g_rgModInfo[3].modX = mask; break; 
00304             case XK_Scroll_Lock: g_modXScrollLock = mask; break;  
00305         }
00306     }
00307 
00308     XFreeModifiermap( xmk );
00309 
00310     
00311     
00312 
00313     g_bInitializedMods = true;
00314 
00315     kdDebug(125) << "KKeyServer::initializeMods(): Win Mod = 0x" << QString::number(g_rgModInfo[3].modX, 16) << endl;
00316     return true;
00317 }
00318 
00319 static void initializeVariations()
00320 {
00321     for( int i = 0; g_rgSymVariation[i].sym != 0; i++ )
00322         g_rgSymVariation[i].bActive = (XKeysymToKeycode( qt_xdisplay(), g_rgSymVariation[i].symVariation ) != 0);
00323     g_bInitializedVariations = true;
00324 }
00325 
00326 static void intializeKKeyLabels()
00327 {
00328     KConfigGroupSaver cgs( KGlobal::config(), "Keyboard" );
00329     g_rgModInfo[0].sLabel = KGlobal::config()->readEntry( "Label Shift", i18n(g_rgModInfo[0].psName) );
00330     g_rgModInfo[1].sLabel = KGlobal::config()->readEntry( "Label Ctrl", i18n(g_rgModInfo[1].psName) );
00331     g_rgModInfo[2].sLabel = KGlobal::config()->readEntry( "Label Alt", i18n(g_rgModInfo[2].psName) );
00332     g_rgModInfo[3].sLabel = KGlobal::config()->readEntry( "Label Win", i18n(g_rgModInfo[3].psName) );
00333     g_bMacLabels = (g_rgModInfo[2].sLabel == "Command");
00334     g_bInitializedKKeyLabels = true;
00335 }
00336 
00337 
00338 
00339 
00340 
00341 
00342 
00343 
00344 
00345 
00346 
00347 
00348 
00349 
00350 bool Sym::initQt( int keyQt )
00351 {
00352     int symQt = keyQt & 0xffff;
00353 
00354     if( (keyQt & Qt::UNICODE_ACCEL) || symQt < 0x1000 ) {
00355         m_sym = QChar(symQt).lower().unicode();
00356         return true;
00357     }
00358 
00359     for( uint i = 0; i < sizeof(g_rgQtToSymX)/sizeof(TransKey); i++ ) {
00360         if( g_rgQtToSymX[i].keySymQt == symQt ) {
00361             m_sym = g_rgQtToSymX[i].keySymX;
00362             return true;
00363         }
00364     }
00365 
00366     m_sym = 0;
00367     if( symQt != Qt::Key_Shift && symQt != Qt::Key_Control && symQt != Qt::Key_Alt &&
00368         symQt != Qt::Key_Meta && symQt != Qt::Key_Direction_L && symQt != Qt::Key_Direction_R )
00369         kdDebug(125) << "Sym::initQt( " << QString::number(keyQt,16) << " ): failed to convert key." << endl;
00370     return false;
00371 }
00372 
00373 bool Sym::init( const QString& s )
00374 {
00375     
00376     if( s.length() == 1 ) {
00377         m_sym = s[0].lower().unicode();
00378         return true;
00379     }
00380 
00381     
00382     for( int i = 0; g_rgSymNames[i].sym != 0; i++ ) {
00383         if( qstricmp( s.latin1(), g_rgSymNames[i].psName ) == 0 ) {
00384             m_sym = g_rgSymNames[i].sym;
00385             return true;
00386         }
00387     }
00388 
00389     
00390     m_sym = XStringToKeysym( s.latin1() );
00391     if( !m_sym ) {
00392         m_sym = XStringToKeysym( s.lower().latin1() );
00393         if( !m_sym ) {
00394             QString s2 = s;
00395             s2[0] = s2[0].upper();
00396             m_sym = XStringToKeysym( s2.latin1() );
00397         }
00398     }
00399 
00400     return m_sym != 0;
00401 }
00402 
00403 int Sym::qt() const
00404 {
00405     if( m_sym < 0x1000 ) {
00406         if( m_sym >= 'a' && m_sym <= 'z' )
00407             return QChar(m_sym).upper();
00408         return m_sym;
00409     }
00410     if( m_sym < 0x3000 )
00411         return m_sym | Qt::UNICODE_ACCEL;
00412 
00413     for( uint i = 0; i < sizeof(g_rgQtToSymX)/sizeof(TransKey); i++ )
00414         if( g_rgQtToSymX[i].keySymX == m_sym )
00415             return g_rgQtToSymX[i].keySymQt;
00416     return Qt::Key_unknown;
00417 }
00418 
00419 QString Sym::toString( bool bUserSpace ) const
00420 {
00421     if( m_sym == 0 )
00422         return QString::null;
00423 
00424     
00425     else if( m_sym < 0x3000 ) {
00426         QChar c = QChar(m_sym).upper();
00427         
00428         
00429         if( (c.latin1() && c.isLetterOrNumber())
00430             || (bUserSpace && !c.isSpace()) )
00431                 return c;
00432     }
00433 
00434     
00435     for( int i = 0; g_rgSymNames[i].sym != 0; i++ ) {
00436         if( m_sym == g_rgSymNames[i].sym )
00437             return bUserSpace ? i18n(g_rgSymNames[i].psName) : QString(g_rgSymNames[i].psName);
00438     }
00439 
00440     
00441     QString s = XKeysymToString( m_sym );
00442     capitalizeKeyname( s );
00443     return bUserSpace ? i18n("QAccel", s.latin1()) : s;
00444 }
00445 
00446 QString Sym::toStringInternal() const { return toString( false ); }
00447 QString Sym::toString() const         { return toString( true ); }
00448 
00449 uint Sym::getModsRequired() const
00450 {
00451     uint mod = 0;
00452 
00453     
00454     if( m_sym == XK_Sys_Req ) return KKey::ALT;
00455     if( m_sym == XK_Break ) return KKey::CTRL;
00456 
00457     if( m_sym < 0x3000 ) {
00458         QChar c(m_sym);
00459         if( c.isLetter() && c.lower() != c.upper() && m_sym == c.upper().unicode() )
00460             return KKey::SHIFT;
00461     }
00462 
00463     uchar code = XKeysymToKeycode( qt_xdisplay(), m_sym );
00464     if( code ) {
00465         
00466         
00467         
00468         if( m_sym == XKeycodeToKeysym( qt_xdisplay(), code, 0 ) )
00469             ;
00470         else if( m_sym == XKeycodeToKeysym( qt_xdisplay(), code, 1 ) )
00471             mod = KKey::SHIFT;
00472         else if( m_sym == XKeycodeToKeysym( qt_xdisplay(), code, 2 ) )
00473             mod = KKeyServer::MODE_SWITCH;
00474         else if( m_sym == XKeycodeToKeysym( qt_xdisplay(), code, 3 ) )
00475             mod = KKey::SHIFT | KKeyServer::MODE_SWITCH;
00476     }
00477 
00478     return mod;
00479 }
00480 
00481 uint Sym::getSymVariation() const
00482 {
00483     if( !g_bInitializedVariations )
00484         initializeVariations();
00485 
00486     for( int i = 0; g_rgSymVariation[i].sym != 0; i++ )
00487         if( g_rgSymVariation[i].sym == m_sym && g_rgSymVariation[i].bActive )
00488             return g_rgSymVariation[i].symVariation;
00489     return 0;
00490 }
00491 
00492 void Sym::capitalizeKeyname( QString& s )
00493 {
00494     s[0] = s[0].upper();
00495     int len = s.length();
00496     if( s.endsWith( "left" ) )       s[len-4] = 'L';
00497     else if( s.endsWith( "right" ) ) s[len-5] = 'R';
00498     else if( s == "Sysreq" )         s[len-3] = 'R';
00499 }
00500 
00501 
00502 
00503 
00504 
00505 uint modX( KKey::ModFlag mod )
00506 {
00507     if( mod == KKey::WIN && !g_bInitializedMods )
00508         initializeMods();
00509 
00510     for( uint i = 0; i < KKey::MOD_FLAG_COUNT; i++ ) {
00511         if( g_rgModInfo[i].mod == mod )
00512             return g_rgModInfo[i].modX;
00513     }
00514     return 0;
00515 }
00516 
00517 bool keyboardHasWinKey() { if( !g_bInitializedMods ) { initializeMods(); } return g_rgModInfo[3].modX != 0; }
00518 uint modXShift()      { return ShiftMask; }
00519 uint modXLock()       { return LockMask; }
00520 uint modXCtrl()       { return ControlMask; }
00521 uint modXAlt()        { return Mod1Mask; }
00522 uint modXNumLock()    { if( !g_bInitializedMods ) { initializeMods(); } return g_modXNumLock; }
00523 uint modXWin()        { if( !g_bInitializedMods ) { initializeMods(); } return g_rgModInfo[3].modX; }
00524 uint modXScrollLock() { if( !g_bInitializedMods ) { initializeMods(); } return g_modXScrollLock; }
00525 
00526 uint accelModMaskX()
00527 {
00528     if( !g_bInitializedMods )
00529         initializeMods();
00530     return ShiftMask | ControlMask | Mod1Mask | g_rgModInfo[3].modX;
00531 }
00532 
00533 bool keyQtToSym( int keyQt, uint& keySym )
00534 {
00535     Sym sym;
00536     if( sym.initQt( keyQt ) ) {
00537         keySym = sym.m_sym;
00538         return true;
00539     } else
00540         return false;
00541 }
00542 
00543 bool keyQtToMod( int keyQt, uint& mod )
00544 {
00545     mod = 0;
00546 
00547     if( keyQt & Qt::SHIFT )    mod |= KKey::SHIFT;
00548     if( keyQt & Qt::CTRL )     mod |= KKey::CTRL;
00549     if( keyQt & Qt::ALT )      mod |= KKey::ALT;
00550     if( keyQt & Qt::META ) mod |= KKey::WIN;
00551 
00552     return true;
00553 }
00554 
00555 bool symToKeyQt( uint keySym, int& keyQt )
00556 {
00557     Sym sym( keySym );
00558     keyQt = sym.qt();
00559     return (keyQt != Qt::Key_unknown);
00560 }
00561 
00562 bool modToModQt( uint mod, int& modQt )
00563 {
00564     modQt = 0;
00565     for( int i = 0; i < KKey::MOD_FLAG_COUNT; i++ ) {
00566         if( mod & g_rgModInfo[i].mod ) {
00567             if( !g_rgModInfo[i].modQt ) {
00568                 modQt = 0;
00569                 return false;
00570             }
00571             modQt |= g_rgModInfo[i].modQt;
00572         }
00573     }
00574     return true;
00575 }
00576 
00577 bool modToModX( uint mod, uint& modX )
00578 {
00579     if( !g_bInitializedMods )
00580         initializeMods();
00581 
00582     modX = 0;
00583     for( int i = 0; i < KKey::MOD_FLAG_COUNT; i++ ) {
00584         if( mod & g_rgModInfo[i].mod ) {
00585             if( !g_rgModInfo[i].modX ) {
00586                 kdDebug(125) << "Invalid modifier flag." << endl;
00587                 modX = 0;
00588                 return false;
00589             }
00590             modX |= g_rgModInfo[i].modX;
00591         }
00592     }
00593     
00594     if( mod & 0x2000 )
00595       modX |= 0x2000;
00596     return true;
00597 }
00598 
00599 bool modXToModQt( uint modX, int& modQt )
00600 {
00601     if( !g_bInitializedMods )
00602         initializeMods();
00603     
00604     modQt = 0;
00605     for( int i = 0; i < KKey::MOD_FLAG_COUNT; i++ ) {
00606         if( modX & g_rgModInfo[i].modX ) {
00607             if( !g_rgModInfo[i].modQt ) {
00608                 modQt = 0;
00609                 return false;
00610             }
00611             modQt |= g_rgModInfo[i].modQt;
00612         }
00613     }
00614     return true;
00615 }
00616 
00617 bool modXToMod( uint modX, uint& mod )
00618 {
00619     if( !g_bInitializedMods )
00620         initializeMods();
00621     
00622     mod = 0;
00623     for( int i = 0; i < KKey::MOD_FLAG_COUNT; i++ ) {
00624         if( modX & g_rgModInfo[i].modX )
00625             mod |= g_rgModInfo[i].mod;
00626     }
00627     return true;
00628 }
00629 
00630 bool codeXToSym( uchar codeX, uint modX, uint& sym )
00631 {
00632     XKeyPressedEvent event;
00633 
00634     event.type = KeyPress;
00635     event.display = qt_xdisplay();
00636     event.state = modX;
00637     event.keycode = codeX;
00638 
00639     XLookupString( &event, 0, 0, (KeySym*) &sym, 0 );
00640     return true;
00641 }
00642 
00643 static QString modToString( uint mod, bool bUserSpace )
00644 {
00645     if( bUserSpace && !g_bInitializedKKeyLabels )
00646         intializeKKeyLabels();
00647 
00648     QString s;
00649     for( int i = KKey::MOD_FLAG_COUNT-1; i >= 0; i-- ) {
00650         if( mod & g_rgModInfo[i].mod ) {
00651             if( !s.isEmpty() )
00652                 s += '+';
00653             s += (bUserSpace)
00654                       ? g_rgModInfo[i].sLabel
00655                   : QString(g_rgModInfo[i].psName);
00656         }
00657     }
00658     return s;
00659 }
00660 
00661 QString modToStringInternal( uint mod ) { return modToString( mod, false ); }
00662 QString modToStringUser( uint mod )     { return modToString( mod, true ); }
00663 
00664 
00665 
00666 
00667 
00668 
00669 
00670 
00671 
00672 
00673 
00674 
00675 
00676 
00677 
00678 
00679 
00680 
00681 
00682 
00683 
00684 
00685 
00686 
00687 
00688 
00689 
00690 
00691 
00692 
00693 
00694 
00695 
00696 
00697 
00698 
00699 
00700 
00701 
00702 
00703 
00704 
00705 
00706 
00707 
00708 
00709 
00710 
00711 
00712 
00713 
00714 
00715 
00716 
00717 
00718 
00719 
00720 
00721 
00722 
00723 
00724 
00725 
00726 
00727 
00728 
00729 
00730 
00731 
00732 
00733 
00734 
00735 
00736 
00737 
00738 
00739 
00740 
00741 
00742 
00743 
00744 
00745 
00746 
00747 
00748 
00749 
00750 
00751 
00752 
00753 
00754 
00755 
00756 
00757 
00758 
00759 
00760 
00761 
00762 
00763 
00764 
00765 
00766 
00767 
00768 
00769 
00770 
00771 
00772 
00773 
00774 
00775 
00776 
00777 
00778 
00779 
00780 bool Key::init( const KKey& key, bool bQt )
00781 {
00782     if( bQt ) {
00783         m_code = CODE_FOR_QT;
00784         m_sym = key.keyCodeQt();
00785     } else {
00786         KKeyNative keyNative( key );
00787         *this = keyNative;
00788     }
00789     return true;
00790 }
00791 
00792 KKey Key::key() const
00793 {
00794     if( m_code == CODE_FOR_QT )
00795         return KKey( keyCodeQt() );
00796     else {
00797         uint mod;
00798         modXToMod( m_mod, mod );
00799         return KKey( m_sym, mod );
00800     }
00801 }
00802 
00803 Key& Key::operator =( const KKeyNative& key )
00804 {
00805     m_code = key.code(); m_mod = key.mod(); m_sym = key.sym();
00806     return *this;
00807 }
00808 
00809 int Key::compare( const Key& b ) const
00810 {
00811     if( m_code == CODE_FOR_QT )
00812         return m_sym - b.m_sym;
00813     if( m_sym != b.m_sym )  return m_sym - b.m_sym;
00814     if( m_mod != b.m_mod )  return m_mod - b.m_mod;
00815     return m_code - b.m_code;
00816 }
00817 
00818 
00819 
00820 
00821 
00822 
00823 void Variations::init( const KKey& key, bool bQt )
00824 {
00825     if( key.isNull() ) {
00826         m_nVariations = 0;
00827         return;
00828     }
00829 
00830     m_nVariations = 1;
00831     m_rgkey[0] = KKeyNative(key);
00832     uint symVar = Sym(key.sym()).getSymVariation();
00833     if( symVar ) {
00834         uint modReq = Sym(m_rgkey[0].sym()).getModsRequired();
00835         uint modReqVar = Sym(symVar).getModsRequired();
00836         
00837         
00838         if( (key.modFlags() & modReq) == (key.modFlags() & modReqVar) ) {
00839             m_rgkey[1] = KKeyNative(KKey(symVar, key.modFlags()));
00840             m_nVariations = 2;
00841         }
00842     }
00843 
00844     if( bQt ) {
00845         uint nVariations = 0;
00846         for( uint i = 0; i < m_nVariations; i++ ) {
00847             int keyQt = KKeyNative( m_rgkey[i].code(), m_rgkey[i].mod(), m_rgkey[i].sym() ).keyCodeQt();
00848             if( keyQt )
00849                 m_rgkey[nVariations++].setKeycodeQt( keyQt );
00850         }
00851         m_nVariations = nVariations;
00852 
00853         
00854         
00855         for( uint i = 1; i < m_nVariations; i++ ) {
00856             for( uint j = 0; j < i; j++ ) {
00857                 
00858                 if( m_rgkey[i].keyCodeQt() == m_rgkey[j].keyCodeQt() ) {
00859                     for( uint k = i; k < m_nVariations - 1; k++ )
00860                         m_rgkey[k].setKeycodeQt( m_rgkey[k+1].keyCodeQt() );
00861                     m_nVariations--;
00862                     i--;
00863                     break;
00864                 }
00865             }
00866         }
00867     }
00868 }
00869 
00870 } 
00871 
00872 
00873 
00874 
00875 
00876 
00877 
00878 void KKey::simplify()
00879 {
00880     if( m_sym == XK_Sys_Req ) {
00881         m_sym = XK_Print;
00882         m_mod |= ALT;
00883     } else if( m_sym == XK_ISO_Left_Tab ) {
00884         m_sym = XK_Tab;
00885         m_mod |= SHIFT;
00886     } else {
00887         
00888         m_sym = KKeyNative(*this).sym();
00889     }
00890 
00891     
00892     if( m_sym < 0x3000 && QChar(m_sym).isLetter() )
00893         m_sym = QChar(m_sym).lower().unicode();
00894 
00895     
00896     
00897     m_mod &= ~KKeyServer::Sym(m_sym).getModsRequired();
00898 }
00899 
00900 #endif // Q_WS_X11