Commit faaf3d38 authored by Henri Verbeet's avatar Henri Verbeet Committed by Alexandre Julliard

user32: Add rawinput mouse support.

parent d601a0de
...@@ -532,12 +532,41 @@ BOOL WINAPI DECLSPEC_HOTPATCH RegisterRawInputDevices(RAWINPUTDEVICE *devices, U ...@@ -532,12 +532,41 @@ BOOL WINAPI DECLSPEC_HOTPATCH RegisterRawInputDevices(RAWINPUTDEVICE *devices, U
/****************************************************************** /******************************************************************
* GetRawInputData (USER32.@) * 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", RAWINPUT *ri = (RAWINPUT *)rawinput;
hRawInput, uiCommand, pData, pcbSize, cbSizeHeader); 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;
} }
......
...@@ -51,6 +51,8 @@ WINE_DEFAULT_DEBUG_CHANNEL(msg); ...@@ -51,6 +51,8 @@ WINE_DEFAULT_DEBUG_CHANNEL(msg);
WINE_DECLARE_DEBUG_CHANNEL(relay); WINE_DECLARE_DEBUG_CHANNEL(relay);
WINE_DECLARE_DEBUG_CHANNEL(key); WINE_DECLARE_DEBUG_CHANNEL(key);
#define WINE_MOUSE_HANDLE ((HANDLE)1)
#define WM_NCMOUSEFIRST WM_NCMOUSEMOVE #define WM_NCMOUSEFIRST WM_NCMOUSEMOVE
#define WM_NCMOUSELAST (WM_NCMOUSEFIRST+(WM_MOUSELAST-WM_MOUSEFIRST)) #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 ) ...@@ -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 * process_keyboard_message
* *
...@@ -2558,14 +2638,17 @@ static BOOL process_mouse_message( MSG *msg, UINT hw_id, ULONG_PTR extra_info, H ...@@ -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 * 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, static BOOL process_hardware_message( MSG *msg, UINT hw_id, const struct hardware_msg_data *msg_data,
UINT first, UINT last, BOOL remove ) 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 )) if (is_keyboard_message( msg->message ))
return process_keyboard_message( msg, hw_id, hwnd_filter, first, last, remove ); return process_keyboard_message( msg, hw_id, hwnd_filter, first, last, remove );
if (is_mouse_message( msg->message )) 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 ); ERR( "unknown message type %x\n", msg->message );
return FALSE; return FALSE;
...@@ -2765,7 +2848,7 @@ static BOOL peek_message( MSG *msg, HWND hwnd, UINT first, UINT last, UINT flags ...@@ -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.x = msg_data->hardware.x;
info.msg.pt.y = msg_data->hardware.y; info.msg.pt.y = msg_data->hardware.y;
hw_id = msg_data->hardware.hw_id; 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 )) hwnd, first, last, flags & PM_REMOVE ))
{ {
TRACE("dropping msg %x\n", info.msg.message ); TRACE("dropping msg %x\n", info.msg.message );
......
...@@ -313,6 +313,7 @@ static void thread_detach(void) ...@@ -313,6 +313,7 @@ static void thread_detach(void)
CloseHandle( thread_info->server_queue ); CloseHandle( thread_info->server_queue );
HeapFree( GetProcessHeap(), 0, thread_info->wmchar_data ); HeapFree( GetProcessHeap(), 0, thread_info->wmchar_data );
HeapFree( GetProcessHeap(), 0, thread_info->key_state ); HeapFree( GetProcessHeap(), 0, thread_info->key_state );
HeapFree( GetProcessHeap(), 0, thread_info->rawinput );
exiting_thread_id = 0; exiting_thread_id = 0;
} }
......
...@@ -182,8 +182,9 @@ struct user_thread_info ...@@ -182,8 +182,9 @@ struct user_thread_info
BYTE *key_state; /* Cache of global key state */ BYTE *key_state; /* Cache of global key state */
HWND top_window; /* Desktop window */ HWND top_window; /* Desktop window */
HWND msg_window; /* HWND_MESSAGE parent 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 struct hook_extra_info
......
...@@ -279,6 +279,17 @@ struct hardware_msg_data ...@@ -279,6 +279,17 @@ struct hardware_msg_data
int y; int y;
unsigned int hw_id; unsigned int hw_id;
unsigned int flags; unsigned int flags;
union
{
int type;
struct
{
int type;
int x;
int y;
unsigned int data;
} mouse;
} rawinput;
}; };
struct callback_msg_data struct callback_msg_data
...@@ -5672,6 +5683,6 @@ union generic_reply ...@@ -5672,6 +5683,6 @@ union generic_reply
struct set_suspend_context_reply set_suspend_context_reply; struct set_suspend_context_reply set_suspend_context_reply;
}; };
#define SERVER_PROTOCOL_VERSION 433 #define SERVER_PROTOCOL_VERSION 434
#endif /* __WINE_WINE_SERVER_PROTOCOL_H */ #endif /* __WINE_WINE_SERVER_PROTOCOL_H */
...@@ -333,6 +333,7 @@ struct thread *create_process( int fd, struct thread *parent_thread, int inherit ...@@ -333,6 +333,7 @@ struct thread *create_process( int fd, struct thread *parent_thread, int inherit
process->desktop = 0; process->desktop = 0;
process->token = NULL; process->token = NULL;
process->trace_data = 0; process->trace_data = 0;
process->rawinput_mouse = NULL;
list_init( &process->thread_list ); list_init( &process->thread_list );
list_init( &process->locks ); list_init( &process->locks );
list_init( &process->classes ); list_init( &process->classes );
......
...@@ -88,6 +88,7 @@ struct process ...@@ -88,6 +88,7 @@ struct process
client_ptr_t ldt_copy; /* pointer to LDT copy in client addr space */ 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 */ unsigned int trace_data; /* opaque data used by the process tracing mechanism */
struct list rawinput_devices;/* list of registered rawinput devices */ struct list rawinput_devices;/* list of registered rawinput devices */
const struct rawinput_device *rawinput_mouse; /* rawinput mouse device, if any */
}; };
struct process_snapshot struct process_snapshot
......
...@@ -295,6 +295,17 @@ struct hardware_msg_data ...@@ -295,6 +295,17 @@ struct hardware_msg_data
int y; /* y position */ int y; /* y position */
unsigned int hw_id; /* unique id */ unsigned int hw_id; /* unique id */
unsigned int flags; /* hook flags */ 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 struct callback_msg_data
......
...@@ -448,11 +448,11 @@ static inline int filter_contains_hw_range( unsigned int first, unsigned int las ...@@ -448,11 +448,11 @@ static inline int filter_contains_hw_range( unsigned int first, unsigned int las
{ {
/* hardware message ranges are (in numerical order): /* hardware message ranges are (in numerical order):
* WM_NCMOUSEFIRST .. WM_NCMOUSELAST * WM_NCMOUSEFIRST .. WM_NCMOUSELAST
* WM_KEYFIRST .. WM_KEYLAST * WM_INPUT_DEVICE_CHANGE .. WM_KEYLAST
* WM_MOUSEFIRST .. WM_MOUSELAST * WM_MOUSEFIRST .. WM_MOUSELAST
*/ */
if (last < WM_NCMOUSEFIRST) return 0; 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_KEYLAST && last < WM_MOUSEFIRST) return 0;
if (first > WM_MOUSELAST) return 0; if (first > WM_MOUSELAST) return 0;
return 1; return 1;
...@@ -461,6 +461,7 @@ static inline int filter_contains_hw_range( unsigned int first, unsigned int las ...@@ -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 */ /* get the QS_* bit corresponding to a given hardware message */
static inline int get_hardware_msg_bit( struct message *msg ) 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 (msg->msg == WM_MOUSEMOVE || msg->msg == WM_NCMOUSEMOVE) return QS_MOUSEMOVE;
if (is_keyboard_msg( msg )) return QS_KEY; if (is_keyboard_msg( msg )) return QS_KEY;
return QS_MOUSEBUTTON; return QS_MOUSEBUTTON;
...@@ -489,8 +490,12 @@ static int merge_message( struct thread_input *input, const struct message *msg ...@@ -489,8 +490,12 @@ static int merge_message( struct thread_input *input, const struct message *msg
struct list *ptr; struct list *ptr;
if (msg->msg != WM_MOUSEMOVE) return 0; if (msg->msg != WM_MOUSEMOVE) return 0;
if (!(ptr = list_tail( &input->msg_list ))) return 0; for (ptr = list_tail( &input->msg_list ); ptr; ptr = list_prev( &input->msg_list, ptr ))
prev = LIST_ENTRY( ptr, struct message, entry ); {
prev = LIST_ENTRY( ptr, struct message, entry );
if (prev->msg != WM_INPUT) break;
}
if (!ptr) return 0;
if (prev->result) return 0; if (prev->result) return 0;
if (prev->win && msg->win && prev->win != msg->win) return 0; if (prev->win && msg->win && prev->win != msg->win) return 0;
if (prev->msg != msg->msg) 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 ...@@ -507,6 +512,8 @@ static int merge_message( struct thread_input *input, const struct message *msg
prev_data->y = msg_data->y; prev_data->y = msg_data->y;
prev_data->info = msg_data->info; prev_data->info = msg_data->info;
} }
list_remove( ptr );
list_add_tail( &input->msg_list, ptr );
return 1; return 1;
} }
...@@ -1372,7 +1379,11 @@ static user_handle_t find_hardware_message_window( struct desktop *desktop, stru ...@@ -1372,7 +1379,11 @@ static user_handle_t find_hardware_message_window( struct desktop *desktop, stru
user_handle_t win = 0; user_handle_t win = 0;
*msg_code = msg->msg; *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)) if (input && !(win = input->focus))
{ {
...@@ -1445,7 +1456,7 @@ static void queue_hardware_message( struct desktop *desktop, struct message *msg ...@@ -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) if (msg->wparam == VK_SHIFT || msg->wparam == VK_LSHIFT || msg->wparam == VK_RSHIFT)
msg->lparam &= ~(KF_EXTENDED << 16); msg->lparam &= ~(KF_EXTENDED << 16);
} }
else else if (msg->msg != WM_INPUT)
{ {
if (msg->msg == WM_MOUSEMOVE) if (msg->msg == WM_MOUSEMOVE)
{ {
...@@ -1545,6 +1556,7 @@ static int send_hook_ll_message( struct desktop *desktop, struct message *hardwa ...@@ -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, 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 ) unsigned int hook_flags, struct msg_queue *sender )
{ {
const struct rawinput_device *device;
struct hardware_msg_data *msg_data; struct hardware_msg_data *msg_data;
struct message *msg; struct message *msg;
unsigned int i, time, flags; unsigned int i, time, flags;
...@@ -1594,6 +1606,35 @@ static int queue_mouse_message( struct desktop *desktop, user_handle_t win, cons ...@@ -1594,6 +1606,35 @@ static int queue_mouse_message( struct desktop *desktop, user_handle_t win, cons
y = desktop->cursor.y; 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++) for (i = 0; i < sizeof(messages)/sizeof(messages[0]); i++)
{ {
if (!messages[i]) continue; if (!messages[i]) continue;
...@@ -1833,7 +1874,7 @@ static int get_hardware_message( struct thread *thread, unsigned int hw_id, user ...@@ -1833,7 +1874,7 @@ static int get_hardware_message( struct thread *thread, unsigned int hw_id, user
} }
if (ptr == list_head( &input->msg_list )) if (ptr == list_head( &input->msg_list ))
clear_bits = QS_KEY | QS_MOUSEMOVE | QS_MOUSEBUTTON; clear_bits = QS_INPUT;
else else
clear_bits = 0; /* don't clear bits if we don't go through the whole list */ 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 ...@@ -1890,6 +1931,7 @@ static int get_hardware_message( struct thread *thread, unsigned int hw_id, user
data->hw_id = msg->unique_id; data->hw_id = msg->unique_id;
set_reply_data( msg->data, msg->data_size ); 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; return 1;
} }
/* nothing found, clear the hardware queue bits */ /* nothing found, clear the hardware queue bits */
...@@ -2970,10 +3012,14 @@ DECL_HANDLER(update_rawinput_devices) ...@@ -2970,10 +3012,14 @@ DECL_HANDLER(update_rawinput_devices)
{ {
const struct rawinput_device *devices = get_req_data(); const struct rawinput_device *devices = get_req_data();
unsigned int device_count = get_req_data_size() / sizeof (*devices); unsigned int device_count = get_req_data_size() / sizeof (*devices);
const struct rawinput_device_entry *e;
unsigned int i; unsigned int i;
for (i = 0; i < device_count; ++i) for (i = 0; i < device_count; ++i)
{ {
update_rawinput_device(&devices[i]); update_rawinput_device(&devices[i]);
} }
e = find_rawinput_device( 1, 2 );
current->process->rawinput_mouse = e ? &e->device : NULL;
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment