Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/SuperOrxoBros_HS18/src/external/ois/mac/MacKeyboard.cpp @ 12177

Last change on this file since 12177 was 12177, checked in by siramesh, 5 years ago

Super Orxo Bros Final (Sidharth Ramesh, Nisa Balta, Jeff Ren)

File size: 17.5 KB
Line 
1/*
2 The zlib/libpng License
3 
4 Copyright (c) 2006 Chris Snyder
5 
6 This software is provided 'as-is', without any express or implied warranty. In no event will
7 the authors be held liable for any damages arising from the use of this software.
8 
9 Permission is granted to anyone to use this software for any purpose, including commercial
10 applications, and to alter it and redistribute it freely, subject to the following
11 restrictions:
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
24#include "mac/MacKeyboard.h"
25#include "mac/MacInputManager.h"
26#include "mac/MacHelpers.h"
27#include "OISException.h"
28#include "OISEvents.h"
29
30#include <Carbon/Carbon.h>
31
32#include <list>
33#include <string>
34
35const EventTypeSpec DownSpec[] = {{kEventClassKeyboard, kEventRawKeyDown},      //non - repeats
36                                                        {kEventClassKeyboard, kEventRawKeyRepeat}}; //repeats
37const EventTypeSpec UpSpec = {kEventClassKeyboard, kEventRawKeyUp},
38                          ModSpec = {kEventClassKeyboard, kEventRawKeyModifiersChanged};
39
40const EventTypeSpec AllSpecs[] = {{kEventClassKeyboard, kEventRawKeyDown},
41                                                  {kEventClassKeyboard, kEventRawKeyRepeat},
42                                                  {kEventClassKeyboard, kEventRawKeyUp},
43                                                  {kEventClassKeyboard, kEventRawKeyModifiersChanged}};
44
45using namespace OIS;
46
47//-------------------------------------------------------------------//
48MacKeyboard::MacKeyboard( InputManager* creator, bool buffered, bool repeat )
49        : Keyboard(creator->inputSystemName(), buffered, 0, creator)
50{
51        keyDownEventRef = NULL;
52        keyUpEventRef = NULL;
53        keyModEventRef = NULL;
54       
55        useRepeat = repeat;
56
57        // Get a so-called "Univeral procedure pointer" for our callback
58        keyDownUPP = NewEventHandlerUPP( KeyDownWrapper );
59        keyUpUPP   = NewEventHandlerUPP( KeyUpWrapper );
60        keyModUPP  = NewEventHandlerUPP( KeyModWrapper );
61       
62        // populate the conversion map
63        populateKeyConversion();
64
65        static_cast<MacInputManager*>(mCreator)->_setKeyboardUsed(true);
66}
67
68//-------------------------------------------------------------------//
69MacKeyboard::~MacKeyboard()
70{
71        // Remove our handlers so that this instance doesn't get called
72        // after it is deleted
73        if (keyDownEventRef != NULL)
74                RemoveEventHandler(keyDownEventRef);
75               
76        if (keyUpEventRef != NULL)
77                RemoveEventHandler(keyUpEventRef);
78       
79        if (keyModEventRef != NULL)
80                RemoveEventHandler(keyModEventRef);
81       
82        // dispose of our UPPs
83        DisposeEventHandlerUPP(keyDownUPP);
84        DisposeEventHandlerUPP(keyUpUPP);
85        DisposeEventHandlerUPP(keyModUPP);
86
87        //Free the input managers keyboard
88        static_cast<MacInputManager*>(mCreator)->_setKeyboardUsed(false);
89}
90
91//-------------------------------------------------------------------//
92void MacKeyboard::_initialize()
93{
94        EventTargetRef event = ((MacInputManager*)mCreator)->_getEventTarget();
95
96        memset( &KeyBuffer, 0, 256 );
97        mModifiers = 0;
98        prevModMask = 0;
99       
100        // just in case this gets called after the first time.. better safe
101        if (keyDownEventRef != NULL)
102                RemoveEventHandler(keyDownEventRef);
103               
104        if (keyUpEventRef != NULL)
105                RemoveEventHandler(keyUpEventRef);
106               
107        if (keyModEventRef != NULL)
108                RemoveEventHandler(keyModEventRef);
109   
110        keyDownEventRef = NULL;
111        keyUpEventRef = NULL;
112        keyModEventRef = NULL;
113
114        OSStatus status;
115        // send both elements of downspec array... second index is for repeat events
116        if ( useRepeat )
117                status = InstallEventHandler( event, keyDownUPP, 2, DownSpec, this, &keyDownEventRef );
118        else
119                status = InstallEventHandler( event, keyDownUPP, 1, DownSpec, this, &keyDownEventRef );
120               
121        if (status != noErr)
122                OIS_EXCEPT( E_General, "MacKeyboard::_initialize >> Error loading KeyDown event handler" );
123
124        if (InstallEventHandler( event, keyUpUPP, 1, &UpSpec, this, &keyUpEventRef ) != noErr)
125                OIS_EXCEPT( E_General, "MacKeyboard::_initialize >> Error loading KeyUp event handler" );
126
127        if (InstallEventHandler( event, keyModUPP, 1, &ModSpec, this, &keyModEventRef ) != noErr )
128                OIS_EXCEPT( E_General, "MacKeyboard::_initialize >> Error loading Keymods event handler" );
129}
130
131//-------------------------------------------------------------------//
132bool MacKeyboard::isKeyDown( KeyCode key ) const
133{
134        return (bool)KeyBuffer[key];
135}
136
137
138//-------------------------------------------------------------------//
139void MacKeyboard::capture()
140{
141        // if not buffered just return, we update the unbuffered automatically
142        if ( !mBuffered || !mListener )
143                return;
144       
145        //If the mListener returns false, that means that we are probably deleted...
146        //send no more events and just leave as the this pointer is invalid now...
147        bool ret = true;
148       
149        // run through our event stack
150        eventStack::iterator cur_it;
151       
152        for (cur_it = pendingEvents.begin(); cur_it != pendingEvents.end(); cur_it++)
153        {
154               
155                if ( (*cur_it).Type == MAC_KEYDOWN || (*cur_it).Type == MAC_KEYREPEAT)
156                        mListener->keyPressed( (*cur_it).Event );
157                else if ( (*cur_it).Type == MAC_KEYUP )
158                        mListener->keyReleased( (*cur_it).Event );
159        }
160       
161        pendingEvents.clear();
162}
163
164
165//-------------------------------------------------------------------//
166std::string& MacKeyboard::getAsString( KeyCode key )
167{
168        getString = "";
169       
170        return getString;
171}
172
173//-------------------------------------------------------------------//
174void MacKeyboard::setBuffered( bool buffered )
175{
176        mBuffered = buffered;
177}
178
179#include <iostream>
180//-------------------------------------------------------------------//
181void MacKeyboard::_keyDownCallback( EventRef theEvent )
182{
183       
184        UInt32 virtualKey;
185        OSStatus status;
186       
187        unsigned int time = (unsigned int)GetEventTime(theEvent);
188       
189        status = GetEventParameter(theEvent,
190                                        'kcod',                 // get it in virtual keycode
191                                        typeUInt32, NULL,       // desired return type
192                                        sizeof(UInt32), NULL,   // bufsize
193                                        &virtualKey );
194       
195        KeyCode kc = keyConversion[virtualKey];
196
197        // record what kind of text we should pass the KeyEvent
198        UniChar text[10];
199        char macChar;
200       
201        if (mTextMode == Unicode)
202        {
203                //get string size
204                UInt32 stringsize;
205                status = GetEventParameter( theEvent, 'kuni', typeUnicodeText, NULL, sizeof(UniChar) * 10, &stringsize, &text );
206               
207                if(stringsize > 0)
208                {
209                        // for each unicode char, send an event
210                        stringsize--; // no termination char
211                        for ( int i = 0; i < stringsize; i++ )
212                        {
213                                injectEvent( kc, time, MAC_KEYDOWN, (unsigned int)text[i] );
214                        }
215                }
216        } 
217        else if (mTextMode == Ascii)
218        {
219                 
220                status = GetEventParameter( theEvent, 'kchr', typeChar, NULL, sizeof(char), NULL, &macChar );
221                injectEvent( kc, time, MAC_KEYDOWN, (unsigned int)macChar );
222        }
223        else
224        {
225                injectEvent( kc, time, MAC_KEYDOWN );
226        }
227}
228
229//-------------------------------------------------------------------//
230void MacKeyboard::_keyUpCallback( EventRef theEvent )
231{
232        UInt32 virtualKey;
233       
234        OSStatus status;
235        status = GetEventParameter( theEvent, kEventParamKeyCode, typeUInt32,
236                                                                NULL, sizeof(UInt32), NULL, &virtualKey );
237       
238        KeyCode kc = keyConversion[virtualKey];
239        injectEvent( kc, (int)GetEventTime(theEvent), MAC_KEYUP );
240       
241}
242
243//-------------------------------------------------------------------//
244void MacKeyboard::_modChangeCallback( EventRef theEvent )
245{
246        UInt32 mods;
247       
248        OSStatus status;
249        status = GetEventParameter( theEvent, kEventParamKeyModifiers,
250                                                                typeUInt32, NULL, sizeof(UInt32), NULL, &mods );
251       
252        // find the changed bit
253        UInt32 change = prevModMask ^ mods;
254        MacEventType newstate = ((change & prevModMask) > 0) ? MAC_KEYUP : MAC_KEYDOWN;
255        unsigned int time = (int)GetEventTime( theEvent );
256       
257        //cout << "preMask: " << hex << prevModMask << endl;
258        //cout << "ModMask: " << hex << mods << endl;
259        //cout << "Change:  " << hex << (change & prevModMask) << endl << endl;
260       
261        // TODO test modifiers on a full keyboard to check if different mask for left/right
262        switch (change)
263        {
264                case (shiftKey): // shift
265                        mModifiers &= (newstate == MAC_KEYDOWN) ? Shift : ~Shift;
266                        injectEvent( KC_LSHIFT, time, newstate );
267                        //injectEvent( KC_RSHIFT, time, newstate );
268                        break;
269                       
270                case (optionKey): // option (alt)
271                        mModifiers &= (newstate == MAC_KEYDOWN) ? Alt : -Alt;
272                        //injectEvent( KC_RMENU, time, newstate );
273                        injectEvent( KC_LMENU, time, newstate );
274                        break;
275                       
276                case (controlKey): // Ctrl
277                        mModifiers += (newstate == MAC_KEYDOWN) ? Ctrl : -Ctrl;
278                        //injectEvent( KC_RCONTROL, time, newstate );
279                        injectEvent( KC_LCONTROL, time, newstate );
280                        break;
281       
282                case (cmdKey): // apple
283                        //injectEvent( KC_RWIN, time, newstate );
284                        injectEvent( KC_LWIN, time, newstate );
285                        break;
286       
287                case (kEventKeyModifierFnMask): // fn key
288                        injectEvent( KC_APPS, time, newstate );
289                        break;
290                       
291                case (kEventKeyModifierNumLockMask): // numlock
292                        injectEvent( KC_NUMLOCK, time, newstate );
293                        break;
294                       
295                case (alphaLock): // caps lock
296                        injectEvent( KC_CAPITAL, time, newstate );
297                        break;
298        }
299       
300        prevModMask = mods;
301}
302
303//-------------------------------------------------------------------//
304void MacKeyboard::injectEvent( KeyCode kc, unsigned int time, MacEventType type, unsigned int txt )
305{
306        // set to 1 if this is either a keydown or repeat
307        KeyBuffer[kc] = ( type == MAC_KEYUP ) ? 0 : 1;
308       
309        if ( mBuffered && mListener )
310                pendingEvents.push_back( MacKeyStackEvent( KeyEvent(this, kc, txt), type) );
311}
312
313
314//-------------------------------------------------------------------//
315void MacKeyboard::copyKeyStates( char keys[256] ) const
316{
317        memcpy( keys, KeyBuffer, 256 );
318}
319
320
321
322//-------------------------------------------------------------------//
323void MacKeyboard::populateKeyConversion()
324{
325        // TODO finish the key mapping
326       
327        // Virtual Key Map to KeyCode
328        keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x12, KC_1));
329        keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x13, KC_2));
330        keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x14, KC_3));
331        keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x15, KC_4));
332        keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x17, KC_5));
333        keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x16, KC_6));
334        keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x1A, KC_7));
335        keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x1C, KC_8));
336        keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x19, KC_9));
337        keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x1D, KC_0));
338       
339        keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x33, KC_BACK));  // might be wrong
340       
341        keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x1B, KC_MINUS));
342        keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x18, KC_EQUALS));
343        keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x31, KC_SPACE));
344        keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x2B, KC_COMMA));
345        keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x2F, KC_PERIOD));
346       
347        keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x2A, KC_BACKSLASH));
348        keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x2C, KC_SLASH));
349        keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x21, KC_LBRACKET));
350        keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x1E, KC_RBRACKET));
351       
352        keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x35, KC_ESCAPE));
353        keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x39, KC_CAPITAL));
354       
355        keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x30, KC_TAB));
356        keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x24, KC_RETURN));  // double check return/enter
357       
358        //keyConversion.insert(VirtualtoOIS_KeyMap::value_type(XK_colon, KC_COLON));     // no colon?
359        keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x29, KC_SEMICOLON));
360        keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x27, KC_APOSTROPHE));
361        keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x32, KC_GRAVE));
362       
363        keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x0B, KC_B));
364        keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x00, KC_A));
365        keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x08, KC_C));
366        keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x02, KC_D));
367        keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x0E, KC_E));
368        keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x03, KC_F));
369        keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x05, KC_G));
370        keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x04, KC_H));
371        keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x22, KC_I));
372        keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x26, KC_J));
373        keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x28, KC_K));
374        keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x25, KC_L));
375        keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x2E, KC_M));
376        keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x2D, KC_N));
377        keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x1F, KC_O));
378        keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x23, KC_P));
379        keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x0C, KC_Q));
380        keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x0F, KC_R));
381        keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x01, KC_S));
382        keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x11, KC_T));
383        keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x20, KC_U));
384        keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x09, KC_V));
385        keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x0D, KC_W));
386        keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x07, KC_X));
387        keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x10, KC_Y));
388        keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x06, KC_Z));
389       
390        keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x7A, KC_F1));
391        keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x78, KC_F2));
392        keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x63, KC_F3));
393        keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x76, KC_F4));
394        keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x60, KC_F5));
395        keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x61, KC_F6));
396        keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x62, KC_F7));
397        keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x64, KC_F8));
398        keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x65, KC_F9));
399        keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x6D, KC_F10));
400        keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x67, KC_F11));
401        keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x6F, KC_F12));
402        keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x69, KC_F13));
403        keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x6B, KC_F14));
404        keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x71, KC_F15));
405       
406        //Keypad
407        keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x52, KC_NUMPAD0));
408        keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x53, KC_NUMPAD1));
409        keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x54, KC_NUMPAD2));
410        keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x55, KC_NUMPAD3));
411        keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x56, KC_NUMPAD4));
412        keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x57, KC_NUMPAD5));
413        keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x58, KC_NUMPAD6));
414        keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x59, KC_NUMPAD7));
415        keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x5B, KC_NUMPAD8));
416        keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x5C, KC_NUMPAD9));
417        keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x45, KC_ADD));
418        keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x4E, KC_SUBTRACT));
419        keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x41, KC_DECIMAL));
420        keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x51, KC_NUMPADEQUALS));
421        keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x4B, KC_DIVIDE));
422        keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x43, KC_MULTIPLY));
423        keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x4C, KC_NUMPADENTER));
424       
425        //Keypad with numlock off
426        //keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x73, KC_NUMPAD7));  // not sure of these
427        //keyConversion.insert(VirtualtoOIS_KeyMap::value_type(XK_KP_Up, KC_NUMPAD8)); // check on a non-laptop
428        //keyConversion.insert(VirtualtoOIS_KeyMap::value_type(XK_KP_Page_Up, KC_NUMPAD9));
429        //keyConversion.insert(VirtualtoOIS_KeyMap::value_type(XK_KP_Left, KC_NUMPAD4));
430        //keyConversion.insert(VirtualtoOIS_KeyMap::value_type(XK_KP_Begin, KC_NUMPAD5));
431        //keyConversion.insert(VirtualtoOIS_KeyMap::value_type(XK_KP_Right, KC_NUMPAD6));
432        //keyConversion.insert(VirtualtoOIS_KeyMap::value_type(XK_KP_End, KC_NUMPAD1));
433        //keyConversion.insert(VirtualtoOIS_KeyMap::value_type(XK_KP_Down, KC_NUMPAD2));
434        //keyConversion.insert(VirtualtoOIS_KeyMap::value_type(XK_KP_Page_Down, KC_NUMPAD3));
435        //keyConversion.insert(VirtualtoOIS_KeyMap::value_type(XK_KP_Insert, KC_NUMPAD0));
436        //keyConversion.insert(VirtualtoOIS_KeyMap::value_type(XK_KP_Delete, KC_DECIMAL));
437       
438        keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x7E, KC_UP));
439        keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x7D, KC_DOWN));
440        keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x7B, KC_LEFT));
441        keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x7C, KC_RIGHT));
442       
443        keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x74, KC_PGUP));
444        keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x79, KC_PGDOWN));
445        keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x73, KC_HOME));
446        keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x77, KC_END));
447       
448        //keyConversion.insert(VirtualtoOIS_KeyMap::value_type(XK_Print, KC_SYSRQ));            // ??
449        //keyConversion.insert(VirtualtoOIS_KeyMap::value_type(XK_Scroll_Lock, KC_SCROLL)); // ??
450        //keyConversion.insert(VirtualtoOIS_KeyMap::value_type(XK_Pause, KC_PAUSE));            // ??
451       
452       
453        //keyConversion.insert(VirtualtoOIS_KeyMap::value_type(XK_Insert, KC_INSERT));    // ??
454        keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x75, KC_DELETE)); // del under help key?
455}
456
457
458
459
Note: See TracBrowser for help on using the repository browser.