Updated rawinput patchsets

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -0,0 +1,44 @@
From a4256a564e309ad44a8aa8e8571c69444de20bf9 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
Date: Thu, 19 Dec 2019 19:00:21 +0100
Subject: [PATCH 1/4] dinput8/tests: Add test for DISCL_EXCLUSIVE flag
interaction with rawinput.
---
dlls/dinput8/tests/device.c | 20 ++++++++++++++++++++
1 file changed, 20 insertions(+)
diff --git a/dlls/dinput8/tests/device.c b/dlls/dinput8/tests/device.c
index 42ba78707c6..845146af023 100644
--- a/dlls/dinput8/tests/device.c
+++ b/dlls/dinput8/tests/device.c
@@ -759,6 +759,26 @@ static void test_mouse_keyboard(void)
todo_wine
ok(raw_devices_count == 1, "Unexpected raw devices registered: %d\n", raw_devices_count);
+ IDirectInputDevice8_SetCooperativeLevel(di_mouse, hwnd, DISCL_FOREGROUND|DISCL_EXCLUSIVE);
+ IDirectInputDevice8_SetCooperativeLevel(di_keyboard, hwnd, DISCL_FOREGROUND|DISCL_EXCLUSIVE);
+
+ hr = IDirectInputDevice8_Acquire(di_keyboard);
+ ok(SUCCEEDED(hr), "IDirectInputDevice8_Acquire failed: %08x\n", hr);
+ hr = IDirectInputDevice8_Acquire(di_mouse);
+ ok(SUCCEEDED(hr), "IDirectInputDevice8_Acquire failed: %08x\n", hr);
+ raw_devices_count = ARRAY_SIZE(raw_devices);
+ memset(raw_devices, 0, sizeof(raw_devices));
+ hr = GetRegisteredRawInputDevices(raw_devices, &raw_devices_count, sizeof(RAWINPUTDEVICE));
+ ok(hr == 3, "GetRegisteredRawInputDevices returned %d, raw_devices_count: %d\n", hr, raw_devices_count);
+ todo_wine
+ ok(raw_devices[0].dwFlags == (RIDEV_CAPTUREMOUSE|RIDEV_NOLEGACY), "Unexpected raw device flags: %x\n", raw_devices[0].dwFlags);
+ todo_wine
+ ok(raw_devices[2].dwFlags == (RIDEV_NOHOTKEYS|RIDEV_NOLEGACY), "Unexpected raw device flags: %x\n", raw_devices[1].dwFlags);
+ hr = IDirectInputDevice8_Unacquire(di_keyboard);
+ ok(SUCCEEDED(hr), "IDirectInputDevice8_Acquire failed: %08x\n", hr);
+ hr = IDirectInputDevice8_Unacquire(di_mouse);
+ ok(SUCCEEDED(hr), "IDirectInputDevice8_Acquire failed: %08x\n", hr);
+
raw_devices_count = ARRAY_SIZE(raw_devices);
hr = GetRegisteredRawInputDevices(raw_devices, &raw_devices_count, sizeof(RAWINPUTDEVICE));
todo_wine
--
2.24.1

View File

@ -0,0 +1,75 @@
From c39bb27347442d2d229d6e851c17094c086411d6 Mon Sep 17 00:00:00 2001
From: Derek Lesho <dereklesho52@Gmail.com>
Date: Tue, 25 Jun 2019 16:23:02 -0400
Subject: [PATCH 2/4] user32: Add support for RIDEV_NOLEGACY flag in
RegisterRawInputDevices.
---
dlls/user32/rawinput.c | 2 +-
server/queue.c | 9 +++++++++
2 files changed, 10 insertions(+), 1 deletion(-)
diff --git a/dlls/user32/rawinput.c b/dlls/user32/rawinput.c
index 3792360b057..8cf9f8ebf62 100644
--- a/dlls/user32/rawinput.c
+++ b/dlls/user32/rawinput.c
@@ -283,7 +283,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)
+ if (devices[i].dwFlags & ~(RIDEV_REMOVE|RIDEV_NOLEGACY))
FIXME("Unhandled flags %#x for device %u.\n", devices[i].dwFlags, i);
d[i].usage_page = devices[i].usUsagePage;
diff --git a/server/queue.c b/server/queue.c
index 8a1bbfff5aa..f5dc06100d1 100644
--- a/server/queue.c
+++ b/server/queue.c
@@ -427,6 +427,9 @@ static void set_cursor_pos( struct desktop *desktop, int x, int y )
static const struct hw_msg_source source = { IMDT_UNAVAILABLE, IMO_SYSTEM };
struct message *msg;
+ if (current->process->rawinput_mouse &&
+ current->process->rawinput_mouse->flags & RIDEV_NOLEGACY) return;
+
if (!(msg = alloc_hardware_message( 0, source, get_tick_count() ))) return;
msg->msg = WM_MOUSEMOVE;
@@ -1793,6 +1796,7 @@ done:
static int queue_mouse_message( struct desktop *desktop, user_handle_t win, const hw_input_t *input,
unsigned int origin, struct msg_queue *sender, unsigned int req_flags )
{
+ const struct rawinput_device *device;
struct hardware_msg_data *msg_data;
struct rawinput_message raw_msg;
struct message *msg;
@@ -1866,6 +1870,8 @@ static int queue_mouse_message( struct desktop *desktop, user_handle_t win, cons
if (!(req_flags & SEND_HWMSG_WINDOW))
return 0;
+ if ((device = current->process->rawinput_mouse) && (device->flags & RIDEV_NOLEGACY))
+ return 0;
for (i = 0; i < ARRAY_SIZE( messages ); i++)
{
@@ -1901,6 +1907,7 @@ static int queue_keyboard_message( struct desktop *desktop, user_handle_t win, c
unsigned int origin, struct msg_queue *sender, unsigned int req_flags )
{
struct hw_msg_source source = { IMDT_KEYBOARD, origin };
+ const struct rawinput_device *device;
struct hardware_msg_data *msg_data;
struct rawinput_message raw_msg;
struct message *msg;
@@ -1996,6 +2003,8 @@ static int queue_keyboard_message( struct desktop *desktop, user_handle_t win, c
if (!(req_flags & SEND_HWMSG_WINDOW))
return 0;
+ if ((device = current->process->rawinput_kbd) && (device->flags & RIDEV_NOLEGACY))
+ return 0;
if (!(msg = alloc_hardware_message( input->kbd.info, source, time ))) return 0;
msg_data = msg->data;
--
2.24.1

View File

@ -0,0 +1,28 @@
From 1372e0e8582eeb423aa65deab17c52f4f5e153d0 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
Date: Thu, 19 Dec 2019 19:00:50 +0100
Subject: [PATCH 3/4] dinput: Set RIDEV_INPUTSINK flag only when
DISCL_BACKGROUND is requested.
---
dlls/dinput/dinput_main.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/dlls/dinput/dinput_main.c b/dlls/dinput/dinput_main.c
index 9e3b9f48250..ef92a7d7c50 100644
--- a/dlls/dinput/dinput_main.c
+++ b/dlls/dinput/dinput_main.c
@@ -1960,7 +1960,9 @@ void check_dinput_hooks(LPDIRECTINPUTDEVICE8W iface, BOOL acquired)
{
if (acquired)
{
- dev->raw_device.dwFlags = RIDEV_INPUTSINK;
+ dev->raw_device.dwFlags = 0;
+ if (dev->dwCoopLevel & DISCL_BACKGROUND)
+ dev->raw_device.dwFlags |= RIDEV_INPUTSINK;
dev->raw_device.hwndTarget = di_em_win;
}
else
--
2.24.1

View File

@ -0,0 +1,40 @@
From 68898282e49228e9a26328373b4cd661a86d7672 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
Date: Thu, 19 Dec 2019 19:30:49 +0100
Subject: [PATCH 4/4] dinput: Set correct rawinput flags for DISCL_EXCLUSIVE.
---
dlls/dinput/dinput_main.c | 4 ++++
dlls/dinput8/tests/device.c | 1 -
2 files changed, 4 insertions(+), 1 deletion(-)
diff --git a/dlls/dinput/dinput_main.c b/dlls/dinput/dinput_main.c
index ef92a7d7c50..6a74b6da500 100644
--- a/dlls/dinput/dinput_main.c
+++ b/dlls/dinput/dinput_main.c
@@ -1963,6 +1963,10 @@ void check_dinput_hooks(LPDIRECTINPUTDEVICE8W iface, BOOL acquired)
dev->raw_device.dwFlags = 0;
if (dev->dwCoopLevel & DISCL_BACKGROUND)
dev->raw_device.dwFlags |= RIDEV_INPUTSINK;
+ if ((dev->dwCoopLevel & DISCL_EXCLUSIVE) && dev->raw_device.usUsage == 2)
+ dev->raw_device.dwFlags |= (RIDEV_CAPTUREMOUSE|RIDEV_NOLEGACY);
+ if ((dev->dwCoopLevel & DISCL_EXCLUSIVE) && dev->raw_device.usUsage == 6)
+ dev->raw_device.dwFlags |= (RIDEV_NOHOTKEYS|RIDEV_NOLEGACY);
dev->raw_device.hwndTarget = di_em_win;
}
else
diff --git a/dlls/dinput8/tests/device.c b/dlls/dinput8/tests/device.c
index 845146af023..31220db220a 100644
--- a/dlls/dinput8/tests/device.c
+++ b/dlls/dinput8/tests/device.c
@@ -770,7 +770,6 @@ static void test_mouse_keyboard(void)
memset(raw_devices, 0, sizeof(raw_devices));
hr = GetRegisteredRawInputDevices(raw_devices, &raw_devices_count, sizeof(RAWINPUTDEVICE));
ok(hr == 3, "GetRegisteredRawInputDevices returned %d, raw_devices_count: %d\n", hr, raw_devices_count);
- todo_wine
ok(raw_devices[0].dwFlags == (RIDEV_CAPTUREMOUSE|RIDEV_NOLEGACY), "Unexpected raw device flags: %x\n", raw_devices[0].dwFlags);
todo_wine
ok(raw_devices[2].dwFlags == (RIDEV_NOHOTKEYS|RIDEV_NOLEGACY), "Unexpected raw device flags: %x\n", raw_devices[1].dwFlags);
--
2.24.1

View File

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

View File

@ -1,61 +0,0 @@
From c91add917b374a1dd98f07d4d3647295d4fd7f20 Mon Sep 17 00:00:00 2001
From: Derek Lesho <dereklesho52@Gmail.com>
Date: Tue, 25 Jun 2019 16:23:02 -0400
Subject: [PATCH 01/11] user32: Add support for RIDEV_NOLEGACY flag.
Signed-off-by: Derek Lesho <dereklesho52@Gmail.com>
---
dlls/user32/rawinput.c | 2 +-
server/queue.c | 9 +++++++++
2 files changed, 10 insertions(+), 1 deletion(-)
diff --git a/dlls/user32/rawinput.c b/dlls/user32/rawinput.c
index 94cf7a9a5d..661a0e3b25 100644
--- a/dlls/user32/rawinput.c
+++ b/dlls/user32/rawinput.c
@@ -282,7 +282,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)
+ if (devices[i].dwFlags & ~(RIDEV_REMOVE|RIDEV_NOLEGACY))
FIXME("Unhandled flags %#x for device %u.\n", devices[i].dwFlags, i);
d[i].usage_page = devices[i].usUsagePage;
diff --git a/server/queue.c b/server/queue.c
index b5e17be18f..7c3c7e5148 100644
--- a/server/queue.c
+++ b/server/queue.c
@@ -372,6 +372,9 @@ static void set_cursor_pos( struct desktop *desktop, int x, int y )
static const struct hw_msg_source source = { IMDT_UNAVAILABLE, IMO_SYSTEM };
struct message *msg;
+ if (current->process->rawinput_mouse &&
+ current->process->rawinput_mouse->flags & RIDEV_NOLEGACY) return;
+
if (!(msg = alloc_hardware_message( 0, source, get_tick_count() ))) return;
msg->msg = WM_MOUSEMOVE;
@@ -1670,6 +1673,9 @@ static int queue_mouse_message( struct desktop *desktop, user_handle_t win, cons
queue_hardware_message( desktop, msg, 0 );
}
+ if (device && device->flags & RIDEV_NOLEGACY)
+ return FALSE;
+
for (i = 0; i < ARRAY_SIZE( messages ); i++)
{
if (!messages[i]) continue;
@@ -1795,6 +1801,9 @@ static int queue_keyboard_message( struct desktop *desktop, user_handle_t win, c
queue_hardware_message( desktop, msg, 0 );
}
+ if (device && device->flags & RIDEV_NOLEGACY)
+ return FALSE;
+
if (!(msg = alloc_hardware_message( input->kbd.info, source, time ))) return 0;
msg_data = msg->data;
--
2.23.0

View File

@ -1,165 +0,0 @@
From 107e1c0afb7e4a6639726891df26a724ffda5f1e Mon Sep 17 00:00:00 2001
From: Derek Lesho <dereklesho52@Gmail.com>
Date: Tue, 25 Jun 2019 20:47:20 -0400
Subject: [PATCH 02/11] server: Move mouse raw-input message faking from user32
to wineserver.
Signed-off-by: Derek Lesho <dereklesho52@Gmail.com>
---
dlls/user32/message.c | 46 +++----------------------------------------
server/protocol.def | 9 +++++----
server/queue.c | 46 +++++++++++++++++++++++++++++++++++++++++--
3 files changed, 52 insertions(+), 49 deletions(-)
diff --git a/dlls/user32/message.c b/dlls/user32/message.c
index 1336865112..cf0fbe2f0c 100644
--- a/dlls/user32/message.c
+++ b/dlls/user32/message.c
@@ -2295,54 +2295,14 @@ static BOOL process_rawinput_message( MSG *msg, const struct hardware_msg_data *
rawinput->header.dwType = msg_data->rawinput.type;
if (msg_data->rawinput.type == RIM_TYPEMOUSE)
{
- static const unsigned int button_flags[] =
- {
- 0, /* MOUSEEVENTF_MOVE */
- RI_MOUSE_LEFT_BUTTON_DOWN, /* MOUSEEVENTF_LEFTDOWN */
- RI_MOUSE_LEFT_BUTTON_UP, /* MOUSEEVENTF_LEFTUP */
- RI_MOUSE_RIGHT_BUTTON_DOWN, /* MOUSEEVENTF_RIGHTDOWN */
- RI_MOUSE_RIGHT_BUTTON_UP, /* MOUSEEVENTF_RIGHTUP */
- RI_MOUSE_MIDDLE_BUTTON_DOWN, /* MOUSEEVENTF_MIDDLEDOWN */
- RI_MOUSE_MIDDLE_BUTTON_UP, /* MOUSEEVENTF_MIDDLEUP */
- };
- unsigned int i;
-
rawinput->header.dwSize = FIELD_OFFSET(RAWINPUT, data) + sizeof(RAWMOUSE);
rawinput->header.hDevice = WINE_MOUSE_HANDLE;
rawinput->header.wParam = 0;
rawinput->data.mouse.usFlags = MOUSE_MOVE_RELATIVE;
- rawinput->data.mouse.u.s.usButtonFlags = 0;
- rawinput->data.mouse.u.s.usButtonData = 0;
- for (i = 1; i < ARRAY_SIZE(button_flags); ++i)
- {
- if (msg_data->flags & (1 << i))
- rawinput->data.mouse.u.s.usButtonFlags |= button_flags[i];
- }
- if (msg_data->flags & MOUSEEVENTF_WHEEL)
- {
- rawinput->data.mouse.u.s.usButtonFlags |= RI_MOUSE_WHEEL;
- rawinput->data.mouse.u.s.usButtonData = msg_data->rawinput.mouse.data;
- }
- if (msg_data->flags & MOUSEEVENTF_HWHEEL)
- {
- rawinput->data.mouse.u.s.usButtonFlags |= RI_MOUSE_HORIZONTAL_WHEEL;
- rawinput->data.mouse.u.s.usButtonData = msg_data->rawinput.mouse.data;
- }
- if (msg_data->flags & MOUSEEVENTF_XDOWN)
- {
- if (msg_data->rawinput.mouse.data == XBUTTON1)
- rawinput->data.mouse.u.s.usButtonFlags |= RI_MOUSE_BUTTON_4_DOWN;
- else if (msg_data->rawinput.mouse.data == XBUTTON2)
- rawinput->data.mouse.u.s.usButtonFlags |= RI_MOUSE_BUTTON_5_DOWN;
- }
- if (msg_data->flags & MOUSEEVENTF_XUP)
- {
- if (msg_data->rawinput.mouse.data == XBUTTON1)
- rawinput->data.mouse.u.s.usButtonFlags |= RI_MOUSE_BUTTON_4_UP;
- else if (msg_data->rawinput.mouse.data == XBUTTON2)
- rawinput->data.mouse.u.s.usButtonFlags |= RI_MOUSE_BUTTON_5_UP;
- }
+
+ rawinput->data.mouse.u.s.usButtonFlags = msg_data->rawinput.mouse.button_flags;
+ rawinput->data.mouse.u.s.usButtonData = msg_data->rawinput.mouse.button_data;
rawinput->data.mouse.ulRawButtons = 0;
rawinput->data.mouse.lLastX = msg_data->rawinput.mouse.x;
diff --git a/server/protocol.def b/server/protocol.def
index 6af0ae0cff..7346e6aa44 100644
--- a/server/protocol.def
+++ b/server/protocol.def
@@ -304,10 +304,11 @@ struct hardware_msg_data
} kbd;
struct
{
- int type; /* RIM_TYPEMOUSE */
- int x; /* x coordinate */
- int y; /* y coordinate */
- unsigned int data; /* mouse data */
+ int type; /* RIM_TYPEMOUSE */
+ int x; /* x coordinate */
+ int y; /* y coordinate */
+ unsigned short button_flags; /* mouse button */
+ unsigned short button_data; /* event details */
} mouse;
} rawinput;
};
diff --git a/server/queue.c b/server/queue.c
index 7c3c7e5148..a85bb15227 100644
--- a/server/queue.c
+++ b/server/queue.c
@@ -1627,6 +1627,16 @@ static int queue_mouse_message( struct desktop *desktop, user_handle_t win, cons
WM_MOUSEHWHEEL /* 0x1000 = MOUSEEVENTF_HWHEEL */
};
+ static const unsigned int raw_button_flags[] = {
+ 0, /* 0x0001 = MOUSEEVENTF_MOVE */
+ RI_MOUSE_LEFT_BUTTON_DOWN, /* 0x0002 = MOUSEEVENTF_LEFTDOWN */
+ RI_MOUSE_LEFT_BUTTON_UP, /* 0x0004 = MOUSEEVENTF_LEFTUP */
+ RI_MOUSE_RIGHT_BUTTON_DOWN, /* 0x0008 = MOUSEEVENTF_RIGHTDOWN */
+ RI_MOUSE_RIGHT_BUTTON_UP, /* 0x0010 = MOUSEEVENTF_RIGHTUP */
+ RI_MOUSE_MIDDLE_BUTTON_DOWN, /* 0x0020 = MOUSEEVENTF_MIDDLEDOWN */
+ RI_MOUSE_MIDDLE_BUTTON_UP, /* 0x0040 = MOUSEEVENTF_MIDDLEUP */
+ };
+
desktop->cursor.last_change = get_tick_count();
flags = input->mouse.flags;
time = input->mouse.time;
@@ -1664,11 +1674,43 @@ static int queue_mouse_message( struct desktop *desktop, user_handle_t win, cons
msg->wparam = RIM_INPUT;
msg->lparam = 0;
- msg_data->flags = flags;
+ msg_data->flags = 0;
msg_data->rawinput.type = RIM_TYPEMOUSE;
msg_data->rawinput.mouse.x = x - desktop->cursor.x;
msg_data->rawinput.mouse.y = y - desktop->cursor.y;
- msg_data->rawinput.mouse.data = input->mouse.data;
+ msg_data->rawinput.mouse.button_flags = 0;
+ msg_data->rawinput.mouse.button_data = 0;
+
+ for (i = 1; i < ARRAY_SIZE(raw_button_flags); ++i)
+ {
+ if (flags & (1 << i))
+ msg_data->rawinput.mouse.button_flags |= raw_button_flags[i];
+ }
+
+ if (flags & MOUSEEVENTF_WHEEL)
+ {
+ msg_data->rawinput.mouse.button_flags |= RI_MOUSE_WHEEL;
+ msg_data->rawinput.mouse.button_data = input->mouse.data;
+ }
+ if (flags & MOUSEEVENTF_HWHEEL)
+ {
+ msg_data->rawinput.mouse.button_flags |= RI_MOUSE_HORIZONTAL_WHEEL;
+ msg_data->rawinput.mouse.button_data = input->mouse.data;
+ }
+ if (flags & MOUSEEVENTF_XDOWN)
+ {
+ if (input->mouse.data == XBUTTON1)
+ msg_data->rawinput.mouse.button_flags |= RI_MOUSE_BUTTON_4_DOWN;
+ else if (input->mouse.data == XBUTTON2)
+ msg_data->rawinput.mouse.button_flags |= RI_MOUSE_BUTTON_5_DOWN;
+ }
+ if (flags & MOUSEEVENTF_XUP)
+ {
+ if (input->mouse.data == XBUTTON1)
+ msg_data->rawinput.mouse.button_flags |= RI_MOUSE_BUTTON_4_UP;
+ else if (input->mouse.data == XBUTTON2)
+ msg_data->rawinput.mouse.button_flags |= RI_MOUSE_BUTTON_5_UP;
+ }
queue_hardware_message( desktop, msg, 0 );
}
--
2.23.0

View File

@ -1,210 +0,0 @@
From 3757f19f58dcbf11648d602212f412d29dc37750 Mon Sep 17 00:00:00 2001
From: Derek Lesho <dereklesho52@Gmail.com>
Date: Tue, 25 Jun 2019 21:24:12 -0400
Subject: [PATCH 03/11] server: Add request for sending native raw-input
messages.
Signed-off-by: Derek Lesho <dereklesho52@Gmail.com>
---
dlls/user32/message.c | 2 +-
server/protocol.def | 51 +++++++++++++++++++++++++++----------------
server/queue.c | 49 +++++++++++++++++++++++++++++++++++++++++
server/trace.c | 21 ++++++++++++++++++
tools/make_requests | 1 +
5 files changed, 104 insertions(+), 20 deletions(-)
diff --git a/dlls/user32/message.c b/dlls/user32/message.c
index cf0fbe2f0c..98d2c1d2c2 100644
--- a/dlls/user32/message.c
+++ b/dlls/user32/message.c
@@ -2299,7 +2299,7 @@ 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;
+ rawinput->data.mouse.usFlags = msg_data->rawinput.mouse.flags;
rawinput->data.mouse.u.s.usButtonFlags = msg_data->rawinput.mouse.button_flags;
rawinput->data.mouse.u.s.usButtonData = msg_data->rawinput.mouse.button_data;
diff --git a/server/protocol.def b/server/protocol.def
index 7346e6aa44..451c9253ee 100644
--- a/server/protocol.def
+++ b/server/protocol.def
@@ -286,31 +286,39 @@ struct hw_msg_source
unsigned int origin; /* source origin (IMO_* values) */
};
+typedef union
+{
+ int type;
+ struct
+ {
+ int type; /* RIM_TYPEKEYBOARD */
+ unsigned int message; /* message generated by this rawinput event */
+ unsigned short vkey; /* virtual key code */
+ unsigned short scan; /* scan code */
+ } kbd;
+ struct
+ {
+ int type; /* RIM_TYPEMOUSE */
+ unsigned short flags; /* event flags */
+ int x; /* x coordinate */
+ int y; /* y coordinate */
+ unsigned short button_flags; /* mouse button */
+ unsigned short button_data; /* event details */
+ } mouse;
+ struct
+ {
+ int type; /* RIM_TYPEHID */
+ /* TODO: fill this in if/when necessary */
+ } hid;
+} hw_rawinput_t;
+
struct hardware_msg_data
{
lparam_t info; /* extra info */
unsigned int hw_id; /* unique id */
unsigned int flags; /* hook flags */
struct hw_msg_source source; /* message source */
- union
- {
- int type;
- struct
- {
- int type; /* RIM_TYPEKEYBOARD */
- unsigned int message; /* message generated by this rawinput event */
- unsigned short vkey; /* virtual key code */
- unsigned short scan; /* scan code */
- } kbd;
- struct
- {
- int type; /* RIM_TYPEMOUSE */
- int x; /* x coordinate */
- int y; /* y coordinate */
- unsigned short button_flags; /* mouse button */
- unsigned short button_data; /* event details */
- } mouse;
- } rawinput;
+ hw_rawinput_t rawinput;
};
struct callback_msg_data
@@ -2318,6 +2326,11 @@ enum message_type
#define SEND_HWMSG_INJECTED 0x01
+@REQ(send_rawinput_message)
+ hw_rawinput_t input;
+@END
+
+
/* Get a message from the current queue */
@REQ(get_message)
unsigned int flags; /* PM_* flags */
diff --git a/server/queue.c b/server/queue.c
index a85bb15227..f9787933f2 100644
--- a/server/queue.c
+++ b/server/queue.c
@@ -2421,6 +2421,55 @@ DECL_HANDLER(send_hardware_message)
release_object( desktop );
}
+/* send a hardware rawinput message to the queue thread */
+DECL_HANDLER(send_rawinput_message)
+{
+ const struct rawinput_device *device;
+ struct hardware_msg_data *msg_data;
+ struct message *msg;
+ struct desktop *desktop;
+ struct hw_msg_source source = { IMDT_MOUSE, IMO_HARDWARE };
+
+ desktop = get_thread_desktop( current, 0 );
+
+ switch (req->input.type)
+ {
+ case RIM_TYPEMOUSE:
+ if ((device = current->process->rawinput_mouse))
+ {
+ struct thread *thread = device->target ? get_window_thread( device->target ) : NULL;
+ if ((current->queue->input != desktop->foreground_input) || (thread && thread != current))
+ goto done;
+
+ if (!(msg = alloc_hardware_message( 0, source, 0 ))) goto done;
+ msg_data = msg->data;
+
+ msg->win = device->target;
+ msg->msg = WM_INPUT;
+ msg->wparam = RIM_INPUT;
+ msg->lparam = 0;
+
+ msg_data->flags = 0;
+ msg_data->rawinput.type = RIM_TYPEMOUSE;
+ msg_data->rawinput.mouse.x = req->input.mouse.x;
+ msg_data->rawinput.mouse.y = req->input.mouse.y;
+ msg_data->rawinput.mouse.button_flags = req->input.mouse.button_flags;
+ msg_data->rawinput.mouse.button_data = req->input.mouse.button_data;
+ msg_data->rawinput.mouse.flags = req->input.mouse.flags;
+
+ queue_hardware_message( desktop, msg, 0 );
+
+ done:
+ if (thread) release_object( thread );
+ }
+ break;
+ default:
+ set_error( STATUS_INVALID_PARAMETER );
+ }
+
+ release_object(desktop);
+}
+
/* post a quit message to the current queue */
DECL_HANDLER(post_quit_message)
{
diff --git a/server/trace.c b/server/trace.c
index 615542cff5..c936c7e57a 100644
--- a/server/trace.c
+++ b/server/trace.c
@@ -405,6 +405,27 @@ static void dump_hw_input( const char *prefix, const hw_input_t *input )
}
}
+static void dump_hw_rawinput( const char *prefix, const hw_rawinput_t *rawinput )
+{
+ switch (rawinput->type)
+ {
+ case RIM_TYPEMOUSE:
+ fprintf( stderr, "%s{type=MOUSE,flags=%04hx,x=%d,y=%d,button_flags=%04hx,button_data=%04hx}",
+ prefix, rawinput->mouse.flags, rawinput->mouse.x, rawinput->mouse.y,
+ rawinput->mouse.button_flags, rawinput->mouse.button_data);
+ break;
+ case RIM_TYPEKEYBOARD:
+ fprintf( stderr, "%s{type=KEYBOARD}\n", prefix);
+ break;
+ case RIM_TYPEHID:
+ fprintf( stderr, "%s{type=HID}\n", prefix);
+ break;
+ default:
+ fprintf( stderr, "%s{type=%04x}", prefix, rawinput->type);
+ break;
+ }
+}
+
static void dump_luid( const char *prefix, const luid_t *luid )
{
fprintf( stderr, "%s%d.%u", prefix, luid->high_part, luid->low_part );
diff --git a/tools/make_requests b/tools/make_requests
index faeabe5852..a6f12af041 100755
--- a/tools/make_requests
+++ b/tools/make_requests
@@ -53,6 +53,7 @@ my %formats =
"ioctl_code_t" => [ 4, 4, "&dump_ioctl_code" ],
"client_cpu_t" => [ 4, 4, "&dump_client_cpu" ],
"hw_input_t" => [ 32, 8, "&dump_hw_input" ],
+ "hw_rawinput_t" => [ 20, 4, "&dump_hw_rawinput" ]
);
my @requests = ();
--
2.23.0

View File

@ -1,86 +0,0 @@
From 8e384f61c8d864ee95892f250cd0f384ac98d587 Mon Sep 17 00:00:00 2001
From: Derek Lesho <dereklesho52@Gmail.com>
Date: Tue, 25 Jun 2019 21:28:54 -0400
Subject: [PATCH 04/11] user32: Add helper for input drivers to submit native
rawinput msgs.
Signed-off-by: Derek Lesho <dereklesho52@Gmail.com>
---
dlls/user32/input.c | 30 ++++++++++++++++++++++++++++++
dlls/user32/user32.spec | 1 +
include/winuser.h | 1 +
3 files changed, 32 insertions(+)
diff --git a/dlls/user32/input.c b/dlls/user32/input.c
index 8b2ae805aa..9b9cc4f0d7 100644
--- a/dlls/user32/input.c
+++ b/dlls/user32/input.c
@@ -33,6 +33,7 @@
#include <assert.h>
#define NONAMELESSUNION
+#define NONAMELESSSTRUCT
#include "ntstatus.h"
#define WIN32_NO_STATUS
@@ -129,6 +130,35 @@ BOOL CDECL __wine_send_input( HWND hwnd, const INPUT *input )
return !status;
}
+BOOL CDECL __wine_send_raw_input( const RAWINPUT *raw_input )
+{
+ NTSTATUS status;
+
+ SERVER_START_REQ( send_rawinput_message )
+ {
+ req->input.type = raw_input->header.dwType;
+ switch (raw_input->header.dwType)
+ {
+ case RIM_TYPEMOUSE:
+ if (raw_input->data.mouse.ulRawButtons ||
+ raw_input->data.mouse.ulExtraInformation)
+ FIXME("Unhandled parameters\n");
+
+ req->input.mouse.flags = raw_input->data.mouse.usFlags;
+ req->input.mouse.x = raw_input->data.mouse.lLastX;
+ req->input.mouse.y = raw_input->data.mouse.lLastY;
+ req->input.mouse.button_flags = raw_input->data.mouse.u.s.usButtonFlags;
+ req->input.mouse.button_data = raw_input->data.mouse.u.s.usButtonData;
+ break;
+ }
+ status = wine_server_call( req );
+ }
+ SERVER_END_REQ;
+
+ if (status) SetLastError( RtlNtStatusToDosError(status) );
+ return !status;
+}
+
/***********************************************************************
* update_mouse_coords
diff --git a/dlls/user32/user32.spec b/dlls/user32/user32.spec
index f9a4ae26df..3311dcd685 100644
--- a/dlls/user32/user32.spec
+++ b/dlls/user32/user32.spec
@@ -833,4 +833,5 @@
# or 'wine_' (for user-visible functions) to avoid namespace conflicts.
#
@ cdecl __wine_send_input(long ptr)
+@ cdecl __wine_send_raw_input(ptr)
@ cdecl __wine_set_pixel_format(long long)
diff --git a/include/winuser.h b/include/winuser.h
index 51c73d25c2..259db275c4 100644
--- a/include/winuser.h
+++ b/include/winuser.h
@@ -4390,6 +4390,7 @@ WORD WINAPI SYSTEM_KillSystemTimer( WORD );
#ifdef __WINESRC__
WINUSERAPI BOOL CDECL __wine_send_input( HWND hwnd, const INPUT *input );
+WINUSERAPI BOOL CDECL __wine_send_raw_input( const RAWINPUT *raw_input );
#endif
#ifdef __cplusplus
--
2.23.0

View File

@ -1,45 +0,0 @@
From 45b1aba399b89c20e93bc358dfba261e40fcf30b Mon Sep 17 00:00:00 2001
From: Derek Lesho <dereklesho52@Gmail.com>
Date: Tue, 25 Jun 2019 21:58:34 -0400
Subject: [PATCH 05/11] server: Don't emulate rawinput mouse events if native
exist.
Signed-off-by: Derek Lesho <dereklesho52@Gmail.com>
---
server/queue.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/server/queue.c b/server/queue.c
index f9787933f2..060e73b819 100644
--- a/server/queue.c
+++ b/server/queue.c
@@ -1599,6 +1599,8 @@ static int send_hook_ll_message( struct desktop *desktop, struct message *hardwa
return 1;
}
+static int emulate_raw_mouse = 1;
+
/* queue a hardware message for a mouse event */
static int queue_mouse_message( struct desktop *desktop, user_handle_t win, const hw_input_t *input,
unsigned int origin, struct msg_queue *sender )
@@ -1664,7 +1666,8 @@ static int queue_mouse_message( struct desktop *desktop, user_handle_t win, cons
y = desktop->cursor.y;
}
- if ((device = current->process->rawinput_mouse))
+ device = current->process->rawinput_mouse;
+ if (device && emulate_raw_mouse)
{
if (!(msg = alloc_hardware_message( input->mouse.info, source, time ))) return 0;
msg_data = msg->data;
@@ -2435,6 +2438,7 @@ DECL_HANDLER(send_rawinput_message)
switch (req->input.type)
{
case RIM_TYPEMOUSE:
+ emulate_raw_mouse = 0;
if ((device = current->process->rawinput_mouse))
{
struct thread *thread = device->target ? get_window_thread( device->target ) : NULL;
--
2.23.0

View File

@ -1,200 +0,0 @@
From 73d2f9ea82a3897f7ba3f979b599ba0273d8f39d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
Date: Tue, 23 Jul 2019 14:10:44 +0200
Subject: [PATCH 06/11] winex11.drv: Directly listen to master XInput2 devices
if supported
Under XInput2 protocol version < 2.1, raw events should not be received
if pointer grab is active. However slave device events are still
received regardless of this specification and Wine implemented a
workaround to get raw events during pointer grabs by listening to these
slave device events.
By advertising to support XInput2 protocol version >= 2.1, where raw
events are sent even during pointer grabs, it is possible to simplify
the code by listening to master device events only.
Signed-off-by: Derek Lesho <dereklesho52@Gmail.com>
---
dlls/winex11.drv/event.c | 42 +-----------------------------
dlls/winex11.drv/mouse.c | 56 +++++++++++++++++++++++++++++-----------
2 files changed, 42 insertions(+), 56 deletions(-)
diff --git a/dlls/winex11.drv/event.c b/dlls/winex11.drv/event.c
index 25730192d3..e31e2cc0c5 100644
--- a/dlls/winex11.drv/event.c
+++ b/dlls/winex11.drv/event.c
@@ -274,46 +274,6 @@ enum event_merge_action
MERGE_IGNORE /* ignore the new event, keep the old one */
};
-/***********************************************************************
- * merge_raw_motion_events
- */
-#ifdef HAVE_X11_EXTENSIONS_XINPUT2_H
-static enum event_merge_action merge_raw_motion_events( XIRawEvent *prev, XIRawEvent *next )
-{
- int i, j, k;
- unsigned char mask;
-
- if (!prev->valuators.mask_len) return MERGE_HANDLE;
- if (!next->valuators.mask_len) return MERGE_HANDLE;
-
- mask = prev->valuators.mask[0] | next->valuators.mask[0];
- if (mask == next->valuators.mask[0]) /* keep next */
- {
- for (i = j = k = 0; i < 8; i++)
- {
- if (XIMaskIsSet( prev->valuators.mask, i ))
- next->valuators.values[j] += prev->valuators.values[k++];
- if (XIMaskIsSet( next->valuators.mask, i )) j++;
- }
- TRACE( "merging duplicate GenericEvent\n" );
- return MERGE_DISCARD;
- }
- if (mask == prev->valuators.mask[0]) /* keep prev */
- {
- for (i = j = k = 0; i < 8; i++)
- {
- if (XIMaskIsSet( next->valuators.mask, i ))
- prev->valuators.values[j] += next->valuators.values[k++];
- if (XIMaskIsSet( prev->valuators.mask, i )) j++;
- }
- TRACE( "merging duplicate GenericEvent\n" );
- return MERGE_IGNORE;
- }
- /* can't merge events with disjoint masks */
- return MERGE_HANDLE;
-}
-#endif
-
/***********************************************************************
* merge_events
*
@@ -365,7 +325,7 @@ static enum event_merge_action merge_events( XEvent *prev, XEvent *next )
if (next->xcookie.extension != xinput2_opcode) break;
if (next->xcookie.evtype != XI_RawMotion) break;
if (x11drv_thread_data()->warp_serial) break;
- return merge_raw_motion_events( prev->xcookie.data, next->xcookie.data );
+ return MERGE_HANDLE;
#endif
}
break;
diff --git a/dlls/winex11.drv/mouse.c b/dlls/winex11.drv/mouse.c
index 15e5c04a41..23c7c6fb35 100644
--- a/dlls/winex11.drv/mouse.c
+++ b/dlls/winex11.drv/mouse.c
@@ -133,6 +133,8 @@ static Cursor create_cursor( HANDLE handle );
#ifdef HAVE_X11_EXTENSIONS_XINPUT2_H
static BOOL xinput2_available;
+static int xinput2_version_major = 2;
+static int xinput2_version_minor = 1;
static BOOL broken_rawevents;
#define MAKE_FUNCPTR(f) static typeof(f) * p##f
MAKE_FUNCPTR(XIGetClientPointer);
@@ -304,8 +306,11 @@ static void enable_xinput2(void)
if (data->xi2_state == xi_unknown)
{
- int major = 2, minor = 0;
- if (!pXIQueryVersion( data->display, &major, &minor )) data->xi2_state = xi_disabled;
+ if (!pXIQueryVersion( data->display, &xinput2_version_major, &xinput2_version_minor ))
+ {
+ TRACE( "XInput2 v%d.%d available\n", xinput2_version_major, xinput2_version_minor );
+ data->xi2_state = xi_disabled;
+ }
else
{
data->xi2_state = xi_unavailable;
@@ -317,11 +322,19 @@ static void enable_xinput2(void)
mask.mask = mask_bits;
mask.mask_len = sizeof(mask_bits);
- mask.deviceid = XIAllDevices;
+ mask.deviceid = XIAllMasterDevices;
memset( mask_bits, 0, sizeof(mask_bits) );
- XISetMask( mask_bits, XI_DeviceChanged );
XISetMask( mask_bits, XI_RawMotion );
XISetMask( mask_bits, XI_ButtonPress );
+ XISetMask( mask_bits, XI_DeviceChanged );
+
+ /* XInput 2.0 has a problematic behavior where master pointer will
+ * not send raw events to the root window whenever a grab is active
+ */
+ if (xinput2_version_major == 2 && xinput2_version_minor == 0)
+ {
+ mask.deviceid = XIAllDevices;
+ }
pXISelectEvents( data->display, DefaultRootWindow( data->display ), &mask, 1 );
@@ -336,7 +349,7 @@ static void enable_xinput2(void)
* safe to be obtained statically at enable_xinput2() time.
*/
if (data->xi2_devices) pXIFreeDeviceInfo( data->xi2_devices );
- data->xi2_devices = pXIQueryDevice( data->display, XIAllDevices, &data->xi2_device_count );
+ data->xi2_devices = pXIQueryDevice( data->display, mask.deviceid, &data->xi2_device_count );
data->xi2_current_slave = 0;
data->xi2_state = xi_enabled;
@@ -359,7 +372,13 @@ static void disable_xinput2(void)
mask.mask = NULL;
mask.mask_len = 0;
- mask.deviceid = XIAllDevices;
+ mask.deviceid = XIAllMasterDevices;
+
+ /* XInput 2.0 has a problematic behavior where master pointer will
+ * not send raw events to the root window whenever a grab is active
+ */
+ if (xinput2_version_major == 2 && xinput2_version_minor == 0)
+ mask.deviceid = XIAllDevices;
pXISelectEvents( data->display, DefaultRootWindow( data->display ), &mask, 1 );
pXIFreeDeviceInfo( data->xi2_devices );
@@ -1793,25 +1812,32 @@ static BOOL X11DRV_RawMotion( XGenericEventCookie *xev )
if (!event->valuators.mask_len) return FALSE;
if (thread_data->xi2_state != xi_enabled) return FALSE;
- /* If there is no slave currently detected, no previous motion nor device
- * change events were received. Look it up now on the device list in this
- * case.
- */
- if (!thread_data->xi2_current_slave)
+ if (xinput2_version_major == 2 && xinput2_version_minor == 0)
{
XIDeviceInfo *devices = thread_data->xi2_devices;
- for (i = 0; i < thread_data->xi2_device_count; i++)
+ /* If there is no slave currently detected, no previous motion nor device
+ * change events were received. Look it up now on the device list in this
+ * case.
+ */
+ for (i = 0; !thread_data->xi2_current_slave && i < thread_data->xi2_device_count; i++)
{
if (devices[i].use != XISlavePointer) continue;
if (devices[i].deviceid != event->deviceid) continue;
if (devices[i].attachment != thread_data->xi2_core_pointer) continue;
thread_data->xi2_current_slave = event->deviceid;
- break;
}
- }
- if (event->deviceid != thread_data->xi2_current_slave) return FALSE;
+ /* Only listen to slave device events on XInput == 2.0 */
+ if (event->deviceid != thread_data->xi2_current_slave)
+ return FALSE;
+ }
+ else
+ {
+ /* Only listen to master device events on XInput >= 2.1 */
+ if (event->deviceid != thread_data->xi2_core_pointer)
+ return FALSE;
+ }
x_rel = &thread_data->x_rel_valuator;
y_rel = &thread_data->y_rel_valuator;
--
2.23.0

View File

@ -1,316 +0,0 @@
From c91c52063e8c06bc8e8788309ecb7dca70bc6b9a Mon Sep 17 00:00:00 2001
From: Derek Lesho <dereklesho52@Gmail.com>
Date: Tue, 25 Jun 2019 22:37:34 -0400
Subject: [PATCH 07/11] winex11.drv: Implement native mouse-movement raw-input
using RawMotion.
Signed-off-by: Derek Lesho <dereklesho52@Gmail.com>
---
dlls/winex11.drv/mouse.c | 102 +++++++++++++++++++++++++++------
dlls/winex11.drv/x11drv.h | 8 ++-
dlls/winex11.drv/x11drv_main.c | 6 ++
3 files changed, 97 insertions(+), 19 deletions(-)
diff --git a/dlls/winex11.drv/mouse.c b/dlls/winex11.drv/mouse.c
index 23c7c6fb35..212511fde8 100644
--- a/dlls/winex11.drv/mouse.c
+++ b/dlls/winex11.drv/mouse.c
@@ -262,6 +262,8 @@ static void update_relative_valuators(XIAnyClassInfo **valuators, int n_valuator
thread_data->x_rel_valuator.number = -1;
thread_data->y_rel_valuator.number = -1;
+ thread_data->x_abs_valuator.number = -1;
+ thread_data->y_abs_valuator.number = -1;
for (i = 0; i < n_valuators; i++)
{
@@ -279,6 +281,16 @@ static void update_relative_valuators(XIAnyClassInfo **valuators, int n_valuator
{
valuator_data = &thread_data->y_rel_valuator;
}
+ else if (class->label == x11drv_atom( Abs_X ) ||
+ (!class->label && class->number == 0 && class->mode == XIModeAbsolute))
+ {
+ valuator_data = &thread_data->x_abs_valuator;
+ }
+ else if (class->label == x11drv_atom( Abs_Y ) ||
+ (!class->label && class->number == 1 && class->mode == XIModeAbsolute))
+ {
+ valuator_data = &thread_data->y_abs_valuator;
+ }
if (valuator_data) {
valuator_data->number = class->number;
@@ -291,9 +303,9 @@ static void update_relative_valuators(XIAnyClassInfo **valuators, int n_valuator
/***********************************************************************
- * enable_xinput2
+ * X11DRV_XInput2_Enable
*/
-static void enable_xinput2(void)
+void X11DRV_XInput2_Enable(void)
{
#ifdef HAVE_X11_EXTENSIONS_XINPUT2_H
struct x11drv_thread_data *data = x11drv_thread_data();
@@ -324,8 +336,8 @@ static void enable_xinput2(void)
mask.mask_len = sizeof(mask_bits);
mask.deviceid = XIAllMasterDevices;
memset( mask_bits, 0, sizeof(mask_bits) );
+ XISetMask( mask_bits, XI_DeviceChanged );
XISetMask( mask_bits, XI_RawMotion );
- XISetMask( mask_bits, XI_ButtonPress );
XISetMask( mask_bits, XI_DeviceChanged );
/* XInput 2.0 has a problematic behavior where master pointer will
@@ -357,15 +369,15 @@ static void enable_xinput2(void)
}
/***********************************************************************
- * disable_xinput2
+ * X11DRV_XInput2_Disable
*/
-static void disable_xinput2(void)
+void X11DRV_XInput2_Disable(void)
{
#ifdef HAVE_X11_EXTENSIONS_XINPUT2_H
struct x11drv_thread_data *data = x11drv_thread_data();
XIEventMask mask;
- if (data->xi2_state != xi_enabled) return;
+ if (data->xi2_state < xi_enabled) return;
TRACE( "disabling\n" );
data->xi2_state = xi_disabled;
@@ -390,6 +402,21 @@ static void disable_xinput2(void)
#endif
}
+static void use_xinput2_path(void)
+{
+ struct x11drv_thread_data *thread_data = x11drv_thread_data();
+
+ if (thread_data->xi2_state == xi_enabled)
+ thread_data->xi2_state = xi_extra;
+}
+
+static void disable_xinput2_path(void)
+{
+ struct x11drv_thread_data *thread_data = x11drv_thread_data();
+
+ if (thread_data->xi2_state == xi_extra)
+ thread_data->xi2_state = xi_enabled;
+}
/***********************************************************************
* grab_clipping_window
@@ -428,9 +455,9 @@ static BOOL grab_clipping_window( const RECT *clip )
}
/* enable XInput2 unless we are already clipping */
- if (!data->clip_hwnd) enable_xinput2();
+ if (!data->clip_hwnd) use_xinput2_path();
- if (data->xi2_state != xi_enabled)
+ if (data->xi2_state < xi_extra)
{
WARN( "XInput2 not supported, refusing to clip to %s\n", wine_dbgstr_rect(clip) );
DestroyWindow( msg_hwnd );
@@ -458,7 +485,7 @@ static BOOL grab_clipping_window( const RECT *clip )
if (!clipping_cursor)
{
- disable_xinput2();
+ disable_xinput2_path();
DestroyWindow( msg_hwnd );
return FALSE;
}
@@ -539,7 +566,7 @@ LRESULT clip_cursor_notify( HWND hwnd, HWND prev_clip_hwnd, HWND new_clip_hwnd )
TRACE( "clip hwnd reset from %p\n", hwnd );
data->clip_hwnd = 0;
data->clip_reset = GetTickCount();
- disable_xinput2();
+ disable_xinput2_path();
DestroyWindow( hwnd );
}
else if (hwnd == GetForegroundWindow()) /* request to clip */
@@ -1801,16 +1828,20 @@ 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;
+ RAWINPUT raw_input;
int i;
- double dx = 0, dy = 0, val;
+ double dx = 0, dy = 0, raw_x = 0, raw_y = 0, val, raw_val;
struct x11drv_thread_data *thread_data = x11drv_thread_data();
- struct x11drv_valuator_data *x_rel, *y_rel;
+ struct x11drv_valuator_data *x_rel, *y_rel, *x_abs, *y_abs;
+
+ if ((thread_data->x_rel_valuator.number < 0 || thread_data->y_rel_valuator.number < 0) &&
+ (thread_data->x_abs_valuator.number < 0 || thread_data->y_abs_valuator.number < 0) return FALSE;
- if (thread_data->x_rel_valuator.number < 0 || thread_data->y_rel_valuator.number < 0) return FALSE;
if (!event->valuators.mask_len) return FALSE;
- if (thread_data->xi2_state != xi_enabled) return FALSE;
+ if (thread_data->xi2_state < xi_enabled) return FALSE;
if (xinput2_version_major == 2 && xinput2_version_minor == 0)
{
@@ -1841,7 +1872,10 @@ static BOOL X11DRV_RawMotion( XGenericEventCookie *xev )
x_rel = &thread_data->x_rel_valuator;
y_rel = &thread_data->y_rel_valuator;
+ x_abs = &thread_data->x_abs_valuator;
+ y_abs = &thread_data->y_abs_valuator;
+ input.type = INPUT_MOUSE;
input.u.mi.mouseData = 0;
input.u.mi.dwFlags = MOUSEEVENTF_MOVE;
input.u.mi.time = EVENT_x11_time_to_win32_time( event->time );
@@ -1849,18 +1883,31 @@ static BOOL X11DRV_RawMotion( XGenericEventCookie *xev )
input.u.mi.dx = 0;
input.u.mi.dy = 0;
+ raw_input.header.dwType = RIM_TYPEMOUSE;
+ raw_input.data.mouse.u.usButtonFlags = 0;
+ raw_input.data.mouse.u.usButtonData = 0;
+ raw_input.data.mouse.ulExtraInformation = 0;
+ raw_input.data.mouse.ulRawButtons = 0;
+ raw_input.data.mouse.usFlags = 0;
+ raw_input.data.mouse.lLastX = 0;
+ raw_input.data.mouse.lLastY = 0;
+
virtual_rect = get_virtual_screen_rect();
- for (i = 0; i <= max ( x_rel->number, y_rel->number ); i++)
+ for (i = 0; i <= max(max(max( x_abs->number, y_abs->number), x_rel->number), y_rel->number); i++)
{
if (!XIMaskIsSet( event->valuators.mask, i )) continue;
val = *values++;
+ raw_val = *raw_values++;
if (i == x_rel->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);
+
+ raw_input.data.mouse.usFlags = MOUSE_MOVE_RELATIVE;
+ raw_input.data.mouse.lLastX = raw_x = raw_val;
}
if (i == y_rel->number)
{
@@ -1868,6 +1915,19 @@ static BOOL X11DRV_RawMotion( XGenericEventCookie *xev )
if (y_rel->min < y_rel->max)
input.u.mi.dy = val * (virtual_rect.bottom - virtual_rect.top)
/ (y_rel->max - y_rel->min);
+
+ raw_input.data.mouse.usFlags = MOUSE_MOVE_RELATIVE;
+ raw_input.data.mouse.lLastY = raw_y = raw_val;
+ }
+ if (i == x_abs->number)
+ {
+ raw_input.data.mouse.usFlags = MOUSE_MOVE_ABSOLUTE | MOUSE_VIRTUAL_DESKTOP;
+ raw_input.data.mouse.lLastX = raw_x = raw_val * (65536 / (x_abs->max - x_abs->min));
+ }
+ if (i == y_abs->number)
+ {
+ raw_input.data.mouse.usFlags = MOUSE_MOVE_ABSOLUTE | MOUSE_VIRTUAL_DESKTOP;
+ raw_input.data.mouse.lLastY = raw_y = raw_val * (65536 / (y_abs->max - y_abs->min));
}
}
@@ -1877,10 +1937,16 @@ static BOOL X11DRV_RawMotion( XGenericEventCookie *xev )
return FALSE;
}
- TRACE( "pos %d,%d (event %f,%f)\n", input.u.mi.dx, input.u.mi.dy, dx, dy );
+ if (thread_data->xi2_state == xi_extra)
+ {
+ TRACE( "pos %d,%d (event %f,%f)\n", input.u.mi.dx, input.u.mi.dy, dx, dy );
+ __wine_send_input( 0, &input );
+ }
+
+ TRACE("raw %s event %f,%f\n",
+ raw_input.data.mouse.usFlags ? "absolute" : "relative", raw_x, raw_y);
+ __wine_send_raw_input( &raw_input );
- input.type = INPUT_MOUSE;
- __wine_send_input( 0, &input );
return TRUE;
}
diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h
index 135faa8989..e9d9514ee2 100644
--- a/dlls/winex11.drv/x11drv.h
+++ b/dlls/winex11.drv/x11drv.h
@@ -194,6 +194,8 @@ extern BOOL CDECL X11DRV_UnrealizePalette( HPALETTE hpal ) DECLSPEC_HIDDEN;
extern void X11DRV_Xcursor_Init(void) DECLSPEC_HIDDEN;
extern void X11DRV_XInput2_Init(void) DECLSPEC_HIDDEN;
+extern void X11DRV_XInput2_Enable(void) DECLSPEC_HIDDEN;
+extern void X11DRV_XInput2_Disable(void) DECLSPEC_HIDDEN;
extern DWORD copy_image_bits( BITMAPINFO *info, BOOL is_r8g8b8, XImage *image,
const struct gdi_image_bits *src_bits, struct gdi_image_bits *dst_bits,
@@ -335,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 */
- enum { xi_unavailable = -1, xi_unknown, xi_disabled, xi_enabled } xi2_state; /* XInput2 state */
+ enum { xi_unavailable = -1, xi_unknown, xi_disabled, xi_enabled, xi_extra } xi2_state; /* XInput2 state */
void *xi2_devices; /* list of XInput2 devices (valid when state is enabled) */
int xi2_device_count;
struct x11drv_valuator_data x_rel_valuator;
struct x11drv_valuator_data y_rel_valuator;
+ struct x11drv_valuator_data x_abs_valuator;
+ struct x11drv_valuator_data y_abs_valuator;
int xi2_core_pointer; /* XInput2 core pointer id */
int xi2_current_slave; /* Current slave driving the Core pointer */
};
@@ -426,6 +430,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 21807af3f1..fb25a45ae2 100644
--- a/dlls/winex11.drv/x11drv_main.c
+++ b/dlls/winex11.drv/x11drv_main.c
@@ -120,6 +120,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",
@@ -611,6 +613,8 @@ void CDECL X11DRV_ThreadDetach(void)
if (data)
{
+ X11DRV_XInput2_Disable();
+
if (data->xim) XCloseIM( data->xim );
if (data->font_set) XFreeFontSet( data->display, data->font_set );
XCloseDisplay( data->display );
@@ -681,6 +685,8 @@ struct x11drv_thread_data *x11drv_init_thread_data(void)
if (use_xim) X11DRV_SetupXIM();
+ X11DRV_XInput2_Enable();
+
return data;
}
--
2.23.0

View File

@ -1,234 +0,0 @@
From f55c05132e87dd3e9436c68920ad512bdcfb8df8 Mon Sep 17 00:00:00 2001
From: Derek Lesho <dereklesho52@Gmail.com>
Date: Fri, 26 Jul 2019 17:37:19 -0400
Subject: [PATCH 08/11] winex11.drv: Implement native mouse-button raw-input
using RawButton*.
Signed-off-by: Derek Lesho <dereklesho52@Gmail.com>
---
dlls/winex11.drv/mouse.c | 97 +++++++++++++++++++++++++++++++---
dlls/winex11.drv/x11drv.h | 3 ++
dlls/winex11.drv/x11drv_main.c | 1 +
3 files changed, 95 insertions(+), 6 deletions(-)
diff --git a/dlls/winex11.drv/mouse.c b/dlls/winex11.drv/mouse.c
index 212511fde8..1d9833b5c9 100644
--- a/dlls/winex11.drv/mouse.c
+++ b/dlls/winex11.drv/mouse.c
@@ -264,12 +264,21 @@ static void update_relative_valuators(XIAnyClassInfo **valuators, int n_valuator
thread_data->y_rel_valuator.number = -1;
thread_data->x_abs_valuator.number = -1;
thread_data->y_abs_valuator.number = -1;
+ thread_data->wheel_valuator.number = -1;
+
+ thread_data->xi2_wheel_multiplier = 0;
for (i = 0; i < n_valuators; i++)
{
XIValuatorClassInfo *class = (XIValuatorClassInfo *)valuators[i];
+ XIScrollClassInfo *scroll_class = (XIScrollClassInfo *)valuators[i];
struct x11drv_valuator_data *valuator_data = NULL;
+ if (valuators[i]->type == XIScrollClass)
+ {
+ if (scroll_class->scroll_type == XIScrollTypeVertical)
+ thread_data->xi2_wheel_multiplier = -WHEEL_DELTA / scroll_class->increment;
+ }
if (valuators[i]->type != XIValuatorClass) continue;
if (class->label == x11drv_atom( Rel_X ) ||
(!class->label && class->number == 0 && class->mode == XIModeRelative))
@@ -291,6 +300,11 @@ static void update_relative_valuators(XIAnyClassInfo **valuators, int n_valuator
{
valuator_data = &thread_data->y_abs_valuator;
}
+ else if (class->label == x11drv_atom( Rel_Vert_Scroll ) ||
+ (!class->label && class->number == 3 && class->mode == XIModeRelative))
+ {
+ valuator_data = &thread_data->wheel_valuator;
+ }
if (valuator_data) {
valuator_data->number = class->number;
@@ -339,6 +353,8 @@ void X11DRV_XInput2_Enable(void)
XISetMask( mask_bits, XI_DeviceChanged );
XISetMask( mask_bits, XI_RawMotion );
XISetMask( mask_bits, XI_DeviceChanged );
+ XISetMask( mask_bits, XI_RawButtonPress );
+ XISetMask( mask_bits, XI_RawButtonRelease );
/* XInput 2.0 has a problematic behavior where master pointer will
* not send raw events to the root window whenever a grab is active
@@ -396,6 +412,7 @@ void X11DRV_XInput2_Disable(void)
pXIFreeDeviceInfo( data->xi2_devices );
data->x_rel_valuator.number = -1;
data->y_rel_valuator.number = -1;
+ data->wheel_valuator.number = -1;
data->xi2_devices = NULL;
data->xi2_core_pointer = 0;
data->xi2_current_slave = 0;
@@ -1833,12 +1850,13 @@ static BOOL X11DRV_RawMotion( XGenericEventCookie *xev )
INPUT input;
RAWINPUT raw_input;
int i;
- double dx = 0, dy = 0, raw_x = 0, raw_y = 0, val, raw_val;
+ double dx = 0, dy = 0, raw_x = 0, raw_y = 0, raw_dwheel = 0, val, raw_val;
struct x11drv_thread_data *thread_data = x11drv_thread_data();
- struct x11drv_valuator_data *x_rel, *y_rel, *x_abs, *y_abs;
+ struct x11drv_valuator_data *x_rel, *y_rel, *x_abs, *y_abs, *wheel;
if ((thread_data->x_rel_valuator.number < 0 || thread_data->y_rel_valuator.number < 0) &&
- (thread_data->x_abs_valuator.number < 0 || thread_data->y_abs_valuator.number < 0) return FALSE;
+ (thread_data->x_abs_valuator.number < 0 || thread_data->y_abs_valuator.number < 0) &&
+ thread_data->wheel_valuator.number < 0) return FALSE;
if (!event->valuators.mask_len) return FALSE;
if (thread_data->xi2_state < xi_enabled) return FALSE;
@@ -1874,6 +1892,7 @@ static BOOL X11DRV_RawMotion( XGenericEventCookie *xev )
y_rel = &thread_data->y_rel_valuator;
x_abs = &thread_data->x_abs_valuator;
y_abs = &thread_data->y_abs_valuator;
+ wheel = &thread_data->wheel_valuator;
input.type = INPUT_MOUSE;
input.u.mi.mouseData = 0;
@@ -1894,7 +1913,7 @@ static BOOL X11DRV_RawMotion( XGenericEventCookie *xev )
virtual_rect = get_virtual_screen_rect();
- for (i = 0; i <= max(max(max( x_abs->number, y_abs->number), x_rel->number), y_rel->number); i++)
+ for (i = 0; i <= max(max(max(max(x_abs->number, y_abs->number), x_rel->number), y_rel->number), wheel->number); i++)
{
if (!XIMaskIsSet( event->valuators.mask, i )) continue;
val = *values++;
@@ -1929,6 +1948,10 @@ static BOOL X11DRV_RawMotion( XGenericEventCookie *xev )
raw_input.data.mouse.usFlags = MOUSE_MOVE_ABSOLUTE | MOUSE_VIRTUAL_DESKTOP;
raw_input.data.mouse.lLastY = raw_y = raw_val * (65536 / (y_abs->max - y_abs->min));
}
+ if (i == wheel->number)
+ {
+ raw_dwheel = raw_val * thread_data->xi2_wheel_multiplier;
+ }
}
if (broken_rawevents && is_old_motion_event( xev->serial ))
@@ -1943,13 +1966,70 @@ static BOOL X11DRV_RawMotion( XGenericEventCookie *xev )
__wine_send_input( 0, &input );
}
- TRACE("raw %s event %f,%f\n",
- raw_input.data.mouse.usFlags ? "absolute" : "relative", raw_x, raw_y);
+ if (raw_dwheel)
+ {
+ raw_input.data.mouse.u.usButtonFlags = RI_MOUSE_WHEEL;
+ raw_input.data.mouse.u.usButtonData = raw_dwheel;
+ }
+
+ TRACE("raw %s event %f,%f + %f\n",
+ raw_input.data.mouse.usFlags ? "absolute" : "relative", raw_x, raw_y, raw_dwheel);
__wine_send_raw_input( &raw_input );
return TRUE;
}
+/***********************************************************************
+ * X11DRV_RawButton
+ */
+static BOOL X11DRV_RawButton( XGenericEventCookie *xev )
+{
+ RAWINPUT ri;
+
+ static const unsigned short raw_button_press_flags[] = {
+ 0, /* 0 = unused */
+ RI_MOUSE_LEFT_BUTTON_DOWN, /* 1 */
+ RI_MOUSE_MIDDLE_BUTTON_DOWN, /* 2 */
+ RI_MOUSE_RIGHT_BUTTON_DOWN, /* 3 */
+ 0, /* 4 = unknown */
+ 0, /* 5 = unknown */
+ 0, /* 6 = unknown */
+ 0, /* 7 = unknown */
+ RI_MOUSE_BUTTON_4_DOWN, /* 8 */
+ RI_MOUSE_BUTTON_5_DOWN /* 9 */
+ };
+
+ static const unsigned short raw_button_release_flags[] = {
+ 0, /* 0 = unused */
+ RI_MOUSE_LEFT_BUTTON_UP, /* 1 */
+ RI_MOUSE_MIDDLE_BUTTON_UP, /* 2 */
+ RI_MOUSE_RIGHT_BUTTON_UP, /* 3 */
+ 0, /* 4 = unknown */
+ 0, /* 5 = unknown */
+ 0, /* 6 = unknown */
+ 0, /* 7 = unknown */
+ RI_MOUSE_BUTTON_4_UP, /* 8 */
+ RI_MOUSE_BUTTON_5_UP /* 9 */
+ };
+
+ int detail = ((XIRawEvent*)xev->data)->detail;
+ if (detail > 9) return TRUE;
+
+ ri.header.dwType = RIM_TYPEMOUSE;
+ ri.data.mouse.u.usButtonFlags = xev->evtype == XI_RawButtonPress ? raw_button_press_flags[detail] : raw_button_release_flags[detail] ;
+ ri.data.mouse.u.usButtonData = 0;
+ ri.data.mouse.lLastX = 0;
+ ri.data.mouse.lLastY = 0;
+ ri.data.mouse.usFlags = 0;
+ ri.data.mouse.ulRawButtons = 0;
+ ri.data.mouse.ulExtraInformation = 0;
+
+ if (ri.data.mouse.u.usButtonFlags)
+ __wine_send_raw_input( &ri );
+
+ return TRUE;
+}
+
#endif /* HAVE_X11_EXTENSIONS_XINPUT2_H */
@@ -2014,6 +2094,11 @@ BOOL X11DRV_GenericEvent( HWND hwnd, XEvent *xev )
case XI_RawMotion:
ret = X11DRV_RawMotion( event );
break;
+ case XI_RawButtonPress:
+ /* fall through */
+ case XI_RawButtonRelease:
+ ret = X11DRV_RawButton( 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 e9d9514ee2..599ed48154 100644
--- a/dlls/winex11.drv/x11drv.h
+++ b/dlls/winex11.drv/x11drv.h
@@ -344,6 +344,8 @@ struct x11drv_thread_data
struct x11drv_valuator_data y_rel_valuator;
struct x11drv_valuator_data x_abs_valuator;
struct x11drv_valuator_data y_abs_valuator;
+ struct x11drv_valuator_data wheel_valuator;
+ double xi2_wheel_multiplier;
int xi2_core_pointer; /* XInput2 core pointer id */
int xi2_current_slave; /* Current slave driving the Core pointer */
};
@@ -432,6 +434,7 @@ enum x11drv_atoms
XATOM_Rel_Y,
XATOM_Abs_X,
XATOM_Abs_Y,
+ XATOM_Rel_Vert_Scroll,
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 fb25a45ae2..05a445a9c1 100644
--- a/dlls/winex11.drv/x11drv_main.c
+++ b/dlls/winex11.drv/x11drv_main.c
@@ -122,6 +122,7 @@ static const char * const atom_names[NB_XATOMS - FIRST_XATOM] =
"Rel Y",
"Abs X",
"Abs Y",
+ "Rel Vert Scroll",
"WM_PROTOCOLS",
"WM_DELETE_WINDOW",
"WM_STATE",
--
2.23.0

View File

@ -1,121 +0,0 @@
From 5c4db171dc87400ecd3e57b7efff805032328b5f 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 09/11] winex11.drv: Don't react to small slow mouse movements.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=42631
From: Jordan Galby <gravemind2a+wine@gmail.com>
Signed-off-by: Derek Lesho <dereklesho52@Gmail.com>
---
dlls/winex11.drv/mouse.c | 51 +++++++++++++++++++++++++++++++--------
dlls/winex11.drv/x11drv.h | 1 +
2 files changed, 42 insertions(+), 10 deletions(-)
diff --git a/dlls/winex11.drv/mouse.c b/dlls/winex11.drv/mouse.c
index 1d9833b5c9..1b109c8d1a 100644
--- a/dlls/winex11.drv/mouse.c
+++ b/dlls/winex11.drv/mouse.c
@@ -266,6 +266,10 @@ static void update_relative_valuators(XIAnyClassInfo **valuators, int n_valuator
thread_data->y_abs_valuator.number = -1;
thread_data->wheel_valuator.number = -1;
+ thread_data->x_rel_valuator.accum = 0;
+ thread_data->y_rel_valuator.accum = 0;
+ thread_data->wheel_valuator.accum = 0;
+
thread_data->xi2_wheel_multiplier = 0;
for (i = 0; i < n_valuators; i++)
@@ -1920,9 +1924,9 @@ static BOOL X11DRV_RawMotion( XGenericEventCookie *xev )
raw_val = *raw_values++;
if (i == x_rel->number)
{
- input.u.mi.dx = dx = val;
+ dx = val;
if (x_rel->min < x_rel->max)
- input.u.mi.dx = val * (virtual_rect.right - virtual_rect.left)
+ dx = val * (virtual_rect.right - virtual_rect.left)
/ (x_rel->max - x_rel->min);
raw_input.data.mouse.usFlags = MOUSE_MOVE_RELATIVE;
@@ -1930,9 +1934,9 @@ static BOOL X11DRV_RawMotion( XGenericEventCookie *xev )
}
if (i == y_rel->number)
{
- input.u.mi.dy = dy = val;
+ dy = val;
if (y_rel->min < y_rel->max)
- input.u.mi.dy = val * (virtual_rect.bottom - virtual_rect.top)
+ dy = val * (virtual_rect.bottom - virtual_rect.top)
/ (y_rel->max - y_rel->min);
raw_input.data.mouse.usFlags = MOUSE_MOVE_RELATIVE;
@@ -1956,20 +1960,47 @@ static BOOL X11DRV_RawMotion( XGenericEventCookie *xev )
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 );
+ TRACE( "pos %d,%d old serial %lu, ignoring\n", (LONG) dx, (LONG) dy, xev->serial );
return FALSE;
}
- if (thread_data->xi2_state == xi_extra)
+ /* Accumulate the fractional parts so they aren't lost after casting
+ * successive motion values to integral fields.
+ *
+ * Note: It looks like raw_dx and raw_dy are already integral values
+ * but that may be wrong.
+ */
+
+ x_rel->accum += dx;
+ y_rel->accum += dy;
+ if ((dy || dy) && fabs(x_rel->accum) < 1.0 && fabs(y_rel->accum) < 1.0)
+ {
+ TRACE( "accumulating raw motion (event %f,%f, accum %f,%f)\n", dx, dy, x_rel->accum, y_rel->accum );
+ }
+ else
{
- TRACE( "pos %d,%d (event %f,%f)\n", input.u.mi.dx, input.u.mi.dy, dx, dy );
- __wine_send_input( 0, &input );
+ input.u.mi.dx = x_rel->accum;
+ input.u.mi.dy = y_rel->accum;
+ x_rel->accum -= input.u.mi.dx;
+ y_rel->accum -= input.u.mi.dy;
+
+ if (thread_data->xi2_state == xi_extra)
+ {
+ TRACE( "pos %d,%d (event %f,%f)\n", input.u.mi.dx, input.u.mi.dy, dx, dy );
+ __wine_send_input( 0, &input );
+ }
}
- if (raw_dwheel)
+ wheel->accum += raw_dwheel;
+ if (raw_dwheel && fabs(wheel->accum) < 1.0)
+ {
+ TRACE("accumulating wheel motion (event %f, accum %f)\n", raw_dwheel, wheel->accum);
+ }
+ else
{
raw_input.data.mouse.u.usButtonFlags = RI_MOUSE_WHEEL;
- raw_input.data.mouse.u.usButtonData = raw_dwheel;
+ raw_input.data.mouse.u.usButtonData = wheel->accum;
+ wheel->accum -= raw_dwheel;
}
TRACE("raw %s event %f,%f + %f\n",
diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h
index 599ed48154..005512fc4e 100644
--- a/dlls/winex11.drv/x11drv.h
+++ b/dlls/winex11.drv/x11drv.h
@@ -320,6 +320,7 @@ struct x11drv_valuator_data
double min;
double max;
int number;
+ double accum;
};
struct x11drv_thread_data
--
2.23.0

View File

@ -1,42 +0,0 @@
From 97ab5ded8d021c911308f215bbfd27ebd0de4294 Mon Sep 17 00:00:00 2001
From: Derek Lesho <dereklesho52@Gmail.com>
Date: Sat, 10 Aug 2019 12:20:59 -0400
Subject: [PATCH 10/11] server: Implement RIDEV_INPUTSINK flag
Signed-off-by: Derek Lesho <dereklesho52@Gmail.com>
---
dlls/user32/rawinput.c | 2 +-
server/queue.c | 4 +++-
2 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/dlls/user32/rawinput.c b/dlls/user32/rawinput.c
index 661a0e3b25..a93dc36500 100644
--- a/dlls/user32/rawinput.c
+++ b/dlls/user32/rawinput.c
@@ -282,7 +282,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/server/queue.c b/server/queue.c
index 060e73b819..0c3b5354bd 100644
--- a/server/queue.c
+++ b/server/queue.c
@@ -2442,7 +2442,9 @@ DECL_HANDLER(send_rawinput_message)
if ((device = current->process->rawinput_mouse))
{
struct thread *thread = device->target ? get_window_thread( device->target ) : NULL;
- if ((current->queue->input != desktop->foreground_input) || (thread && thread != current))
+ if ((current->queue->input != desktop->foreground_input && !(device->flags & RIDEV_INPUTSINK))
+ || (thread && thread != current)
+ || (!thread && device->flags & RIDEV_INPUTSINK))
goto done;
if (!(msg = alloc_hardware_message( 0, source, 0 ))) goto done;
--
2.23.0

View File

@ -1,76 +0,0 @@
From 1a2b1df3e51425163af922ae5181d17a7f5ad380 Mon Sep 17 00:00:00 2001
From: Derek Lesho <dereklesho52@Gmail.com>
Date: Wed, 4 Sep 2019 10:07:39 -0500
Subject: [PATCH 11/11] winex11.drv: [HACK] XWayland workaround.
---
dlls/winex11.drv/mouse.c | 36 ++++++++++++++++++++++++++++++++----
1 file changed, 32 insertions(+), 4 deletions(-)
diff --git a/dlls/winex11.drv/mouse.c b/dlls/winex11.drv/mouse.c
index 1b109c8d1a..b06b7dc170 100644
--- a/dlls/winex11.drv/mouse.c
+++ b/dlls/winex11.drv/mouse.c
@@ -25,6 +25,7 @@
#include <X11/Xlib.h>
#include <X11/cursorfont.h>
#include <stdarg.h>
+#include <stdlib.h>
#ifdef HAVE_X11_EXTENSIONS_XINPUT2_H
#include <X11/extensions/XInput2.h>
#endif
@@ -1842,6 +1843,17 @@ static BOOL X11DRV_DeviceChanged( XGenericEventCookie *xev )
return TRUE;
}
+/* XWayland only reports normalized absolute values and raw relative values,
+ * all under an absolute valuator.
+ */
+static inline int xwayland_workaround(void)
+{
+ static int workaround = -1;
+ if (workaround != -1) return workaround;
+ workaround = !!getenv("WAYLAND_DISPLAY");
+ return workaround;
+}
+
/***********************************************************************
* X11DRV_RawMotion
*/
@@ -1944,13 +1956,29 @@ static BOOL X11DRV_RawMotion( XGenericEventCookie *xev )
}
if (i == x_abs->number)
{
- raw_input.data.mouse.usFlags = MOUSE_MOVE_ABSOLUTE | MOUSE_VIRTUAL_DESKTOP;
- raw_input.data.mouse.lLastX = raw_x = raw_val * (65536 / (x_abs->max - x_abs->min));
+ if (xwayland_workaround())
+ {
+ raw_input.data.mouse.usFlags = MOUSE_MOVE_RELATIVE;
+ raw_input.data.mouse.lLastX = raw_x = raw_val;
+ }
+ else
+ {
+ raw_input.data.mouse.usFlags = MOUSE_MOVE_ABSOLUTE | MOUSE_VIRTUAL_DESKTOP;
+ raw_input.data.mouse.lLastX = raw_x = raw_val * (65536 / (x_abs->max - x_abs->min));
+ }
}
if (i == y_abs->number)
{
- raw_input.data.mouse.usFlags = MOUSE_MOVE_ABSOLUTE | MOUSE_VIRTUAL_DESKTOP;
- raw_input.data.mouse.lLastY = raw_y = raw_val * (65536 / (y_abs->max - y_abs->min));
+ if (xwayland_workaround())
+ {
+ raw_input.data.mouse.usFlags = MOUSE_MOVE_RELATIVE;
+ raw_input.data.mouse.lLastY = raw_y = raw_val;
+ }
+ else
+ {
+ raw_input.data.mouse.usFlags = MOUSE_MOVE_ABSOLUTE | MOUSE_VIRTUAL_DESKTOP;
+ raw_input.data.mouse.lLastY = raw_y = raw_val * (65536 / (y_abs->max - y_abs->min));
+ }
}
if (i == wheel->number)
{
--
2.23.0

View File

@ -1,5 +0,0 @@
Fixes: [42675] - Overwatch - Phantom mouse input / view pulled up to ceiling.
Fixes: [45882] - Raw Input should use untransformed mouse values (affects Overwatch, several Source games).
Fixes: [47457] - Mouse click-click-hold is treated as double click, causing gun jam in Overwatch.
Fixes: [42631] - user32: Add Raw Input support.
Disabled: True

View File

@ -1,17 +1,17 @@
From 335a6ec241f64bf4ceffc39170cfd3ab88001cb8 Mon Sep 17 00:00:00 2001
From 614fe3af1cabb038c779700fa18dc4992747a164 Mon Sep 17 00:00:00 2001
From: Ken Thomases <ken@codeweavers.com>
Date: Tue, 11 Dec 2018 08:30:41 +1100
Subject: [PATCH 1/2] winex11: Match keyboard in Unicode
Subject: [PATCH] winex11: Match keyboard in Unicode
---
dlls/winex11.drv/keyboard.c | 163 ++++++++++++++++++++++--------------
1 file changed, 98 insertions(+), 65 deletions(-)
diff --git a/dlls/winex11.drv/keyboard.c b/dlls/winex11.drv/keyboard.c
index b9b8293e4d8..3f13a7331cc 100644
index 4d113d8c184..b16d913a4a2 100644
--- a/dlls/winex11.drv/keyboard.c
+++ b/dlls/winex11.drv/keyboard.c
@@ -37,6 +37,7 @@
@@ -40,6 +40,7 @@
#include <ctype.h>
#include <stdarg.h>
#include <string.h>
@ -19,7 +19,7 @@ index b9b8293e4d8..3f13a7331cc 100644
#define NONAMELESSUNION
@@ -76,7 +77,7 @@ static CRITICAL_SECTION_DEBUG critsect_debug =
@@ -79,7 +80,7 @@ static CRITICAL_SECTION_DEBUG critsect_debug =
};
static CRITICAL_SECTION kbd_section = { &critsect_debug, -1, 0, 0, 0, 0 };
@ -28,9 +28,9 @@ index b9b8293e4d8..3f13a7331cc 100644
/* Keyboard translation tables */
#define MAIN_LEN 49
@@ -1452,6 +1453,36 @@ BOOL X11DRV_KeyEvent( HWND hwnd, XEvent *xev )
return TRUE;
@@ -1455,6 +1456,36 @@ BOOL X11DRV_RawKeyEvent( XGenericEventCookie *cookie )
}
#endif
+static WCHAR translate_keysym( Display *display, KeySym keysym )
+{
@ -65,7 +65,7 @@ index b9b8293e4d8..3f13a7331cc 100644
/**********************************************************************
* X11DRV_KEYBOARD_DetectLayout
*
@@ -1468,8 +1499,8 @@ X11DRV_KEYBOARD_DetectLayout( Display *display )
@@ -1471,8 +1502,8 @@ X11DRV_KEYBOARD_DetectLayout( Display *display )
KeySym keysym = 0;
const char (*lkey)[MAIN_LEN][4];
unsigned max_seq = 0;
@ -76,7 +76,7 @@ index b9b8293e4d8..3f13a7331cc 100644
syms = keysyms_per_keycode;
if (syms > 4) {
@@ -1482,35 +1513,25 @@ X11DRV_KEYBOARD_DetectLayout( Display *display )
@@ -1485,35 +1516,25 @@ X11DRV_KEYBOARD_DetectLayout( Display *display )
/* get data for keycode from X server */
for (i = 0; i < syms; i++) {
if (!(keysym = keycode_to_keysym (display, keyc, i))) continue;
@ -120,7 +120,7 @@ index b9b8293e4d8..3f13a7331cc 100644
for (keyc = min_keycode; keyc <= max_keycode; keyc++) {
if (ckey[keyc][0]) {
/* search for a match in layout table */
@@ -1519,10 +1540,13 @@ X11DRV_KEYBOARD_DetectLayout( Display *display )
@@ -1522,10 +1543,13 @@ X11DRV_KEYBOARD_DetectLayout( Display *display )
/* the table, it's okay that the X server has "3#£", for example) */
/* however, the score will be higher for longer matches */
for (key = 0; key < MAIN_LEN; key++) {
@ -137,7 +137,7 @@ index b9b8293e4d8..3f13a7331cc 100644
ok = -1;
}
if (ok > 0) {
@@ -1537,11 +1561,7 @@ X11DRV_KEYBOARD_DetectLayout( Display *display )
@@ -1540,11 +1564,7 @@ X11DRV_KEYBOARD_DetectLayout( Display *display )
if (key > pkey) seq++;
pkey = key;
} else {
@ -150,7 +150,7 @@ index b9b8293e4d8..3f13a7331cc 100644
mismatch++;
score -= syms;
}
@@ -1648,9 +1668,11 @@ void X11DRV_InitKeyboard( Display *display )
@@ -1651,9 +1671,11 @@ void X11DRV_InitKeyboard( Display *display )
XKeyEvent e2;
WORD scan, vkey;
int keyc, i, keyn, syms;
@ -163,7 +163,7 @@ index b9b8293e4d8..3f13a7331cc 100644
/* Ranges of OEM, function key, and character virtual key codes.
* Don't include those handled specially in X11DRV_ToUnicodeEx and
@@ -1707,7 +1729,11 @@ void X11DRV_InitKeyboard( Display *display )
@@ -1710,7 +1732,11 @@ void X11DRV_InitKeyboard( Display *display )
/* Detect the keyboard layout */
X11DRV_KEYBOARD_DetectLayout( display );
lkey = main_key_tab[kbd_layout].key;
@ -175,7 +175,7 @@ index b9b8293e4d8..3f13a7331cc 100644
/* Now build two conversion arrays :
* keycode -> vkey + scancode + extended
@@ -1748,26 +1774,14 @@ void X11DRV_InitKeyboard( Display *display )
@@ -1751,26 +1777,14 @@ void X11DRV_InitKeyboard( Display *display )
int maxlen=0,maxval=-1,ok;
for (i=0; i<syms; i++) {
keysym = keycode_to_keysym(display, keyc, i);
@ -207,7 +207,7 @@ index b9b8293e4d8..3f13a7331cc 100644
if (!ok) i--; /* we overshot */
if (ok||(i>maxlen)) {
maxlen=i; maxval=keyn;
@@ -2369,7 +2383,7 @@ INT CDECL X11DRV_GetKeyNameText(LONG lParam, LPWSTR lpBuffer, INT nSize)
@@ -2388,7 +2402,7 @@ INT CDECL X11DRV_GetKeyNameText(LONG lParam, LPWSTR lpBuffer, INT nSize)
/***********************************************************************
* X11DRV_KEYBOARD_MapDeadKeysym
*/
@ -216,7 +216,7 @@ index b9b8293e4d8..3f13a7331cc 100644
{
switch (keysym)
{
@@ -2379,65 +2393,84 @@ static char KEYBOARD_MapDeadKeysym(KeySym keysym)
@@ -2398,65 +2412,84 @@ static char KEYBOARD_MapDeadKeysym(KeySym keysym)
#endif
case 0x1000FE7E : /* Xfree's XK_Dtilde */
return '~'; /* '? */
@ -316,7 +316,7 @@ index b9b8293e4d8..3f13a7331cc 100644
*/
}
TRACE("no character for dead keysym 0x%08lx\n",keysym);
@@ -2622,7 +2655,7 @@ INT CDECL X11DRV_ToUnicodeEx(UINT virtKey, UINT scanCode, const BYTE *lpKeyState
@@ -2641,7 +2674,7 @@ INT CDECL X11DRV_ToUnicodeEx(UINT virtKey, UINT scanCode, const BYTE *lpKeyState
if (ret == 0)
{
@ -325,7 +325,7 @@ index b9b8293e4d8..3f13a7331cc 100644
#ifdef XK_EuroSign
/* An ugly hack for EuroSign: X can't translate it to a character
@@ -2646,7 +2679,7 @@ INT CDECL X11DRV_ToUnicodeEx(UINT virtKey, UINT scanCode, const BYTE *lpKeyState
@@ -2665,7 +2698,7 @@ INT CDECL X11DRV_ToUnicodeEx(UINT virtKey, UINT scanCode, const BYTE *lpKeyState
dead_char = KEYBOARD_MapDeadKeysym(keysym);
if (dead_char)
{
@ -335,5 +335,5 @@ index b9b8293e4d8..3f13a7331cc 100644
goto found;
}
--
2.19.2
2.24.0