1
0
mirror of https://github.com/wine-mirror/wine synced 2024-06-29 06:14:34 +00:00

server: Move the desktop keystate to shared memory.

Based on a patch by Huw Davies.
This commit is contained in:
Rémi Bernon 2024-06-21 00:11:11 +02:00 committed by Alexandre Julliard
parent d5b4458c8d
commit 2eeb4d5192
4 changed files with 55 additions and 32 deletions

View File

@ -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 ### */

View File

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

View File

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

View File

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