Skip to content

Commit 9a814b4

Browse files
committed
Wayland: Unify key handling logic
Previously we had different logic for direct key presses and client-side key repetition, as one queued up input events and the other dispatched them directly (client-side key repetition is run from the main thread). I kinda figured out that this difference doesn't really matter, as we can queue them up before the thread message dispatching logic. That's exactly what we do now, which allows us to make a single method for both of them, making the code much clearer and simplifying future maintenance. This patch also includes a tiny fixup in the compose logic, which checks for the validity of the generated key event before actually working with it. The cases in which we can end up with an invalid reference are very few, so it's not the end of the world, but it's still absolutely a good idea to check, to avoid nasty surprises down the line.
1 parent 3a97723 commit 9a814b4

File tree

3 files changed

+73
-91
lines changed

3 files changed

+73
-91
lines changed

platform/linuxbsd/wayland/display_server_wayland.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1695,6 +1695,8 @@ void DisplayServerWayland::try_suspend() {
16951695
void DisplayServerWayland::process_events() {
16961696
wayland_thread.mutex.lock();
16971697

1698+
wayland_thread.keyboard_echo_keys();
1699+
16981700
while (wayland_thread.has_message()) {
16991701
Ref<WaylandThread::Message> msg = wayland_thread.pop_message();
17001702

@@ -1837,8 +1839,6 @@ void DisplayServerWayland::process_events() {
18371839
}
18381840
}
18391841

1840-
wayland_thread.keyboard_echo_keys();
1841-
18421842
switch (suspend_state) {
18431843
case SuspendState::NONE: {
18441844
bool emulate_vsync = false;

platform/linuxbsd/wayland/wayland_thread.cpp

Lines changed: 69 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -302,6 +302,73 @@ Ref<InputEventKey> WaylandThread::_seat_state_get_unstuck_key_event(SeatState *p
302302
return event;
303303
}
304304

305+
void WaylandThread::_seat_state_handle_xkb_keycode(SeatState *p_ss, xkb_keycode_t p_xkb_keycode, bool p_pressed, bool p_echo) {
306+
ERR_FAIL_NULL(p_ss);
307+
308+
WaylandThread *wayland_thread = p_ss->wayland_thread;
309+
ERR_FAIL_NULL(wayland_thread);
310+
311+
Key last_key = Key::NONE;
312+
xkb_compose_status compose_status = xkb_compose_state_get_status(p_ss->xkb_compose_state);
313+
314+
if (p_pressed) {
315+
xkb_keysym_t keysym = xkb_state_key_get_one_sym(p_ss->xkb_state, p_xkb_keycode);
316+
xkb_compose_feed_result compose_result = xkb_compose_state_feed(p_ss->xkb_compose_state, keysym);
317+
compose_status = xkb_compose_state_get_status(p_ss->xkb_compose_state);
318+
319+
if (compose_result == XKB_COMPOSE_FEED_ACCEPTED && compose_status == XKB_COMPOSE_COMPOSED) {
320+
// We need to generate multiple key events to report the composed result, One
321+
// per character.
322+
char str_xkb[256] = {};
323+
int str_xkb_size = xkb_compose_state_get_utf8(p_ss->xkb_compose_state, str_xkb, 255);
324+
325+
String decoded_str = String::utf8(str_xkb, str_xkb_size);
326+
for (int i = 0; i < decoded_str.length(); ++i) {
327+
Ref<InputEventKey> k = _seat_state_get_key_event(p_ss, p_xkb_keycode, p_pressed);
328+
if (k.is_null()) {
329+
continue;
330+
}
331+
332+
k->set_unicode(decoded_str[i]);
333+
k->set_echo(p_echo);
334+
335+
Ref<InputEventMessage> msg;
336+
msg.instantiate();
337+
msg->event = k;
338+
wayland_thread->push_message(msg);
339+
340+
last_key = k->get_keycode();
341+
}
342+
}
343+
}
344+
345+
if (last_key == Key::NONE && compose_status == XKB_COMPOSE_NOTHING) {
346+
// If we continued with other compose status (e.g. XKB_COMPOSE_COMPOSING) we
347+
// would get the composing keys _and_ the result.
348+
Ref<InputEventKey> k = _seat_state_get_key_event(p_ss, p_xkb_keycode, p_pressed);
349+
if (k.is_valid()) {
350+
k->set_echo(p_echo);
351+
352+
Ref<InputEventMessage> msg;
353+
msg.instantiate();
354+
msg->event = k;
355+
wayland_thread->push_message(msg);
356+
357+
last_key = k->get_keycode();
358+
}
359+
}
360+
361+
if (last_key != Key::NONE) {
362+
Ref<InputEventKey> uk = _seat_state_get_unstuck_key_event(p_ss, p_xkb_keycode, p_pressed, last_key);
363+
if (uk.is_valid()) {
364+
Ref<InputEventMessage> u_msg;
365+
u_msg.instantiate();
366+
u_msg->event = uk;
367+
wayland_thread->push_message(u_msg);
368+
}
369+
}
370+
}
371+
305372
void WaylandThread::_set_current_seat(struct wl_seat *p_seat) {
306373
if (p_seat == wl_seat_current) {
307374
return;
@@ -2198,16 +2265,10 @@ void WaylandThread::_wl_keyboard_on_key(void *data, struct wl_keyboard *wl_keybo
21982265
return;
21992266
}
22002267

2201-
WaylandThread *wayland_thread = ss->wayland_thread;
2202-
ERR_FAIL_NULL(wayland_thread);
2203-
22042268
// We have to add 8 to the scancode to get an XKB-compatible keycode.
22052269
xkb_keycode_t xkb_keycode = key + 8;
22062270

22072271
bool pressed = state & WL_KEYBOARD_KEY_STATE_PRESSED;
2208-
Key last_key = Key::NONE;
2209-
2210-
xkb_compose_status compose_status = xkb_compose_state_get_status(ss->xkb_compose_state);
22112272

22122273
if (pressed) {
22132274
if (xkb_keymap_key_repeats(ss->xkb_keymap, xkb_keycode)) {
@@ -2216,58 +2277,11 @@ void WaylandThread::_wl_keyboard_on_key(void *data, struct wl_keyboard *wl_keybo
22162277
}
22172278

22182279
ss->last_key_pressed_serial = serial;
2219-
2220-
xkb_keysym_t keysym = xkb_state_key_get_one_sym(ss->xkb_state, xkb_keycode);
2221-
xkb_compose_feed_result compose_result = xkb_compose_state_feed(ss->xkb_compose_state, keysym);
2222-
compose_status = xkb_compose_state_get_status(ss->xkb_compose_state);
2223-
2224-
if (compose_result == XKB_COMPOSE_FEED_ACCEPTED && compose_status == XKB_COMPOSE_COMPOSED) {
2225-
// We need to generate multiple key events to report the composed result, One
2226-
// per character.
2227-
char str_xkb[256] = {};
2228-
int str_xkb_size = xkb_compose_state_get_utf8(ss->xkb_compose_state, str_xkb, 255);
2229-
2230-
String decoded_str = String::utf8(str_xkb, str_xkb_size);
2231-
for (int i = 0; i < decoded_str.length(); ++i) {
2232-
Ref<InputEventKey> k = _seat_state_get_key_event(ss, xkb_keycode, pressed);
2233-
k->set_unicode(decoded_str[i]);
2234-
2235-
Ref<InputEventMessage> msg;
2236-
msg.instantiate();
2237-
msg->event = k;
2238-
wayland_thread->push_message(msg);
2239-
2240-
last_key = k->get_keycode();
2241-
}
2242-
}
22432280
} else if (ss->repeating_keycode == xkb_keycode) {
22442281
ss->repeating_keycode = XKB_KEYCODE_INVALID;
22452282
}
22462283

2247-
if (last_key == Key::NONE && compose_status == XKB_COMPOSE_NOTHING) {
2248-
// If we continued with other compose status (e.g. XKB_COMPOSE_COMPOSING) we
2249-
// would get the composing keys _and_ the result.
2250-
Ref<InputEventKey> k = _seat_state_get_key_event(ss, xkb_keycode, pressed);
2251-
2252-
if (k.is_valid()) {
2253-
Ref<InputEventMessage> msg;
2254-
msg.instantiate();
2255-
msg->event = k;
2256-
wayland_thread->push_message(msg);
2257-
2258-
last_key = k->get_keycode();
2259-
}
2260-
}
2261-
2262-
if (last_key != Key::NONE) {
2263-
Ref<InputEventKey> uk = _seat_state_get_unstuck_key_event(ss, xkb_keycode, pressed, last_key);
2264-
if (uk.is_valid()) {
2265-
Ref<InputEventMessage> u_msg;
2266-
u_msg.instantiate();
2267-
u_msg->event = uk;
2268-
wayland_thread->push_message(u_msg);
2269-
}
2270-
}
2284+
_seat_state_handle_xkb_keycode(ss, xkb_keycode, pressed);
22712285
}
22722286

22732287
void WaylandThread::_wl_keyboard_on_modifiers(void *data, struct wl_keyboard *wl_keyboard, uint32_t serial, uint32_t mods_depressed, uint32_t mods_latched, uint32_t mods_locked, uint32_t group) {
@@ -3683,42 +3697,8 @@ void WaylandThread::seat_state_echo_keys(SeatState *p_ss) {
36833697

36843698
int keys_amount = (ticks_delta / p_ss->repeat_key_delay_msec);
36853699

3686-
xkb_compose_status compose_status = xkb_compose_state_get_status(p_ss->xkb_compose_state);
3687-
3688-
Key last_key = Key::NONE;
36893700
for (int i = 0; i < keys_amount; i++) {
3690-
xkb_keysym_t keysym = xkb_state_key_get_one_sym(p_ss->xkb_state, p_ss->repeating_keycode);
3691-
xkb_compose_feed_result compose_result = xkb_compose_state_feed(p_ss->xkb_compose_state, keysym);
3692-
compose_status = xkb_compose_state_get_status(p_ss->xkb_compose_state);
3693-
3694-
if (compose_result == XKB_COMPOSE_FEED_ACCEPTED && compose_status == XKB_COMPOSE_COMPOSED) {
3695-
// We need to generate multiple key events to report the composed result, One
3696-
// per character.
3697-
char str_xkb[256] = {};
3698-
int str_xkb_size = xkb_compose_state_get_utf8(p_ss->xkb_compose_state, str_xkb, 255);
3699-
3700-
String decoded_str = String::utf8(str_xkb, str_xkb_size);
3701-
for (int j = 0; j < decoded_str.length(); ++j) {
3702-
Ref<InputEventKey> k = _seat_state_get_key_event(p_ss, p_ss->repeating_keycode, true);
3703-
k->set_unicode(decoded_str[j]);
3704-
Input::get_singleton()->parse_input_event(k);
3705-
3706-
last_key = k->get_keycode();
3707-
}
3708-
} else if (compose_status == XKB_COMPOSE_NOTHING) {
3709-
Ref<InputEventKey> k = _seat_state_get_key_event(p_ss, p_ss->repeating_keycode, true);
3710-
k->set_echo(true);
3711-
Input::get_singleton()->parse_input_event(k);
3712-
3713-
last_key = k->get_keycode();
3714-
}
3715-
3716-
if (last_key != Key::NONE) {
3717-
Ref<InputEventKey> uk = _seat_state_get_unstuck_key_event(p_ss, p_ss->repeating_keycode, true, last_key);
3718-
if (uk.is_valid()) {
3719-
Input::get_singleton()->parse_input_event(uk);
3720-
}
3721-
}
3701+
_seat_state_handle_xkb_keycode(p_ss, p_ss->repeating_keycode, true, true);
37223702
}
37233703

37243704
p_ss->last_repeat_msec += ticks_delta - (ticks_delta % p_ss->repeat_key_delay_msec);

platform/linuxbsd/wayland/wayland_thread.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1037,6 +1037,8 @@ class WaylandThread {
10371037
static Ref<InputEventKey> _seat_state_get_key_event(SeatState *p_ss, xkb_keycode_t p_keycode, bool p_pressed);
10381038
static Ref<InputEventKey> _seat_state_get_unstuck_key_event(SeatState *p_ss, xkb_keycode_t p_keycode, bool p_pressed, Key p_key);
10391039

1040+
static void _seat_state_handle_xkb_keycode(SeatState *p_ss, xkb_keycode_t p_xkb_keycode, bool p_pressed, bool p_echo = false);
1041+
10401042
static void _wayland_state_update_cursor();
10411043

10421044
void _set_current_seat(struct wl_seat *p_seat);

0 commit comments

Comments
 (0)