diff options
-rw-r--r-- | client/pool-buffer.c | 1 | ||||
-rw-r--r-- | include/sway/config.h | 2 | ||||
-rw-r--r-- | include/sway/input/keyboard.h | 5 | ||||
-rw-r--r-- | sway/commands/bind.c | 25 | ||||
-rw-r--r-- | sway/desktop/output.c | 4 | ||||
-rw-r--r-- | sway/input/keyboard.c | 206 | ||||
-rw-r--r-- | swayidle/main.c | 3 |
7 files changed, 135 insertions, 111 deletions
diff --git a/client/pool-buffer.c b/client/pool-buffer.c index 52438303..fa468c0d 100644 --- a/client/pool-buffer.c +++ b/client/pool-buffer.c | |||
@@ -144,5 +144,6 @@ struct pool_buffer *get_next_buffer(struct wl_shm *shm, | |||
144 | return NULL; | 144 | return NULL; |
145 | } | 145 | } |
146 | } | 146 | } |
147 | buffer->busy = true; | ||
147 | return buffer; | 148 | return buffer; |
148 | } | 149 | } |
diff --git a/include/sway/config.h b/include/sway/config.h index 81e9c382..e75b0664 100644 --- a/include/sway/config.h +++ b/include/sway/config.h | |||
@@ -30,7 +30,7 @@ struct sway_binding { | |||
30 | bool release; | 30 | bool release; |
31 | bool locked; | 31 | bool locked; |
32 | bool bindcode; | 32 | bool bindcode; |
33 | list_t *keys; | 33 | list_t *keys; // sorted in ascending order |
34 | uint32_t modifiers; | 34 | uint32_t modifiers; |
35 | char *command; | 35 | char *command; |
36 | }; | 36 | }; |
diff --git a/include/sway/input/keyboard.h b/include/sway/input/keyboard.h index e99a54b1..6713398e 100644 --- a/include/sway/input/keyboard.h +++ b/include/sway/input/keyboard.h | |||
@@ -21,7 +21,9 @@ struct sway_shortcut_state { | |||
21 | * including duplicates when a keycode generates multiple key ids. | 21 | * including duplicates when a keycode generates multiple key ids. |
22 | */ | 22 | */ |
23 | uint32_t pressed_keycodes[SWAY_KEYBOARD_PRESSED_KEYS_CAP]; | 23 | uint32_t pressed_keycodes[SWAY_KEYBOARD_PRESSED_KEYS_CAP]; |
24 | int last_key_index; | 24 | uint32_t last_keycode; |
25 | uint32_t last_raw_modifiers; | ||
26 | size_t npressed; | ||
25 | }; | 27 | }; |
26 | 28 | ||
27 | struct sway_keyboard { | 29 | struct sway_keyboard { |
@@ -36,7 +38,6 @@ struct sway_keyboard { | |||
36 | struct sway_shortcut_state state_keysyms_raw; | 38 | struct sway_shortcut_state state_keysyms_raw; |
37 | struct sway_shortcut_state state_keycodes; | 39 | struct sway_shortcut_state state_keycodes; |
38 | struct sway_binding *held_binding; | 40 | struct sway_binding *held_binding; |
39 | uint32_t last_modifiers; | ||
40 | }; | 41 | }; |
41 | 42 | ||
42 | struct sway_keyboard *sway_keyboard_create(struct sway_seat *seat, | 43 | struct sway_keyboard *sway_keyboard_create(struct sway_seat *seat, |
diff --git a/sway/commands/bind.c b/sway/commands/bind.c index d0e3e22f..821f9cd1 100644 --- a/sway/commands/bind.c +++ b/sway/commands/bind.c | |||
@@ -32,7 +32,7 @@ void free_sway_binding(struct sway_binding *binding) { | |||
32 | * Note that keyboard layout is not considered, so the bindings might actually | 32 | * Note that keyboard layout is not considered, so the bindings might actually |
33 | * not be equivalent on some layouts. | 33 | * not be equivalent on some layouts. |
34 | */ | 34 | */ |
35 | bool binding_key_compare(struct sway_binding *binding_a, | 35 | static bool binding_key_compare(struct sway_binding *binding_a, |
36 | struct sway_binding *binding_b) { | 36 | struct sway_binding *binding_b) { |
37 | if (binding_a->release != binding_b->release) { | 37 | if (binding_a->release != binding_b->release) { |
38 | return false; | 38 | return false; |
@@ -50,18 +50,12 @@ bool binding_key_compare(struct sway_binding *binding_a, | |||
50 | return false; | 50 | return false; |
51 | } | 51 | } |
52 | 52 | ||
53 | // Keys are sorted | ||
53 | int keys_len = binding_a->keys->length; | 54 | int keys_len = binding_a->keys->length; |
54 | for (int i = 0; i < keys_len; ++i) { | 55 | for (int i = 0; i < keys_len; ++i) { |
55 | uint32_t key_a = *(uint32_t*)binding_a->keys->items[i]; | 56 | uint32_t key_a = *(uint32_t *)binding_a->keys->items[i]; |
56 | bool found = false; | 57 | uint32_t key_b = *(uint32_t *)binding_b->keys->items[i]; |
57 | for (int j = 0; j < keys_len; ++j) { | 58 | if (key_a != key_b) { |
58 | uint32_t key_b = *(uint32_t*)binding_b->keys->items[j]; | ||
59 | if (key_b == key_a) { | ||
60 | found = true; | ||
61 | break; | ||
62 | } | ||
63 | } | ||
64 | if (!found) { | ||
65 | return false; | 59 | return false; |
66 | } | 60 | } |
67 | } | 61 | } |
@@ -69,6 +63,12 @@ bool binding_key_compare(struct sway_binding *binding_a, | |||
69 | return true; | 63 | return true; |
70 | } | 64 | } |
71 | 65 | ||
66 | static int key_qsort_cmp(const void *keyp_a, const void *keyp_b) { | ||
67 | uint32_t key_a = **(uint32_t **)keyp_a; | ||
68 | uint32_t key_b = **(uint32_t **)keyp_b; | ||
69 | return (key_a < key_b) ? -1 : ((key_a > key_b) ? 1 : 0); | ||
70 | } | ||
71 | |||
72 | static struct cmd_results *cmd_bindsym_or_bindcode(int argc, char **argv, | 72 | static struct cmd_results *cmd_bindsym_or_bindcode(int argc, char **argv, |
73 | bool bindcode) { | 73 | bool bindcode) { |
74 | const char *bindtype = bindcode ? "bindcode" : "bindsym"; | 74 | const char *bindtype = bindcode ? "bindcode" : "bindsym"; |
@@ -169,6 +169,9 @@ static struct cmd_results *cmd_bindsym_or_bindcode(int argc, char **argv, | |||
169 | free_flat_list(split); | 169 | free_flat_list(split); |
170 | binding->order = binding_order++; | 170 | binding->order = binding_order++; |
171 | 171 | ||
172 | // sort ascending | ||
173 | list_qsort(binding->keys, key_qsort_cmp); | ||
174 | |||
172 | list_t *mode_bindings; | 175 | list_t *mode_bindings; |
173 | if (bindcode) { | 176 | if (bindcode) { |
174 | mode_bindings = config->current_mode->keycode_bindings; | 177 | mode_bindings = config->current_mode->keycode_bindings; |
diff --git a/sway/desktop/output.c b/sway/desktop/output.c index 5c26ac52..37528cac 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c | |||
@@ -285,10 +285,10 @@ static void render_surface_iterator(struct wlr_surface *surface, int sx, int sy, | |||
285 | intersects = get_view_box(&data->root_geo, data->output, data->view, | 285 | intersects = get_view_box(&data->root_geo, data->output, data->view, |
286 | sx, sy, &box); | 286 | sx, sy, &box); |
287 | } else { | 287 | } else { |
288 | if (!wlr_surface_has_buffer(surface)) { | 288 | texture = wlr_surface_get_texture(surface); |
289 | if (texture == NULL) { | ||
289 | return; | 290 | return; |
290 | } | 291 | } |
291 | texture = surface->texture; | ||
292 | intersects = get_surface_box(&data->root_geo, data->output, surface, | 292 | intersects = get_surface_box(&data->root_geo, data->output, surface, |
293 | sx, sy, &box); | 293 | sx, sy, &box); |
294 | } | 294 | } |
diff --git a/sway/input/keyboard.c b/sway/input/keyboard.c index d90655f2..9e093828 100644 --- a/sway/input/keyboard.c +++ b/sway/input/keyboard.c | |||
@@ -10,85 +10,111 @@ | |||
10 | #include "log.h" | 10 | #include "log.h" |
11 | 11 | ||
12 | /** | 12 | /** |
13 | * Remove all key ids associated to a keycode from the list of pressed keys | ||
14 | */ | ||
15 | static void state_erase_key(struct sway_shortcut_state *state, | ||
16 | uint32_t keycode) { | ||
17 | size_t j = 0; | ||
18 | for (size_t i = 0; i < state->npressed; ++i) { | ||
19 | if (i > j) { | ||
20 | state->pressed_keys[j] = state->pressed_keys[i]; | ||
21 | state->pressed_keycodes[j] = state->pressed_keycodes[i]; | ||
22 | } | ||
23 | if (state->pressed_keycodes[i] != keycode) { | ||
24 | ++j; | ||
25 | } | ||
26 | } | ||
27 | while(state->npressed > j) { | ||
28 | --state->npressed; | ||
29 | state->pressed_keys[state->npressed] = 0; | ||
30 | state->pressed_keycodes[state->npressed] = 0; | ||
31 | } | ||
32 | } | ||
33 | |||
34 | /** | ||
35 | * Add a key id (with associated keycode) to the list of pressed keys, | ||
36 | * if the list is not full. | ||
37 | */ | ||
38 | static void state_add_key(struct sway_shortcut_state *state, | ||
39 | uint32_t keycode, uint32_t key_id) { | ||
40 | if (state->npressed >= SWAY_KEYBOARD_PRESSED_KEYS_CAP) { | ||
41 | return; | ||
42 | } | ||
43 | size_t i = 0; | ||
44 | while (i < state->npressed && state->pressed_keys[i] < key_id) { | ||
45 | ++i; | ||
46 | } | ||
47 | size_t j = state->npressed; | ||
48 | while (j > i) { | ||
49 | state->pressed_keys[j] = state->pressed_keys[j - 1]; | ||
50 | state->pressed_keycodes[j] = state->pressed_keycodes[j - 1]; | ||
51 | --j; | ||
52 | } | ||
53 | state->pressed_keys[i] = key_id; | ||
54 | state->pressed_keycodes[i] = keycode; | ||
55 | state->npressed++; | ||
56 | } | ||
57 | |||
58 | /** | ||
13 | * Update the shortcut model state in response to new input | 59 | * Update the shortcut model state in response to new input |
14 | */ | 60 | */ |
15 | static void update_shortcut_state(struct sway_shortcut_state *state, | 61 | static void update_shortcut_state(struct sway_shortcut_state *state, |
16 | struct wlr_event_keyboard_key *event, uint32_t new_key, | 62 | struct wlr_event_keyboard_key *event, uint32_t new_key, |
17 | bool last_key_was_a_modifier) { | 63 | uint32_t raw_modifiers) { |
64 | bool last_key_was_a_modifier = raw_modifiers != state->last_raw_modifiers; | ||
65 | state->last_raw_modifiers = raw_modifiers; | ||
66 | |||
18 | if (event->state == WLR_KEY_PRESSED) { | 67 | if (event->state == WLR_KEY_PRESSED) { |
19 | if (last_key_was_a_modifier && state->last_key_index >= 0) { | 68 | if (last_key_was_a_modifier && state->last_keycode) { |
20 | // Last pressed key before this one was a modifier | 69 | // Last pressed key before this one was a modifier |
21 | state->pressed_keycodes[state->last_key_index] = 0; | 70 | state_erase_key(state, state->last_keycode); |
22 | state->pressed_keys[state->last_key_index] = 0; | ||
23 | state->last_key_index = -1; | ||
24 | } | 71 | } |
25 | 72 | ||
26 | // Add current key to set; there may be duplicates | 73 | // Add current key to set; there may be duplicates |
27 | for (size_t i = 0; i < SWAY_KEYBOARD_PRESSED_KEYS_CAP; ++i) { | 74 | state_add_key(state, event->keycode, new_key); |
28 | if (!state->pressed_keys[i]) { | 75 | state->last_keycode = event->keycode; |
29 | state->pressed_keys[i] = new_key; | ||
30 | state->pressed_keycodes[i] = event->keycode; | ||
31 | state->last_key_index = i; | ||
32 | break; | ||
33 | } | ||
34 | } | ||
35 | } else { | 76 | } else { |
36 | for (size_t i = 0; i < SWAY_KEYBOARD_PRESSED_KEYS_CAP; ++i) { | 77 | state_erase_key(state, event->keycode); |
37 | // The same keycode may match multiple keysyms. | ||
38 | if (state->pressed_keycodes[i] == event->keycode) { | ||
39 | state->pressed_keys[i] = 0; | ||
40 | state->pressed_keycodes[i] = 0; | ||
41 | } | ||
42 | } | ||
43 | } | 78 | } |
44 | } | 79 | } |
45 | 80 | ||
46 | /** | 81 | /** |
47 | * | 82 | * If one exists, finds a binding which matches the shortcut model state, |
48 | * Returns a binding which matches the shortcut model state (ignoring the | 83 | * current modifiers, release state, and locked state. |
49 | * `release` flag). | ||
50 | */ | 84 | */ |
51 | static struct sway_binding *get_active_binding( | 85 | static void get_active_binding(const struct sway_shortcut_state *state, |
52 | struct sway_shortcut_state *state, list_t *bindings, | 86 | list_t *bindings, struct sway_binding **current_binding, |
53 | uint32_t modifiers, bool locked) { | 87 | uint32_t modifiers, bool release, bool locked) { |
54 | int npressed_keys = 0; | ||
55 | for (size_t i = 0; i < SWAY_KEYBOARD_PRESSED_KEYS_CAP; ++i) { | ||
56 | if (state->pressed_keys[i]) { | ||
57 | ++npressed_keys; | ||
58 | } | ||
59 | } | ||
60 | for (int i = 0; i < bindings->length; ++i) { | 88 | for (int i = 0; i < bindings->length; ++i) { |
61 | struct sway_binding *binding = bindings->items[i]; | 89 | struct sway_binding *binding = bindings->items[i]; |
62 | 90 | ||
63 | if (modifiers ^ binding->modifiers || | 91 | if (modifiers ^ binding->modifiers || |
64 | npressed_keys != binding->keys->length || | 92 | state->npressed != (size_t)binding->keys->length || |
65 | locked > binding->locked) { | 93 | locked > binding->locked || |
94 | release != binding->release) { | ||
66 | continue; | 95 | continue; |
67 | } | 96 | } |
68 | 97 | ||
69 | bool match = true; | 98 | bool match = true; |
70 | for (int j = 0; j < binding->keys->length; ++j) { | 99 | for (size_t j = 0; j < state->npressed; j++) { |
71 | uint32_t key = *(uint32_t *)binding->keys->items[j]; | 100 | uint32_t key = *(uint32_t *)binding->keys->items[j]; |
72 | 101 | if (key != state->pressed_keys[j]) { | |
73 | bool key_found = false; | ||
74 | for (int k = 0; k < SWAY_KEYBOARD_PRESSED_KEYS_CAP; ++k) { | ||
75 | if (state->pressed_keys[k] == key) { | ||
76 | key_found = true; | ||
77 | break; | ||
78 | } | ||
79 | } | ||
80 | if (!key_found) { | ||
81 | match = false; | 102 | match = false; |
82 | break; | 103 | break; |
83 | } | 104 | } |
84 | } | 105 | } |
106 | if (!match) { | ||
107 | continue; | ||
108 | } | ||
85 | 109 | ||
86 | if (match) { | 110 | if (*current_binding && *current_binding != binding) { |
87 | return binding; | 111 | wlr_log(L_DEBUG, "encountered duplicate bindings %d and %d", |
112 | (*current_binding)->order, binding->order); | ||
113 | } else { | ||
114 | *current_binding = binding; | ||
88 | } | 115 | } |
116 | return; | ||
89 | } | 117 | } |
90 | |||
91 | return NULL; | ||
92 | } | 118 | } |
93 | 119 | ||
94 | /** | 120 | /** |
@@ -204,69 +230,65 @@ static void handle_keyboard_key(struct wl_listener *listener, void *data) { | |||
204 | size_t raw_keysyms_len = | 230 | size_t raw_keysyms_len = |
205 | keyboard_keysyms_raw(keyboard, keycode, &raw_keysyms, &raw_modifiers); | 231 | keyboard_keysyms_raw(keyboard, keycode, &raw_keysyms, &raw_modifiers); |
206 | 232 | ||
207 | struct wlr_input_device *device = | 233 | uint32_t code_modifiers = wlr_keyboard_get_modifiers(wlr_device->keyboard); |
208 | keyboard->seat_device->input_device->wlr_device; | ||
209 | uint32_t code_modifiers = wlr_keyboard_get_modifiers(device->keyboard); | ||
210 | |||
211 | bool last_key_was_a_modifier = code_modifiers != keyboard->last_modifiers; | ||
212 | keyboard->last_modifiers = code_modifiers; | ||
213 | 234 | ||
214 | // Update shortcut model state | 235 | // Update shortcut model state |
215 | update_shortcut_state(&keyboard->state_keycodes, event, | 236 | update_shortcut_state(&keyboard->state_keycodes, event, |
216 | (uint32_t)keycode, last_key_was_a_modifier); | 237 | (uint32_t)keycode, code_modifiers); |
217 | for (size_t i = 0; i < translated_keysyms_len; ++i) { | 238 | for (size_t i = 0; i < translated_keysyms_len; ++i) { |
218 | update_shortcut_state(&keyboard->state_keysyms_translated, | 239 | update_shortcut_state(&keyboard->state_keysyms_translated, |
219 | event, (uint32_t)translated_keysyms[i], | 240 | event, (uint32_t)translated_keysyms[i], |
220 | last_key_was_a_modifier && i == 0); | 241 | code_modifiers); |
221 | } | 242 | } |
222 | for (size_t i = 0; i < raw_keysyms_len; ++i) { | 243 | for (size_t i = 0; i < raw_keysyms_len; ++i) { |
223 | update_shortcut_state(&keyboard->state_keysyms_raw, | 244 | update_shortcut_state(&keyboard->state_keysyms_raw, |
224 | event, (uint32_t)raw_keysyms[i], | 245 | event, (uint32_t)raw_keysyms[i], |
225 | last_key_was_a_modifier && i == 0); | 246 | code_modifiers); |
226 | } | 247 | } |
227 | 248 | ||
228 | // identify which binding should be executed. | ||
229 | struct sway_binding *binding = get_active_binding( | ||
230 | &keyboard->state_keycodes, | ||
231 | config->current_mode->keycode_bindings, | ||
232 | code_modifiers, input_inhibited); | ||
233 | struct sway_binding *translated_binding = get_active_binding( | ||
234 | &keyboard->state_keysyms_translated, | ||
235 | config->current_mode->keysym_bindings, | ||
236 | translated_modifiers, input_inhibited); | ||
237 | if (translated_binding && !binding) { | ||
238 | binding = translated_binding; | ||
239 | } else if (binding && translated_binding && binding != translated_binding) { | ||
240 | wlr_log(L_DEBUG, "encountered duplicate bindings %d and %d", | ||
241 | binding->order, translated_binding->order); | ||
242 | } | ||
243 | struct sway_binding *raw_binding = get_active_binding( | ||
244 | &keyboard->state_keysyms_raw, | ||
245 | config->current_mode->keysym_bindings, | ||
246 | raw_modifiers, input_inhibited); | ||
247 | if (raw_binding && !binding) { | ||
248 | binding = raw_binding; | ||
249 | } else if (binding && raw_binding && binding != raw_binding) { | ||
250 | wlr_log(L_DEBUG, "encountered duplicate bindings %d and %d", | ||
251 | binding->order, raw_binding->order); | ||
252 | } | ||
253 | 249 | ||
254 | bool handled = false; | 250 | bool handled = false; |
255 | 251 | ||
256 | // Execute the identified binding if need be. | 252 | // Identify active release binding |
257 | if (keyboard->held_binding && binding != keyboard->held_binding && | 253 | struct sway_binding *binding_released = NULL; |
254 | get_active_binding(&keyboard->state_keycodes, | ||
255 | config->current_mode->keycode_bindings, &binding_released, | ||
256 | code_modifiers, true, input_inhibited); | ||
257 | get_active_binding(&keyboard->state_keysyms_translated, | ||
258 | config->current_mode->keysym_bindings, &binding_released, | ||
259 | translated_modifiers, true, input_inhibited); | ||
260 | get_active_binding(&keyboard->state_keysyms_raw, | ||
261 | config->current_mode->keysym_bindings, &binding_released, | ||
262 | raw_modifiers, true, input_inhibited); | ||
263 | |||
264 | // Execute stored release binding once no longer active | ||
265 | if (keyboard->held_binding && binding_released != keyboard->held_binding && | ||
258 | event->state == WLR_KEY_RELEASED) { | 266 | event->state == WLR_KEY_RELEASED) { |
259 | keyboard_execute_command(keyboard, keyboard->held_binding); | 267 | keyboard_execute_command(keyboard, keyboard->held_binding); |
260 | handled = true; | 268 | handled = true; |
261 | } | 269 | } |
262 | if (binding != keyboard->held_binding) { | 270 | if (binding_released != keyboard->held_binding) { |
263 | keyboard->held_binding = NULL; | 271 | keyboard->held_binding = NULL; |
264 | } | 272 | } |
265 | if (binding && event->state == WLR_KEY_PRESSED) { | 273 | if (binding_released && event->state == WLR_KEY_PRESSED) { |
266 | if (binding->release) { | 274 | keyboard->held_binding = binding_released; |
267 | keyboard->held_binding = binding; | 275 | } |
268 | } else { | 276 | |
269 | keyboard_execute_command(keyboard, binding); | 277 | // Identify and execute active pressed binding |
278 | if (event->state == WLR_KEY_PRESSED) { | ||
279 | struct sway_binding *binding_pressed = NULL; | ||
280 | get_active_binding(&keyboard->state_keycodes, | ||
281 | config->current_mode->keycode_bindings, &binding_pressed, | ||
282 | code_modifiers, false, input_inhibited); | ||
283 | get_active_binding(&keyboard->state_keysyms_translated, | ||
284 | config->current_mode->keysym_bindings, &binding_pressed, | ||
285 | translated_modifiers, false, input_inhibited); | ||
286 | get_active_binding(&keyboard->state_keysyms_raw, | ||
287 | config->current_mode->keysym_bindings, &binding_pressed, | ||
288 | raw_modifiers, false, input_inhibited); | ||
289 | |||
290 | if (binding_pressed) { | ||
291 | keyboard_execute_command(keyboard, binding_pressed); | ||
270 | handled = true; | 292 | handled = true; |
271 | } | 293 | } |
272 | } | 294 | } |
@@ -315,10 +337,6 @@ struct sway_keyboard *sway_keyboard_create(struct sway_seat *seat, | |||
315 | wl_list_init(&keyboard->keyboard_key.link); | 337 | wl_list_init(&keyboard->keyboard_key.link); |
316 | wl_list_init(&keyboard->keyboard_modifiers.link); | 338 | wl_list_init(&keyboard->keyboard_modifiers.link); |
317 | 339 | ||
318 | keyboard->state_keycodes.last_key_index = -1; | ||
319 | keyboard->state_keysyms_raw.last_key_index = -1; | ||
320 | keyboard->state_keysyms_translated.last_key_index = -1; | ||
321 | |||
322 | return keyboard; | 340 | return keyboard; |
323 | } | 341 | } |
324 | 342 | ||
diff --git a/swayidle/main.c b/swayidle/main.c index d83ab98d..7666578f 100644 --- a/swayidle/main.c +++ b/swayidle/main.c | |||
@@ -127,7 +127,8 @@ void acquire_sleep_lock() { | |||
127 | 127 | ||
128 | static int prepare_for_sleep(sd_bus_message *msg, void *userdata, | 128 | static int prepare_for_sleep(sd_bus_message *msg, void *userdata, |
129 | sd_bus_error *ret_error) { | 129 | sd_bus_error *ret_error) { |
130 | bool going_down = true; | 130 | /* "b" apparently reads into an int, not a bool */ |
131 | int going_down = 1; | ||
131 | int ret = sd_bus_message_read(msg, "b", &going_down); | 132 | int ret = sd_bus_message_read(msg, "b", &going_down); |
132 | if (ret < 0) { | 133 | if (ret < 0) { |
133 | wlr_log(L_ERROR, "Failed to parse D-Bus response for Inhibit: %s", | 134 | wlr_log(L_ERROR, "Failed to parse D-Bus response for Inhibit: %s", |