From ad8ffb96789f90180982b344540870a2d4e2d60b Mon Sep 17 00:00:00 2001 From: chai Date: Thu, 31 May 2018 08:12:40 +0800 Subject: init --- 3rdparty/SDL/src/video/windx5/SDL_dx5events.c | 1005 +++++++++++++++++++++++++ 1 file changed, 1005 insertions(+) create mode 100644 3rdparty/SDL/src/video/windx5/SDL_dx5events.c (limited to '3rdparty/SDL/src/video/windx5/SDL_dx5events.c') diff --git a/3rdparty/SDL/src/video/windx5/SDL_dx5events.c b/3rdparty/SDL/src/video/windx5/SDL_dx5events.c new file mode 100644 index 0000000..e12092f --- /dev/null +++ b/3rdparty/SDL/src/video/windx5/SDL_dx5events.c @@ -0,0 +1,1005 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* CAUTION!!!! If you modify this file, check ../windib/SDL_sysevents.c */ + +#include "directx.h" + +#include "SDL_main.h" +#include "SDL_events.h" +#include "SDL_video.h" +#include "SDL_syswm.h" +#include "../../events/SDL_sysevents.h" +#include "../../events/SDL_events_c.h" +#include "../wincommon/SDL_lowvideo.h" +#include "SDL_dx5video.h" + +#ifndef WM_APP +#define WM_APP 0x8000 +#endif + +#ifdef _WIN32_WCE +#define NO_GETKEYBOARDSTATE +#endif + +/* The keyboard and mouse device input */ +#define MAX_INPUTS 2 +#define INPUT_QSIZE 512 /* Buffer up to 512 input messages */ + +static LPDIRECTINPUT dinput = NULL; +static LPDIRECTINPUTDEVICE2 SDL_DIdev[MAX_INPUTS]; +static HANDLE SDL_DIevt[MAX_INPUTS]; +static void (*SDL_DIfun[MAX_INPUTS])(const int, DIDEVICEOBJECTDATA *); +static int SDL_DIndev = 0; +static int mouse_lost; +static int mouse_pressed; +static int mouse_buttons_swapped = 0; + +/* The translation table from a DirectInput scancode to an SDL keysym */ +static SDLKey DIK_keymap[256]; +static SDL_keysym *TranslateKey(UINT scancode, SDL_keysym *keysym, int pressed); + +/* DJM: If the user setup the window for us, we want to save his window proc, + and give him a chance to handle some messages. */ +#ifdef STRICT +#define WNDPROCTYPE WNDPROC +#else +#define WNDPROCTYPE FARPROC +#endif +static WNDPROCTYPE userWindowProc = NULL; + +static HWND GetTopLevelParent(HWND hWnd) +{ + HWND hParentWnd; + while (1) + { + hParentWnd = GetParent(hWnd); + if (hParentWnd == NULL) + break; + hWnd = hParentWnd; + } + return hWnd; +} + +/* Convert a DirectInput return code to a text message */ +static void SetDIerror(char *function, int code) +{ + static char *error; + static char errbuf[1024]; + + errbuf[0] = 0; + switch (code) { + case DIERR_GENERIC: + error = "Undefined error!"; + break; + case DIERR_OLDDIRECTINPUTVERSION: + error = "Your version of DirectInput needs upgrading"; + break; + case DIERR_INVALIDPARAM: + error = "Invalid parameters"; + break; + case DIERR_OUTOFMEMORY: + error = "Out of memory"; + break; + case DIERR_DEVICENOTREG: + error = "Device not registered"; + break; + case DIERR_NOINTERFACE: + error = "Interface not supported"; + break; + case DIERR_NOTINITIALIZED: + error = "Device not initialized"; + break; + default: + SDL_snprintf(errbuf, SDL_arraysize(errbuf), + "%s: Unknown DirectInput error: 0x%x", + function, code); + break; + } + if ( ! errbuf[0] ) { + SDL_snprintf(errbuf, SDL_arraysize(errbuf), "%s: %s", function, error); + } + SDL_SetError("%s", errbuf); + return; +} + +/* Initialize DirectInput + Note: If NONEXCLUSIVE access is requested for the devices, normal + windows input messages will continue to be generated for that + input device, in addition to DirectInput messages. + */ +static void handle_keyboard(const int numevents, DIDEVICEOBJECTDATA *events); +static void handle_mouse(const int numevents, DIDEVICEOBJECTDATA *events); +struct { + char *name; + REFGUID guid; + LPCDIDATAFORMAT format; + DWORD win_level; + DWORD raw_level; + void (*fun)(const int numevents, DIDEVICEOBJECTDATA *events); +} inputs[] = { + { "keyboard", + &GUID_SysKeyboard, &c_dfDIKeyboard, + (DISCL_FOREGROUND|DISCL_NONEXCLUSIVE), + (DISCL_FOREGROUND|DISCL_NONEXCLUSIVE), handle_keyboard }, + { "mouse", + &GUID_SysMouse, +#if DIRECTINPUT_VERSION >= 0x700 + &c_dfDIMouse2, +#else + &c_dfDIMouse, +#endif + (DISCL_BACKGROUND|DISCL_NONEXCLUSIVE), + (DISCL_BACKGROUND|DISCL_NONEXCLUSIVE), handle_mouse }, + { NULL, NULL, NULL, 0, 0, NULL } +}; + +static int DX5_DInputInit(_THIS) +{ + int i; + LPDIRECTINPUTDEVICE device; + HRESULT result; + DIPROPDWORD dipdw; + HWND topwnd; + + /* Create the DirectInput object */ + result = DInputCreate(SDL_Instance, DIRECTINPUT_VERSION, + &dinput, NULL); + if ( result != DI_OK ) { + SetDIerror("DirectInputCreate", result); + return(-1); + } + + /* Create all of our registered input devices */ + SDL_DIndev = 0; + for ( i=0; inputs[i].name; ++i ) { + /* Create the DirectInput device */ + result = IDirectInput_CreateDevice(dinput, inputs[i].guid, + &device, NULL); + if ( result != DI_OK ) { + SetDIerror("DirectInput::CreateDevice", result); + return(-1); + } + result = IDirectInputDevice_QueryInterface(device, + &IID_IDirectInputDevice2, (LPVOID *)&SDL_DIdev[i]); + IDirectInputDevice_Release(device); + if ( result != DI_OK ) { + SetDIerror("DirectInputDevice::QueryInterface", result); + return(-1); + } + topwnd = GetTopLevelParent(SDL_Window); + result = IDirectInputDevice2_SetCooperativeLevel(SDL_DIdev[i], + topwnd, inputs[i].win_level); + if ( result != DI_OK ) { + SetDIerror("DirectInputDevice::SetCooperativeLevel", + result); + return(-1); + } + result = IDirectInputDevice2_SetDataFormat(SDL_DIdev[i], + inputs[i].format); + if ( result != DI_OK ) { + SetDIerror("DirectInputDevice::SetDataFormat", result); + return(-1); + } + + /* Set buffered input -- we aren't polling */ + SDL_memset(&dipdw, 0, sizeof(dipdw)); + dipdw.diph.dwSize = sizeof(dipdw); + dipdw.diph.dwHeaderSize = sizeof(dipdw.diph); + dipdw.diph.dwObj = 0; + dipdw.diph.dwHow = DIPH_DEVICE; + dipdw.dwData = INPUT_QSIZE; + result = IDirectInputDevice2_SetProperty(SDL_DIdev[i], + DIPROP_BUFFERSIZE, &dipdw.diph); + if ( result != DI_OK ) { + SetDIerror("DirectInputDevice::SetProperty", result); + return(-1); + } + + /* Create an event to be signaled when input is ready */ + SDL_DIevt[i] = CreateEvent(NULL, FALSE, FALSE, NULL); + if ( SDL_DIevt[i] == NULL ) { + SDL_SetError("Couldn't create DirectInput event"); + return(-1); + } + result = IDirectInputDevice2_SetEventNotification(SDL_DIdev[i], + SDL_DIevt[i]); + if ( result != DI_OK ) { + SetDIerror("DirectInputDevice::SetEventNotification", + result); + return(-1); + } + SDL_DIfun[i] = inputs[i].fun; + + /* Acquire the device for input */ + IDirectInputDevice2_Acquire(SDL_DIdev[i]); + + /* Increment the number of devices we have */ + ++SDL_DIndev; + } + mouse_pressed = 0; + mouse_buttons_swapped = GetSystemMetrics(SM_SWAPBUTTON); + + /* DirectInput is ready! */ + return(0); +} + +/* Clean up DirectInput */ +static void DX5_DInputQuit(_THIS) +{ + int i; + + if ( dinput != NULL ) { + /* Close and release all DirectInput devices */ + for ( i=0; iw/2); + center.y = (SDL_VideoSurface->h/2); + ClientToScreen(SDL_Window, ¢er); + SetCursorPos(center.x, center.y); + } + } +} + +static void handle_mouse(const int numevents, DIDEVICEOBJECTDATA *ptrbuf) +{ + int i; + Sint16 xrel, yrel; + Uint8 state; + Uint8 button; + DWORD timestamp = 0; + + /* Sanity check. Mailing list reports this being NULL unexpectedly. */ + if (SDL_PublicSurface == NULL) { + return; + } + + /* If mouse focus has been lost, make sure we release the cursor. */ + if ( !(SDL_GetAppState() & SDL_APPMOUSEFOCUS) ) { + mouse_lost = 1; + ClipCursor(NULL); + } else { + /* If the mouse was lost, regain some sense of mouse state */ + if ( mouse_lost ) { + POINT mouse_pos; + Uint8 old_state; + Uint8 new_state; + + /* Set ourselves up with the current cursor position */ + GetCursorPos(&mouse_pos); + ScreenToClient(SDL_Window, &mouse_pos); + post_mouse_motion( 0, (Sint16)mouse_pos.x, (Sint16)mouse_pos.y); + + /* Check for mouse button changes */ + old_state = SDL_GetMouseState(NULL, NULL); + new_state = 0; + { /* Get the new DirectInput button state for the mouse */ + #if DIRECTINPUT_VERSION >= 0x700 + DIMOUSESTATE2 distate; + #else + DIMOUSESTATE distate; + #endif + HRESULT result; + + result=IDirectInputDevice2_GetDeviceState(SDL_DIdev[1], + sizeof(distate), &distate); + if ( result != DI_OK ) { + /* Try again next time */ + SetDIerror( + "IDirectInputDevice2::GetDeviceState", result); + return; + } + for ( i=3; i>=0; --i ) { + if ( (distate.rgbButtons[i]&0x80) == 0x80 ) { + new_state |= 0x01; + } + new_state <<= 1; + } + } + for ( i=0; i<8; ++i ) { + if ( (old_state&0x01) != (new_state&0x01) ) { + button = (Uint8)(i+1); + /* Map DI button numbers to SDL */ + switch ( button ) { + case 2: button = SDL_BUTTON_RIGHT; break; + case 3: button = SDL_BUTTON_MIDDLE; break; + case 4: button = SDL_BUTTON_X1; break; + case 5: button = SDL_BUTTON_X2; break; + default: break; + } + if ( new_state & 0x01 ) { + /* Grab mouse so we get mouse-up */ + if ( ++mouse_pressed > 0 ) { + SetCapture(SDL_Window); + } + state = SDL_PRESSED; + } else { + /* Release mouse after all mouse-ups */ + if ( --mouse_pressed <= 0 ) { + ReleaseCapture(); + mouse_pressed = 0; + } + state = SDL_RELEASED; + } + if ( mouse_buttons_swapped ) { + if ( button == 1 ) button = 3; + else + if ( button == 3 ) button = 1; + } + posted = SDL_PrivateMouseButton(state, button, + 0, 0); + } + old_state >>= 1; + new_state >>= 1; + } + mouse_lost = 0; + return; + } + + /* Translate mouse messages */ + xrel = 0; + yrel = 0; + for ( i=0; i<(int)numevents; ++i ) { + switch (ptrbuf[i].dwOfs) { + case DIMOFS_X: + if ( timestamp != ptrbuf[i].dwTimeStamp ) { + if ( xrel || yrel ) { + post_mouse_motion(1, xrel, yrel); + xrel = 0; + yrel = 0; + } + timestamp = ptrbuf[i].dwTimeStamp; + } + xrel += (Sint16)ptrbuf[i].dwData; + break; + case DIMOFS_Y: + if ( timestamp != ptrbuf[i].dwTimeStamp ) { + if ( xrel || yrel ) { + post_mouse_motion(1, xrel, yrel); + xrel = 0; + yrel = 0; + } + timestamp = ptrbuf[i].dwTimeStamp; + } + yrel += (Sint16)ptrbuf[i].dwData; + break; + case DIMOFS_Z: + if ( xrel || yrel ) { + post_mouse_motion(1, xrel, yrel); + xrel = 0; + yrel = 0; + } + timestamp = 0; + if((int)ptrbuf[i].dwData > 0) + button = SDL_BUTTON_WHEELUP; + else + button = SDL_BUTTON_WHEELDOWN; + posted = SDL_PrivateMouseButton( + SDL_PRESSED, button, 0, 0); + posted |= SDL_PrivateMouseButton( + SDL_RELEASED, button, 0, 0); + break; + case DIMOFS_BUTTON0: + case DIMOFS_BUTTON1: + case DIMOFS_BUTTON2: + case DIMOFS_BUTTON3: + #if DIRECTINPUT_VERSION >= 0x700 + case DIMOFS_BUTTON4: + case DIMOFS_BUTTON5: + case DIMOFS_BUTTON6: + case DIMOFS_BUTTON7: + #endif + if ( xrel || yrel ) { + post_mouse_motion(1, xrel, yrel); + xrel = 0; + yrel = 0; + } + timestamp = 0; + button = (Uint8)(ptrbuf[i].dwOfs-DIMOFS_BUTTON0)+1; + /* Map DI button numbers to SDL */ + switch ( button ) { + case 2: button = SDL_BUTTON_RIGHT; break; + case 3: button = SDL_BUTTON_MIDDLE; break; + case 4: button = SDL_BUTTON_X1; break; + case 5: button = SDL_BUTTON_X2; break; + default: break; + } + if ( ptrbuf[i].dwData & 0x80 ) { + /* Grab mouse so we get mouse-up */ + if ( ++mouse_pressed > 0 ) { + SetCapture(SDL_Window); + } + state = SDL_PRESSED; + } else { + /* Release mouse after all mouse-ups */ + if ( --mouse_pressed <= 0 ) { + ReleaseCapture(); + mouse_pressed = 0; + } + state = SDL_RELEASED; + } + if ( mouse_buttons_swapped ) { + if ( button == 1 ) button = 3; + else + if ( button == 3 ) button = 1; + } + posted = SDL_PrivateMouseButton(state, button, + 0, 0); + break; + } + } + if ( xrel || yrel ) { + post_mouse_motion(1, xrel, yrel); + } + } +} + +/* The main Win32 event handler */ +LRESULT DX5_HandleMessage(_THIS, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + switch (msg) { +#ifdef WM_ACTIVATEAPP + case WM_ACTIVATEAPP: { + int i, active; + + active = (wParam && (GetForegroundWindow() == hwnd)); + if ( active ) { + for ( i=0; i 0 ) { + DispatchMessage(&msg); + } else { + return(-1); + } + } + if ( posted ) { + return(1); + } + + /* Pump the DirectInput flow */ + if ( SDL_GetAppState() & SDL_APPMOUSEFOCUS ) { + for ( i=0; i= WAIT_OBJECT_0) && (event < (WAIT_OBJECT_0+SDL_DIndev))) { + DWORD numevents; + static DIDEVICEOBJECTDATA evtbuf[INPUT_QSIZE]; + + event -= WAIT_OBJECT_0; + numevents = INPUT_QSIZE; + result = IDirectInputDevice2_GetDeviceData( + SDL_DIdev[event], sizeof(DIDEVICEOBJECTDATA), + evtbuf, &numevents, 0); + if ( (result == DIERR_INPUTLOST) || + (result == DIERR_NOTACQUIRED) ) { + if ( SDL_strcmp(inputs[event].name, "mouse") == 0 ) { + mouse_lost = 1; + } + IDirectInputDevice2_Acquire(SDL_DIdev[event]); + result = IDirectInputDevice2_GetDeviceData( + SDL_DIdev[event], sizeof(DIDEVICEOBJECTDATA), + evtbuf, &numevents, 0); + } + /* Handle the events */ + if ( result == DI_OK && processInput ) { + /* Note: This can post multiple events to event queue + */ + (*SDL_DIfun[event])((int)numevents, evtbuf); + return(1); + } + } + if ( event != WAIT_TIMEOUT ) { + /* Maybe there was a windows message? */ + if ( PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE) ) { + if ( GetMessage(&msg, NULL, 0, 0) > 0 ) { + DispatchMessage(&msg); + } else { + return(-1); + } + return(1); + } + } + return(0); +} + +/* Change cooperative level based on whether or not we are fullscreen */ +void DX5_DInputReset(_THIS, int fullscreen) +{ + DWORD level; + int i; + HRESULT result; + HWND topwnd; + + for ( i=0; i 0 ) { + /* Loop and check again */; + } +} + +void DX5_InitOSKeymap(_THIS) +{ +#ifndef DIK_PAUSE +#define DIK_PAUSE 0xC5 +#endif +#ifndef DIK_OEM_102 +#define DIK_OEM_102 0x56 /* < > | on UK/Germany keyboards */ +#endif + int i; + + /* Map the DIK scancodes to SDL keysyms */ + for ( i=0; iscancode = (unsigned char)scancode; + keysym->sym = DIK_keymap[scancode]; + keysym->mod = KMOD_NONE; + keysym->unicode = 0; + if ( pressed && SDL_TranslateUNICODE ) { + UINT vkey; +#ifndef NO_GETKEYBOARDSTATE + BYTE keystate[256]; + Uint16 wchars[2]; +#endif + + vkey = MapVirtualKey(scancode, 1); +#ifdef NO_GETKEYBOARDSTATE + /* Uh oh, better hope the vkey is close enough.. */ + keysym->unicode = vkey; +#else + GetKeyboardState(keystate); + /* Numlock isn't taken into account in ToUnicode, + * so we handle it as a special case here */ + if ((keystate[VK_NUMLOCK] & 1) && vkey >= VK_NUMPAD0 && vkey <= VK_NUMPAD9) + { + keysym->unicode = vkey - VK_NUMPAD0 + '0'; + } + else if (SDL_ToUnicode(vkey, scancode, keystate, wchars, sizeof(wchars)/sizeof(wchars[0]), 0) > 0) + { + keysym->unicode = wchars[0]; + } +#endif /* NO_GETKEYBOARDSTATE */ + } + return(keysym); +} + +int DX5_CreateWindow(_THIS) +{ + char *windowid = SDL_getenv("SDL_WINDOWID"); + int i; + + /* Clear out DirectInput variables in case we fail */ + for ( i=0; i