From 2eeb4d5192e808c18e5949cc1c14b51b22fee342 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Bernon?= Date: Fri, 21 Jun 2024 00:11:11 +0200 Subject: [PATCH] server: Move the desktop keystate to shared memory. Based on a patch by Huw Davies. --- include/wine/server_protocol.h | 3 +- server/protocol.def | 1 + server/queue.c | 81 +++++++++++++++++++++------------- server/winstation.c | 2 +- 4 files changed, 55 insertions(+), 32 deletions(-) diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h index 162d00bd65f..f5b1e9f8475 100644 --- a/include/wine/server_protocol.h +++ b/include/wine/server_protocol.h @@ -894,6 +894,7 @@ struct shared_cursor typedef volatile struct { struct shared_cursor cursor; + unsigned char keystate[256]; } desktop_shm_t; typedef volatile union @@ -6568,7 +6569,7 @@ union generic_reply /* ### protocol_version begin ### */ -#define SERVER_PROTOCOL_VERSION 814 +#define SERVER_PROTOCOL_VERSION 815 /* ### protocol_version end ### */ diff --git a/server/protocol.def b/server/protocol.def index 0592dddaa97..11539654dc3 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -910,6 +910,7 @@ struct shared_cursor typedef volatile struct { struct shared_cursor cursor; /* global cursor information */ + unsigned char keystate[256]; /* asynchronous key state */ } desktop_shm_t; typedef volatile union diff --git a/server/queue.c b/server/queue.c index 699a8fdf248..a7814c83737 100644 --- a/server/queue.c +++ b/server/queue.c @@ -278,7 +278,8 @@ static struct thread_input *create_thread_input( struct thread *thread ) release_object( input ); return NULL; } - memcpy( input->desktop_keystate, input->desktop->keystate, sizeof(input->desktop_keystate) ); + memcpy( input->desktop_keystate, (const void *)input->desktop->shared->keystate, + sizeof(input->desktop_keystate) ); } return input; } @@ -338,12 +339,16 @@ void free_msg_queue( struct thread *thread ) /* synchronize thread input keystate with the desktop */ static void sync_input_keystate( struct thread_input *input ) { + const desktop_shm_t *desktop_shm; int i; + if (!input->desktop || input->keystate_lock) return; + desktop_shm = input->desktop->shared; + for (i = 0; i < sizeof(input->keystate); ++i) { - if (input->desktop_keystate[i] == input->desktop->keystate[i]) continue; - input->keystate[i] = input->desktop_keystate[i] = input->desktop->keystate[i]; + if (input->desktop_keystate[i] == desktop_shm->keystate[i]) continue; + input->keystate[i] = input->desktop_keystate[i] = desktop_shm->keystate[i]; } } @@ -1470,7 +1475,7 @@ static struct timer *set_timer( struct msg_queue *queue, unsigned int rate ) } /* change the input key state for a given key */ -static void set_input_key_state( unsigned char *keystate, unsigned char key, unsigned char down ) +static void set_input_key_state( volatile unsigned char *keystate, unsigned char key, unsigned char down ) { if (down) { @@ -1481,7 +1486,7 @@ static void set_input_key_state( unsigned char *keystate, unsigned char key, uns } /* update the input key state for a keyboard message */ -static void update_key_state( unsigned char *keystate, unsigned int msg, +static void update_key_state( volatile unsigned char *keystate, unsigned int msg, lparam_t wparam, int desktop ) { unsigned char key, down = 0, down_val = desktop ? 0xc0 : 0x80; @@ -1550,7 +1555,11 @@ static void update_thread_input_key_state( struct thread_input *input, unsigned static void update_desktop_key_state( struct desktop *desktop, unsigned int msg, lparam_t wparam ) { - update_key_state( desktop->keystate, msg, wparam, 1 ); + SHARED_WRITE_BEGIN( desktop->shared, desktop_shm_t ) + { + update_key_state( shared->keystate, msg, wparam, 1 ); + } + SHARED_WRITE_END; } /* release the hardware message currently being processed by the given thread */ @@ -1585,15 +1594,16 @@ static void release_hardware_message( struct msg_queue *queue, unsigned int hw_i static int queue_hotkey_message( struct desktop *desktop, struct message *msg ) { + const desktop_shm_t *desktop_shm = desktop->shared; struct hotkey *hotkey; unsigned int modifiers = 0; if (msg->msg != WM_KEYDOWN && msg->msg != WM_SYSKEYDOWN) return 0; - if (desktop->keystate[VK_MENU] & 0x80) modifiers |= MOD_ALT; - if (desktop->keystate[VK_CONTROL] & 0x80) modifiers |= MOD_CONTROL; - if (desktop->keystate[VK_SHIFT] & 0x80) modifiers |= MOD_SHIFT; - if ((desktop->keystate[VK_LWIN] & 0x80) || (desktop->keystate[VK_RWIN] & 0x80)) modifiers |= MOD_WIN; + if (desktop_shm->keystate[VK_MENU] & 0x80) modifiers |= MOD_ALT; + if (desktop_shm->keystate[VK_CONTROL] & 0x80) modifiers |= MOD_CONTROL; + if (desktop_shm->keystate[VK_SHIFT] & 0x80) modifiers |= MOD_SHIFT; + if ((desktop_shm->keystate[VK_LWIN] & 0x80) || (desktop_shm->keystate[VK_RWIN] & 0x80)) modifiers |= MOD_WIN; LIST_FOR_EACH_ENTRY( hotkey, &desktop->hotkeys, struct hotkey, entry ) { @@ -1713,7 +1723,7 @@ static void queue_hardware_message( struct desktop *desktop, struct message *msg { case QS_KEY: if (queue_hotkey_message( desktop, msg )) return; - if (desktop->keystate[VK_MENU] & 0x80) msg->lparam |= KF_ALTDOWN << 16; + if (desktop_shm->keystate[VK_MENU] & 0x80) msg->lparam |= KF_ALTDOWN << 16; if (msg->wparam == VK_SHIFT || msg->wparam == VK_LSHIFT || msg->wparam == VK_RSHIFT) msg->lparam &= ~(KF_EXTENDED << 16); break; @@ -1722,13 +1732,13 @@ static void queue_hardware_message( struct desktop *desktop, struct message *msg /* fallthrough */ case QS_MOUSEBUTTON: if (update_desktop_cursor_pos( desktop, msg->win, msg->x, msg->y )) always_queue = 1; - if (desktop->keystate[VK_LBUTTON] & 0x80) msg->wparam |= MK_LBUTTON; - if (desktop->keystate[VK_MBUTTON] & 0x80) msg->wparam |= MK_MBUTTON; - if (desktop->keystate[VK_RBUTTON] & 0x80) msg->wparam |= MK_RBUTTON; - if (desktop->keystate[VK_SHIFT] & 0x80) msg->wparam |= MK_SHIFT; - if (desktop->keystate[VK_CONTROL] & 0x80) msg->wparam |= MK_CONTROL; - if (desktop->keystate[VK_XBUTTON1] & 0x80) msg->wparam |= MK_XBUTTON1; - if (desktop->keystate[VK_XBUTTON2] & 0x80) msg->wparam |= MK_XBUTTON2; + if (desktop_shm->keystate[VK_LBUTTON] & 0x80) msg->wparam |= MK_LBUTTON; + if (desktop_shm->keystate[VK_MBUTTON] & 0x80) msg->wparam |= MK_MBUTTON; + if (desktop_shm->keystate[VK_RBUTTON] & 0x80) msg->wparam |= MK_RBUTTON; + if (desktop_shm->keystate[VK_SHIFT] & 0x80) msg->wparam |= MK_SHIFT; + if (desktop_shm->keystate[VK_CONTROL] & 0x80) msg->wparam |= MK_CONTROL; + if (desktop_shm->keystate[VK_XBUTTON1] & 0x80) msg->wparam |= MK_XBUTTON1; + if (desktop_shm->keystate[VK_XBUTTON2] & 0x80) msg->wparam |= MK_XBUTTON2; break; } msg->x = desktop_shm->cursor.x; @@ -2134,6 +2144,7 @@ static void stop_key_repeat( struct desktop *desktop ) static int queue_keyboard_message( struct desktop *desktop, user_handle_t win, const hw_input_t *input, unsigned int origin, struct msg_queue *sender, int repeat ) { + const desktop_shm_t *desktop_shm = desktop->shared; struct hw_msg_source source = { IMDT_KEYBOARD, origin }; struct hardware_msg_data *msg_data; struct message *msg; @@ -2180,14 +2191,14 @@ static int queue_keyboard_message( struct desktop *desktop, user_handle_t win, c if (input->kbd.flags & KEYEVENTF_KEYUP) { /* send WM_SYSKEYUP if Alt still pressed and no other key in between */ - if (!(desktop->keystate[VK_MENU] & 0x80) || !desktop->alt_pressed) break; + if (!(desktop_shm->keystate[VK_MENU] & 0x80) || !desktop->alt_pressed) break; message_code = WM_SYSKEYUP; desktop->alt_pressed = 0; } else { /* send WM_SYSKEYDOWN for Alt except with Ctrl */ - if (desktop->keystate[VK_CONTROL] & 0x80) break; + if (desktop_shm->keystate[VK_CONTROL] & 0x80) break; message_code = WM_SYSKEYDOWN; desktop->alt_pressed = 1; } @@ -2197,15 +2208,15 @@ static int queue_keyboard_message( struct desktop *desktop, user_handle_t win, c 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; + if (!(desktop_shm->keystate[VK_MENU] & 0x80)) break; message_code = WM_SYSKEYUP; desktop->alt_pressed = 0; 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; + if (desktop_shm->keystate[VK_CONTROL] & 0x80) break; + if (!(desktop_shm->keystate[VK_MENU] & 0x80)) break; /* fall through */ case VK_F10: message_code = (input->kbd.flags & KEYEVENTF_KEYUP) ? WM_SYSKEYUP : WM_SYSKEYDOWN; @@ -2281,7 +2292,7 @@ static int queue_keyboard_message( struct desktop *desktop, user_handle_t win, c 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; + else if (desktop_shm->keystate[vkey] & 0x80) flags |= KF_REPEAT; lparam &= 0xff0000; /* mask off scan code high bits for non-unicode input */ msg_data->flags |= (flags & (KF_EXTENDED | KF_ALTDOWN | KF_UP)) >> 8; @@ -3523,10 +3534,14 @@ DECL_HANDLER(get_key_state) if (!(desktop = get_thread_desktop( current, 0 ))) return; if (req->key >= 0) { - reply->state = desktop->keystate[req->key & 0xff]; - desktop->keystate[req->key & 0xff] &= ~0x40; + SHARED_WRITE_BEGIN( desktop->shared, desktop_shm_t ) + { + reply->state = shared->keystate[req->key & 0xff]; + shared->keystate[req->key & 0xff] &= ~0x40; + } + SHARED_WRITE_END; } - set_reply_data( desktop->keystate, size ); + set_reply_data( (const void *)desktop->shared->keystate, size ); release_object( desktop ); } else @@ -3546,15 +3561,21 @@ DECL_HANDLER(get_key_state) /* set queue keyboard state for current thread */ DECL_HANDLER(set_key_state) { - struct desktop *desktop; struct msg_queue *queue = get_current_queue(); + struct desktop *desktop = queue->input->desktop; data_size_t size = min( 256, get_req_data_size() ); memcpy( queue->input->keystate, get_req_data(), size ); - memcpy( queue->input->desktop_keystate, queue->input->desktop->keystate, 256 ); + memcpy( queue->input->desktop_keystate, (const void *)desktop->shared->keystate, + sizeof(queue->input->desktop_keystate) ); + if (req->async && (desktop = get_thread_desktop( current, 0 ))) { - memcpy( desktop->keystate, get_req_data(), size ); + SHARED_WRITE_BEGIN( desktop->shared, desktop_shm_t ) + { + memcpy( (void *)shared->keystate, get_req_data(), size ); + } + SHARED_WRITE_END; release_object( desktop ); } } diff --git a/server/winstation.c b/server/winstation.c index 63bdc3389de..45c7defa1f7 100644 --- a/server/winstation.c +++ b/server/winstation.c @@ -295,7 +295,6 @@ static struct desktop *create_desktop( const struct unicode_str *name, unsigned desktop->clip_flags = 0; desktop->cursor_win = 0; desktop->alt_pressed = 0; - memset( desktop->keystate, 0, sizeof(desktop->keystate) ); memset( &desktop->key_repeat, 0, sizeof(desktop->key_repeat) ); list_add_tail( &winstation->desktops, &desktop->entry ); list_init( &desktop->hotkeys ); @@ -316,6 +315,7 @@ static struct desktop *create_desktop( const struct unicode_str *name, unsigned shared->cursor.clip.top = 0; shared->cursor.clip.right = 0; shared->cursor.clip.bottom = 0; + memset( (void *)shared->keystate, 0, sizeof(shared->keystate) ); } SHARED_WRITE_END; }