commit 6d459f0
Michael Forney
·
2014-02-27 04:57:59 +0000 UTC
parent ce14c72
Properly support binding key releases Now, the keyboard keeps track of a single array of keys pressed, similar to th pointer, and the client handler keeps track of an array of keys to be sent on enter. This way, we can keep track of the binding used when a key is invoked, in order to ensure that the same binding is invoked when the key is released.
4 files changed,
+124,
-55
+50,
-20
1@@ -23,7 +23,9 @@
2
3 #include "swc.h"
4 #include "bindings.h"
5+#include "internal.h"
6 #include "keyboard.h"
7+#include "seat.h"
8 #include "util.h"
9
10 #include <wayland-util.h>
11@@ -37,7 +39,7 @@ struct binding
12 };
13
14 static bool handle_key(struct keyboard * keyboard, uint32_t time,
15- uint32_t key, uint32_t state);
16+ struct press * press, uint32_t state);
17
18 static struct keyboard_handler binding_handler = {
19 .key = &handle_key,
20@@ -49,51 +51,79 @@ const struct swc_bindings swc_bindings = {
21 .keyboard_handler = &binding_handler
22 };
23
24-static bool handle_binding(struct wl_array * bindings, uint32_t time,
25- uint32_t modifiers, uint32_t value, uint32_t state)
26+static struct binding * find_binding(struct wl_array * bindings,
27+ uint32_t modifiers, uint32_t value)
28 {
29 struct binding * binding;
30
31 wl_array_for_each(binding, bindings)
32 {
33- if (binding->value == value
34- && (binding->modifiers == modifiers
35- || binding->modifiers == SWC_MOD_ANY))
36+ if (binding->value == value && (binding->modifiers == modifiers
37+ || binding->modifiers == SWC_MOD_ANY))
38 {
39- binding->handler(binding->data, time, value, state);
40- return true;
41+ return binding;
42 }
43 }
44
45- return false;
46+ return NULL;
47 }
48
49-bool handle_key(struct keyboard * keyboard, uint32_t time,
50- uint32_t key, uint32_t state)
51+static struct binding * find_key_binding(uint32_t modifiers, uint32_t key)
52 {
53+ struct binding * binding;
54+ struct swc_xkb * xkb = &swc.seat->keyboard->xkb;
55 xkb_keysym_t keysym;
56
57 /* First try the keysym the keymap generates in it's current state. */
58- keysym = xkb_state_key_get_one_sym(keyboard->xkb.state, XKB_KEY(key));
59+ keysym = xkb_state_key_get_one_sym(xkb->state, XKB_KEY(key));
60+ binding = find_binding(&key_bindings, modifiers, keysym);
61
62- if (handle_binding(&key_bindings, time, keyboard->modifiers, keysym, state))
63- return true;
64+ if (binding)
65+ return binding;
66
67 xkb_layout_index_t layout;
68 const xkb_keysym_t * keysyms;
69
70 /* Then try the keysym associated with shift-level 0 for the key. */
71- layout = xkb_state_key_get_layout(keyboard->xkb.state, XKB_KEY(key));
72- xkb_keymap_key_get_syms_by_level(keyboard->xkb.keymap.map, XKB_KEY(key),
73+ layout = xkb_state_key_get_layout(xkb->state, XKB_KEY(key));
74+ xkb_keymap_key_get_syms_by_level(xkb->keymap.map, XKB_KEY(key),
75 layout, 0, &keysyms);
76
77- if (keysyms && handle_binding(&key_bindings, time,
78- keyboard->modifiers, keysyms[0], state))
79+ if (!keysyms)
80+ return NULL;
81+
82+ binding = find_binding(&key_bindings, modifiers, keysyms[0]);
83+
84+ return binding;
85+}
86+
87+static bool handle_binding
88+ (uint32_t time, struct press * press, uint32_t state,
89+ struct binding * (* find_binding)(uint32_t, uint32_t))
90+{
91+ struct binding * binding;
92+
93+ if (state)
94 {
95- return true;
96+ binding = find_binding(swc.seat->keyboard->modifiers, press->value);
97+
98+ if (!binding)
99+ return false;
100+
101+ press->data = binding;
102 }
103+ else
104+ binding = press->data;
105+
106+ binding->handler(binding->data, time, binding->value, state);
107+
108+ return true;
109+}
110
111- return false;
112+bool handle_key(struct keyboard * keyboard, uint32_t time,
113+ struct press * key, uint32_t state)
114+{
115+ return handle_binding(time, key, state, &find_key_binding);
116 }
117
118 bool swc_bindings_initialize()
+1,
-0
1@@ -83,6 +83,7 @@ struct press
2 {
3 uint32_t value;
4 uint32_t serial;
5+ void * data;
6 };
7
8 /* }}} */
+64,
-33
1@@ -43,7 +43,7 @@ static void enter(struct input_focus_handler * handler,
2
3 serial = wl_display_next_serial(swc.display);
4 wl_keyboard_send_enter(resource, serial, view->surface->resource,
5- &keyboard->client_handler.keys);
6+ &keyboard->client_keys);
7 }
8
9 static void leave(struct input_focus_handler * handler,
10@@ -56,19 +56,37 @@ static void leave(struct input_focus_handler * handler,
11 }
12
13 static bool client_handle_key(struct keyboard * keyboard, uint32_t time,
14- uint32_t key, uint32_t state)
15+ struct press * press, uint32_t state)
16 {
17- struct wl_client * client;
18- struct wl_display * display;
19- uint32_t serial;
20+ uint32_t * client_key;
21
22- if (!keyboard->focus.resource)
23- return true;
24+ if (state == WL_KEYBOARD_KEY_STATE_PRESSED)
25+ {
26+ client_key = wl_array_add(&keyboard->client_keys, sizeof *client_key);
27
28- client = wl_resource_get_client(keyboard->focus.resource);
29- display = wl_client_get_display(client);
30- serial = wl_display_next_serial(display);
31- wl_keyboard_send_key(keyboard->focus.resource, serial, time, key, state);
32+ if (!client_key)
33+ return false;
34+
35+ *client_key = press->value;
36+ }
37+ else
38+ {
39+ wl_array_for_each(client_key, &keyboard->client_keys)
40+ {
41+ if (*client_key == press->value)
42+ {
43+ swc_array_remove(&keyboard->client_keys,
44+ client_key, sizeof *client_key);
45+ break;
46+ }
47+ }
48+ }
49+
50+ if (keyboard->focus.resource)
51+ {
52+ wl_keyboard_send_key(keyboard->focus.resource, press->serial, time,
53+ press->value, state);
54+ }
55
56 return true;
57 }
58@@ -110,7 +128,8 @@ bool keyboard_initialize(struct keyboard * keyboard)
59 keyboard->focus_handler.leave = &leave;
60 keyboard->client_handler.key = &client_handle_key;
61 keyboard->client_handler.modifiers = &client_handle_modifiers;
62- wl_array_init(&keyboard->client_handler.keys);
63+ wl_array_init(&keyboard->client_keys);
64+ wl_array_init(&keyboard->keys);
65 wl_list_init(&keyboard->handlers);
66 wl_list_insert(&keyboard->handlers, &keyboard->client_handler.link);
67
68@@ -124,7 +143,8 @@ bool keyboard_initialize(struct keyboard * keyboard)
69
70 void keyboard_finalize(struct keyboard * keyboard)
71 {
72- wl_array_release(&keyboard->client_handler.keys);
73+ wl_array_release(&keyboard->client_keys);
74+ wl_array_release(&keyboard->keys);
75 input_focus_finalize(&keyboard->focus);
76 swc_xkb_finalize(&keyboard->xkb);
77 }
78@@ -163,41 +183,52 @@ struct wl_resource * keyboard_bind(struct keyboard * keyboard,
79 }
80
81 void keyboard_handle_key(struct keyboard * keyboard, uint32_t time,
82- uint32_t key, uint32_t state)
83+ uint32_t value, uint32_t state)
84 {
85- uint32_t * pressed_key;
86+ struct key * key;
87 struct keyboard_modifier_state modifier_state;
88 enum xkb_key_direction direction;
89 struct swc_xkb * xkb = &keyboard->xkb;
90 struct keyboard_handler * handler;
91+ uint32_t serial;
92
93- /* First handle key events associated with a particular handler. */
94- wl_list_for_each(handler, &keyboard->handlers, link)
95+ serial = wl_display_next_serial(swc.display);
96+
97+ /* First handle key release events associated with a particular handler. */
98+ wl_array_for_each(key, &keyboard->keys)
99 {
100- wl_array_for_each(pressed_key, &handler->keys)
101+ if (key->press.value == value)
102 {
103- if (*pressed_key == key)
104+ /* Ignore repeat events. */
105+ if (state == WL_KEYBOARD_KEY_STATE_PRESSED)
106+ return;
107+
108+ if (key->handler)
109 {
110- /* Ignore repeat events. */
111- if (state == WL_KEYBOARD_KEY_STATE_PRESSED)
112- return;
113-
114- swc_array_remove(&handler->keys,
115- pressed_key, sizeof *pressed_key);
116- if (handler->key)
117- handler->key(keyboard, time, key, state);
118- goto update_xkb_state;
119+ key->press.serial = serial;
120+ key->handler->key(keyboard, time, &key->press, state);
121 }
122+
123+ swc_array_remove(&keyboard->keys, key, sizeof *key);
124+ goto update_xkb_state;
125 }
126 }
127
128- /* Go through handlers again to see if any will accept this key event. */
129+ key = wl_array_add(&keyboard->keys, sizeof *key);
130+
131+ if (!key)
132+ goto update_xkb_state;
133+
134+ key->press.value = value;
135+ key->press.serial = serial;
136+ key->handler = NULL;
137+
138+ /* Go through handlers to see if any will accept this key event. */
139 wl_list_for_each(handler, &keyboard->handlers, link)
140 {
141- if (handler->key && handler->key(keyboard, time, key, state))
142+ if (handler->key && handler->key(keyboard, time, &key->press, state))
143 {
144- pressed_key = wl_array_add(&handler->keys, sizeof *pressed_key);
145- *pressed_key = key;
146+ key->handler = handler;
147 break;
148 }
149 }
150@@ -206,7 +237,7 @@ void keyboard_handle_key(struct keyboard * keyboard, uint32_t time,
151 update_xkb_state:
152 direction = state == WL_KEYBOARD_KEY_STATE_PRESSED ? XKB_KEY_DOWN
153 : XKB_KEY_UP;
154- xkb_state_update_key(xkb->state, XKB_KEY(key), direction);
155+ xkb_state_update_key(xkb->state, XKB_KEY(value), direction);
156
157 modifier_state.depressed
158 = xkb_state_serialize_mods(xkb->state, XKB_STATE_DEPRESSED);
+9,
-2
1@@ -33,6 +33,12 @@
2 struct keyboard;
3 struct wl_client;
4
5+struct key
6+{
7+ struct press press;
8+ struct keyboard_handler * handler;
9+};
10+
11 struct keyboard_modifier_state
12 {
13 uint32_t depressed;
14@@ -44,11 +50,10 @@ struct keyboard_modifier_state
15 struct keyboard_handler
16 {
17 bool (* key)(struct keyboard * keyboard, uint32_t time,
18- uint32_t key, uint32_t state);
19+ struct press * press, uint32_t state);
20 bool (* modifiers)(struct keyboard * keyboard,
21 const struct keyboard_modifier_state * state);
22
23- struct wl_array keys;
24 struct wl_list link;
25 };
26
27@@ -58,8 +63,10 @@ struct keyboard
28 struct input_focus_handler focus_handler;
29 struct swc_xkb xkb;
30
31+ struct wl_array keys;
32 struct wl_list handlers;
33 struct keyboard_handler client_handler;
34+ struct wl_array client_keys;
35
36 struct keyboard_modifier_state modifier_state;
37 uint32_t modifiers;