[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