mirror of
https://gitlab.winehq.org/wine/wine-staging.git
synced 2025-01-28 22:04:43 -08:00
Updated rawinput patchsets
This is a completely updated rawinput patchsets from Rémi Bernon, replacing the current user32-rawinput.
This commit is contained in:
parent
a8cb853708
commit
8218a78955
@ -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:
|
||||
|
@ -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, ¤t->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( ¤t->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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
1
patches/user32-rawinput-hid/definition
Normal file
1
patches/user32-rawinput-hid/definition
Normal file
@ -0,0 +1 @@
|
||||
Depends: user32-rawinput-nolegacy
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
1
patches/user32-rawinput-keyboard/definition
Normal file
1
patches/user32-rawinput-keyboard/definition
Normal file
@ -0,0 +1 @@
|
||||
Depends: user32-rawinput-hid
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
2
patches/user32-rawinput-mouse-experimental/definition
Normal file
2
patches/user32-rawinput-mouse-experimental/definition
Normal file
@ -0,0 +1,2 @@
|
||||
Fixes: [45882] - Raw Input should use untransformed mouse values (affects Overwatch, several Source games).
|
||||
Depends: user32-rawinput-nolegacy
|
@ -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, ¶ms, 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
|
||||
|
@ -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
|
||||
|
@ -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
Loading…
x
Reference in New Issue
Block a user