blob: 234c034b6fb67df8a38ec9ff6a2f37b0bfdc01d2 [file] [log] [blame]
Ander Conselvan de Oliveiracbdebc22013-02-21 18:35:16 +02001/*
Pekka Paalanen2829f7c2015-02-19 17:02:13 +02002 * Copyright © 2011-2012 Intel Corporation
Ander Conselvan de Oliveiracbdebc22013-02-21 18:35:16 +02003 *
Bryce Harringtona0bbfea2015-06-11 15:35:43 -07004 * Permission is hereby granted, free of charge, to any person obtaining
5 * a copy of this software and associated documentation files (the
6 * "Software"), to deal in the Software without restriction, including
7 * without limitation the rights to use, copy, modify, merge, publish,
8 * distribute, sublicense, and/or sell copies of the Software, and to
9 * permit persons to whom the Software is furnished to do so, subject to
10 * the following conditions:
Ander Conselvan de Oliveiracbdebc22013-02-21 18:35:16 +020011 *
Bryce Harringtona0bbfea2015-06-11 15:35:43 -070012 * The above copyright notice and this permission notice (including the
13 * next paragraph) shall be included in all copies or substantial
14 * portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
20 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
21 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 * SOFTWARE.
Ander Conselvan de Oliveiracbdebc22013-02-21 18:35:16 +020024 */
25
Daniel Stonec228e232013-05-22 18:03:19 +030026#include "config.h"
27
Ander Conselvan de Oliveiracbdebc22013-02-21 18:35:16 +020028#include <stdlib.h>
Pekka Paalanen2829f7c2015-02-19 17:02:13 +020029#include <linux/input.h>
Ander Conselvan de Oliveiracbdebc22013-02-21 18:35:16 +020030
31#include "compositor.h"
Jon Cruz867d50e2015-06-15 15:37:10 -070032#include "shared/helpers.h"
Ander Conselvan de Oliveiracbdebc22013-02-21 18:35:16 +020033
34struct weston_binding {
35 uint32_t key;
36 uint32_t button;
37 uint32_t axis;
38 uint32_t modifier;
39 void *handler;
40 void *data;
41 struct wl_list link;
42};
43
44static struct weston_binding *
45weston_compositor_add_binding(struct weston_compositor *compositor,
46 uint32_t key, uint32_t button, uint32_t axis,
47 uint32_t modifier, void *handler, void *data)
48{
49 struct weston_binding *binding;
50
51 binding = malloc(sizeof *binding);
52 if (binding == NULL)
53 return NULL;
54
55 binding->key = key;
56 binding->button = button;
57 binding->axis = axis;
58 binding->modifier = modifier;
59 binding->handler = handler;
60 binding->data = data;
61
62 return binding;
63}
64
65WL_EXPORT struct weston_binding *
66weston_compositor_add_key_binding(struct weston_compositor *compositor,
67 uint32_t key, uint32_t modifier,
68 weston_key_binding_handler_t handler,
69 void *data)
70{
71 struct weston_binding *binding;
72
73 binding = weston_compositor_add_binding(compositor, key, 0, 0,
74 modifier, handler, data);
75 if (binding == NULL)
76 return NULL;
77
78 wl_list_insert(compositor->key_binding_list.prev, &binding->link);
79
80 return binding;
81}
82
83WL_EXPORT struct weston_binding *
Daniel Stone96d47c02013-11-19 11:37:12 +010084weston_compositor_add_modifier_binding(struct weston_compositor *compositor,
85 uint32_t modifier,
86 weston_modifier_binding_handler_t handler,
87 void *data)
88{
89 struct weston_binding *binding;
90
91 binding = weston_compositor_add_binding(compositor, 0, 0, 0,
92 modifier, handler, data);
93 if (binding == NULL)
94 return NULL;
95
96 wl_list_insert(compositor->modifier_binding_list.prev, &binding->link);
97
98 return binding;
99}
100
101WL_EXPORT struct weston_binding *
Ander Conselvan de Oliveiracbdebc22013-02-21 18:35:16 +0200102weston_compositor_add_button_binding(struct weston_compositor *compositor,
103 uint32_t button, uint32_t modifier,
104 weston_button_binding_handler_t handler,
105 void *data)
106{
107 struct weston_binding *binding;
108
109 binding = weston_compositor_add_binding(compositor, 0, button, 0,
110 modifier, handler, data);
111 if (binding == NULL)
112 return NULL;
113
114 wl_list_insert(compositor->button_binding_list.prev, &binding->link);
115
116 return binding;
117}
118
119WL_EXPORT struct weston_binding *
Neil Robertsa28c6932013-10-03 16:43:04 +0100120weston_compositor_add_touch_binding(struct weston_compositor *compositor,
121 uint32_t modifier,
122 weston_touch_binding_handler_t handler,
123 void *data)
124{
125 struct weston_binding *binding;
126
127 binding = weston_compositor_add_binding(compositor, 0, 0, 0,
128 modifier, handler, data);
129 if (binding == NULL)
130 return NULL;
131
132 wl_list_insert(compositor->touch_binding_list.prev, &binding->link);
133
134 return binding;
135}
136
137WL_EXPORT struct weston_binding *
Ander Conselvan de Oliveiracbdebc22013-02-21 18:35:16 +0200138weston_compositor_add_axis_binding(struct weston_compositor *compositor,
139 uint32_t axis, uint32_t modifier,
140 weston_axis_binding_handler_t handler,
141 void *data)
142{
143 struct weston_binding *binding;
144
145 binding = weston_compositor_add_binding(compositor, 0, 0, axis,
146 modifier, handler, data);
147 if (binding == NULL)
148 return NULL;
149
150 wl_list_insert(compositor->axis_binding_list.prev, &binding->link);
151
152 return binding;
153}
154
155WL_EXPORT struct weston_binding *
156weston_compositor_add_debug_binding(struct weston_compositor *compositor,
157 uint32_t key,
158 weston_key_binding_handler_t handler,
159 void *data)
160{
161 struct weston_binding *binding;
162
163 binding = weston_compositor_add_binding(compositor, key, 0, 0, 0,
164 handler, data);
165
166 wl_list_insert(compositor->debug_binding_list.prev, &binding->link);
167
168 return binding;
169}
170
171WL_EXPORT void
172weston_binding_destroy(struct weston_binding *binding)
173{
174 wl_list_remove(&binding->link);
175 free(binding);
176}
177
Derek Foreman2e6485c2015-07-15 13:00:34 -0500178void
Ander Conselvan de Oliveiracbdebc22013-02-21 18:35:16 +0200179weston_binding_list_destroy_all(struct wl_list *list)
180{
181 struct weston_binding *binding, *tmp;
182
183 wl_list_for_each_safe(binding, tmp, list, link)
184 weston_binding_destroy(binding);
185}
186
187struct binding_keyboard_grab {
188 uint32_t key;
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400189 struct weston_keyboard_grab grab;
Ander Conselvan de Oliveiracbdebc22013-02-21 18:35:16 +0200190};
191
192static void
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400193binding_key(struct weston_keyboard_grab *grab,
Ander Conselvan de Oliveiracbdebc22013-02-21 18:35:16 +0200194 uint32_t time, uint32_t key, uint32_t state_w)
195{
196 struct binding_keyboard_grab *b =
197 container_of(grab, struct binding_keyboard_grab, grab);
198 struct wl_resource *resource;
Ander Conselvan de Oliveiracbdebc22013-02-21 18:35:16 +0200199 enum wl_keyboard_key_state state = state_w;
200 uint32_t serial;
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400201 struct weston_keyboard *keyboard = grab->keyboard;
Rob Bradford880ebc72013-07-22 17:31:38 +0100202 struct wl_display *display = keyboard->seat->compositor->wl_display;
Ander Conselvan de Oliveiracbdebc22013-02-21 18:35:16 +0200203
Ander Conselvan de Oliveiracbdebc22013-02-21 18:35:16 +0200204 if (key == b->key) {
205 if (state == WL_KEYBOARD_KEY_STATE_RELEASED) {
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400206 weston_keyboard_end_grab(grab->keyboard);
Ander Conselvan de Oliveiracbdebc22013-02-21 18:35:16 +0200207 if (keyboard->input_method_resource)
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400208 keyboard->grab = &keyboard->input_method_grab;
Ander Conselvan de Oliveiracbdebc22013-02-21 18:35:16 +0200209 free(b);
Giulio Camuffo943b46e2014-12-05 18:02:58 +0200210 } else {
211 /* Don't send the key press event for the binding key */
212 return;
Ander Conselvan de Oliveiracbdebc22013-02-21 18:35:16 +0200213 }
Giulio Camuffoa20ca812014-11-22 11:16:56 +0200214 }
215 if (!wl_list_empty(&keyboard->focus_resource_list)) {
Ander Conselvan de Oliveiracbdebc22013-02-21 18:35:16 +0200216 serial = wl_display_next_serial(display);
Neil Roberts96d790e2013-09-19 17:32:00 +0100217 wl_resource_for_each(resource, &keyboard->focus_resource_list) {
218 wl_keyboard_send_key(resource,
219 serial,
220 time,
221 key,
222 state);
223 }
Ander Conselvan de Oliveiracbdebc22013-02-21 18:35:16 +0200224 }
225}
226
227static void
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400228binding_modifiers(struct weston_keyboard_grab *grab, uint32_t serial,
Ander Conselvan de Oliveiracbdebc22013-02-21 18:35:16 +0200229 uint32_t mods_depressed, uint32_t mods_latched,
230 uint32_t mods_locked, uint32_t group)
231{
232 struct wl_resource *resource;
233
Neil Roberts96d790e2013-09-19 17:32:00 +0100234 wl_resource_for_each(resource, &grab->keyboard->focus_resource_list) {
235 wl_keyboard_send_modifiers(resource, serial, mods_depressed,
236 mods_latched, mods_locked, group);
237 }
Ander Conselvan de Oliveiracbdebc22013-02-21 18:35:16 +0200238}
239
Jonas Ådahl1ea343e2013-10-25 23:18:05 +0200240static void
241binding_cancel(struct weston_keyboard_grab *grab)
242{
243 struct binding_keyboard_grab *binding_grab =
244 container_of(grab, struct binding_keyboard_grab, grab);
245
246 weston_keyboard_end_grab(grab->keyboard);
247 free(binding_grab);
248}
249
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400250static const struct weston_keyboard_grab_interface binding_grab = {
Ander Conselvan de Oliveiracbdebc22013-02-21 18:35:16 +0200251 binding_key,
252 binding_modifiers,
Jonas Ådahl1ea343e2013-10-25 23:18:05 +0200253 binding_cancel,
Ander Conselvan de Oliveiracbdebc22013-02-21 18:35:16 +0200254};
255
256static void
Derek Foremanb591a302015-07-15 13:00:42 -0500257install_binding_grab(struct weston_keyboard *keyboard, uint32_t time,
258 uint32_t key, struct weston_surface *focus)
Ander Conselvan de Oliveiracbdebc22013-02-21 18:35:16 +0200259{
260 struct binding_keyboard_grab *grab;
261
262 grab = malloc(sizeof *grab);
263 grab->key = key;
264 grab->grab.interface = &binding_grab;
Derek Foremanb591a302015-07-15 13:00:42 -0500265 weston_keyboard_start_grab(keyboard, &grab->grab);
Giulio Camuffoa20ca812014-11-22 11:16:56 +0200266
267 /* Notify the surface which had the focus before this binding
268 * triggered that we stole a keypress from under it, by forcing
269 * a wl_keyboard leave/enter pair. The enter event will contain
270 * the pressed key in the keys array, so the client will know
271 * the exact state of the keyboard.
272 * If the old focus surface is different than the new one it
273 * means it was changed in the binding handler, so it received
274 * the enter event already. */
Derek Foremanb591a302015-07-15 13:00:42 -0500275 if (focus && keyboard->focus == focus) {
276 weston_keyboard_set_focus(keyboard, NULL);
277 weston_keyboard_set_focus(keyboard, focus);
Giulio Camuffoa20ca812014-11-22 11:16:56 +0200278 }
Ander Conselvan de Oliveiracbdebc22013-02-21 18:35:16 +0200279}
280
Derek Foreman2e6485c2015-07-15 13:00:34 -0500281void
Ander Conselvan de Oliveiracbdebc22013-02-21 18:35:16 +0200282weston_compositor_run_key_binding(struct weston_compositor *compositor,
Derek Foreman99a6a2d2015-07-15 13:00:43 -0500283 struct weston_keyboard *keyboard,
Ander Conselvan de Oliveiracbdebc22013-02-21 18:35:16 +0200284 uint32_t time, uint32_t key,
285 enum wl_keyboard_key_state state)
286{
Giulio Camuffo24b98d02014-10-03 23:36:34 +0300287 struct weston_binding *b, *tmp;
Giulio Camuffoa20ca812014-11-22 11:16:56 +0200288 struct weston_surface *focus;
Derek Foreman99a6a2d2015-07-15 13:00:43 -0500289 struct weston_seat *seat = keyboard->seat;
Ander Conselvan de Oliveiracbdebc22013-02-21 18:35:16 +0200290
291 if (state == WL_KEYBOARD_KEY_STATE_RELEASED)
Pekka Paalanen86b53962014-11-19 13:43:32 +0200292 return;
Ander Conselvan de Oliveiracbdebc22013-02-21 18:35:16 +0200293
Daniel Stone96d47c02013-11-19 11:37:12 +0100294 /* Invalidate all active modifier bindings. */
295 wl_list_for_each(b, &compositor->modifier_binding_list, link)
296 b->key = key;
297
Giulio Camuffo24b98d02014-10-03 23:36:34 +0300298 wl_list_for_each_safe(b, tmp, &compositor->key_binding_list, link) {
Ander Conselvan de Oliveiracbdebc22013-02-21 18:35:16 +0200299 if (b->key == key && b->modifier == seat->modifier_state) {
300 weston_key_binding_handler_t handler = b->handler;
Derek Foreman99a6a2d2015-07-15 13:00:43 -0500301 focus = keyboard->focus;
302 handler(keyboard, time, key, b->data);
Ander Conselvan de Oliveiracbdebc22013-02-21 18:35:16 +0200303
304 /* If this was a key binding and it didn't
305 * install a keyboard grab, install one now to
Giulio Camuffo943b46e2014-12-05 18:02:58 +0200306 * swallow the key press. */
Derek Foreman99a6a2d2015-07-15 13:00:43 -0500307 if (keyboard->grab ==
308 &keyboard->default_grab)
309 install_binding_grab(keyboard,
Derek Foremanb591a302015-07-15 13:00:42 -0500310 time,
311 key,
312 focus);
Ander Conselvan de Oliveiracbdebc22013-02-21 18:35:16 +0200313 }
314 }
315}
316
Derek Foreman2e6485c2015-07-15 13:00:34 -0500317void
Daniel Stone96d47c02013-11-19 11:37:12 +0100318weston_compositor_run_modifier_binding(struct weston_compositor *compositor,
Derek Foreman99a6a2d2015-07-15 13:00:43 -0500319 struct weston_keyboard *keyboard,
Daniel Stone96d47c02013-11-19 11:37:12 +0100320 enum weston_keyboard_modifier modifier,
321 enum wl_keyboard_key_state state)
322{
Giulio Camuffo24b98d02014-10-03 23:36:34 +0300323 struct weston_binding *b, *tmp;
Daniel Stone96d47c02013-11-19 11:37:12 +0100324
Derek Foreman99a6a2d2015-07-15 13:00:43 -0500325 if (keyboard->grab != &keyboard->default_grab)
Emilio Pozuelo Monfort1539ea22013-11-27 10:34:32 +0100326 return;
327
Giulio Camuffo24b98d02014-10-03 23:36:34 +0300328 wl_list_for_each_safe(b, tmp, &compositor->modifier_binding_list, link) {
Daniel Stone96d47c02013-11-19 11:37:12 +0100329 weston_modifier_binding_handler_t handler = b->handler;
330
331 if (b->modifier != modifier)
332 continue;
333
334 /* Prime the modifier binding. */
335 if (state == WL_KEYBOARD_KEY_STATE_PRESSED) {
336 b->key = 0;
337 continue;
338 }
339 /* Ignore the binding if a key was pressed in between. */
340 else if (b->key != 0) {
341 return;
342 }
343
Derek Foreman99a6a2d2015-07-15 13:00:43 -0500344 handler(keyboard, modifier, b->data);
Daniel Stone96d47c02013-11-19 11:37:12 +0100345 }
346}
347
Derek Foreman2e6485c2015-07-15 13:00:34 -0500348void
Ander Conselvan de Oliveiracbdebc22013-02-21 18:35:16 +0200349weston_compositor_run_button_binding(struct weston_compositor *compositor,
Derek Foreman99a6a2d2015-07-15 13:00:43 -0500350 struct weston_pointer *pointer,
Ander Conselvan de Oliveiracbdebc22013-02-21 18:35:16 +0200351 uint32_t time, uint32_t button,
352 enum wl_pointer_button_state state)
353{
Giulio Camuffo24b98d02014-10-03 23:36:34 +0300354 struct weston_binding *b, *tmp;
Ander Conselvan de Oliveiracbdebc22013-02-21 18:35:16 +0200355
356 if (state == WL_POINTER_BUTTON_STATE_RELEASED)
357 return;
358
Daniel Stone96d47c02013-11-19 11:37:12 +0100359 /* Invalidate all active modifier bindings. */
360 wl_list_for_each(b, &compositor->modifier_binding_list, link)
361 b->key = button;
362
Giulio Camuffo24b98d02014-10-03 23:36:34 +0300363 wl_list_for_each_safe(b, tmp, &compositor->button_binding_list, link) {
Derek Foreman99a6a2d2015-07-15 13:00:43 -0500364 if (b->button == button &&
365 b->modifier == pointer->seat->modifier_state) {
Ander Conselvan de Oliveiracbdebc22013-02-21 18:35:16 +0200366 weston_button_binding_handler_t handler = b->handler;
Derek Foreman99a6a2d2015-07-15 13:00:43 -0500367 handler(pointer, time, button, b->data);
Ander Conselvan de Oliveiracbdebc22013-02-21 18:35:16 +0200368 }
369 }
370}
371
Derek Foreman2e6485c2015-07-15 13:00:34 -0500372void
Neil Robertsa28c6932013-10-03 16:43:04 +0100373weston_compositor_run_touch_binding(struct weston_compositor *compositor,
Derek Foreman99a6a2d2015-07-15 13:00:43 -0500374 struct weston_touch *touch, uint32_t time,
Neil Robertsa28c6932013-10-03 16:43:04 +0100375 int touch_type)
376{
Giulio Camuffo24b98d02014-10-03 23:36:34 +0300377 struct weston_binding *b, *tmp;
Neil Robertsa28c6932013-10-03 16:43:04 +0100378
Derek Foreman99a6a2d2015-07-15 13:00:43 -0500379 if (touch->num_tp != 1 || touch_type != WL_TOUCH_DOWN)
Neil Robertsa28c6932013-10-03 16:43:04 +0100380 return;
381
Giulio Camuffo24b98d02014-10-03 23:36:34 +0300382 wl_list_for_each_safe(b, tmp, &compositor->touch_binding_list, link) {
Derek Foreman99a6a2d2015-07-15 13:00:43 -0500383 if (b->modifier == touch->seat->modifier_state) {
Neil Robertsa28c6932013-10-03 16:43:04 +0100384 weston_touch_binding_handler_t handler = b->handler;
Derek Foreman99a6a2d2015-07-15 13:00:43 -0500385 handler(touch, time, b->data);
Neil Robertsa28c6932013-10-03 16:43:04 +0100386 }
387 }
388}
389
Derek Foreman2e6485c2015-07-15 13:00:34 -0500390int
Ander Conselvan de Oliveiracbdebc22013-02-21 18:35:16 +0200391weston_compositor_run_axis_binding(struct weston_compositor *compositor,
Derek Foreman99a6a2d2015-07-15 13:00:43 -0500392 struct weston_pointer *pointer,
Ander Conselvan de Oliveiracbdebc22013-02-21 18:35:16 +0200393 uint32_t time, uint32_t axis,
394 wl_fixed_t value)
395{
Giulio Camuffo24b98d02014-10-03 23:36:34 +0300396 struct weston_binding *b, *tmp;
Ander Conselvan de Oliveiracbdebc22013-02-21 18:35:16 +0200397
Daniel Stone96d47c02013-11-19 11:37:12 +0100398 /* Invalidate all active modifier bindings. */
399 wl_list_for_each(b, &compositor->modifier_binding_list, link)
400 b->key = axis;
401
Giulio Camuffo24b98d02014-10-03 23:36:34 +0300402 wl_list_for_each_safe(b, tmp, &compositor->axis_binding_list, link) {
Derek Foreman99a6a2d2015-07-15 13:00:43 -0500403 if (b->axis == axis &&
404 b->modifier == pointer->seat->modifier_state) {
Ander Conselvan de Oliveiracbdebc22013-02-21 18:35:16 +0200405 weston_axis_binding_handler_t handler = b->handler;
Derek Foreman99a6a2d2015-07-15 13:00:43 -0500406 handler(pointer, time, axis, value, b->data);
Rune K. Svendsen14b2fe72013-03-07 21:50:00 +0100407 return 1;
Ander Conselvan de Oliveiracbdebc22013-02-21 18:35:16 +0200408 }
409 }
Rune K. Svendsen14b2fe72013-03-07 21:50:00 +0100410
411 return 0;
Ander Conselvan de Oliveiracbdebc22013-02-21 18:35:16 +0200412}
413
Derek Foreman2e6485c2015-07-15 13:00:34 -0500414int
Ander Conselvan de Oliveiracbdebc22013-02-21 18:35:16 +0200415weston_compositor_run_debug_binding(struct weston_compositor *compositor,
Derek Foreman99a6a2d2015-07-15 13:00:43 -0500416 struct weston_keyboard *keyboard,
Ander Conselvan de Oliveiracbdebc22013-02-21 18:35:16 +0200417 uint32_t time, uint32_t key,
418 enum wl_keyboard_key_state state)
419{
420 weston_key_binding_handler_t handler;
Giulio Camuffo24b98d02014-10-03 23:36:34 +0300421 struct weston_binding *binding, *tmp;
Ander Conselvan de Oliveiracbdebc22013-02-21 18:35:16 +0200422 int count = 0;
423
Giulio Camuffo24b98d02014-10-03 23:36:34 +0300424 wl_list_for_each_safe(binding, tmp, &compositor->debug_binding_list, link) {
Ander Conselvan de Oliveiracbdebc22013-02-21 18:35:16 +0200425 if (key != binding->key)
426 continue;
427
428 count++;
429 handler = binding->handler;
Derek Foreman99a6a2d2015-07-15 13:00:43 -0500430 handler(keyboard, time, key, binding->data);
Ander Conselvan de Oliveiracbdebc22013-02-21 18:35:16 +0200431 }
432
433 return count;
434}
Pekka Paalanen2829f7c2015-02-19 17:02:13 +0200435
436struct debug_binding_grab {
437 struct weston_keyboard_grab grab;
438 struct weston_seat *seat;
439 uint32_t key[2];
440 int key_released[2];
441};
442
443static void
444debug_binding_key(struct weston_keyboard_grab *grab, uint32_t time,
445 uint32_t key, uint32_t state)
446{
447 struct debug_binding_grab *db = (struct debug_binding_grab *) grab;
448 struct weston_compositor *ec = db->seat->compositor;
449 struct wl_display *display = ec->wl_display;
450 struct wl_resource *resource;
451 uint32_t serial;
452 int send = 0, terminate = 0;
453 int check_binding = 1;
454 int i;
455 struct wl_list *resource_list;
456
457 if (state == WL_KEYBOARD_KEY_STATE_RELEASED) {
458 /* Do not run bindings on key releases */
459 check_binding = 0;
460
461 for (i = 0; i < 2; i++)
462 if (key == db->key[i])
463 db->key_released[i] = 1;
464
465 if (db->key_released[0] && db->key_released[1]) {
466 /* All key releases been swalled so end the grab */
467 terminate = 1;
468 } else if (key != db->key[0] && key != db->key[1]) {
469 /* Should not swallow release of other keys */
470 send = 1;
471 }
472 } else if (key == db->key[0] && !db->key_released[0]) {
473 /* Do not check bindings for the first press of the binding
474 * key. This allows it to be used as a debug shortcut.
475 * We still need to swallow this event. */
476 check_binding = 0;
477 } else if (db->key[1]) {
478 /* If we already ran a binding don't process another one since
479 * we can't keep track of all the binding keys that were
480 * pressed in order to swallow the release events. */
481 send = 1;
482 check_binding = 0;
483 }
484
485 if (check_binding) {
Derek Foreman99a6a2d2015-07-15 13:00:43 -0500486 if (weston_compositor_run_debug_binding(ec, grab->keyboard,
487 time, key, state)) {
Pekka Paalanen2829f7c2015-02-19 17:02:13 +0200488 /* We ran a binding so swallow the press and keep the
489 * grab to swallow the released too. */
490 send = 0;
491 terminate = 0;
492 db->key[1] = key;
493 } else {
494 /* Terminate the grab since the key pressed is not a
495 * debug binding key. */
496 send = 1;
497 terminate = 1;
498 }
499 }
500
501 if (send) {
502 serial = wl_display_next_serial(display);
503 resource_list = &grab->keyboard->focus_resource_list;
504 wl_resource_for_each(resource, resource_list) {
505 wl_keyboard_send_key(resource, serial, time, key, state);
506 }
507 }
508
509 if (terminate) {
510 weston_keyboard_end_grab(grab->keyboard);
511 if (grab->keyboard->input_method_resource)
512 grab->keyboard->grab = &grab->keyboard->input_method_grab;
513 free(db);
514 }
515}
516
517static void
518debug_binding_modifiers(struct weston_keyboard_grab *grab, uint32_t serial,
519 uint32_t mods_depressed, uint32_t mods_latched,
520 uint32_t mods_locked, uint32_t group)
521{
522 struct wl_resource *resource;
523 struct wl_list *resource_list;
524
525 resource_list = &grab->keyboard->focus_resource_list;
526
527 wl_resource_for_each(resource, resource_list) {
528 wl_keyboard_send_modifiers(resource, serial, mods_depressed,
529 mods_latched, mods_locked, group);
530 }
531}
532
533static void
534debug_binding_cancel(struct weston_keyboard_grab *grab)
535{
536 struct debug_binding_grab *db = (struct debug_binding_grab *) grab;
537
538 weston_keyboard_end_grab(grab->keyboard);
539 free(db);
540}
541
542struct weston_keyboard_grab_interface debug_binding_keyboard_grab = {
543 debug_binding_key,
544 debug_binding_modifiers,
545 debug_binding_cancel,
546};
547
548static void
Derek Foreman8ae2db52015-07-15 13:00:36 -0500549debug_binding(struct weston_keyboard *keyboard, uint32_t time,
550 uint32_t key, void *data)
Pekka Paalanen2829f7c2015-02-19 17:02:13 +0200551{
552 struct debug_binding_grab *grab;
553
554 grab = calloc(1, sizeof *grab);
555 if (!grab)
556 return;
557
Derek Foreman8ae2db52015-07-15 13:00:36 -0500558 grab->seat = keyboard->seat;
Pekka Paalanen2829f7c2015-02-19 17:02:13 +0200559 grab->key[0] = key;
560 grab->grab.interface = &debug_binding_keyboard_grab;
Derek Foreman8ae2db52015-07-15 13:00:36 -0500561 weston_keyboard_start_grab(keyboard, &grab->grab);
Pekka Paalanen2829f7c2015-02-19 17:02:13 +0200562}
563
564/** Install the trigger binding for debug bindings.
565 *
566 * \param compositor The compositor.
567 * \param mod The modifier.
568 *
569 * This will add a key binding for modifier+SHIFT+SPACE that will trigger
570 * debug key bindings.
571 */
572WL_EXPORT void
573weston_install_debug_key_binding(struct weston_compositor *compositor,
574 uint32_t mod)
575{
576 weston_compositor_add_key_binding(compositor, KEY_SPACE,
577 mod | MODIFIER_SHIFT,
578 debug_binding, NULL);
579}