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, g_modXModeSwitch;
00287 
00288 bool initializeMods()
00289 {
00290     XModifierKeymap* xmk = XGetModifierMapping( qt_xdisplay() );
00291 
00292     g_rgModInfo[3].modX = g_modXNumLock = g_modXScrollLock = g_modXModeSwitch = 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             case XK_Mode_switch: g_modXModeSwitch = mask; break;
00317         }
00318     }
00319 
00320     XFreeModifiermap( xmk );
00321 
00322     //KConfigGroupSaver cgs( KGlobal::config(), "Keyboard" );
00323     // read in mod that win should be attached to
00324 
00325     g_bInitializedMods = true;
00326 
00327     kdDebug(125) << "KKeyServer::initializeMods(): Win Mod = 0x" << QString::number(g_rgModInfo[3].modX, 16) << endl;
00328     return true;
00329 }
00330 
00331 static void initializeVariations()
00332 {
00333     for( int i = 0; g_rgSymVariation[i].sym != 0; i++ )
00334         g_rgSymVariation[i].bActive = (XKeysymToKeycode( qt_xdisplay(), g_rgSymVariation[i].symVariation ) != 0);
00335     g_bInitializedVariations = true;
00336 }
00337 
00338 static void intializeKKeyLabels()
00339 {
00340     KConfigGroupSaver cgs( KGlobal::config(), "Keyboard" );
00341     g_rgModInfo[0].sLabel = KGlobal::config()->readEntry( "Label Shift", i18n(g_rgModInfo[0].psName) );
00342     g_rgModInfo[1].sLabel = KGlobal::config()->readEntry( "Label Ctrl", i18n(g_rgModInfo[1].psName) );
00343     g_rgModInfo[2].sLabel = KGlobal::config()->readEntry( "Label Alt", i18n(g_rgModInfo[2].psName) );
00344     g_rgModInfo[3].sLabel = KGlobal::config()->readEntry( "Label Win", i18n(g_rgModInfo[3].psName) );
00345     g_bMacLabels = (g_rgModInfo[2].sLabel == "Command");
00346     g_bInitializedKKeyLabels = true;
00347 }
00348 
00349 //---------------------------------------------------------------------
00350 // class Mod
00351 //---------------------------------------------------------------------
00352 
00353 /*void Mod::init( const QString& s )
00354 {
00355 
00356 }*/
00357 
00358 //---------------------------------------------------------------------
00359 // class Sym
00360 //---------------------------------------------------------------------
00361 
00362 bool Sym::initQt( int keyQt )
00363 {
00364     int symQt = keyQt & 0xffff;
00365 
00366     if( (keyQt & Qt::UNICODE_ACCEL) || symQt < 0x1000 ) {
00367         m_sym = QChar(symQt).lower().unicode();
00368         return true;
00369     }
00370 
00371     for( uint i = 0; i < sizeof(g_rgQtToSymX)/sizeof(TransKey); i++ ) {
00372         if( g_rgQtToSymX[i].keySymQt == symQt ) {
00373             m_sym = g_rgQtToSymX[i].keySymX;
00374             return true;
00375         }
00376     }
00377 
00378     m_sym = 0;
00379     if( symQt != Qt::Key_Shift && symQt != Qt::Key_Control && symQt != Qt::Key_Alt &&
00380         symQt != Qt::Key_Meta && symQt != Qt::Key_Direction_L && symQt != Qt::Key_Direction_R )
00381         kdDebug(125) << "Sym::initQt( " << QString::number(keyQt,16) << " ): failed to convert key." << endl;
00382     return false;
00383 }
00384 
00385 bool Sym::init( const QString& s )
00386 {
00387     // If it's a single character, get unicode value.
00388     if( s.length() == 1 ) {
00389         m_sym = s[0].lower().unicode();
00390         return true;
00391     }
00392 
00393     // Look up in special names list
00394     for( int i = 0; g_rgSymNames[i].sym != 0; i++ ) {
00395         if( qstricmp( s.latin1(), g_rgSymNames[i].psName ) == 0 ) {
00396             m_sym = g_rgSymNames[i].sym;
00397             return true;
00398         }
00399     }
00400 
00401     // search X list: 's' as is, all lower, first letter in caps
00402     m_sym = XStringToKeysym( s.latin1() );
00403     if( !m_sym ) {
00404         m_sym = XStringToKeysym( s.lower().latin1() );
00405         if( !m_sym ) {
00406             QString s2 = s;
00407             s2[0] = s2[0].upper();
00408             m_sym = XStringToKeysym( s2.latin1() );
00409         }
00410     }
00411 
00412     return m_sym != 0;
00413 }
00414 
00415 int Sym::qt() const
00416 {
00417     if( m_sym < 0x1000 ) {
00418         if( m_sym >= 'a' && m_sym <= 'z' )
00419             return QChar(m_sym).upper();
00420         return m_sym;
00421     }
00422     if( m_sym < 0x3000 )
00423         return m_sym | Qt::UNICODE_ACCEL;
00424 
00425     for( uint i = 0; i < sizeof(g_rgQtToSymX)/sizeof(TransKey); i++ )
00426         if( g_rgQtToSymX[i].keySymX == m_sym )
00427             return g_rgQtToSymX[i].keySymQt;
00428     return Qt::Key_unknown;
00429 }
00430 
00431 QString Sym::toString( bool bUserSpace ) const
00432 {
00433     if( m_sym == 0 )
00434         return QString::null;
00435 
00436     // If it's a unicode character,
00437     else if( m_sym < 0x3000 ) {
00438         QChar c = QChar(m_sym).upper();
00439         // Print all non-space characters directly when output is user-visible.
00440         // Otherwise only print alphanumeric latin1 characters directly (A,B,C,1,2,3).
00441         if( (c.latin1() && c.isLetterOrNumber())
00442             || (bUserSpace && !c.isSpace()) )
00443                 return c;
00444     }
00445 
00446     // Look up in special names list
00447     for( int i = 0; g_rgSymNames[i].sym != 0; i++ ) {
00448         if( m_sym == g_rgSymNames[i].sym )
00449             return bUserSpace ? i18n(g_rgSymNames[i].psName) : QString(g_rgSymNames[i].psName);
00450     }
00451 
00452     // Get X-name
00453     QString s = XKeysymToString( m_sym );
00454     capitalizeKeyname( s );
00455     return bUserSpace ? i18n("QAccel", s.latin1()) : s;
00456 }
00457 
00458 QString Sym::toStringInternal() const { return toString( false ); }
00459 QString Sym::toString() const         { return toString( true ); }
00460 
00461 uint Sym::getModsRequired() const
00462 {
00463     uint mod = 0;
00464 
00465     // FIXME: This might not be true on all keyboard layouts!
00466     if( m_sym == XK_Sys_Req ) return KKey::ALT;
00467     if( m_sym == XK_Break ) return KKey::CTRL;
00468 
00469     if( m_sym < 0x3000 ) {
00470         QChar c(m_sym);
00471         if( c.isLetter() && c.lower() != c.upper() && m_sym == c.upper().unicode() )
00472             return KKey::SHIFT;
00473     }
00474 
00475     uchar code = XKeysymToKeycode( qt_xdisplay(), m_sym );
00476     if( code ) {
00477         // need to check index 0 before the others, so that a null-mod
00478         //  can take precedence over the others, in case the modified
00479         //  key produces the same symbol.
00480         if( m_sym == XKeycodeToKeysym( qt_xdisplay(), code, 0 ) )
00481             ;
00482         else if( m_sym == XKeycodeToKeysym( qt_xdisplay(), code, 1 ) )
00483             mod = KKey::SHIFT;
00484         else if( m_sym == XKeycodeToKeysym( qt_xdisplay(), code, 2 ) )
00485             mod = KKeyServer::MODE_SWITCH;
00486         else if( m_sym == XKeycodeToKeysym( qt_xdisplay(), code, 3 ) )
00487             mod = KKey::SHIFT | KKeyServer::MODE_SWITCH;
00488     }
00489 
00490     return mod;
00491 }
00492 
00493 uint Sym::getSymVariation() const
00494 {
00495     if( !g_bInitializedVariations )
00496         initializeVariations();
00497 
00498     for( int i = 0; g_rgSymVariation[i].sym != 0; i++ )
00499         if( g_rgSymVariation[i].sym == m_sym && g_rgSymVariation[i].bActive )
00500             return g_rgSymVariation[i].symVariation;
00501     return 0;
00502 }
00503 
00504 void Sym::capitalizeKeyname( QString& s )
00505 {
00506     s[0] = s[0].upper();
00507     int len = s.length();
00508     if( s.endsWith( "left" ) )       s[len-4] = 'L';
00509     else if( s.endsWith( "right" ) ) s[len-5] = 'R';
00510     else if( s == "Sysreq" )         s[len-3] = 'R';
00511 }
00512 
00513 //---------------------------------------------------------------------
00514 // Public functions
00515 //---------------------------------------------------------------------
00516 
00517 uint modX( KKey::ModFlag mod )
00518 {
00519     if( mod == KKey::WIN && !g_bInitializedMods )
00520         initializeMods();
00521 
00522     for( uint i = 0; i < KKey::MOD_FLAG_COUNT; i++ ) {
00523         if( g_rgModInfo[i].mod == mod )
00524             return g_rgModInfo[i].modX;
00525     }
00526     return 0;
00527 }
00528 
00529 bool keyboardHasWinKey() { if( !g_bInitializedMods ) { initializeMods(); } return g_rgModInfo[3].modX != 0; }
00530 uint modXShift()      { return ShiftMask; }
00531 uint modXLock()       { return LockMask; }
00532 uint modXCtrl()       { return ControlMask; }
00533 uint modXAlt()        { return Mod1Mask; }
00534 uint modXNumLock()    { if( !g_bInitializedMods ) { initializeMods(); } return g_modXNumLock; }
00535 uint modXWin()        { if( !g_bInitializedMods ) { initializeMods(); } return g_rgModInfo[3].modX; }
00536 uint modXScrollLock() { if( !g_bInitializedMods ) { initializeMods(); } return g_modXScrollLock; }
00537 uint modXModeSwitch() { if( !g_bInitializedMods ) { initializeMods(); } return g_modXModeSwitch; }
00538 
00539 uint accelModMaskX()
00540 {
00541     if( !g_bInitializedMods )
00542         initializeMods();
00543     return ShiftMask | ControlMask | Mod1Mask | g_rgModInfo[3].modX;
00544 }
00545 
00546 bool keyQtToSym( int keyQt, uint& keySym )
00547 {
00548     Sym sym;
00549     if( sym.initQt( keyQt ) ) {
00550         keySym = sym.m_sym;
00551         return true;
00552     } else
00553         return false;
00554 }
00555 
00556 bool keyQtToMod( int keyQt, uint& mod )
00557 {
00558     mod = 0;
00559 
00560     if( keyQt & Qt::SHIFT )    mod |= KKey::SHIFT;
00561     if( keyQt & Qt::CTRL )     mod |= KKey::CTRL;
00562     if( keyQt & Qt::ALT )      mod |= KKey::ALT;
00563     if( keyQt & Qt::META ) mod |= KKey::WIN;
00564 
00565     return true;
00566 }
00567 
00568 bool symToKeyQt( uint keySym, int& keyQt )
00569 {
00570     Sym sym( keySym );
00571     keyQt = sym.qt();
00572     return (keyQt != Qt::Key_unknown);
00573 }
00574 
00575 bool modToModQt( uint mod, int& modQt )
00576 {
00577     modQt = 0;
00578     for( int i = 0; i < KKey::MOD_FLAG_COUNT; i++ ) {
00579         if( mod & g_rgModInfo[i].mod ) {
00580             if( !g_rgModInfo[i].modQt ) {
00581                 modQt = 0;
00582                 return false;
00583             }
00584             modQt |= g_rgModInfo[i].modQt;
00585         }
00586     }
00587     return true;
00588 }
00589 
00590 bool modToModX( uint mod, uint& modX )
00591 {
00592     if( !g_bInitializedMods )
00593         initializeMods();
00594 
00595     modX = 0;
00596     for( int i = 0; i < KKey::MOD_FLAG_COUNT; i++ ) {
00597         if( mod & g_rgModInfo[i].mod ) {
00598             if( !g_rgModInfo[i].modX ) {
00599                 kdDebug(125) << "Invalid modifier flag." << endl;
00600                 modX = 0;
00601                 return false;
00602             }
00603             modX |= g_rgModInfo[i].modX;
00604         }
00605     }
00606     // TODO: document 0x2000 flag
00607     if( mod & 0x2000 )
00608       modX |= 0x2000;
00609     return true;
00610 }
00611 
00612 bool modXToModQt( uint modX, int& modQt )
00613 {
00614     if( !g_bInitializedMods )
00615         initializeMods();
00616     
00617     modQt = 0;
00618     for( int i = 0; i < KKey::MOD_FLAG_COUNT; i++ ) {
00619         if( modX & g_rgModInfo[i].modX ) {
00620             if( !g_rgModInfo[i].modQt ) {
00621                 modQt = 0;
00622                 return false;
00623             }
00624             modQt |= g_rgModInfo[i].modQt;
00625         }
00626     }
00627     return true;
00628 }
00629 
00630 bool modXToMod( uint modX, uint& mod )
00631 {
00632     if( !g_bInitializedMods )
00633         initializeMods();
00634     
00635     mod = 0;
00636     for( int i = 0; i < KKey::MOD_FLAG_COUNT; i++ ) {
00637         if( modX & g_rgModInfo[i].modX )
00638             mod |= g_rgModInfo[i].mod;
00639     }
00640     return true;
00641 }
00642 
00643 bool codeXToSym( uchar codeX, uint modX, uint& sym )
00644 {
00645     XKeyPressedEvent event;
00646 
00647     event.type = KeyPress;
00648     event.display = qt_xdisplay();
00649     event.state = modX;
00650     event.keycode = codeX;
00651 
00652     XLookupString( &event, 0, 0, (KeySym*) &sym, 0 );
00653     return true;
00654 }
00655 
00656 static QString modToString( uint mod, bool bUserSpace )
00657 {
00658     if( bUserSpace && !g_bInitializedKKeyLabels )
00659         intializeKKeyLabels();
00660 
00661     QString s;
00662     for( int i = KKey::MOD_FLAG_COUNT-1; i >= 0; i-- ) {
00663         if( mod & g_rgModInfo[i].mod ) {
00664             if( !s.isEmpty() )
00665                 s += '+';
00666             s += (bUserSpace)
00667                       ? g_rgModInfo[i].sLabel
00668                   : QString(g_rgModInfo[i].psName);
00669         }
00670     }
00671     return s;
00672 }
00673 
00674 QString modToStringInternal( uint mod ) { return modToString( mod, false ); }
00675 QString modToStringUser( uint mod )     { return modToString( mod, true ); }
00676 
00677 /*void keySymModToKeyX( uint sym, uint mod, unsigned char *pKeyCodeX, uint *pKeySymX, uint *pKeyModX )
00678 {
00679 ...
00680     uint    keySymQt;
00681     uint    keySymX = 0;
00682     unsigned char   keyCodeX = 0;
00683     uint    keyModX = 0;
00684 
00685     const char *psKeySym = 0;
00686 
00687     if( !g_bInitialized )
00688         Initialize();
00689 
00690     // Get code of just the primary key
00691     keySymQt = keyCombQt & 0xffff;
00692 
00693     // If unicode value beneath 0x1000 (special Qt codes begin thereafter),
00694     if( keySymQt < 0x1000 ) {
00695         // For reasons unbeknownst to me, Qt converts 'a-z' to 'A-Z'.
00696         // So convert it back to lowercase if SHIFT isn't held down.
00697         if( keySymQt >= Qt::Key_A && keySymQt <= Qt::Key_Z && !(keyCombQt & Qt::SHIFT) )
00698             keySymQt = tolower( keySymQt );
00699         keySymX = keySymQt;
00700     }
00701     // Else, special key (e.g. Delete, F1, etc.)
00702     else {
00703         for( int i = 0; i < NB_KEYS; i++ ) {
00704             if( keySymQt == (uint) KKEYS[i].code ) {
00705                 psKeySym = KKEYS[i].name;
00706                 //kdDebug(125) << " symbol found: \"" << psKeySym << "\"" << endl;
00707                 break;
00708             }
00709         }
00710 
00711         // Get X key symbol.  Only works if Qt name is same as X name.
00712         if( psKeySym ) {
00713             QString sKeySym = psKeySym;
00714 
00715             // Check for lower-case equalent first because most
00716             //  X11 names are all lower-case.
00717             keySymX = XStringToKeysym( sKeySym.lower().ascii() );
00718             if( keySymX == 0 )
00719                 keySymX = XStringToKeysym( psKeySym );
00720         }
00721 
00722         if( keySymX == 0 )
00723             keySymX = getSymXEquiv( keySymQt );
00724     }
00725 
00726     if( keySymX != 0 ) {
00727         // Get X keyboard code
00728         keyCodeX = XKeysymToKeycode( qt_xdisplay(), keySymX );
00729         // Add ModeSwitch modifier bit, if necessary
00730         keySymXMods( keySymX, 0, &keyModX );
00731 
00732         // Get X modifier flags
00733         for( int i = 0; i < MOD_KEYS; i++ ) {
00734             if( keyCombQt & g_aModKeys[i].keyModMaskQt ) {
00735                 if( g_aModKeys[i].keyModMaskX )
00736                     keyModX |= g_aModKeys[i].keyModMaskX;
00737                 // Qt key calls for a modifier which the current
00738                 //  X modifier map doesn't support.
00739                 else {
00740                     keySymX = 0;
00741                     keyCodeX = 0;
00742                     keyModX = 0;
00743                     break;
00744                 }
00745             }
00746         }
00747     }
00748 
00749     // Take care of complications:
00750     //  The following keys will not have been correctly interpreted,
00751     //   because their shifted values are not activated with the
00752     //   Shift key, but rather something else.  They are also
00753     //   defined twice under different keycodes.
00754     //  keycode 111 & 92:  Print Sys_Req -> Sys_Req = Alt+Print
00755     //  keycode 110 & 114: Pause Break   -> Break = Ctrl+Pause
00756     if( (keyCodeX == 92 || keyCodeX == 111) &&
00757         XKeycodeToKeysym( qt_xdisplay(), 92, 0 ) == XK_Print &&
00758         XKeycodeToKeysym( qt_xdisplay(), 111, 0 ) == XK_Print )
00759     {
00760         // If Alt is pressed, then we need keycode 92, keysym XK_Sys_Req
00761         if( keyModX & keyModXAlt() ) {
00762             keyCodeX = 92;
00763             keySymX = XK_Sys_Req;
00764         }
00765         // Otherwise, keycode 111, keysym XK_Print
00766         else {
00767             keyCodeX = 111;
00768             keySymX = XK_Print;
00769         }
00770     }
00771     else if( (keyCodeX == 110 || keyCodeX == 114) &&
00772         XKeycodeToKeysym( qt_xdisplay(), 110, 0 ) == XK_Pause &&
00773         XKeycodeToKeysym( qt_xdisplay(), 114, 0 ) == XK_Pause )
00774     {
00775         if( keyModX & keyModXCtrl() ) {
00776             keyCodeX = 114;
00777             keySymX = XK_Break;
00778         } else {
00779             keyCodeX = 110;
00780             keySymX = XK_Pause;
00781         }
00782     }
00783 
00784     if( pKeySymX )  *pKeySymX = keySymX;
00785     if( pKeyCodeX ) *pKeyCodeX = keyCodeX;
00786     if( pKeyModX )  *pKeyModX = keyModX;
00787 }*/
00788 
00789 //---------------------------------------------------------------------
00790 // Key
00791 //---------------------------------------------------------------------
00792 
00793 bool Key::init( const KKey& key, bool bQt )
00794 {
00795     if( bQt ) {
00796         m_code = CODE_FOR_QT;
00797         m_sym = key.keyCodeQt();
00798     } else {
00799         KKeyNative keyNative( key );
00800         *this = keyNative;
00801     }
00802     return true;
00803 }
00804 
00805 KKey Key::key() const
00806 {
00807     if( m_code == CODE_FOR_QT )
00808         return KKey( keyCodeQt() );
00809     else {
00810         uint mod;
00811         modXToMod( m_mod, mod );
00812         return KKey( m_sym, mod );
00813     }
00814 }
00815 
00816 Key& Key::operator =( const KKeyNative& key )
00817 {
00818     m_code = key.code(); m_mod = key.mod(); m_sym = key.sym();
00819     return *this;
00820 }
00821 
00822 int Key::compare( const Key& b ) const
00823 {
00824     if( m_code == CODE_FOR_QT )
00825         return m_sym - b.m_sym;
00826     if( m_sym != b.m_sym )  return m_sym - b.m_sym;
00827     if( m_mod != b.m_mod )  return m_mod - b.m_mod;
00828     return m_code - b.m_code;
00829 }
00830 
00831 //---------------------------------------------------------------------
00832 // Variations
00833 //---------------------------------------------------------------------
00834 
00835 // TODO: allow for sym to have variations, such as Plus => { Plus, KP_Add }
00836 void Variations::init( const KKey& key, bool bQt )
00837 {
00838     if( key.isNull() ) {
00839         m_nVariations = 0;
00840         return;
00841     }
00842 
00843     m_nVariations = 1;
00844     m_rgkey[0] = KKeyNative(key);
00845     uint symVar = Sym(key.sym()).getSymVariation();
00846     if( symVar ) {
00847         uint modReq = Sym(m_rgkey[0].sym()).getModsRequired();
00848         uint modReqVar = Sym(symVar).getModsRequired();
00849         // If 'key' doesn't require any mods that are inherent in
00850         //  the primary key but not required for the alternate,
00851         if( (key.modFlags() & modReq) == (key.modFlags() & modReqVar) ) {
00852             m_rgkey[1] = KKeyNative(KKey(symVar, key.modFlags()));
00853             m_nVariations = 2;
00854         }
00855     }
00856 
00857     if( bQt ) {
00858         uint nVariations = 0;
00859         for( uint i = 0; i < m_nVariations; i++ ) {
00860             int keyQt = KKeyNative( m_rgkey[i].code(), m_rgkey[i].mod(), m_rgkey[i].sym() ).keyCodeQt();
00861             if( keyQt )
00862                 m_rgkey[nVariations++].setKeycodeQt( keyQt );
00863         }
00864         m_nVariations = nVariations;
00865 
00866         // Two different native codes may produce a single
00867         //  Qt code.  Search for duplicates.
00868         for( uint i = 1; i < m_nVariations; i++ ) {
00869             for( uint j = 0; j < i; j++ ) {
00870                 // If key is already present in list, then remove it.
00871                 if( m_rgkey[i].keyCodeQt() == m_rgkey[j].keyCodeQt() ) {
00872                     for( uint k = i; k < m_nVariations - 1; k++ )
00873                         m_rgkey[k].setKeycodeQt( m_rgkey[k+1].keyCodeQt() );
00874                     m_nVariations--;
00875                     i--;
00876                     break;
00877                 }
00878             }
00879         }
00880     }
00881 }
00882 
00883 } // end of namespace KKeyServer block
00884 
00885 // FIXME: This needs to be moved to kshortcut.cpp, and create a 
00886 //  KKeyServer::method which it will call.
00887 // Alt+SysReq => Alt+Print
00888 // Ctrl+Shift+Plus => Ctrl+Plus (en)
00889 // Ctrl+Shift+Equal => Ctrl+Plus
00890 // Ctrl+Pause => Ctrl+Break
00891 void KKey::simplify()
00892 {
00893     if( m_sym == XK_Sys_Req ) {
00894         m_sym = XK_Print;
00895         m_mod |= ALT;
00896     } else if( m_sym == XK_ISO_Left_Tab ) {
00897         m_sym = XK_Tab;
00898         m_mod |= SHIFT;
00899     } else {
00900         // Shift+Equal => Shift+Plus (en)
00901         m_sym = KKeyNative(*this).sym();
00902     }
00903 
00904     // If this is a letter, don't remove any modifiers.
00905     if( m_sym < 0x3000 && QChar(m_sym).isLetter() )
00906         m_sym = QChar(m_sym).lower().unicode();
00907 
00908     // Remove modifers from modifier list which are implicit in the symbol.
00909     // Ex. Shift+Plus => Plus (en)
00910     m_mod &= ~KKeyServer::Sym(m_sym).getModsRequired();
00911 }
00912 
00913 #endif // Q_WS_X11
KDE Logo
This file is part of the documentation for kdecore Library Version 3.3.2.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Sun Jan 15 13:32:29 2006 by doxygen 1.4.2 written by Dimitri van Heesch, © 1997-2003