user32: Add rawinput mouse support.

This commit is contained in:
Henri Verbeet 2012-09-11 00:27:04 +02:00 committed by Alexandre Julliard
parent d601a0dede
commit faaf3d388e
9 changed files with 201 additions and 17 deletions

View File

@ -532,12 +532,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;
}

View File

@ -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 );

View File

@ -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;
}

View File

@ -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

View File

@ -279,6 +279,17 @@ struct hardware_msg_data
int y;
unsigned int hw_id;
unsigned int flags;
union
{
int type;
struct
{
int type;
int x;
int y;
unsigned int data;
} mouse;
} rawinput;
};
struct callback_msg_data
@ -5672,6 +5683,6 @@ union generic_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 */

View File

@ -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 );

View File

@ -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

View File

@ -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

View File

@ -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 */
@ -2970,10 +3012,14 @@ DECL_HANDLER(update_rawinput_devices)
{
const struct rawinput_device *devices = get_req_data();
unsigned int device_count = get_req_data_size() / sizeof (*devices);
const struct rawinput_device_entry *e;
unsigned int i;
for (i = 0; i < device_count; ++i)
{
update_rawinput_device(&devices[i]);
}
e = find_rawinput_device( 1, 2 );
current->process->rawinput_mouse = e ? &e->device : NULL;
}