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

@ -304,6 +304,11 @@ patch_enable_all ()
enable_user32_ScrollWindowEx="$1"
enable_user32_ShowWindow="$1"
enable_user32_msgbox_Support_WM_COPY_mesg="$1"
enable_user32_rawinput_hid="$1"
enable_user32_rawinput_keyboard="$1"
enable_user32_rawinput_mouse="$1"
enable_user32_rawinput_mouse_experimental="$1"
enable_user32_rawinput_nolegacy="$1"
enable_user32_recursive_activation="$1"
enable_user32_window_activation="$1"
enable_uxtheme_CloseThemeClass="$1"
@ -1041,6 +1046,21 @@ patch_enable ()
user32-msgbox-Support-WM_COPY-mesg)
enable_user32_msgbox_Support_WM_COPY_mesg="$2"
;;
user32-rawinput-hid)
enable_user32_rawinput_hid="$2"
;;
user32-rawinput-keyboard)
enable_user32_rawinput_keyboard="$2"
;;
user32-rawinput-mouse)
enable_user32_rawinput_mouse="$2"
;;
user32-rawinput-mouse-experimental)
enable_user32_rawinput_mouse_experimental="$2"
;;
user32-rawinput-nolegacy)
enable_user32_rawinput_nolegacy="$2"
;;
user32-recursive-activation)
enable_user32_recursive_activation="$2"
;;
@ -1671,6 +1691,41 @@ if test "$enable_user32_window_activation" -eq 1; then
enable_user32_recursive_activation=1
fi
if test "$enable_user32_rawinput_mouse_experimental" -eq 1; then
if test "$enable_user32_rawinput_nolegacy" -gt 1; then
abort "Patchset user32-rawinput-nolegacy disabled, but user32-rawinput-mouse-experimental depends on that."
fi
enable_user32_rawinput_nolegacy=1
fi
if test "$enable_user32_rawinput_keyboard" -eq 1; then
if test "$enable_user32_rawinput_hid" -gt 1; then
abort "Patchset user32-rawinput-hid disabled, but user32-rawinput-keyboard depends on that."
fi
enable_user32_rawinput_hid=1
fi
if test "$enable_user32_rawinput_hid" -eq 1; then
if test "$enable_user32_rawinput_nolegacy" -gt 1; then
abort "Patchset user32-rawinput-nolegacy disabled, but user32-rawinput-hid depends on that."
fi
enable_user32_rawinput_nolegacy=1
fi
if test "$enable_user32_rawinput_nolegacy" -eq 1; then
if test "$enable_user32_rawinput_mouse" -gt 1; then
abort "Patchset user32-rawinput-mouse disabled, but user32-rawinput-nolegacy depends on that."
fi
enable_user32_rawinput_mouse=1
fi
if test "$enable_user32_rawinput_mouse" -eq 1; then
if test "$enable_winex11_drv_mouse_coorrds" -gt 1; then
abort "Patchset winex11.drv-mouse-coorrds disabled, but user32-rawinput-mouse depends on that."
fi
enable_winex11_drv_mouse_coorrds=1
fi
if test "$enable_stdole32_tlb_SLTG_Typelib" -eq 1; then
if test "$enable_widl_SLTG_Typelib_Support" -gt 1; then
abort "Patchset widl-SLTG_Typelib_Support disabled, but stdole32.tlb-SLTG_Typelib depends on that."
@ -6450,6 +6505,158 @@ if test "$enable_user32_msgbox_Support_WM_COPY_mesg" -eq 1; then
) >> "$patchlist"
fi
# Patchset winex11.drv-mouse-coorrds
# |
# | This patchset fixes the following Wine bugs:
# | * [#46309] winex11.drv: Use root-relative coordinates for events, if possible.
# |
# | Modified files:
# | * dlls/winex11.drv/mouse.c
# |
if test "$enable_winex11_drv_mouse_coorrds" -eq 1; then
patch_apply winex11.drv-mouse-coorrds/0001-winex11.drv-mouse-Use-root-relative-coordinates-for-ev.patch
(
printf '%s\n' '+ { "Gabriel Ivăncescu", "winex11.drv/mouse: Use root-relative coordinates for events, if possible.", 1 },';
) >> "$patchlist"
fi
# Patchset user32-rawinput-mouse
# |
# | This patchset has the following (direct or indirect) dependencies:
# | * winex11.drv-mouse-coorrds
# |
# | This patchset fixes the following Wine bugs:
# | * [#42631] - user32: Add Raw Input support.
# |
# | Modified files:
# | * dlls/dinput/device_private.h, dlls/dinput/dinput_main.c, dlls/dinput/mouse.c, dlls/dinput8/tests/device.c,
# | dlls/user32/input.c, dlls/user32/rawinput.c, dlls/user32/tests/input.c, dlls/user32/user32.spec,
# | dlls/wineandroid.drv/keyboard.c, dlls/wineandroid.drv/window.c, dlls/winemac.drv/ime.c, dlls/winemac.drv/keyboard.c,
# | dlls/winemac.drv/mouse.c, dlls/winex11.drv/event.c, dlls/winex11.drv/keyboard.c, dlls/winex11.drv/mouse.c,
# | dlls/winex11.drv/x11drv.h, dlls/winex11.drv/x11drv_main.c, include/winuser.h, server/protocol.def, server/queue.c
# |
if test "$enable_user32_rawinput_mouse" -eq 1; then
patch_apply user32-rawinput-mouse/0001-user32-tests-Add-rawinput-test-for-ClipCursor-intera.patch
patch_apply user32-rawinput-mouse/0002-user32-tests-Add-rawinput-test-for-cross-thread-inte.patch
patch_apply user32-rawinput-mouse/0003-user32-tests-Add-rawinput-test-for-cross-process-int.patch
patch_apply user32-rawinput-mouse/0004-server-Add-send_hardware_message-flags-for-rawinput-.patch
patch_apply user32-rawinput-mouse/0005-server-Broadcast-rawinput-message-if-request-flag-is.patch
patch_apply user32-rawinput-mouse/0006-user32-Add-__wine_send_input-flags-to-hint-raw-input.patch
patch_apply user32-rawinput-mouse/0007-winex11.drv-Advertise-XInput2-version-2.1-support.patch
patch_apply user32-rawinput-mouse/0008-winex11.drv-Keep-track-of-pointer-and-device-button-.patch
patch_apply user32-rawinput-mouse/0009-winex11.drv-Listen-to-RawMotion-and-RawButton-events.patch
patch_apply user32-rawinput-mouse/0010-user32-Implement-GetRegisteredRawInputDevices.patch
patch_apply user32-rawinput-mouse/0011-dinput8-Add-support-for-dinput-devices-that-use-raw-.patch
patch_apply user32-rawinput-mouse/0012-dinput8-Use-raw-input-interface-for-dinput8-mouse-de.patch
(
printf '%s\n' '+ { "Rémi Bernon", "user32/tests: Add rawinput test for ClipCursor interactions.", 1 },';
printf '%s\n' '+ { "Rémi Bernon", "user32/tests: Add rawinput test for cross-thread interactions.", 1 },';
printf '%s\n' '+ { "Rémi Bernon", "user32/tests: Add rawinput test for cross-process interactions.", 1 },';
printf '%s\n' '+ { "Rémi Bernon", "server: Add send_hardware_message flags for rawinput translation.", 1 },';
printf '%s\n' '+ { "Rémi Bernon", "server: Broadcast rawinput message if request flag is SEND_HWMSG_RAWINPUT.", 1 },';
printf '%s\n' '+ { "Rémi Bernon", "user32: Add __wine_send_input flags to hint raw input translation.", 1 },';
printf '%s\n' '+ { "Rémi Bernon", "winex11.drv: Advertise XInput2 version 2.1 support.", 1 },';
printf '%s\n' '+ { "Rémi Bernon", "winex11.drv: Keep track of pointer and device button mappings.", 1 },';
printf '%s\n' '+ { "Rémi Bernon", "winex11.drv: Listen to RawMotion and RawButton* events in the desktop thread.", 1 },';
printf '%s\n' '+ { "Rémi Bernon", "user32: Implement GetRegisteredRawInputDevices.", 1 },';
printf '%s\n' '+ { "Rémi Bernon", "dinput8: Add support for dinput devices that use raw input interface.", 1 },';
printf '%s\n' '+ { "Rémi Bernon", "dinput8: Use raw input interface for dinput8 mouse device.", 1 },';
) >> "$patchlist"
fi
# Patchset user32-rawinput-nolegacy
# |
# | This patchset has the following (direct or indirect) dependencies:
# | * winex11.drv-mouse-coorrds, user32-rawinput-mouse
# |
# | Modified files:
# | * dlls/dinput/dinput_main.c, dlls/dinput8/tests/device.c, dlls/user32/rawinput.c, server/queue.c
# |
if test "$enable_user32_rawinput_nolegacy" -eq 1; then
patch_apply user32-rawinput-nolegacy/0001-dinput8-tests-Add-test-for-DISCL_EXCLUSIVE-flag-inte.patch
patch_apply user32-rawinput-nolegacy/0002-user32-Add-support-for-RIDEV_NOLEGACY-flag-in-Regist.patch
patch_apply user32-rawinput-nolegacy/0003-dinput-Set-RIDEV_INPUTSINK-flag-only-when-DISCL_BACK.patch
patch_apply user32-rawinput-nolegacy/0004-dinput-Set-correct-rawinput-flags-for-DISCL_EXCLUSIV.patch
(
printf '%s\n' '+ { "Rémi Bernon", "dinput8/tests: Add test for DISCL_EXCLUSIVE flag interaction with rawinput.", 1 },';
printf '%s\n' '+ { "Derek Lesho", "user32: Add support for RIDEV_NOLEGACY flag in RegisterRawInputDevices.", 1 },';
printf '%s\n' '+ { "Rémi Bernon", "dinput: Set RIDEV_INPUTSINK flag only when DISCL_BACKGROUND is requested.", 1 },';
printf '%s\n' '+ { "Rémi Bernon", "dinput: Set correct rawinput flags for DISCL_EXCLUSIVE.", 1 },';
) >> "$patchlist"
fi
# Patchset user32-rawinput-hid
# |
# | This patchset has the following (direct or indirect) dependencies:
# | * winex11.drv-mouse-coorrds, user32-rawinput-mouse, user32-rawinput-nolegacy
# |
# | Modified files:
# | * dlls/hidclass.sys/device.c, dlls/hidclass.sys/hid.h, dlls/hidclass.sys/pnp.c, dlls/user32/message.c,
# | dlls/user32/rawinput.c, dlls/user32/user_private.h, server/protocol.def, server/queue.c, server/trace.c
# |
if test "$enable_user32_rawinput_hid" -eq 1; then
patch_apply user32-rawinput-hid/0001-server-Add-process-argument-to-find_rawinput_device.patch
patch_apply user32-rawinput-hid/0002-server-Allow-extra-data-for-hardware_msg_data-messag.patch
patch_apply user32-rawinput-hid/0003-server-Add-HID-input-message-type-to-send_hardware_m.patch
patch_apply user32-rawinput-hid/0004-user32-Implement-WM_INPUT-RIM_TYPEHID-message-handli.patch
patch_apply user32-rawinput-hid/0005-hidclass.sys-Send-input-message-to-server-when-HID-r.patch
(
printf '%s\n' '+ { "Rémi Bernon", "server: Add process argument to find_rawinput_device.", 1 },';
printf '%s\n' '+ { "Rémi Bernon", "server: Allow extra data for hardware_msg_data message.", 1 },';
printf '%s\n' '+ { "Rémi Bernon", "server: Add HID input message type to send_hardware_message request.", 1 },';
printf '%s\n' '+ { "Rémi Bernon", "user32: Implement WM_INPUT/RIM_TYPEHID message handling.", 1 },';
printf '%s\n' '+ { "Rémi Bernon", "hidclass.sys: Send input message to server when HID report is received.", 1 },';
) >> "$patchlist"
fi
# Patchset user32-rawinput-keyboard
# |
# | This patchset has the following (direct or indirect) dependencies:
# | * winex11.drv-mouse-coorrds, user32-rawinput-mouse, user32-rawinput-nolegacy, user32-rawinput-hid
# |
# | Modified files:
# | * dlls/dinput/device.c, dlls/dinput/device_private.h, dlls/dinput/keyboard.c, dlls/dinput/mouse.c,
# | dlls/dinput8/tests/device.c, dlls/user32/rawinput.c, dlls/user32/tests/input.c, dlls/winex11.drv/keyboard.c,
# | dlls/winex11.drv/mouse.c, dlls/winex11.drv/x11drv.h, server/queue.c
# |
if test "$enable_user32_rawinput_keyboard" -eq 1; then
patch_apply user32-rawinput-keyboard/0001-dinput-Add-DIERR_INPUTLOST-error-code-support-for-DI.patch
patch_apply user32-rawinput-keyboard/0002-dinput8-Use-raw-input-interface-for-dinput8-keyboard.patch
patch_apply user32-rawinput-keyboard/0003-user32-Add-support-for-RIDEV_INPUTSINK-flag-in-Regis.patch
patch_apply user32-rawinput-keyboard/0004-winex11.drv-Listen-to-RawKey-events-in-the-desktop-t.patch
(
printf '%s\n' '+ { "Rémi Bernon", "dinput: Add DIERR_INPUTLOST error code support for DISCL_FOREGROUND cooperative level.", 1 },';
printf '%s\n' '+ { "Rémi Bernon", "dinput8: Use raw input interface for dinput8 keyboard device.", 1 },';
printf '%s\n' '+ { "Rémi Bernon", "user32: Add support for RIDEV_INPUTSINK flag in RegisterRawInputDevices.", 1 },';
printf '%s\n' '+ { "Rémi Bernon", "winex11.drv: Listen to RawKey* events in the desktop thread.", 1 },';
) >> "$patchlist"
fi
# Patchset user32-rawinput-mouse-experimental
# |
# | This patchset has the following (direct or indirect) dependencies:
# | * winex11.drv-mouse-coorrds, user32-rawinput-mouse, user32-rawinput-nolegacy
# |
# | This patchset fixes the following Wine bugs:
# | * [#45882] - Raw Input should use untransformed mouse values (affects Overwatch, several Source games).
# |
# | Modified files:
# | * dlls/user32/message.c, dlls/winex11.drv/mouse.c, dlls/winex11.drv/x11drv.h, dlls/winex11.drv/x11drv_main.c,
# | server/queue.c
# |
if test "$enable_user32_rawinput_mouse_experimental" -eq 1; then
patch_apply user32-rawinput-mouse-experimental/0001-winex11.drv-Add-support-for-absolute-RawMotion-event.patch
patch_apply user32-rawinput-mouse-experimental/0002-winex11.drv-Send-relative-RawMotion-events-unprocess.patch
patch_apply user32-rawinput-mouse-experimental/0003-winex11.drv-Implement-relative-wheel-input-from-RawM.patch
patch_apply user32-rawinput-mouse-experimental/0004-winex11.drv-Accumulate-mouse-movement-to-avoid-round.patch
(
printf '%s\n' '+ { "Derek Lesho", "winex11.drv: Add support for absolute RawMotion events.", 1 },';
printf '%s\n' '+ { "Rémi Bernon", "winex11.drv: Send relative RawMotion events unprocessed.", 1 },';
printf '%s\n' '+ { "Derek Lesho", "winex11.drv: Implement relative wheel input from RawMotion events.", 1 },';
printf '%s\n' '+ { "Jordan Galby", "winex11.drv: Accumulate mouse movement to avoid rounding losses.", 1 },';
) >> "$patchlist"
fi
# Patchset user32-recursive-activation
# |
# | This patchset fixes the following Wine bugs:
@ -7304,21 +7511,6 @@ if test "$enable_winex11_drv_Query_server_position" -eq 1; then
) >> "$patchlist"
fi
# Patchset winex11.drv-mouse-coorrds
# |
# | This patchset fixes the following Wine bugs:
# | * [#46309] winex11.drv: Use root-relative coordinates for events, if possible.
# |
# | Modified files:
# | * dlls/winex11.drv/mouse.c
# |
if test "$enable_winex11_drv_mouse_coorrds" -eq 1; then
patch_apply winex11.drv-mouse-coorrds/0001-winex11.drv-mouse-Use-root-relative-coordinates-for-ev.patch
(
printf '%s\n' '+ { "Gabriel Ivăncescu", "winex11.drv/mouse: Use root-relative coordinates for events, if possible.", 1 },';
) >> "$patchlist"
fi
# Patchset wininet-Cleanup
# |
# | Modified files:

View File

@ -0,0 +1,53 @@
From 694ff514bfce59c2590668e3e812d501b713acdb Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
Date: Thu, 12 Sep 2019 14:14:08 +0200
Subject: [PATCH 1/5] server: Add process argument to find_rawinput_device.
We need to be able to iterate all registered rawinput devices for
foreign processes, not only the current one.
---
server/queue.c | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/server/queue.c b/server/queue.c
index f5dc06100d1..3ed7e82a906 100644
--- a/server/queue.c
+++ b/server/queue.c
@@ -1576,11 +1576,11 @@ static user_handle_t find_hardware_message_window( struct desktop *desktop, stru
return win;
}
-static struct rawinput_device_entry *find_rawinput_device( unsigned short usage_page, unsigned short usage )
+static struct rawinput_device_entry *find_rawinput_device( struct process *process, unsigned short usage_page, unsigned short usage )
{
struct rawinput_device_entry *e;
- LIST_FOR_EACH_ENTRY( e, &current->process->rawinput_devices, struct rawinput_device_entry, entry )
+ LIST_FOR_EACH_ENTRY( e, &process->rawinput_devices, struct rawinput_device_entry, entry )
{
if (e->device.usage_page != usage_page || e->device.usage != usage) continue;
return e;
@@ -1593,7 +1593,7 @@ static void update_rawinput_device(const struct rawinput_device *device)
{
struct rawinput_device_entry *e;
- if (!(e = find_rawinput_device( device->usage_page, device->usage )))
+ if (!(e = find_rawinput_device( current->process, device->usage_page, device->usage )))
{
if (!(e = mem_alloc( sizeof(*e) ))) return;
list_add_tail( &current->process->rawinput_devices, &e->entry );
@@ -3375,9 +3375,9 @@ DECL_HANDLER(update_rawinput_devices)
update_rawinput_device(&devices[i]);
}
- e = find_rawinput_device( 1, 2 );
+ e = find_rawinput_device( current->process, 1, 2 );
current->process->rawinput_mouse = e ? &e->device : NULL;
- e = find_rawinput_device( 1, 6 );
+ e = find_rawinput_device( current->process, 1, 6 );
current->process->rawinput_kbd = e ? &e->device : NULL;
}
--
2.24.1

View File

@ -0,0 +1,150 @@
From 56609fdaab139ec8718cf0c4963e6990c9b88003 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
Date: Thu, 19 Sep 2019 09:20:44 +0200
Subject: [PATCH 2/5] server: Allow extra data for hardware_msg_data message.
The RIM_TYPEHID messages will have to carry the variable length HID
report.
---
server/queue.c | 43 +++++++++++++++++++++++++++----------------
1 file changed, 27 insertions(+), 16 deletions(-)
diff --git a/server/queue.c b/server/queue.c
index 3ed7e82a906..feff00e2b9f 100644
--- a/server/queue.c
+++ b/server/queue.c
@@ -398,13 +398,13 @@ static int assign_thread_input( struct thread *thread, struct thread_input *new_
/* allocate a hardware message and its data */
static struct message *alloc_hardware_message( lparam_t info, struct hw_msg_source source,
- unsigned int time )
+ unsigned int time, data_size_t extra_len )
{
struct hardware_msg_data *msg_data;
struct message *msg;
if (!(msg = mem_alloc( sizeof(*msg) ))) return NULL;
- if (!(msg_data = mem_alloc( sizeof(*msg_data) )))
+ if (!(msg_data = mem_alloc( sizeof(*msg_data) + extra_len )))
{
free( msg );
return NULL;
@@ -413,9 +413,9 @@ static struct message *alloc_hardware_message( lparam_t info, struct hw_msg_sour
msg->type = MSG_HARDWARE;
msg->time = time;
msg->data = msg_data;
- msg->data_size = sizeof(*msg_data);
+ msg->data_size = sizeof(*msg_data) + extra_len;
- memset( msg_data, 0, sizeof(*msg_data) );
+ memset( msg_data, 0, sizeof(*msg_data) + extra_len );
msg_data->info = info;
msg_data->source = source;
return msg;
@@ -430,7 +430,7 @@ static void set_cursor_pos( struct desktop *desktop, int x, int y )
if (current->process->rawinput_mouse &&
current->process->rawinput_mouse->flags & RIDEV_NOLEGACY) return;
- if (!(msg = alloc_hardware_message( 0, source, get_tick_count() ))) return;
+ if (!(msg = alloc_hardware_message( 0, source, get_tick_count(), 0 ))) return;
msg->msg = WM_MOUSEMOVE;
msg->x = x;
@@ -1743,6 +1743,8 @@ struct rawinput_message
struct hw_msg_source source;
unsigned int time;
struct hardware_msg_data data;
+ const void *extra;
+ data_size_t extra_len;
};
static int queue_rawinput_message( struct process* process, void* user )
@@ -1752,6 +1754,7 @@ static int queue_rawinput_message( struct process* process, void* user )
struct desktop *desktop = NULL;
struct thread *thread = NULL, *foreground = NULL;
struct message *msg;
+ struct hardware_msg_data *msg_data;
if (raw_msg->data.rawinput.type == RIM_TYPEMOUSE)
device = process->rawinput_mouse;
@@ -1774,14 +1777,18 @@ static int queue_rawinput_message( struct process* process, void* user )
thread->process != foreground->process)
goto done;
- if (!(msg = alloc_hardware_message( raw_msg->data.info, raw_msg->source, raw_msg->time )))
+ if (!(msg = alloc_hardware_message( raw_msg->data.info, raw_msg->source, raw_msg->time, raw_msg->extra_len )))
goto done;
+ msg_data = msg->data;
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) );
+
+ memcpy( msg_data, &raw_msg->data, sizeof(*msg_data) );
+ if (raw_msg->extra_len && raw_msg->extra)
+ memcpy( msg_data + 1, raw_msg->extra, raw_msg->extra_len );
queue_hardware_message( desktop, msg, 0 );
@@ -1850,9 +1857,11 @@ static int queue_mouse_message( struct desktop *desktop, user_handle_t win, cons
if (req_flags & SEND_HWMSG_RAWINPUT)
{
- raw_msg.desktop = desktop;
- raw_msg.source = source;
- raw_msg.time = time;
+ raw_msg.desktop = desktop;
+ raw_msg.source = source;
+ raw_msg.time = time;
+ raw_msg.extra = NULL;
+ raw_msg.extra_len = 0;
msg_data = &raw_msg.data;
msg_data->info = input->mouse.info;
@@ -1879,7 +1888,7 @@ static int queue_mouse_message( struct desktop *desktop, user_handle_t win, cons
if (!(flags & (1 << i))) continue;
flags &= ~(1 << i);
- if (!(msg = alloc_hardware_message( input->mouse.info, source, time ))) return 0;
+ if (!(msg = alloc_hardware_message( input->mouse.info, source, time, 0 ))) return 0;
msg_data = msg->data;
msg->win = get_user_full_handle( win );
@@ -1983,9 +1992,11 @@ static int queue_keyboard_message( struct desktop *desktop, user_handle_t win, c
if (req_flags & SEND_HWMSG_RAWINPUT)
{
- raw_msg.desktop = desktop;
- raw_msg.source = source;
- raw_msg.time = time;
+ raw_msg.desktop = desktop;
+ raw_msg.source = source;
+ raw_msg.time = time;
+ raw_msg.extra = NULL;
+ raw_msg.extra_len = 0;
msg_data = &raw_msg.data;
msg_data->info = input->kbd.info;
@@ -2006,7 +2017,7 @@ static int queue_keyboard_message( struct desktop *desktop, user_handle_t win, c
if ((device = current->process->rawinput_kbd) && (device->flags & RIDEV_NOLEGACY))
return 0;
- if (!(msg = alloc_hardware_message( input->kbd.info, source, time ))) return 0;
+ if (!(msg = alloc_hardware_message( input->kbd.info, source, time, 0 ))) return 0;
msg_data = msg->data;
msg->win = get_user_full_handle( win );
@@ -2044,7 +2055,7 @@ static void queue_custom_hardware_message( struct desktop *desktop, user_handle_
struct hw_msg_source source = { IMDT_UNAVAILABLE, origin };
struct message *msg;
- if (!(msg = alloc_hardware_message( 0, source, get_tick_count() ))) return;
+ if (!(msg = alloc_hardware_message( 0, source, get_tick_count(), 0 ))) return;
msg->win = get_user_full_handle( win );
msg->msg = input->hw.msg;
--
2.24.1

View File

@ -0,0 +1,262 @@
From d0347613c7149144d4339109b641901537c4c326 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
Date: Mon, 11 Nov 2019 18:35:18 +0100
Subject: [PATCH 3/5] server: Add HID input message type to
send_hardware_message request.
---
dlls/user32/message.c | 4 +++-
server/protocol.def | 26 +++++++++++++++++++---
server/queue.c | 50 ++++++++++++++++++++++++++++++++++++++-----
server/trace.c | 10 ++++++---
4 files changed, 78 insertions(+), 12 deletions(-)
diff --git a/dlls/user32/message.c b/dlls/user32/message.c
index cc25d2f6c2f..55bbe409c9e 100644
--- a/dlls/user32/message.c
+++ b/dlls/user32/message.c
@@ -3354,10 +3354,10 @@ NTSTATUS send_hardware_message( HWND hwnd, const INPUT *input, UINT flags )
{
req->win = wine_server_user_handle( hwnd );
req->flags = flags;
- req->input.type = input->type;
switch (input->type)
{
case INPUT_MOUSE:
+ req->input.type = HW_INPUT_MOUSE;
req->input.mouse.x = input->u.mi.dx;
req->input.mouse.y = input->u.mi.dy;
req->input.mouse.data = input->u.mi.mouseData;
@@ -3366,6 +3366,7 @@ NTSTATUS send_hardware_message( HWND hwnd, const INPUT *input, UINT flags )
req->input.mouse.info = input->u.mi.dwExtraInfo;
break;
case INPUT_KEYBOARD:
+ req->input.type = HW_INPUT_KEYBOARD;
req->input.kbd.vkey = input->u.ki.wVk;
req->input.kbd.scan = input->u.ki.wScan;
req->input.kbd.flags = input->u.ki.dwFlags;
@@ -3373,6 +3374,7 @@ NTSTATUS send_hardware_message( HWND hwnd, const INPUT *input, UINT flags )
req->input.kbd.info = input->u.ki.dwExtraInfo;
break;
case INPUT_HARDWARE:
+ req->input.type = HW_INPUT_HARDWARE;
req->input.hw.msg = input->u.hi.uMsg;
req->input.hw.lparam = MAKELONG( input->u.hi.wParamL, input->u.hi.wParamH );
break;
diff --git a/server/protocol.def b/server/protocol.def
index d37dceba40c..85cc2ac6937 100644
--- a/server/protocol.def
+++ b/server/protocol.def
@@ -321,6 +321,13 @@ struct hardware_msg_data
int y; /* y coordinate */
unsigned int data; /* mouse data */
} mouse;
+ struct
+ {
+ int type; /* RIM_TYPEHID */
+ obj_handle_t device;
+ unsigned int length; /* HID report length */
+ /* followed by length bytes of HID report data */
+ } hid;
} rawinput;
};
@@ -344,7 +351,7 @@ typedef union
int type;
struct
{
- int type; /* INPUT_KEYBOARD */
+ int type; /* HW_INPUT_KEYBOARD */
unsigned short vkey; /* virtual key code */
unsigned short scan; /* scan code */
unsigned int flags; /* event flags */
@@ -353,7 +360,7 @@ typedef union
} kbd;
struct
{
- int type; /* INPUT_MOUSE */
+ int type; /* HW_INPUT_MOUSE */
int x; /* coordinates */
int y;
unsigned int data; /* mouse data */
@@ -363,11 +370,23 @@ typedef union
} mouse;
struct
{
- int type; /* INPUT_HARDWARE */
+ int type; /* HW_INPUT_HARDWARE */
unsigned int msg; /* message code */
lparam_t lparam; /* message param */
} hw;
+ struct
+ {
+ int type; /* HW_INPUT_HID */
+ obj_handle_t device;
+ unsigned char usage_page;
+ unsigned char usage;
+ unsigned int length;
+ } hid;
} hw_input_t;
+#define HW_INPUT_MOUSE 0
+#define HW_INPUT_KEYBOARD 1
+#define HW_INPUT_HARDWARE 2
+#define HW_INPUT_HID 3
typedef union
{
@@ -2361,6 +2380,7 @@ enum message_type
user_handle_t win; /* window handle */
hw_input_t input; /* input data */
unsigned int flags; /* flags (see below) */
+ VARARG(data,bytes); /* hid report data */
@REPLY
int wait; /* do we need to wait for a reply? */
int prev_x; /* previous cursor position */
diff --git a/server/queue.c b/server/queue.c
index feff00e2b9f..85aa896c7bd 100644
--- a/server/queue.c
+++ b/server/queue.c
@@ -1698,7 +1698,7 @@ static int send_hook_ll_message( struct desktop *desktop, struct message *hardwa
struct msg_queue *queue;
struct message *msg;
timeout_t timeout = 2000 * -10000; /* FIXME: load from registry */
- int id = (input->type == INPUT_MOUSE) ? WH_MOUSE_LL : WH_KEYBOARD_LL;
+ int id = (input->type == HW_INPUT_MOUSE) ? WH_MOUSE_LL : WH_KEYBOARD_LL;
if (!(hook_thread = get_first_global_hook( id ))) return 0;
if (!(queue = hook_thread->queue)) return 0;
@@ -1716,7 +1716,7 @@ static int send_hook_ll_message( struct desktop *desktop, struct message *hardwa
msg->data_size = hardware_msg->data_size;
msg->result = NULL;
- if (input->type == INPUT_KEYBOARD)
+ if (input->type == HW_INPUT_KEYBOARD)
{
unsigned short vkey = input->kbd.vkey;
if (input->kbd.flags & KEYEVENTF_UNICODE) vkey = VK_PACKET;
@@ -1742,6 +1742,8 @@ struct rawinput_message
struct desktop *desktop;
struct hw_msg_source source;
unsigned int time;
+ unsigned char usage_page;
+ unsigned char usage;
struct hardware_msg_data data;
const void *extra;
data_size_t extra_len;
@@ -1750,6 +1752,7 @@ struct rawinput_message
static int queue_rawinput_message( struct process* process, void* user )
{
const struct rawinput_message* raw_msg = user;
+ const struct rawinput_device_entry *entry;
const struct rawinput_device *device = NULL;
struct desktop *desktop = NULL;
struct thread *thread = NULL, *foreground = NULL;
@@ -1760,6 +1763,8 @@ static int queue_rawinput_message( struct process* process, void* user )
device = process->rawinput_mouse;
else if (raw_msg->data.rawinput.type == RIM_TYPEKEYBOARD)
device = process->rawinput_kbd;
+ else if ((entry = find_rawinput_device( process, raw_msg->usage_page, raw_msg->usage )))
+ device = &entry->device;
if (!device)
goto done;
@@ -2067,6 +2072,38 @@ static void queue_custom_hardware_message( struct desktop *desktop, user_handle_
queue_hardware_message( desktop, msg, 1 );
}
+/* queue a hardware message for an hid event */
+static void queue_hid_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 void *report, data_size_t report_len )
+{
+ struct hw_msg_source source = { IMDT_UNAVAILABLE, origin };
+ struct hardware_msg_data *msg_data;
+ struct rawinput_message raw_msg;
+
+ if (!(req_flags & SEND_HWMSG_RAWINPUT))
+ return;
+
+ raw_msg.desktop = NULL; /* send to all desktops */
+ raw_msg.source = source;
+ raw_msg.time = get_tick_count();
+ raw_msg.usage_page = input->hid.usage_page;
+ raw_msg.usage = input->hid.usage;
+ raw_msg.extra = report;
+ raw_msg.extra_len = report_len;
+
+ msg_data = &raw_msg.data;
+ msg_data->flags = 0;
+ msg_data->rawinput.type = RIM_TYPEHID;
+ msg_data->rawinput.hid.device = input->hid.device;
+ msg_data->rawinput.hid.length = report_len;
+
+ if (req_flags == SEND_HWMSG_RAWINPUT)
+ enum_processes( queue_rawinput_message, &raw_msg );
+ else
+ queue_rawinput_message( current->process, &raw_msg );
+}
+
/* check message filter for a hardware message */
static int check_hw_message_filter( user_handle_t win, unsigned int msg_code,
user_handle_t filter_win, unsigned int first, unsigned int last )
@@ -2577,15 +2614,18 @@ DECL_HANDLER(send_hardware_message)
switch (req->input.type)
{
- case INPUT_MOUSE:
+ case HW_INPUT_MOUSE:
reply->wait = queue_mouse_message( desktop, req->win, &req->input, origin, sender, req->flags );
break;
- case INPUT_KEYBOARD:
+ case HW_INPUT_KEYBOARD:
reply->wait = queue_keyboard_message( desktop, req->win, &req->input, origin, sender, req->flags );
break;
- case INPUT_HARDWARE:
+ case HW_INPUT_HARDWARE:
queue_custom_hardware_message( desktop, req->win, origin, &req->input );
break;
+ case HW_INPUT_HID:
+ queue_hid_message( desktop, req->win, &req->input, origin, sender, req->flags, get_req_data(), get_req_data_size() );
+ break;
default:
set_error( STATUS_INVALID_PARAMETER );
}
diff --git a/server/trace.c b/server/trace.c
index 18b56c729e4..c39c56087c1 100644
--- a/server/trace.c
+++ b/server/trace.c
@@ -381,24 +381,28 @@ static void dump_hw_input( const char *prefix, const hw_input_t *input )
{
switch (input->type)
{
- case INPUT_MOUSE:
+ case HW_INPUT_MOUSE:
fprintf( stderr, "%s{type=MOUSE,x=%d,y=%d,data=%08x,flags=%08x,time=%u",
prefix, input->mouse.x, input->mouse.y, input->mouse.data, input->mouse.flags,
input->mouse.time );
dump_uint64( ",info=", &input->mouse.info );
fputc( '}', stderr );
break;
- case INPUT_KEYBOARD:
+ case HW_INPUT_KEYBOARD:
fprintf( stderr, "%s{type=KEYBOARD,vkey=%04hx,scan=%04hx,flags=%08x,time=%u",
prefix, input->kbd.vkey, input->kbd.scan, input->kbd.flags, input->kbd.time );
dump_uint64( ",info=", &input->kbd.info );
fputc( '}', stderr );
break;
- case INPUT_HARDWARE:
+ case HW_INPUT_HARDWARE:
fprintf( stderr, "%s{type=HARDWARE,msg=%04x", prefix, input->hw.msg );
dump_uint64( ",lparam=", &input->hw.lparam );
fputc( '}', stderr );
break;
+ case HW_INPUT_HID:
+ fprintf( stderr, "%s{type=HID,device=%04x,usage_page=%02x,usage=%02x,length=%04x}",
+ prefix, input->hid.device, input->hid.usage_page, input->hid.usage, input->hid.length );
+ break;
default:
fprintf( stderr, "%s{type=%04x}", prefix, input->type );
break;
--
2.24.1

View File

@ -0,0 +1,138 @@
From bbb38b3c009d47aced1ba746549fdc51e34cbaf4 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
Date: Thu, 12 Sep 2019 14:48:23 +0200
Subject: [PATCH 4/5] user32: Implement WM_INPUT/RIM_TYPEHID message handling.
---
dlls/user32/message.c | 19 ++++++++++++++++++-
dlls/user32/rawinput.c | 37 +++++++++++++++++++++++++++++++++++++
dlls/user32/user_private.h | 2 ++
3 files changed, 57 insertions(+), 1 deletion(-)
diff --git a/dlls/user32/message.c b/dlls/user32/message.c
index 55bbe409c9e..ae081cd6eb1 100644
--- a/dlls/user32/message.c
+++ b/dlls/user32/message.c
@@ -2285,10 +2285,17 @@ static BOOL process_rawinput_message( MSG *msg, const struct hardware_msg_data *
{
struct user_thread_info *thread_info = get_user_thread_info();
RAWINPUT *rawinput = thread_info->rawinput;
+ SIZE_T data_len = 0;
+
+ if (msg_data->rawinput.type == RIM_TYPEHID)
+ {
+ data_len = msg_data->rawinput.hid.length;
+ rawinput = thread_info->rawinput = HeapReAlloc( GetProcessHeap(), 0, rawinput, sizeof(*rawinput) + data_len );
+ }
if (!rawinput)
{
- thread_info->rawinput = HeapAlloc( GetProcessHeap(), 0, sizeof(*rawinput) );
+ thread_info->rawinput = HeapAlloc( GetProcessHeap(), 0, sizeof(*rawinput) + data_len );
if (!(rawinput = thread_info->rawinput)) return FALSE;
}
@@ -2383,6 +2390,16 @@ static BOOL process_rawinput_message( MSG *msg, const struct hardware_msg_data *
rawinput->data.keyboard.Message = msg_data->rawinput.kbd.message;
rawinput->data.keyboard.ExtraInformation = msg_data->info;
}
+ else if (msg_data->rawinput.type == RIM_TYPEHID)
+ {
+ rawinput->header.dwSize = FIELD_OFFSET(RAWINPUT, data.hid.bRawData) + data_len;
+ rawinput->header.hDevice = rawinput_handle_from_device_handle(wine_server_ptr_handle(msg_data->rawinput.hid.device));
+ rawinput->header.wParam = 0;
+
+ rawinput->data.hid.dwSizeHid = data_len;
+ rawinput->data.hid.dwCount = 1;
+ memcpy(rawinput->data.hid.bRawData, msg_data + 1, data_len);
+ }
else
{
FIXME("Unhandled rawinput type %#x.\n", msg_data->rawinput.type);
diff --git a/dlls/user32/rawinput.c b/dlls/user32/rawinput.c
index 8cf9f8ebf62..72ae91cfcb5 100644
--- a/dlls/user32/rawinput.c
+++ b/dlls/user32/rawinput.c
@@ -43,6 +43,7 @@ struct hid_device
{
WCHAR *path;
HANDLE file;
+ HANDLE handle;
RID_DEVICE_INFO_HID info;
PHIDP_PREPARSED_DATA data;
};
@@ -59,6 +60,8 @@ static CRITICAL_SECTION_DEBUG hid_devices_cs_debug =
};
static CRITICAL_SECTION hid_devices_cs = { &hid_devices_cs_debug, -1, 0, 0, 0, 0 };
+extern DWORD WINAPI GetFinalPathNameByHandleW(HANDLE file, LPWSTR path, DWORD charcount, DWORD flags);
+
static BOOL array_reserve(void **elements, unsigned int *capacity, unsigned int count, unsigned int size)
{
unsigned int new_capacity, max_capacity;
@@ -138,10 +141,43 @@ static struct hid_device *add_device(HDEVINFO set, SP_DEVICE_INTERFACE_DATA *ifa
device = &hid_devices[hid_devices_count++];
device->path = path;
device->file = file;
+ device->handle = INVALID_HANDLE_VALUE;
return device;
}
+HANDLE rawinput_handle_from_device_handle(HANDLE device)
+{
+ WCHAR buffer[sizeof(OBJECT_NAME_INFORMATION) + MAX_PATH + 1];
+ OBJECT_NAME_INFORMATION *info = (OBJECT_NAME_INFORMATION*)&buffer;
+ ULONG dummy;
+ unsigned int i;
+
+ for (i = 0; i < hid_devices_count; ++i)
+ {
+ if (hid_devices[i].handle == device)
+ return &hid_devices[i];
+ }
+
+ if (NtQueryObject( device, ObjectNameInformation, &buffer, sizeof(buffer) - sizeof(WCHAR), &dummy ) || !info->Name.Buffer)
+ return NULL;
+
+ /* replace \??\ with \\?\ to match hid_devices paths */
+ if (info->Name.Length > 1 && info->Name.Buffer[0] == '\\' && info->Name.Buffer[1] == '?')
+ info->Name.Buffer[1] = '\\';
+
+ for (i = 0; i < hid_devices_count; ++i)
+ {
+ if (strcmpW(hid_devices[i].path, info->Name.Buffer) == 0)
+ {
+ hid_devices[i].handle = device;
+ return &hid_devices[i];
+ }
+ }
+
+ return NULL;
+}
+
static void find_hid_devices(void)
{
static ULONGLONG last_check;
@@ -415,6 +451,7 @@ UINT WINAPI GetRawInputDeviceInfoW(HANDLE device, UINT command, void *data, UINT
device, command, data, data_size);
if (!data_size) return ~0U;
+ if (!device) return ~0U;
/* each case below must set:
* *data_size: length (meaning defined by command) of data we want to copy
diff --git a/dlls/user32/user_private.h b/dlls/user32/user_private.h
index e8f6abb6813..0c3d52fca5b 100644
--- a/dlls/user32/user_private.h
+++ b/dlls/user32/user_private.h
@@ -378,4 +378,6 @@ static inline WCHAR *heap_strdupW(const WCHAR *src)
return dst;
}
+extern HANDLE rawinput_handle_from_device_handle(HANDLE device);
+
#endif /* __WINE_USER_PRIVATE_H */
--
2.24.1

View File

@ -0,0 +1,139 @@
From 249548cff4ae17da6731e28a5fafe277a7b3d6ea Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
Date: Wed, 18 Sep 2019 21:04:25 +0200
Subject: [PATCH 5/5] hidclass.sys: Send input message to server when HID
report is received.
---
dlls/hidclass.sys/device.c | 30 ++++++++++++++++++++++++++++++
dlls/hidclass.sys/hid.h | 1 +
dlls/hidclass.sys/pnp.c | 16 ++++++++++++++++
3 files changed, 47 insertions(+)
diff --git a/dlls/hidclass.sys/device.c b/dlls/hidclass.sys/device.c
index 0e905c8322f..369d847e3c1 100644
--- a/dlls/hidclass.sys/device.c
+++ b/dlls/hidclass.sys/device.c
@@ -26,9 +26,11 @@
#include "winuser.h"
#include "setupapi.h"
+#include "wine/server.h"
#include "wine/debug.h"
#include "ddk/hidsdi.h"
#include "ddk/hidtypes.h"
+#include "ddk/ntifs.h"
#include "ddk/wdm.h"
#include "initguid.h"
@@ -123,6 +125,8 @@ NTSTATUS HID_LinkDevice(DEVICE_OBJECT *device)
return status;
}
+ ext->link_handle = INVALID_HANDLE_VALUE;
+
/* FIXME: This should probably be done in mouhid.sys. */
if (ext->preparseData->caps.UsagePage == HID_USAGE_PAGE_GENERIC
&& ext->preparseData->caps.Usage == HID_USAGE_GENERIC_MOUSE)
@@ -207,6 +211,8 @@ void HID_DeleteDevice(DEVICE_OBJECT *device)
IoCompleteRequest(irp, IO_NO_INCREMENT);
}
+ CloseHandle(ext->link_handle);
+
TRACE("Delete device(%p) %s\n", device, debugstr_w(ext->device_name));
HeapFree(GetProcessHeap(), 0, ext->device_name);
RtlFreeUnicodeString(&ext->link_name);
@@ -241,6 +247,28 @@ static NTSTATUS copy_packet_into_buffer(HID_XFER_PACKET *packet, BYTE* buffer, U
return STATUS_BUFFER_OVERFLOW;
}
+static void HID_Device_sendRawInput(DEVICE_OBJECT *device, HID_XFER_PACKET *packet)
+{
+ BASE_DEVICE_EXTENSION *ext = device->DeviceExtension;
+
+ if (ext->link_handle == INVALID_HANDLE_VALUE)
+ return;
+
+ SERVER_START_REQ(send_hardware_message)
+ {
+ req->win = 0;
+ req->flags = SEND_HWMSG_RAWINPUT;
+ req->input.type = HW_INPUT_HID;
+ req->input.hid.device = wine_server_obj_handle(ext->link_handle);
+ req->input.hid.usage_page = ext->preparseData->caps.UsagePage;
+ req->input.hid.usage = ext->preparseData->caps.Usage;
+ req->input.hid.length = packet->reportBufferLen;
+ wine_server_add_data(req, packet->reportBuffer, packet->reportBufferLen);
+ wine_server_call(req);
+ }
+ SERVER_END_REQ;
+}
+
static void HID_Device_processQueue(DEVICE_OBJECT *device)
{
IRP *irp;
@@ -324,6 +352,7 @@ static DWORD CALLBACK hid_device_thread(void *args)
if (irp->IoStatus.u.Status == STATUS_SUCCESS)
{
RingBuffer_Write(ext->ring_buffer, packet);
+ HID_Device_sendRawInput(device, packet);
HID_Device_processQueue(device);
}
@@ -370,6 +399,7 @@ static DWORD CALLBACK hid_device_thread(void *args)
else
packet->reportId = 0;
RingBuffer_Write(ext->ring_buffer, packet);
+ HID_Device_sendRawInput(device, packet);
HID_Device_processQueue(device);
}
diff --git a/dlls/hidclass.sys/hid.h b/dlls/hidclass.sys/hid.h
index 36d13c009d7..f12e04d7898 100644
--- a/dlls/hidclass.sys/hid.h
+++ b/dlls/hidclass.sys/hid.h
@@ -46,6 +46,7 @@ typedef struct _BASE_DEVICE_EXTENSION {
ULONG poll_interval;
WCHAR *device_name;
UNICODE_STRING link_name;
+ HANDLE link_handle;
WCHAR device_id[MAX_DEVICE_ID_LEN];
WCHAR instance_id[MAX_DEVICE_ID_LEN];
struct ReportRingBuffer *ring_buffer;
diff --git a/dlls/hidclass.sys/pnp.c b/dlls/hidclass.sys/pnp.c
index 1c130e8dd80..b84a358dba4 100644
--- a/dlls/hidclass.sys/pnp.c
+++ b/dlls/hidclass.sys/pnp.c
@@ -299,12 +299,28 @@ NTSTATUS WINAPI HID_PNP_Dispatch(DEVICE_OBJECT *device, IRP *irp)
case IRP_MN_START_DEVICE:
{
BASE_DEVICE_EXTENSION *ext = device->DeviceExtension;
+ OBJECT_ATTRIBUTES attr;
rc = minidriver->PNPDispatch(device, irp);
IoSetDeviceInterfaceState(&ext->link_name, TRUE);
if (ext->is_mouse)
IoSetDeviceInterfaceState(&ext->mouse_link_name, TRUE);
+
+ attr.Length = sizeof(attr);
+ attr.RootDirectory = 0;
+ attr.Attributes = OBJ_CASE_INSENSITIVE;
+ attr.ObjectName = &ext->link_name;
+ attr.SecurityDescriptor = NULL;
+ attr.SecurityQualityOfService = NULL;
+ NtOpenSymbolicLinkObject(&ext->link_handle, SYMBOLIC_LINK_QUERY, &attr);
+ ext->link_handle = ConvertToGlobalHandle(ext->link_handle);
+
+ if (ext->link_handle == INVALID_HANDLE_VALUE)
+ ERR("Failed to open link %s, error %u.\n", debugstr_w(ext->link_name.Buffer), GetLastError());
+ else
+ TRACE("Opened link handle: %p for %s\n", ext->link_handle, debugstr_w(ext->link_name.Buffer));
+
return rc;
}
case IRP_MN_REMOVE_DEVICE:
--
2.24.1

View File

@ -0,0 +1 @@
Depends: user32-rawinput-nolegacy

View File

@ -0,0 +1,82 @@
From 3f8031f89ca79ef5c4dd46666cda2304aa647083 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
Date: Mon, 4 Nov 2019 23:33:09 +0100
Subject: [PATCH 1/4] dinput: Add DIERR_INPUTLOST error code support for
DISCL_FOREGROUND cooperative level.
---
dlls/dinput/device.c | 2 ++
dlls/dinput/device_private.h | 1 +
dlls/dinput/keyboard.c | 6 ++++++
dlls/dinput/mouse.c | 6 ++++++
4 files changed, 15 insertions(+)
diff --git a/dlls/dinput/device.c b/dlls/dinput/device.c
index df7a22a303b..51a536f0892 100644
--- a/dlls/dinput/device.c
+++ b/dlls/dinput/device.c
@@ -1087,6 +1087,7 @@ HRESULT WINAPI IDirectInputDevice2WImpl_Acquire(LPDIRECTINPUTDEVICE8W iface)
EnterCriticalSection(&This->crit);
res = This->acquired ? S_FALSE : DI_OK;
This->acquired = 1;
+ This->inputlost = 0;
LeaveCriticalSection(&This->crit);
if (res == DI_OK)
check_dinput_hooks(iface, TRUE);
@@ -1115,6 +1116,7 @@ HRESULT WINAPI IDirectInputDevice2WImpl_Unacquire(LPDIRECTINPUTDEVICE8W iface)
EnterCriticalSection(&This->crit);
res = !This->acquired ? DI_NOEFFECT : DI_OK;
This->acquired = 0;
+ This->inputlost = 0;
LeaveCriticalSection(&This->crit);
if (res == DI_OK)
check_dinput_hooks(iface, FALSE);
diff --git a/dlls/dinput/device_private.h b/dlls/dinput/device_private.h
index 9116aaeab66..70b4ae1ef69 100644
--- a/dlls/dinput/device_private.h
+++ b/dlls/dinput/device_private.h
@@ -68,6 +68,7 @@ struct IDirectInputDeviceImpl
DWORD dwCoopLevel;
HWND win;
int acquired;
+ int inputlost;
DI_EVENT_PROC event_proc; /* function to receive mouse & keyboard events */
BOOL use_raw_input; /* use raw input instead of low-level messages */
diff --git a/dlls/dinput/keyboard.c b/dlls/dinput/keyboard.c
index 1ec8003897a..2c62d3eab09 100644
--- a/dlls/dinput/keyboard.c
+++ b/dlls/dinput/keyboard.c
@@ -371,6 +371,12 @@ static HRESULT WINAPI SysKeyboardWImpl_GetDeviceState(LPDIRECTINPUTDEVICE8W ifac
check_dinput_events();
+ if ((This->base.dwCoopLevel & DISCL_FOREGROUND) && This->base.win != GetForegroundWindow())
+ {
+ This->base.acquired = 0;
+ return DIERR_INPUTLOST;
+ }
+
EnterCriticalSection(&This->base.crit);
if (TRACE_ON(dinput)) {
diff --git a/dlls/dinput/mouse.c b/dlls/dinput/mouse.c
index b8b88f38c15..06cf78de13a 100644
--- a/dlls/dinput/mouse.c
+++ b/dlls/dinput/mouse.c
@@ -672,6 +672,12 @@ static HRESULT WINAPI SysMouseWImpl_GetDeviceState(LPDIRECTINPUTDEVICE8W iface,
check_dinput_events();
+ if ((This->base.dwCoopLevel & DISCL_FOREGROUND) && This->base.win != GetForegroundWindow())
+ {
+ This->base.acquired = 0;
+ return DIERR_INPUTLOST;
+ }
+
EnterCriticalSection(&This->base.crit);
_dump_mouse_state(&This->m_state);
--
2.24.1

View File

@ -0,0 +1,146 @@
From 87087e7d92d5cbbaf8e63cdfadead60701d0b360 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
Date: Mon, 26 Aug 2019 15:32:07 +0200
Subject: [PATCH 2/4] dinput8: Use raw input interface for dinput8 keyboard
device.
---
dlls/dinput/keyboard.c | 69 +++++++++++++++++++++++++++++++++----
dlls/dinput8/tests/device.c | 7 ----
2 files changed, 62 insertions(+), 14 deletions(-)
diff --git a/dlls/dinput/keyboard.c b/dlls/dinput/keyboard.c
index 2c62d3eab09..fb0f273bdbe 100644
--- a/dlls/dinput/keyboard.c
+++ b/dlls/dinput/keyboard.c
@@ -107,17 +107,65 @@ static int KeyboardCallback( LPDIRECTINPUTDEVICE8A iface, WPARAM wparam, LPARAM
{
SysKeyboardImpl *This = impl_from_IDirectInputDevice8A(iface);
int dik_code, ret = This->base.dwCoopLevel & DISCL_EXCLUSIVE;
- KBDLLHOOKSTRUCT *hook = (KBDLLHOOKSTRUCT *)lparam;
BYTE new_diks;
+ DWORD vkey_code, scan_code;
+ BOOL is_key_ext, is_key_up;
if (wparam != WM_KEYDOWN && wparam != WM_KEYUP &&
- wparam != WM_SYSKEYDOWN && wparam != WM_SYSKEYUP)
+ wparam != WM_SYSKEYDOWN && wparam != WM_SYSKEYUP &&
+ wparam != RIM_INPUT && wparam != RIM_INPUTSINK)
return 0;
+ if (wparam == RIM_INPUT || wparam == RIM_INPUTSINK)
+ {
+ RAWINPUTHEADER raw_header;
+ RAWINPUT raw_input;
+ UINT size;
+
+ 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_TYPEKEYBOARD)
+ return 0;
+
+ if (raw_header.dwSize > sizeof(raw_input))
+ {
+ WARN( "Unexpected size for keyboard 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;
+ }
+
+ vkey_code = raw_input.data.keyboard.VKey;
+ scan_code = raw_input.data.keyboard.MakeCode;
+ is_key_ext = (raw_input.data.keyboard.Flags & RI_KEY_E0);
+ is_key_up = (raw_input.data.keyboard.Flags & RI_KEY_BREAK);
+ }
+ else
+ {
+ KBDLLHOOKSTRUCT *hook = (KBDLLHOOKSTRUCT *)lparam;
+
+ vkey_code = hook->vkCode;
+ scan_code = hook->scanCode;
+ is_key_ext = (hook->flags & LLKHF_EXTENDED);
+ is_key_up = (hook->flags & LLKHF_UP);
+ }
+
TRACE("(%p) wp %08lx, lp %08lx, vk %02x, scan %02x\n",
- iface, wparam, lparam, hook->vkCode, hook->scanCode);
+ iface, wparam, lparam, vkey_code, scan_code);
- switch (hook->vkCode)
+ switch (vkey_code)
{
/* R-Shift is special - it is an extended key with separate scan code */
case VK_RSHIFT : dik_code = DIK_RSHIFT; break;
@@ -125,10 +173,10 @@ static int KeyboardCallback( LPDIRECTINPUTDEVICE8A iface, WPARAM wparam, LPARAM
case VK_NUMLOCK : dik_code = DIK_NUMLOCK; break;
case VK_SUBTRACT: dik_code = DIK_SUBTRACT; break;
default:
- dik_code = map_dik_code(hook->scanCode & 0xff, hook->vkCode, This->subtype);
- if (hook->flags & LLKHF_EXTENDED) dik_code |= 0x80;
+ dik_code = map_dik_code(scan_code & 0xff, vkey_code, This->subtype);
+ if (is_key_ext) dik_code |= 0x80;
}
- new_diks = hook->flags & LLKHF_UP ? 0 : 0x80;
+ new_diks = is_key_up ? 0 : 0x80;
/* returns now if key event already known */
if (new_diks == This->DInputKeyState[dik_code])
@@ -295,6 +343,13 @@ static SysKeyboardImpl *alloc_device(REFGUID rguid, IDirectInputImpl *dinput)
list_add_tail(&dinput->devices_list, &newDevice->base.entry);
LeaveCriticalSection(&dinput->crit);
+ if (dinput->dwVersion >= 0x800)
+ {
+ newDevice->base.use_raw_input = TRUE;
+ newDevice->base.raw_device.usUsagePage = 1; /* HID generic device page */
+ newDevice->base.raw_device.usUsage = 6; /* HID generic keyboard */
+ }
+
return newDevice;
failed:
diff --git a/dlls/dinput8/tests/device.c b/dlls/dinput8/tests/device.c
index 31220db220a..8a6d1997b67 100644
--- a/dlls/dinput8/tests/device.c
+++ b/dlls/dinput8/tests/device.c
@@ -659,15 +659,10 @@ 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 == 6, "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 != NULL, "Unexpected raw device target: %p\n", raw_devices[0].hwndTarget);
hr = IDirectInputDevice8_Unacquire(di_keyboard);
ok(SUCCEEDED(hr), "IDirectInputDevice8_Acquire failed: %08x\n", hr);
@@ -746,9 +741,7 @@ static void test_mouse_keyboard(void)
ok(raw_devices[1].hwndTarget == hwnd, "Unexpected raw device target: %p\n", raw_devices[1].hwndTarget);
ok(raw_devices[2].usUsagePage == 1, "Unexpected raw device usage page: %x\n", raw_devices[1].usUsagePage);
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);
- todo_wine
ok(raw_devices[2].hwndTarget == di_hwnd, "Unexpected raw device target: %p\n", raw_devices[1].hwndTarget);
hr = IDirectInputDevice8_Unacquire(di_keyboard);
ok(SUCCEEDED(hr), "IDirectInputDevice8_Acquire failed: %08x\n", hr);
--
2.24.1

View File

@ -0,0 +1,95 @@
From 31d4d9619c14a37522b99917deae40273f6e3654 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
Date: Sat, 7 Sep 2019 09:41:59 +0200
Subject: [PATCH 3/4] user32: Add support for RIDEV_INPUTSINK flag in
RegisterRawInputDevices.
This flag allows applications to receive rawinput messages while in
background. They have to specify a target hwnd in which queue to receive
them and the messages will carry a RIM_INPUTSINK wparam in this case.
---
dlls/user32/rawinput.c | 9 ++++++++-
dlls/user32/tests/input.c | 2 --
server/queue.c | 9 ++++++---
3 files changed, 14 insertions(+), 6 deletions(-)
diff --git a/dlls/user32/rawinput.c b/dlls/user32/rawinput.c
index 72ae91cfcb5..5a238928b24 100644
--- a/dlls/user32/rawinput.c
+++ b/dlls/user32/rawinput.c
@@ -304,6 +304,13 @@ BOOL WINAPI DECLSPEC_HOTPATCH RegisterRawInputDevices(RAWINPUTDEVICE *devices, U
for (i = 0; i < device_count; ++i)
{
+ if ((devices[i].dwFlags & RIDEV_INPUTSINK) &&
+ (devices[i].hwndTarget == NULL))
+ {
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return FALSE;
+ }
+
if ((devices[i].dwFlags & RIDEV_REMOVE) &&
(devices[i].hwndTarget != NULL))
{
@@ -319,7 +326,7 @@ BOOL WINAPI DECLSPEC_HOTPATCH RegisterRawInputDevices(RAWINPUTDEVICE *devices, U
TRACE("device %u: page %#x, usage %#x, flags %#x, target %p.\n",
i, devices[i].usUsagePage, devices[i].usUsage,
devices[i].dwFlags, devices[i].hwndTarget);
- if (devices[i].dwFlags & ~(RIDEV_REMOVE|RIDEV_NOLEGACY))
+ if (devices[i].dwFlags & ~(RIDEV_REMOVE|RIDEV_NOLEGACY|RIDEV_INPUTSINK))
FIXME("Unhandled flags %#x for device %u.\n", devices[i].dwFlags, i);
d[i].usage_page = devices[i].usUsagePage;
diff --git a/dlls/user32/tests/input.c b/dlls/user32/tests/input.c
index a1f983f1960..68d6731551a 100644
--- a/dlls/user32/tests/input.c
+++ b/dlls/user32/tests/input.c
@@ -1812,9 +1812,7 @@ static void test_RegisterRawInputDevices(void)
SetLastError(0xdeadbeef);
res = RegisterRawInputDevices(raw_devices, ARRAY_SIZE(raw_devices), sizeof(RAWINPUTDEVICE));
- todo_wine
ok(res == FALSE, "RegisterRawInputDevices failed\n");
- todo_wine
ok(GetLastError() == ERROR_INVALID_PARAMETER, "RegisterRawInputDevices returned %08x\n", GetLastError());
raw_devices[0].hwndTarget = hwnd;
diff --git a/server/queue.c b/server/queue.c
index 85aa896c7bd..145b9c110b1 100644
--- a/server/queue.c
+++ b/server/queue.c
@@ -1758,6 +1758,7 @@ static int queue_rawinput_message( struct process* process, void* user )
struct thread *thread = NULL, *foreground = NULL;
struct message *msg;
struct hardware_msg_data *msg_data;
+ int wparam = RIM_INPUT;
if (raw_msg->data.rawinput.type == RIM_TYPEMOUSE)
device = process->rawinput_mouse;
@@ -1777,10 +1778,12 @@ static int queue_rawinput_message( struct process* process, void* user )
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 (!(device->flags & RIDEV_INPUTSINK)) goto done;
+ wparam = RIM_INPUTSINK;
+ }
if (!(msg = alloc_hardware_message( raw_msg->data.info, raw_msg->source, raw_msg->time, raw_msg->extra_len )))
goto done;
@@ -1788,7 +1791,7 @@ static int queue_rawinput_message( struct process* process, void* user )
msg->win = device->target;
msg->msg = WM_INPUT;
- msg->wparam = RIM_INPUT;
+ msg->wparam = wparam;
msg->lparam = 0;
memcpy( msg_data, &raw_msg->data, sizeof(*msg_data) );
--
2.24.1

View File

@ -0,0 +1,119 @@
From 18e2112beb69c8499cdd90b133348ec52502dc6d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
Date: Wed, 21 Aug 2019 16:37:57 +0200
Subject: [PATCH] winex11.drv: Listen to RawKey* events in the desktop thread.
This adds keyboard input support while Wine windows are in background,
so the events can be translated to raw input messages as on Windows,
which are required to keep dinput8 keyboard state up-to-date when
Alt+Tab is used to switch to a non-Wine window.
---
dlls/winex11.drv/keyboard.c | 40 ++++++++++++++++++++++++++++++++++++-
dlls/winex11.drv/mouse.c | 6 ++++++
dlls/winex11.drv/x11drv.h | 1 +
3 files changed, 46 insertions(+), 1 deletion(-)
diff --git a/dlls/winex11.drv/keyboard.c b/dlls/winex11.drv/keyboard.c
index 37c96c926f4..4d113d8c184 100644
--- a/dlls/winex11.drv/keyboard.c
+++ b/dlls/winex11.drv/keyboard.c
@@ -33,6 +33,9 @@
#ifdef HAVE_X11_XKBLIB_H
#include <X11/XKBlib.h>
#endif
+#ifdef HAVE_X11_EXTENSIONS_XINPUT2_H
+#include <X11/extensions/XInput2.h>
+#endif
#include <ctype.h>
#include <stdarg.h>
@@ -1148,7 +1151,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, SEND_HWMSG_RAWINPUT|SEND_HWMSG_WINDOW );
+ __wine_send_input( hwnd, &input, SEND_HWMSG_WINDOW );
}
@@ -1417,6 +1420,41 @@ BOOL X11DRV_KeyEvent( HWND hwnd, XEvent *xev )
return TRUE;
}
+#ifdef HAVE_X11_EXTENSIONS_XINPUT2_H
+/***********************************************************************
+ * X11DRV_KeyEvent
+ *
+ * Handle a raw XInput2 key event for background windows
+ */
+BOOL X11DRV_RawKeyEvent( XGenericEventCookie *cookie )
+{
+ XIRawEvent *event = cookie->data;
+ DWORD flags;
+ WORD vkey, scan;
+ INPUT input;
+
+ vkey = keyc2vkey[event->detail];
+ scan = keyc2scan[event->detail];
+
+ flags = 0;
+ if ( event->evtype == XI_RawKeyRelease ) flags |= KEYEVENTF_KEYUP;
+ if ( vkey & 0x100 ) flags |= KEYEVENTF_EXTENDEDKEY;
+
+ TRACE_(key)( "vkey=%04x scan=%04x flags=%04x\n", vkey, scan, flags );
+
+ input.type = INPUT_KEYBOARD;
+ input.u.ki.wVk = vkey & 0xff;
+ input.u.ki.wScan = scan & 0xff;
+ input.u.ki.dwFlags = flags;
+ input.u.ki.time = EVENT_x11_time_to_win32_time(event->time);
+ input.u.ki.dwExtraInfo = 0;
+
+ __wine_send_input( 0, &input, SEND_HWMSG_RAWINPUT );
+
+ return TRUE;
+}
+#endif
+
/**********************************************************************
* X11DRV_KEYBOARD_DetectLayout
*
diff --git a/dlls/winex11.drv/mouse.c b/dlls/winex11.drv/mouse.c
index bc23b9cbba1..2e9b39fcff7 100644
--- a/dlls/winex11.drv/mouse.c
+++ b/dlls/winex11.drv/mouse.c
@@ -406,6 +406,8 @@ void X11DRV_XInput2_Enable(void)
{
XISetMask( mask_bits, XI_RawButtonPress );
XISetMask( mask_bits, XI_RawButtonRelease );
+ XISetMask( mask_bits, XI_RawKeyPress );
+ XISetMask( mask_bits, XI_RawKeyRelease );
data->xi2_rawinput_only = TRUE;
}
else
@@ -2038,6 +2040,10 @@ BOOL X11DRV_GenericEvent( HWND hwnd, XEvent *xev )
case XI_RawButtonRelease:
ret = X11DRV_RawButtonEvent( event );
break;
+ case XI_RawKeyPress:
+ case XI_RawKeyRelease:
+ ret = X11DRV_RawKeyEvent( 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 c843cd74ace..f89538a1755 100644
--- a/dlls/winex11.drv/x11drv.h
+++ b/dlls/winex11.drv/x11drv.h
@@ -518,6 +518,7 @@ extern BOOL X11DRV_ButtonRelease( HWND hwnd, XEvent *event ) DECLSPEC_HIDDEN;
extern BOOL X11DRV_MotionNotify( HWND hwnd, XEvent *event ) DECLSPEC_HIDDEN;
extern BOOL X11DRV_EnterNotify( HWND hwnd, XEvent *event ) DECLSPEC_HIDDEN;
extern BOOL X11DRV_KeyEvent( HWND hwnd, XEvent *event ) DECLSPEC_HIDDEN;
+extern BOOL X11DRV_RawKeyEvent( XGenericEventCookie *cookie ) DECLSPEC_HIDDEN;
extern BOOL X11DRV_KeymapNotify( HWND hwnd, XEvent *event ) DECLSPEC_HIDDEN;
extern BOOL X11DRV_DestroyNotify( HWND hwnd, XEvent *event ) DECLSPEC_HIDDEN;
extern BOOL X11DRV_SelectionRequest( HWND hWnd, XEvent *event ) DECLSPEC_HIDDEN;
--
2.24.0

View File

@ -0,0 +1 @@
Depends: user32-rawinput-hid

View File

@ -0,0 +1,277 @@
From c227552d313a51f625b741c330ce4509dff99cb5 Mon Sep 17 00:00:00 2001
From: Derek Lesho <dereklesho52@Gmail.com>
Date: Tue, 25 Jun 2019 22:37:34 -0400
Subject: [PATCH 1/4] winex11.drv: Add support for absolute RawMotion events.
When running Xwayland, or using pointing devices, the valuators may
provide absolute values only. In which case, we should translate the
events to the corresponding absolute rawinput messages.
The server side was trying to convert all rawinput messages to relative
positions, but it may not be correct as the desktop cursor position may
not be initialized yet. Keeping the values absolute if we received them
this way seems more reliable.
Note that we cannot really trust valuator names, as it is possible to
configure a pointing device to work in relative mode - wacom tablets for
example - while their axis valuators keep their "Abs X/Y" name. We can
however use the valuator mode to distinguish between relative movements
and absolute position events.
---
dlls/user32/message.c | 7 ++-
dlls/winex11.drv/mouse.c | 96 +++++++++++++++++++++-------------
dlls/winex11.drv/x11drv.h | 18 +++----
dlls/winex11.drv/x11drv_main.c | 2 +
server/queue.c | 4 +-
5 files changed, 79 insertions(+), 48 deletions(-)
diff --git a/dlls/user32/message.c b/dlls/user32/message.c
index cc25d2f6c2f..26c3aa91421 100644
--- a/dlls/user32/message.c
+++ b/dlls/user32/message.c
@@ -2311,7 +2311,12 @@ static BOOL process_rawinput_message( MSG *msg, const struct hardware_msg_data *
rawinput->header.hDevice = WINE_MOUSE_HANDLE;
rawinput->header.wParam = 0;
- rawinput->data.mouse.usFlags = MOUSE_MOVE_RELATIVE;
+ if (msg_data->flags & MOUSEEVENTF_ABSOLUTE)
+ rawinput->data.mouse.usFlags = MOUSE_MOVE_ABSOLUTE;
+ else
+ rawinput->data.mouse.usFlags = MOUSE_MOVE_RELATIVE;
+ if (msg_data->flags & MOUSEEVENTF_VIRTUALDESK)
+ rawinput->data.mouse.usFlags |= MOUSE_VIRTUAL_DESKTOP;
rawinput->data.mouse.u.s.usButtonFlags = 0;
rawinput->data.mouse.u.s.usButtonData = 0;
for (i = 1; i < ARRAY_SIZE(button_flags); ++i)
diff --git a/dlls/winex11.drv/mouse.c b/dlls/winex11.drv/mouse.c
index d331ed5aef8..3474a176003 100644
--- a/dlls/winex11.drv/mouse.c
+++ b/dlls/winex11.drv/mouse.c
@@ -333,32 +333,40 @@ static void update_relative_valuators(XIAnyClassInfo **valuators, int n_valuator
struct x11drv_thread_data *thread_data = x11drv_thread_data();
int i;
- thread_data->x_rel_valuator.number = -1;
- thread_data->y_rel_valuator.number = -1;
+ thread_data->x_pos_valuator.number = -1;
+ thread_data->y_pos_valuator.number = -1;
for (i = 0; i < n_valuators; i++)
{
XIValuatorClassInfo *class = (XIValuatorClassInfo *)valuators[i];
- struct x11drv_valuator_data *valuator_data = NULL;
- if (valuators[i]->type != XIValuatorClass) continue;
- if (class->label == x11drv_atom( Rel_X ) ||
- (!class->label && class->number == 0 && class->mode == XIModeRelative))
- {
- valuator_data = &thread_data->x_rel_valuator;
- }
+ if (valuators[i]->type != XIValuatorClass)
+ continue;
+ else if (class->label == x11drv_atom( Rel_X ) ||
+ class->label == x11drv_atom( Abs_X ) ||
+ (!class->label && class->number == 0))
+ thread_data->x_pos_valuator = *class;
else if (class->label == x11drv_atom( Rel_Y ) ||
- (!class->label && class->number == 1 && class->mode == XIModeRelative))
- {
- valuator_data = &thread_data->y_rel_valuator;
- }
+ class->label == x11drv_atom( Abs_Y ) ||
+ (!class->label && class->number == 1))
+ thread_data->y_pos_valuator = *class;
+ }
- if (valuator_data) {
- valuator_data->number = class->number;
- valuator_data->min = class->min;
- valuator_data->max = class->max;
- }
+ if (thread_data->x_pos_valuator.number < 0 || thread_data->y_pos_valuator.number < 0)
+ {
+ WARN("Only one X/Y axis found, ignoring RawMotion events\n");
+ }
+ else if (thread_data->x_pos_valuator.mode != thread_data->y_pos_valuator.mode)
+ {
+ WARN("Relative/Absolute mismatch between X/Y axis, ignoring RawMotion events\n");
+ thread_data->y_pos_valuator.number = -1;
+ thread_data->y_pos_valuator.number = -1;
}
+
+ if (thread_data->x_pos_valuator.min >= thread_data->x_pos_valuator.max)
+ thread_data->x_pos_valuator.min = thread_data->x_pos_valuator.max = 0;
+ if (thread_data->y_pos_valuator.min >= thread_data->y_pos_valuator.max)
+ thread_data->y_pos_valuator.min = thread_data->y_pos_valuator.max = 0;
}
#endif
@@ -443,8 +451,8 @@ void X11DRV_XInput2_Disable(void)
mask.deviceid = XIAllMasterDevices;
pXISelectEvents( data->display, DefaultRootWindow( data->display ), &mask, 1 );
- data->x_rel_valuator.number = -1;
- data->y_rel_valuator.number = -1;
+ data->x_pos_valuator.number = -1;
+ data->y_pos_valuator.number = -1;
data->xi2_core_pointer = 0;
#endif
}
@@ -1895,16 +1903,22 @@ static BOOL X11DRV_RawMotion( XGenericEventCookie *xev )
INPUT input;
int i;
double dx = 0, dy = 0, val;
+ double x_scale = 1, y_scale = 1;
struct x11drv_thread_data *thread_data = x11drv_thread_data();
- struct x11drv_valuator_data *x_rel, *y_rel;
+ XIValuatorClassInfo *x_pos, *y_pos;
- if (thread_data->x_rel_valuator.number < 0 || thread_data->y_rel_valuator.number < 0) return FALSE;
+ if (thread_data->x_pos_valuator.number < 0 || thread_data->y_pos_valuator.number < 0) return FALSE;
+ if (thread_data->x_pos_valuator.mode != thread_data->y_pos_valuator.mode)
+ {
+ FIXME("Unsupported relative/absolute X/Y axis mismatch\n.");
+ return FALSE;
+ }
if (!event->valuators.mask_len) return FALSE;
if (thread_data->xi2_state != xi_enabled) 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;
+ x_pos = &thread_data->x_pos_valuator;
+ y_pos = &thread_data->y_pos_valuator;
input.type = INPUT_MOUSE;
input.u.mi.mouseData = 0;
@@ -1915,24 +1929,34 @@ static BOOL X11DRV_RawMotion( XGenericEventCookie *xev )
input.u.mi.dy = 0;
virtual_rect = get_virtual_screen_rect();
-
- for (i = 0; i <= max ( x_rel->number, y_rel->number ); i++)
+ if (x_pos->min < x_pos->max)
+ x_scale = (x_pos->mode == XIModeAbsolute ? 65535 : (virtual_rect.right - virtual_rect.left)) /
+ (x_pos->max - x_pos->min);
+ if (y_pos->min < y_pos->max)
+ y_scale = (y_pos->mode == XIModeAbsolute ? 65535 : (virtual_rect.bottom - virtual_rect.top)) /
+ (y_pos->max - y_pos->min);
+
+ for (i = 0; i <= max( x_pos->number, y_pos->number ); i++)
{
if (!XIMaskIsSet( event->valuators.mask, i )) continue;
val = *values++;
- if (i == x_rel->number)
+ if (i == x_pos->number)
{
- input.u.mi.dx = dx = val;
- if (x_rel->min < x_rel->max)
- input.u.mi.dx = val * (virtual_rect.right - virtual_rect.left)
- / (x_rel->max - x_rel->min);
+ dx = val;
+ input.u.mi.dwFlags |= (x_pos->mode == XIModeAbsolute ? MOUSEEVENTF_ABSOLUTE : 0);
+ if (x_pos->mode == XIModeAbsolute)
+ input.u.mi.dx = (dx - x_pos->min) * x_scale;
+ else
+ input.u.mi.dx = dx * x_scale;
}
- if (i == y_rel->number)
+ if (i == y_pos->number)
{
- input.u.mi.dy = dy = val;
- if (y_rel->min < y_rel->max)
- input.u.mi.dy = val * (virtual_rect.bottom - virtual_rect.top)
- / (y_rel->max - y_rel->min);
+ dy = val;
+ input.u.mi.dwFlags |= (y_pos->mode == XIModeAbsolute ? MOUSEEVENTF_ABSOLUTE : 0);
+ if (y_pos->mode == XIModeAbsolute)
+ input.u.mi.dy = (dy - y_pos->min) * y_scale;
+ else
+ input.u.mi.dy = dy * y_scale;
}
}
diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h
index 4a7cab67ada..c4218699034 100644
--- a/dlls/winex11.drv/x11drv.h
+++ b/dlls/winex11.drv/x11drv.h
@@ -32,6 +32,9 @@
#include <X11/Xresource.h>
#include <X11/Xutil.h>
#include <X11/Xatom.h>
+#ifdef HAVE_X11_EXTENSIONS_XINPUT2_H
+#include <X11/extensions/XInput2.h>
+#endif
#define BOOL X_BOOL
#define BYTE X_BYTE
@@ -318,13 +321,6 @@ struct x11drv_escape_flush_gl_drawable
* X11 USER driver
*/
-struct x11drv_valuator_data
-{
- double min;
- double max;
- int number;
-};
-
struct x11drv_thread_data
{
Display *display;
@@ -341,11 +337,13 @@ struct x11drv_thread_data
HWND clip_hwnd; /* message window stored in desktop while clipping is active */
DWORD clip_reset; /* time when clipping was last reset */
HKL kbd_layout; /* active keyboard layout */
+#ifdef HAVE_X11_EXTENSIONS_XINPUT2_H
enum { xi_unavailable = -1, xi_unknown, xi_disabled, xi_enabled } xi2_state; /* XInput2 state */
- struct x11drv_valuator_data x_rel_valuator;
- struct x11drv_valuator_data y_rel_valuator;
+ XIValuatorClassInfo x_pos_valuator;
+ XIValuatorClassInfo y_pos_valuator;
int xi2_core_pointer; /* XInput2 core pointer id */
int xi2_rawinput_only;
+#endif
};
extern struct x11drv_thread_data *x11drv_init_thread_data(void) DECLSPEC_HIDDEN;
@@ -431,6 +429,8 @@ enum x11drv_atoms
XATOM_RAW_CAP_HEIGHT,
XATOM_Rel_X,
XATOM_Rel_Y,
+ XATOM_Abs_X,
+ XATOM_Abs_Y,
XATOM_WM_PROTOCOLS,
XATOM_WM_DELETE_WINDOW,
XATOM_WM_STATE,
diff --git a/dlls/winex11.drv/x11drv_main.c b/dlls/winex11.drv/x11drv_main.c
index f33a79d98bf..3e8dd82654a 100644
--- a/dlls/winex11.drv/x11drv_main.c
+++ b/dlls/winex11.drv/x11drv_main.c
@@ -144,6 +144,8 @@ static const char * const atom_names[NB_XATOMS - FIRST_XATOM] =
"RAW_CAP_HEIGHT",
"Rel X",
"Rel Y",
+ "Abs X",
+ "Abs Y",
"WM_PROTOCOLS",
"WM_DELETE_WINDOW",
"WM_STATE",
diff --git a/server/queue.c b/server/queue.c
index f5dc06100d1..b369f0cdb78 100644
--- a/server/queue.c
+++ b/server/queue.c
@@ -1858,8 +1858,8 @@ static int queue_mouse_message( struct desktop *desktop, user_handle_t win, cons
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.x = input->mouse.x;
+ msg_data->rawinput.mouse.y = input->mouse.y;
msg_data->rawinput.mouse.data = input->mouse.data;
if (req_flags == SEND_HWMSG_RAWINPUT)
--
2.24.1

View File

@ -0,0 +1,86 @@
From 108f1467e2d2712b5fb8956e69d481a033cbcbfe Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
Date: Tue, 10 Sep 2019 12:24:22 +0200
Subject: [PATCH 2/4] winex11.drv: Send relative RawMotion events unprocessed.
This makes relative raw input independent from cursor speed, as it is
the case on Windows. Absolute raw input is already translated to
virtual desktop space, and cursor speed is meaningless in this case.
This does not support mixed relative/absolute X/Y axis.
---
dlls/winex11.drv/mouse.c | 19 +++++++++++++------
1 file changed, 13 insertions(+), 6 deletions(-)
diff --git a/dlls/winex11.drv/mouse.c b/dlls/winex11.drv/mouse.c
index 3474a176003..a2310297ff9 100644
--- a/dlls/winex11.drv/mouse.c
+++ b/dlls/winex11.drv/mouse.c
@@ -1899,20 +1899,17 @@ static BOOL X11DRV_RawMotion( XGenericEventCookie *xev )
{
XIRawEvent *event = xev->data;
const double *values = event->valuators.values;
+ const double *raw_values = event->raw_values;
RECT virtual_rect;
INPUT input;
int i;
double dx = 0, dy = 0, val;
+ double raw_dx = 0, raw_dy = 0, raw_val;
double x_scale = 1, y_scale = 1;
struct x11drv_thread_data *thread_data = x11drv_thread_data();
XIValuatorClassInfo *x_pos, *y_pos;
if (thread_data->x_pos_valuator.number < 0 || thread_data->y_pos_valuator.number < 0) return FALSE;
- if (thread_data->x_pos_valuator.mode != thread_data->y_pos_valuator.mode)
- {
- FIXME("Unsupported relative/absolute X/Y axis mismatch\n.");
- return FALSE;
- }
if (!event->valuators.mask_len) return FALSE;
if (thread_data->xi2_state != xi_enabled) return FALSE;
if (event->deviceid != thread_data->xi2_core_pointer) return FALSE;
@@ -1940,9 +1937,11 @@ static BOOL X11DRV_RawMotion( XGenericEventCookie *xev )
{
if (!XIMaskIsSet( event->valuators.mask, i )) continue;
val = *values++;
+ raw_val = *raw_values++;
if (i == x_pos->number)
{
dx = val;
+ raw_dx = raw_val;
input.u.mi.dwFlags |= (x_pos->mode == XIModeAbsolute ? MOUSEEVENTF_ABSOLUTE : 0);
if (x_pos->mode == XIModeAbsolute)
input.u.mi.dx = (dx - x_pos->min) * x_scale;
@@ -1952,6 +1951,7 @@ static BOOL X11DRV_RawMotion( XGenericEventCookie *xev )
if (i == y_pos->number)
{
dy = val;
+ raw_dy = raw_val;
input.u.mi.dwFlags |= (y_pos->mode == XIModeAbsolute ? MOUSEEVENTF_ABSOLUTE : 0);
if (y_pos->mode == XIModeAbsolute)
input.u.mi.dy = (dy - y_pos->min) * y_scale;
@@ -1966,13 +1966,20 @@ static BOOL X11DRV_RawMotion( XGenericEventCookie *xev )
return FALSE;
}
- if (!thread_data->xi2_rawinput_only)
+ if (x_pos->mode == XIModeAbsolute)
+ {
+ 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_RAWINPUT );
+ }
+ else 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
{
+ input.u.mi.dx = raw_dx;
+ input.u.mi.dy = raw_dy;
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 );
}
--
2.24.1

View File

@ -0,0 +1,166 @@
From f4b6ceb3c008b73dfdb89acc601da3be83c47f86 Mon Sep 17 00:00:00 2001
From: Derek Lesho <dereklesho52@Gmail.com>
Date: Fri, 26 Jul 2019 17:37:19 -0400
Subject: [PATCH 3/4] winex11.drv: Implement relative wheel input from
RawMotion events.
---
dlls/winex11.drv/mouse.c | 33 +++++++++++++++++++++++++++------
dlls/winex11.drv/x11drv.h | 3 +++
dlls/winex11.drv/x11drv_main.c | 1 +
3 files changed, 31 insertions(+), 6 deletions(-)
diff --git a/dlls/winex11.drv/mouse.c b/dlls/winex11.drv/mouse.c
index a2310297ff9..49734ba195b 100644
--- a/dlls/winex11.drv/mouse.c
+++ b/dlls/winex11.drv/mouse.c
@@ -335,11 +335,17 @@ static void update_relative_valuators(XIAnyClassInfo **valuators, int n_valuator
thread_data->x_pos_valuator.number = -1;
thread_data->y_pos_valuator.number = -1;
+ thread_data->wheel_valuator.number = -1;
+ thread_data->wheel_scale = 1;
for (i = 0; i < n_valuators; i++)
{
XIValuatorClassInfo *class = (XIValuatorClassInfo *)valuators[i];
+ XIScrollClassInfo *scroll_class = (XIScrollClassInfo *)valuators[i];
+ if (valuators[i]->type == XIScrollClass &&
+ scroll_class->scroll_type == XIScrollTypeVertical)
+ thread_data->wheel_scale = WHEEL_DELTA / scroll_class->increment;
if (valuators[i]->type != XIValuatorClass)
continue;
else if (class->label == x11drv_atom( Rel_X ) ||
@@ -350,6 +356,9 @@ static void update_relative_valuators(XIAnyClassInfo **valuators, int n_valuator
class->label == x11drv_atom( Abs_Y ) ||
(!class->label && class->number == 1))
thread_data->y_pos_valuator = *class;
+ else if (class->label == x11drv_atom( Rel_Vert_Scroll ) ||
+ (!class->label && class->number == 3 && class->mode == XIModeRelative))
+ thread_data->wheel_valuator = *class;
}
if (thread_data->x_pos_valuator.number < 0 || thread_data->y_pos_valuator.number < 0)
@@ -453,6 +462,8 @@ void X11DRV_XInput2_Disable(void)
pXISelectEvents( data->display, DefaultRootWindow( data->display ), &mask, 1 );
data->x_pos_valuator.number = -1;
data->y_pos_valuator.number = -1;
+ data->wheel_valuator.number = -1;
+ data->wheel_scale = 1;
data->xi2_core_pointer = 0;
#endif
}
@@ -1903,11 +1914,11 @@ static BOOL X11DRV_RawMotion( XGenericEventCookie *xev )
RECT virtual_rect;
INPUT input;
int i;
- double dx = 0, dy = 0, val;
+ double dx = 0, dy = 0, dw = 0, val;
double raw_dx = 0, raw_dy = 0, raw_val;
double x_scale = 1, y_scale = 1;
struct x11drv_thread_data *thread_data = x11drv_thread_data();
- XIValuatorClassInfo *x_pos, *y_pos;
+ XIValuatorClassInfo *x_pos, *y_pos, *wheel;
if (thread_data->x_pos_valuator.number < 0 || thread_data->y_pos_valuator.number < 0) return FALSE;
if (!event->valuators.mask_len) return FALSE;
@@ -1916,6 +1927,7 @@ static BOOL X11DRV_RawMotion( XGenericEventCookie *xev )
x_pos = &thread_data->x_pos_valuator;
y_pos = &thread_data->y_pos_valuator;
+ wheel = &thread_data->wheel_valuator;
input.type = INPUT_MOUSE;
input.u.mi.mouseData = 0;
@@ -1933,7 +1945,7 @@ static BOOL X11DRV_RawMotion( XGenericEventCookie *xev )
y_scale = (y_pos->mode == XIModeAbsolute ? 65535 : (virtual_rect.bottom - virtual_rect.top)) /
(y_pos->max - y_pos->min);
- for (i = 0; i <= max( x_pos->number, y_pos->number ); i++)
+ for (i = 0; i <= max( max( x_pos->number, y_pos->number ), wheel->number ); i++)
{
if (!XIMaskIsSet( event->valuators.mask, i )) continue;
val = *values++;
@@ -1958,6 +1970,12 @@ static BOOL X11DRV_RawMotion( XGenericEventCookie *xev )
else
input.u.mi.dy = dy * y_scale;
}
+ if (i == wheel->number)
+ {
+ dw = val;
+ input.u.mi.dwFlags |= MOUSEEVENTF_WHEEL;
+ input.u.mi.mouseData = dw * thread_data->wheel_scale;
+ }
}
if (broken_rawevents && is_old_motion_event( xev->serial ))
@@ -1968,19 +1986,19 @@ static BOOL X11DRV_RawMotion( XGenericEventCookie *xev )
if (x_pos->mode == XIModeAbsolute)
{
- TRACE( "pos %d,%d (event %f,%f)\n", input.u.mi.dx, input.u.mi.dy, dx, dy );
+ TRACE( "pos %d,%d w:%d (event %f,%f,%f)\n", input.u.mi.dx, input.u.mi.dy, input.u.mi.mouseData, dx, dy, dw );
__wine_send_input( 0, &input, SEND_HWMSG_RAWINPUT );
}
else if (!thread_data->xi2_rawinput_only)
{
- TRACE( "pos %d,%d (event %f,%f)\n", input.u.mi.dx, input.u.mi.dy, dx, dy );
+ TRACE( "pos %d,%d w:%d (event %f,%f,%f)\n", input.u.mi.dx, input.u.mi.dy, input.u.mi.mouseData, dx, dy, dw );
__wine_send_input( 0, &input, SEND_HWMSG_WINDOW );
}
else
{
input.u.mi.dx = raw_dx;
input.u.mi.dy = raw_dy;
- TRACE( "raw pos %d,%d (event %f,%f)\n", input.u.mi.dx, input.u.mi.dy, dx, dy );
+ TRACE( "raw pos %d,%d w:%d (event %f,%f,%f)\n", input.u.mi.dx, input.u.mi.dy, input.u.mi.mouseData, raw_dx, raw_dy, dw );
__wine_send_input( 0, &input, SEND_HWMSG_RAWINPUT );
}
return TRUE;
@@ -2009,6 +2027,9 @@ static BOOL X11DRV_RawButtonEvent( XGenericEventCookie *cookie )
if (thread_data->xi2_state != xi_enabled) return FALSE;
if (event->deviceid != thread_data->xi2_core_pointer) return FALSE;
+ /* mouse wheel is already handled by RawMotion events */
+ if (button == 3 || button == 4) return TRUE;
+
TRACE( "raw button %u (raw: %u) %s\n", button, event->detail, event->evtype == XI_RawButtonRelease ? "up" : "down" );
input.type = INPUT_MOUSE;
diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h
index c4218699034..47c19a83175 100644
--- a/dlls/winex11.drv/x11drv.h
+++ b/dlls/winex11.drv/x11drv.h
@@ -341,6 +341,8 @@ struct x11drv_thread_data
enum { xi_unavailable = -1, xi_unknown, xi_disabled, xi_enabled } xi2_state; /* XInput2 state */
XIValuatorClassInfo x_pos_valuator;
XIValuatorClassInfo y_pos_valuator;
+ XIValuatorClassInfo wheel_valuator;
+ double wheel_scale;
int xi2_core_pointer; /* XInput2 core pointer id */
int xi2_rawinput_only;
#endif
@@ -429,6 +431,7 @@ enum x11drv_atoms
XATOM_RAW_CAP_HEIGHT,
XATOM_Rel_X,
XATOM_Rel_Y,
+ XATOM_Rel_Vert_Scroll,
XATOM_Abs_X,
XATOM_Abs_Y,
XATOM_WM_PROTOCOLS,
diff --git a/dlls/winex11.drv/x11drv_main.c b/dlls/winex11.drv/x11drv_main.c
index 3e8dd82654a..3ed8058fc50 100644
--- a/dlls/winex11.drv/x11drv_main.c
+++ b/dlls/winex11.drv/x11drv_main.c
@@ -144,6 +144,7 @@ static const char * const atom_names[NB_XATOMS - FIRST_XATOM] =
"RAW_CAP_HEIGHT",
"Rel X",
"Rel Y",
+ "Rel Vert Scroll",
"Abs X",
"Abs Y",
"WM_PROTOCOLS",
--
2.24.1

View File

@ -0,0 +1,121 @@
From cf8668ffad406a26dde59993b81619c966446975 Mon Sep 17 00:00:00 2001
From: Jordan Galby <gravemind2a+wine@gmail.com>
Date: Tue, 16 Jul 2019 00:34:38 -0400
Subject: [PATCH 4/4] winex11.drv: Accumulate mouse movement to avoid rounding
losses.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=42631
From: Jordan Galby <gravemind2a+wine@gmail.com>
---
dlls/winex11.drv/mouse.c | 44 +++++++++++++++++++++++++++++++++-------
1 file changed, 37 insertions(+), 7 deletions(-)
diff --git a/dlls/winex11.drv/mouse.c b/dlls/winex11.drv/mouse.c
index 49734ba195b..b5cba492d7e 100644
--- a/dlls/winex11.drv/mouse.c
+++ b/dlls/winex11.drv/mouse.c
@@ -376,6 +376,10 @@ static void update_relative_valuators(XIAnyClassInfo **valuators, int n_valuator
thread_data->x_pos_valuator.min = thread_data->x_pos_valuator.max = 0;
if (thread_data->y_pos_valuator.min >= thread_data->y_pos_valuator.max)
thread_data->y_pos_valuator.min = thread_data->y_pos_valuator.max = 0;
+
+ thread_data->x_pos_valuator.value = 0;
+ thread_data->y_pos_valuator.value = 0;
+ thread_data->wheel_valuator.value = 0;
}
#endif
@@ -1917,6 +1921,7 @@ static BOOL X11DRV_RawMotion( XGenericEventCookie *xev )
double dx = 0, dy = 0, dw = 0, val;
double raw_dx = 0, raw_dy = 0, raw_val;
double x_scale = 1, y_scale = 1;
+ double x_accum = 0, y_accum = 0, w_accum = 0;
struct x11drv_thread_data *thread_data = x11drv_thread_data();
XIValuatorClassInfo *x_pos, *y_pos, *wheel;
@@ -1929,6 +1934,10 @@ static BOOL X11DRV_RawMotion( XGenericEventCookie *xev )
y_pos = &thread_data->y_pos_valuator;
wheel = &thread_data->wheel_valuator;
+ x_accum = x_pos->value;
+ y_accum = y_pos->value;
+ w_accum = wheel->value;
+
input.type = INPUT_MOUSE;
input.u.mi.mouseData = 0;
input.u.mi.dwFlags = MOUSEEVENTF_MOVE;
@@ -1956,9 +1965,9 @@ static BOOL X11DRV_RawMotion( XGenericEventCookie *xev )
raw_dx = raw_val;
input.u.mi.dwFlags |= (x_pos->mode == XIModeAbsolute ? MOUSEEVENTF_ABSOLUTE : 0);
if (x_pos->mode == XIModeAbsolute)
- input.u.mi.dx = (dx - x_pos->min) * x_scale;
+ x_accum = (dx - x_pos->min) * x_scale;
else
- input.u.mi.dx = dx * x_scale;
+ x_accum += dx * x_scale;
}
if (i == y_pos->number)
{
@@ -1966,24 +1975,38 @@ static BOOL X11DRV_RawMotion( XGenericEventCookie *xev )
raw_dy = raw_val;
input.u.mi.dwFlags |= (y_pos->mode == XIModeAbsolute ? MOUSEEVENTF_ABSOLUTE : 0);
if (y_pos->mode == XIModeAbsolute)
- input.u.mi.dy = (dy - y_pos->min) * y_scale;
+ y_accum = (dy - y_pos->min) * y_scale;
else
- input.u.mi.dy = dy * y_scale;
+ y_accum += dy * y_scale;
}
if (i == wheel->number)
{
dw = val;
input.u.mi.dwFlags |= MOUSEEVENTF_WHEEL;
- input.u.mi.mouseData = dw * thread_data->wheel_scale;
+ w_accum += dw * thread_data->wheel_scale;
}
}
+ /* Accumulate the fractional parts so they aren't lost after casting
+ * successive motion values to integral fields.
+ *
+ * Note: It looks like raw_dx, raw_dy and raw_dw are already
+ * integral values but that may be wrong.
+ */
+ input.u.mi.dx = (LONG)x_accum;
+ input.u.mi.dy = (LONG)y_accum;
+ input.u.mi.mouseData = (DWORD)w_accum;
+
if (broken_rawevents && is_old_motion_event( xev->serial ))
{
TRACE( "pos %d,%d old serial %lu, ignoring\n", input.u.mi.dx, input.u.mi.dy, xev->serial );
return FALSE;
}
+ x_pos->value = x_accum - input.u.mi.dx;
+ y_pos->value = y_accum - input.u.mi.dy;
+ wheel->value = w_accum - input.u.mi.mouseData;
+
if (x_pos->mode == XIModeAbsolute)
{
TRACE( "pos %d,%d w:%d (event %f,%f,%f)\n", input.u.mi.dx, input.u.mi.dy, input.u.mi.mouseData, dx, dy, dw );
@@ -1991,8 +2014,15 @@ static BOOL X11DRV_RawMotion( XGenericEventCookie *xev )
}
else if (!thread_data->xi2_rawinput_only)
{
- TRACE( "pos %d,%d w:%d (event %f,%f,%f)\n", input.u.mi.dx, input.u.mi.dy, input.u.mi.mouseData, dx, dy, dw );
- __wine_send_input( 0, &input, SEND_HWMSG_WINDOW );
+ if ((dy || dy || dw) && !(input.u.mi.dx || input.u.mi.dy || input.u.mi.mouseData))
+ {
+ TRACE( "accumulating raw motion (event %f,%f,%f accum %f,%f,%f)\n", dx, dy, dw, x_pos->value, y_pos->value, wheel->value );
+ }
+ else
+ {
+ TRACE( "pos %d,%d w:%d (event %f,%f,%f)\n", input.u.mi.dx, input.u.mi.dy, input.u.mi.mouseData, dx, dy, dw );
+ __wine_send_input( 0, &input, SEND_HWMSG_WINDOW );
+ }
}
else
{
--
2.24.1

View File

@ -0,0 +1,2 @@
Fixes: [45882] - Raw Input should use untransformed mouse values (affects Overwatch, several Source games).
Depends: user32-rawinput-nolegacy

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

Some files were not shown because too many files have changed in this diff Show More