swc

Unnamed repository; edit this file 'description' to name the repository.
git clone git://git.nihaljere.xyz/swc
Log | Files | Refs | README | LICENSE

commit e8b0c05ef1e4139c67603c0f6c6033d71b1c0077
parent f0477fa60d0c1b4b8434b8cc0db09492aac4c9f4
Author: Michael Forney <mforney@mforney.org>
Date:   Fri,  6 Dec 2013 02:10:33 -0800

Refactor swc_keyboard_handle_key

- Move key and modifier sending to it's own keyboard handler.
- Make keyboard handlers keep track of they keys they've handled. This
  fixes a couple of issues:
    * Surfaces no longer receive spurious key release events if they are
      focused due to a key binding.
    * Since xwayland sends key press events for every key pressed when
      the keyboard enters a surface, keys pressed because they were part
      of a key bindings were being sent to X clients.
- Use a list of keyboard handlers in case other handlers are added
  later.

Diffstat:
Mlibswc/bindings.c | 2+-
Mlibswc/bindings.h | 2+-
Mlibswc/keyboard.c | 122+++++++++++++++++++++++++++++++++++++++++++++++++------------------------------
Mlibswc/keyboard.h | 11++++++-----
Mlibswc/swc.c | 3++-
5 files changed, 86 insertions(+), 54 deletions(-)

diff --git a/libswc/bindings.c b/libswc/bindings.c @@ -75,7 +75,7 @@ static bool handle_key(struct swc_keyboard * keyboard, uint32_t time, return false; } -static const struct swc_keyboard_handler binding_handler = { +static struct swc_keyboard_handler binding_handler = { .key = &handle_key, }; diff --git a/libswc/bindings.h b/libswc/bindings.h @@ -28,7 +28,7 @@ struct swc_bindings_global { - const struct swc_keyboard_handler * keyboard_handler; + struct swc_keyboard_handler * keyboard_handler; }; bool swc_bindings_initialize(); diff --git a/libswc/keyboard.c b/libswc/keyboard.c @@ -46,7 +46,7 @@ static void enter(struct swc_input_focus_handler * handler, serial = wl_display_next_serial(display); wl_keyboard_send_enter(resource, serial, surface->resource, - &keyboard->keys); + &keyboard->client_handler.keys); } static void leave(struct swc_input_focus_handler * handler, @@ -63,6 +63,45 @@ static void leave(struct swc_input_focus_handler * handler, wl_keyboard_send_leave(resource, serial, surface->resource); } +static bool client_handle_key(struct swc_keyboard * keyboard, uint32_t time, + uint32_t key, uint32_t state) +{ + struct wl_client * client; + struct wl_display * display; + uint32_t serial; + + if (!keyboard->focus.resource) + return true; + + client = wl_resource_get_client(keyboard->focus.resource); + display = wl_client_get_display(client); + serial = wl_display_next_serial(display); + wl_keyboard_send_key(keyboard->focus.resource, serial, time, key, state); + + return true; +} + +static bool client_handle_modifiers + (struct swc_keyboard * keyboard, + const struct swc_keyboard_modifier_state * state) +{ + struct wl_client * client; + struct wl_display * display; + uint32_t serial; + + if (!keyboard->focus.resource) + return false; + + client = wl_resource_get_client(keyboard->focus.resource); + display = wl_client_get_display(client); + serial = wl_display_next_serial(display); + wl_keyboard_send_modifiers(keyboard->focus.resource, serial, + state->depressed, state->locked, state->latched, + state->group); + + return true; +} + bool swc_keyboard_initialize(struct swc_keyboard * keyboard) { if (!swc_xkb_initialize(&keyboard->xkb)) @@ -74,11 +113,15 @@ bool swc_keyboard_initialize(struct swc_keyboard * keyboard) if (!swc_input_focus_initialize(&keyboard->focus, &keyboard->focus_handler)) goto error1; - wl_array_init(&keyboard->keys); keyboard->modifier_state = (struct swc_keyboard_modifier_state) { 0 }; keyboard->modifiers = 0; keyboard->focus_handler.enter = &enter; keyboard->focus_handler.leave = &leave; + keyboard->client_handler.key = &client_handle_key; + keyboard->client_handler.modifiers = &client_handle_modifiers; + wl_array_init(&keyboard->client_handler.keys); + wl_list_init(&keyboard->handlers); + wl_list_insert(&keyboard->handlers, &keyboard->client_handler.link); swc_input_focus_initialize(&keyboard->focus, &keyboard->focus_handler); @@ -92,7 +135,7 @@ bool swc_keyboard_initialize(struct swc_keyboard * keyboard) void swc_keyboard_finish(struct swc_keyboard * keyboard) { - wl_array_release(&keyboard->keys); + wl_array_release(&keyboard->client_handler.keys); swc_input_focus_finish(&keyboard->focus); swc_xkb_finish(&keyboard->xkb); } @@ -135,52 +178,43 @@ void swc_keyboard_handle_key(struct swc_keyboard * keyboard, uint32_t time, { uint32_t * pressed_key; struct swc_keyboard_modifier_state modifier_state; - struct wl_display * display; - uint32_t serial; enum xkb_key_direction direction; struct swc_xkb * xkb = &keyboard->xkb; + struct swc_keyboard_handler * handler; - if (keyboard->focus.resource) + /* First handle key events associated with a particular handler. */ + wl_list_for_each(handler, &keyboard->handlers, link) { - struct wl_client * client - = wl_resource_get_client(keyboard->focus.resource); - display = wl_client_get_display(client); - } - - /* Update keyboard state state */ - wl_array_for_each(pressed_key, &keyboard->keys) - { - if (*pressed_key == key) + wl_array_for_each(pressed_key, &handler->keys) { - /* Ignore repeat events. */ - if (state == WL_KEYBOARD_KEY_STATE_PRESSED) - return; - else + if (*pressed_key == key) { - /* Remove the key from the array */ - swc_array_remove(&keyboard->keys, pressed_key, sizeof key); - break; + /* Ignore repeat events. */ + if (state == WL_KEYBOARD_KEY_STATE_PRESSED) + return; + + swc_array_remove(&handler->keys, + pressed_key, sizeof *pressed_key); + if (handler->key) + handler->key(keyboard, time, key, state); + goto update_xkb_state; } } } - if (state == WL_KEYBOARD_KEY_STATE_PRESSED) - { - pressed_key = wl_array_add(&keyboard->keys, sizeof key); - *pressed_key = key; - } - - /* Check if the key event is handled by the keyboard handler. */ - if ((!keyboard->handler || !keyboard->handler->key - || !keyboard->handler->key(keyboard, time, key, state)) - && keyboard->focus.resource) + /* Go through handlers again to see if any will accept this key event. */ + wl_list_for_each(handler, &keyboard->handlers, link) { - serial = wl_display_next_serial(display); - wl_keyboard_send_key(keyboard->focus.resource, serial, time, - key, state); + if (handler->key && handler->key(keyboard, time, key, state)) + { + if (state == WL_KEYBOARD_KEY_STATE_PRESSED) + *((uint32_t *) wl_array_add(&handler->keys, sizeof key)) = key; + break; + } } /* Update XKB state. */ + update_xkb_state: direction = state == WL_KEYBOARD_KEY_STATE_PRESSED ? XKB_KEY_DOWN : XKB_KEY_UP; xkb_state_update_key(xkb->state, XKB_KEY(key), direction); @@ -204,17 +238,6 @@ void swc_keyboard_handle_key(struct swc_keyboard * keyboard, uint32_t time, /* Update keyboard modifier state. */ keyboard->modifier_state = modifier_state; - - if (keyboard->focus.resource) - { - serial = wl_display_next_serial(display); - wl_keyboard_send_modifiers - (keyboard->focus.resource, serial, modifier_state.depressed, - modifier_state.latched, modifier_state.locked, - modifier_state.group); - } - - keyboard->modifiers = 0; if (mods_active & (1 << keyboard->xkb.indices.ctrl)) keyboard->modifiers |= SWC_MOD_CTRL; @@ -224,6 +247,13 @@ void swc_keyboard_handle_key(struct swc_keyboard * keyboard, uint32_t time, keyboard->modifiers |= SWC_MOD_LOGO; if (mods_active & (1 << keyboard->xkb.indices.shift)) keyboard->modifiers |= SWC_MOD_SHIFT; + + /* Run any modifier handlers. */ + wl_list_for_each(handler, &keyboard->handlers, link) + { + if (handler->modifiers) + handler->modifiers(keyboard, &modifier_state); + } } } diff --git a/libswc/keyboard.h b/libswc/keyboard.h @@ -47,20 +47,21 @@ struct swc_keyboard_handler uint32_t key, uint32_t state); bool (* modifiers)(struct swc_keyboard * keyboard, const struct swc_keyboard_modifier_state * state); + + struct wl_array keys; + struct wl_list link; }; struct swc_keyboard { struct swc_input_focus focus; struct swc_input_focus_handler focus_handler; - - const struct swc_keyboard_handler * handler; - struct swc_xkb xkb; - struct wl_array keys; - struct swc_keyboard_modifier_state modifier_state; + struct wl_list handlers; + struct swc_keyboard_handler client_handler; + struct swc_keyboard_modifier_state modifier_state; uint32_t modifiers; }; diff --git a/libswc/swc.c b/libswc/swc.c @@ -52,7 +52,8 @@ static void setup_compositor() pixman_region32_t pointer_region; struct swc_output * output; - swc.seat->keyboard->handler = swc.bindings->keyboard_handler; + wl_list_insert(&swc.seat->keyboard->handlers, + &swc.bindings->keyboard_handler->link); swc.seat->pointer->handler = &compositor.pointer_handler; wl_signal_add(&swc.seat->pointer->focus.event_signal, swc_window_enter_listener);