From 03f8528315fa46c95991a34f3325d7b33ae5538c Mon Sep 17 00:00:00 2001
From: Edward Rudd <urkle@outoforder.cc>
Date: Sat, 02 May 2020 21:48:36 +0000
Subject: [PATCH] Update source to SDL2 2.0.12
---
source/src/video/windows/SDL_windowsevents.c | 175 +++++++++++++++++++++++++++++++++++++++++-----------------
1 files changed, 124 insertions(+), 51 deletions(-)
diff --git a/source/src/video/windows/SDL_windowsevents.c b/source/src/video/windows/SDL_windowsevents.c
index e961cf5..d79d42c 100644
--- a/source/src/video/windows/SDL_windowsevents.c
+++ b/source/src/video/windows/SDL_windowsevents.c
@@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
- Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
+ Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
@@ -47,9 +47,6 @@
#include "wmmsg.h"
#endif
-/* For processing mouse WM_*BUTTON* and WM_MOUSEMOVE message-data from GetMessageExtraInfo() */
-#define MOUSEEVENTF_FROMTOUCH 0xFF515700
-
/* Masks for processing the windows KEYDOWN and KEYUP messages */
#define REPEATED_KEYMASK (1<<30)
#define EXTENDED_KEYMASK (1<<24)
@@ -86,7 +83,14 @@
VKeytoScancode(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;
+
case VK_MODECHANGE: return SDL_SCANCODE_MODE;
case VK_SELECT: return SDL_SCANCODE_SELECT;
case VK_EXECUTE: return SDL_SCANCODE_EXECUTE;
@@ -244,7 +248,7 @@
/*
* Some windows systems fail to send a WM_LBUTTONDOWN sometimes, but each mouse move contains the current button state also
-* so this funciton reconciles our view of the world with the current buttons reported by windows
+* so this function reconciles our view of the world with the current buttons reported by windows
*/
static void
WIN_CheckWParamMouseButtons(WPARAM wParam, SDL_WindowData *data, SDL_MouseID mouseID)
@@ -259,7 +263,6 @@
data->mouse_button_flags = wParam;
}
}
-
static void
WIN_CheckRawMouseButtons(ULONG rawButtons, SDL_WindowData *data)
@@ -362,6 +365,37 @@
This is used to implement a workaround.. */
static SDL_bool isWin10FCUorNewer = SDL_FALSE;
+/* We want to generate mouse events from mouse and pen, and touch events from touchscreens */
+#define MI_WP_SIGNATURE 0xFF515700
+#define MI_WP_SIGNATURE_MASK 0xFFFFFF00
+#define IsTouchEvent(dw) ((dw) & MI_WP_SIGNATURE_MASK) == MI_WP_SIGNATURE
+
+typedef enum
+{
+ SDL_MOUSE_EVENT_SOURCE_UNKNOWN,
+ SDL_MOUSE_EVENT_SOURCE_MOUSE,
+ SDL_MOUSE_EVENT_SOURCE_TOUCH,
+ SDL_MOUSE_EVENT_SOURCE_PEN,
+} SDL_MOUSE_EVENT_SOURCE;
+
+static SDL_MOUSE_EVENT_SOURCE GetMouseMessageSource()
+{
+ LPARAM extrainfo = GetMessageExtraInfo();
+ /* Mouse data (ignoring synthetic mouse events generated for touchscreens) */
+ /* Versions below Vista will set the low 7 bits to the Mouse ID and don't use bit 7:
+ Check bits 8-32 for the signature (which will indicate a Tablet PC Pen or Touch Device).
+ Only check bit 7 when Vista and up(Cleared=Pen, Set=Touch(which we need to filter out)),
+ when the signature is set. The Mouse ID will be zero for an actual mouse. */
+ if (IsTouchEvent(extrainfo)) {
+ if (extrainfo & 0x80) {
+ return SDL_MOUSE_EVENT_SOURCE_TOUCH;
+ } else {
+ return SDL_MOUSE_EVENT_SOURCE_PEN;
+ }
+ }
+ return SDL_MOUSE_EVENT_SOURCE_MOUSE;
+}
+
LRESULT CALLBACK
WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
@@ -426,13 +460,12 @@
POINT cursorPos;
BOOL minimized;
- /* Don't mark the window as shown if it's activated before being shown */
- if (!IsWindowVisible(hwnd)) {
- break;
- }
-
minimized = HIWORD(wParam);
if (!minimized && (LOWORD(wParam) != WA_INACTIVE)) {
+ /* Don't mark the window as shown if it's activated before being shown */
+ if (!IsWindowVisible(hwnd)) {
+ break;
+ }
if (LOWORD(wParam) == WA_CLICKACTIVE) {
if (GetAsyncKeyState(VK_LBUTTON)) {
data->focus_click_pending |= SDL_BUTTON_LMASK;
@@ -450,7 +483,7 @@
data->focus_click_pending |= SDL_BUTTON_X2MASK;
}
}
-
+
SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_SHOWN, 0, 0);
if (SDL_GetKeyboardFocus() != data->window) {
SDL_SetKeyboardFocus(data->window);
@@ -479,7 +512,7 @@
WIN_ResetDeadKeys();
}
- if (GetClipCursor(&rect) && SDL_memcmp(&rect, &data->cursor_clipped_rect, sizeof(rect) == 0)) {
+ if (GetClipCursor(&rect) && SDL_memcmp(&rect, &data->cursor_clipped_rect, sizeof(rect)) == 0) {
ClipCursor(NULL);
SDL_zero(data->cursor_clipped_rect);
}
@@ -494,19 +527,24 @@
{
SDL_Mouse *mouse = SDL_GetMouse();
if (!mouse->relative_mode || mouse->relative_mode_warp) {
- SDL_MouseID mouseID = (((GetMessageExtraInfo() & MOUSEEVENTF_FROMTOUCH) == MOUSEEVENTF_FROMTOUCH) ? SDL_TOUCH_MOUSEID : 0);
- SDL_SendMouseMotion(data->window, mouseID, 0, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
- if (isWin10FCUorNewer && mouseID != SDL_TOUCH_MOUSEID && mouse->relative_mode_warp) {
- /* To work around #3931, Win10 bug introduced in Fall Creators Update, where
- SetCursorPos() (SDL_WarpMouseInWindow()) doesn't reliably generate mouse events anymore,
- after each windows mouse event generate a fake event for the middle of the window
- if relative_mode_warp is used */
- int center_x = 0, center_y = 0;
- SDL_GetWindowSize(data->window, ¢er_x, ¢er_y);
- center_x /= 2;
- center_y /= 2;
- SDL_SendMouseMotion(data->window, mouseID, 0, center_x, center_y);
+ /* Only generate mouse events for real mouse */
+ if (GetMouseMessageSource() != SDL_MOUSE_EVENT_SOURCE_TOUCH) {
+ 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
+ SetCursorPos() (SDL_WarpMouseInWindow()) doesn't reliably generate mouse events anymore,
+ after each windows mouse event generate a fake event for the middle of the window
+ if relative_mode_warp is used */
+ int center_x = 0, center_y = 0;
+ SDL_GetWindowSize(data->window, ¢er_x, ¢er_y);
+ center_x /= 2;
+ center_y /= 2;
+ SDL_SendMouseMotion(data->window, 0, 0, center_x, center_y);
+ }
}
+ } else {
+ /* We still need to update focus */
+ SDL_SetMouseFocus(data->window);
}
}
/* don't break here, fall through to check the wParam like the button presses */
@@ -525,8 +563,9 @@
{
SDL_Mouse *mouse = SDL_GetMouse();
if (!mouse->relative_mode || mouse->relative_mode_warp) {
- SDL_MouseID mouseID = (((GetMessageExtraInfo() & MOUSEEVENTF_FROMTOUCH) == MOUSEEVENTF_FROMTOUCH) ? SDL_TOUCH_MOUSEID : 0);
- WIN_CheckWParamMouseButtons(wParam, data, mouseID);
+ if (GetMouseMessageSource() != SDL_MOUSE_EVENT_SOURCE_TOUCH) {
+ WIN_CheckWParamMouseButtons(wParam, data, 0);
+ }
}
}
break;
@@ -548,8 +587,11 @@
GetRawInputData(hRawInput, RID_INPUT, &inp, &size, sizeof(RAWINPUTHEADER));
- /* Mouse data */
+ /* Mouse data (ignoring synthetic mouse events generated for touchscreens) */
if (inp.header.dwType == RIM_TYPEMOUSE) {
+ if (GetMouseMessageSource() == SDL_MOUSE_EVENT_SOURCE_TOUCH) {
+ break;
+ }
if (isRelative) {
RAWMOUSE* rawmouse = &inp.data.mouse;
@@ -557,16 +599,22 @@
SDL_SendMouseMotion(data->window, 0, 1, (int)rawmouse->lLastX, (int)rawmouse->lLastY);
} else {
/* synthesize relative moves from the abs position */
- static SDL_Point initialMousePoint;
- if (initialMousePoint.x == 0 && initialMousePoint.y == 0) {
- initialMousePoint.x = rawmouse->lLastX;
- initialMousePoint.y = rawmouse->lLastY;
+ static SDL_Point lastMousePoint;
+ SDL_bool virtual_desktop = (rawmouse->usFlags & MOUSE_VIRTUAL_DESKTOP) ? SDL_TRUE : SDL_FALSE;
+ int w = GetSystemMetrics(virtual_desktop ? SM_CXVIRTUALSCREEN : SM_CXSCREEN);
+ int h = GetSystemMetrics(virtual_desktop ? SM_CYVIRTUALSCREEN : SM_CYSCREEN);
+ int x = (int)(((float)rawmouse->lLastX / 65535.0f) * w);
+ int y = (int)(((float)rawmouse->lLastY / 65535.0f) * h);
+
+ if (lastMousePoint.x == 0 && lastMousePoint.y == 0) {
+ lastMousePoint.x = x;
+ lastMousePoint.y = y;
}
- SDL_SendMouseMotion(data->window, 0, 1, (int)(rawmouse->lLastX-initialMousePoint.x), (int)(rawmouse->lLastY-initialMousePoint.y));
+ SDL_SendMouseMotion(data->window, 0, 1, (int)(x-lastMousePoint.x), (int)(y-lastMousePoint.y));
- initialMousePoint.x = rawmouse->lLastX;
- initialMousePoint.y = rawmouse->lLastY;
+ lastMousePoint.x = x;
+ lastMousePoint.y = y;
}
WIN_CheckRawMouseButtons(rawmouse->usButtonFlags, data);
} else if (isCapture) {
@@ -612,10 +660,21 @@
case WM_MOUSELEAVE:
if (SDL_GetMouseFocus() == data->window && !SDL_GetMouse()->relative_mode && !(data->window->flags & SDL_WINDOW_MOUSE_CAPTURE)) {
if (!IsIconic(hwnd)) {
+ SDL_Mouse *mouse;
POINT cursorPos;
GetCursorPos(&cursorPos);
ScreenToClient(hwnd, &cursorPos);
- SDL_SendMouseMotion(data->window, 0, 0, cursorPos.x, cursorPos.y);
+ mouse = SDL_GetMouse();
+ if (!mouse->was_touch_mouse_events) { /* we're not a touch handler causing a mouse leave? */
+ SDL_SendMouseMotion(data->window, 0, 0, cursorPos.x, cursorPos.y);
+ } else { /* touch handling? */
+ mouse->was_touch_mouse_events = SDL_FALSE; /* not anymore */
+ if (mouse->touch_mouse_events) { /* convert touch to mouse events */
+ SDL_SendMouseMotion(data->window, SDL_TOUCH_MOUSEID, 0, cursorPos.x, cursorPos.y);
+ } else { /* normal handling */
+ SDL_SendMouseMotion(data->window, 0, 0, cursorPos.x, cursorPos.y);
+ }
+ }
}
SDL_SetMouseFocus(NULL);
}
@@ -714,8 +773,9 @@
int max_w, max_h;
BOOL constrain_max_size;
- if (SDL_IsShapedWindow(data->window))
+ if (SDL_IsShapedWindow(data->window)) {
Win32_ResizeWindowShape(data->window);
+ }
/* If this is an expected size change, allow it */
if (data->expected_resize) {
@@ -817,8 +877,7 @@
w = rect.right - rect.left;
h = rect.bottom - rect.top;
- SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_RESIZED, w,
- h);
+ SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_RESIZED, w, h);
/* Forces a WM_PAINT event */
InvalidateRect(hwnd, NULL, FALSE);
@@ -867,8 +926,7 @@
RECT rect;
if (GetUpdateRect(hwnd, &rect, FALSE)) {
ValidateRect(hwnd, NULL);
- SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_EXPOSED,
- 0, 0);
+ SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_EXPOSED, 0, 0);
}
}
returnCode = 0;
@@ -908,7 +966,8 @@
case WM_TOUCH:
if (data->videodata->GetTouchInputInfo && data->videodata->CloseTouchInputHandle) {
UINT i, num_inputs = LOWORD(wParam);
- PTOUCHINPUT inputs = SDL_stack_alloc(TOUCHINPUT, num_inputs);
+ SDL_bool isstack;
+ PTOUCHINPUT inputs = SDL_small_alloc(TOUCHINPUT, num_inputs, &isstack);
if (data->videodata->GetTouchInputInfo((HTOUCHINPUT)lParam, num_inputs, inputs, sizeof(TOUCHINPUT))) {
RECT rect;
float x, y;
@@ -916,7 +975,7 @@
if (!GetClientRect(hwnd, &rect) ||
(rect.right == rect.left && rect.bottom == rect.top)) {
if (inputs) {
- SDL_stack_free(inputs);
+ SDL_small_free(inputs, isstack);
}
break;
}
@@ -931,7 +990,11 @@
PTOUCHINPUT input = &inputs[i];
const SDL_TouchID touchId = (SDL_TouchID)((size_t)input->hSource);
- if (SDL_AddTouch(touchId, "") < 0) {
+
+ /* TODO: Can we use GetRawInputDeviceInfo and HID info to
+ determine if this is a direct or indirect touch device?
+ */
+ if (SDL_AddTouch(touchId, SDL_TOUCH_DEVICE_DIRECT, "") < 0) {
continue;
}
@@ -940,17 +1003,17 @@
y = (float)(input->y - rect.top)/(rect.bottom - rect.top);
if (input->dwFlags & TOUCHEVENTF_DOWN) {
- SDL_SendTouch(touchId, input->dwID, SDL_TRUE, x, y, 1.0f);
+ SDL_SendTouch(touchId, input->dwID, data->window, SDL_TRUE, x, y, 1.0f);
}
if (input->dwFlags & TOUCHEVENTF_MOVE) {
- SDL_SendTouchMotion(touchId, input->dwID, x, y, 1.0f);
+ SDL_SendTouchMotion(touchId, input->dwID, data->window, x, y, 1.0f);
}
if (input->dwFlags & TOUCHEVENTF_UP) {
- SDL_SendTouch(touchId, input->dwID, SDL_FALSE, x, y, 1.0f);
+ SDL_SendTouch(touchId, input->dwID, data->window, SDL_FALSE, x, y, 1.0f);
}
}
}
- SDL_stack_free(inputs);
+ SDL_small_free(inputs, isstack);
data->videodata->CloseTouchInputHandle((HTOUCHINPUT)lParam);
return 0;
@@ -963,15 +1026,16 @@
HDROP drop = (HDROP) wParam;
UINT count = DragQueryFile(drop, 0xFFFFFFFF, NULL, 0);
for (i = 0; i < count; ++i) {
+ SDL_bool isstack;
UINT size = DragQueryFile(drop, i, NULL, 0) + 1;
- LPTSTR buffer = SDL_stack_alloc(TCHAR, size);
+ LPTSTR buffer = SDL_small_alloc(TCHAR, size, &isstack);
if (buffer) {
if (DragQueryFile(drop, i, buffer, size)) {
char *file = WIN_StringToUTF8(buffer);
SDL_SendDropFile(data->window, file);
SDL_free(file);
}
- SDL_stack_free(buffer);
+ SDL_small_free(buffer, isstack);
}
}
SDL_SendDropComplete(data->window);
@@ -1067,6 +1131,7 @@
const Uint8 *keystate;
MSG msg;
DWORD start_ticks = GetTickCount();
+ int new_messages = 0;
if (g_WindowsEnableMessageLoop) {
while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
@@ -1080,7 +1145,15 @@
/* Make sure we don't busy loop here forever if there are lots of events coming in */
if (SDL_TICKS_PASSED(msg.time, start_ticks)) {
- break;
+ /* We might get a few new messages generated by the Steam overlay or other application hooks
+ In this case those messages will be processed before any pending input, so we want to continue after those messages.
+ (thanks to Peter Deayton for his investigation here)
+ */
+ const int MAX_NEW_MESSAGES = 3;
+ ++new_messages;
+ if (new_messages > MAX_NEW_MESSAGES) {
+ break;
+ }
}
}
}
--
Gitblit v1.9.3