Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/mac_osx/src/external/ois/linux/LinuxKeyboard.cpp @ 8049

Last change on this file since 8049 was 7506, checked in by rgrieder, 14 years ago

Updated OIS source files to its current SVN trunk (r26).

  • Property svn:eol-style set to native
File size: 15.3 KB
Line 
1/*
2The zlib/libpng License
3
4Copyright (c) 2005-2007 Phillip Castaneda (pjcast -- www.wreckedgames.com)
5
6This software is provided 'as-is', without any express or implied warranty. In no event will
7the authors be held liable for any damages arising from the use of this software.
8
9Permission is granted to anyone to use this software for any purpose, including commercial
10applications, and to alter it and redistribute it freely, subject to the following
11restrictions:
12
13    1. The origin of this software must not be misrepresented; you must not claim that
14                you wrote the original software. If you use this software in a product,
15                an acknowledgment in the product documentation would be appreciated but is
16                not required.
17
18    2. Altered source versions must be plainly marked as such, and must not be
19                misrepresented as being the original software.
20
21    3. This notice may not be removed or altered from any source distribution.
22*/
23#include "linux/LinuxInputManager.h"
24#include "linux/LinuxKeyboard.h"
25#include "OISException.h"
26#include "OISEvents.h"
27
28#include <X11/keysym.h>
29#include <X11/Xutil.h>
30#include <cstring>
31
32using namespace OIS;
33#include <iostream>
34//-------------------------------------------------------------------//
35LinuxKeyboard::LinuxKeyboard(InputManager* creator, bool buffered, bool grab)
36        : Keyboard(creator->inputSystemName(), buffered, 0, creator)
37{
38        setlocale(LC_CTYPE, ""); //Set the locale to (hopefully) the users LANG UTF-8 Env var
39
40        display = 0;
41        window = 0;
42
43        grabKeyboard = grab;
44        keyFocusLost = false;
45
46        //X Key Map to KeyCode
47        keyConversion.insert(XtoOIS_KeyMap::value_type(XK_1, KC_1));
48        keyConversion.insert(XtoOIS_KeyMap::value_type(XK_2, KC_2));
49        keyConversion.insert(XtoOIS_KeyMap::value_type(XK_3, KC_3));
50        keyConversion.insert(XtoOIS_KeyMap::value_type(XK_4, KC_4));
51        keyConversion.insert(XtoOIS_KeyMap::value_type(XK_5, KC_5));
52        keyConversion.insert(XtoOIS_KeyMap::value_type(XK_6, KC_6));
53        keyConversion.insert(XtoOIS_KeyMap::value_type(XK_7, KC_7));
54        keyConversion.insert(XtoOIS_KeyMap::value_type(XK_8, KC_8));
55        keyConversion.insert(XtoOIS_KeyMap::value_type(XK_9, KC_9));
56        keyConversion.insert(XtoOIS_KeyMap::value_type(XK_0, KC_0));
57
58        keyConversion.insert(XtoOIS_KeyMap::value_type(XK_BackSpace, KC_BACK));
59
60        keyConversion.insert(XtoOIS_KeyMap::value_type(XK_minus, KC_MINUS));
61        keyConversion.insert(XtoOIS_KeyMap::value_type(XK_equal, KC_EQUALS));
62        keyConversion.insert(XtoOIS_KeyMap::value_type(XK_space, KC_SPACE));
63        keyConversion.insert(XtoOIS_KeyMap::value_type(XK_comma, KC_COMMA));
64        keyConversion.insert(XtoOIS_KeyMap::value_type(XK_period, KC_PERIOD));
65
66        keyConversion.insert(XtoOIS_KeyMap::value_type(XK_backslash, KC_BACKSLASH));
67        keyConversion.insert(XtoOIS_KeyMap::value_type(XK_slash, KC_SLASH));
68        keyConversion.insert(XtoOIS_KeyMap::value_type(XK_bracketleft, KC_LBRACKET));
69        keyConversion.insert(XtoOIS_KeyMap::value_type(XK_bracketright, KC_RBRACKET));
70
71        keyConversion.insert(XtoOIS_KeyMap::value_type(XK_Escape,KC_ESCAPE));
72        keyConversion.insert(XtoOIS_KeyMap::value_type(XK_Caps_Lock, KC_CAPITAL));
73
74        keyConversion.insert(XtoOIS_KeyMap::value_type(XK_Tab, KC_TAB));
75        keyConversion.insert(XtoOIS_KeyMap::value_type(XK_Return, KC_RETURN));
76        keyConversion.insert(XtoOIS_KeyMap::value_type(XK_Control_L, KC_LCONTROL));
77        keyConversion.insert(XtoOIS_KeyMap::value_type(XK_Control_R, KC_RCONTROL));
78
79        keyConversion.insert(XtoOIS_KeyMap::value_type(XK_colon, KC_COLON));
80        keyConversion.insert(XtoOIS_KeyMap::value_type(XK_semicolon, KC_SEMICOLON));
81        keyConversion.insert(XtoOIS_KeyMap::value_type(XK_apostrophe, KC_APOSTROPHE));
82        keyConversion.insert(XtoOIS_KeyMap::value_type(XK_grave, KC_GRAVE));
83
84        keyConversion.insert(XtoOIS_KeyMap::value_type(XK_b, KC_B));
85        keyConversion.insert(XtoOIS_KeyMap::value_type(XK_a, KC_A));
86        keyConversion.insert(XtoOIS_KeyMap::value_type(XK_c, KC_C));
87        keyConversion.insert(XtoOIS_KeyMap::value_type(XK_d, KC_D));
88        keyConversion.insert(XtoOIS_KeyMap::value_type(XK_e, KC_E));
89        keyConversion.insert(XtoOIS_KeyMap::value_type(XK_f, KC_F));
90        keyConversion.insert(XtoOIS_KeyMap::value_type(XK_g, KC_G));
91        keyConversion.insert(XtoOIS_KeyMap::value_type(XK_h, KC_H));
92        keyConversion.insert(XtoOIS_KeyMap::value_type(XK_i, KC_I));
93        keyConversion.insert(XtoOIS_KeyMap::value_type(XK_j, KC_J));
94        keyConversion.insert(XtoOIS_KeyMap::value_type(XK_k, KC_K));
95        keyConversion.insert(XtoOIS_KeyMap::value_type(XK_l, KC_L));
96        keyConversion.insert(XtoOIS_KeyMap::value_type(XK_m, KC_M));
97        keyConversion.insert(XtoOIS_KeyMap::value_type(XK_n, KC_N));
98        keyConversion.insert(XtoOIS_KeyMap::value_type(XK_o, KC_O));
99        keyConversion.insert(XtoOIS_KeyMap::value_type(XK_p, KC_P));
100        keyConversion.insert(XtoOIS_KeyMap::value_type(XK_q, KC_Q));
101        keyConversion.insert(XtoOIS_KeyMap::value_type(XK_r, KC_R));
102        keyConversion.insert(XtoOIS_KeyMap::value_type(XK_s, KC_S));
103        keyConversion.insert(XtoOIS_KeyMap::value_type(XK_t, KC_T));
104        keyConversion.insert(XtoOIS_KeyMap::value_type(XK_u, KC_U));
105        keyConversion.insert(XtoOIS_KeyMap::value_type(XK_v, KC_V));
106        keyConversion.insert(XtoOIS_KeyMap::value_type(XK_w, KC_W));
107        keyConversion.insert(XtoOIS_KeyMap::value_type(XK_x, KC_X));
108        keyConversion.insert(XtoOIS_KeyMap::value_type(XK_y, KC_Y));
109        keyConversion.insert(XtoOIS_KeyMap::value_type(XK_z, KC_Z));
110
111        keyConversion.insert(XtoOIS_KeyMap::value_type(XK_F1, KC_F1));
112        keyConversion.insert(XtoOIS_KeyMap::value_type(XK_F2, KC_F2));
113        keyConversion.insert(XtoOIS_KeyMap::value_type(XK_F3, KC_F3));
114        keyConversion.insert(XtoOIS_KeyMap::value_type(XK_F4, KC_F4));
115        keyConversion.insert(XtoOIS_KeyMap::value_type(XK_F5, KC_F5));
116        keyConversion.insert(XtoOIS_KeyMap::value_type(XK_F6, KC_F6));
117        keyConversion.insert(XtoOIS_KeyMap::value_type(XK_F7, KC_F7));
118        keyConversion.insert(XtoOIS_KeyMap::value_type(XK_F8, KC_F8));
119        keyConversion.insert(XtoOIS_KeyMap::value_type(XK_F9, KC_F9));
120        keyConversion.insert(XtoOIS_KeyMap::value_type(XK_F10, KC_F10));
121        keyConversion.insert(XtoOIS_KeyMap::value_type(XK_F11, KC_F11));
122        keyConversion.insert(XtoOIS_KeyMap::value_type(XK_F12, KC_F12));
123        keyConversion.insert(XtoOIS_KeyMap::value_type(XK_F13, KC_F13));
124        keyConversion.insert(XtoOIS_KeyMap::value_type(XK_F14, KC_F14));
125        keyConversion.insert(XtoOIS_KeyMap::value_type(XK_F15, KC_F15));
126
127        //Keypad
128        keyConversion.insert(XtoOIS_KeyMap::value_type(XK_KP_0, KC_NUMPAD0));
129        keyConversion.insert(XtoOIS_KeyMap::value_type(XK_KP_1, KC_NUMPAD1));
130        keyConversion.insert(XtoOIS_KeyMap::value_type(XK_KP_2, KC_NUMPAD2));
131        keyConversion.insert(XtoOIS_KeyMap::value_type(XK_KP_3, KC_NUMPAD3));
132        keyConversion.insert(XtoOIS_KeyMap::value_type(XK_KP_4, KC_NUMPAD4));
133        keyConversion.insert(XtoOIS_KeyMap::value_type(XK_KP_5, KC_NUMPAD5));
134        keyConversion.insert(XtoOIS_KeyMap::value_type(XK_KP_6, KC_NUMPAD6));
135        keyConversion.insert(XtoOIS_KeyMap::value_type(XK_KP_7, KC_NUMPAD7));
136        keyConversion.insert(XtoOIS_KeyMap::value_type(XK_KP_8, KC_NUMPAD8));
137        keyConversion.insert(XtoOIS_KeyMap::value_type(XK_KP_9, KC_NUMPAD9));
138        keyConversion.insert(XtoOIS_KeyMap::value_type(XK_KP_Add, KC_ADD));
139        keyConversion.insert(XtoOIS_KeyMap::value_type(XK_KP_Subtract, KC_SUBTRACT));
140        keyConversion.insert(XtoOIS_KeyMap::value_type(XK_KP_Decimal, KC_DECIMAL));
141        keyConversion.insert(XtoOIS_KeyMap::value_type(XK_KP_Equal, KC_NUMPADEQUALS));
142        keyConversion.insert(XtoOIS_KeyMap::value_type(XK_KP_Divide, KC_DIVIDE));
143        keyConversion.insert(XtoOIS_KeyMap::value_type(XK_KP_Multiply, KC_MULTIPLY));
144        keyConversion.insert(XtoOIS_KeyMap::value_type(XK_KP_Enter, KC_NUMPADENTER));
145
146        //Keypad with numlock off
147        keyConversion.insert(XtoOIS_KeyMap::value_type(XK_KP_Home, KC_NUMPAD7));
148        keyConversion.insert(XtoOIS_KeyMap::value_type(XK_KP_Up, KC_NUMPAD8));
149        keyConversion.insert(XtoOIS_KeyMap::value_type(XK_KP_Page_Up, KC_NUMPAD9));
150        keyConversion.insert(XtoOIS_KeyMap::value_type(XK_KP_Left, KC_NUMPAD4));
151        keyConversion.insert(XtoOIS_KeyMap::value_type(XK_KP_Begin, KC_NUMPAD5));
152        keyConversion.insert(XtoOIS_KeyMap::value_type(XK_KP_Right, KC_NUMPAD6));
153        keyConversion.insert(XtoOIS_KeyMap::value_type(XK_KP_End, KC_NUMPAD1));
154        keyConversion.insert(XtoOIS_KeyMap::value_type(XK_KP_Down, KC_NUMPAD2));
155        keyConversion.insert(XtoOIS_KeyMap::value_type(XK_KP_Page_Down, KC_NUMPAD3));
156        keyConversion.insert(XtoOIS_KeyMap::value_type(XK_KP_Insert, KC_NUMPAD0));
157        keyConversion.insert(XtoOIS_KeyMap::value_type(XK_KP_Delete, KC_DECIMAL));
158
159        keyConversion.insert(XtoOIS_KeyMap::value_type(XK_Up, KC_UP));
160        keyConversion.insert(XtoOIS_KeyMap::value_type(XK_Down, KC_DOWN));
161        keyConversion.insert(XtoOIS_KeyMap::value_type(XK_Left, KC_LEFT));
162        keyConversion.insert(XtoOIS_KeyMap::value_type(XK_Right, KC_RIGHT));
163
164        keyConversion.insert(XtoOIS_KeyMap::value_type(XK_Page_Up, KC_PGUP));
165        keyConversion.insert(XtoOIS_KeyMap::value_type(XK_Page_Down, KC_PGDOWN));
166        keyConversion.insert(XtoOIS_KeyMap::value_type(XK_Home, KC_HOME));
167        keyConversion.insert(XtoOIS_KeyMap::value_type(XK_End, KC_END));
168
169        keyConversion.insert(XtoOIS_KeyMap::value_type(XK_Num_Lock, KC_NUMLOCK));
170        keyConversion.insert(XtoOIS_KeyMap::value_type(XK_Print, KC_SYSRQ));
171        keyConversion.insert(XtoOIS_KeyMap::value_type(XK_Scroll_Lock, KC_SCROLL));
172        keyConversion.insert(XtoOIS_KeyMap::value_type(XK_Pause, KC_PAUSE));
173
174        keyConversion.insert(XtoOIS_KeyMap::value_type(XK_Shift_R, KC_RSHIFT));
175        keyConversion.insert(XtoOIS_KeyMap::value_type(XK_Shift_L, KC_LSHIFT));
176        keyConversion.insert(XtoOIS_KeyMap::value_type(XK_Alt_R, KC_RMENU));
177        keyConversion.insert(XtoOIS_KeyMap::value_type(XK_Alt_L, KC_LMENU));
178
179        keyConversion.insert(XtoOIS_KeyMap::value_type(XK_Insert, KC_INSERT));
180        keyConversion.insert(XtoOIS_KeyMap::value_type(XK_Delete, KC_DELETE));
181
182        keyConversion.insert(XtoOIS_KeyMap::value_type(XK_Super_L, KC_LWIN));
183        keyConversion.insert(XtoOIS_KeyMap::value_type(XK_Super_R, KC_RWIN));
184        keyConversion.insert(XtoOIS_KeyMap::value_type(XK_Menu, KC_APPS));
185
186        static_cast<LinuxInputManager*>(mCreator)->_setKeyboardUsed(true);
187}
188
189//-------------------------------------------------------------------//
190void LinuxKeyboard::_initialize()
191{
192        //Clear our keyboard state buffer
193        memset( &KeyBuffer, 0, 256 );
194        mModifiers = 0;
195
196        if( display ) XCloseDisplay(display);
197        display = 0;
198        window = static_cast<LinuxInputManager*>(mCreator)->_getWindow();
199
200        //Create our local X mListener connection
201        if( !(display = XOpenDisplay(0)) )
202                OIS_EXCEPT(E_General, "LinuxKeyboard::_initialize >> Error opening X!");
203
204        //Set it to recieve Input events
205        if( XSelectInput(display, window, KeyPressMask | KeyReleaseMask) == BadWindow )
206                OIS_EXCEPT(E_General, "LinuxKeyboard::_initialize: X error!");
207
208        if( grabKeyboard )
209                XGrabKeyboard(display,window,True,GrabModeAsync,GrabModeAsync,CurrentTime);
210
211        keyFocusLost = false;
212}
213
214//-------------------------------------------------------------------//
215LinuxKeyboard::~LinuxKeyboard()
216{
217        if( display )
218        {
219                if( grabKeyboard )
220                        XUngrabKeyboard(display, CurrentTime);
221
222                XCloseDisplay(display);
223        }
224
225        static_cast<LinuxInputManager*>(mCreator)->_setKeyboardUsed(true);
226}
227
228//-------------------------------------------------------------------//
229unsigned int UTF8ToUTF32(unsigned char* buf)
230{
231        unsigned char &FirstChar = buf[0];
232
233        if(FirstChar < 128)
234                return FirstChar;
235
236        unsigned int val = 0;
237        unsigned int len = 0;
238
239        if((FirstChar & 0xE0) == 0xC0) //2 Chars
240        {
241                len = 2;
242                val = FirstChar & 0x1F;
243        }
244        else if((FirstChar & 0xF0) == 0xE0) //3 Chars
245        {
246                len = 3;
247                val = FirstChar & 0x0F;
248        }
249        else if((FirstChar & 0xF8) == 0xF0) //4 Chars
250        {
251                len = 4;
252                val = FirstChar & 0x07;
253        }
254        else if((FirstChar & 0xFC) == 0xF8) //5 Chars
255        {
256                len = 5;
257                val = FirstChar & 0x03;
258        }
259        else // if((FirstChar & 0xFE) == 0xFC) //6 Chars
260        {
261                len = 6;
262                val = FirstChar & 0x01;
263        }
264
265        for(int i = 1; i < len; i++)
266                val = (val << 6) | (buf[i] & 0x3F);
267
268        return val;
269}
270
271//-------------------------------------------------------------------//
272bool LinuxKeyboard::isKeyDown( KeyCode key ) const
273{
274        return (KeyBuffer[key]);
275}
276
277//-------------------------------------------------------------------//
278void LinuxKeyboard::capture()
279{
280        KeySym key;
281        XEvent event;
282        LinuxInputManager* linMan = static_cast<LinuxInputManager*>(mCreator);
283
284        while( XPending(display) > 0 )
285        {
286                XNextEvent(display, &event);            if(KeyPress == event.type)
287                {
288                        unsigned int character = 0;
289
290                        if(mTextMode != Off)
291                        {
292                                unsigned char buffer[6] = {0,0,0,0,0,0};
293                                XLookupString(&event.xkey, (char*)buffer, 6, &key, 0);
294
295                                if( mTextMode == Unicode )
296                                        character = UTF8ToUTF32(buffer);
297                                else if( mTextMode == Ascii)
298                                        character = buffer[0];
299                        }
300
301                        //Mask out the modifier states X11 sets and read again
302                        event.xkey.state &= ~ShiftMask;
303                        event.xkey.state &= ~LockMask;
304                        XLookupString(&event.xkey, 0, 0,&key, 0);
305
306                        _injectKeyDown(key, character);
307
308                        //Just printing out some debugging info.. to verify all chars are mapped
309                        //std::cout << "KEY PRESSED X=" << event.xkey.keycode;
310                        //std::cout << "\n KeySym=" << key << std::endl;
311
312                        //Check for Alt-Tab
313                        if( event.xkey.state & Mod1Mask && key == XK_Tab )
314                                linMan->_setGrabState(false);
315                }
316                else if(KeyRelease == event.type)
317                {
318                        if(!_isKeyRepeat(event))
319                        {
320                                //Mask out the modifier states X sets.. or we will get improper values
321                                event.xkey.state &= ~ShiftMask;
322                                event.xkey.state &= ~LockMask;
323
324                                XLookupString(&event.xkey,NULL,0,&key,NULL);
325                                _injectKeyUp(key);
326                        }
327                }
328        }
329
330        //If grabbing mode is on.. Handle focus lost/gained via Alt-Tab and mouse clicks
331        if( grabKeyboard )
332        {
333                if( linMan->_getGrabState() == false )
334                {
335                        // are no longer grabbing
336                        if( keyFocusLost == false )
337                        {
338                                //UnGrab KeyBoard
339                                XUngrabKeyboard(display, CurrentTime);
340                                keyFocusLost = true;
341                        }
342                }
343                else
344                {
345                        //We are grabbing - and regained focus
346                        if( keyFocusLost == true )
347                        {
348                                //ReGrab KeyBoard
349                                XGrabKeyboard(display, window, True, GrabModeAsync, GrabModeAsync, CurrentTime);
350                                keyFocusLost = false;
351                        }
352                }
353        }
354}
355
356//-------------------------------------------------------------------//
357void LinuxKeyboard::setBuffered(bool buffered)
358{
359        mBuffered = buffered;
360}
361
362//-------------------------------------------------------------------//
363bool LinuxKeyboard::_injectKeyDown( KeySym key, int text )
364{
365        KeyCode kc = keyConversion[key];
366        KeyBuffer[kc] = 1;
367
368        //Turn on modifier flags
369        if( kc == KC_LCONTROL || kc == KC_RCONTROL)
370                mModifiers |= Ctrl;
371        else if( kc == KC_LSHIFT || kc == KC_RSHIFT )
372                mModifiers |= Shift;
373        else if( kc == KC_LMENU || kc == KC_RMENU )
374                mModifiers |= Alt;
375
376        if( mBuffered && mListener )
377                return mListener->keyPressed(KeyEvent(this,kc,text));
378
379        return true;
380}
381
382//-------------------------------------------------------------------//
383bool LinuxKeyboard::_injectKeyUp( KeySym key )
384{
385        KeyCode kc = keyConversion[key];
386        KeyBuffer[kc] = 0;
387
388        //Turn off modifier flags
389        if( kc == KC_LCONTROL || kc == KC_RCONTROL)
390                mModifiers &= ~Ctrl;
391        else if( kc == KC_LSHIFT || kc == KC_RSHIFT )
392                mModifiers &= ~Shift;
393        else if( kc == KC_LMENU || kc == KC_RMENU )
394                mModifiers &= ~Alt;
395
396        if( mBuffered && mListener )
397                return mListener->keyReleased(KeyEvent(this, kc, 0));
398
399        return true;
400}
401
402//-------------------------------------------------------------------//
403const std::string& LinuxKeyboard::getAsString( KeyCode kc )
404{
405        mGetString = "Unknown";
406        char *temp = 0;
407
408        XtoOIS_KeyMap::iterator i = keyConversion.begin(),
409                                e = keyConversion.end();
410
411        for( ; i != e; ++i )
412        {
413                if( i->second == kc )
414                {
415                        temp = XKeysymToString(i->first);
416                        if( temp )
417                                mGetString = temp;
418                        break;
419                }
420        }
421
422        return mGetString;
423}
424
425//-------------------------------------------------------------------//
426void LinuxKeyboard::copyKeyStates( char keys[256] ) const
427{
428        memcpy( keys, KeyBuffer, 256 );
429}
Note: See TracBrowser for help on using the repository browser.