| | |
| | | #include "../../events/SDL_events_c.h" |
| | | #include "../../events/SDL_touch_c.h" |
| | | #include "../../events/scancodes_windows.h" |
| | | #include "SDL_assert.h" |
| | | #include "SDL_hints.h" |
| | | |
| | | /* Dropfile support */ |
| | |
| | | #ifndef WM_MOUSEHWHEEL |
| | | #define WM_MOUSEHWHEEL 0x020E |
| | | #endif |
| | | #ifndef WM_POINTERUPDATE |
| | | #define WM_POINTERUPDATE 0x0245 |
| | | #endif |
| | | #ifndef WM_UNICHAR |
| | | #define WM_UNICHAR 0x0109 |
| | | #endif |
| | | |
| | | static SDL_Scancode |
| | | VKeytoScancode(WPARAM vkey) |
| | | VKeytoScancodeFallback(WPARAM vkey) |
| | | { |
| | | switch (vkey) { |
| | | /* Windows generates this virtual keycode for Keypad 5 when NumLock is off. |
| | | case VK_CLEAR: return SDL_SCANCODE_CLEAR; |
| | | */ |
| | | case VK_LEFT: return SDL_SCANCODE_LEFT; |
| | | case VK_UP: return SDL_SCANCODE_UP; |
| | | case VK_RIGHT: return SDL_SCANCODE_RIGHT; |
| | | case VK_DOWN: return SDL_SCANCODE_DOWN; |
| | | |
| | | default: return SDL_SCANCODE_UNKNOWN; |
| | | } |
| | | } |
| | | |
| | | static SDL_Scancode |
| | | VKeytoScancode(WPARAM vkey) |
| | | { |
| | | switch (vkey) { |
| | | case VK_MODECHANGE: return SDL_SCANCODE_MODE; |
| | | case VK_SELECT: return SDL_SCANCODE_SELECT; |
| | | case VK_EXECUTE: return SDL_SCANCODE_EXECUTE; |
| | |
| | | } |
| | | } |
| | | } |
| | | |
| | | /* The on-screen keyboard can generate VK_LEFT and VK_RIGHT events without a scancode |
| | | * value set, however we cannot simply map these in VKeytoScancode() or we will be |
| | | * incorrectly handling the arrow keys on the number pad when NumLock is disabled |
| | | * (which also generate VK_LEFT, VK_RIGHT, etc in that scenario). Instead, we'll only |
| | | * map them if none of the above special number pad mappings applied. */ |
| | | if (code == SDL_SCANCODE_UNKNOWN) { |
| | | code = VKeytoScancodeFallback(wParam); |
| | | } |
| | | |
| | | return code; |
| | | } |
| | | |
| | |
| | | } |
| | | |
| | | static void |
| | | WIN_CheckWParamMouseButton(SDL_bool bwParamMousePressed, SDL_bool bSDLMousePressed, SDL_WindowData *data, Uint8 button, SDL_MouseID mouseID) |
| | | WIN_CheckWParamMouseButton(SDL_bool bwParamMousePressed, Uint32 mouseFlags, SDL_bool bSwapButtons, SDL_WindowData *data, Uint8 button, SDL_MouseID mouseID) |
| | | { |
| | | if (bSwapButtons) { |
| | | if (button == SDL_BUTTON_LEFT) { |
| | | button = SDL_BUTTON_RIGHT; |
| | | } |
| | | else if (button == SDL_BUTTON_RIGHT) { |
| | | button = SDL_BUTTON_LEFT; |
| | | } |
| | | } |
| | | |
| | | if (data->focus_click_pending & SDL_BUTTON(button)) { |
| | | /* Ignore the button click for activation */ |
| | | if (!bwParamMousePressed) { |
| | |
| | | } |
| | | } |
| | | |
| | | if (bwParamMousePressed && !bSDLMousePressed) { |
| | | if (bwParamMousePressed && !(mouseFlags & SDL_BUTTON(button))) { |
| | | SDL_SendMouseButton(data->window, mouseID, SDL_PRESSED, button); |
| | | } else if (!bwParamMousePressed && bSDLMousePressed) { |
| | | } else if (!bwParamMousePressed && (mouseFlags & SDL_BUTTON(button))) { |
| | | SDL_SendMouseButton(data->window, mouseID, SDL_RELEASED, button); |
| | | } |
| | | } |
| | |
| | | { |
| | | if (wParam != data->mouse_button_flags) { |
| | | Uint32 mouseFlags = SDL_GetMouseState(NULL, NULL); |
| | | WIN_CheckWParamMouseButton((wParam & MK_LBUTTON), (mouseFlags & SDL_BUTTON_LMASK), data, SDL_BUTTON_LEFT, mouseID); |
| | | WIN_CheckWParamMouseButton((wParam & MK_MBUTTON), (mouseFlags & SDL_BUTTON_MMASK), data, SDL_BUTTON_MIDDLE, mouseID); |
| | | WIN_CheckWParamMouseButton((wParam & MK_RBUTTON), (mouseFlags & SDL_BUTTON_RMASK), data, SDL_BUTTON_RIGHT, mouseID); |
| | | WIN_CheckWParamMouseButton((wParam & MK_XBUTTON1), (mouseFlags & SDL_BUTTON_X1MASK), data, SDL_BUTTON_X1, mouseID); |
| | | WIN_CheckWParamMouseButton((wParam & MK_XBUTTON2), (mouseFlags & SDL_BUTTON_X2MASK), data, SDL_BUTTON_X2, mouseID); |
| | | |
| | | /* WM_LBUTTONDOWN and friends handle button swapping for us. No need to check SM_SWAPBUTTON here. */ |
| | | WIN_CheckWParamMouseButton((wParam & MK_LBUTTON), mouseFlags, SDL_FALSE, data, SDL_BUTTON_LEFT, mouseID); |
| | | WIN_CheckWParamMouseButton((wParam & MK_MBUTTON), mouseFlags, SDL_FALSE, data, SDL_BUTTON_MIDDLE, mouseID); |
| | | WIN_CheckWParamMouseButton((wParam & MK_RBUTTON), mouseFlags, SDL_FALSE, data, SDL_BUTTON_RIGHT, mouseID); |
| | | WIN_CheckWParamMouseButton((wParam & MK_XBUTTON1), mouseFlags, SDL_FALSE, data, SDL_BUTTON_X1, mouseID); |
| | | WIN_CheckWParamMouseButton((wParam & MK_XBUTTON2), mouseFlags, SDL_FALSE, data, SDL_BUTTON_X2, mouseID); |
| | | |
| | | data->mouse_button_flags = wParam; |
| | | } |
| | | } |
| | |
| | | { |
| | | if (rawButtons != data->mouse_button_flags) { |
| | | Uint32 mouseFlags = SDL_GetMouseState(NULL, NULL); |
| | | SDL_bool swapButtons = GetSystemMetrics(SM_SWAPBUTTON) != 0; |
| | | if ((rawButtons & RI_MOUSE_BUTTON_1_DOWN)) |
| | | WIN_CheckWParamMouseButton((rawButtons & RI_MOUSE_BUTTON_1_DOWN), (mouseFlags & SDL_BUTTON_LMASK), data, SDL_BUTTON_LEFT, 0); |
| | | WIN_CheckWParamMouseButton((rawButtons & RI_MOUSE_BUTTON_1_DOWN), mouseFlags, swapButtons, data, SDL_BUTTON_LEFT, 0); |
| | | if ((rawButtons & RI_MOUSE_BUTTON_1_UP)) |
| | | WIN_CheckWParamMouseButton(!(rawButtons & RI_MOUSE_BUTTON_1_UP), (mouseFlags & SDL_BUTTON_LMASK), data, SDL_BUTTON_LEFT, 0); |
| | | WIN_CheckWParamMouseButton(!(rawButtons & RI_MOUSE_BUTTON_1_UP), mouseFlags, swapButtons, data, SDL_BUTTON_LEFT, 0); |
| | | if ((rawButtons & RI_MOUSE_BUTTON_2_DOWN)) |
| | | WIN_CheckWParamMouseButton((rawButtons & RI_MOUSE_BUTTON_2_DOWN), (mouseFlags & SDL_BUTTON_RMASK), data, SDL_BUTTON_RIGHT, 0); |
| | | WIN_CheckWParamMouseButton((rawButtons & RI_MOUSE_BUTTON_2_DOWN), mouseFlags, swapButtons, data, SDL_BUTTON_RIGHT, 0); |
| | | if ((rawButtons & RI_MOUSE_BUTTON_2_UP)) |
| | | WIN_CheckWParamMouseButton(!(rawButtons & RI_MOUSE_BUTTON_2_UP), (mouseFlags & SDL_BUTTON_RMASK), data, SDL_BUTTON_RIGHT, 0); |
| | | WIN_CheckWParamMouseButton(!(rawButtons & RI_MOUSE_BUTTON_2_UP), mouseFlags, swapButtons, data, SDL_BUTTON_RIGHT, 0); |
| | | if ((rawButtons & RI_MOUSE_BUTTON_3_DOWN)) |
| | | WIN_CheckWParamMouseButton((rawButtons & RI_MOUSE_BUTTON_3_DOWN), (mouseFlags & SDL_BUTTON_MMASK), data, SDL_BUTTON_MIDDLE, 0); |
| | | WIN_CheckWParamMouseButton((rawButtons & RI_MOUSE_BUTTON_3_DOWN), mouseFlags, swapButtons, data, SDL_BUTTON_MIDDLE, 0); |
| | | if ((rawButtons & RI_MOUSE_BUTTON_3_UP)) |
| | | WIN_CheckWParamMouseButton(!(rawButtons & RI_MOUSE_BUTTON_3_UP), (mouseFlags & SDL_BUTTON_MMASK), data, SDL_BUTTON_MIDDLE, 0); |
| | | WIN_CheckWParamMouseButton(!(rawButtons & RI_MOUSE_BUTTON_3_UP), mouseFlags, swapButtons, data, SDL_BUTTON_MIDDLE, 0); |
| | | if ((rawButtons & RI_MOUSE_BUTTON_4_DOWN)) |
| | | WIN_CheckWParamMouseButton((rawButtons & RI_MOUSE_BUTTON_4_DOWN), (mouseFlags & SDL_BUTTON_X1MASK), data, SDL_BUTTON_X1, 0); |
| | | WIN_CheckWParamMouseButton((rawButtons & RI_MOUSE_BUTTON_4_DOWN), mouseFlags, swapButtons, data, SDL_BUTTON_X1, 0); |
| | | if ((rawButtons & RI_MOUSE_BUTTON_4_UP)) |
| | | WIN_CheckWParamMouseButton(!(rawButtons & RI_MOUSE_BUTTON_4_UP), (mouseFlags & SDL_BUTTON_X1MASK), data, SDL_BUTTON_X1, 0); |
| | | WIN_CheckWParamMouseButton(!(rawButtons & RI_MOUSE_BUTTON_4_UP), mouseFlags, swapButtons, data, SDL_BUTTON_X1, 0); |
| | | if ((rawButtons & RI_MOUSE_BUTTON_5_DOWN)) |
| | | WIN_CheckWParamMouseButton((rawButtons & RI_MOUSE_BUTTON_5_DOWN), (mouseFlags & SDL_BUTTON_X2MASK), data, SDL_BUTTON_X2, 0); |
| | | WIN_CheckWParamMouseButton((rawButtons & RI_MOUSE_BUTTON_5_DOWN), mouseFlags, swapButtons, data, SDL_BUTTON_X2, 0); |
| | | if ((rawButtons & RI_MOUSE_BUTTON_5_UP)) |
| | | WIN_CheckWParamMouseButton(!(rawButtons & RI_MOUSE_BUTTON_5_UP), (mouseFlags & SDL_BUTTON_X2MASK), data, SDL_BUTTON_X2, 0); |
| | | WIN_CheckWParamMouseButton(!(rawButtons & RI_MOUSE_BUTTON_5_UP), mouseFlags, swapButtons, data, SDL_BUTTON_X2, 0); |
| | | data->mouse_button_flags = rawButtons; |
| | | } |
| | | } |
| | |
| | | { |
| | | Uint32 mouseFlags; |
| | | SHORT keyState; |
| | | SDL_bool swapButtons; |
| | | |
| | | /* mouse buttons may have changed state here, we need to resync them, |
| | | but we will get a WM_MOUSEMOVE right away which will fix things up if in non raw mode also |
| | | */ |
| | | mouseFlags = SDL_GetMouseState(NULL, NULL); |
| | | swapButtons = GetSystemMetrics(SM_SWAPBUTTON) != 0; |
| | | |
| | | keyState = GetAsyncKeyState(VK_LBUTTON); |
| | | if (!(keyState & 0x8000)) { |
| | | WIN_CheckWParamMouseButton(SDL_FALSE, (mouseFlags & SDL_BUTTON_LMASK), data, SDL_BUTTON_LEFT, 0); |
| | | WIN_CheckWParamMouseButton(SDL_FALSE, mouseFlags, swapButtons, data, SDL_BUTTON_LEFT, 0); |
| | | } |
| | | keyState = GetAsyncKeyState(VK_RBUTTON); |
| | | if (!(keyState & 0x8000)) { |
| | | WIN_CheckWParamMouseButton(SDL_FALSE, (mouseFlags & SDL_BUTTON_RMASK), data, SDL_BUTTON_RIGHT, 0); |
| | | WIN_CheckWParamMouseButton(SDL_FALSE, mouseFlags, swapButtons, data, SDL_BUTTON_RIGHT, 0); |
| | | } |
| | | keyState = GetAsyncKeyState(VK_MBUTTON); |
| | | if (!(keyState & 0x8000)) { |
| | | WIN_CheckWParamMouseButton(SDL_FALSE, (mouseFlags & SDL_BUTTON_MMASK), data, SDL_BUTTON_MIDDLE, 0); |
| | | WIN_CheckWParamMouseButton(SDL_FALSE, mouseFlags, swapButtons, data, SDL_BUTTON_MIDDLE, 0); |
| | | } |
| | | keyState = GetAsyncKeyState(VK_XBUTTON1); |
| | | if (!(keyState & 0x8000)) { |
| | | WIN_CheckWParamMouseButton(SDL_FALSE, (mouseFlags & SDL_BUTTON_X1MASK), data, SDL_BUTTON_X1, 0); |
| | | WIN_CheckWParamMouseButton(SDL_FALSE, mouseFlags, swapButtons, data, SDL_BUTTON_X1, 0); |
| | | } |
| | | keyState = GetAsyncKeyState(VK_XBUTTON2); |
| | | if (!(keyState & 0x8000)) { |
| | | WIN_CheckWParamMouseButton(SDL_FALSE, (mouseFlags & SDL_BUTTON_X2MASK), data, SDL_BUTTON_X2, 0); |
| | | WIN_CheckWParamMouseButton(SDL_FALSE, mouseFlags, swapButtons, data, SDL_BUTTON_X2, 0); |
| | | } |
| | | data->mouse_button_flags = 0; |
| | | } |
| | |
| | | break; |
| | | } |
| | | if (LOWORD(wParam) == WA_CLICKACTIVE) { |
| | | SDL_bool swapButtons = GetSystemMetrics(SM_SWAPBUTTON) != 0; |
| | | if (GetAsyncKeyState(VK_LBUTTON)) { |
| | | data->focus_click_pending |= SDL_BUTTON_LMASK; |
| | | data->focus_click_pending |= !swapButtons ? SDL_BUTTON_LMASK : SDL_BUTTON_RMASK; |
| | | } |
| | | if (GetAsyncKeyState(VK_RBUTTON)) { |
| | | data->focus_click_pending |= SDL_BUTTON_RMASK; |
| | | data->focus_click_pending |= !swapButtons ? SDL_BUTTON_RMASK : SDL_BUTTON_LMASK; |
| | | } |
| | | if (GetAsyncKeyState(VK_MBUTTON)) { |
| | | data->focus_click_pending |= SDL_BUTTON_MMASK; |
| | |
| | | SDL_SendMouseMotion(data->window, 0, 0, cursorPos.x, cursorPos.y); |
| | | |
| | | WIN_CheckAsyncMouseRelease(data); |
| | | WIN_UpdateClipCursor(data->window); |
| | | |
| | | /* |
| | | * FIXME: Update keyboard state |
| | |
| | | returnCode = 0; |
| | | break; |
| | | |
| | | case WM_POINTERUPDATE: |
| | | { |
| | | data->last_pointer_update = lParam; |
| | | break; |
| | | } |
| | | |
| | | case WM_MOUSEMOVE: |
| | | { |
| | | SDL_Mouse *mouse = SDL_GetMouse(); |
| | | if (!mouse->relative_mode || mouse->relative_mode_warp) { |
| | | /* Only generate mouse events for real mouse */ |
| | | if (GetMouseMessageSource() != SDL_MOUSE_EVENT_SOURCE_TOUCH) { |
| | | if (GetMouseMessageSource() != SDL_MOUSE_EVENT_SOURCE_TOUCH && |
| | | lParam != data->last_pointer_update) { |
| | | SDL_SendMouseMotion(data->window, 0, 0, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)); |
| | | if (isWin10FCUorNewer && mouse->relative_mode_warp) { |
| | | /* To work around #3931, Win10 bug introduced in Fall Creators Update, where |
| | |
| | | { |
| | | SDL_Mouse *mouse = SDL_GetMouse(); |
| | | if (!mouse->relative_mode || mouse->relative_mode_warp) { |
| | | if (GetMouseMessageSource() != SDL_MOUSE_EVENT_SOURCE_TOUCH) { |
| | | if (GetMouseMessageSource() != SDL_MOUSE_EVENT_SOURCE_TOUCH && |
| | | lParam != data->last_pointer_update) { |
| | | WIN_CheckWParamMouseButtons(wParam, data, 0); |
| | | } |
| | | } |
| | |
| | | |
| | | /* Mouse data (ignoring synthetic mouse events generated for touchscreens) */ |
| | | if (inp.header.dwType == RIM_TYPEMOUSE) { |
| | | if (GetMouseMessageSource() == SDL_MOUSE_EVENT_SOURCE_TOUCH) { |
| | | if (GetMouseMessageSource() == SDL_MOUSE_EVENT_SOURCE_TOUCH || |
| | | (GetMessageExtraInfo() & 0x82) == 0x82) { |
| | | break; |
| | | } |
| | | if (isRelative) { |
| | |
| | | |
| | | if ((rawmouse->usFlags & 0x01) == MOUSE_MOVE_RELATIVE) { |
| | | SDL_SendMouseMotion(data->window, 0, 1, (int)rawmouse->lLastX, (int)rawmouse->lLastY); |
| | | } else { |
| | | } else if (rawmouse->lLastX || rawmouse->lLastY) { |
| | | /* synthesize relative moves from the abs position */ |
| | | static SDL_Point lastMousePoint; |
| | | SDL_bool virtual_desktop = (rawmouse->usFlags & MOUSE_VIRTUAL_DESKTOP) ? SDL_TRUE : SDL_FALSE; |
| | |
| | | |
| | | /* if in the window, WM_MOUSEMOVE, etc, will cover it. */ |
| | | if(currentHnd != hwnd || pt.x < 0 || pt.y < 0 || pt.x > hwndRect.right || pt.y > hwndRect.right) { |
| | | SDL_bool swapButtons = GetSystemMetrics(SM_SWAPBUTTON) != 0; |
| | | |
| | | SDL_SendMouseMotion(data->window, 0, 0, (int)pt.x, (int)pt.y); |
| | | SDL_SendMouseButton(data->window, 0, GetAsyncKeyState(VK_LBUTTON) & 0x8000 ? SDL_PRESSED : SDL_RELEASED, SDL_BUTTON_LEFT); |
| | | SDL_SendMouseButton(data->window, 0, GetAsyncKeyState(VK_RBUTTON) & 0x8000 ? SDL_PRESSED : SDL_RELEASED, SDL_BUTTON_RIGHT); |
| | | SDL_SendMouseButton(data->window, 0, GetAsyncKeyState(VK_LBUTTON) & 0x8000 ? SDL_PRESSED : SDL_RELEASED, !swapButtons ? SDL_BUTTON_LEFT : SDL_BUTTON_RIGHT); |
| | | SDL_SendMouseButton(data->window, 0, GetAsyncKeyState(VK_RBUTTON) & 0x8000 ? SDL_PRESSED : SDL_RELEASED, !swapButtons ? SDL_BUTTON_RIGHT : SDL_BUTTON_LEFT); |
| | | SDL_SendMouseButton(data->window, 0, GetAsyncKeyState(VK_MBUTTON) & 0x8000 ? SDL_PRESSED : SDL_RELEASED, SDL_BUTTON_MIDDLE); |
| | | SDL_SendMouseButton(data->window, 0, GetAsyncKeyState(VK_XBUTTON1) & 0x8000 ? SDL_PRESSED : SDL_RELEASED, SDL_BUTTON_X1); |
| | | SDL_SendMouseButton(data->window, 0, GetAsyncKeyState(VK_XBUTTON2) & 0x8000 ? SDL_PRESSED : SDL_RELEASED, SDL_BUTTON_X2); |
| | |
| | | } |
| | | break; |
| | | |
| | | case WM_DISPLAYCHANGE: |
| | | { |
| | | // Reacquire displays if any were added or removed |
| | | WIN_RefreshDisplays(SDL_GetVideoDevice()); |
| | | } |
| | | break; |
| | | |
| | | case WM_NCCALCSIZE: |
| | | { |
| | | Uint32 window_flags = SDL_GetWindowFlags(data->window); |
| | |
| | | { |
| | | SDL_VideoDevice *_this = SDL_GetVideoDevice(); |
| | | SDL_Window *window; |
| | | Uint32 now = SDL_GetTicks(); |
| | | const Uint32 CLIPCURSOR_UPDATE_INTERVAL_MS = 3000; |
| | | |
| | | if (_this) { |
| | | for (window = _this->windows; window; window = window->next) { |
| | | if (window->driverdata) { |
| | | SDL_WindowData *data = (SDL_WindowData *)window->driverdata; |
| | | if (data) { |
| | | if (data->skip_update_clipcursor) { |
| | | data->skip_update_clipcursor = SDL_FALSE; |
| | | WIN_UpdateClipCursor(window); |
| | | } else if ((now - data->last_updated_clipcursor) >= CLIPCURSOR_UPDATE_INTERVAL_MS) { |
| | | WIN_UpdateClipCursor(window); |
| | | } |
| | | } |
| | | } |
| | | } |