2 SDL - Simple DirectMedia Layer
3 Copyright (C) 1997-2009 Sam Lantinga
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public
16 License along with this library; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22 #include "SDL_config.h"
24 /* CAUTION!!!! If you modify this file, check ../windib/SDL_sysevents.c */
29 #include "SDL_events.h"
30 #include "SDL_video.h"
31 #include "SDL_syswm.h"
32 #include "../../events/SDL_sysevents.h"
33 #include "../../events/SDL_events_c.h"
34 #include "../wincommon/SDL_lowvideo.h"
35 #include "SDL_dx5video.h"
42 #define NO_GETKEYBOARDSTATE
45 /* The keyboard and mouse device input */
47 #define INPUT_QSIZE 512 /* Buffer up to 512 input messages */
49 static LPDIRECTINPUT dinput = NULL;
50 static LPDIRECTINPUTDEVICE2 SDL_DIdev[MAX_INPUTS];
51 static HANDLE SDL_DIevt[MAX_INPUTS];
52 static void (*SDL_DIfun[MAX_INPUTS])(const int, DIDEVICEOBJECTDATA *);
53 static int SDL_DIndev = 0;
54 static int mouse_lost;
55 static int mouse_pressed;
56 static int mouse_buttons_swapped = 0;
58 /* The translation table from a DirectInput scancode to an SDL keysym */
59 static SDLKey DIK_keymap[256];
60 static SDL_keysym *TranslateKey(UINT scancode, SDL_keysym *keysym, int pressed);
62 /* DJM: If the user setup the window for us, we want to save his window proc,
63 and give him a chance to handle some messages. */
65 #define WNDPROCTYPE WNDPROC
67 #define WNDPROCTYPE FARPROC
69 static WNDPROCTYPE userWindowProc = NULL;
71 static HWND GetTopLevelParent(HWND hWnd)
76 hParentWnd = GetParent(hWnd);
77 if (hParentWnd == NULL)
84 /* Convert a DirectInput return code to a text message */
85 static void SetDIerror(char *function, int code)
88 static char errbuf[1024];
93 error = "Undefined error!";
95 case DIERR_OLDDIRECTINPUTVERSION:
96 error = "Your version of DirectInput needs upgrading";
98 case DIERR_INVALIDPARAM:
99 error = "Invalid parameters";
101 case DIERR_OUTOFMEMORY:
102 error = "Out of memory";
104 case DIERR_DEVICENOTREG:
105 error = "Device not registered";
107 case DIERR_NOINTERFACE:
108 error = "Interface not supported";
110 case DIERR_NOTINITIALIZED:
111 error = "Device not initialized";
114 SDL_snprintf(errbuf, SDL_arraysize(errbuf),
115 "%s: Unknown DirectInput error: 0x%x",
120 SDL_snprintf(errbuf, SDL_arraysize(errbuf), "%s: %s", function, error);
122 SDL_SetError("%s", errbuf);
126 /* Initialize DirectInput
127 Note: If NONEXCLUSIVE access is requested for the devices, normal
128 windows input messages will continue to be generated for that
129 input device, in addition to DirectInput messages.
131 static void handle_keyboard(const int numevents, DIDEVICEOBJECTDATA *events);
132 static void handle_mouse(const int numevents, DIDEVICEOBJECTDATA *events);
136 LPCDIDATAFORMAT format;
139 void (*fun)(const int numevents, DIDEVICEOBJECTDATA *events);
142 &GUID_SysKeyboard, &c_dfDIKeyboard,
143 (DISCL_FOREGROUND|DISCL_NONEXCLUSIVE),
144 (DISCL_FOREGROUND|DISCL_NONEXCLUSIVE), handle_keyboard },
147 #if DIRECTINPUT_VERSION >= 0x700
152 (DISCL_FOREGROUND|DISCL_NONEXCLUSIVE),
153 (DISCL_FOREGROUND|DISCL_NONEXCLUSIVE), handle_mouse },
154 { NULL, NULL, NULL, 0, 0, NULL }
157 static int DX5_DInputInit(_THIS)
160 LPDIRECTINPUTDEVICE device;
165 /* Create the DirectInput object */
166 result = DInputCreate(SDL_Instance, DIRECTINPUT_VERSION,
168 if ( result != DI_OK ) {
169 SetDIerror("DirectInputCreate", result);
173 /* Create all of our registered input devices */
175 for ( i=0; inputs[i].name; ++i ) {
176 /* Create the DirectInput device */
177 result = IDirectInput_CreateDevice(dinput, inputs[i].guid,
179 if ( result != DI_OK ) {
180 SetDIerror("DirectInput::CreateDevice", result);
183 result = IDirectInputDevice_QueryInterface(device,
184 &IID_IDirectInputDevice2, (LPVOID *)&SDL_DIdev[i]);
185 IDirectInputDevice_Release(device);
186 if ( result != DI_OK ) {
187 SetDIerror("DirectInputDevice::QueryInterface", result);
190 topwnd = GetTopLevelParent(SDL_Window);
191 result = IDirectInputDevice2_SetCooperativeLevel(SDL_DIdev[i],
192 topwnd, inputs[i].win_level);
193 if ( result != DI_OK ) {
194 SetDIerror("DirectInputDevice::SetCooperativeLevel",
198 result = IDirectInputDevice2_SetDataFormat(SDL_DIdev[i],
200 if ( result != DI_OK ) {
201 SetDIerror("DirectInputDevice::SetDataFormat", result);
205 /* Set buffered input -- we aren't polling */
206 SDL_memset(&dipdw, 0, sizeof(dipdw));
207 dipdw.diph.dwSize = sizeof(dipdw);
208 dipdw.diph.dwHeaderSize = sizeof(dipdw.diph);
209 dipdw.diph.dwObj = 0;
210 dipdw.diph.dwHow = DIPH_DEVICE;
211 dipdw.dwData = INPUT_QSIZE;
212 result = IDirectInputDevice2_SetProperty(SDL_DIdev[i],
213 DIPROP_BUFFERSIZE, &dipdw.diph);
214 if ( result != DI_OK ) {
215 SetDIerror("DirectInputDevice::SetProperty", result);
219 /* Create an event to be signaled when input is ready */
220 SDL_DIevt[i] = CreateEvent(NULL, FALSE, FALSE, NULL);
221 if ( SDL_DIevt[i] == NULL ) {
222 SDL_SetError("Couldn't create DirectInput event");
225 result = IDirectInputDevice2_SetEventNotification(SDL_DIdev[i],
227 if ( result != DI_OK ) {
228 SetDIerror("DirectInputDevice::SetEventNotification",
232 SDL_DIfun[i] = inputs[i].fun;
234 /* Acquire the device for input */
235 IDirectInputDevice2_Acquire(SDL_DIdev[i]);
237 /* Increment the number of devices we have */
241 mouse_buttons_swapped = GetSystemMetrics(SM_SWAPBUTTON);
243 /* DirectInput is ready! */
247 /* Clean up DirectInput */
248 static void DX5_DInputQuit(_THIS)
252 if ( dinput != NULL ) {
253 /* Close and release all DirectInput devices */
254 for ( i=0; i<MAX_INPUTS; ++i ) {
255 if ( SDL_DIdev[i] != NULL ) {
256 IDirectInputDevice2_Unacquire(SDL_DIdev[i]);
257 IDirectInputDevice2_SetEventNotification(
259 if ( SDL_DIevt[i] != NULL ) {
260 CloseHandle(SDL_DIevt[i]);
263 IDirectInputDevice2_Release(SDL_DIdev[i]);
269 /* Release DirectInput */
270 IDirectInput_Release(dinput);
275 /* Flag to tell SDL whether or not we queued an event */
276 static int posted = 0;
278 /* Input event handler functions */
279 static void handle_keyboard(const int numevents, DIDEVICEOBJECTDATA *keybuf)
284 /* Translate keyboard messages */
285 for ( i=0; i<numevents; ++i ) {
286 if ( keybuf[i].dwData & 0x80 ) {
287 posted = SDL_PrivateKeyboard(SDL_PRESSED,
288 TranslateKey(keybuf[i].dwOfs, &keysym, 1));
290 posted = SDL_PrivateKeyboard(SDL_RELEASED,
291 TranslateKey(keybuf[i].dwOfs, &keysym, 0));
296 static void post_mouse_motion(int relative, Sint16 x, Sint16 y)
298 extern int mouse_relative;
300 if ( (SDL_GetAppState() & (SDL_APPINPUTFOCUS|SDL_APPMOUSEFOCUS)) ==
301 (SDL_APPINPUTFOCUS|SDL_APPMOUSEFOCUS) ) {
302 posted = SDL_PrivateMouseMotion(
305 if ( !mouse_relative ) {
306 /* As DirectInput reads raw device coordinates, it has no notion of
307 * cursors or absolute position. We must assume responsibility for
308 * keeping track of this. */
309 int current_x, current_y;
315 /* Get the current cursor position */
316 SDL_GetMouseState(¤t_x, ¤t_y);
317 cursor.x = current_x;
318 cursor.y = current_y;
319 ClientToScreen(SDL_Window, &cursor);
321 /* Construct a 1 pixel square RECT that is used to confine the cursor
322 * pointer to a specific pixel using ClipCursor. This is used in
323 * preference to SetCursorPos as it avoids the cursor jumping around as
324 * both the OS and SDL attempt to move it simultaneously. */
325 trap.left = cursor.x;
327 trap.right = cursor.x + 1;
328 trap.bottom = cursor.y + 1;
330 GetClientRect(SDL_Window, &window);
331 window.right -= window.left; window.left = 0;
332 window.bottom -= window.top; window.top = 0;
334 /* As we're assuming control over the cursor, we need to know when to
335 * relinquish control of it back to the operating system. This is when
336 * the cursor reaches the edge of the window. */
337 at_edge = (current_x == window.left) ||
338 (current_x == (window.right - 1)) ||
339 (current_y == window.top) ||
340 (current_y == (window.bottom - 1));
348 /* When in relative mode, warp the OS's idea of where the cursor is to
349 * the center of the screen. This isn't really necessary as DirectInput
350 * reads from the hardware itself, but in case things go wrong, the
351 * cursor will be left in a sensible place. */
353 center.x = (SDL_VideoSurface->w/2);
354 center.y = (SDL_VideoSurface->h/2);
355 ClientToScreen(SDL_Window, ¢er);
356 SetCursorPos(center.x, center.y);
359 /* No window or mouse focus, control is lost */
365 static void handle_mouse(const int numevents, DIDEVICEOBJECTDATA *ptrbuf)
373 /* Sanity check. Mailing list reports this being NULL unexpectedly. */
374 if (SDL_PublicSurface == NULL) {
378 /* If the mouse was lost, regain some sense of mouse state */
379 if ( mouse_lost && (SDL_GetAppState() & SDL_APPMOUSEFOCUS) ) {
384 /* Set ourselves up with the current cursor position */
385 GetCursorPos(&mouse_pos);
386 ScreenToClient(SDL_Window, &mouse_pos);
387 post_mouse_motion( 0, (Sint16)mouse_pos.x, (Sint16)mouse_pos.y);
389 /* Check for mouse button changes */
390 old_state = SDL_GetMouseState(NULL, NULL);
392 { /* Get the new DirectInput button state for the mouse */
393 #if DIRECTINPUT_VERSION >= 0x700
394 DIMOUSESTATE2 distate;
396 DIMOUSESTATE distate;
400 result=IDirectInputDevice2_GetDeviceState(SDL_DIdev[1],
401 sizeof(distate), &distate);
402 if ( result != DI_OK ) {
403 /* Try again next time */
405 "IDirectInputDevice2::GetDeviceState", result);
408 for ( i=3; i>=0; --i ) {
409 if ( (distate.rgbButtons[i]&0x80) == 0x80 ) {
415 for ( i=0; i<8; ++i ) {
416 if ( (old_state&0x01) != (new_state&0x01) ) {
417 button = (Uint8)(i+1);
418 /* Map DI button numbers to SDL */
420 case 2: button = SDL_BUTTON_RIGHT; break;
421 case 3: button = SDL_BUTTON_MIDDLE; break;
422 case 4: button = SDL_BUTTON_X1; break;
423 case 5: button = SDL_BUTTON_X2; break;
426 if ( new_state & 0x01 ) {
427 /* Grab mouse so we get mouse-up */
428 if ( ++mouse_pressed > 0 ) {
429 SetCapture(SDL_Window);
433 /* Release mouse after all mouse-ups */
434 if ( --mouse_pressed <= 0 ) {
438 state = SDL_RELEASED;
440 if ( mouse_buttons_swapped ) {
441 if ( button == 1 ) button = 3;
443 if ( button == 3 ) button = 1;
445 posted = SDL_PrivateMouseButton(state, button,
455 /* Translate mouse messages */
458 for ( i=0; i<(int)numevents; ++i ) {
459 switch (ptrbuf[i].dwOfs) {
461 if ( timestamp != ptrbuf[i].dwTimeStamp ) {
462 if ( xrel || yrel ) {
463 post_mouse_motion(1, xrel, yrel);
467 timestamp = ptrbuf[i].dwTimeStamp;
469 xrel += (Sint16)ptrbuf[i].dwData;
472 if ( timestamp != ptrbuf[i].dwTimeStamp ) {
473 if ( xrel || yrel ) {
474 post_mouse_motion(1, xrel, yrel);
478 timestamp = ptrbuf[i].dwTimeStamp;
480 yrel += (Sint16)ptrbuf[i].dwData;
483 if ( xrel || yrel ) {
484 post_mouse_motion(1, xrel, yrel);
489 if((int)ptrbuf[i].dwData > 0)
490 button = SDL_BUTTON_WHEELUP;
492 button = SDL_BUTTON_WHEELDOWN;
493 posted = SDL_PrivateMouseButton(
494 SDL_PRESSED, button, 0, 0);
495 posted |= SDL_PrivateMouseButton(
496 SDL_RELEASED, button, 0, 0);
502 #if DIRECTINPUT_VERSION >= 0x700
508 if ( xrel || yrel ) {
509 post_mouse_motion(1, xrel, yrel);
514 button = (Uint8)(ptrbuf[i].dwOfs-DIMOFS_BUTTON0)+1;
515 /* Map DI button numbers to SDL */
517 case 2: button = SDL_BUTTON_RIGHT; break;
518 case 3: button = SDL_BUTTON_MIDDLE; break;
519 case 4: button = SDL_BUTTON_X1; break;
520 case 5: button = SDL_BUTTON_X2; break;
523 if ( ptrbuf[i].dwData & 0x80 ) {
524 /* Grab mouse so we get mouse-up */
525 if ( ++mouse_pressed > 0 ) {
526 SetCapture(SDL_Window);
530 /* Release mouse after all mouse-ups */
531 if ( --mouse_pressed <= 0 ) {
535 state = SDL_RELEASED;
537 if ( mouse_buttons_swapped ) {
538 if ( button == 1 ) button = 3;
540 if ( button == 3 ) button = 1;
542 posted = SDL_PrivateMouseButton(state, button,
547 if ( xrel || yrel ) {
548 post_mouse_motion(1, xrel, yrel);
552 /* The main Win32 event handler */
553 LRESULT DX5_HandleMessage(_THIS, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
556 #ifdef WM_ACTIVATEAPP
557 case WM_ACTIVATEAPP: {
560 active = (wParam && (GetForegroundWindow() == hwnd));
562 for ( i=0; SDL_DIdev[i]; ++i ) {
563 IDirectInputDevice2_Acquire(
567 for ( i=0; SDL_DIdev[i]; ++i ) {
568 IDirectInputDevice2_Unacquire(
575 #endif /* WM_ACTIVATEAPP */
577 #ifdef WM_DISPLAYCHANGE
578 case WM_DISPLAYCHANGE: {
582 /* Ack! The display changed size and/or depth! */
583 SizeX = LOWORD(lParam);
584 SizeY = HIWORD(lParam);
585 BitsPerPixel = wParam;
586 /* We cause this message when we go fullscreen */
589 #endif /* WM_DISPLAYCHANGE */
591 /* The keyboard is handled via DirectInput */
596 /* Ignore windows keyboard messages */;
600 #if defined(SC_SCREENSAVE) || defined(SC_MONITORPOWER)
601 /* Don't allow screen savers or monitor power downs.
602 This is because they quietly clear DirectX surfaces.
603 It would be better to allow the application to
604 decide whether or not to blow these off, but the
605 semantics of SDL_PrivateSysWMEvent() don't allow
606 the application that choice.
608 case WM_SYSCOMMAND: {
609 if ((wParam&0xFFF0)==SC_SCREENSAVE ||
610 (wParam&0xFFF0)==SC_MONITORPOWER)
613 /* Fall through to default processing */
615 #endif /* SC_SCREENSAVE || SC_MONITORPOWER */
618 /* Only post the event if we're watching for it */
619 if ( SDL_ProcessEvents[SDL_SYSWMEVENT] == SDL_ENABLE ) {
622 SDL_VERSION(&wmmsg.version);
625 wmmsg.wParam = wParam;
626 wmmsg.lParam = lParam;
627 posted = SDL_PrivateSysWMEvent(&wmmsg);
629 /* DJM: If the user isn't watching for private
630 messages in her SDL event loop, then pass it
631 along to any win32 specific window proc.
633 } else if (userWindowProc) {
634 return CallWindowProc(userWindowProc, hwnd, msg, wParam, lParam);
639 return(DefWindowProc(hwnd, msg, wParam, lParam));
642 /* This function checks the windows message queue and DirectInput and returns
643 1 if there was input, 0 if there was no input, or -1 if the application has
644 posted a quit message.
646 static int DX5_CheckInput(_THIS, int timeout, BOOL processInput)
653 /* Check the normal windows queue (highest preference) */
656 PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE) ) {
657 if ( GetMessage(&msg, NULL, 0, 0) > 0 ) {
658 TranslateMessage(&msg);
659 DispatchMessage(&msg);
668 /* Pump the DirectInput flow */
669 if ( SDL_GetAppState() & SDL_APPINPUTFOCUS ) {
670 for ( i=0; i<MAX_INPUTS; ++i ) {
671 if ( SDL_DIdev[i] != NULL ) {
672 result = IDirectInputDevice2_Poll(SDL_DIdev[i]);
673 if ( (result == DIERR_INPUTLOST) ||
674 (result == DIERR_NOTACQUIRED) ) {
675 if ( SDL_strcmp(inputs[i].name, "mouse") == 0 ) {
678 IDirectInputDevice2_Acquire(SDL_DIdev[i]);
679 IDirectInputDevice2_Poll(SDL_DIdev[i]);
685 /* Wait for messages and input events */
686 event = MsgWaitForMultipleObjects(SDL_DIndev, SDL_DIevt, FALSE,
687 timeout, QS_ALLEVENTS);
688 if ((event >= WAIT_OBJECT_0) && (event < (WAIT_OBJECT_0+SDL_DIndev))) {
690 static DIDEVICEOBJECTDATA evtbuf[INPUT_QSIZE];
692 event -= WAIT_OBJECT_0;
693 numevents = INPUT_QSIZE;
694 result = IDirectInputDevice2_GetDeviceData(
695 SDL_DIdev[event], sizeof(DIDEVICEOBJECTDATA),
696 evtbuf, &numevents, 0);
697 if ( (result == DIERR_INPUTLOST) ||
698 (result == DIERR_NOTACQUIRED) ) {
699 if ( SDL_strcmp(inputs[event].name, "mouse") == 0 ) {
702 IDirectInputDevice2_Acquire(SDL_DIdev[event]);
703 result = IDirectInputDevice2_GetDeviceData(
704 SDL_DIdev[event], sizeof(DIDEVICEOBJECTDATA),
705 evtbuf, &numevents, 0);
707 /* Handle the events */
708 if ( result == DI_OK && processInput ) {
709 /* Note: This can post multiple events to event queue
711 (*SDL_DIfun[event])((int)numevents, evtbuf);
715 if ( event != WAIT_TIMEOUT ) {
716 /* Maybe there was a windows message? */
719 PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE) ) {
720 if ( GetMessage(&msg, NULL, 0, 0) > 0 ) {
721 TranslateMessage(&msg);
722 DispatchMessage(&msg);
734 /* Change cooperative level based on whether or not we are fullscreen */
735 void DX5_DInputReset(_THIS, int fullscreen)
742 for ( i=0; i<MAX_INPUTS; ++i ) {
743 if ( SDL_DIdev[i] != NULL ) {
745 level = inputs[i].raw_level;
747 level = inputs[i].win_level;
749 IDirectInputDevice2_Unacquire(SDL_DIdev[i]);
750 topwnd = GetTopLevelParent(SDL_Window);
751 result = IDirectInputDevice2_SetCooperativeLevel(
752 SDL_DIdev[i], topwnd, level);
753 IDirectInputDevice2_Acquire(SDL_DIdev[i]);
754 if ( result != DI_OK ) {
756 "DirectInputDevice::SetCooperativeLevel", result);
762 /* Flush pending input */
763 DX5_CheckInput(this, 0, FALSE);
766 void DX5_PumpEvents(_THIS)
768 /* Wait for messages and DirectInput */
769 while ( DX5_CheckInput(this, 0, TRUE) > 0 ) {
770 /* Loop and check again */;
774 void DX5_InitOSKeymap(_THIS)
777 #define DIK_PAUSE 0xC5
780 #define DIK_OEM_102 0x56 /* < > | on UK/Germany keyboards */
784 /* Map the DIK scancodes to SDL keysyms */
785 for ( i=0; i<SDL_arraysize(DIK_keymap); ++i )
788 /* Defined DIK_* constants */
789 DIK_keymap[DIK_ESCAPE] = SDLK_ESCAPE;
790 DIK_keymap[DIK_1] = SDLK_1;
791 DIK_keymap[DIK_2] = SDLK_2;
792 DIK_keymap[DIK_3] = SDLK_3;
793 DIK_keymap[DIK_4] = SDLK_4;
794 DIK_keymap[DIK_5] = SDLK_5;
795 DIK_keymap[DIK_6] = SDLK_6;
796 DIK_keymap[DIK_7] = SDLK_7;
797 DIK_keymap[DIK_8] = SDLK_8;
798 DIK_keymap[DIK_9] = SDLK_9;
799 DIK_keymap[DIK_0] = SDLK_0;
800 DIK_keymap[DIK_MINUS] = SDLK_MINUS;
801 DIK_keymap[DIK_EQUALS] = SDLK_EQUALS;
802 DIK_keymap[DIK_BACK] = SDLK_BACKSPACE;
803 DIK_keymap[DIK_TAB] = SDLK_TAB;
804 DIK_keymap[DIK_Q] = SDLK_q;
805 DIK_keymap[DIK_W] = SDLK_w;
806 DIK_keymap[DIK_E] = SDLK_e;
807 DIK_keymap[DIK_R] = SDLK_r;
808 DIK_keymap[DIK_T] = SDLK_t;
809 DIK_keymap[DIK_Y] = SDLK_y;
810 DIK_keymap[DIK_U] = SDLK_u;
811 DIK_keymap[DIK_I] = SDLK_i;
812 DIK_keymap[DIK_O] = SDLK_o;
813 DIK_keymap[DIK_P] = SDLK_p;
814 DIK_keymap[DIK_LBRACKET] = SDLK_LEFTBRACKET;
815 DIK_keymap[DIK_RBRACKET] = SDLK_RIGHTBRACKET;
816 DIK_keymap[DIK_RETURN] = SDLK_RETURN;
817 DIK_keymap[DIK_LCONTROL] = SDLK_LCTRL;
818 DIK_keymap[DIK_A] = SDLK_a;
819 DIK_keymap[DIK_S] = SDLK_s;
820 DIK_keymap[DIK_D] = SDLK_d;
821 DIK_keymap[DIK_F] = SDLK_f;
822 DIK_keymap[DIK_G] = SDLK_g;
823 DIK_keymap[DIK_H] = SDLK_h;
824 DIK_keymap[DIK_J] = SDLK_j;
825 DIK_keymap[DIK_K] = SDLK_k;
826 DIK_keymap[DIK_L] = SDLK_l;
827 DIK_keymap[DIK_SEMICOLON] = SDLK_SEMICOLON;
828 DIK_keymap[DIK_APOSTROPHE] = SDLK_QUOTE;
829 DIK_keymap[DIK_GRAVE] = SDLK_BACKQUOTE;
830 DIK_keymap[DIK_LSHIFT] = SDLK_LSHIFT;
831 DIK_keymap[DIK_BACKSLASH] = SDLK_BACKSLASH;
832 DIK_keymap[DIK_OEM_102] = SDLK_LESS;
833 DIK_keymap[DIK_Z] = SDLK_z;
834 DIK_keymap[DIK_X] = SDLK_x;
835 DIK_keymap[DIK_C] = SDLK_c;
836 DIK_keymap[DIK_V] = SDLK_v;
837 DIK_keymap[DIK_B] = SDLK_b;
838 DIK_keymap[DIK_N] = SDLK_n;
839 DIK_keymap[DIK_M] = SDLK_m;
840 DIK_keymap[DIK_COMMA] = SDLK_COMMA;
841 DIK_keymap[DIK_PERIOD] = SDLK_PERIOD;
842 DIK_keymap[DIK_SLASH] = SDLK_SLASH;
843 DIK_keymap[DIK_RSHIFT] = SDLK_RSHIFT;
844 DIK_keymap[DIK_MULTIPLY] = SDLK_KP_MULTIPLY;
845 DIK_keymap[DIK_LMENU] = SDLK_LALT;
846 DIK_keymap[DIK_SPACE] = SDLK_SPACE;
847 DIK_keymap[DIK_CAPITAL] = SDLK_CAPSLOCK;
848 DIK_keymap[DIK_F1] = SDLK_F1;
849 DIK_keymap[DIK_F2] = SDLK_F2;
850 DIK_keymap[DIK_F3] = SDLK_F3;
851 DIK_keymap[DIK_F4] = SDLK_F4;
852 DIK_keymap[DIK_F5] = SDLK_F5;
853 DIK_keymap[DIK_F6] = SDLK_F6;
854 DIK_keymap[DIK_F7] = SDLK_F7;
855 DIK_keymap[DIK_F8] = SDLK_F8;
856 DIK_keymap[DIK_F9] = SDLK_F9;
857 DIK_keymap[DIK_F10] = SDLK_F10;
858 DIK_keymap[DIK_NUMLOCK] = SDLK_NUMLOCK;
859 DIK_keymap[DIK_SCROLL] = SDLK_SCROLLOCK;
860 DIK_keymap[DIK_NUMPAD7] = SDLK_KP7;
861 DIK_keymap[DIK_NUMPAD8] = SDLK_KP8;
862 DIK_keymap[DIK_NUMPAD9] = SDLK_KP9;
863 DIK_keymap[DIK_SUBTRACT] = SDLK_KP_MINUS;
864 DIK_keymap[DIK_NUMPAD4] = SDLK_KP4;
865 DIK_keymap[DIK_NUMPAD5] = SDLK_KP5;
866 DIK_keymap[DIK_NUMPAD6] = SDLK_KP6;
867 DIK_keymap[DIK_ADD] = SDLK_KP_PLUS;
868 DIK_keymap[DIK_NUMPAD1] = SDLK_KP1;
869 DIK_keymap[DIK_NUMPAD2] = SDLK_KP2;
870 DIK_keymap[DIK_NUMPAD3] = SDLK_KP3;
871 DIK_keymap[DIK_NUMPAD0] = SDLK_KP0;
872 DIK_keymap[DIK_DECIMAL] = SDLK_KP_PERIOD;
873 DIK_keymap[DIK_F11] = SDLK_F11;
874 DIK_keymap[DIK_F12] = SDLK_F12;
876 DIK_keymap[DIK_F13] = SDLK_F13;
877 DIK_keymap[DIK_F14] = SDLK_F14;
878 DIK_keymap[DIK_F15] = SDLK_F15;
880 DIK_keymap[DIK_NUMPADEQUALS] = SDLK_KP_EQUALS;
881 DIK_keymap[DIK_NUMPADENTER] = SDLK_KP_ENTER;
882 DIK_keymap[DIK_RCONTROL] = SDLK_RCTRL;
883 DIK_keymap[DIK_DIVIDE] = SDLK_KP_DIVIDE;
884 DIK_keymap[DIK_SYSRQ] = SDLK_PRINT;
885 DIK_keymap[DIK_RMENU] = SDLK_RALT;
886 DIK_keymap[DIK_PAUSE] = SDLK_PAUSE;
887 DIK_keymap[DIK_HOME] = SDLK_HOME;
888 DIK_keymap[DIK_UP] = SDLK_UP;
889 DIK_keymap[DIK_PRIOR] = SDLK_PAGEUP;
890 DIK_keymap[DIK_LEFT] = SDLK_LEFT;
891 DIK_keymap[DIK_RIGHT] = SDLK_RIGHT;
892 DIK_keymap[DIK_END] = SDLK_END;
893 DIK_keymap[DIK_DOWN] = SDLK_DOWN;
894 DIK_keymap[DIK_NEXT] = SDLK_PAGEDOWN;
895 DIK_keymap[DIK_INSERT] = SDLK_INSERT;
896 DIK_keymap[DIK_DELETE] = SDLK_DELETE;
897 DIK_keymap[DIK_LWIN] = SDLK_LMETA;
898 DIK_keymap[DIK_RWIN] = SDLK_RMETA;
899 DIK_keymap[DIK_APPS] = SDLK_MENU;
902 static SDL_keysym *TranslateKey(UINT scancode, SDL_keysym *keysym, int pressed)
904 /* Set the keysym information */
905 keysym->scancode = (unsigned char)scancode;
906 keysym->sym = DIK_keymap[scancode];
907 keysym->mod = KMOD_NONE;
909 if ( pressed && SDL_TranslateUNICODE ) {
911 #ifndef NO_GETKEYBOARDSTATE
916 vkey = MapVirtualKey(scancode, 1);
917 #ifdef NO_GETKEYBOARDSTATE
918 /* Uh oh, better hope the vkey is close enough.. */
919 keysym->unicode = vkey;
921 GetKeyboardState(keystate);
922 /* Numlock isn't taken into account in ToUnicode,
923 * so we handle it as a special case here */
924 if ((keystate[VK_NUMLOCK] & 1) && vkey >= VK_NUMPAD0 && vkey <= VK_NUMPAD9)
926 keysym->unicode = vkey - VK_NUMPAD0 + '0';
928 else if (SDL_ToUnicode(vkey, scancode, keystate, wchars, sizeof(wchars)/sizeof(wchars[0]), 0) > 0)
930 keysym->unicode = wchars[0];
932 #endif /* NO_GETKEYBOARDSTATE */
937 int DX5_CreateWindow(_THIS)
939 char *windowid = SDL_getenv("SDL_WINDOWID");
942 /* Clear out DirectInput variables in case we fail */
943 for ( i=0; i<MAX_INPUTS; ++i ) {
949 SDL_RegisterApp(NULL, 0, 0);
951 SDL_windowid = (windowid != NULL);
952 if ( SDL_windowid ) {
953 SDL_Window = (HWND)SDL_strtoull(windowid, NULL, 0);
954 if ( SDL_Window == NULL ) {
955 SDL_SetError("Couldn't get user specified window");
959 /* DJM: we want all event's for the user specified
960 window to be handled by SDL.
962 userWindowProc = (WNDPROCTYPE)GetWindowLongPtr(SDL_Window, GWLP_WNDPROC);
963 SetWindowLongPtr(SDL_Window, GWLP_WNDPROC, (LONG_PTR)WinMessage);
965 SDL_Window = CreateWindow(SDL_Appname, SDL_Appname,
966 (WS_OVERLAPPED|WS_CAPTION|WS_SYSMENU|WS_MINIMIZEBOX),
967 CW_USEDEFAULT, CW_USEDEFAULT, 0, 0, NULL, NULL, SDL_Instance, NULL);
968 if ( SDL_Window == NULL ) {
969 SDL_SetError("Couldn't create window");
972 ShowWindow(SDL_Window, SW_HIDE);
975 /* Initialize DirectInput */
976 if ( DX5_DInputInit(this) < 0 ) {
981 Flush the message loop or this can cause big problems later
982 Especially if the user decides to use dialog boxes or assert()!
984 WIN_FlushMessageQueue();
990 void DX5_DestroyWindow(_THIS)
992 /* Close down DirectInput */
993 DX5_DInputQuit(this);
995 /* Destroy our window */
996 if ( SDL_windowid ) {
997 SetWindowLongPtr(SDL_Window, GWLP_WNDPROC, (LONG_PTR)userWindowProc);
999 DestroyWindow(SDL_Window);
1001 SDL_UnregisterApp();
1004 Flush the message loop or this can cause big problems later
1005 Especially if the user decides to use dialog boxes or assert()!
1007 WIN_FlushMessageQueue();