• Skip to content
  • Skip to link menu
KDE 3.5 API Reference
  • KDE API Reference
  • API Reference
  • Sitemap
  • Contact Us
 

KDECore

kkeyserver_x11.cpp

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

KDECore

Skip menu "KDECore"
  • Main Page
  • Modules
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

API Reference

Skip menu "API Reference"
  • dcop
  • DNSSD
  • interfaces
  • Kate
  • kconf_update
  • KDECore
  • KDED
  • kdefx
  • KDEsu
  • kdeui
  • KDocTools
  • KHTML
  • KImgIO
  • KInit
  • kio
  • kioslave
  • KJS
  • KNewStuff
  • KParts
  • KUtils
Generated for API Reference by doxygen 1.5.9
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal