blob: e339454c5995fea3f672d55332beb48810bf04c2 [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
178WL_EXPORT void
179weston_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
Giulio Camuffoa20ca812014-11-22 11:16:56 +0200257install_binding_grab(struct weston_seat *seat, uint32_t time, uint32_t key,
258 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;
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400265 weston_keyboard_start_grab(seat->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. */
275 if (focus && seat->keyboard->focus == focus) {
276 weston_keyboard_set_focus(seat->keyboard, NULL);
277 weston_keyboard_set_focus(seat->keyboard, focus);
278 }
Ander Conselvan de Oliveiracbdebc22013-02-21 18:35:16 +0200279}
280
Pekka Paalanen86b53962014-11-19 13:43:32 +0200281WL_EXPORT void
Ander Conselvan de Oliveiracbdebc22013-02-21 18:35:16 +0200282weston_compositor_run_key_binding(struct weston_compositor *compositor,
283 struct weston_seat *seat,
284 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;
Ander Conselvan de Oliveiracbdebc22013-02-21 18:35:16 +0200289
290 if (state == WL_KEYBOARD_KEY_STATE_RELEASED)
Pekka Paalanen86b53962014-11-19 13:43:32 +0200291 return;
Ander Conselvan de Oliveiracbdebc22013-02-21 18:35:16 +0200292
Daniel Stone96d47c02013-11-19 11:37:12 +0100293 /* Invalidate all active modifier bindings. */
294 wl_list_for_each(b, &compositor->modifier_binding_list, link)
295 b->key = key;
296
Giulio Camuffo24b98d02014-10-03 23:36:34 +0300297 wl_list_for_each_safe(b, tmp, &compositor->key_binding_list, link) {
Ander Conselvan de Oliveiracbdebc22013-02-21 18:35:16 +0200298 if (b->key == key && b->modifier == seat->modifier_state) {
299 weston_key_binding_handler_t handler = b->handler;
Giulio Camuffoa20ca812014-11-22 11:16:56 +0200300 focus = seat->keyboard->focus;
Kristian Høgsberge3148752013-05-06 23:19:49 -0400301 handler(seat, time, key, b->data);
Ander Conselvan de Oliveiracbdebc22013-02-21 18:35:16 +0200302
303 /* If this was a key binding and it didn't
304 * install a keyboard grab, install one now to
Giulio Camuffo943b46e2014-12-05 18:02:58 +0200305 * swallow the key press. */
Kristian Høgsberge3148752013-05-06 23:19:49 -0400306 if (seat->keyboard->grab ==
307 &seat->keyboard->default_grab)
Giulio Camuffoa20ca812014-11-22 11:16:56 +0200308 install_binding_grab(seat, time, key, focus);
Ander Conselvan de Oliveiracbdebc22013-02-21 18:35:16 +0200309 }
310 }
311}
312
313WL_EXPORT void
Daniel Stone96d47c02013-11-19 11:37:12 +0100314weston_compositor_run_modifier_binding(struct weston_compositor *compositor,
315 struct weston_seat *seat,
316 enum weston_keyboard_modifier modifier,
317 enum wl_keyboard_key_state state)
318{
Giulio Camuffo24b98d02014-10-03 23:36:34 +0300319 struct weston_binding *b, *tmp;
Daniel Stone96d47c02013-11-19 11:37:12 +0100320
Emilio Pozuelo Monfort1539ea22013-11-27 10:34:32 +0100321 if (seat->keyboard->grab != &seat->keyboard->default_grab)
322 return;
323
Giulio Camuffo24b98d02014-10-03 23:36:34 +0300324 wl_list_for_each_safe(b, tmp, &compositor->modifier_binding_list, link) {
Daniel Stone96d47c02013-11-19 11:37:12 +0100325 weston_modifier_binding_handler_t handler = b->handler;
326
327 if (b->modifier != modifier)
328 continue;
329
330 /* Prime the modifier binding. */
331 if (state == WL_KEYBOARD_KEY_STATE_PRESSED) {
332 b->key = 0;
333 continue;
334 }
335 /* Ignore the binding if a key was pressed in between. */
336 else if (b->key != 0) {
337 return;
338 }
339
340 handler(seat, modifier, b->data);
341 }
342}
343
344WL_EXPORT void
Ander Conselvan de Oliveiracbdebc22013-02-21 18:35:16 +0200345weston_compositor_run_button_binding(struct weston_compositor *compositor,
346 struct weston_seat *seat,
347 uint32_t time, uint32_t button,
348 enum wl_pointer_button_state state)
349{
Giulio Camuffo24b98d02014-10-03 23:36:34 +0300350 struct weston_binding *b, *tmp;
Ander Conselvan de Oliveiracbdebc22013-02-21 18:35:16 +0200351
352 if (state == WL_POINTER_BUTTON_STATE_RELEASED)
353 return;
354
Daniel Stone96d47c02013-11-19 11:37:12 +0100355 /* Invalidate all active modifier bindings. */
356 wl_list_for_each(b, &compositor->modifier_binding_list, link)
357 b->key = button;
358
Giulio Camuffo24b98d02014-10-03 23:36:34 +0300359 wl_list_for_each_safe(b, tmp, &compositor->button_binding_list, link) {
Ander Conselvan de Oliveiracbdebc22013-02-21 18:35:16 +0200360 if (b->button == button && b->modifier == seat->modifier_state) {
361 weston_button_binding_handler_t handler = b->handler;
Kristian Høgsberge3148752013-05-06 23:19:49 -0400362 handler(seat, time, button, b->data);
Ander Conselvan de Oliveiracbdebc22013-02-21 18:35:16 +0200363 }
364 }
365}
366
Neil Robertsa28c6932013-10-03 16:43:04 +0100367WL_EXPORT void
368weston_compositor_run_touch_binding(struct weston_compositor *compositor,
369 struct weston_seat *seat, uint32_t time,
370 int touch_type)
371{
Giulio Camuffo24b98d02014-10-03 23:36:34 +0300372 struct weston_binding *b, *tmp;
Neil Robertsa28c6932013-10-03 16:43:04 +0100373
Jonas Ådahl9484b692013-12-02 22:05:03 +0100374 if (seat->touch->num_tp != 1 || touch_type != WL_TOUCH_DOWN)
Neil Robertsa28c6932013-10-03 16:43:04 +0100375 return;
376
Giulio Camuffo24b98d02014-10-03 23:36:34 +0300377 wl_list_for_each_safe(b, tmp, &compositor->touch_binding_list, link) {
Neil Robertsa28c6932013-10-03 16:43:04 +0100378 if (b->modifier == seat->modifier_state) {
379 weston_touch_binding_handler_t handler = b->handler;
380 handler(seat, time, b->data);
381 }
382 }
383}
384
Rune K. Svendsen14b2fe72013-03-07 21:50:00 +0100385WL_EXPORT int
Ander Conselvan de Oliveiracbdebc22013-02-21 18:35:16 +0200386weston_compositor_run_axis_binding(struct weston_compositor *compositor,
387 struct weston_seat *seat,
388 uint32_t time, uint32_t axis,
389 wl_fixed_t value)
390{
Giulio Camuffo24b98d02014-10-03 23:36:34 +0300391 struct weston_binding *b, *tmp;
Ander Conselvan de Oliveiracbdebc22013-02-21 18:35:16 +0200392
Daniel Stone96d47c02013-11-19 11:37:12 +0100393 /* Invalidate all active modifier bindings. */
394 wl_list_for_each(b, &compositor->modifier_binding_list, link)
395 b->key = axis;
396
Giulio Camuffo24b98d02014-10-03 23:36:34 +0300397 wl_list_for_each_safe(b, tmp, &compositor->axis_binding_list, link) {
Ander Conselvan de Oliveiracbdebc22013-02-21 18:35:16 +0200398 if (b->axis == axis && b->modifier == seat->modifier_state) {
399 weston_axis_binding_handler_t handler = b->handler;
Kristian Høgsberge3148752013-05-06 23:19:49 -0400400 handler(seat, time, axis, value, b->data);
Rune K. Svendsen14b2fe72013-03-07 21:50:00 +0100401 return 1;
Ander Conselvan de Oliveiracbdebc22013-02-21 18:35:16 +0200402 }
403 }
Rune K. Svendsen14b2fe72013-03-07 21:50:00 +0100404
405 return 0;
Ander Conselvan de Oliveiracbdebc22013-02-21 18:35:16 +0200406}
407
408WL_EXPORT int
409weston_compositor_run_debug_binding(struct weston_compositor *compositor,
410 struct weston_seat *seat,
411 uint32_t time, uint32_t key,
412 enum wl_keyboard_key_state state)
413{
414 weston_key_binding_handler_t handler;
Giulio Camuffo24b98d02014-10-03 23:36:34 +0300415 struct weston_binding *binding, *tmp;
Ander Conselvan de Oliveiracbdebc22013-02-21 18:35:16 +0200416 int count = 0;
417
Giulio Camuffo24b98d02014-10-03 23:36:34 +0300418 wl_list_for_each_safe(binding, tmp, &compositor->debug_binding_list, link) {
Ander Conselvan de Oliveiracbdebc22013-02-21 18:35:16 +0200419 if (key != binding->key)
420 continue;
421
422 count++;
423 handler = binding->handler;
Kristian Høgsberge3148752013-05-06 23:19:49 -0400424 handler(seat, time, key, binding->data);
Ander Conselvan de Oliveiracbdebc22013-02-21 18:35:16 +0200425 }
426
427 return count;
428}
Pekka Paalanen2829f7c2015-02-19 17:02:13 +0200429
430struct debug_binding_grab {
431 struct weston_keyboard_grab grab;
432 struct weston_seat *seat;
433 uint32_t key[2];
434 int key_released[2];
435};
436
437static void
438debug_binding_key(struct weston_keyboard_grab *grab, uint32_t time,
439 uint32_t key, uint32_t state)
440{
441 struct debug_binding_grab *db = (struct debug_binding_grab *) grab;
442 struct weston_compositor *ec = db->seat->compositor;
443 struct wl_display *display = ec->wl_display;
444 struct wl_resource *resource;
445 uint32_t serial;
446 int send = 0, terminate = 0;
447 int check_binding = 1;
448 int i;
449 struct wl_list *resource_list;
450
451 if (state == WL_KEYBOARD_KEY_STATE_RELEASED) {
452 /* Do not run bindings on key releases */
453 check_binding = 0;
454
455 for (i = 0; i < 2; i++)
456 if (key == db->key[i])
457 db->key_released[i] = 1;
458
459 if (db->key_released[0] && db->key_released[1]) {
460 /* All key releases been swalled so end the grab */
461 terminate = 1;
462 } else if (key != db->key[0] && key != db->key[1]) {
463 /* Should not swallow release of other keys */
464 send = 1;
465 }
466 } else if (key == db->key[0] && !db->key_released[0]) {
467 /* Do not check bindings for the first press of the binding
468 * key. This allows it to be used as a debug shortcut.
469 * We still need to swallow this event. */
470 check_binding = 0;
471 } else if (db->key[1]) {
472 /* If we already ran a binding don't process another one since
473 * we can't keep track of all the binding keys that were
474 * pressed in order to swallow the release events. */
475 send = 1;
476 check_binding = 0;
477 }
478
479 if (check_binding) {
480 if (weston_compositor_run_debug_binding(ec, db->seat, time,
481 key, state)) {
482 /* We ran a binding so swallow the press and keep the
483 * grab to swallow the released too. */
484 send = 0;
485 terminate = 0;
486 db->key[1] = key;
487 } else {
488 /* Terminate the grab since the key pressed is not a
489 * debug binding key. */
490 send = 1;
491 terminate = 1;
492 }
493 }
494
495 if (send) {
496 serial = wl_display_next_serial(display);
497 resource_list = &grab->keyboard->focus_resource_list;
498 wl_resource_for_each(resource, resource_list) {
499 wl_keyboard_send_key(resource, serial, time, key, state);
500 }
501 }
502
503 if (terminate) {
504 weston_keyboard_end_grab(grab->keyboard);
505 if (grab->keyboard->input_method_resource)
506 grab->keyboard->grab = &grab->keyboard->input_method_grab;
507 free(db);
508 }
509}
510
511static void
512debug_binding_modifiers(struct weston_keyboard_grab *grab, uint32_t serial,
513 uint32_t mods_depressed, uint32_t mods_latched,
514 uint32_t mods_locked, uint32_t group)
515{
516 struct wl_resource *resource;
517 struct wl_list *resource_list;
518
519 resource_list = &grab->keyboard->focus_resource_list;
520
521 wl_resource_for_each(resource, resource_list) {
522 wl_keyboard_send_modifiers(resource, serial, mods_depressed,
523 mods_latched, mods_locked, group);
524 }
525}
526
527static void
528debug_binding_cancel(struct weston_keyboard_grab *grab)
529{
530 struct debug_binding_grab *db = (struct debug_binding_grab *) grab;
531
532 weston_keyboard_end_grab(grab->keyboard);
533 free(db);
534}
535
536struct weston_keyboard_grab_interface debug_binding_keyboard_grab = {
537 debug_binding_key,
538 debug_binding_modifiers,
539 debug_binding_cancel,
540};
541
542static void
543debug_binding(struct weston_seat *seat, uint32_t time, uint32_t key, void *data)
544{
545 struct debug_binding_grab *grab;
546
547 grab = calloc(1, sizeof *grab);
548 if (!grab)
549 return;
550
551 grab->seat = seat;
552 grab->key[0] = key;
553 grab->grab.interface = &debug_binding_keyboard_grab;
554 weston_keyboard_start_grab(seat->keyboard, &grab->grab);
555}
556
557/** Install the trigger binding for debug bindings.
558 *
559 * \param compositor The compositor.
560 * \param mod The modifier.
561 *
562 * This will add a key binding for modifier+SHIFT+SPACE that will trigger
563 * debug key bindings.
564 */
565WL_EXPORT void
566weston_install_debug_key_binding(struct weston_compositor *compositor,
567 uint32_t mod)
568{
569 weston_compositor_add_key_binding(compositor, KEY_SPACE,
570 mod | MODIFIER_SHIFT,
571 debug_binding, NULL);
572}