diff options
Diffstat (limited to 'src/bindings.c')
-rw-r--r-- | src/bindings.c | 342 |
1 files changed, 342 insertions, 0 deletions
diff --git a/src/bindings.c b/src/bindings.c new file mode 100644 index 00000000..7cbded92 --- /dev/null +++ b/src/bindings.c @@ -0,0 +1,342 @@ +/* + * Copyright © 2011 Intel Corporation + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, provided + * that the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of the copyright holders not be used in + * advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. The copyright holders make + * no representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS + * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER + * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "config.h" + +#include <stdlib.h> + +#include "compositor.h" + +struct weston_binding { + uint32_t key; + uint32_t button; + uint32_t axis; + uint32_t modifier; + void *handler; + void *data; + struct wl_list link; +}; + +static struct weston_binding * +weston_compositor_add_binding(struct weston_compositor *compositor, + uint32_t key, uint32_t button, uint32_t axis, + uint32_t modifier, void *handler, void *data) +{ + struct weston_binding *binding; + + binding = malloc(sizeof *binding); + if (binding == NULL) + return NULL; + + binding->key = key; + binding->button = button; + binding->axis = axis; + binding->modifier = modifier; + binding->handler = handler; + binding->data = data; + + return binding; +} + +WL_EXPORT struct weston_binding * +weston_compositor_add_key_binding(struct weston_compositor *compositor, + uint32_t key, uint32_t modifier, + weston_key_binding_handler_t handler, + void *data) +{ + struct weston_binding *binding; + + binding = weston_compositor_add_binding(compositor, key, 0, 0, + modifier, handler, data); + if (binding == NULL) + return NULL; + + wl_list_insert(compositor->key_binding_list.prev, &binding->link); + + return binding; +} + +WL_EXPORT struct weston_binding * +weston_compositor_add_button_binding(struct weston_compositor *compositor, + uint32_t button, uint32_t modifier, + weston_button_binding_handler_t handler, + void *data) +{ + struct weston_binding *binding; + + binding = weston_compositor_add_binding(compositor, 0, button, 0, + modifier, handler, data); + if (binding == NULL) + return NULL; + + wl_list_insert(compositor->button_binding_list.prev, &binding->link); + + return binding; +} + +WL_EXPORT struct weston_binding * +weston_compositor_add_touch_binding(struct weston_compositor *compositor, + uint32_t modifier, + weston_touch_binding_handler_t handler, + void *data) +{ + struct weston_binding *binding; + + binding = weston_compositor_add_binding(compositor, 0, 0, 0, + modifier, handler, data); + if (binding == NULL) + return NULL; + + wl_list_insert(compositor->touch_binding_list.prev, &binding->link); + + return binding; +} + +WL_EXPORT struct weston_binding * +weston_compositor_add_axis_binding(struct weston_compositor *compositor, + uint32_t axis, uint32_t modifier, + weston_axis_binding_handler_t handler, + void *data) +{ + struct weston_binding *binding; + + binding = weston_compositor_add_binding(compositor, 0, 0, axis, + modifier, handler, data); + if (binding == NULL) + return NULL; + + wl_list_insert(compositor->axis_binding_list.prev, &binding->link); + + return binding; +} + +WL_EXPORT struct weston_binding * +weston_compositor_add_debug_binding(struct weston_compositor *compositor, + uint32_t key, + weston_key_binding_handler_t handler, + void *data) +{ + struct weston_binding *binding; + + binding = weston_compositor_add_binding(compositor, key, 0, 0, 0, + handler, data); + + wl_list_insert(compositor->debug_binding_list.prev, &binding->link); + + return binding; +} + +WL_EXPORT void +weston_binding_destroy(struct weston_binding *binding) +{ + wl_list_remove(&binding->link); + free(binding); +} + +WL_EXPORT void +weston_binding_list_destroy_all(struct wl_list *list) +{ + struct weston_binding *binding, *tmp; + + wl_list_for_each_safe(binding, tmp, list, link) + weston_binding_destroy(binding); +} + +struct binding_keyboard_grab { + uint32_t key; + struct weston_keyboard_grab grab; +}; + +static void +binding_key(struct weston_keyboard_grab *grab, + uint32_t time, uint32_t key, uint32_t state_w) +{ + struct binding_keyboard_grab *b = + container_of(grab, struct binding_keyboard_grab, grab); + struct wl_resource *resource; + enum wl_keyboard_key_state state = state_w; + uint32_t serial; + struct weston_keyboard *keyboard = grab->keyboard; + struct wl_display *display = keyboard->seat->compositor->wl_display; + + if (key == b->key) { + if (state == WL_KEYBOARD_KEY_STATE_RELEASED) { + weston_keyboard_end_grab(grab->keyboard); + if (keyboard->input_method_resource) + keyboard->grab = &keyboard->input_method_grab; + free(b); + } + } else if (!wl_list_empty(&keyboard->focus_resource_list)) { + serial = wl_display_next_serial(display); + wl_resource_for_each(resource, &keyboard->focus_resource_list) { + wl_keyboard_send_key(resource, + serial, + time, + key, + state); + } + } +} + +static void +binding_modifiers(struct weston_keyboard_grab *grab, uint32_t serial, + uint32_t mods_depressed, uint32_t mods_latched, + uint32_t mods_locked, uint32_t group) +{ + struct wl_resource *resource; + + wl_resource_for_each(resource, &grab->keyboard->focus_resource_list) { + wl_keyboard_send_modifiers(resource, serial, mods_depressed, + mods_latched, mods_locked, group); + } +} + +static void +binding_cancel(struct weston_keyboard_grab *grab) +{ + struct binding_keyboard_grab *binding_grab = + container_of(grab, struct binding_keyboard_grab, grab); + + weston_keyboard_end_grab(grab->keyboard); + free(binding_grab); +} + +static const struct weston_keyboard_grab_interface binding_grab = { + binding_key, + binding_modifiers, + binding_cancel, +}; + +static void +install_binding_grab(struct weston_seat *seat, uint32_t time, uint32_t key) +{ + struct binding_keyboard_grab *grab; + + grab = malloc(sizeof *grab); + grab->key = key; + grab->grab.interface = &binding_grab; + weston_keyboard_start_grab(seat->keyboard, &grab->grab); +} + +WL_EXPORT void +weston_compositor_run_key_binding(struct weston_compositor *compositor, + struct weston_seat *seat, + uint32_t time, uint32_t key, + enum wl_keyboard_key_state state) +{ + struct weston_binding *b; + + if (state == WL_KEYBOARD_KEY_STATE_RELEASED) + return; + + wl_list_for_each(b, &compositor->key_binding_list, link) { + if (b->key == key && b->modifier == seat->modifier_state) { + weston_key_binding_handler_t handler = b->handler; + handler(seat, time, key, b->data); + + /* If this was a key binding and it didn't + * install a keyboard grab, install one now to + * swallow the key release. */ + if (seat->keyboard->grab == + &seat->keyboard->default_grab) + install_binding_grab(seat, time, key); + } + } +} + +WL_EXPORT void +weston_compositor_run_button_binding(struct weston_compositor *compositor, + struct weston_seat *seat, + uint32_t time, uint32_t button, + enum wl_pointer_button_state state) +{ + struct weston_binding *b; + + if (state == WL_POINTER_BUTTON_STATE_RELEASED) + return; + + wl_list_for_each(b, &compositor->button_binding_list, link) { + if (b->button == button && b->modifier == seat->modifier_state) { + weston_button_binding_handler_t handler = b->handler; + handler(seat, time, button, b->data); + } + } +} + +WL_EXPORT void +weston_compositor_run_touch_binding(struct weston_compositor *compositor, + struct weston_seat *seat, uint32_t time, + int touch_type) +{ + struct weston_binding *b; + + if (seat->num_tp != 1 || touch_type != WL_TOUCH_DOWN) + return; + + wl_list_for_each(b, &compositor->touch_binding_list, link) { + if (b->modifier == seat->modifier_state) { + weston_touch_binding_handler_t handler = b->handler; + handler(seat, time, b->data); + } + } +} + +WL_EXPORT int +weston_compositor_run_axis_binding(struct weston_compositor *compositor, + struct weston_seat *seat, + uint32_t time, uint32_t axis, + wl_fixed_t value) +{ + struct weston_binding *b; + + wl_list_for_each(b, &compositor->axis_binding_list, link) { + if (b->axis == axis && b->modifier == seat->modifier_state) { + weston_axis_binding_handler_t handler = b->handler; + handler(seat, time, axis, value, b->data); + return 1; + } + } + + return 0; +} + +WL_EXPORT int +weston_compositor_run_debug_binding(struct weston_compositor *compositor, + struct weston_seat *seat, + uint32_t time, uint32_t key, + enum wl_keyboard_key_state state) +{ + weston_key_binding_handler_t handler; + struct weston_binding *binding; + int count = 0; + + wl_list_for_each(binding, &compositor->debug_binding_list, link) { + if (key != binding->key) + continue; + + count++; + handler = binding->handler; + handler(seat, time, key, binding->data); + } + + return count; +} |