[PATCH 2/3] user32: Add rawinput mouse support.
Henri Verbeet
hverbeet at codeweavers.com
Thu Sep 6 14:33:26 CDT 2012
---
dlls/user32/input.c | 37 ++++++++++++++++--
dlls/user32/message.c | 91 ++++++++++++++++++++++++++++++++++++++++++--
dlls/user32/user_main.c | 1 +
dlls/user32/user_private.h | 3 +-
server/process.c | 1 +
server/process.h | 1 +
server/protocol.def | 11 +++++
server/queue.c | 60 +++++++++++++++++++++++++---
8 files changed, 189 insertions(+), 16 deletions(-)
diff --git a/dlls/user32/input.c b/dlls/user32/input.c
index 3629224..dc22145 100644
--- a/dlls/user32/input.c
+++ b/dlls/user32/input.c
@@ -533,12 +533,41 @@ BOOL WINAPI DECLSPEC_HOTPATCH RegisterRawInputDevices(RAWINPUTDEVICE *devices, U
/******************************************************************
* GetRawInputData (USER32.@)
*/
-UINT WINAPI GetRawInputData(HRAWINPUT hRawInput, UINT uiCommand, LPVOID pData, PUINT pcbSize, UINT cbSizeHeader)
+UINT WINAPI GetRawInputData(HRAWINPUT rawinput, UINT command, void *data, UINT *data_size, UINT header_size)
{
- FIXME("(hRawInput=%p, uiCommand=%d, pData=%p, pcbSize=%p, cbSizeHeader=%d) stub!\n",
- hRawInput, uiCommand, pData, pcbSize, cbSizeHeader);
+ RAWINPUT *ri = (RAWINPUT *)rawinput;
+ UINT s;
- return 0;
+ TRACE("rawinput %p, command %#x, data %p, data_size %p, header_size %u.\n",
+ rawinput, command, data, data_size, header_size);
+
+ if (header_size != sizeof(RAWINPUTHEADER))
+ {
+ WARN("Invalid structure size %u.\n", header_size);
+ return ~0U;
+ }
+
+ switch (command)
+ {
+ case RID_INPUT:
+ s = ri->header.dwSize;
+ break;
+ case RID_HEADER:
+ s = sizeof(RAWINPUTHEADER);
+ break;
+ default:
+ return ~0U;
+ }
+
+ if (!data)
+ {
+ *data_size = s;
+ return 0;
+ }
+
+ if (*data_size < s) return ~0U;
+ memcpy(data, ri, s);
+ return s;
}
diff --git a/dlls/user32/message.c b/dlls/user32/message.c
index 4972bb8..264eeec 100644
--- a/dlls/user32/message.c
+++ b/dlls/user32/message.c
@@ -51,6 +51,8 @@ WINE_DEFAULT_DEBUG_CHANNEL(msg);
WINE_DECLARE_DEBUG_CHANNEL(relay);
WINE_DECLARE_DEBUG_CHANNEL(key);
+#define WINE_MOUSE_HANDLE ((HANDLE)1)
+
#define WM_NCMOUSEFIRST WM_NCMOUSEMOVE
#define WM_NCMOUSELAST (WM_NCMOUSEFIRST+(WM_MOUSELAST-WM_MOUSEFIRST))
@@ -2268,6 +2270,84 @@ static void accept_hardware_message( UINT hw_id, BOOL remove, HWND new_hwnd )
}
+static BOOL process_rawinput_message( MSG *msg, const struct hardware_msg_data *msg_data )
+{
+ struct user_thread_info *thread_info = get_user_thread_info();
+ RAWINPUT *rawinput = thread_info->rawinput;
+
+ if (!rawinput)
+ {
+ thread_info->rawinput = HeapAlloc( GetProcessHeap(), 0, sizeof(*rawinput) );
+ if (!(rawinput = thread_info->rawinput)) return FALSE;
+ }
+
+ 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 < sizeof(button_flags) / sizeof(*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.ulRawButtons = 0;
+ rawinput->data.mouse.lLastX = msg_data->rawinput.mouse.x;
+ rawinput->data.mouse.lLastY = msg_data->rawinput.mouse.y;
+ rawinput->data.mouse.ulExtraInformation = msg_data->info;
+ }
+ else
+ {
+ FIXME("Unhandled rawinput type %#x.\n", msg_data->rawinput.type);
+ return FALSE;
+ }
+
+ msg->lParam = (LPARAM)rawinput;
+ return TRUE;
+}
+
/***********************************************************************
* process_keyboard_message
*
@@ -2558,14 +2638,17 @@ static BOOL process_mouse_message( MSG *msg, UINT hw_id, ULONG_PTR extra_info, H
*
* Process a hardware message; return TRUE if message should be passed on to the app
*/
-static BOOL process_hardware_message( MSG *msg, UINT hw_id, ULONG_PTR extra_info, HWND hwnd_filter,
- UINT first, UINT last, BOOL remove )
+static BOOL process_hardware_message( MSG *msg, UINT hw_id, const struct hardware_msg_data *msg_data,
+ HWND hwnd_filter, UINT first, UINT last, BOOL remove )
{
+ if (msg->message == WM_INPUT)
+ return process_rawinput_message( msg, msg_data );
+
if (is_keyboard_message( msg->message ))
return process_keyboard_message( msg, hw_id, hwnd_filter, first, last, remove );
if (is_mouse_message( msg->message ))
- return process_mouse_message( msg, hw_id, extra_info, hwnd_filter, first, last, remove );
+ return process_mouse_message( msg, hw_id, msg_data->info, hwnd_filter, first, last, remove );
ERR( "unknown message type %x\n", msg->message );
return FALSE;
@@ -2765,7 +2848,7 @@ static BOOL peek_message( MSG *msg, HWND hwnd, UINT first, UINT last, UINT flags
info.msg.pt.x = msg_data->hardware.x;
info.msg.pt.y = msg_data->hardware.y;
hw_id = msg_data->hardware.hw_id;
- if (!process_hardware_message( &info.msg, hw_id, msg_data->hardware.info,
+ if (!process_hardware_message( &info.msg, hw_id, &msg_data->hardware,
hwnd, first, last, flags & PM_REMOVE ))
{
TRACE("dropping msg %x\n", info.msg.message );
diff --git a/dlls/user32/user_main.c b/dlls/user32/user_main.c
index 790ba92..6e39999 100644
--- a/dlls/user32/user_main.c
+++ b/dlls/user32/user_main.c
@@ -313,6 +313,7 @@ static void thread_detach(void)
CloseHandle( thread_info->server_queue );
HeapFree( GetProcessHeap(), 0, thread_info->wmchar_data );
HeapFree( GetProcessHeap(), 0, thread_info->key_state );
+ HeapFree( GetProcessHeap(), 0, thread_info->rawinput );
exiting_thread_id = 0;
}
diff --git a/dlls/user32/user_private.h b/dlls/user32/user_private.h
index bc78d2d..505b2bf 100644
--- a/dlls/user32/user_private.h
+++ b/dlls/user32/user_private.h
@@ -182,8 +182,9 @@ struct user_thread_info
BYTE *key_state; /* Cache of global key state */
HWND top_window; /* Desktop window */
HWND msg_window; /* HWND_MESSAGE parent window */
+ RAWINPUT *rawinput;
- ULONG pad[9]; /* Available for more data */
+ ULONG pad[8]; /* Available for more data */
};
struct hook_extra_info
diff --git a/server/process.c b/server/process.c
index b8d5474..f6fb772 100644
--- a/server/process.c
+++ b/server/process.c
@@ -333,6 +333,7 @@ struct thread *create_process( int fd, struct thread *parent_thread, int inherit
process->desktop = 0;
process->token = NULL;
process->trace_data = 0;
+ process->rawinput_mouse = NULL;
list_init( &process->thread_list );
list_init( &process->locks );
list_init( &process->classes );
diff --git a/server/process.h b/server/process.h
index e9861bb..4a20c76 100644
--- a/server/process.h
+++ b/server/process.h
@@ -88,6 +88,7 @@ struct process
client_ptr_t ldt_copy; /* pointer to LDT copy in client addr space */
unsigned int trace_data; /* opaque data used by the process tracing mechanism */
struct list rawinput_devices;/* list of registered rawinput devices */
+ const struct rawinput_device *rawinput_mouse; /* rawinput mouse device, if any */
};
struct process_snapshot
diff --git a/server/protocol.def b/server/protocol.def
index 10f6e05..14e8239 100644
--- a/server/protocol.def
+++ b/server/protocol.def
@@ -295,6 +295,17 @@ struct hardware_msg_data
int y; /* y position */
unsigned int hw_id; /* unique id */
unsigned int flags; /* hook flags */
+ union
+ {
+ int type;
+ struct
+ {
+ int type; /* RIM_TYPEMOUSE */
+ int x; /* x coordinate */
+ int y; /* y coordinate */
+ unsigned int data; /* mouse data */
+ } mouse;
+ } rawinput;
};
struct callback_msg_data
diff --git a/server/queue.c b/server/queue.c
index 620f6d1..840dfbe 100644
--- a/server/queue.c
+++ b/server/queue.c
@@ -448,11 +448,11 @@ static inline int filter_contains_hw_range( unsigned int first, unsigned int las
{
/* hardware message ranges are (in numerical order):
* WM_NCMOUSEFIRST .. WM_NCMOUSELAST
- * WM_KEYFIRST .. WM_KEYLAST
+ * WM_INPUT_DEVICE_CHANGE .. WM_KEYLAST
* WM_MOUSEFIRST .. WM_MOUSELAST
*/
if (last < WM_NCMOUSEFIRST) return 0;
- if (first > WM_NCMOUSELAST && last < WM_KEYFIRST) return 0;
+ if (first > WM_NCMOUSELAST && last < WM_INPUT_DEVICE_CHANGE) return 0;
if (first > WM_KEYLAST && last < WM_MOUSEFIRST) return 0;
if (first > WM_MOUSELAST) return 0;
return 1;
@@ -461,6 +461,7 @@ static inline int filter_contains_hw_range( unsigned int first, unsigned int las
/* get the QS_* bit corresponding to a given hardware message */
static inline int get_hardware_msg_bit( struct message *msg )
{
+ if (msg->msg == WM_INPUT_DEVICE_CHANGE || msg->msg == WM_INPUT) return QS_RAWINPUT;
if (msg->msg == WM_MOUSEMOVE || msg->msg == WM_NCMOUSEMOVE) return QS_MOUSEMOVE;
if (is_keyboard_msg( msg )) return QS_KEY;
return QS_MOUSEBUTTON;
@@ -489,8 +490,12 @@ static int merge_message( struct thread_input *input, const struct message *msg
struct list *ptr;
if (msg->msg != WM_MOUSEMOVE) return 0;
- if (!(ptr = list_tail( &input->msg_list ))) return 0;
- prev = LIST_ENTRY( ptr, struct message, entry );
+ for (ptr = list_tail( &input->msg_list ); ptr; ptr = list_prev( &input->msg_list, ptr ))
+ {
+ prev = LIST_ENTRY( ptr, struct message, entry );
+ if (prev->msg != WM_INPUT) break;
+ }
+ if (!ptr) return 0;
if (prev->result) return 0;
if (prev->win && msg->win && prev->win != msg->win) return 0;
if (prev->msg != msg->msg) return 0;
@@ -507,6 +512,8 @@ static int merge_message( struct thread_input *input, const struct message *msg
prev_data->y = msg_data->y;
prev_data->info = msg_data->info;
}
+ list_remove( ptr );
+ list_add_tail( &input->msg_list, ptr );
return 1;
}
@@ -1372,7 +1379,11 @@ static user_handle_t find_hardware_message_window( struct desktop *desktop, stru
user_handle_t win = 0;
*msg_code = msg->msg;
- if (is_keyboard_msg( msg ))
+ if (msg->msg == WM_INPUT)
+ {
+ if (!(win = msg->win) && input) win = input->focus;
+ }
+ else if (is_keyboard_msg( msg ))
{
if (input && !(win = input->focus))
{
@@ -1445,7 +1456,7 @@ static void queue_hardware_message( struct desktop *desktop, struct message *msg
if (msg->wparam == VK_SHIFT || msg->wparam == VK_LSHIFT || msg->wparam == VK_RSHIFT)
msg->lparam &= ~(KF_EXTENDED << 16);
}
- else
+ else if (msg->msg != WM_INPUT)
{
if (msg->msg == WM_MOUSEMOVE)
{
@@ -1545,6 +1556,7 @@ static int send_hook_ll_message( struct desktop *desktop, struct message *hardwa
static int queue_mouse_message( struct desktop *desktop, user_handle_t win, const hw_input_t *input,
unsigned int hook_flags, struct msg_queue *sender )
{
+ const struct rawinput_device *device;
struct hardware_msg_data *msg_data;
struct message *msg;
unsigned int i, time, flags;
@@ -1594,6 +1606,35 @@ static int queue_mouse_message( struct desktop *desktop, user_handle_t win, cons
y = desktop->cursor.y;
}
+ if ((device = current->process->rawinput_mouse))
+ {
+ if (!(msg = mem_alloc( sizeof(*msg) ))) return 0;
+ if (!(msg_data = mem_alloc( sizeof(*msg_data) )))
+ {
+ free( msg );
+ return 0;
+ }
+
+ msg->type = MSG_HARDWARE;
+ msg->win = device->target;
+ msg->msg = WM_INPUT;
+ msg->wparam = RIM_INPUT;
+ msg->lparam = 0;
+ msg->time = time;
+ msg->data = msg_data;
+ msg->data_size = sizeof(*msg_data);
+ msg->result = NULL;
+
+ 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 );
+ }
+
for (i = 0; i < sizeof(messages)/sizeof(messages[0]); i++)
{
if (!messages[i]) continue;
@@ -1833,7 +1874,7 @@ static int get_hardware_message( struct thread *thread, unsigned int hw_id, user
}
if (ptr == list_head( &input->msg_list ))
- clear_bits = QS_KEY | QS_MOUSEMOVE | QS_MOUSEBUTTON;
+ clear_bits = QS_INPUT;
else
clear_bits = 0; /* don't clear bits if we don't go through the whole list */
@@ -1890,6 +1931,7 @@ static int get_hardware_message( struct thread *thread, unsigned int hw_id, user
data->hw_id = msg->unique_id;
set_reply_data( msg->data, msg->data_size );
+ if (msg->msg == WM_INPUT) release_hardware_message( current->queue, data->hw_id, 1, 0 );
return 1;
}
/* nothing found, clear the hardware queue bits */
@@ -2969,10 +3011,14 @@ DECL_HANDLER(set_cursor)
DECL_HANDLER(update_rawinput_devices)
{
const struct rawinput_device *devices = get_req_data();
+ const struct rawinput_device_entry *e;
unsigned int i;
for (i = 0; i < req->device_count; ++i)
{
update_rawinput_device(&devices[i]);
}
+
+ e = find_rawinput_device( 1, 2 );
+ current->process->rawinput_mouse = e ? &e->device : NULL;
}
--
1.7.8.6
More information about the wine-patches
mailing list