Updated rawinput patchsets

This is a completely updated rawinput patchsets from Rémi Bernon,
replacing the current user32-rawinput.
This commit is contained in:
Alistair Leslie-Hughes
2019-12-23 20:03:44 +11:00
parent a8cb853708
commit 8218a78955
48 changed files with 4509 additions and 1595 deletions

View File

@@ -0,0 +1,262 @@
From fe1ae8a2e1ee05143a9a0b7248420edada9bc09d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
Date: Thu, 14 Nov 2019 16:41:43 +0100
Subject: [PATCH 01/12] user32/tests: Add rawinput test for ClipCursor
interactions.
This shows unexpected rawinput messages triggered from cursor clipping.
The sleeps are required to let native cursor clipping time to activate.
We also repeat the clipping multiple times to be increase the chances
that the counts will be wrong as it doesn't always trigger.
---
dlls/user32/tests/input.c | 226 ++++++++++++++++++++++++++++++++++++++
1 file changed, 226 insertions(+)
diff --git a/dlls/user32/tests/input.c b/dlls/user32/tests/input.c
index 478c269017a..bf9d19906a8 100644
--- a/dlls/user32/tests/input.c
+++ b/dlls/user32/tests/input.c
@@ -1826,6 +1826,231 @@ static void test_RegisterRawInputDevices(void)
DestroyWindow(hwnd);
}
+static int rawinput_received;
+static int rawinput_received_foreground;
+static int rawinput_motion_x;
+static int rawinput_motion_y;
+static HANDLE rawinput_wndproc_done;
+
+static LRESULT CALLBACK rawinput_wndproc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
+{
+ UINT ret, raw_size;
+ RAWINPUT raw;
+
+ if (msg == WM_INPUT)
+ {
+ rawinput_received++;
+
+ ok(wparam == RIM_INPUT || wparam == RIM_INPUTSINK, "Unexpected wparam: %lu\n", wparam);
+ if (wparam == RIM_INPUT)
+ rawinput_received_foreground++;
+
+ ret = GetRawInputData((HRAWINPUT)lparam, RID_INPUT, NULL, &raw_size, sizeof(RAWINPUTHEADER));
+ ok(ret == 0, "GetRawInputData failed\n");
+ ok(raw_size <= sizeof(raw), "Unexpected rawinput data size: %u", raw_size);
+
+ if (raw_size <= sizeof(raw))
+ {
+ ret = GetRawInputData((HRAWINPUT)lparam, RID_INPUT, &raw, &raw_size, sizeof(RAWINPUTHEADER));
+ ok(ret > 0 && ret != (UINT)-1, "GetRawInputData failed\n");
+ ok(raw.header.dwType == RIM_TYPEMOUSE, "Unexpected rawinput type: %u\n", raw.header.dwType);
+
+ if (raw.header.dwType == RIM_TYPEMOUSE)
+ {
+ ok(!(raw.data.mouse.usFlags & MOUSE_MOVE_ABSOLUTE), "Unexpected absolute rawinput motion\n");
+ ok(!(raw.data.mouse.usFlags & MOUSE_VIRTUAL_DESKTOP), "Unexpected virtual desktop rawinput motion\n");
+ rawinput_motion_x += raw.data.mouse.lLastX;
+ rawinput_motion_y += raw.data.mouse.lLastY;
+ }
+ }
+ }
+
+ if (msg == WM_USER)
+ SetEvent(rawinput_wndproc_done);
+
+ return DefWindowProcA(hwnd, msg, wparam, lparam);
+}
+
+struct rawinput_mouse_thread_params
+{
+ int step;
+ HWND window;
+ HANDLE ready;
+ HANDLE start;
+};
+
+static DWORD WINAPI rawinput_mouse_thread(void *arg)
+{
+ struct rawinput_mouse_thread_params *params = arg;
+ RECT rect_105 = { 105, 105, 105, 105 };
+ RECT rect_110 = { 110, 110, 110, 110 };
+ int i;
+
+ while (WaitForSingleObject(params->ready, INFINITE) == 0)
+ {
+ ResetEvent(params->ready);
+ SetEvent(params->start);
+
+ switch (params->step)
+ {
+ case 0:
+ case 1:
+ case 2:
+ mouse_event(MOUSEEVENTF_MOVE, -1, 0, 0, 0);
+ mouse_event(MOUSEEVENTF_MOVE, 0, -1, 0, 0);
+ break;
+ case 3:
+ for (i = 0; i < 10; ++i)
+ {
+ ClipCursor(&rect_105);
+ Sleep(5);
+ ClipCursor(&rect_110);
+ Sleep(5);
+ ClipCursor(NULL);
+ Sleep(5);
+ }
+ break;
+ case 4:
+ for (i = 0; i < 10; ++i)
+ {
+ ClipCursor(&rect_110);
+ Sleep(5);
+ mouse_event(MOUSEEVENTF_MOVE, 1, 1, 0, 0);
+ ClipCursor(NULL);
+ Sleep(5);
+ mouse_event(MOUSEEVENTF_MOVE, 1, 1, 0, 0);
+ ClipCursor(&rect_110);
+ ClipCursor(NULL);
+ Sleep(5);
+ }
+ break;
+ default:
+ return 0;
+ }
+
+ PostMessageA(params->window, WM_USER, 0, 0);
+ }
+
+ return 0;
+}
+
+struct rawinput_mouse_test
+{
+ BOOL register_device;
+ BOOL register_window;
+ DWORD register_flags;
+ int expect_received;
+ int expect_received_foreground;
+ int expect_motion_x;
+ int expect_motion_y;
+ BOOL todo;
+};
+
+static void test_rawinput_mouse(void)
+{
+ struct rawinput_mouse_thread_params params;
+ RAWINPUTDEVICE raw_devices[1];
+ HANDLE thread;
+ DWORD ret;
+ int i;
+
+ struct rawinput_mouse_test tests[] =
+ {
+ { FALSE, FALSE, 0, 0, 0, 0, 0, FALSE },
+ { TRUE, FALSE, 0, 2, 2, -1, -1, FALSE },
+ { TRUE, TRUE, 0, 2, 2, -1, -1, FALSE },
+ { TRUE, TRUE, 0, 0, 0, 0, 0, TRUE },
+ { TRUE, TRUE, 0, 20, 20, 20, 20, TRUE },
+ };
+
+ mouse_event(MOUSEEVENTF_ABSOLUTE, 100, 100, 0, 0);
+ SetCursorPos(100, 100);
+
+ rawinput_wndproc_done = CreateEventA(NULL, FALSE, FALSE, NULL);
+ ok(rawinput_wndproc_done != NULL, "CreateEvent failed\n");
+
+ params.window = CreateWindowA("static", "static", WS_VISIBLE | WS_POPUP, 100, 100, 100, 100, 0, NULL, NULL, NULL);
+ ok(params.window != 0, "CreateWindow failed\n");
+
+ ShowWindow(params.window, SW_SHOW);
+ SetWindowPos(params.window, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE);
+ SetForegroundWindow(params.window);
+ UpdateWindow(params.window);
+ empty_message_queue();
+
+ SetWindowLongPtrA(params.window, GWLP_WNDPROC, (LONG_PTR)rawinput_wndproc);
+
+ params.step = 0;
+ params.ready = CreateEventA(NULL, FALSE, FALSE, NULL);
+ ok(params.ready != NULL, "CreateEvent failed\n");
+
+ params.start = CreateEventA(NULL, FALSE, FALSE, NULL);
+ ok(params.start != NULL, "CreateEvent failed\n");
+
+ thread = CreateThread(NULL, 0, rawinput_mouse_thread, &params, 0, NULL);
+ ok(thread != NULL, "CreateThread failed\n");
+
+ for (i = 0; i < ARRAY_SIZE(tests); ++i)
+ {
+ rawinput_received = 0;
+ rawinput_received_foreground = 0;
+ rawinput_motion_x = 0;
+ rawinput_motion_y = 0;
+
+ raw_devices[0].usUsagePage = 0x01;
+ raw_devices[0].usUsage = 0x02;
+ raw_devices[0].dwFlags = tests[i].register_flags;
+ raw_devices[0].hwndTarget = tests[i].register_window ? params.window : 0;
+
+ if (tests[i].register_device)
+ {
+ SetLastError(0xdeadbeef);
+ ret = RegisterRawInputDevices(raw_devices, ARRAY_SIZE(raw_devices), sizeof(RAWINPUTDEVICE));
+ ok(ret, "%d: RegisterRawInputDevices failed\n", i);
+ ok(GetLastError() == 0xdeadbeef, "%d: RegisterRawInputDevices returned %08x\n", i, GetLastError());
+ }
+
+ params.step = i;
+ SetEvent(params.ready);
+
+ WaitForSingleObject(params.start, INFINITE);
+ ResetEvent(params.start);
+
+ while (MsgWaitForMultipleObjects(1, &rawinput_wndproc_done, FALSE, INFINITE, QS_ALLINPUT) != WAIT_OBJECT_0)
+ empty_message_queue();
+ ResetEvent(rawinput_wndproc_done);
+
+ /* Wine is sometimes passing some of the conditions, but not always, let's test
+ * all at once in the todo block, there should be at least one that fails. */
+ todo_wine_if(tests[i].todo)
+ ok(rawinput_received == tests[i].expect_received &&
+ rawinput_received_foreground == tests[i].expect_received_foreground &&
+ rawinput_motion_x == tests[i].expect_motion_x &&
+ rawinput_motion_y == tests[i].expect_motion_y,
+ "%d: Unexpected rawinput results: received %d, %d in foreground, motion is %dx%d\n",
+ i, rawinput_received, rawinput_received_foreground, rawinput_motion_x, rawinput_motion_y);
+
+ if (tests[i].register_device)
+ {
+ raw_devices[0].dwFlags = RIDEV_REMOVE;
+ raw_devices[0].hwndTarget = 0;
+
+ SetLastError(0xdeadbeef);
+ ret = RegisterRawInputDevices(raw_devices, ARRAY_SIZE(raw_devices), sizeof(RAWINPUTDEVICE));
+ ok(ret, "%d: RegisterRawInputDevices failed\n", i);
+ ok(GetLastError() == 0xdeadbeef, "%d: RegisterRawInputDevices returned %08x\n", i, GetLastError());
+ }
+ }
+
+ params.step = -1;
+ SetEvent(params.ready);
+ WaitForSingleObject(thread, INFINITE);
+
+ CloseHandle(params.start);
+ CloseHandle(params.ready);
+ CloseHandle(thread);
+}
+
static void test_key_map(void)
{
HKL kl = GetKeyboardLayout(0);
@@ -3326,6 +3551,7 @@ START_TEST(input)
test_GetRawInputData();
test_GetKeyboardLayoutList();
test_RegisterRawInputDevices();
+ test_rawinput_mouse();
if(pGetMouseMovePointsEx)
test_GetMouseMovePointsEx();
--
2.24.1

View File

@@ -0,0 +1,70 @@
From d407a40a11f0cbf3e61faded5e6e7e1e2e63ef9c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
Date: Thu, 14 Nov 2019 17:03:38 +0100
Subject: [PATCH 02/12] user32/tests: Add rawinput test for cross-thread
interactions.
The rawinput messages are received on the target window if is from the
same process as the foreground window, it doesn't need to be the
foreground window itself.
---
dlls/user32/tests/input.c | 27 +++++++++++++++++++++++++++
1 file changed, 27 insertions(+)
diff --git a/dlls/user32/tests/input.c b/dlls/user32/tests/input.c
index bf9d19906a8..bdcc6834d9d 100644
--- a/dlls/user32/tests/input.c
+++ b/dlls/user32/tests/input.c
@@ -1884,6 +1884,7 @@ static DWORD WINAPI rawinput_mouse_thread(void *arg)
struct rawinput_mouse_thread_params *params = arg;
RECT rect_105 = { 105, 105, 105, 105 };
RECT rect_110 = { 110, 110, 110, 110 };
+ HWND window;
int i;
while (WaitForSingleObject(params->ready, INFINITE) == 0)
@@ -1924,6 +1925,26 @@ static DWORD WINAPI rawinput_mouse_thread(void *arg)
Sleep(5);
}
break;
+ case 5:
+ case 6:
+ window = CreateWindowA("static", "static", WS_VISIBLE | WS_POPUP, 100, 100, 100, 100, 0, NULL, NULL, NULL);
+ ok(window != 0, "%d: CreateWindow failed\n", params->step);
+
+ ShowWindow(window, SW_SHOW);
+ SetWindowPos(window, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE);
+ SetForegroundWindow(window);
+ UpdateWindow(window);
+ empty_message_queue();
+
+ mouse_event(MOUSEEVENTF_MOVE, 1, 1, 0, 0);
+ SendMessageA(GetForegroundWindow(), WM_USER, 0, 0);
+ mouse_event(MOUSEEVENTF_MOVE, -1, -1, 0, 0);
+ SendMessageA(GetForegroundWindow(), WM_USER, 0, 0);
+
+ empty_message_queue();
+
+ DestroyWindow(window);
+ break;
default:
return 0;
}
@@ -1959,8 +1980,14 @@ static void test_rawinput_mouse(void)
{ FALSE, FALSE, 0, 0, 0, 0, 0, FALSE },
{ TRUE, FALSE, 0, 2, 2, -1, -1, FALSE },
{ TRUE, TRUE, 0, 2, 2, -1, -1, FALSE },
+
+ /* clip cursor tests */
{ TRUE, TRUE, 0, 0, 0, 0, 0, TRUE },
{ TRUE, TRUE, 0, 20, 20, 20, 20, TRUE },
+
+ /* same-process foreground tests */
+ { TRUE, TRUE, 0, 2, 2, 0, 0, TRUE },
+ { TRUE, TRUE, RIDEV_INPUTSINK, 2, 2, 0, 0, TRUE },
};
mouse_event(MOUSEEVENTF_ABSOLUTE, 100, 100, 0, 0);
--
2.24.1

View File

@@ -0,0 +1,173 @@
From 35e259f69a7c5a6a065833eaeaca28d92591056b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
Date: Thu, 14 Nov 2019 18:44:28 +0100
Subject: [PATCH 03/12] user32/tests: Add rawinput test for cross-process
interactions.
Validating the rest of the assumption, rawinput messages are not
received anymore if the foreground window is from another process.
---
dlls/user32/tests/input.c | 86 ++++++++++++++++++++++++++++++++++++++-
1 file changed, 84 insertions(+), 2 deletions(-)
diff --git a/dlls/user32/tests/input.c b/dlls/user32/tests/input.c
index bdcc6834d9d..cc7babd1af4 100644
--- a/dlls/user32/tests/input.c
+++ b/dlls/user32/tests/input.c
@@ -49,6 +49,7 @@
#define _WIN32_IE 0x0500
#include <stdarg.h>
+#include <stdio.h>
#include <assert.h>
#include "windef.h"
@@ -1877,8 +1878,36 @@ struct rawinput_mouse_thread_params
HWND window;
HANDLE ready;
HANDLE start;
+ const char *argv0;
};
+static void rawinput_mouse_process(void)
+{
+ HWND window;
+ HANDLE start_event, stop_event;
+
+ start_event = OpenEventA(EVENT_ALL_ACCESS, FALSE, "test_rawinput_mouse_start");
+ ok(start_event != 0, "OpenEventA failed, error: %u\n", GetLastError());
+
+ stop_event = OpenEventA(EVENT_ALL_ACCESS, FALSE, "test_rawinput_mouse_stop");
+ ok(stop_event != 0, "OpenEventA failed, error: %u\n", GetLastError());
+
+ window = CreateWindowA("static", "static", WS_VISIBLE | WS_POPUP, 200, 100, 100, 100, 0, NULL, NULL, NULL);
+ ok(window != 0, "CreateWindow failed\n");
+
+ ShowWindow(window, SW_SHOW);
+ SetWindowPos(window, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE);
+ SetForegroundWindow(window);
+ UpdateWindow(window);
+ empty_message_queue();
+
+ SetEvent(start_event);
+ while (MsgWaitForMultipleObjects(1, &stop_event, FALSE, INFINITE, QS_ALLINPUT) != WAIT_OBJECT_0)
+ empty_message_queue();
+
+ DestroyWindow(window);
+}
+
static DWORD WINAPI rawinput_mouse_thread(void *arg)
{
struct rawinput_mouse_thread_params *params = arg;
@@ -1886,6 +1915,11 @@ static DWORD WINAPI rawinput_mouse_thread(void *arg)
RECT rect_110 = { 110, 110, 110, 110 };
HWND window;
int i;
+ char path[MAX_PATH];
+ PROCESS_INFORMATION process_info;
+ STARTUPINFOA startup_info;
+ HANDLE start_event, stop_event;
+ BOOL ret;
while (WaitForSingleObject(params->ready, INFINITE) == 0)
{
@@ -1945,6 +1979,39 @@ static DWORD WINAPI rawinput_mouse_thread(void *arg)
DestroyWindow(window);
break;
+ case 7:
+ case 8:
+ start_event = CreateEventA(NULL, 0, 0, "test_rawinput_mouse_start");
+ ok(start_event != 0, "%d: CreateEventA failed, error %u\n", params->step, GetLastError());
+
+ stop_event = CreateEventA(NULL, 0, 0, "test_rawinput_mouse_stop");
+ ok(stop_event != 0, "%d: CreateEventA failed, error %u\n", params->step, GetLastError());
+
+ memset(&startup_info, 0, sizeof(startup_info));
+ startup_info.cb = sizeof(startup_info);
+ startup_info.dwFlags = STARTF_USESHOWWINDOW;
+ startup_info.wShowWindow = SW_SHOWNORMAL;
+
+ sprintf(path, "%s input test_rawinput_mouse", params->argv0);
+ ret = CreateProcessA(NULL, path, NULL, NULL, TRUE, 0, NULL, NULL, &startup_info, &process_info );
+ ok(ret, "%d: CreateProcess '%s' failed err %u.\n", params->step, path, GetLastError());
+
+ ret = WaitForSingleObject(start_event, 5000);
+ ok(ret == WAIT_OBJECT_0, "%d: WaitForSingleObject failed\n", params->step);
+
+ mouse_event(MOUSEEVENTF_MOVE, 1, 1, 0, 0);
+ SendMessageA(GetForegroundWindow(), WM_USER, 0, 0);
+ mouse_event(MOUSEEVENTF_MOVE, -1, -1, 0, 0);
+ SendMessageA(GetForegroundWindow(), WM_USER, 0, 0);
+
+ SetEvent(stop_event);
+
+ winetest_wait_child_process(process_info.hProcess);
+ CloseHandle(process_info.hProcess);
+ CloseHandle(process_info.hThread);
+ CloseHandle(start_event);
+ CloseHandle(stop_event);
+ break;
default:
return 0;
}
@@ -1967,7 +2034,7 @@ struct rawinput_mouse_test
BOOL todo;
};
-static void test_rawinput_mouse(void)
+static void test_rawinput_mouse(const char *argv0)
{
struct rawinput_mouse_thread_params params;
RAWINPUTDEVICE raw_devices[1];
@@ -1988,11 +2055,17 @@ static void test_rawinput_mouse(void)
/* same-process foreground tests */
{ TRUE, TRUE, 0, 2, 2, 0, 0, TRUE },
{ TRUE, TRUE, RIDEV_INPUTSINK, 2, 2, 0, 0, TRUE },
+
+ /* cross-process foreground tests */
+ { TRUE, TRUE, 0, 0, 0, 0, 0, TRUE },
+ { TRUE, TRUE, RIDEV_INPUTSINK, 2, 0, 0, 0, TRUE },
};
mouse_event(MOUSEEVENTF_ABSOLUTE, 100, 100, 0, 0);
SetCursorPos(100, 100);
+ params.argv0 = argv0;
+
rawinput_wndproc_done = CreateEventA(NULL, FALSE, FALSE, NULL);
ok(rawinput_wndproc_done != NULL, "CreateEvent failed\n");
@@ -3555,11 +3628,20 @@ static void test_GetKeyboardLayoutList(void)
START_TEST(input)
{
+ char **argv;
+ int argc;
POINT pos;
init_function_pointers();
GetCursorPos( &pos );
+ argc = winetest_get_mainargs(&argv);
+ if (argc >= 3 && strcmp(argv[2], "test_rawinput_mouse") == 0)
+ {
+ rawinput_mouse_process();
+ return;
+ }
+
test_Input_blackbox();
test_Input_whitebox();
test_Input_unicode();
@@ -3578,7 +3660,7 @@ START_TEST(input)
test_GetRawInputData();
test_GetKeyboardLayoutList();
test_RegisterRawInputDevices();
- test_rawinput_mouse();
+ test_rawinput_mouse(argv[0]);
if(pGetMouseMovePointsEx)
test_GetMouseMovePointsEx();
--
2.24.1

View File

@@ -0,0 +1,128 @@
From 430580824e975bbda41884affd3e5fbf104ac6fe Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
Date: Mon, 26 Aug 2019 14:37:20 +0200
Subject: [PATCH 04/12] server: Add send_hardware_message flags for rawinput
translation.
---
dlls/user32/input.c | 6 +++---
server/protocol.def | 2 ++
server/queue.c | 20 ++++++++++++++------
3 files changed, 19 insertions(+), 9 deletions(-)
diff --git a/dlls/user32/input.c b/dlls/user32/input.c
index 340d20e58f9..7d947a98d0f 100644
--- a/dlls/user32/input.c
+++ b/dlls/user32/input.c
@@ -124,7 +124,7 @@ BOOL set_capture_window( HWND hwnd, UINT gui_flags, HWND *prev_ret )
*/
BOOL CDECL __wine_send_input( HWND hwnd, const INPUT *input )
{
- NTSTATUS status = send_hardware_message( hwnd, input, 0 );
+ NTSTATUS status = send_hardware_message( hwnd, input, SEND_HWMSG_RAWINPUT|SEND_HWMSG_WINDOW );
if (status) SetLastError( RtlNtStatusToDosError(status) );
return !status;
}
@@ -192,9 +192,9 @@ UINT WINAPI SendInput( UINT count, LPINPUT inputs, int size )
/* we need to update the coordinates to what the server expects */
INPUT input = inputs[i];
update_mouse_coords( &input );
- status = send_hardware_message( 0, &input, SEND_HWMSG_INJECTED );
+ status = send_hardware_message( 0, &input, SEND_HWMSG_INJECTED|SEND_HWMSG_RAWINPUT|SEND_HWMSG_WINDOW );
}
- else status = send_hardware_message( 0, &inputs[i], SEND_HWMSG_INJECTED );
+ else status = send_hardware_message( 0, &inputs[i], SEND_HWMSG_INJECTED|SEND_HWMSG_RAWINPUT|SEND_HWMSG_WINDOW );
if (status)
{
diff --git a/server/protocol.def b/server/protocol.def
index ae3702b150f..9f9f9197134 100644
--- a/server/protocol.def
+++ b/server/protocol.def
@@ -2370,6 +2370,8 @@ enum message_type
VARARG(keystate,bytes); /* global state array for all the keys */
@END
#define SEND_HWMSG_INJECTED 0x01
+#define SEND_HWMSG_RAWINPUT 0x02
+#define SEND_HWMSG_WINDOW 0x04
/* Get a message from the current queue */
diff --git a/server/queue.c b/server/queue.c
index af65b5f6b4c..9528453b190 100644
--- a/server/queue.c
+++ b/server/queue.c
@@ -1736,7 +1736,7 @@ static int send_hook_ll_message( struct desktop *desktop, struct message *hardwa
/* queue a hardware message for a mouse event */
static int queue_mouse_message( struct desktop *desktop, user_handle_t win, const hw_input_t *input,
- unsigned int origin, struct msg_queue *sender )
+ unsigned int origin, struct msg_queue *sender, unsigned int req_flags )
{
const struct rawinput_device *device;
struct hardware_msg_data *msg_data;
@@ -1789,7 +1789,8 @@ static int queue_mouse_message( struct desktop *desktop, user_handle_t win, cons
y = desktop->cursor.y;
}
- if ((device = current->process->rawinput_mouse))
+ if ((device = current->process->rawinput_mouse) &&
+ (req_flags & SEND_HWMSG_RAWINPUT))
{
if (!(msg = alloc_hardware_message( input->mouse.info, source, time ))) return 0;
msg_data = msg->data;
@@ -1808,6 +1809,9 @@ static int queue_mouse_message( struct desktop *desktop, user_handle_t win, cons
queue_hardware_message( desktop, msg, 0 );
}
+ if (!(req_flags & SEND_HWMSG_WINDOW))
+ return 0;
+
for (i = 0; i < ARRAY_SIZE( messages ); i++)
{
if (!messages[i]) continue;
@@ -1839,7 +1843,7 @@ static int queue_mouse_message( struct desktop *desktop, user_handle_t win, cons
/* queue a hardware message for a keyboard event */
static int queue_keyboard_message( struct desktop *desktop, user_handle_t win, const hw_input_t *input,
- unsigned int origin, struct msg_queue *sender )
+ unsigned int origin, struct msg_queue *sender, unsigned int req_flags )
{
struct hw_msg_source source = { IMDT_KEYBOARD, origin };
const struct rawinput_device *device;
@@ -1915,7 +1919,8 @@ static int queue_keyboard_message( struct desktop *desktop, user_handle_t win, c
break;
}
- if ((device = current->process->rawinput_kbd))
+ if ((device = current->process->rawinput_kbd) &&
+ (req_flags & SEND_HWMSG_RAWINPUT))
{
if (!(msg = alloc_hardware_message( input->kbd.info, source, time ))) return 0;
msg_data = msg->data;
@@ -1933,6 +1938,9 @@ static int queue_keyboard_message( struct desktop *desktop, user_handle_t win, c
queue_hardware_message( desktop, msg, 0 );
}
+ if (!(req_flags & SEND_HWMSG_WINDOW))
+ return 0;
+
if (!(msg = alloc_hardware_message( input->kbd.info, source, time ))) return 0;
msg_data = msg->data;
@@ -2494,10 +2502,10 @@ DECL_HANDLER(send_hardware_message)
switch (req->input.type)
{
case INPUT_MOUSE:
- reply->wait = queue_mouse_message( desktop, req->win, &req->input, origin, sender );
+ reply->wait = queue_mouse_message( desktop, req->win, &req->input, origin, sender, req->flags );
break;
case INPUT_KEYBOARD:
- reply->wait = queue_keyboard_message( desktop, req->win, &req->input, origin, sender );
+ reply->wait = queue_keyboard_message( desktop, req->win, &req->input, origin, sender, req->flags );
break;
case INPUT_HARDWARE:
queue_custom_hardware_message( desktop, req->win, origin, &req->input );
--
2.24.1

View File

@@ -0,0 +1,182 @@
From 9a0c9443ada9bccc1d10270398dbf9bddb483d53 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
Date: Tue, 12 Nov 2019 12:41:55 +0100
Subject: [PATCH 05/12] server: Broadcast rawinput message if request flag is
SEND_HWMSG_RAWINPUT.
If the request flag is equal to SEND_HWMSG_RAWINPUT, we broadcast the
message to all listening processes -or at least to the foreground
process until RIDEV_INPUTSINK is supported.
---
dlls/user32/tests/input.c | 2 +-
server/queue.c | 98 ++++++++++++++++++++++++++++++---------
2 files changed, 78 insertions(+), 22 deletions(-)
diff --git a/dlls/user32/tests/input.c b/dlls/user32/tests/input.c
index cc7babd1af4..d18ccfebcaf 100644
--- a/dlls/user32/tests/input.c
+++ b/dlls/user32/tests/input.c
@@ -2057,7 +2057,7 @@ static void test_rawinput_mouse(const char *argv0)
{ TRUE, TRUE, RIDEV_INPUTSINK, 2, 2, 0, 0, TRUE },
/* cross-process foreground tests */
- { TRUE, TRUE, 0, 0, 0, 0, 0, TRUE },
+ { TRUE, TRUE, 0, 0, 0, 0, 0, FALSE },
{ TRUE, TRUE, RIDEV_INPUTSINK, 2, 0, 0, 0, TRUE },
};
diff --git a/server/queue.c b/server/queue.c
index 9528453b190..2bdd099d1bb 100644
--- a/server/queue.c
+++ b/server/queue.c
@@ -1734,12 +1734,67 @@ static int send_hook_ll_message( struct desktop *desktop, struct message *hardwa
return 1;
}
+struct rawinput_message
+{
+ struct desktop *desktop;
+ struct hw_msg_source source;
+ unsigned int time;
+ struct hardware_msg_data data;
+};
+
+static int queue_rawinput_message( struct process* process, void* user )
+{
+ const struct rawinput_message* raw_msg = user;
+ const struct rawinput_device *device = NULL;
+ struct desktop *desktop = NULL;
+ struct thread *thread = NULL, *foreground = NULL;
+ struct message *msg;
+
+ if (raw_msg->data.rawinput.type == RIM_TYPEMOUSE)
+ device = process->rawinput_mouse;
+ else if (raw_msg->data.rawinput.type == RIM_TYPEKEYBOARD)
+ device = process->rawinput_kbd;
+
+ if (!device)
+ goto done;
+
+ if (!(desktop = get_desktop_obj( process, process->desktop, 0 )) ||
+ (raw_msg->desktop && desktop != raw_msg->desktop))
+ goto done;
+
+ if (!(thread = get_window_thread( device->target ? device->target : desktop->foreground_input->active )) ||
+ process != thread->process)
+ goto done;
+
+ /* FIXME: Implement RIDEV_INPUTSINK */
+ if (!(foreground = get_window_thread( desktop->foreground_input->active )) ||
+ thread->process != foreground->process)
+ goto done;
+
+ if (!(msg = alloc_hardware_message( raw_msg->data.info, raw_msg->source, raw_msg->time )))
+ goto done;
+
+ msg->win = device->target;
+ msg->msg = WM_INPUT;
+ msg->wparam = RIM_INPUT;
+ msg->lparam = 0;
+ memcpy( msg->data, &raw_msg->data, sizeof(raw_msg->data) );
+
+ queue_hardware_message( desktop, msg, 0 );
+
+done:
+ if (foreground) release_object( foreground );
+ if (thread) release_object( thread );
+ if (desktop) release_object( desktop );
+ return 0;
+}
+
/* queue a hardware message for a mouse event */
static int queue_mouse_message( struct desktop *desktop, user_handle_t win, const hw_input_t *input,
unsigned int origin, struct msg_queue *sender, unsigned int req_flags )
{
- const struct rawinput_device *device;
struct hardware_msg_data *msg_data;
+ struct rawinput_message raw_msg;
struct message *msg;
unsigned int i, time, flags;
struct hw_msg_source source = { IMDT_MOUSE, origin };
@@ -1789,24 +1844,24 @@ static int queue_mouse_message( struct desktop *desktop, user_handle_t win, cons
y = desktop->cursor.y;
}
- if ((device = current->process->rawinput_mouse) &&
- (req_flags & SEND_HWMSG_RAWINPUT))
+ if (req_flags & SEND_HWMSG_RAWINPUT)
{
- if (!(msg = alloc_hardware_message( input->mouse.info, source, time ))) return 0;
- msg_data = msg->data;
-
- msg->win = device->target;
- msg->msg = WM_INPUT;
- msg->wparam = RIM_INPUT;
- msg->lparam = 0;
+ raw_msg.desktop = desktop;
+ raw_msg.source = source;
+ raw_msg.time = time;
+ msg_data = &raw_msg.data;
+ msg_data->info = input->mouse.info;
msg_data->flags = flags;
msg_data->rawinput.type = RIM_TYPEMOUSE;
msg_data->rawinput.mouse.x = x - desktop->cursor.x;
msg_data->rawinput.mouse.y = y - desktop->cursor.y;
msg_data->rawinput.mouse.data = input->mouse.data;
- queue_hardware_message( desktop, msg, 0 );
+ if (req_flags == SEND_HWMSG_RAWINPUT)
+ enum_processes( queue_rawinput_message, &raw_msg );
+ else
+ queue_rawinput_message( current->process, &raw_msg );
}
if (!(req_flags & SEND_HWMSG_WINDOW))
@@ -1846,8 +1901,8 @@ static int queue_keyboard_message( struct desktop *desktop, user_handle_t win, c
unsigned int origin, struct msg_queue *sender, unsigned int req_flags )
{
struct hw_msg_source source = { IMDT_KEYBOARD, origin };
- const struct rawinput_device *device;
struct hardware_msg_data *msg_data;
+ struct rawinput_message raw_msg;
struct message *msg;
unsigned char vkey = input->kbd.vkey;
unsigned int message_code, time;
@@ -1919,23 +1974,24 @@ static int queue_keyboard_message( struct desktop *desktop, user_handle_t win, c
break;
}
- if ((device = current->process->rawinput_kbd) &&
- (req_flags & SEND_HWMSG_RAWINPUT))
+ if (req_flags & SEND_HWMSG_RAWINPUT)
{
- if (!(msg = alloc_hardware_message( input->kbd.info, source, time ))) return 0;
- msg_data = msg->data;
-
- msg->win = device->target;
- msg->msg = WM_INPUT;
- msg->wparam = RIM_INPUT;
+ raw_msg.desktop = desktop;
+ raw_msg.source = source;
+ raw_msg.time = time;
+ msg_data = &raw_msg.data;
+ msg_data->info = input->kbd.info;
msg_data->flags = input->kbd.flags;
msg_data->rawinput.type = RIM_TYPEKEYBOARD;
msg_data->rawinput.kbd.message = message_code;
msg_data->rawinput.kbd.vkey = vkey;
msg_data->rawinput.kbd.scan = input->kbd.scan;
- queue_hardware_message( desktop, msg, 0 );
+ if (req_flags == SEND_HWMSG_RAWINPUT)
+ enum_processes( queue_rawinput_message, &raw_msg );
+ else
+ queue_rawinput_message( current->process, &raw_msg );
}
if (!(req_flags & SEND_HWMSG_WINDOW))
--
2.24.1

View File

@@ -0,0 +1,193 @@
From 8304a54fbb8d34bf4278155624464d2b47ce37cf Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
Date: Mon, 26 Aug 2019 15:20:32 +0200
Subject: [PATCH 06/12] user32: Add __wine_send_input flags to hint raw input
translation.
---
dlls/user32/input.c | 4 ++--
dlls/user32/user32.spec | 2 +-
dlls/wineandroid.drv/keyboard.c | 2 +-
dlls/wineandroid.drv/window.c | 4 ++--
dlls/winemac.drv/ime.c | 4 ++--
dlls/winemac.drv/keyboard.c | 2 +-
dlls/winemac.drv/mouse.c | 2 +-
dlls/winex11.drv/keyboard.c | 2 +-
dlls/winex11.drv/mouse.c | 8 ++++----
include/winuser.h | 2 +-
10 files changed, 16 insertions(+), 16 deletions(-)
diff --git a/dlls/user32/input.c b/dlls/user32/input.c
index 7d947a98d0f..97a5ada922e 100644
--- a/dlls/user32/input.c
+++ b/dlls/user32/input.c
@@ -122,9 +122,9 @@ BOOL set_capture_window( HWND hwnd, UINT gui_flags, HWND *prev_ret )
*
* Internal SendInput function to allow the graphics driver to inject real events.
*/
-BOOL CDECL __wine_send_input( HWND hwnd, const INPUT *input )
+BOOL CDECL __wine_send_input( HWND hwnd, const INPUT *input, UINT flags )
{
- NTSTATUS status = send_hardware_message( hwnd, input, SEND_HWMSG_RAWINPUT|SEND_HWMSG_WINDOW );
+ NTSTATUS status = send_hardware_message( hwnd, input, flags );
if (status) SetLastError( RtlNtStatusToDosError(status) );
return !status;
}
diff --git a/dlls/user32/user32.spec b/dlls/user32/user32.spec
index c08ad5ff4f9..b59ba381334 100644
--- a/dlls/user32/user32.spec
+++ b/dlls/user32/user32.spec
@@ -833,5 +833,5 @@
# All functions must be prefixed with '__wine_' (for internal functions)
# or 'wine_' (for user-visible functions) to avoid namespace conflicts.
#
-@ cdecl __wine_send_input(long ptr)
+@ cdecl __wine_send_input(long ptr long)
@ cdecl __wine_set_pixel_format(long long)
diff --git a/dlls/wineandroid.drv/keyboard.c b/dlls/wineandroid.drv/keyboard.c
index a0f3257f74b..1af8a98f1f9 100644
--- a/dlls/wineandroid.drv/keyboard.c
+++ b/dlls/wineandroid.drv/keyboard.c
@@ -680,7 +680,7 @@ static void send_keyboard_input( HWND hwnd, WORD vkey, WORD scan, DWORD flags )
input.u.ki.time = 0;
input.u.ki.dwExtraInfo = 0;
- __wine_send_input( hwnd, &input );
+ __wine_send_input( hwnd, &input, SEND_HWMSG_RAWINPUT|SEND_HWMSG_WINDOW );
}
/***********************************************************************
diff --git a/dlls/wineandroid.drv/window.c b/dlls/wineandroid.drv/window.c
index 2fc258dfd90..d96f001432d 100644
--- a/dlls/wineandroid.drv/window.c
+++ b/dlls/wineandroid.drv/window.c
@@ -524,7 +524,7 @@ static int process_events( DWORD mask )
}
SERVER_END_REQ;
}
- __wine_send_input( capture ? capture : event->data.motion.hwnd, &event->data.motion.input );
+ __wine_send_input( capture ? capture : event->data.motion.hwnd, &event->data.motion.input, SEND_HWMSG_RAWINPUT|SEND_HWMSG_WINDOW );
}
break;
@@ -538,7 +538,7 @@ static int process_events( DWORD mask )
event->data.kbd.input.u.ki.wVk, event->data.kbd.input.u.ki.wVk,
event->data.kbd.input.u.ki.wScan );
update_keyboard_lock_state( event->data.kbd.input.u.ki.wVk, event->data.kbd.lock_state );
- __wine_send_input( 0, &event->data.kbd.input );
+ __wine_send_input( 0, &event->data.kbd.input, SEND_HWMSG_RAWINPUT|SEND_HWMSG_WINDOW );
break;
default:
diff --git a/dlls/winemac.drv/ime.c b/dlls/winemac.drv/ime.c
index dabe6654f98..2ed6e6f66a3 100644
--- a/dlls/winemac.drv/ime.c
+++ b/dlls/winemac.drv/ime.c
@@ -1427,10 +1427,10 @@ void macdrv_im_set_text(const macdrv_event *event)
{
input.ki.wScan = chars[i];
input.ki.dwFlags = KEYEVENTF_UNICODE;
- __wine_send_input(hwnd, &input);
+ __wine_send_input(hwnd, &input, SEND_HWMSG_RAWINPUT|SEND_HWMSG_WINDOW);
input.ki.dwFlags = KEYEVENTF_UNICODE | KEYEVENTF_KEYUP;
- __wine_send_input(hwnd, &input);
+ __wine_send_input(hwnd, &input, SEND_HWMSG_RAWINPUT|SEND_HWMSG_WINDOW);
}
}
diff --git a/dlls/winemac.drv/keyboard.c b/dlls/winemac.drv/keyboard.c
index bb408cb20c5..41919baafc7 100644
--- a/dlls/winemac.drv/keyboard.c
+++ b/dlls/winemac.drv/keyboard.c
@@ -929,7 +929,7 @@ static void macdrv_send_keyboard_input(HWND hwnd, WORD vkey, WORD scan, DWORD fl
input.ki.time = time;
input.ki.dwExtraInfo = 0;
- __wine_send_input(hwnd, &input);
+ __wine_send_input(hwnd, &input, SEND_HWMSG_RAWINPUT|SEND_HWMSG_WINDOW);
}
diff --git a/dlls/winemac.drv/mouse.c b/dlls/winemac.drv/mouse.c
index dd6443fe1ba..91cafdf1362 100644
--- a/dlls/winemac.drv/mouse.c
+++ b/dlls/winemac.drv/mouse.c
@@ -165,7 +165,7 @@ static void send_mouse_input(HWND hwnd, macdrv_window cocoa_window, UINT flags,
input.mi.time = time;
input.mi.dwExtraInfo = 0;
- __wine_send_input(top_level_hwnd, &input);
+ __wine_send_input(top_level_hwnd, &input, SEND_HWMSG_RAWINPUT|SEND_HWMSG_WINDOW);
}
diff --git a/dlls/winex11.drv/keyboard.c b/dlls/winex11.drv/keyboard.c
index 3c38784ebf9..7856b04c8f5 100644
--- a/dlls/winex11.drv/keyboard.c
+++ b/dlls/winex11.drv/keyboard.c
@@ -1149,7 +1149,7 @@ static void X11DRV_send_keyboard_input( HWND hwnd, WORD vkey, WORD scan, DWORD f
input.u.ki.time = time;
input.u.ki.dwExtraInfo = 0;
- __wine_send_input( hwnd, &input );
+ __wine_send_input( hwnd, &input, SEND_HWMSG_RAWINPUT|SEND_HWMSG_WINDOW );
}
diff --git a/dlls/winex11.drv/mouse.c b/dlls/winex11.drv/mouse.c
index 8e1eb6d5e0e..96e04509e73 100644
--- a/dlls/winex11.drv/mouse.c
+++ b/dlls/winex11.drv/mouse.c
@@ -659,7 +659,7 @@ static void send_mouse_input( HWND hwnd, Window window, unsigned int state, INPU
}
input->u.mi.dx += clip_rect.left;
input->u.mi.dy += clip_rect.top;
- __wine_send_input( hwnd, input );
+ __wine_send_input( hwnd, input, SEND_HWMSG_RAWINPUT|SEND_HWMSG_WINDOW );
return;
}
@@ -699,7 +699,7 @@ static void send_mouse_input( HWND hwnd, Window window, unsigned int state, INPU
SERVER_END_REQ;
}
- __wine_send_input( hwnd, input );
+ __wine_send_input( hwnd, input, SEND_HWMSG_RAWINPUT|SEND_HWMSG_WINDOW );
}
#ifdef SONAME_LIBXCURSOR
@@ -1645,7 +1645,7 @@ void move_resize_window( HWND hwnd, int dir )
input.u.mi.dwFlags = button_up_flags[button - 1] | MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE;
input.u.mi.time = GetTickCount();
input.u.mi.dwExtraInfo = 0;
- __wine_send_input( hwnd, &input );
+ __wine_send_input( hwnd, &input, SEND_HWMSG_RAWINPUT|SEND_HWMSG_WINDOW );
}
while (PeekMessageW( &msg, 0, 0, 0, PM_REMOVE ))
@@ -1884,7 +1884,7 @@ static BOOL X11DRV_RawMotion( XGenericEventCookie *xev )
TRACE( "pos %d,%d (event %f,%f)\n", input.u.mi.dx, input.u.mi.dy, dx, dy );
input.type = INPUT_MOUSE;
- __wine_send_input( 0, &input );
+ __wine_send_input( 0, &input, SEND_HWMSG_RAWINPUT|SEND_HWMSG_WINDOW );
return TRUE;
}
diff --git a/include/winuser.h b/include/winuser.h
index 51c73d25c2f..10cebfa97d0 100644
--- a/include/winuser.h
+++ b/include/winuser.h
@@ -4389,7 +4389,7 @@ static inline BOOL WINAPI SetRectEmpty(LPRECT rect)
WORD WINAPI SYSTEM_KillSystemTimer( WORD );
#ifdef __WINESRC__
-WINUSERAPI BOOL CDECL __wine_send_input( HWND hwnd, const INPUT *input );
+WINUSERAPI BOOL CDECL __wine_send_input( HWND hwnd, const INPUT *input, UINT flags );
#endif
#ifdef __cplusplus
--
2.24.1

View File

@@ -0,0 +1,146 @@
From 9038e4871284e636f277be8fc8a2a901049bcaf6 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
Date: Fri, 2 Aug 2019 02:24:32 -0400
Subject: [PATCH 07/12] winex11.drv: Advertise XInput2 version 2.1 support.
Under XInput2 protocol version < 2.1, RawEvents are not supposed to be
sent if a pointer grab is active. However slave device events are still
received regardless of this specification and Wine implemented a
workaround to receive RawEvents during pointer grabs by listening to
these slave device events. Then, as soon as a mouse button is pressed
only the grabbing client will receive the raw motion events.
By advertising the support of XInput2 version >= 2.1, where RawEvents
are sent even during pointer grabs, we ensure to receive the RawMotion
events from the desktop window thread, even if a mouse grab is active.
It is now also possible to simplify the code by listening to master
device events only and get rid of slave device id tracking.
---
dlls/winex11.drv/mouse.c | 49 ++++++++-------------------------------
dlls/winex11.drv/x11drv.h | 3 ---
2 files changed, 10 insertions(+), 42 deletions(-)
diff --git a/dlls/winex11.drv/mouse.c b/dlls/winex11.drv/mouse.c
index 96e04509e73..105db08a78a 100644
--- a/dlls/winex11.drv/mouse.c
+++ b/dlls/winex11.drv/mouse.c
@@ -304,12 +304,16 @@ static void enable_xinput2(void)
if (data->xi2_state == xi_unknown)
{
- int major = 2, minor = 0;
- if (!pXIQueryVersion( data->display, &major, &minor )) data->xi2_state = xi_disabled;
+ int major = 2, minor = 1;
+ if (!pXIQueryVersion( data->display, &major, &minor ) && major == 2 && minor > 0)
+ {
+ TRACE( "XInput2 v%d.%d available\n", major, minor );
+ data->xi2_state = xi_disabled;
+ }
else
{
data->xi2_state = xi_unavailable;
- WARN( "X Input 2 not available\n" );
+ WARN( "XInput v2.1 not available\n" );
}
}
if (data->xi2_state == xi_unavailable) return;
@@ -317,7 +321,7 @@ static void enable_xinput2(void)
mask.mask = mask_bits;
mask.mask_len = sizeof(mask_bits);
- mask.deviceid = XIAllDevices;
+ mask.deviceid = XIAllMasterDevices;
memset( mask_bits, 0, sizeof(mask_bits) );
XISetMask( mask_bits, XI_DeviceChanged );
XISetMask( mask_bits, XI_RawMotion );
@@ -329,16 +333,6 @@ static void enable_xinput2(void)
update_relative_valuators( pointer_info->classes, pointer_info->num_classes );
pXIFreeDeviceInfo( pointer_info );
- /* This device info list is only used to find the initial current slave if
- * no XI_DeviceChanged events happened. If any hierarchy change occurred that
- * might be relevant here (eg. user switching mice after (un)plugging), a
- * XI_DeviceChanged event will point us to the right slave. So this list is
- * safe to be obtained statically at enable_xinput2() time.
- */
- if (data->xi2_devices) pXIFreeDeviceInfo( data->xi2_devices );
- data->xi2_devices = pXIQueryDevice( data->display, XIAllDevices, &data->xi2_device_count );
- data->xi2_current_slave = 0;
-
data->xi2_state = xi_enabled;
#endif
}
@@ -359,15 +353,12 @@ static void disable_xinput2(void)
mask.mask = NULL;
mask.mask_len = 0;
- mask.deviceid = XIAllDevices;
+ mask.deviceid = XIAllMasterDevices;
pXISelectEvents( data->display, DefaultRootWindow( data->display ), &mask, 1 );
- pXIFreeDeviceInfo( data->xi2_devices );
data->x_rel_valuator.number = -1;
data->y_rel_valuator.number = -1;
- data->xi2_devices = NULL;
data->xi2_core_pointer = 0;
- data->xi2_current_slave = 0;
#endif
}
@@ -1801,7 +1792,6 @@ static BOOL X11DRV_DeviceChanged( XGenericEventCookie *xev )
if (event->reason != XISlaveSwitch) return FALSE;
update_relative_valuators( event->classes, event->num_classes );
- data->xi2_current_slave = event->sourceid;
return TRUE;
}
@@ -1822,26 +1812,7 @@ static BOOL X11DRV_RawMotion( XGenericEventCookie *xev )
if (thread_data->x_rel_valuator.number < 0 || thread_data->y_rel_valuator.number < 0) return FALSE;
if (!event->valuators.mask_len) return FALSE;
if (thread_data->xi2_state != xi_enabled) return FALSE;
-
- /* If there is no slave currently detected, no previous motion nor device
- * change events were received. Look it up now on the device list in this
- * case.
- */
- if (!thread_data->xi2_current_slave)
- {
- XIDeviceInfo *devices = thread_data->xi2_devices;
-
- for (i = 0; i < thread_data->xi2_device_count; i++)
- {
- if (devices[i].use != XISlavePointer) continue;
- if (devices[i].deviceid != event->deviceid) continue;
- if (devices[i].attachment != thread_data->xi2_core_pointer) continue;
- thread_data->xi2_current_slave = event->deviceid;
- break;
- }
- }
-
- if (event->deviceid != thread_data->xi2_current_slave) return FALSE;
+ if (event->deviceid != thread_data->xi2_core_pointer) return FALSE;
x_rel = &thread_data->x_rel_valuator;
y_rel = &thread_data->y_rel_valuator;
diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h
index cca87433264..432dd5909ca 100644
--- a/dlls/winex11.drv/x11drv.h
+++ b/dlls/winex11.drv/x11drv.h
@@ -340,12 +340,9 @@ struct x11drv_thread_data
DWORD clip_reset; /* time when clipping was last reset */
HKL kbd_layout; /* active keyboard layout */
enum { xi_unavailable = -1, xi_unknown, xi_disabled, xi_enabled } xi2_state; /* XInput2 state */
- void *xi2_devices; /* list of XInput2 devices (valid when state is enabled) */
- int xi2_device_count;
struct x11drv_valuator_data x_rel_valuator;
struct x11drv_valuator_data y_rel_valuator;
int xi2_core_pointer; /* XInput2 core pointer id */
- int xi2_current_slave; /* Current slave driving the Core pointer */
};
extern struct x11drv_thread_data *x11drv_init_thread_data(void) DECLSPEC_HIDDEN;
--
2.24.1

View File

@@ -0,0 +1,224 @@
From ef0b82046445fe430ab85bb8069f3e4536b11f7a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
Date: Thu, 19 Dec 2019 22:34:44 +0100
Subject: [PATCH 08/12] winex11.drv: Keep track of pointer and device button
mappings.
We are going to receive raw button events and we will need to apply the
correct button mappings ourselves.
Original patch by Andrew Eikum <aeikum@codeweavers.com>.
---
dlls/winex11.drv/keyboard.c | 23 ++++++---
dlls/winex11.drv/mouse.c | 89 +++++++++++++++++++++++++++++++++-
dlls/winex11.drv/x11drv.h | 1 +
dlls/winex11.drv/x11drv_main.c | 1 +
4 files changed, 106 insertions(+), 8 deletions(-)
diff --git a/dlls/winex11.drv/keyboard.c b/dlls/winex11.drv/keyboard.c
index 7856b04c8f5..3f5d76be57b 100644
--- a/dlls/winex11.drv/keyboard.c
+++ b/dlls/winex11.drv/keyboard.c
@@ -2010,13 +2010,24 @@ BOOL X11DRV_MappingNotify( HWND dummy, XEvent *event )
{
HWND hwnd;
- XRefreshKeyboardMapping(&event->xmapping);
- X11DRV_InitKeyboard( event->xmapping.display );
+ switch (event->xmapping.request)
+ {
+ case MappingModifier:
+ case MappingKeyboard:
+ XRefreshKeyboardMapping( &event->xmapping );
+ X11DRV_InitKeyboard( event->xmapping.display );
+
+ hwnd = GetFocus();
+ if (!hwnd) hwnd = GetActiveWindow();
+ PostMessageW(hwnd, WM_INPUTLANGCHANGEREQUEST,
+ 0 /*FIXME*/, (LPARAM)X11DRV_GetKeyboardLayout(0));
+ break;
+
+ case MappingPointer:
+ X11DRV_InitMouse( event->xmapping.display );
+ break;
+ }
- hwnd = GetFocus();
- if (!hwnd) hwnd = GetActiveWindow();
- PostMessageW(hwnd, WM_INPUTLANGCHANGEREQUEST,
- 0 /*FIXME*/, (LPARAM)X11DRV_GetKeyboardLayout(0));
return TRUE;
}
diff --git a/dlls/winex11.drv/mouse.c b/dlls/winex11.drv/mouse.c
index 105db08a78a..19ed2a29287 100644
--- a/dlls/winex11.drv/mouse.c
+++ b/dlls/winex11.drv/mouse.c
@@ -25,6 +25,9 @@
#include <X11/Xlib.h>
#include <X11/cursorfont.h>
#include <stdarg.h>
+#ifdef HAVE_X11_EXTENSIONS_XINPUT_H
+#include <X11/extensions/XInput.h>
+#endif
#ifdef HAVE_X11_EXTENSIONS_XINPUT2_H
#include <X11/extensions/XInput2.h>
#endif
@@ -143,6 +146,14 @@ MAKE_FUNCPTR(XISelectEvents);
#undef MAKE_FUNCPTR
#endif
+#ifdef HAVE_X11_EXTENSIONS_XINPUT_H
+#define MAKE_FUNCPTR(f) static typeof(f) * p##f
+MAKE_FUNCPTR(XOpenDevice);
+MAKE_FUNCPTR(XCloseDevice);
+MAKE_FUNCPTR(XGetDeviceButtonMapping);
+#undef MAKE_FUNCPTR
+#endif
+
/***********************************************************************
* X11DRV_Xcursor_Init
*
@@ -249,6 +260,70 @@ void sync_window_cursor( Window window )
set_window_cursor( window, cursor );
}
+struct mouse_button_mapping
+{
+ int deviceid;
+ unsigned int button_count;
+ unsigned char buttons[256];
+};
+
+static struct mouse_button_mapping *pointer_mapping;
+static struct mouse_button_mapping *device_mapping;
+
+static void update_pointer_mapping( Display *display )
+{
+ struct mouse_button_mapping *tmp;
+
+ if (!(tmp = HeapAlloc( GetProcessHeap(), 0, sizeof(*tmp) )))
+ {
+ WARN("Unable to allocate device mapping.\n");
+ return;
+ }
+
+ tmp->button_count = ARRAY_SIZE( tmp->buttons );
+ tmp->button_count = XGetPointerMapping( display, tmp->buttons, tmp->button_count );
+
+ tmp = InterlockedExchangePointer( (void**)&pointer_mapping, tmp );
+
+ HeapFree( GetProcessHeap(), 0, tmp );
+}
+
+static void update_device_mapping( Display *display, int deviceid )
+{
+#ifdef HAVE_X11_EXTENSIONS_XINPUT_H
+ struct mouse_button_mapping *tmp;
+ XDevice *device;
+
+ if (!(device = pXOpenDevice( display, deviceid )))
+ {
+ WARN( "Unable to open cursor device %d\n", deviceid );
+ return;
+ }
+
+ if (!(tmp = HeapAlloc( GetProcessHeap(), 0, sizeof(*tmp) )))
+ {
+ WARN( "Unable to allocate device mapping.\n" );
+ pXCloseDevice( display, device );
+ return;
+ }
+
+ tmp->deviceid = deviceid;
+ tmp->button_count = ARRAY_SIZE( tmp->buttons );
+ tmp->button_count = pXGetDeviceButtonMapping( display, device, tmp->buttons, tmp->button_count );
+
+ tmp = InterlockedExchangePointer( (void**)&device_mapping, tmp );
+
+ HeapFree( GetProcessHeap(), 0, tmp );
+
+ pXCloseDevice( display, device );
+#endif
+}
+
+void X11DRV_InitMouse( Display *display )
+{
+ update_pointer_mapping( display );
+}
+
#ifdef HAVE_X11_EXTENSIONS_XINPUT2_H
/***********************************************************************
* update_relative_valuators
@@ -1792,6 +1867,8 @@ static BOOL X11DRV_DeviceChanged( XGenericEventCookie *xev )
if (event->reason != XISlaveSwitch) return FALSE;
update_relative_valuators( event->classes, event->num_classes );
+ update_device_mapping( event->display, event->sourceid );
+
return TRUE;
}
@@ -1861,13 +1938,12 @@ static BOOL X11DRV_RawMotion( XGenericEventCookie *xev )
#endif /* HAVE_X11_EXTENSIONS_XINPUT2_H */
-
/***********************************************************************
* X11DRV_XInput2_Init
*/
void X11DRV_XInput2_Init(void)
{
-#if defined(SONAME_LIBXI) && defined(HAVE_X11_EXTENSIONS_XINPUT2_H)
+#if defined(SONAME_LIBXI)
int event, error;
void *libxi_handle = wine_dlopen( SONAME_LIBXI, RTLD_NOW, NULL, 0 );
@@ -1883,11 +1959,20 @@ void X11DRV_XInput2_Init(void)
return; \
}
+#ifdef HAVE_X11_EXTENSIONS_XINPUT2_H
LOAD_FUNCPTR(XIGetClientPointer);
LOAD_FUNCPTR(XIFreeDeviceInfo);
LOAD_FUNCPTR(XIQueryDevice);
LOAD_FUNCPTR(XIQueryVersion);
LOAD_FUNCPTR(XISelectEvents);
+#endif
+
+#ifdef HAVE_X11_EXTENSIONS_XINPUT_H
+ LOAD_FUNCPTR(XOpenDevice);
+ LOAD_FUNCPTR(XCloseDevice);
+ LOAD_FUNCPTR(XGetDeviceButtonMapping);
+#endif
+
#undef LOAD_FUNCPTR
xinput2_available = XQueryExtension( gdi_display, "XInputExtension", &xinput2_opcode, &event, &error );
diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h
index 432dd5909ca..7145fec74e7 100644
--- a/dlls/winex11.drv/x11drv.h
+++ b/dlls/winex11.drv/x11drv.h
@@ -632,6 +632,7 @@ extern void retry_grab_clipping_window(void) DECLSPEC_HIDDEN;
extern BOOL clip_fullscreen_window( HWND hwnd, BOOL reset ) DECLSPEC_HIDDEN;
extern void move_resize_window( HWND hwnd, int dir ) DECLSPEC_HIDDEN;
extern void X11DRV_InitKeyboard( Display *display ) DECLSPEC_HIDDEN;
+extern void X11DRV_InitMouse( Display *display ) DECLSPEC_HIDDEN;
extern DWORD CDECL X11DRV_MsgWaitForMultipleObjectsEx( DWORD count, const HANDLE *handles, DWORD timeout,
DWORD mask, DWORD flags ) DECLSPEC_HIDDEN;
diff --git a/dlls/winex11.drv/x11drv_main.c b/dlls/winex11.drv/x11drv_main.c
index 11e4ee29155..ff9185a523c 100644
--- a/dlls/winex11.drv/x11drv_main.c
+++ b/dlls/winex11.drv/x11drv_main.c
@@ -623,6 +623,7 @@ static BOOL process_attach(void)
if (use_xkb) use_xkb = XkbUseExtension( gdi_display, NULL, NULL );
#endif
X11DRV_InitKeyboard( gdi_display );
+ X11DRV_InitMouse( gdi_display );
if (use_xim) use_xim = X11DRV_InitXIM( input_style );
X11DRV_DisplayDevices_Init(FALSE);
--
2.24.1

View File

@@ -0,0 +1,304 @@
From e8b90f221774d70fb9510b6de18378ab3abdcad2 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
Date: Wed, 11 Sep 2019 10:15:20 +0200
Subject: [PATCH 09/12] winex11.drv: Listen to RawMotion and RawButton* events
in the desktop thread.
We still need to send "normal" input from the clipping window thread
to trigger low-level hooks callbacks when clipping cursor. This is for
instance used in our dinput implementation.
---
dlls/user32/tests/input.c | 8 ++--
dlls/winex11.drv/event.c | 10 +++-
dlls/winex11.drv/mouse.c | 88 ++++++++++++++++++++++++++++------
dlls/winex11.drv/x11drv.h | 3 ++
dlls/winex11.drv/x11drv_main.c | 4 ++
5 files changed, 93 insertions(+), 20 deletions(-)
diff --git a/dlls/user32/tests/input.c b/dlls/user32/tests/input.c
index d18ccfebcaf..a1f983f1960 100644
--- a/dlls/user32/tests/input.c
+++ b/dlls/user32/tests/input.c
@@ -2049,12 +2049,12 @@ static void test_rawinput_mouse(const char *argv0)
{ TRUE, TRUE, 0, 2, 2, -1, -1, FALSE },
/* clip cursor tests */
- { TRUE, TRUE, 0, 0, 0, 0, 0, TRUE },
- { TRUE, TRUE, 0, 20, 20, 20, 20, TRUE },
+ { TRUE, TRUE, 0, 0, 0, 0, 0, FALSE },
+ { TRUE, TRUE, 0, 20, 20, 20, 20, FALSE },
/* same-process foreground tests */
- { TRUE, TRUE, 0, 2, 2, 0, 0, TRUE },
- { TRUE, TRUE, RIDEV_INPUTSINK, 2, 2, 0, 0, TRUE },
+ { TRUE, TRUE, 0, 2, 2, 0, 0, FALSE },
+ { TRUE, TRUE, RIDEV_INPUTSINK, 2, 2, 0, 0, FALSE },
/* cross-process foreground tests */
{ TRUE, TRUE, 0, 0, 0, 0, 0, FALSE },
diff --git a/dlls/winex11.drv/event.c b/dlls/winex11.drv/event.c
index 87ba808956f..b3faf3f7cc5 100644
--- a/dlls/winex11.drv/event.c
+++ b/dlls/winex11.drv/event.c
@@ -321,6 +321,10 @@ static enum event_merge_action merge_raw_motion_events( XIRawEvent *prev, XIRawE
*/
static enum event_merge_action merge_events( XEvent *prev, XEvent *next )
{
+#ifdef HAVE_X11_EXTENSIONS_XINPUT2_H
+ struct x11drv_thread_data *thread_data = x11drv_thread_data();
+#endif
+
switch (prev->type)
{
case ConfigureNotify:
@@ -352,19 +356,21 @@ static enum event_merge_action merge_events( XEvent *prev, XEvent *next )
case GenericEvent:
if (next->xcookie.extension != xinput2_opcode) break;
if (next->xcookie.evtype != XI_RawMotion) break;
- if (x11drv_thread_data()->warp_serial) break;
+ if (thread_data->xi2_rawinput_only) break;
+ if (thread_data->warp_serial) break;
return MERGE_KEEP;
}
break;
case GenericEvent:
if (prev->xcookie.extension != xinput2_opcode) break;
if (prev->xcookie.evtype != XI_RawMotion) break;
+ if (thread_data->xi2_rawinput_only) break;
switch (next->type)
{
case GenericEvent:
if (next->xcookie.extension != xinput2_opcode) break;
if (next->xcookie.evtype != XI_RawMotion) break;
- if (x11drv_thread_data()->warp_serial) break;
+ if (thread_data->warp_serial) break;
return merge_raw_motion_events( prev->xcookie.data, next->xcookie.data );
#endif
}
diff --git a/dlls/winex11.drv/mouse.c b/dlls/winex11.drv/mouse.c
index 19ed2a29287..d331ed5aef8 100644
--- a/dlls/winex11.drv/mouse.c
+++ b/dlls/winex11.drv/mouse.c
@@ -364,9 +364,9 @@ static void update_relative_valuators(XIAnyClassInfo **valuators, int n_valuator
/***********************************************************************
- * enable_xinput2
+ * X11DRV_XInput2_Enable
*/
-static void enable_xinput2(void)
+void X11DRV_XInput2_Enable(void)
{
#ifdef HAVE_X11_EXTENSIONS_XINPUT2_H
struct x11drv_thread_data *data = x11drv_thread_data();
@@ -398,9 +398,21 @@ static void enable_xinput2(void)
mask.mask_len = sizeof(mask_bits);
mask.deviceid = XIAllMasterDevices;
memset( mask_bits, 0, sizeof(mask_bits) );
+
XISetMask( mask_bits, XI_DeviceChanged );
XISetMask( mask_bits, XI_RawMotion );
- XISetMask( mask_bits, XI_ButtonPress );
+
+ if (GetWindowThreadProcessId( GetDesktopWindow(), NULL ) == GetCurrentThreadId())
+ {
+ XISetMask( mask_bits, XI_RawButtonPress );
+ XISetMask( mask_bits, XI_RawButtonRelease );
+ data->xi2_rawinput_only = TRUE;
+ }
+ else
+ {
+ XISetMask( mask_bits, XI_ButtonPress );
+ data->xi2_rawinput_only = FALSE;
+ }
pXISelectEvents( data->display, DefaultRootWindow( data->display ), &mask, 1 );
@@ -413,9 +425,9 @@ static void enable_xinput2(void)
}
/***********************************************************************
- * disable_xinput2
+ * X11DRV_XInput2_Disable
*/
-static void disable_xinput2(void)
+void X11DRV_XInput2_Disable(void)
{
#ifdef HAVE_X11_EXTENSIONS_XINPUT2_H
struct x11drv_thread_data *data = x11drv_thread_data();
@@ -475,7 +487,7 @@ static BOOL grab_clipping_window( const RECT *clip )
}
/* enable XInput2 unless we are already clipping */
- if (!data->clip_hwnd) enable_xinput2();
+ if (!data->clip_hwnd) X11DRV_XInput2_Enable();
if (data->xi2_state != xi_enabled)
{
@@ -505,7 +517,7 @@ static BOOL grab_clipping_window( const RECT *clip )
if (!clipping_cursor)
{
- disable_xinput2();
+ X11DRV_XInput2_Disable();
DestroyWindow( msg_hwnd );
return FALSE;
}
@@ -586,7 +598,7 @@ LRESULT clip_cursor_notify( HWND hwnd, HWND prev_clip_hwnd, HWND new_clip_hwnd )
TRACE( "clip hwnd reset from %p\n", hwnd );
data->clip_hwnd = 0;
data->clip_reset = GetTickCount();
- disable_xinput2();
+ X11DRV_XInput2_Disable();
DestroyWindow( hwnd );
}
else if (hwnd == GetForegroundWindow()) /* request to clip */
@@ -725,7 +737,7 @@ static void send_mouse_input( HWND hwnd, Window window, unsigned int state, INPU
}
input->u.mi.dx += clip_rect.left;
input->u.mi.dy += clip_rect.top;
- __wine_send_input( hwnd, input, SEND_HWMSG_RAWINPUT|SEND_HWMSG_WINDOW );
+ __wine_send_input( hwnd, input, SEND_HWMSG_WINDOW );
return;
}
@@ -765,7 +777,7 @@ static void send_mouse_input( HWND hwnd, Window window, unsigned int state, INPU
SERVER_END_REQ;
}
- __wine_send_input( hwnd, input, SEND_HWMSG_RAWINPUT|SEND_HWMSG_WINDOW );
+ __wine_send_input( hwnd, input, SEND_HWMSG_WINDOW );
}
#ifdef SONAME_LIBXCURSOR
@@ -1711,7 +1723,7 @@ void move_resize_window( HWND hwnd, int dir )
input.u.mi.dwFlags = button_up_flags[button - 1] | MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE;
input.u.mi.time = GetTickCount();
input.u.mi.dwExtraInfo = 0;
- __wine_send_input( hwnd, &input, SEND_HWMSG_RAWINPUT|SEND_HWMSG_WINDOW );
+ __wine_send_input( hwnd, &input, SEND_HWMSG_WINDOW );
}
while (PeekMessageW( &msg, 0, 0, 0, PM_REMOVE ))
@@ -1894,6 +1906,7 @@ static BOOL X11DRV_RawMotion( XGenericEventCookie *xev )
x_rel = &thread_data->x_rel_valuator;
y_rel = &thread_data->y_rel_valuator;
+ input.type = INPUT_MOUSE;
input.u.mi.mouseData = 0;
input.u.mi.dwFlags = MOUSEEVENTF_MOVE;
input.u.mi.time = EVENT_x11_time_to_win32_time( event->time );
@@ -1929,10 +1942,53 @@ static BOOL X11DRV_RawMotion( XGenericEventCookie *xev )
return FALSE;
}
- TRACE( "pos %d,%d (event %f,%f)\n", input.u.mi.dx, input.u.mi.dy, dx, dy );
+ if (!thread_data->xi2_rawinput_only)
+ {
+ TRACE( "pos %d,%d (event %f,%f)\n", input.u.mi.dx, input.u.mi.dy, dx, dy );
+ __wine_send_input( 0, &input, SEND_HWMSG_WINDOW );
+ }
+ else
+ {
+ TRACE( "raw pos %d,%d (event %f,%f)\n", input.u.mi.dx, input.u.mi.dy, dx, dy );
+ __wine_send_input( 0, &input, SEND_HWMSG_RAWINPUT );
+ }
+ return TRUE;
+}
- input.type = INPUT_MOUSE;
- __wine_send_input( 0, &input, SEND_HWMSG_RAWINPUT|SEND_HWMSG_WINDOW );
+/***********************************************************************
+ * X11DRV_RawButtonEvent
+ */
+static BOOL X11DRV_RawButtonEvent( XGenericEventCookie *cookie )
+{
+ struct x11drv_thread_data *thread_data = x11drv_thread_data();
+ XIRawEvent *event = cookie->data;
+ int button = event->detail - 1;
+ INPUT input;
+
+ if (!device_mapping || device_mapping->deviceid != event->sourceid)
+ update_device_mapping( event->display, event->sourceid );
+
+ if (button >= 0 && device_mapping)
+ button = device_mapping->buttons[button] - 1;
+
+ if (button >= 0 && pointer_mapping)
+ button = pointer_mapping->buttons[button] - 1;
+
+ if (button < 0 || button >= NB_BUTTONS) return FALSE;
+ if (thread_data->xi2_state != xi_enabled) return FALSE;
+ if (event->deviceid != thread_data->xi2_core_pointer) return FALSE;
+
+ TRACE( "raw button %u (raw: %u) %s\n", button, event->detail, event->evtype == XI_RawButtonRelease ? "up" : "down" );
+
+ input.type = INPUT_MOUSE;
+ input.u.mi.dx = 0;
+ input.u.mi.dy = 0;
+ input.u.mi.mouseData = event->evtype == XI_RawButtonRelease ? button_up_data[button] : button_down_data[button];
+ input.u.mi.dwFlags = event->evtype == XI_RawButtonRelease ? button_up_flags[button] : button_down_flags[button];
+ input.u.mi.time = EVENT_x11_time_to_win32_time(event->time);
+ input.u.mi.dwExtraInfo = 0;
+
+ __wine_send_input( 0, &input, SEND_HWMSG_RAWINPUT );
return TRUE;
}
@@ -2008,6 +2064,10 @@ BOOL X11DRV_GenericEvent( HWND hwnd, XEvent *xev )
case XI_RawMotion:
ret = X11DRV_RawMotion( event );
break;
+ case XI_RawButtonPress:
+ case XI_RawButtonRelease:
+ ret = X11DRV_RawButtonEvent( event );
+ break;
default:
TRACE( "Unhandled event %#x\n", event->evtype );
diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h
index 7145fec74e7..4a7cab67ada 100644
--- a/dlls/winex11.drv/x11drv.h
+++ b/dlls/winex11.drv/x11drv.h
@@ -196,6 +196,8 @@ extern BOOL CDECL X11DRV_UnrealizePalette( HPALETTE hpal ) DECLSPEC_HIDDEN;
extern void X11DRV_Xcursor_Init(void) DECLSPEC_HIDDEN;
extern void X11DRV_XInput2_Init(void) DECLSPEC_HIDDEN;
+extern void X11DRV_XInput2_Enable(void) DECLSPEC_HIDDEN;
+extern void X11DRV_XInput2_Disable(void) DECLSPEC_HIDDEN;
extern DWORD copy_image_bits( BITMAPINFO *info, BOOL is_r8g8b8, XImage *image,
const struct gdi_image_bits *src_bits, struct gdi_image_bits *dst_bits,
@@ -343,6 +345,7 @@ struct x11drv_thread_data
struct x11drv_valuator_data x_rel_valuator;
struct x11drv_valuator_data y_rel_valuator;
int xi2_core_pointer; /* XInput2 core pointer id */
+ int xi2_rawinput_only;
};
extern struct x11drv_thread_data *x11drv_init_thread_data(void) DECLSPEC_HIDDEN;
diff --git a/dlls/winex11.drv/x11drv_main.c b/dlls/winex11.drv/x11drv_main.c
index ff9185a523c..f33a79d98bf 100644
--- a/dlls/winex11.drv/x11drv_main.c
+++ b/dlls/winex11.drv/x11drv_main.c
@@ -640,6 +640,8 @@ void CDECL X11DRV_ThreadDetach(void)
if (data)
{
+ if (GetWindowThreadProcessId( GetDesktopWindow(), NULL ) == GetCurrentThreadId())
+ X11DRV_XInput2_Disable();
if (data->xim) XCloseIM( data->xim );
if (data->font_set) XFreeFontSet( data->display, data->font_set );
XCloseDisplay( data->display );
@@ -712,6 +714,8 @@ struct x11drv_thread_data *x11drv_init_thread_data(void)
TlsSetValue( thread_data_tls_index, data );
if (use_xim) X11DRV_SetupXIM();
+ if (GetWindowThreadProcessId( GetDesktopWindow(), NULL ) == GetCurrentThreadId())
+ X11DRV_XInput2_Enable();
return data;
}
--
2.24.1

View File

@@ -0,0 +1,204 @@
From d4dd0d48cec74bd2185eae5a6020c026040c1319 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
Date: Mon, 26 Aug 2019 16:06:58 +0200
Subject: [PATCH 10/12] user32: Implement GetRegisteredRawInputDevices.
---
dlls/dinput8/tests/device.c | 13 ---------
dlls/user32/rawinput.c | 55 +++++++++++++++++++++++++++++++++++--
server/protocol.def | 6 ++++
server/queue.c | 24 ++++++++++++++++
4 files changed, 83 insertions(+), 15 deletions(-)
diff --git a/dlls/dinput8/tests/device.c b/dlls/dinput8/tests/device.c
index bec2a6b863c..45fc2889066 100644
--- a/dlls/dinput8/tests/device.c
+++ b/dlls/dinput8/tests/device.c
@@ -652,7 +652,6 @@ static void test_mouse_keyboard(void)
raw_devices_count = ARRAY_SIZE(raw_devices);
GetRegisteredRawInputDevices(NULL, &raw_devices_count, sizeof(RAWINPUTDEVICE));
- todo_wine
ok(raw_devices_count == 0, "Unexpected raw devices registered: %d\n", raw_devices_count);
hr = IDirectInputDevice8_Acquire(di_keyboard);
@@ -674,7 +673,6 @@ static void test_mouse_keyboard(void)
ok(SUCCEEDED(hr), "IDirectInputDevice8_Acquire failed: %08x\n", hr);
raw_devices_count = ARRAY_SIZE(raw_devices);
GetRegisteredRawInputDevices(NULL, &raw_devices_count, sizeof(RAWINPUTDEVICE));
- todo_wine
ok(raw_devices_count == 0, "Unexpected raw devices registered: %d\n", raw_devices_count);
if (raw_devices[0].hwndTarget != NULL)
@@ -712,7 +710,6 @@ static void test_mouse_keyboard(void)
ok(SUCCEEDED(hr), "IDirectInputDevice8_Acquire failed: %08x\n", hr);
raw_devices_count = ARRAY_SIZE(raw_devices);
GetRegisteredRawInputDevices(NULL, &raw_devices_count, sizeof(RAWINPUTDEVICE));
- todo_wine
ok(raw_devices_count == 0, "Unexpected raw devices registered: %d\n", raw_devices_count);
/* expect dinput8 to take over any activated raw input devices */
@@ -739,26 +736,18 @@ static void test_mouse_keyboard(void)
raw_devices_count = ARRAY_SIZE(raw_devices);
memset(raw_devices, 0, sizeof(raw_devices));
hr = GetRegisteredRawInputDevices(raw_devices, &raw_devices_count, sizeof(RAWINPUTDEVICE));
- todo_wine
ok(hr == 3, "GetRegisteredRawInputDevices returned %d, raw_devices_count: %d\n", hr, raw_devices_count);
- todo_wine
ok(raw_devices[0].usUsagePage == 1, "Unexpected raw device usage page: %x\n", raw_devices[0].usUsagePage);
- todo_wine
ok(raw_devices[0].usUsage == 2, "Unexpected raw device usage: %x\n", raw_devices[0].usUsage);
todo_wine
ok(raw_devices[0].dwFlags == RIDEV_INPUTSINK, "Unexpected raw device flags: %x\n", raw_devices[0].dwFlags);
todo_wine
ok(raw_devices[0].hwndTarget == di_hwnd, "Unexpected raw device target: %p\n", raw_devices[0].hwndTarget);
- todo_wine
ok(raw_devices[1].usUsagePage == 1, "Unexpected raw device usage page: %x\n", raw_devices[1].usUsagePage);
- todo_wine
ok(raw_devices[1].usUsage == 5, "Unexpected raw device usage: %x\n", raw_devices[1].usUsage);
ok(raw_devices[1].dwFlags == 0, "Unexpected raw device flags: %x\n", raw_devices[1].dwFlags);
- todo_wine
ok(raw_devices[1].hwndTarget == hwnd, "Unexpected raw device target: %p\n", raw_devices[1].hwndTarget);
- todo_wine
ok(raw_devices[2].usUsagePage == 1, "Unexpected raw device usage page: %x\n", raw_devices[1].usUsagePage);
- todo_wine
ok(raw_devices[2].usUsage == 6, "Unexpected raw device usage: %x\n", raw_devices[1].usUsage);
todo_wine
ok(raw_devices[2].dwFlags == RIDEV_INPUTSINK, "Unexpected raw device flags: %x\n", raw_devices[1].dwFlags);
@@ -777,12 +766,10 @@ static void test_mouse_keyboard(void)
hr = GetRegisteredRawInputDevices(raw_devices, &raw_devices_count, sizeof(RAWINPUTDEVICE));
todo_wine
ok(hr == 1, "GetRegisteredRawInputDevices returned %d, raw_devices_count: %d\n", hr, raw_devices_count);
- todo_wine
ok(raw_devices[0].usUsagePage == 1, "Unexpected raw device usage page: %x\n", raw_devices[0].usUsagePage);
todo_wine
ok(raw_devices[0].usUsage == 5, "Unexpected raw device usage: %x\n", raw_devices[0].usUsage);
ok(raw_devices[0].dwFlags == 0, "Unexpected raw device flags: %x\n", raw_devices[0].dwFlags);
- todo_wine
ok(raw_devices[0].hwndTarget == hwnd, "Unexpected raw device target: %p\n", raw_devices[0].hwndTarget);
IDirectInputDevice8_Release(di_mouse);
diff --git a/dlls/user32/rawinput.c b/dlls/user32/rawinput.c
index 85ff0c5e809..3792360b057 100644
--- a/dlls/user32/rawinput.c
+++ b/dlls/user32/rawinput.c
@@ -501,14 +501,65 @@ UINT WINAPI GetRawInputDeviceInfoW(HANDLE device, UINT command, void *data, UINT
return *data_size;
}
+static int compare_raw_input_devices(const void *ap, const void *bp)
+{
+ const RAWINPUTDEVICE a = *(const RAWINPUTDEVICE *)ap;
+ const RAWINPUTDEVICE b = *(const RAWINPUTDEVICE *)bp;
+
+ if (a.usUsagePage != b.usUsagePage) return a.usUsagePage - b.usUsagePage;
+ if (a.usUsage != b.usUsage) return a.usUsage - b.usUsage;
+ return 0;
+}
+
/***********************************************************************
* GetRegisteredRawInputDevices (USER32.@)
*/
UINT WINAPI DECLSPEC_HOTPATCH GetRegisteredRawInputDevices(RAWINPUTDEVICE *devices, UINT *device_count, UINT size)
{
- FIXME("devices %p, device_count %p, size %u stub!\n", devices, device_count, size);
+ struct rawinput_device *d = NULL;
+ unsigned int count = ~0U;
- return 0;
+ TRACE("devices %p, device_count %p, size %u\n", devices, device_count, size);
+
+ if (!device_count)
+ {
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return ~0U;
+ }
+
+ if (devices && !(d = HeapAlloc( GetProcessHeap(), 0, *device_count * sizeof(*d) )))
+ return ~0U;
+
+ SERVER_START_REQ( get_rawinput_devices )
+ {
+ if (d)
+ wine_server_set_reply( req, d, *device_count * sizeof(*d) );
+
+ if (wine_server_call( req ))
+ goto done;
+
+ if (!d || reply->device_count > *device_count)
+ {
+ *device_count = reply->device_count;
+ SetLastError( ERROR_INSUFFICIENT_BUFFER );
+ goto done;
+ }
+
+ for (count = 0; count < reply->device_count; ++count)
+ {
+ devices[count].usUsagePage = d[count].usage_page;
+ devices[count].usUsage = d[count].usage;
+ devices[count].dwFlags = d[count].flags;
+ devices[count].hwndTarget = wine_server_ptr_handle(d[count].target);
+ }
+ }
+ SERVER_END_REQ;
+
+ qsort(devices, count, sizeof(*devices), compare_raw_input_devices);
+
+done:
+ if (d) HeapFree( GetProcessHeap(), 0, d );
+ return count;
}
diff --git a/server/protocol.def b/server/protocol.def
index 9f9f9197134..d37dceba40c 100644
--- a/server/protocol.def
+++ b/server/protocol.def
@@ -3986,6 +3986,12 @@ struct handle_info
VARARG(devices,rawinput_devices);
@END
+/* Retrieve the list of registered rawinput devices */
+@REQ(get_rawinput_devices)
+@REPLY
+ unsigned int device_count;
+ VARARG(devices,rawinput_devices);
+@END
/* Retrieve the suspended context of a thread */
@REQ(get_suspend_context)
diff --git a/server/queue.c b/server/queue.c
index 2bdd099d1bb..8a1bbfff5aa 100644
--- a/server/queue.c
+++ b/server/queue.c
@@ -3382,3 +3382,27 @@ DECL_HANDLER(esync_msgwait)
if (current->process->idle_event && !(queue->wake_mask & QS_SMRESULT))
set_event( current->process->idle_event );
}
+
+DECL_HANDLER(get_rawinput_devices)
+{
+ unsigned int device_count = list_count(&current->process->rawinput_devices);
+ struct rawinput_device *devices;
+ struct rawinput_device_entry *e;
+ unsigned int i;
+
+ reply->device_count = device_count;
+ if (get_reply_max_size() / sizeof (*devices) < device_count)
+ return;
+
+ if (!(devices = mem_alloc( device_count * sizeof (*devices) )))
+ {
+ set_error( STATUS_NO_MEMORY );
+ return;
+ }
+
+ i = 0;
+ LIST_FOR_EACH_ENTRY( e, &current->process->rawinput_devices, struct rawinput_device_entry, entry )
+ devices[i++] = e->device;
+
+ set_reply_data_ptr( devices, device_count * sizeof (*devices) );
+}
--
2.24.1

View File

@@ -0,0 +1,174 @@
From 7f814cd77f1766b98318bbc8ea5fff241c20ec4b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
Date: Mon, 26 Aug 2019 16:06:59 +0200
Subject: [PATCH 11/12] dinput8: Add support for dinput devices that use raw
input interface.
This adds a global message window that will receive WM_INPUT messages,
dispatched to every raw input device event_proc.
Devices that use raw input interface will not register low-level hooks
anymore. They will also conflict with any raw input device registered
outside of dinput, as exposed by the unit tests.
---
dlls/dinput/device_private.h | 3 ++
dlls/dinput/dinput_main.c | 84 +++++++++++++++++++++++++++++++++++-
2 files changed, 86 insertions(+), 1 deletion(-)
diff --git a/dlls/dinput/device_private.h b/dlls/dinput/device_private.h
index 114e3971ed8..9116aaeab66 100644
--- a/dlls/dinput/device_private.h
+++ b/dlls/dinput/device_private.h
@@ -70,6 +70,9 @@ struct IDirectInputDeviceImpl
int acquired;
DI_EVENT_PROC event_proc; /* function to receive mouse & keyboard events */
+ BOOL use_raw_input; /* use raw input instead of low-level messages */
+ RAWINPUTDEVICE raw_device; /* raw device to (un)register */
+
LPDIDEVICEOBJECTDATA data_queue; /* buffer for 'GetDeviceData'. */
int queue_len; /* size of the queue - set in 'SetProperty' */
int queue_head; /* position to write new event into queue */
diff --git a/dlls/dinput/dinput_main.c b/dlls/dinput/dinput_main.c
index 4d2d4afe106..9e3b9f48250 100644
--- a/dlls/dinput/dinput_main.c
+++ b/dlls/dinput/dinput_main.c
@@ -98,6 +98,10 @@ static const struct dinput_device *dinput_devices[] =
HINSTANCE DINPUT_instance;
+static ATOM di_em_win_class;
+static const WCHAR di_em_winW[] = {'D','I','E','m','W','i','n',0};
+static HWND di_em_win;
+
static BOOL check_hook_thread(void);
static CRITICAL_SECTION dinput_hook_crit;
static struct list direct_input_list = LIST_INIT( direct_input_list );
@@ -626,6 +630,59 @@ static HRESULT WINAPI IDirectInputWImpl_QueryInterface(LPDIRECTINPUT7W iface, RE
return IDirectInputAImpl_QueryInterface( &This->IDirectInput7A_iface, riid, ppobj );
}
+static LRESULT WINAPI di_em_win_wndproc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
+{
+ IDirectInputImpl *dinput;
+
+ TRACE( "%p %d %lx %lx\n", hwnd, msg, wparam, lparam );
+
+ if (msg == WM_INPUT)
+ {
+ EnterCriticalSection( &dinput_hook_crit );
+ LIST_FOR_EACH_ENTRY( dinput, &direct_input_list, IDirectInputImpl, entry )
+ {
+ IDirectInputDeviceImpl *dev;
+
+ EnterCriticalSection( &dinput->crit );
+ LIST_FOR_EACH_ENTRY( dev, &dinput->devices_list, IDirectInputDeviceImpl, entry )
+ {
+ if (dev->acquired && dev->event_proc && dev->use_raw_input)
+ {
+ TRACE("calling %p->%p (%lx %lx)\n", dev, dev->event_proc, wparam, lparam);
+ dev->event_proc( &dev->IDirectInputDevice8A_iface, GET_RAWINPUT_CODE_WPARAM(wparam), lparam );
+ }
+ }
+ LeaveCriticalSection( &dinput->crit );
+ }
+ LeaveCriticalSection( &dinput_hook_crit );
+ }
+
+ return DefWindowProcW(hwnd, msg, wparam, lparam);
+}
+
+static void register_di_em_win_class(void)
+{
+ static WNDCLASSEXW class;
+
+ ZeroMemory(&class, sizeof(class));
+ class.cbSize = sizeof(class);
+ class.lpfnWndProc = di_em_win_wndproc;
+ class.hInstance = DINPUT_instance;
+ class.lpszClassName = di_em_winW;
+
+ if (!(di_em_win_class = RegisterClassExW( &class )))
+ WARN( "Unable to register message window class\n" );
+}
+
+static void unregister_di_em_win_class(void)
+{
+ if (!di_em_win_class)
+ return;
+
+ if (!UnregisterClassW( MAKEINTRESOURCEW( di_em_win_class ), DINPUT_instance ))
+ WARN( "Unable to unregister message window class\n" );
+}
+
static HRESULT initialize_directinput_instance(IDirectInputImpl *This, DWORD dwVersion)
{
if (!This->initialized)
@@ -1695,7 +1752,7 @@ static LRESULT CALLBACK LL_hook_proc( int code, WPARAM wparam, LPARAM lparam )
EnterCriticalSection( &dinput->crit );
LIST_FOR_EACH_ENTRY( dev, &dinput->devices_list, IDirectInputDeviceImpl, entry )
- if (dev->acquired && dev->event_proc)
+ if (dev->acquired && dev->event_proc && !dev->use_raw_input)
{
TRACE("calling %p->%p (%lx %lx)\n", dev, dev->event_proc, wparam, lparam);
skip |= dev->event_proc( &dev->IDirectInputDevice8A_iface, wparam, lparam );
@@ -1748,6 +1805,9 @@ static DWORD WINAPI hook_thread_proc(void *param)
static HHOOK kbd_hook, mouse_hook;
MSG msg;
+ di_em_win = CreateWindowW( MAKEINTRESOURCEW(di_em_win_class), di_em_winW,
+ 0, 0, 0, 0, 0, HWND_MESSAGE, 0, DINPUT_instance, NULL );
+
/* Force creation of the message queue */
PeekMessageW( &msg, 0, 0, 0, PM_NOREMOVE );
SetEvent(param);
@@ -1812,6 +1872,9 @@ static DWORD WINAPI hook_thread_proc(void *param)
DispatchMessageW(&msg);
}
+ DestroyWindow( di_em_win );
+ di_em_win = NULL;
+
FreeLibraryAndExitThread(DINPUT_instance, 0);
}
@@ -1893,6 +1956,23 @@ void check_dinput_hooks(LPDIRECTINPUTDEVICE8W iface, BOOL acquired)
hook_thread_event = NULL;
}
+ if (dev->use_raw_input)
+ {
+ if (acquired)
+ {
+ dev->raw_device.dwFlags = RIDEV_INPUTSINK;
+ dev->raw_device.hwndTarget = di_em_win;
+ }
+ else
+ {
+ dev->raw_device.dwFlags = RIDEV_REMOVE;
+ dev->raw_device.hwndTarget = NULL;
+ }
+
+ if (!RegisterRawInputDevices( &dev->raw_device, 1, sizeof(RAWINPUTDEVICE) ))
+ WARN( "Unable to (un)register raw device %x:%x\n", dev->raw_device.usUsagePage, dev->raw_device.usUsage );
+ }
+
PostThreadMessageW( hook_thread_id, WM_USER+0x10, 1, 0 );
LeaveCriticalSection(&dinput_hook_crit);
@@ -1919,9 +1999,11 @@ BOOL WINAPI DllMain( HINSTANCE inst, DWORD reason, LPVOID reserved)
case DLL_PROCESS_ATTACH:
DisableThreadLibraryCalls(inst);
DINPUT_instance = inst;
+ register_di_em_win_class();
break;
case DLL_PROCESS_DETACH:
if (reserved) break;
+ unregister_di_em_win_class();
DeleteCriticalSection(&dinput_hook_crit);
break;
}
--
2.24.1

View File

@@ -0,0 +1,195 @@
From 4994e308b4f1e21c0d84de23df8c655c4bc5bf9f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
Date: Mon, 26 Aug 2019 14:08:20 +0200
Subject: [PATCH 12/12] dinput8: Use raw input interface for dinput8 mouse
device.
---
dlls/dinput/mouse.c | 117 +++++++++++++++++++++++++++++++++++-
dlls/dinput8/tests/device.c | 10 +--
2 files changed, 119 insertions(+), 8 deletions(-)
diff --git a/dlls/dinput/mouse.c b/dlls/dinput/mouse.c
index 2e0101facec..b8b88f38c15 100644
--- a/dlls/dinput/mouse.c
+++ b/dlls/dinput/mouse.c
@@ -246,6 +246,13 @@ static SysMouseImpl *alloc_device(REFGUID rguid, IDirectInputImpl *dinput)
list_add_tail(&dinput->devices_list, &newDevice->base.entry);
LeaveCriticalSection(&dinput->crit);
+ if (dinput->dwVersion >= 0x0800)
+ {
+ newDevice->base.use_raw_input = TRUE;
+ newDevice->base.raw_device.usUsagePage = 1; /* HID generic device page */
+ newDevice->base.raw_device.usUsage = 2; /* HID generic mouse */
+ }
+
return newDevice;
failed:
@@ -318,7 +325,115 @@ static int dinput_mouse_hook( LPDIRECTINPUTDEVICE8A iface, WPARAM wparam, LPARAM
{
MSLLHOOKSTRUCT *hook = (MSLLHOOKSTRUCT *)lparam;
SysMouseImpl* This = impl_from_IDirectInputDevice8A(iface);
- int wdata = 0, inst_id = -1, ret = 0;
+ int wdata = 0, inst_id = -1, ret = 0, i;
+
+ if (wparam == RIM_INPUT || wparam == RIM_INPUTSINK)
+ {
+ RAWINPUTHEADER raw_header;
+ RAWINPUT raw_input;
+ UINT size;
+ POINT rel, pt;
+
+ static const USHORT mouse_button_flags[] =
+ {
+ RI_MOUSE_BUTTON_1_DOWN, RI_MOUSE_BUTTON_1_UP,
+ RI_MOUSE_BUTTON_2_DOWN, RI_MOUSE_BUTTON_2_UP,
+ RI_MOUSE_BUTTON_3_DOWN, RI_MOUSE_BUTTON_3_UP,
+ RI_MOUSE_BUTTON_4_DOWN, RI_MOUSE_BUTTON_4_UP,
+ RI_MOUSE_BUTTON_5_DOWN, RI_MOUSE_BUTTON_5_UP
+ };
+
+ TRACE("(%p) wp %08lx, lp %08lx\n", iface, wparam, lparam);
+
+ size = sizeof(raw_header);
+ if (GetRawInputData( (HRAWINPUT)lparam, RID_HEADER, &raw_header, &size, sizeof(RAWINPUTHEADER) ) != sizeof(raw_header))
+ {
+ WARN( "Unable to read raw input data header\n" );
+ return 0;
+ }
+
+ if (raw_header.dwType != RIM_TYPEMOUSE)
+ return 0;
+
+ if (raw_header.dwSize > sizeof(raw_input))
+ {
+ WARN( "Unexpected size for mouse raw input data\n" );
+ return 0;
+ }
+
+ size = raw_header.dwSize;
+ if (GetRawInputData( (HRAWINPUT)lparam, RID_INPUT, &raw_input, &size, sizeof(RAWINPUTHEADER) ) != raw_header.dwSize )
+ {
+ WARN( "Unable to read raw input data\n" );
+ return 0;
+ }
+
+ if (raw_input.data.mouse.usFlags & MOUSE_VIRTUAL_DESKTOP)
+ FIXME( "Unimplemented MOUSE_VIRTUAL_DESKTOP flag\n" );
+ if (raw_input.data.mouse.usFlags & MOUSE_ATTRIBUTES_CHANGED)
+ FIXME( "Unimplemented MOUSE_ATTRIBUTES_CHANGED flag\n" );
+
+ EnterCriticalSection(&This->base.crit);
+
+ rel.x = raw_input.data.mouse.lLastX;
+ rel.y = raw_input.data.mouse.lLastY;
+ if (raw_input.data.mouse.usFlags & MOUSE_MOVE_ABSOLUTE)
+ {
+ GetCursorPos(&pt);
+ rel.x -= pt.x;
+ rel.y -= pt.y;
+ }
+
+ This->m_state.lX += rel.x;
+ This->m_state.lY += rel.y;
+
+ if (This->base.data_format.user_df->dwFlags & DIDF_ABSAXIS)
+ {
+ pt.x = This->m_state.lX;
+ pt.y = This->m_state.lY;
+ }
+ else
+ {
+ pt = rel;
+ }
+
+ if (rel.x)
+ queue_event(iface, DIDFT_MAKEINSTANCE(WINE_MOUSE_X_AXIS_INSTANCE) | DIDFT_RELAXIS,
+ pt.x, GetCurrentTime(), This->base.dinput->evsequence);
+
+ if (rel.y)
+ queue_event(iface, DIDFT_MAKEINSTANCE(WINE_MOUSE_Y_AXIS_INSTANCE) | DIDFT_RELAXIS,
+ pt.y, GetCurrentTime(), This->base.dinput->evsequence);
+
+ if (rel.x || rel.y)
+ {
+ if ((This->warp_override == WARP_FORCE_ON) ||
+ (This->warp_override != WARP_DISABLE && (This->base.dwCoopLevel & DISCL_EXCLUSIVE)))
+ This->need_warp = TRUE;
+ }
+
+ if (raw_input.data.mouse.usButtonFlags & RI_MOUSE_WHEEL)
+ {
+ This->m_state.lZ += (wdata = (SHORT)raw_input.data.mouse.usButtonData);
+ queue_event(iface, DIDFT_MAKEINSTANCE(WINE_MOUSE_Z_AXIS_INSTANCE) | DIDFT_RELAXIS,
+ wdata, GetCurrentTime(), This->base.dinput->evsequence);
+ ret = This->clipped;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(mouse_button_flags); ++i)
+ {
+ if (raw_input.data.mouse.usButtonFlags & mouse_button_flags[i])
+ {
+ This->m_state.rgbButtons[i / 2] = 0x80 - (i % 2) * 0x80;
+ queue_event(iface, DIDFT_MAKEINSTANCE(WINE_MOUSE_BUTTONS_INSTANCE + (i / 2)) | DIDFT_PSHBUTTON,
+ This->m_state.rgbButtons[i / 2], GetCurrentTime(), This->base.dinput->evsequence);
+ }
+ }
+
+ LeaveCriticalSection(&This->base.crit);
+
+ return ret;
+ }
TRACE("msg %lx @ (%d %d)\n", wparam, hook->pt.x, hook->pt.y);
diff --git a/dlls/dinput8/tests/device.c b/dlls/dinput8/tests/device.c
index 45fc2889066..42ba78707c6 100644
--- a/dlls/dinput8/tests/device.c
+++ b/dlls/dinput8/tests/device.c
@@ -696,13 +696,9 @@ static void test_mouse_keyboard(void)
raw_devices_count = ARRAY_SIZE(raw_devices);
memset(raw_devices, 0, sizeof(raw_devices));
hr = GetRegisteredRawInputDevices(raw_devices, &raw_devices_count, sizeof(RAWINPUTDEVICE));
- todo_wine
ok(hr == 1, "GetRegisteredRawInputDevices returned %d, raw_devices_count: %d\n", hr, raw_devices_count);
- todo_wine
ok(raw_devices[0].usUsagePage == 1, "Unexpected raw device usage page: %x\n", raw_devices[0].usUsagePage);
- todo_wine
ok(raw_devices[0].usUsage == 2, "Unexpected raw device usage: %x\n", raw_devices[0].usUsage);
- todo_wine
ok(raw_devices[0].dwFlags == RIDEV_INPUTSINK, "Unexpected raw device flags: %x\n", raw_devices[0].dwFlags);
todo_wine
ok(raw_devices[0].hwndTarget == di_hwnd, "Unexpected raw device target: %p\n", raw_devices[0].hwndTarget);
@@ -712,6 +708,9 @@ static void test_mouse_keyboard(void)
GetRegisteredRawInputDevices(NULL, &raw_devices_count, sizeof(RAWINPUTDEVICE));
ok(raw_devices_count == 0, "Unexpected raw devices registered: %d\n", raw_devices_count);
+ if (raw_devices[0].hwndTarget != NULL)
+ di_hwnd = raw_devices[0].hwndTarget;
+
/* expect dinput8 to take over any activated raw input devices */
raw_devices[0].usUsagePage = 0x01;
raw_devices[0].usUsage = 0x05;
@@ -739,9 +738,7 @@ static void test_mouse_keyboard(void)
ok(hr == 3, "GetRegisteredRawInputDevices returned %d, raw_devices_count: %d\n", hr, raw_devices_count);
ok(raw_devices[0].usUsagePage == 1, "Unexpected raw device usage page: %x\n", raw_devices[0].usUsagePage);
ok(raw_devices[0].usUsage == 2, "Unexpected raw device usage: %x\n", raw_devices[0].usUsage);
- todo_wine
ok(raw_devices[0].dwFlags == RIDEV_INPUTSINK, "Unexpected raw device flags: %x\n", raw_devices[0].dwFlags);
- todo_wine
ok(raw_devices[0].hwndTarget == di_hwnd, "Unexpected raw device target: %p\n", raw_devices[0].hwndTarget);
ok(raw_devices[1].usUsagePage == 1, "Unexpected raw device usage page: %x\n", raw_devices[1].usUsagePage);
ok(raw_devices[1].usUsage == 5, "Unexpected raw device usage: %x\n", raw_devices[1].usUsage);
@@ -767,7 +764,6 @@ static void test_mouse_keyboard(void)
todo_wine
ok(hr == 1, "GetRegisteredRawInputDevices returned %d, raw_devices_count: %d\n", hr, raw_devices_count);
ok(raw_devices[0].usUsagePage == 1, "Unexpected raw device usage page: %x\n", raw_devices[0].usUsagePage);
- todo_wine
ok(raw_devices[0].usUsage == 5, "Unexpected raw device usage: %x\n", raw_devices[0].usUsage);
ok(raw_devices[0].dwFlags == 0, "Unexpected raw device flags: %x\n", raw_devices[0].dwFlags);
ok(raw_devices[0].hwndTarget == hwnd, "Unexpected raw device target: %p\n", raw_devices[0].hwndTarget);
--
2.24.1

View File

@@ -0,0 +1,2 @@
Fixes: [42631] - user32: Add Raw Input support.
Depends: winex11.drv-mouse-coorrds