user32: Add rawinput keyboard support.

This commit is contained in:
Henri Verbeet 2012-09-12 11:30:54 +02:00 committed by Alexandre Julliard
parent 706ece827b
commit c6fcc0255c
6 changed files with 157 additions and 67 deletions

View File

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

View File

@ -283,6 +283,13 @@ struct hardware_msg_data
{
int type;
struct
{
int type;
unsigned int message;
unsigned short vkey;
unsigned short scan;
} kbd;
struct
{
int type;
int x;
@ -5683,6 +5690,6 @@ union generic_reply
struct set_suspend_context_reply set_suspend_context_reply;
};
#define SERVER_PROTOCOL_VERSION 434
#define SERVER_PROTOCOL_VERSION 435
#endif /* __WINE_WINE_SERVER_PROTOCOL_H */

View File

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

View File

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

View File

@ -299,6 +299,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 */

View File

@ -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,6 +1708,105 @@ static int queue_keyboard_message( struct desktop *desktop, user_handle_t win, c
vkey = (input->kbd.flags & KEYEVENTF_EXTENDEDKEY) ? VK_RSHIFT : VK_LSHIFT;
break;
}
}
message_code = (input->kbd.flags & KEYEVENTF_KEYUP) ? WM_KEYUP : WM_KEYDOWN;
switch (vkey)
{
case VK_LMENU:
case VK_RMENU:
if (input->kbd.flags & KEYEVENTF_KEYUP)
{
/* 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;
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;
message_code = WM_SYSKEYDOWN;
desktop->keystate[VK_MENU] |= 0x02;
}
break;
case VK_LCONTROL:
case VK_RCONTROL:
/* send WM_SYSKEYUP on release if Alt still pressed */
if (!(input->kbd.flags & KEYEVENTF_KEYUP)) break;
if (!(desktop->keystate[VK_MENU] & 0x80)) break;
message_code = WM_SYSKEYUP;
desktop->keystate[VK_MENU] &= ~0x02;
break;
default:
/* send WM_SYSKEY for Alt-anykey and for F10 */
if (desktop->keystate[VK_CONTROL] & 0x80) break;
if (!(desktop->keystate[VK_MENU] & 0x80)) break;
/* fall through */
case VK_F10:
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;
@ -1738,48 +1817,6 @@ static int queue_keyboard_message( struct desktop *desktop, user_handle_t win, c
msg_data->flags |= (flags & (KF_EXTENDED | KF_ALTDOWN | KF_UP)) >> 8;
}
msg->msg = (input->kbd.flags & KEYEVENTF_KEYUP) ? WM_KEYUP : WM_KEYDOWN;
switch (vkey)
{
case VK_LMENU:
case VK_RMENU:
if (input->kbd.flags & KEYEVENTF_KEYUP)
{
/* 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;
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;
desktop->keystate[VK_MENU] |= 0x02;
}
break;
case VK_LCONTROL:
case VK_RCONTROL:
/* 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;
desktop->keystate[VK_MENU] &= ~0x02;
break;
default:
/* send WM_SYSKEY for Alt-anykey and for F10 */
if (desktop->keystate[VK_CONTROL] & 0x80) break;
if (!(desktop->keystate[VK_MENU] & 0x80)) break;
/* fall through */
case VK_F10:
msg->msg = (input->kbd.flags & KEYEVENTF_KEYUP) ? WM_SYSKEYUP : WM_SYSKEYDOWN;
desktop->keystate[VK_MENU] &= ~0x02;
break;
}
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;
}