E:/Download/ois-1.0RC1/src/linux/LinuxKeyboard.cpp

Go to the documentation of this file.
00001 /*
00002 The zlib/libpng License
00003 
00004 Copyright (c) 2006 Phillip Castaneda (pjcast -- www.wreckedgames.com)
00005 
00006 This software is provided 'as-is', without any express or implied warranty. In no event will
00007 the authors be held liable for any damages arising from the use of this software.
00008 
00009 Permission is granted to anyone to use this software for any purpose, including commercial
00010 applications, and to alter it and redistribute it freely, subject to the following
00011 restrictions:
00012 
00013     1. The origin of this software must not be misrepresented; you must not claim that
00014                 you wrote the original software. If you use this software in a product,
00015                 an acknowledgment in the product documentation would be appreciated but is
00016                 not required.
00017 
00018     2. Altered source versions must be plainly marked as such, and must not be
00019                 misrepresented as being the original software.
00020 
00021     3. This notice may not be removed or altered from any source distribution.
00022 */
00023 #include "linux/LinuxInputManager.h"
00024 #include "linux/LinuxKeyboard.h"
00025 #include "OISException.h"
00026 #include "OISEvents.h"
00027 
00028 #include <X11/keysym.h>
00029 #include <X11/Xutil.h>
00030 
00031 using namespace OIS;
00032 #include <iostream>
00033 //-------------------------------------------------------------------//
00034 LinuxKeyboard::LinuxKeyboard(InputManager* creator, bool buffered, bool grab, bool useXRepeat)
00035 {
00036         mCreator = creator;
00037         mBuffered = buffered;
00038         mType = OISKeyboard;
00039         listener = 0;
00040         display = 0;
00041         window = 0;
00042 
00043         grabKeyboard = grab;
00044         keyFocusLost = false;
00045 
00046         xAutoRepeat = useXRepeat;
00047         oldXAutoRepeat = false;
00048 
00049         //X Key Map to KeyCode
00050         keyConversion.insert(XtoOIS_KeyMap::value_type(XK_1, KC_1));
00051         keyConversion.insert(XtoOIS_KeyMap::value_type(XK_2, KC_2));
00052         keyConversion.insert(XtoOIS_KeyMap::value_type(XK_3, KC_3));
00053         keyConversion.insert(XtoOIS_KeyMap::value_type(XK_4, KC_4));
00054         keyConversion.insert(XtoOIS_KeyMap::value_type(XK_5, KC_5));
00055         keyConversion.insert(XtoOIS_KeyMap::value_type(XK_6, KC_6));
00056         keyConversion.insert(XtoOIS_KeyMap::value_type(XK_7, KC_7));
00057         keyConversion.insert(XtoOIS_KeyMap::value_type(XK_8, KC_8));
00058         keyConversion.insert(XtoOIS_KeyMap::value_type(XK_9, KC_9));
00059         keyConversion.insert(XtoOIS_KeyMap::value_type(XK_0, KC_0));
00060 
00061         keyConversion.insert(XtoOIS_KeyMap::value_type(XK_BackSpace, KC_BACK));
00062 
00063         keyConversion.insert(XtoOIS_KeyMap::value_type(XK_minus, KC_MINUS));
00064         keyConversion.insert(XtoOIS_KeyMap::value_type(XK_equal, KC_EQUALS));
00065         keyConversion.insert(XtoOIS_KeyMap::value_type(XK_space, KC_SPACE));
00066         keyConversion.insert(XtoOIS_KeyMap::value_type(XK_comma, KC_COMMA));
00067         keyConversion.insert(XtoOIS_KeyMap::value_type(XK_period, KC_PERIOD));
00068 
00069         keyConversion.insert(XtoOIS_KeyMap::value_type(XK_backslash, KC_BACKSLASH));
00070         keyConversion.insert(XtoOIS_KeyMap::value_type(XK_slash, KC_SLASH));
00071         keyConversion.insert(XtoOIS_KeyMap::value_type(XK_bracketleft, KC_LBRACKET));
00072         keyConversion.insert(XtoOIS_KeyMap::value_type(XK_bracketright, KC_RBRACKET));
00073 
00074         keyConversion.insert(XtoOIS_KeyMap::value_type(XK_Escape,KC_ESCAPE));
00075         keyConversion.insert(XtoOIS_KeyMap::value_type(XK_Caps_Lock, KC_CAPITAL));
00076 
00077         keyConversion.insert(XtoOIS_KeyMap::value_type(XK_Tab, KC_TAB));
00078         keyConversion.insert(XtoOIS_KeyMap::value_type(XK_Return, KC_RETURN));
00079         keyConversion.insert(XtoOIS_KeyMap::value_type(XK_Control_L, KC_LCONTROL));
00080         keyConversion.insert(XtoOIS_KeyMap::value_type(XK_Control_R, KC_RCONTROL));
00081 
00082         keyConversion.insert(XtoOIS_KeyMap::value_type(XK_colon, KC_COLON));
00083         keyConversion.insert(XtoOIS_KeyMap::value_type(XK_semicolon, KC_SEMICOLON));
00084         keyConversion.insert(XtoOIS_KeyMap::value_type(XK_apostrophe, KC_APOSTROPHE));
00085         keyConversion.insert(XtoOIS_KeyMap::value_type(XK_grave, KC_GRAVE));
00086 
00087         keyConversion.insert(XtoOIS_KeyMap::value_type(XK_b, KC_B));
00088         keyConversion.insert(XtoOIS_KeyMap::value_type(XK_a, KC_A));
00089         keyConversion.insert(XtoOIS_KeyMap::value_type(XK_c, KC_C));
00090         keyConversion.insert(XtoOIS_KeyMap::value_type(XK_d, KC_D));
00091         keyConversion.insert(XtoOIS_KeyMap::value_type(XK_e, KC_E));
00092         keyConversion.insert(XtoOIS_KeyMap::value_type(XK_f, KC_F));
00093         keyConversion.insert(XtoOIS_KeyMap::value_type(XK_g, KC_G));
00094         keyConversion.insert(XtoOIS_KeyMap::value_type(XK_h, KC_H));
00095         keyConversion.insert(XtoOIS_KeyMap::value_type(XK_i, KC_I));
00096         keyConversion.insert(XtoOIS_KeyMap::value_type(XK_j, KC_J));
00097         keyConversion.insert(XtoOIS_KeyMap::value_type(XK_k, KC_K));
00098         keyConversion.insert(XtoOIS_KeyMap::value_type(XK_l, KC_L));
00099         keyConversion.insert(XtoOIS_KeyMap::value_type(XK_m, KC_M));
00100         keyConversion.insert(XtoOIS_KeyMap::value_type(XK_n, KC_N));
00101         keyConversion.insert(XtoOIS_KeyMap::value_type(XK_o, KC_O));
00102         keyConversion.insert(XtoOIS_KeyMap::value_type(XK_p, KC_P));
00103         keyConversion.insert(XtoOIS_KeyMap::value_type(XK_q, KC_Q));
00104         keyConversion.insert(XtoOIS_KeyMap::value_type(XK_r, KC_R));
00105         keyConversion.insert(XtoOIS_KeyMap::value_type(XK_s, KC_S));
00106         keyConversion.insert(XtoOIS_KeyMap::value_type(XK_t, KC_T));
00107         keyConversion.insert(XtoOIS_KeyMap::value_type(XK_u, KC_U));
00108         keyConversion.insert(XtoOIS_KeyMap::value_type(XK_v, KC_V));
00109         keyConversion.insert(XtoOIS_KeyMap::value_type(XK_w, KC_W));
00110         keyConversion.insert(XtoOIS_KeyMap::value_type(XK_x, KC_X));
00111         keyConversion.insert(XtoOIS_KeyMap::value_type(XK_y, KC_Y));
00112         keyConversion.insert(XtoOIS_KeyMap::value_type(XK_z, KC_Z));
00113 
00114         keyConversion.insert(XtoOIS_KeyMap::value_type(XK_F1, KC_F1));
00115         keyConversion.insert(XtoOIS_KeyMap::value_type(XK_F2, KC_F2));
00116         keyConversion.insert(XtoOIS_KeyMap::value_type(XK_F3, KC_F3));
00117         keyConversion.insert(XtoOIS_KeyMap::value_type(XK_F4, KC_F4));
00118         keyConversion.insert(XtoOIS_KeyMap::value_type(XK_F5, KC_F5));
00119         keyConversion.insert(XtoOIS_KeyMap::value_type(XK_F6, KC_F6));
00120         keyConversion.insert(XtoOIS_KeyMap::value_type(XK_F7, KC_F7));
00121         keyConversion.insert(XtoOIS_KeyMap::value_type(XK_F8, KC_F8));
00122         keyConversion.insert(XtoOIS_KeyMap::value_type(XK_F9, KC_F9));
00123         keyConversion.insert(XtoOIS_KeyMap::value_type(XK_F10, KC_F10));
00124         keyConversion.insert(XtoOIS_KeyMap::value_type(XK_F11, KC_F11));
00125         keyConversion.insert(XtoOIS_KeyMap::value_type(XK_F12, KC_F12));
00126         keyConversion.insert(XtoOIS_KeyMap::value_type(XK_F13, KC_F13));
00127         keyConversion.insert(XtoOIS_KeyMap::value_type(XK_F14, KC_F14));
00128         keyConversion.insert(XtoOIS_KeyMap::value_type(XK_F15, KC_F15));
00129 
00130         //Keypad
00131         keyConversion.insert(XtoOIS_KeyMap::value_type(XK_KP_0, KC_NUMPAD0));
00132         keyConversion.insert(XtoOIS_KeyMap::value_type(XK_KP_1, KC_NUMPAD1));
00133         keyConversion.insert(XtoOIS_KeyMap::value_type(XK_KP_2, KC_NUMPAD2));
00134         keyConversion.insert(XtoOIS_KeyMap::value_type(XK_KP_3, KC_NUMPAD3));
00135         keyConversion.insert(XtoOIS_KeyMap::value_type(XK_KP_4, KC_NUMPAD4));
00136         keyConversion.insert(XtoOIS_KeyMap::value_type(XK_KP_5, KC_NUMPAD5));
00137         keyConversion.insert(XtoOIS_KeyMap::value_type(XK_KP_6, KC_NUMPAD6));
00138         keyConversion.insert(XtoOIS_KeyMap::value_type(XK_KP_7, KC_NUMPAD7));
00139         keyConversion.insert(XtoOIS_KeyMap::value_type(XK_KP_8, KC_NUMPAD8));
00140         keyConversion.insert(XtoOIS_KeyMap::value_type(XK_KP_9, KC_NUMPAD9));
00141         keyConversion.insert(XtoOIS_KeyMap::value_type(XK_KP_Add, KC_ADD));
00142         keyConversion.insert(XtoOIS_KeyMap::value_type(XK_KP_Subtract, KC_SUBTRACT));
00143         keyConversion.insert(XtoOIS_KeyMap::value_type(XK_KP_Decimal, KC_DECIMAL));
00144         keyConversion.insert(XtoOIS_KeyMap::value_type(XK_KP_Equal, KC_NUMPADEQUALS));
00145         keyConversion.insert(XtoOIS_KeyMap::value_type(XK_KP_Divide, KC_DIVIDE));
00146         keyConversion.insert(XtoOIS_KeyMap::value_type(XK_KP_Multiply, KC_MULTIPLY));
00147         keyConversion.insert(XtoOIS_KeyMap::value_type(XK_KP_Enter, KC_NUMPADENTER));
00148 
00149         //Keypad with numlock off
00150         keyConversion.insert(XtoOIS_KeyMap::value_type(XK_KP_Home, KC_NUMPAD7));
00151         keyConversion.insert(XtoOIS_KeyMap::value_type(XK_KP_Up, KC_NUMPAD8));
00152         keyConversion.insert(XtoOIS_KeyMap::value_type(XK_KP_Page_Up, KC_NUMPAD9));
00153         keyConversion.insert(XtoOIS_KeyMap::value_type(XK_KP_Left, KC_NUMPAD4));
00154         keyConversion.insert(XtoOIS_KeyMap::value_type(XK_KP_Begin, KC_NUMPAD5));
00155         keyConversion.insert(XtoOIS_KeyMap::value_type(XK_KP_Right, KC_NUMPAD6));
00156         keyConversion.insert(XtoOIS_KeyMap::value_type(XK_KP_End, KC_NUMPAD1));
00157         keyConversion.insert(XtoOIS_KeyMap::value_type(XK_KP_Down, KC_NUMPAD2));
00158         keyConversion.insert(XtoOIS_KeyMap::value_type(XK_KP_Page_Down, KC_NUMPAD3));
00159         keyConversion.insert(XtoOIS_KeyMap::value_type(XK_KP_Insert, KC_NUMPAD0));
00160         keyConversion.insert(XtoOIS_KeyMap::value_type(XK_KP_Delete, KC_DECIMAL));
00161 
00162         keyConversion.insert(XtoOIS_KeyMap::value_type(XK_Up, KC_UP));
00163         keyConversion.insert(XtoOIS_KeyMap::value_type(XK_Down, KC_DOWN));
00164         keyConversion.insert(XtoOIS_KeyMap::value_type(XK_Left, KC_LEFT));
00165         keyConversion.insert(XtoOIS_KeyMap::value_type(XK_Right, KC_RIGHT));
00166 
00167         keyConversion.insert(XtoOIS_KeyMap::value_type(XK_Page_Up, KC_PGUP));
00168         keyConversion.insert(XtoOIS_KeyMap::value_type(XK_Page_Down, KC_PGDOWN));
00169         keyConversion.insert(XtoOIS_KeyMap::value_type(XK_Home, KC_HOME));
00170         keyConversion.insert(XtoOIS_KeyMap::value_type(XK_End, KC_END));
00171 
00172         keyConversion.insert(XtoOIS_KeyMap::value_type(XK_Num_Lock, KC_NUMLOCK));
00173         keyConversion.insert(XtoOIS_KeyMap::value_type(XK_Print, KC_SYSRQ));
00174         keyConversion.insert(XtoOIS_KeyMap::value_type(XK_Scroll_Lock, KC_SCROLL));
00175         keyConversion.insert(XtoOIS_KeyMap::value_type(XK_Pause, KC_PAUSE));
00176 
00177         keyConversion.insert(XtoOIS_KeyMap::value_type(XK_Shift_R, KC_RSHIFT));
00178         keyConversion.insert(XtoOIS_KeyMap::value_type(XK_Shift_L, KC_LSHIFT));
00179         keyConversion.insert(XtoOIS_KeyMap::value_type(XK_Alt_R, KC_RMENU));
00180         keyConversion.insert(XtoOIS_KeyMap::value_type(XK_Alt_L, KC_LMENU));
00181 
00182         keyConversion.insert(XtoOIS_KeyMap::value_type(XK_Insert, KC_INSERT));
00183         keyConversion.insert(XtoOIS_KeyMap::value_type(XK_Delete, KC_DELETE));
00184 
00185         keyConversion.insert(XtoOIS_KeyMap::value_type(XK_Super_L, KC_LWIN));
00186         keyConversion.insert(XtoOIS_KeyMap::value_type(XK_Super_R, KC_RWIN));
00187         keyConversion.insert(XtoOIS_KeyMap::value_type(XK_Menu, KC_APPS));
00188 }
00189 
00190 //-------------------------------------------------------------------//
00191 void LinuxKeyboard::_initialize()
00192 {
00193         //Clear our keyboard state buffer
00194         memset( &KeyBuffer, 0, 256 );
00195         mModifiers = 0;
00196 
00197         if( display ) XCloseDisplay(display);
00198         display = 0;
00199         window = static_cast<LinuxInputManager*>(mCreator)->_getWindow();
00200 
00201         //Create our local X listener connection
00202         if( !(display = XOpenDisplay(0)) )
00203                 OIS_EXCEPT(E_General, "LinuxKeyboard::_initialize >> Error opening X!");
00204 
00205         //Set it to recieve Input events
00206         if( XSelectInput(display, window, KeyPressMask | KeyReleaseMask) == BadWindow )
00207                 OIS_EXCEPT(E_General, "LinuxKeyboard::_initialize: X error!");
00208 
00209         if( grabKeyboard )
00210                 XGrabKeyboard(display,window,True,GrabModeAsync,GrabModeAsync,CurrentTime);
00211 
00212         keyFocusLost = false;
00213 
00214         if( xAutoRepeat == false )
00215         {
00216                 //We do not want to blindly turn on autorepeat later when quiting if
00217                 //it was not on to begin with.. So, let us check and see first
00218                 XKeyboardState old;
00219                 XGetKeyboardControl( display, &old );
00220                 oldXAutoRepeat = false;
00221 
00222                 if( old.global_auto_repeat == AutoRepeatModeOn )
00223                         oldXAutoRepeat = true;
00224 
00225                 XAutoRepeatOff( display );
00226         }
00227 }
00228 
00229 //-------------------------------------------------------------------//
00230 LinuxKeyboard::~LinuxKeyboard()
00231 {
00232         if( display )
00233         {
00234                 if( oldXAutoRepeat )
00235                         XAutoRepeatOn(display);
00236 
00237                 if( grabKeyboard )
00238                         XUngrabKeyboard(display, CurrentTime);
00239 
00240                 XCloseDisplay(display);
00241         }
00242 }
00243 
00244 //-------------------------------------------------------------------//
00245 bool LinuxKeyboard::isKeyDown( KeyCode key )
00246 {
00247         return (KeyBuffer[key]);
00248 }
00249 
00250 //-------------------------------------------------------------------//
00251 void LinuxKeyboard::capture()
00252 {
00253         KeySym key;
00254         XEvent event;
00255         LinuxInputManager* linMan = static_cast<LinuxInputManager*>(mCreator);
00256 
00257         while( XPending(display) > 0 )
00258         {
00259 
00260                 XNextEvent(display, &event);
00261 
00262 
00263 
00264                 if( KeyPress == event.type )
00265                 {
00266                         char buffer[3] = {0,0,0};
00267                         if( mTextMode != Off )
00268                                 /*int bytes =*/ XLookupString(&event.xkey, buffer, 3, &key, 0);
00269 
00270                         //Mask out the modifier states X11 sets and read again
00271                         event.xkey.state &= ~ShiftMask;
00272                         event.xkey.state &= ~LockMask;
00273                         XLookupString(&event.xkey, 0, 0,&key, 0);
00274 
00275                         _injectKeyDown(key, buffer[0]);
00276 
00277                         //Just printing out some debugging info.. to verify all chars are mapped
00278                         //std::cout << "KEY PRESSED X=" << event.xkey.keycode;
00279                         //std::cout << "\n KeySym=" << key << std::endl;
00280 
00281                         //Check for Alt-Tab
00282                         if( event.xkey.state & Mod1Mask && key == XK_Tab )
00283                                 linMan->_setGrabState(false);
00284                 }
00285 
00286                 else if( KeyRelease == event.type )
00287                 {
00288                         //Mask out the modifier states X sets.. or we will get improper values
00289                         event.xkey.state &= ~ShiftMask;
00290                         event.xkey.state &= ~LockMask;
00291 
00292                         //Else, it is a valid key release
00293                         XLookupString(&event.xkey,NULL,0,&key,NULL);
00294                         _injectKeyUp(key);
00295 
00296                 }
00297         }
00298 
00299         //If grabbing mode is on.. Handle focus lost/gained via Alt-Tab and mouse clicks
00300         if( grabKeyboard )
00301         {
00302                 if( linMan->_getGrabState() == false )
00303                 {
00304                         // are no longer grabbing
00305                         if( keyFocusLost == false )
00306                         {
00307                                 //UnGrab KeyBoard
00308                                 XUngrabKeyboard(display, CurrentTime);
00309                                 keyFocusLost = true;
00310                         }
00311                 }
00312                 else
00313                 {
00314                         //We are grabbing - and regained focus
00315                         if( keyFocusLost == true )
00316                         {
00317                                 //ReGrab KeyBoard
00318                                 XGrabKeyboard(display, window, True, GrabModeAsync, GrabModeAsync, CurrentTime);
00319                                 keyFocusLost = false;
00320                         }
00321                 }
00322         }
00323 }
00324 
00325 //-------------------------------------------------------------------//
00326 void LinuxKeyboard::setBuffered(bool buffered)
00327 {
00328         mBuffered = buffered;
00329 }
00330 
00331 //-------------------------------------------------------------------//
00332 bool LinuxKeyboard::_injectKeyDown( KeySym key, int text )
00333 {
00334         KeyCode kc = keyConversion[key];
00335         KeyBuffer[kc] = 1;
00336 
00337         //Turn on modifier flags
00338         if( kc == KC_LCONTROL || kc == KC_RCONTROL)
00339                 mModifiers |= Ctrl;
00340         else if( kc == KC_LSHIFT || kc == KC_RSHIFT )
00341                 mModifiers |= Shift;
00342         else if( kc == KC_LMENU || kc == KC_RMENU )
00343                 mModifiers |= Alt;
00344 
00345         if( mBuffered && listener )
00346                 return listener->keyPressed(KeyEvent(this,kc,text));
00347 
00348         return true;
00349 }
00350 
00351 //-------------------------------------------------------------------//
00352 bool LinuxKeyboard::_injectKeyUp( KeySym key )
00353 {
00354         KeyCode kc = keyConversion[key];
00355         KeyBuffer[kc] = 0;
00356 
00357         //Turn off modifier flags
00358         if( kc == KC_LCONTROL || kc == KC_RCONTROL)
00359                 mModifiers &= ~Ctrl;
00360         else if( kc == KC_LSHIFT || kc == KC_RSHIFT )
00361                 mModifiers &= ~Shift;
00362         else if( kc == KC_LMENU || kc == KC_RMENU )
00363                 mModifiers &= ~Alt;
00364 
00365         if( mBuffered && listener )
00366                 return listener->keyReleased(KeyEvent(this, kc, 0));
00367 
00368         return true;
00369 }
00370 
00371 //-------------------------------------------------------------------//
00372 const std::string& LinuxKeyboard::getAsString( KeyCode kc )
00373 {
00374         mGetString = "Unknown";
00375         char *temp = 0;
00376 
00377         XtoOIS_KeyMap::iterator i = keyConversion.begin(),
00378                                 e = keyConversion.end();
00379 
00380         for( ; i != e; ++i )
00381         {
00382                 if( i->second == kc )
00383                 {
00384                         temp = XKeysymToString(i->first);
00385                         if( temp )
00386                                 mGetString = temp;
00387                         break;
00388                 }
00389         }
00390 
00391         return mGetString;
00392 }
00393 
00394 //-------------------------------------------------------------------//
00395 void LinuxKeyboard::copyKeyStates( char keys[256] )
00396 {
00397         memcpy( keys, KeyBuffer, 256 );
00398 }

Generated on Sat Dec 1 20:13:51 2007 for OIS by  doxygen 1.5.4