[PATCH 4/4] user32: Add rawinput keyboard support.

Henri Verbeet hverbeet at codeweavers.com
Wed Sep 12 04:30:54 CDT 2012


---
 dlls/user32/message.c |   35 +++++++++++++++
 server/process.c      |    1 +
 server/process.h      |    1 +
 server/protocol.def   |    7 +++
 server/queue.c        |  115 +++++++++++++++++++++++++++++++++----------------
 5 files changed, 121 insertions(+), 38 deletions(-)

diff --git a/dlls/user32/message.c b/dlls/user32/message.c
index 264eeec..2e81e3a 100644
--- a/dlls/user32/message.c
+++ b/dlls/user32/message.c
@@ -52,6 +52,7 @@ WINE_DECLARE_DEBUG_CHANNEL(relay);
 WINE_DECLARE_DEBUG_CHANNEL(key);
 
 #define WINE_MOUSE_HANDLE       ((HANDLE)1)
+#define WINE_KEYBOARD_HANDLE    ((HANDLE)2)
 
 #define WM_NCMOUSEFIRST WM_NCMOUSEMOVE
 #define WM_NCMOUSELAST  (WM_NCMOUSEFIRST+(WM_MOUSELAST-WM_MOUSEFIRST))
@@ -2338,6 +2339,40 @@ static BOOL process_rawinput_message( MSG *msg, const struct hardware_msg_data *
         rawinput->data.mouse.lLastY             = msg_data->rawinput.mouse.y;
         rawinput->data.mouse.ulExtraInformation = msg_data->info;
     }
+    else if (msg_data->rawinput.type == RIM_TYPEKEYBOARD)
+    {
+        rawinput->header.dwSize  = FIELD_OFFSET(RAWINPUT, data) + sizeof(RAWKEYBOARD);
+        rawinput->header.hDevice = WINE_KEYBOARD_HANDLE;
+        rawinput->header.wParam  = 0;
+
+        rawinput->data.keyboard.MakeCode = msg_data->rawinput.kbd.scan;
+        rawinput->data.keyboard.Flags    = msg_data->flags & KEYEVENTF_KEYUP ? RI_KEY_BREAK : RI_KEY_MAKE;
+        if (msg_data->flags & KEYEVENTF_EXTENDEDKEY) rawinput->data.keyboard.Flags |= RI_KEY_E0;
+        rawinput->data.keyboard.Reserved = 0;
+
+        switch (msg_data->rawinput.kbd.vkey)
+        {
+        case VK_LSHIFT:
+        case VK_RSHIFT:
+            rawinput->data.keyboard.VKey   = VK_SHIFT;
+            rawinput->data.keyboard.Flags &= ~RI_KEY_E0;
+            break;
+        case VK_LCONTROL:
+        case VK_RCONTROL:
+            rawinput->data.keyboard.VKey = VK_CONTROL;
+            break;
+        case VK_LMENU:
+        case VK_RMENU:
+            rawinput->data.keyboard.VKey = VK_MENU;
+            break;
+        default:
+            rawinput->data.keyboard.VKey = msg_data->rawinput.kbd.vkey;
+            break;
+        }
+
+        rawinput->data.keyboard.Message          = msg_data->rawinput.kbd.message;
+        rawinput->data.keyboard.ExtraInformation = msg_data->info;
+    }
     else
     {
         FIXME("Unhandled rawinput type %#x.\n", msg_data->rawinput.type);
diff --git a/server/process.c b/server/process.c
index f6fb772..058538f 100644
--- a/server/process.c
+++ b/server/process.c
@@ -334,6 +334,7 @@ struct thread *create_process( int fd, struct thread *parent_thread, int inherit
     process->token           = NULL;
     process->trace_data      = 0;
     process->rawinput_mouse  = NULL;
+    process->rawinput_kbd    = 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 afda3f9..f216ecd 100644
--- a/server/process.h
+++ b/server/process.h
@@ -89,6 +89,7 @@ struct process
     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 */
+    const struct rawinput_device *rawinput_kbd;   /* rawinput keyboard device, if any */
 };
 
 struct process_snapshot
diff --git a/server/protocol.def b/server/protocol.def
index b3ffbc1..a4bb626 100644
--- a/server/protocol.def
+++ b/server/protocol.def
@@ -300,6 +300,13 @@ struct hardware_msg_data
         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 */
diff --git a/server/queue.c b/server/queue.c
index 81331f5..f290c0b 100644
--- a/server/queue.c
+++ b/server/queue.c
@@ -1679,37 +1679,17 @@ static int queue_mouse_message( struct desktop *desktop, user_handle_t win, cons
 static int queue_keyboard_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 char vkey = input->kbd.vkey;
+    unsigned int message_code, time;
     int wait;
 
-    if (!(msg = mem_alloc( sizeof(*msg) ))) return 0;
-    if (!(msg_data = mem_alloc( sizeof(*msg_data) )))
-    {
-        free( msg );
-        return 0;
-    }
-    memset( msg_data, 0, sizeof(*msg_data) );
+    if (!(time = input->kbd.time)) time = get_tick_count();
 
-    msg->type      = MSG_HARDWARE;
-    msg->win       = get_user_full_handle( win );
-    msg->lparam    = (input->kbd.scan << 16) | 1u; /* repeat count */
-    msg->time      = input->kbd.time;
-    msg->result    = NULL;
-    msg->data      = msg_data;
-    msg->data_size = sizeof(*msg_data);
-    msg_data->info = input->kbd.info;
-    if (!msg->time) msg->time = get_tick_count();
-    if (hook_flags & SEND_HWMSG_INJECTED) msg_data->flags = LLKHF_INJECTED;
-
-    if (input->kbd.flags & KEYEVENTF_UNICODE)
+    if (!(input->kbd.flags & KEYEVENTF_UNICODE))
     {
-        msg->wparam = VK_PACKET;
-    }
-    else
-    {
-        unsigned int flags = 0;
         switch (vkey)
         {
         case VK_MENU:
@@ -1728,18 +1708,9 @@ static int queue_keyboard_message( struct desktop *desktop, user_handle_t win, c
             vkey = (input->kbd.flags & KEYEVENTF_EXTENDEDKEY) ? VK_RSHIFT : VK_LSHIFT;
             break;
         }
-        if (input->kbd.flags & KEYEVENTF_EXTENDEDKEY) flags |= KF_EXTENDED;
-        /* FIXME: set KF_DLGMODE and KF_MENUMODE when needed */
-        if (input->kbd.flags & KEYEVENTF_KEYUP) flags |= KF_REPEAT | KF_UP;
-        else if (desktop->keystate[vkey] & 0x80) flags |= KF_REPEAT;
-
-        msg->wparam = vkey;
-        msg->lparam |= flags << 16;
-        msg_data->flags |= (flags & (KF_EXTENDED | KF_ALTDOWN | KF_UP)) >> 8;
     }
 
-    msg->msg = (input->kbd.flags & KEYEVENTF_KEYUP) ? WM_KEYUP : WM_KEYDOWN;
-
+    message_code = (input->kbd.flags & KEYEVENTF_KEYUP) ? WM_KEYUP : WM_KEYDOWN;
     switch (vkey)
     {
     case VK_LMENU:
@@ -1749,14 +1720,14 @@ static int queue_keyboard_message( struct desktop *desktop, user_handle_t win, c
             /* send WM_SYSKEYUP if Alt still pressed and no other key in between */
             /* we use 0x02 as a flag to track if some other SYSKEYUP was sent already */
             if ((desktop->keystate[VK_MENU] & 0x82) != 0x82) break;
-            msg->msg = WM_SYSKEYUP;
+            message_code = WM_SYSKEYUP;
             desktop->keystate[VK_MENU] &= ~0x02;
         }
         else
         {
             /* send WM_SYSKEYDOWN for Alt except with Ctrl */
             if (desktop->keystate[VK_CONTROL] & 0x80) break;
-            msg->msg = WM_SYSKEYDOWN;
+            message_code = WM_SYSKEYDOWN;
             desktop->keystate[VK_MENU] |= 0x02;
         }
         break;
@@ -1766,7 +1737,7 @@ static int queue_keyboard_message( struct desktop *desktop, user_handle_t win, c
         /* send WM_SYSKEYUP on release if Alt still pressed */
         if (!(input->kbd.flags & KEYEVENTF_KEYUP)) break;
         if (!(desktop->keystate[VK_MENU] & 0x80)) break;
-        msg->msg = WM_SYSKEYUP;
+        message_code = WM_SYSKEYUP;
         desktop->keystate[VK_MENU] &= ~0x02;
         break;
 
@@ -1776,10 +1747,76 @@ static int queue_keyboard_message( struct desktop *desktop, user_handle_t win, c
         if (!(desktop->keystate[VK_MENU] & 0x80)) break;
         /* fall through */
     case VK_F10:
-        msg->msg = (input->kbd.flags & KEYEVENTF_KEYUP) ? WM_SYSKEYUP : WM_SYSKEYDOWN;
+        message_code = (input->kbd.flags & KEYEVENTF_KEYUP) ? WM_SYSKEYUP : WM_SYSKEYDOWN;
         desktop->keystate[VK_MENU] &= ~0x02;
         break;
     }
+
+    if ((device = current->process->rawinput_kbd))
+    {
+        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->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 (!(msg = mem_alloc( sizeof(*msg) ))) return 0;
+    if (!(msg_data = mem_alloc( sizeof(*msg_data) )))
+    {
+        free( msg );
+        return 0;
+    }
+    memset( msg_data, 0, sizeof(*msg_data) );
+
+    msg->type      = MSG_HARDWARE;
+    msg->win       = get_user_full_handle( win );
+    msg->msg       = message_code;
+    msg->lparam    = (input->kbd.scan << 16) | 1u; /* repeat count */
+    msg->time      = time;
+    msg->result    = NULL;
+    msg->data      = msg_data;
+    msg->data_size = sizeof(*msg_data);
+    msg_data->info = input->kbd.info;
+    if (hook_flags & SEND_HWMSG_INJECTED) msg_data->flags = LLKHF_INJECTED;
+
+    if (input->kbd.flags & KEYEVENTF_UNICODE)
+    {
+        msg->wparam = VK_PACKET;
+    }
+    else
+    {
+        unsigned int flags = 0;
+        if (input->kbd.flags & KEYEVENTF_EXTENDEDKEY) flags |= KF_EXTENDED;
+        /* FIXME: set KF_DLGMODE and KF_MENUMODE when needed */
+        if (input->kbd.flags & KEYEVENTF_KEYUP) flags |= KF_REPEAT | KF_UP;
+        else if (desktop->keystate[vkey] & 0x80) flags |= KF_REPEAT;
+
+        msg->wparam = vkey;
+        msg->lparam |= flags << 16;
+        msg_data->flags |= (flags & (KF_EXTENDED | KF_ALTDOWN | KF_UP)) >> 8;
+    }
+
     if (!(wait = send_hook_ll_message( desktop, msg, input, sender )))
         queue_hardware_message( desktop, msg, 1 );
 
@@ -3022,4 +3059,6 @@ DECL_HANDLER(update_rawinput_devices)
 
     e = find_rawinput_device( 1, 2 );
     current->process->rawinput_mouse = e ? &e->device : NULL;
+    e = find_rawinput_device( 1, 6 );
+    current->process->rawinput_kbd   = e ? &e->device : NULL;
 }
-- 
1.7.8.6




More information about the wine-patches mailing list