blob: 2136652241e32c7fcdfb817c46c86b3bd0cae722 [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
Jussi Kukkonen649bbce2016-07-19 14:16:27 +030028#include <stdint.h>
Ander Conselvan de Oliveiracbdebc22013-02-21 18:35:16 +020029#include <stdlib.h>
Pekka Paalanen2829f7c2015-02-19 17:02:13 +020030#include <linux/input.h>
Ander Conselvan de Oliveiracbdebc22013-02-21 18:35:16 +020031
32#include "compositor.h"
Jon Cruz867d50e2015-06-15 15:37:10 -070033#include "shared/helpers.h"
Ander Conselvan de Oliveiracbdebc22013-02-21 18:35:16 +020034
35struct weston_binding {
36 uint32_t key;
37 uint32_t button;
38 uint32_t axis;
39 uint32_t modifier;
40 void *handler;
41 void *data;
42 struct wl_list link;
43};
44
45static struct weston_binding *
46weston_compositor_add_binding(struct weston_compositor *compositor,
47 uint32_t key, uint32_t button, uint32_t axis,
48 uint32_t modifier, void *handler, void *data)
49{
50 struct weston_binding *binding;
51
52 binding = malloc(sizeof *binding);
53 if (binding == NULL)
54 return NULL;
55
56 binding->key = key;
57 binding->button = button;
58 binding->axis = axis;
59 binding->modifier = modifier;
60 binding->handler = handler;
61 binding->data = data;
62
63 return binding;
64}
65
66WL_EXPORT struct weston_binding *
67weston_compositor_add_key_binding(struct weston_compositor *compositor,
68 uint32_t key, uint32_t modifier,
69 weston_key_binding_handler_t handler,
70 void *data)
71{
72 struct weston_binding *binding;
73
74 binding = weston_compositor_add_binding(compositor, key, 0, 0,
75 modifier, handler, data);
76 if (binding == NULL)
77 return NULL;
78
79 wl_list_insert(compositor->key_binding_list.prev, &binding->link);
80
81 return binding;
82}
83
84WL_EXPORT struct weston_binding *
Daniel Stone96d47c02013-11-19 11:37:12 +010085weston_compositor_add_modifier_binding(struct weston_compositor *compositor,
86 uint32_t modifier,
87 weston_modifier_binding_handler_t handler,
88 void *data)
89{
90 struct weston_binding *binding;
91
92 binding = weston_compositor_add_binding(compositor, 0, 0, 0,
93 modifier, handler, data);
94 if (binding == NULL)
95 return NULL;
96
97 wl_list_insert(compositor->modifier_binding_list.prev, &binding->link);
98
99 return binding;
100}
101
102WL_EXPORT struct weston_binding *
Ander Conselvan de Oliveiracbdebc22013-02-21 18:35:16 +0200103weston_compositor_add_button_binding(struct weston_compositor *compositor,
104 uint32_t button, uint32_t modifier,
105 weston_button_binding_handler_t handler,
106 void *data)
107{
108 struct weston_binding *binding;
109
110 binding = weston_compositor_add_binding(compositor, 0, button, 0,
111 modifier, handler, data);
112 if (binding == NULL)
113 return NULL;
114
115 wl_list_insert(compositor->button_binding_list.prev, &binding->link);
116
117 return binding;
118}
119
120WL_EXPORT struct weston_binding *
Neil Robertsa28c6932013-10-03 16:43:04 +0100121weston_compositor_add_touch_binding(struct weston_compositor *compositor,
122 uint32_t modifier,
123 weston_touch_binding_handler_t handler,
124 void *data)
125{
126 struct weston_binding *binding;
127
128 binding = weston_compositor_add_binding(compositor, 0, 0, 0,
129 modifier, handler, data);
130 if (binding == NULL)
131 return NULL;
132
133 wl_list_insert(compositor->touch_binding_list.prev, &binding->link);
134
135 return binding;
136}
137
138WL_EXPORT struct weston_binding *
Ander Conselvan de Oliveiracbdebc22013-02-21 18:35:16 +0200139weston_compositor_add_axis_binding(struct weston_compositor *compositor,
140 uint32_t axis, uint32_t modifier,
141 weston_axis_binding_handler_t handler,
142 void *data)
143{
144 struct weston_binding *binding;
145
146 binding = weston_compositor_add_binding(compositor, 0, 0, axis,
147 modifier, handler, data);
148 if (binding == NULL)
149 return NULL;
150
151 wl_list_insert(compositor->axis_binding_list.prev, &binding->link);
152
153 return binding;
154}
155
156WL_EXPORT struct weston_binding *
157weston_compositor_add_debug_binding(struct weston_compositor *compositor,
158 uint32_t key,
159 weston_key_binding_handler_t handler,
160 void *data)
161{
162 struct weston_binding *binding;
163
164 binding = weston_compositor_add_binding(compositor, key, 0, 0, 0,
165 handler, data);
166
167 wl_list_insert(compositor->debug_binding_list.prev, &binding->link);
168
169 return binding;
170}
171
172WL_EXPORT void
173weston_binding_destroy(struct weston_binding *binding)
174{
175 wl_list_remove(&binding->link);
176 free(binding);
177}
178
Derek Foreman2e6485c2015-07-15 13:00:34 -0500179void
Ander Conselvan de Oliveiracbdebc22013-02-21 18:35:16 +0200180weston_binding_list_destroy_all(struct wl_list *list)
181{
182 struct weston_binding *binding, *tmp;
183
184 wl_list_for_each_safe(binding, tmp, list, link)
185 weston_binding_destroy(binding);
186}
187
188struct binding_keyboard_grab {
189 uint32_t key;
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400190 struct weston_keyboard_grab grab;
Ander Conselvan de Oliveiracbdebc22013-02-21 18:35:16 +0200191};
192
193static void
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400194binding_key(struct weston_keyboard_grab *grab,
Ander Conselvan de Oliveiracbdebc22013-02-21 18:35:16 +0200195 uint32_t time, uint32_t key, uint32_t state_w)
196{
197 struct binding_keyboard_grab *b =
198 container_of(grab, struct binding_keyboard_grab, grab);
199 struct wl_resource *resource;
Ander Conselvan de Oliveiracbdebc22013-02-21 18:35:16 +0200200 enum wl_keyboard_key_state state = state_w;
201 uint32_t serial;
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400202 struct weston_keyboard *keyboard = grab->keyboard;
Rob Bradford880ebc72013-07-22 17:31:38 +0100203 struct wl_display *display = keyboard->seat->compositor->wl_display;
Ander Conselvan de Oliveiracbdebc22013-02-21 18:35:16 +0200204
Ander Conselvan de Oliveiracbdebc22013-02-21 18:35:16 +0200205 if (key == b->key) {
206 if (state == WL_KEYBOARD_KEY_STATE_RELEASED) {
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400207 weston_keyboard_end_grab(grab->keyboard);
Ander Conselvan de Oliveiracbdebc22013-02-21 18:35:16 +0200208 if (keyboard->input_method_resource)
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400209 keyboard->grab = &keyboard->input_method_grab;
Ander Conselvan de Oliveiracbdebc22013-02-21 18:35:16 +0200210 free(b);
Giulio Camuffo943b46e2014-12-05 18:02:58 +0200211 } else {
212 /* Don't send the key press event for the binding key */
213 return;
Ander Conselvan de Oliveiracbdebc22013-02-21 18:35:16 +0200214 }
Giulio Camuffoa20ca812014-11-22 11:16:56 +0200215 }
216 if (!wl_list_empty(&keyboard->focus_resource_list)) {
Ander Conselvan de Oliveiracbdebc22013-02-21 18:35:16 +0200217 serial = wl_display_next_serial(display);
Neil Roberts96d790e2013-09-19 17:32:00 +0100218 wl_resource_for_each(resource, &keyboard->focus_resource_list) {
219 wl_keyboard_send_key(resource,
220 serial,
221 time,
222 key,
223 state);
224 }
Ander Conselvan de Oliveiracbdebc22013-02-21 18:35:16 +0200225 }
226}
227
228static void
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400229binding_modifiers(struct weston_keyboard_grab *grab, uint32_t serial,
Ander Conselvan de Oliveiracbdebc22013-02-21 18:35:16 +0200230 uint32_t mods_depressed, uint32_t mods_latched,
231 uint32_t mods_locked, uint32_t group)
232{
233 struct wl_resource *resource;
234
Neil Roberts96d790e2013-09-19 17:32:00 +0100235 wl_resource_for_each(resource, &grab->keyboard->focus_resource_list) {
236 wl_keyboard_send_modifiers(resource, serial, mods_depressed,
237 mods_latched, mods_locked, group);
238 }
Ander Conselvan de Oliveiracbdebc22013-02-21 18:35:16 +0200239}
240
Jonas Ådahl1ea343e2013-10-25 23:18:05 +0200241static void
242binding_cancel(struct weston_keyboard_grab *grab)
243{
244 struct binding_keyboard_grab *binding_grab =
245 container_of(grab, struct binding_keyboard_grab, grab);
246
247 weston_keyboard_end_grab(grab->keyboard);
248 free(binding_grab);
249}
250
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400251static const struct weston_keyboard_grab_interface binding_grab = {
Ander Conselvan de Oliveiracbdebc22013-02-21 18:35:16 +0200252 binding_key,
253 binding_modifiers,
Jonas Ådahl1ea343e2013-10-25 23:18:05 +0200254 binding_cancel,
Ander Conselvan de Oliveiracbdebc22013-02-21 18:35:16 +0200255};
256
257static void
Derek Foremanb591a302015-07-15 13:00:42 -0500258install_binding_grab(struct weston_keyboard *keyboard, uint32_t time,
259 uint32_t key, struct weston_surface *focus)
Ander Conselvan de Oliveiracbdebc22013-02-21 18:35:16 +0200260{
261 struct binding_keyboard_grab *grab;
262
263 grab = malloc(sizeof *grab);
264 grab->key = key;
265 grab->grab.interface = &binding_grab;
Derek Foremanb591a302015-07-15 13:00:42 -0500266 weston_keyboard_start_grab(keyboard, &grab->grab);
Giulio Camuffoa20ca812014-11-22 11:16:56 +0200267
268 /* Notify the surface which had the focus before this binding
269 * triggered that we stole a keypress from under it, by forcing
270 * a wl_keyboard leave/enter pair. The enter event will contain
271 * the pressed key in the keys array, so the client will know
272 * the exact state of the keyboard.
273 * If the old focus surface is different than the new one it
274 * means it was changed in the binding handler, so it received
275 * the enter event already. */
Derek Foremanb591a302015-07-15 13:00:42 -0500276 if (focus && keyboard->focus == focus) {
277 weston_keyboard_set_focus(keyboard, NULL);
278 weston_keyboard_set_focus(keyboard, focus);
Giulio Camuffoa20ca812014-11-22 11:16:56 +0200279 }
Ander Conselvan de Oliveiracbdebc22013-02-21 18:35:16 +0200280}
281
Derek Foreman2e6485c2015-07-15 13:00:34 -0500282void
Ander Conselvan de Oliveiracbdebc22013-02-21 18:35:16 +0200283weston_compositor_run_key_binding(struct weston_compositor *compositor,
Derek Foreman99a6a2d2015-07-15 13:00:43 -0500284 struct weston_keyboard *keyboard,
Ander Conselvan de Oliveiracbdebc22013-02-21 18:35:16 +0200285 uint32_t time, uint32_t key,
286 enum wl_keyboard_key_state state)
287{
Giulio Camuffo24b98d02014-10-03 23:36:34 +0300288 struct weston_binding *b, *tmp;
Giulio Camuffoa20ca812014-11-22 11:16:56 +0200289 struct weston_surface *focus;
Derek Foreman99a6a2d2015-07-15 13:00:43 -0500290 struct weston_seat *seat = keyboard->seat;
Ander Conselvan de Oliveiracbdebc22013-02-21 18:35:16 +0200291
292 if (state == WL_KEYBOARD_KEY_STATE_RELEASED)
Pekka Paalanen86b53962014-11-19 13:43:32 +0200293 return;
Ander Conselvan de Oliveiracbdebc22013-02-21 18:35:16 +0200294
Daniel Stone96d47c02013-11-19 11:37:12 +0100295 /* Invalidate all active modifier bindings. */
296 wl_list_for_each(b, &compositor->modifier_binding_list, link)
297 b->key = key;
298
Giulio Camuffo24b98d02014-10-03 23:36:34 +0300299 wl_list_for_each_safe(b, tmp, &compositor->key_binding_list, link) {
Ander Conselvan de Oliveiracbdebc22013-02-21 18:35:16 +0200300 if (b->key == key && b->modifier == seat->modifier_state) {
301 weston_key_binding_handler_t handler = b->handler;
Derek Foreman99a6a2d2015-07-15 13:00:43 -0500302 focus = keyboard->focus;
303 handler(keyboard, time, key, b->data);
Ander Conselvan de Oliveiracbdebc22013-02-21 18:35:16 +0200304
305 /* If this was a key binding and it didn't
306 * install a keyboard grab, install one now to
Giulio Camuffo943b46e2014-12-05 18:02:58 +0200307 * swallow the key press. */
Derek Foreman99a6a2d2015-07-15 13:00:43 -0500308 if (keyboard->grab ==
309 &keyboard->default_grab)
310 install_binding_grab(keyboard,
Derek Foremanb591a302015-07-15 13:00:42 -0500311 time,
312 key,
313 focus);
Ander Conselvan de Oliveiracbdebc22013-02-21 18:35:16 +0200314 }
315 }
316}
317
Derek Foreman2e6485c2015-07-15 13:00:34 -0500318void
Daniel Stone96d47c02013-11-19 11:37:12 +0100319weston_compositor_run_modifier_binding(struct weston_compositor *compositor,
Derek Foreman99a6a2d2015-07-15 13:00:43 -0500320 struct weston_keyboard *keyboard,
Daniel Stone96d47c02013-11-19 11:37:12 +0100321 enum weston_keyboard_modifier modifier,
322 enum wl_keyboard_key_state state)
323{
Giulio Camuffo24b98d02014-10-03 23:36:34 +0300324 struct weston_binding *b, *tmp;
Daniel Stone96d47c02013-11-19 11:37:12 +0100325
Derek Foreman99a6a2d2015-07-15 13:00:43 -0500326 if (keyboard->grab != &keyboard->default_grab)
Emilio Pozuelo Monfort1539ea22013-11-27 10:34:32 +0100327 return;
328
Giulio Camuffo24b98d02014-10-03 23:36:34 +0300329 wl_list_for_each_safe(b, tmp, &compositor->modifier_binding_list, link) {
Daniel Stone96d47c02013-11-19 11:37:12 +0100330 weston_modifier_binding_handler_t handler = b->handler;
331
332 if (b->modifier != modifier)
333 continue;
334
335 /* Prime the modifier binding. */
336 if (state == WL_KEYBOARD_KEY_STATE_PRESSED) {
337 b->key = 0;
338 continue;
339 }
340 /* Ignore the binding if a key was pressed in between. */
341 else if (b->key != 0) {
342 return;
343 }
344
Derek Foreman99a6a2d2015-07-15 13:00:43 -0500345 handler(keyboard, modifier, b->data);
Daniel Stone96d47c02013-11-19 11:37:12 +0100346 }
347}
348
Derek Foreman2e6485c2015-07-15 13:00:34 -0500349void
Ander Conselvan de Oliveiracbdebc22013-02-21 18:35:16 +0200350weston_compositor_run_button_binding(struct weston_compositor *compositor,
Derek Foreman99a6a2d2015-07-15 13:00:43 -0500351 struct weston_pointer *pointer,
Ander Conselvan de Oliveiracbdebc22013-02-21 18:35:16 +0200352 uint32_t time, uint32_t button,
353 enum wl_pointer_button_state state)
354{
Giulio Camuffo24b98d02014-10-03 23:36:34 +0300355 struct weston_binding *b, *tmp;
Ander Conselvan de Oliveiracbdebc22013-02-21 18:35:16 +0200356
357 if (state == WL_POINTER_BUTTON_STATE_RELEASED)
358 return;
359
Daniel Stone96d47c02013-11-19 11:37:12 +0100360 /* Invalidate all active modifier bindings. */
361 wl_list_for_each(b, &compositor->modifier_binding_list, link)
362 b->key = button;
363
Giulio Camuffo24b98d02014-10-03 23:36:34 +0300364 wl_list_for_each_safe(b, tmp, &compositor->button_binding_list, link) {
Derek Foreman99a6a2d2015-07-15 13:00:43 -0500365 if (b->button == button &&
366 b->modifier == pointer->seat->modifier_state) {
Ander Conselvan de Oliveiracbdebc22013-02-21 18:35:16 +0200367 weston_button_binding_handler_t handler = b->handler;
Derek Foreman99a6a2d2015-07-15 13:00:43 -0500368 handler(pointer, time, button, b->data);
Ander Conselvan de Oliveiracbdebc22013-02-21 18:35:16 +0200369 }
370 }
371}
372
Derek Foreman2e6485c2015-07-15 13:00:34 -0500373void
Neil Robertsa28c6932013-10-03 16:43:04 +0100374weston_compositor_run_touch_binding(struct weston_compositor *compositor,
Derek Foreman99a6a2d2015-07-15 13:00:43 -0500375 struct weston_touch *touch, uint32_t time,
Neil Robertsa28c6932013-10-03 16:43:04 +0100376 int touch_type)
377{
Giulio Camuffo24b98d02014-10-03 23:36:34 +0300378 struct weston_binding *b, *tmp;
Neil Robertsa28c6932013-10-03 16:43:04 +0100379
Derek Foreman99a6a2d2015-07-15 13:00:43 -0500380 if (touch->num_tp != 1 || touch_type != WL_TOUCH_DOWN)
Neil Robertsa28c6932013-10-03 16:43:04 +0100381 return;
382
Giulio Camuffo24b98d02014-10-03 23:36:34 +0300383 wl_list_for_each_safe(b, tmp, &compositor->touch_binding_list, link) {
Derek Foreman99a6a2d2015-07-15 13:00:43 -0500384 if (b->modifier == touch->seat->modifier_state) {
Neil Robertsa28c6932013-10-03 16:43:04 +0100385 weston_touch_binding_handler_t handler = b->handler;
Derek Foreman99a6a2d2015-07-15 13:00:43 -0500386 handler(touch, time, b->data);
Neil Robertsa28c6932013-10-03 16:43:04 +0100387 }
388 }
389}
390
Derek Foreman2e6485c2015-07-15 13:00:34 -0500391int
Ander Conselvan de Oliveiracbdebc22013-02-21 18:35:16 +0200392weston_compositor_run_axis_binding(struct weston_compositor *compositor,
Derek Foreman99a6a2d2015-07-15 13:00:43 -0500393 struct weston_pointer *pointer,
Peter Hutterer89b6a492016-01-18 15:58:17 +1000394 uint32_t time,
395 struct weston_pointer_axis_event *event)
Ander Conselvan de Oliveiracbdebc22013-02-21 18:35:16 +0200396{
Giulio Camuffo24b98d02014-10-03 23:36:34 +0300397 struct weston_binding *b, *tmp;
Ander Conselvan de Oliveiracbdebc22013-02-21 18:35:16 +0200398
Daniel Stone96d47c02013-11-19 11:37:12 +0100399 /* Invalidate all active modifier bindings. */
400 wl_list_for_each(b, &compositor->modifier_binding_list, link)
Peter Hutterer89b6a492016-01-18 15:58:17 +1000401 b->key = event->axis;
Daniel Stone96d47c02013-11-19 11:37:12 +0100402
Giulio Camuffo24b98d02014-10-03 23:36:34 +0300403 wl_list_for_each_safe(b, tmp, &compositor->axis_binding_list, link) {
Peter Hutterer89b6a492016-01-18 15:58:17 +1000404 if (b->axis == event->axis &&
Derek Foreman99a6a2d2015-07-15 13:00:43 -0500405 b->modifier == pointer->seat->modifier_state) {
Ander Conselvan de Oliveiracbdebc22013-02-21 18:35:16 +0200406 weston_axis_binding_handler_t handler = b->handler;
Peter Hutterer89b6a492016-01-18 15:58:17 +1000407 handler(pointer, time, event, b->data);
Rune K. Svendsen14b2fe72013-03-07 21:50:00 +0100408 return 1;
Ander Conselvan de Oliveiracbdebc22013-02-21 18:35:16 +0200409 }
410 }
Rune K. Svendsen14b2fe72013-03-07 21:50:00 +0100411
412 return 0;
Ander Conselvan de Oliveiracbdebc22013-02-21 18:35:16 +0200413}
414
Derek Foreman2e6485c2015-07-15 13:00:34 -0500415int
Ander Conselvan de Oliveiracbdebc22013-02-21 18:35:16 +0200416weston_compositor_run_debug_binding(struct weston_compositor *compositor,
Derek Foreman99a6a2d2015-07-15 13:00:43 -0500417 struct weston_keyboard *keyboard,
Ander Conselvan de Oliveiracbdebc22013-02-21 18:35:16 +0200418 uint32_t time, uint32_t key,
419 enum wl_keyboard_key_state state)
420{
421 weston_key_binding_handler_t handler;
Giulio Camuffo24b98d02014-10-03 23:36:34 +0300422 struct weston_binding *binding, *tmp;
Ander Conselvan de Oliveiracbdebc22013-02-21 18:35:16 +0200423 int count = 0;
424
Giulio Camuffo24b98d02014-10-03 23:36:34 +0300425 wl_list_for_each_safe(binding, tmp, &compositor->debug_binding_list, link) {
Ander Conselvan de Oliveiracbdebc22013-02-21 18:35:16 +0200426 if (key != binding->key)
427 continue;
428
429 count++;
430 handler = binding->handler;
Derek Foreman99a6a2d2015-07-15 13:00:43 -0500431 handler(keyboard, time, key, binding->data);
Ander Conselvan de Oliveiracbdebc22013-02-21 18:35:16 +0200432 }
433
434 return count;
435}
Pekka Paalanen2829f7c2015-02-19 17:02:13 +0200436
437struct debug_binding_grab {
438 struct weston_keyboard_grab grab;
439 struct weston_seat *seat;
440 uint32_t key[2];
441 int key_released[2];
442};
443
444static void
445debug_binding_key(struct weston_keyboard_grab *grab, uint32_t time,
446 uint32_t key, uint32_t state)
447{
448 struct debug_binding_grab *db = (struct debug_binding_grab *) grab;
449 struct weston_compositor *ec = db->seat->compositor;
450 struct wl_display *display = ec->wl_display;
451 struct wl_resource *resource;
452 uint32_t serial;
453 int send = 0, terminate = 0;
454 int check_binding = 1;
455 int i;
456 struct wl_list *resource_list;
457
458 if (state == WL_KEYBOARD_KEY_STATE_RELEASED) {
459 /* Do not run bindings on key releases */
460 check_binding = 0;
461
462 for (i = 0; i < 2; i++)
463 if (key == db->key[i])
464 db->key_released[i] = 1;
465
466 if (db->key_released[0] && db->key_released[1]) {
467 /* All key releases been swalled so end the grab */
468 terminate = 1;
469 } else if (key != db->key[0] && key != db->key[1]) {
470 /* Should not swallow release of other keys */
471 send = 1;
472 }
473 } else if (key == db->key[0] && !db->key_released[0]) {
474 /* Do not check bindings for the first press of the binding
475 * key. This allows it to be used as a debug shortcut.
476 * We still need to swallow this event. */
477 check_binding = 0;
478 } else if (db->key[1]) {
479 /* If we already ran a binding don't process another one since
480 * we can't keep track of all the binding keys that were
481 * pressed in order to swallow the release events. */
482 send = 1;
483 check_binding = 0;
484 }
485
486 if (check_binding) {
Derek Foreman99a6a2d2015-07-15 13:00:43 -0500487 if (weston_compositor_run_debug_binding(ec, grab->keyboard,
488 time, key, state)) {
Pekka Paalanen2829f7c2015-02-19 17:02:13 +0200489 /* We ran a binding so swallow the press and keep the
490 * grab to swallow the released too. */
491 send = 0;
492 terminate = 0;
493 db->key[1] = key;
494 } else {
495 /* Terminate the grab since the key pressed is not a
496 * debug binding key. */
497 send = 1;
498 terminate = 1;
499 }
500 }
501
502 if (send) {
503 serial = wl_display_next_serial(display);
504 resource_list = &grab->keyboard->focus_resource_list;
505 wl_resource_for_each(resource, resource_list) {
506 wl_keyboard_send_key(resource, serial, time, key, state);
507 }
508 }
509
510 if (terminate) {
511 weston_keyboard_end_grab(grab->keyboard);
512 if (grab->keyboard->input_method_resource)
513 grab->keyboard->grab = &grab->keyboard->input_method_grab;
514 free(db);
515 }
516}
517
518static void
519debug_binding_modifiers(struct weston_keyboard_grab *grab, uint32_t serial,
520 uint32_t mods_depressed, uint32_t mods_latched,
521 uint32_t mods_locked, uint32_t group)
522{
523 struct wl_resource *resource;
524 struct wl_list *resource_list;
525
526 resource_list = &grab->keyboard->focus_resource_list;
527
528 wl_resource_for_each(resource, resource_list) {
529 wl_keyboard_send_modifiers(resource, serial, mods_depressed,
530 mods_latched, mods_locked, group);
531 }
532}
533
534static void
535debug_binding_cancel(struct weston_keyboard_grab *grab)
536{
537 struct debug_binding_grab *db = (struct debug_binding_grab *) grab;
538
539 weston_keyboard_end_grab(grab->keyboard);
540 free(db);
541}
542
543struct weston_keyboard_grab_interface debug_binding_keyboard_grab = {
544 debug_binding_key,
545 debug_binding_modifiers,
546 debug_binding_cancel,
547};
548
549static void
Derek Foreman8ae2db52015-07-15 13:00:36 -0500550debug_binding(struct weston_keyboard *keyboard, uint32_t time,
551 uint32_t key, void *data)
Pekka Paalanen2829f7c2015-02-19 17:02:13 +0200552{
553 struct debug_binding_grab *grab;
554
555 grab = calloc(1, sizeof *grab);
556 if (!grab)
557 return;
558
Derek Foreman8ae2db52015-07-15 13:00:36 -0500559 grab->seat = keyboard->seat;
Pekka Paalanen2829f7c2015-02-19 17:02:13 +0200560 grab->key[0] = key;
561 grab->grab.interface = &debug_binding_keyboard_grab;
Derek Foreman8ae2db52015-07-15 13:00:36 -0500562 weston_keyboard_start_grab(keyboard, &grab->grab);
Pekka Paalanen2829f7c2015-02-19 17:02:13 +0200563}
564
565/** Install the trigger binding for debug bindings.
566 *
567 * \param compositor The compositor.
568 * \param mod The modifier.
569 *
570 * This will add a key binding for modifier+SHIFT+SPACE that will trigger
571 * debug key bindings.
572 */
573WL_EXPORT void
574weston_install_debug_key_binding(struct weston_compositor *compositor,
575 uint32_t mod)
576{
577 weston_compositor_add_key_binding(compositor, KEY_SPACE,
578 mod | MODIFIER_SHIFT,
579 debug_binding, NULL);
580}