commit e8b0c05

Michael Forney  ·  2013-12-06 10:10:33 +0000 UTC
parent f0477fa
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.
5 files changed,  +86, -54
+1, -1
1@@ -75,7 +75,7 @@ static bool handle_key(struct swc_keyboard * keyboard, uint32_t time,
2     return false;
3 }
4 
5-static const struct swc_keyboard_handler binding_handler = {
6+static struct swc_keyboard_handler binding_handler = {
7     .key = &handle_key,
8 };
9 
+1, -1
1@@ -28,7 +28,7 @@
2 
3 struct swc_bindings_global
4 {
5-    const struct swc_keyboard_handler * keyboard_handler;
6+    struct swc_keyboard_handler * keyboard_handler;
7 };
8 
9 bool swc_bindings_initialize();
+76, -46
  1@@ -46,7 +46,7 @@ static void enter(struct swc_input_focus_handler * handler,
  2     serial = wl_display_next_serial(display);
  3 
  4     wl_keyboard_send_enter(resource, serial, surface->resource,
  5-                           &keyboard->keys);
  6+                           &keyboard->client_handler.keys);
  7 }
  8 
  9 static void leave(struct swc_input_focus_handler * handler,
 10@@ -63,6 +63,45 @@ static void leave(struct swc_input_focus_handler * handler,
 11     wl_keyboard_send_leave(resource, serial, surface->resource);
 12 }
 13 
 14+static bool client_handle_key(struct swc_keyboard * keyboard, uint32_t time,
 15+                              uint32_t key, uint32_t state)
 16+{
 17+    struct wl_client * client;
 18+    struct wl_display * display;
 19+    uint32_t serial;
 20+
 21+    if (!keyboard->focus.resource)
 22+        return true;
 23+
 24+    client = wl_resource_get_client(keyboard->focus.resource);
 25+    display = wl_client_get_display(client);
 26+    serial = wl_display_next_serial(display);
 27+    wl_keyboard_send_key(keyboard->focus.resource, serial, time, key, state);
 28+
 29+    return true;
 30+}
 31+
 32+static bool client_handle_modifiers
 33+    (struct swc_keyboard * keyboard,
 34+     const struct swc_keyboard_modifier_state * state)
 35+{
 36+    struct wl_client * client;
 37+    struct wl_display * display;
 38+    uint32_t serial;
 39+
 40+    if (!keyboard->focus.resource)
 41+        return false;
 42+
 43+    client = wl_resource_get_client(keyboard->focus.resource);
 44+    display = wl_client_get_display(client);
 45+    serial = wl_display_next_serial(display);
 46+    wl_keyboard_send_modifiers(keyboard->focus.resource, serial,
 47+                               state->depressed, state->locked, state->latched,
 48+                               state->group);
 49+
 50+    return true;
 51+}
 52+
 53 bool swc_keyboard_initialize(struct swc_keyboard * keyboard)
 54 {
 55     if (!swc_xkb_initialize(&keyboard->xkb))
 56@@ -74,11 +113,15 @@ bool swc_keyboard_initialize(struct swc_keyboard * keyboard)
 57     if (!swc_input_focus_initialize(&keyboard->focus, &keyboard->focus_handler))
 58         goto error1;
 59 
 60-    wl_array_init(&keyboard->keys);
 61     keyboard->modifier_state = (struct swc_keyboard_modifier_state) { 0 };
 62     keyboard->modifiers = 0;
 63     keyboard->focus_handler.enter = &enter;
 64     keyboard->focus_handler.leave = &leave;
 65+    keyboard->client_handler.key = &client_handle_key;
 66+    keyboard->client_handler.modifiers = &client_handle_modifiers;
 67+    wl_array_init(&keyboard->client_handler.keys);
 68+    wl_list_init(&keyboard->handlers);
 69+    wl_list_insert(&keyboard->handlers, &keyboard->client_handler.link);
 70 
 71     swc_input_focus_initialize(&keyboard->focus, &keyboard->focus_handler);
 72 
 73@@ -92,7 +135,7 @@ bool swc_keyboard_initialize(struct swc_keyboard * keyboard)
 74 
 75 void swc_keyboard_finish(struct swc_keyboard * keyboard)
 76 {
 77-    wl_array_release(&keyboard->keys);
 78+    wl_array_release(&keyboard->client_handler.keys);
 79     swc_input_focus_finish(&keyboard->focus);
 80     swc_xkb_finish(&keyboard->xkb);
 81 }
 82@@ -135,52 +178,43 @@ void swc_keyboard_handle_key(struct swc_keyboard * keyboard, uint32_t time,
 83 {
 84     uint32_t * pressed_key;
 85     struct swc_keyboard_modifier_state modifier_state;
 86-    struct wl_display * display;
 87-    uint32_t serial;
 88     enum xkb_key_direction direction;
 89     struct swc_xkb * xkb = &keyboard->xkb;
 90+    struct swc_keyboard_handler * handler;
 91 
 92-    if (keyboard->focus.resource)
 93+    /* First handle key events associated with a particular handler. */
 94+    wl_list_for_each(handler, &keyboard->handlers, link)
 95     {
 96-        struct wl_client * client
 97-            = wl_resource_get_client(keyboard->focus.resource);
 98-        display = wl_client_get_display(client);
 99-    }
100-
101-    /* Update keyboard state state */
102-    wl_array_for_each(pressed_key, &keyboard->keys)
103-    {
104-        if (*pressed_key == key)
105+        wl_array_for_each(pressed_key, &handler->keys)
106         {
107-            /* Ignore repeat events. */
108-            if (state == WL_KEYBOARD_KEY_STATE_PRESSED)
109-                return;
110-            else
111+            if (*pressed_key == key)
112             {
113-                /* Remove the key from the array */
114-                swc_array_remove(&keyboard->keys, pressed_key, sizeof key);
115-                break;
116+                /* Ignore repeat events. */
117+                if (state == WL_KEYBOARD_KEY_STATE_PRESSED)
118+                    return;
119+
120+                swc_array_remove(&handler->keys,
121+                                 pressed_key, sizeof *pressed_key);
122+                if (handler->key)
123+                    handler->key(keyboard, time, key, state);
124+                goto update_xkb_state;
125             }
126         }
127     }
128 
129-    if (state == WL_KEYBOARD_KEY_STATE_PRESSED)
130-    {
131-        pressed_key = wl_array_add(&keyboard->keys, sizeof key);
132-        *pressed_key = key;
133-    }
134-
135-    /* Check if the key event is handled by the keyboard handler. */
136-    if ((!keyboard->handler || !keyboard->handler->key
137-         || !keyboard->handler->key(keyboard, time, key, state))
138-        && keyboard->focus.resource)
139+    /* Go through handlers again to see if any will accept this key event. */
140+    wl_list_for_each(handler, &keyboard->handlers, link)
141     {
142-        serial = wl_display_next_serial(display);
143-        wl_keyboard_send_key(keyboard->focus.resource, serial, time,
144-                             key, state);
145+        if (handler->key && handler->key(keyboard, time, key, state))
146+        {
147+            if (state == WL_KEYBOARD_KEY_STATE_PRESSED)
148+                *((uint32_t *) wl_array_add(&handler->keys, sizeof key)) = key;
149+            break;
150+        }
151     }
152 
153     /* Update XKB state. */
154+  update_xkb_state:
155     direction = state == WL_KEYBOARD_KEY_STATE_PRESSED ? XKB_KEY_DOWN
156                                                        : XKB_KEY_UP;
157     xkb_state_update_key(xkb->state, XKB_KEY(key), direction);
158@@ -204,17 +238,6 @@ void swc_keyboard_handle_key(struct swc_keyboard * keyboard, uint32_t time,
159 
160         /* Update keyboard modifier state. */
161         keyboard->modifier_state = modifier_state;
162-
163-        if (keyboard->focus.resource)
164-        {
165-            serial = wl_display_next_serial(display);
166-            wl_keyboard_send_modifiers
167-                (keyboard->focus.resource, serial, modifier_state.depressed,
168-                 modifier_state.latched, modifier_state.locked,
169-                 modifier_state.group);
170-        }
171-
172-
173         keyboard->modifiers = 0;
174         if (mods_active & (1 << keyboard->xkb.indices.ctrl))
175             keyboard->modifiers |= SWC_MOD_CTRL;
176@@ -224,6 +247,13 @@ void swc_keyboard_handle_key(struct swc_keyboard * keyboard, uint32_t time,
177             keyboard->modifiers |= SWC_MOD_LOGO;
178         if (mods_active & (1 << keyboard->xkb.indices.shift))
179             keyboard->modifiers |= SWC_MOD_SHIFT;
180+
181+        /* Run any modifier handlers. */
182+        wl_list_for_each(handler, &keyboard->handlers, link)
183+        {
184+            if (handler->modifiers)
185+                handler->modifiers(keyboard, &modifier_state);
186+        }
187     }
188 }
189 
+6, -5
 1@@ -47,20 +47,21 @@ struct swc_keyboard_handler
 2                  uint32_t key, uint32_t state);
 3     bool (* modifiers)(struct swc_keyboard * keyboard,
 4                        const struct swc_keyboard_modifier_state * state);
 5+
 6+    struct wl_array keys;
 7+    struct wl_list link;
 8 };
 9 
10 struct swc_keyboard
11 {
12     struct swc_input_focus focus;
13     struct swc_input_focus_handler focus_handler;
14-
15-    const struct swc_keyboard_handler * handler;
16-
17     struct swc_xkb xkb;
18 
19-    struct wl_array keys;
20-    struct swc_keyboard_modifier_state modifier_state;
21+    struct wl_list handlers;
22+    struct swc_keyboard_handler client_handler;
23 
24+    struct swc_keyboard_modifier_state modifier_state;
25     uint32_t modifiers;
26 };
27 
+2, -1
 1@@ -52,7 +52,8 @@ static void setup_compositor()
 2     pixman_region32_t pointer_region;
 3     struct swc_output * output;
 4 
 5-    swc.seat->keyboard->handler = swc.bindings->keyboard_handler;
 6+    wl_list_insert(&swc.seat->keyboard->handlers,
 7+                   &swc.bindings->keyboard_handler->link);
 8     swc.seat->pointer->handler = &compositor.pointer_handler;
 9     wl_signal_add(&swc.seat->pointer->focus.event_signal,
10                   swc_window_enter_listener);