00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
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
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
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
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
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
00202 if( !(display = XOpenDisplay(0)) )
00203 OIS_EXCEPT(E_General, "LinuxKeyboard::_initialize >> Error opening X!");
00204
00205
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
00217
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 XLookupString(&event.xkey, buffer, 3, &key, 0);
00269
00270
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
00278
00279
00280
00281
00282 if( event.xkey.state & Mod1Mask && key == XK_Tab )
00283 linMan->_setGrabState(false);
00284 }
00285
00286 else if( KeyRelease == event.type )
00287 {
00288
00289 event.xkey.state &= ~ShiftMask;
00290 event.xkey.state &= ~LockMask;
00291
00292
00293 XLookupString(&event.xkey,NULL,0,&key,NULL);
00294 _injectKeyUp(key);
00295
00296 }
00297 }
00298
00299
00300 if( grabKeyboard )
00301 {
00302 if( linMan->_getGrabState() == false )
00303 {
00304
00305 if( keyFocusLost == false )
00306 {
00307
00308 XUngrabKeyboard(display, CurrentTime);
00309 keyFocusLost = true;
00310 }
00311 }
00312 else
00313 {
00314
00315 if( keyFocusLost == true )
00316 {
00317
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
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
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 }