]> icculus.org git repositories - icculus/iodoom3.git/blob - neo/sys/osx/macosx_event.mm
Various Mac OS X tweaks to get this to build. Probably breaking things.
[icculus/iodoom3.git] / neo / sys / osx / macosx_event.mm
1 /*
2 ===========================================================================
3
4 Doom 3 GPL Source Code
5 Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company. 
6
7 This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).  
8
9 Doom 3 Source Code is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13
14 Doom 3 Source Code is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with Doom 3 Source Code.  If not, see <http://www.gnu.org/licenses/>.
21
22 In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code.  If not, please request a copy in writing from id Software at the address below.
23
24 If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
25
26 ===========================================================================
27 */
28
29 // -*- mode: objc -*-
30 #import "../../idlib/precompiled.h"
31
32 #import "macosx_local.h"
33 #import "macosx_sys.h"
34
35 #import <AppKit/NSCursor.h>
36 #import <AppKit/NSWindow.h>
37 #import <AppKit/NSScreen.h>
38 #import <AppKit/NSApplication.h>
39 #import <AppKit/NSGraphicsContext.h>
40 #import <AppKit/NSEvent.h>
41
42 #import <Foundation/NSArray.h>
43 #import <Foundation/NSString.h>
44 #import <Foundation/NSRunLoop.h>
45 #import <Carbon/Carbon.h>
46
47 #import <ApplicationServices/ApplicationServices.h>
48
49 #import <sys/types.h>
50 #import <sys/time.h>
51 #import <unistd.h>
52 #include <pthread.h>
53
54 static NSDate  *distantPast             = NULL;
55 static bool             inputActive             = false;
56 static bool             mouseActive             = false;
57 static bool             inputRectValid  = NO;
58 static CGRect   inputRect;
59 static const void *sKLuchrData  = NULL;
60 static const void *sKLKCHRData  = NULL;
61
62 int     vkeyToDoom3Key[256] = {
63         /*0x00*/        'a', 's', 'd', 'f', 'h', 'g', 'z', 'x',
64         /*0x08*/        'c', 'v', '?', 'b', 'q', 'w', 'e', 'r',
65         /*0x10*/        'y', 't', '1', '2', '3', '4', '6', '5',
66         /*0x18*/        '=', '9', '7', '-', '8', '0', ']', 'o',
67         /*0x20*/        'u', '[', 'i', 'p', K_ENTER, 'l', 'j', '\'',
68         /*0x28*/        'k', ';', '\\', ',', '/', 'n', 'm', '.',
69         /*0x30*/        K_TAB, K_SPACE, '`', K_BACKSPACE, '?', K_ESCAPE, '?', K_COMMAND,
70         /*0x38*/        K_SHIFT, K_CAPSLOCK, K_ALT, K_CTRL, '?', '?', '?', '?',
71         /*0x40*/        '?', K_KP_DEL, '?', K_KP_STAR, '?', K_KP_PLUS, '?', K_KP_NUMLOCK,
72         /*0x48*/        '?', '?', '?', K_KP_SLASH, K_KP_ENTER, '?', K_KP_MINUS, '?',
73         /*0x50*/        '?', K_KP_EQUALS, K_KP_INS, K_KP_END, K_KP_DOWNARROW, K_KP_PGDN, K_KP_LEFTARROW, K_KP_5,
74         /*0x58*/        K_KP_RIGHTARROW, K_KP_HOME, '?', K_KP_UPARROW, K_KP_PGUP, '?', '?', '?',
75         /*0x60*/        K_F5, K_F6, K_F7, K_F3, K_F8, K_F9, '?', K_F11,
76         /*0x68*/        '?', K_PRINT_SCR, '?', K_F14, '?', K_F10, '?', K_F12,
77         /*0x70*/        '?', K_F15, K_INS, K_HOME, K_PGUP, K_DEL, K_F4, K_END,  
78         /*0x78*/        K_F2, K_PGDN, K_F1, K_LEFTARROW, K_RIGHTARROW, K_DOWNARROW, K_UPARROW, K_POWER
79 };
80
81 int     vkeyToDoom3Key_French[256] = {
82         /*0x00*/        'q',    's',            'd',    'f',            'h',            'g',            'w',            'x',
83         /*0x08*/        'c',    'v',            '?',    'b',            'a',            'z',            'e',            'r',
84         /*0x10*/        'y',    't',            '1',    '2',            '3',            '4',            '6',            '5',
85         /*0x18*/        '-',    '9',            '7',    ')',            '8',            '0',            '$',            'o',
86         /*0x20*/        'u',    '^',            'i',    'p',            K_ENTER,        'l',            'j',            'ù',
87         /*0x28*/        'k',    'm',            0x60,   ';',                    '=',    'n',            ',',                    ':',
88         /*0x30*/        K_TAB, K_SPACE, '<', K_BACKSPACE, '?', K_ESCAPE, '?', K_COMMAND,
89         /*0x38*/        K_SHIFT, K_CAPSLOCK, K_ALT, K_CTRL, '?', '?', '?', '?',
90         /*0x40*/        '?', K_KP_DEL, '?', K_KP_STAR, '?', K_KP_PLUS, '?', K_KP_NUMLOCK,
91         /*0x48*/        '?', '?', '?', K_KP_SLASH, K_KP_ENTER, '?', K_KP_MINUS, '?',
92         /*0x50*/        '?', K_KP_EQUALS, K_KP_INS, K_KP_END, K_KP_DOWNARROW, K_KP_PGDN, K_KP_LEFTARROW, K_KP_5,
93         /*0x58*/        K_KP_RIGHTARROW, K_KP_HOME, '?', K_KP_UPARROW, K_KP_PGUP, '?', '?', '?',
94         /*0x60*/        K_F5, K_F6, K_F7, K_F3, K_F8, K_F9, '?', K_F11,
95         /*0x68*/        '?', K_PRINT_SCR, '?', K_F14, '?', K_F10, '?', K_F12,
96         /*0x70*/        '?', K_F15, K_INS, K_HOME, K_PGUP, K_DEL, K_F4, K_END,  
97         /*0x78*/        K_F2, K_PGDN, K_F1, K_LEFTARROW, K_RIGHTARROW, K_DOWNARROW, K_UPARROW, K_POWER
98 };
99
100 int     vkeyToDoom3Key_German[256] = {
101         /*0x00*/        'a',    's',            'd',    'f',            'h',            'g',            'y',            'x',
102         /*0x08*/        'c',    'v',            '?',    'b',            'q',            'w',            'e',            'r',
103         /*0x10*/        'z',    't',            '1',    '2',            '3',            '4',            '6',            '5',
104         /*0x18*/        '«',    '9',            '7',    '-',            '8',            '0',            '+',            'o',
105         /*0x20*/        'u',    '[',            'i',    'p',            K_ENTER,        'l',            'j',            '\'',
106         /*0x28*/        'k',    ';',            '#',    ',',            '-',            'n',            'm',            '.',
107         /*0x30*/        K_TAB, K_SPACE, '`', K_BACKSPACE, '?', K_ESCAPE, '?', K_COMMAND,
108         /*0x38*/        K_SHIFT, K_CAPSLOCK, K_ALT, K_CTRL, '?', '?', '?', '?',
109         /*0x40*/        '?', K_KP_DEL, '?', K_KP_STAR, '?', K_KP_PLUS, '?', K_KP_NUMLOCK,
110         /*0x48*/        '?', '?', '?', K_KP_SLASH, K_KP_ENTER, '?', K_KP_MINUS, '?',
111         /*0x50*/        '?', K_KP_EQUALS, K_KP_INS, K_KP_END, K_KP_DOWNARROW, K_KP_PGDN, K_KP_LEFTARROW, K_KP_5,
112         /*0x58*/        K_KP_RIGHTARROW, K_KP_HOME, '?', K_KP_UPARROW, K_KP_PGUP, '?', '?', '?',
113         /*0x60*/        K_F5, K_F6, K_F7, K_F3, K_F8, K_F9, '?', K_F11,
114         /*0x68*/        '?', K_PRINT_SCR, '?', K_F14, '?', K_F10, '?', K_F12,
115         /*0x70*/        '?', K_F15, K_INS, K_HOME, K_PGUP, K_DEL, K_F4, K_END,  
116         /*0x78*/        K_F2, K_PGDN, K_F1, K_LEFTARROW, K_RIGHTARROW, K_DOWNARROW, K_UPARROW, K_POWER
117 };
118
119 static const int *vkeyTable = vkeyToDoom3Key;   
120
121 /*
122  ===========
123  Sys_InitScanTable
124  ===========
125  */
126 void Sys_InitScanTable( void ) {
127         KeyboardLayoutRef kbLayout;
128         
129         idStr lang = cvarSystem->GetCVarString( "sys_lang" );
130         if ( lang.Length() == 0 ) {
131                 lang = "english";
132         }
133
134         if ( lang.Icmp( "english" ) == 0 ) {
135                 vkeyTable = vkeyToDoom3Key;
136         } else if ( lang.Icmp( "french" ) == 0 ) {
137                 vkeyTable = vkeyToDoom3Key_French;
138         } else if ( lang.Icmp( "german" ) == 0 ) {
139                 vkeyTable = vkeyToDoom3Key_German;
140         }
141
142         if ( KLGetCurrentKeyboardLayout( &kbLayout )  == 0 ) {
143                 if ( KLGetKeyboardLayoutProperty( kbLayout, kKLuchrData, &sKLuchrData ) ) {
144                         common->Warning("KLGetKeyboardLayoutProperty failed");
145                 }
146                 if ( !sKLuchrData ) {
147                         if ( KLGetKeyboardLayoutProperty( kbLayout, kKLKCHRData, &sKLKCHRData ) ) {
148                                 common->Warning("KLGetKeyboardLayoutProperty failed");
149                         }
150                 }
151         }
152         if ( !sKLuchrData && !sKLKCHRData ) {
153                 common->Warning("Keyboard input initialziation failed");
154         }
155 }
156
157 void Sys_InitInput( void ) {
158         common->Printf( "------- Input Initialization -------\n" );
159         
160         if ( !distantPast ) {
161                 distantPast = [ [ NSDate distantPast ] retain ];
162         }
163
164     IN_ActivateMouse();
165
166         inputActive = true;
167 }
168
169 void Sys_ShutdownInput( void ) {
170         common->Printf( "------- Input Shutdown -------\n" );
171
172     if ( !inputActive ) {
173         return;
174     }
175     inputActive = false;
176     if ( mouseActive ) {
177                 IN_DeactivateMouse();
178     }
179         
180     common->Printf( "------------------------------\n" );
181 }
182
183 void processMouseMovedEvent( NSEvent *mouseMovedEvent ) {
184     CGMouseDelta dx, dy;
185     
186     if ( !mouseActive ) {
187         return;
188         }
189
190 #if 0
191
192 #define ACT_LIKE_WINDOWS
193 #ifdef ACT_LIKE_WINDOWS
194     cvar_t *in_mouseLowEndSlope = Cvar_Get("in_mouseLowEndSlope", "3.5", CVAR_ARCHIVE);
195     if (in_mouseLowEndSlope->value < 1) {
196         Cvar_Set("in_mouseLowEndSlope", "1");
197     }
198 #else
199     cvar_t *in_mouseLowEndSlope = Cvar_Get("in_mouseLowEndSlope", "1", CVAR_ARCHIVE);
200     if (in_mouseLowEndSlope->value < 1) {
201         Cvar_Set("in_mouseLowEndSlope", "1");
202     }
203 #endif
204
205     cvar_t *in_mouseHighEndCutoff = Cvar_Get("in_mouseHighEndCutoff", "20", CVAR_ARCHIVE);
206     if (in_mouseLowEndSlope->value < 1) {
207         Cvar_Set("in_mouseHighEndCutoff", "1");
208     }
209
210 #endif
211
212     CGGetLastMouseDelta(&dx, &dy);
213     
214     if ( dx || dy ) {
215   #if 0 // this is be handled by the mouse driver clean me out later       
216       CGMouseDelta distSqr;
217         float m0, N;
218         
219         distSqr = dx * dx + dy * dy;
220         //Com_Printf("distSqr = %d\n", distSqr);
221
222         /* This code is here to help people that like the feel of the Logitech USB Gaming Mouse with the Win98 drivers.  By empirical testing, the Windows drivers seem to be more heavily accelerated at the low end of the curve. */
223         //N = in_mouseHighEndCutoff->value;
224                 N = 1;
225
226         if (distSqr < N*N) {
227             float dist, accel, scale;
228             
229             //m0 = in_mouseLowEndSlope->value;
230                         m0 = 1;
231             dist = sqrt(distSqr);
232             accel = (((m0 - 1.0)/(N*N) * dist + (2.0 - 2.0*m0)/N) * dist + m0) * dist;
233             
234             scale = accel / dist;
235             //Com_Printf("dx = %d, dy = %d, dist = %f, accel = %f, scale = %f\n", dx, dy, dist, accel, scale);
236
237             dx *= scale;
238             dy *= scale;
239         }
240 #endif
241         Posix_QueEvent( SE_MOUSE, dx, dy, 0, NULL );
242                 Posix_AddMousePollEvent( M_DELTAX, dx );
243                 Posix_AddMousePollEvent( M_DELTAY, dy );
244     }
245 }
246
247 inline bool OSX_LookupCharacter(unsigned short vkey, unsigned int modifiers, bool keyDownFlag, unsigned char *outChar)
248 {
249         UInt32 translated;
250         UInt32 deadKeyState = 0;
251         UniChar unicodeString[16];
252         UniCharCount actualStringLength = 0;
253         static UInt32 keyTranslateState = 0;
254         
255         // Only want character if Translate() returns a single character
256         if ( sKLuchrData ) {
257                 UCKeyTranslate( (UCKeyboardLayout*)sKLuchrData, vkey, keyDownFlag ? kUCKeyActionDown : kUCKeyActionUp, modifiers,
258                                                 LMGetKbdType(), 0, &deadKeyState, 16, &actualStringLength, unicodeString );
259
260                 if ( actualStringLength == 1 ) {
261                         *outChar = (unsigned char)unicodeString[0];
262                         return true;
263                 }
264         }
265         else if ( sKLKCHRData ) {
266                 translated = KeyTranslate( sKLKCHRData, vkey, &keyTranslateState );
267                 if ( ( translated & 0x00ff0000 ) == 0 ) {
268                         *outChar = translated & 0xff;
269                         return true;
270                 }
271         }
272         return false;
273 }
274
275 void OSX_ProcessKeyEvent( NSEvent *keyEvent, bool keyDownFlag ) {
276         unsigned char character;
277         unsigned int modifiers = 0;
278         unsigned short vkey = [ keyEvent keyCode ];
279
280         if ( [ keyEvent modifierFlags ] & NSAlphaShiftKeyMask )
281                 modifiers |= alphaLock;
282         if ( [ keyEvent modifierFlags ] & NSShiftKeyMask )
283                 modifiers |= shiftKey;
284         if ( [ keyEvent modifierFlags ] & NSControlKeyMask )
285                 modifiers |= controlKey;
286         if ( [ keyEvent modifierFlags ] & NSAlternateKeyMask )
287                 modifiers |= optionKey;
288         if ( [ keyEvent modifierFlags ] & NSCommandKeyMask )
289                 modifiers |= cmdKey;
290         modifiers >>= 8;
291                                 
292         int doomKey = (unsigned char)vkeyTable[vkey];
293         Posix_QueEvent( SE_KEY, doomKey, keyDownFlag, 0, NULL );
294         if ( keyDownFlag ) {
295                 if ( OSX_LookupCharacter(vkey, modifiers, keyDownFlag, &character ) && 
296                          character != Sys_GetConsoleKey( false ) && character != Sys_GetConsoleKey( true ) ) {
297                         Posix_QueEvent( SE_CHAR, character, 0, 0, NULL);
298                 }
299         }
300         Posix_AddKeyboardPollEvent( doomKey, keyDownFlag );
301         
302         return;
303 }
304
305 void sendEventForMaskChangeInFlags( int quakeKey, unsigned int modifierMask, unsigned int oldModifierFlags, unsigned int newModifierFlags ) {
306     bool oldHadModifier, newHasModifier;
307
308     oldHadModifier = (oldModifierFlags & modifierMask) != 0;
309     newHasModifier = (newModifierFlags & modifierMask) != 0;
310     if (oldHadModifier != newHasModifier) {
311         //NSLog(@"Key %d posted for modifier mask modifierMask", quakeKey);
312         Posix_QueEvent( SE_KEY, quakeKey, newHasModifier, 0, NULL);
313                 Posix_AddKeyboardPollEvent( quakeKey, newHasModifier );
314     }
315 }
316
317 void processFlagsChangedEvent( NSEvent *flagsChangedEvent ) {
318     static int  oldModifierFlags;
319     int                 newModifierFlags;
320
321     newModifierFlags = [flagsChangedEvent modifierFlags];
322     sendEventForMaskChangeInFlags( K_ALT, NSAlternateKeyMask, oldModifierFlags, newModifierFlags );
323     sendEventForMaskChangeInFlags( K_CTRL, NSControlKeyMask, oldModifierFlags, newModifierFlags );
324     sendEventForMaskChangeInFlags( K_SHIFT, NSShiftKeyMask, oldModifierFlags, newModifierFlags );
325     oldModifierFlags = newModifierFlags;
326 }
327
328 void processSystemDefinedEvent( NSEvent *systemDefinedEvent ) {
329     static int oldButtons = 0;
330     int buttonsDelta;
331     int buttons;
332     int isDown;
333     
334     if ( [systemDefinedEvent subtype] == 7 ) {
335
336         if ( !mouseActive ) {
337             return;
338                 }        
339     
340                 buttons = [systemDefinedEvent data2];
341         buttonsDelta = oldButtons ^ buttons;
342         
343         //common->Printf( "uberbuttons: %08lx %08lx\n", buttonsDelta, buttons );
344
345                 if (buttonsDelta & 1) {
346             isDown = buttons & 1;
347             Posix_QueEvent( SE_KEY, K_MOUSE1, isDown, 0, NULL);
348                         Posix_AddMousePollEvent( M_ACTION1, isDown );
349                 }
350
351                 if (buttonsDelta & 2) {
352             isDown = buttons & 2;
353             Posix_QueEvent( SE_KEY, K_MOUSE2, isDown, 0, NULL);
354                         Posix_AddMousePollEvent( M_ACTION2, isDown );
355                 }
356
357                 if (buttonsDelta & 4) {
358             isDown = buttons & 4;
359             Posix_QueEvent( SE_KEY, K_MOUSE3, isDown, 0, NULL);
360                         Posix_AddMousePollEvent( M_ACTION3, isDown );
361                 }
362
363                 if (buttonsDelta & 8) {
364             isDown = buttons & 8;
365             Posix_QueEvent( SE_KEY, K_MOUSE4, isDown, 0, NULL);
366                         Posix_AddMousePollEvent( M_ACTION4, isDown );
367         }
368         
369                 if (buttonsDelta & 16) {
370             isDown = buttons & 16;
371             Posix_QueEvent( SE_KEY, K_MOUSE5, isDown, 0, NULL);
372                         Posix_AddMousePollEvent( M_ACTION5, isDown );
373                 }
374         
375         oldButtons = buttons;
376     }
377 }
378
379 void processEvent( NSEvent *event ) {
380         NSEventType eventType;
381
382         if ( !inputActive ) {
383                 return;
384         }
385
386         eventType = [ event type ];
387
388         switch ( eventType ) {
389                 // These four event types are ignored since we do all of our mouse down/up process via the uber-mouse system defined event.      We have to accept these events however since they get enqueued and the queue will fill up if we don't.
390         case NSLeftMouseDown:
391         case NSLeftMouseUp:
392         case NSRightMouseDown:
393         case NSRightMouseUp:
394                 //NSLog( @"ignore simple mouse event %@", event );
395                 return;         
396         case NSMouseMoved:
397         case NSLeftMouseDragged:
398         case NSRightMouseDragged:
399                 processMouseMovedEvent( event );
400                 return;
401         case NSKeyDown:
402                 // Send ALL command key-ups to Quake, but not command key-downs, otherwise if the user hits a key, presses command, and lets up on the key, the key-up won't register.
403                 if ( [ event modifierFlags ] & NSCommandKeyMask ) {
404                         NSLog( @"command key up ignored: %@", event );
405                         break;
406                 }
407         case NSKeyUp:
408                 OSX_ProcessKeyEvent( event, eventType == NSKeyDown );
409                 return;
410         case NSFlagsChanged:
411                 processFlagsChangedEvent( event );
412                 return;
413         case NSSystemDefined:
414                 processSystemDefinedEvent( event );
415                 return;
416         case NSScrollWheel:
417                 if ([event deltaY] < 0.0) {
418                         Posix_QueEvent( SE_KEY, K_MWHEELDOWN, true, 0, NULL );
419                         Posix_QueEvent( SE_KEY, K_MWHEELDOWN, false, 0, NULL );
420                         Posix_AddMousePollEvent( M_DELTAZ, -1 );
421                 } else {
422                         Posix_QueEvent( SE_KEY, K_MWHEELUP, true, 0, NULL );
423                         Posix_QueEvent( SE_KEY, K_MWHEELUP, false, 0, NULL );
424                         Posix_AddMousePollEvent( M_DELTAZ, 1 );
425                 }
426                 return;
427         default:
428                 //NSLog( @"handle event %@", event );
429                 break;
430         }
431     [NSApp sendEvent:event];
432 }
433
434 void Posix_PollInput( void ) {
435     NSEvent *event;
436     unsigned int eventMask;
437     
438     eventMask = NSAnyEventMask;
439      
440     while ( ( event = [ NSApp nextEventMatchingMask: eventMask
441                                                           untilDate: distantPast
442                                                           inMode: NSDefaultRunLoopMode
443                                                           dequeue:YES ] ) ) {
444                 processEvent( event );
445         }
446 }
447
448 void Sys_PreventMouseMovement( CGPoint point ) {
449     CGEventErr err;
450
451     //common->Printf( "**** Calling CGAssociateMouseAndMouseCursorPosition(false)\n" );
452     err = CGAssociateMouseAndMouseCursorPosition( false );
453     if ( err != CGEventNoErr ) {
454         common->Error( "Could not disable mouse movement, CGAssociateMouseAndMouseCursorPosition returned %d\n", err );
455     }
456
457     // Put the mouse in the position we want to leave it at
458     err = CGWarpMouseCursorPosition( point );
459     if ( err != CGEventNoErr ) {
460         common->Error( "Could not disable mouse movement, CGWarpMouseCursorPosition returned %d\n", err );
461     }
462 }
463
464 void Sys_ReenableMouseMovement() {
465     CGEventErr err;
466
467     //common->Printf( "**** Calling CGAssociateMouseAndMouseCursorPosition(true)\n" );
468     err = CGAssociateMouseAndMouseCursorPosition( true );
469     if ( err != CGEventNoErr ) {
470         common->Error( "Could not reenable mouse movement, CGAssociateMouseAndMouseCursorPosition returned %d\n", err );
471     }
472
473     // Leave the mouse where it was -- don't warp here.
474 }
475
476 void Sys_LockMouseInInputRect(CGRect rect) {
477     CGPoint center;
478
479     center.x = rect.origin.x + rect.size.width / 2.0;
480     center.y = rect.origin.y + rect.size.height / 2.0;
481
482     // Now, put the mouse in the middle of the input rect (anywhere over it would do)
483     // and don't allow it to move.  This means that the user won't be able to accidentally
484     // select another application.
485     Sys_PreventMouseMovement(center);
486 }
487
488 void Sys_SetMouseInputRect(CGRect newRect) {
489     inputRectValid = YES;
490     inputRect = newRect;
491
492     if ( mouseActive ) {
493         Sys_LockMouseInInputRect( inputRect );
494         }
495 }
496
497 void IN_ActivateMouse( void ) {
498     if ( mouseActive ) {
499         return;
500     }
501     if ( inputRectValid ) {
502         // Make sure that if window moved we don't hose the user...
503         Sys_UpdateWindowMouseInputRect();
504     }
505     Sys_LockMouseInInputRect( inputRect );
506     CGDisplayHideCursor( Sys_DisplayToUse() );
507     mouseActive = true;
508 }
509
510 void IN_DeactivateMouse( void ) {
511     if ( !mouseActive ) {
512         return;
513     }
514     Sys_ReenableMouseMovement();
515     CGDisplayShowCursor( Sys_DisplayToUse() );
516     mouseActive = false;
517 }
518
519 /*
520 ===============
521 Sys_MapCharForKey
522 ===============
523 */
524 unsigned char Sys_MapCharForKey( int key ) {
525         return (unsigned char)key;
526 }
527
528 /*
529  ===============
530  Sys_GetConsoleKey
531  ===============
532  */
533 unsigned char Sys_GetConsoleKey( bool shifted ) {
534         if ( vkeyTable == vkeyToDoom3Key_French ) {
535                 return shifted ? '>' : '<';
536         }
537         else {
538                 return shifted ? '~' : '`';
539         }
540
541 }
542