/* * Clutter. * * An OpenGL based 'interactive canvas' library. * * Copyright (C) 2010 Intel Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library. If not, see . * Authors: * Matthew Allum * Robert Bragg * Kristian Høgsberg */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include "clutter-debug.h" #include "clutter-device-manager-private.h" #include "clutter-event-private.h" #include "clutter-private.h" #include "clutter-keysyms.h" #include "evdev/clutter-xkb-utils.h" #include "clutter-input-device-wayland.h" #include "clutter-backend-wayland.h" #include "clutter-stage-private.h" #include "cogl/clutter-stage-cogl.h" typedef struct _ClutterInputDeviceClass ClutterInputDeviceWaylandClass; G_DEFINE_TYPE (ClutterInputDeviceWayland, clutter_input_device_wayland, CLUTTER_TYPE_INPUT_DEVICE); static void clutter_wayland_handle_motion (void *data, struct wl_input_device *input_device, uint32_t _time, int32_t x, int32_t y, int32_t sx, int32_t sy) { ClutterInputDeviceWayland *device = data; ClutterStageCogl *stage_cogl = device->pointer_focus; ClutterEvent *event; event = clutter_event_new (CLUTTER_MOTION); event->motion.stage = stage_cogl->wrapper; event->motion.device = CLUTTER_INPUT_DEVICE (device); event->motion.time = _time; event->motion.modifier_state = 0; event->motion.x = sx; event->motion.y = sy; device->surface_x = sx; device->surface_y = sy; device->x = x; device->y = y; _clutter_event_push (event, FALSE); } static void clutter_wayland_handle_button (void *data, struct wl_input_device *input_device, uint32_t _time, uint32_t button, uint32_t state) { ClutterInputDeviceWayland *device = data; ClutterStageCogl *stage_cogl = device->pointer_focus; ClutterEvent *event; ClutterEventType type; if (state) type = CLUTTER_BUTTON_PRESS; else type = CLUTTER_BUTTON_RELEASE; event = clutter_event_new (type); event->button.stage = stage_cogl->wrapper; event->button.device = CLUTTER_INPUT_DEVICE (device); event->button.time = _time; event->button.x = device->surface_x; event->button.y = device->surface_y; event->button.modifier_state = device->modifier_state; /* evdev button codes */ switch (button) { case 272: event->button.button = 1; break; case 273: event->button.button = 3; break; case 274: event->button.button = 2; break; } _clutter_event_push (event, FALSE); } static void clutter_wayland_handle_key (void *data, struct wl_input_device *input_device, uint32_t _time, uint32_t key, uint32_t state) { ClutterInputDeviceWayland *device = data; ClutterStageCogl *stage_cogl = device->keyboard_focus; ClutterEvent *event; event = _clutter_key_event_new_from_evdev ((ClutterInputDevice *) device, stage_cogl->wrapper, device->xkb, _time, key, state, &device->modifier_state); _clutter_event_push (event, FALSE); } static void clutter_wayland_handle_pointer_focus (void *data, struct wl_input_device *input_device, uint32_t _time, struct wl_surface *surface, int32_t x, int32_t y, int32_t sx, int32_t sy) { ClutterInputDeviceWayland *device = data; ClutterStageCogl *stage_cogl; ClutterEvent *event; if (!surface) { stage_cogl = device->pointer_focus; event = clutter_event_new (CLUTTER_LEAVE); event->crossing.stage = stage_cogl->wrapper; event->crossing.time = _time; event->crossing.x = sx; event->crossing.y = sy; event->crossing.source = CLUTTER_ACTOR (stage_cogl->wrapper); event->crossing.device = CLUTTER_INPUT_DEVICE (device); _clutter_event_push (event, FALSE); device->pointer_focus = NULL; _clutter_input_device_set_stage (CLUTTER_INPUT_DEVICE (device), NULL); } if (surface) { ClutterBackend *backend; ClutterBackendWayland *backend_wayland; stage_cogl = wl_surface_get_user_data (surface); device->pointer_focus = stage_cogl; _clutter_input_device_set_stage (CLUTTER_INPUT_DEVICE (device), stage_cogl->wrapper); event = clutter_event_new (CLUTTER_ENTER); event->crossing.stage = stage_cogl->wrapper; event->crossing.time = _time; event->crossing.x = sx; event->crossing.y = sy; event->crossing.source = CLUTTER_ACTOR (stage_cogl->wrapper); event->crossing.device = CLUTTER_INPUT_DEVICE (device); _clutter_event_push (event, FALSE); device->surface_x = sx; device->surface_y = sy; device->x = x; device->y = y; /* Set the cursor to the cursor loaded at backend initialisation */ backend = clutter_get_default_backend (); backend_wayland = CLUTTER_BACKEND_WAYLAND (backend); wl_input_device_attach (input_device, _time, backend_wayland->cursor_buffer, backend_wayland->cursor_x, backend_wayland->cursor_y); } } static void clutter_wayland_handle_keyboard_focus (void *data, struct wl_input_device *input_device, uint32_t _time, struct wl_surface *surface, struct wl_array *keys) { ClutterInputDeviceWayland *device = data; ClutterStageCogl *stage_cogl; uint32_t *k, *end; if (device->keyboard_focus) { stage_cogl = device->keyboard_focus; device->keyboard_focus = NULL; _clutter_stage_update_state (stage_cogl->wrapper, CLUTTER_STAGE_STATE_ACTIVATED, 0); } if (surface) { stage_cogl = wl_surface_get_user_data (surface); device->keyboard_focus = stage_cogl; _clutter_stage_update_state (stage_cogl->wrapper, 0, CLUTTER_STAGE_STATE_ACTIVATED); end = (uint32_t *)((guint8 *)keys->data + keys->size); device->modifier_state = 0; for (k = keys->data; k < end; k++) device->modifier_state |= device->xkb->map->modmap[*k]; } } const struct wl_input_device_listener _clutter_input_device_wayland_listener = { clutter_wayland_handle_motion, clutter_wayland_handle_button, clutter_wayland_handle_key, clutter_wayland_handle_pointer_focus, clutter_wayland_handle_keyboard_focus, }; static gboolean clutter_input_device_wayland_keycode_to_evdev (ClutterInputDevice *device, guint hardware_keycode, guint *evdev_keycode) { /* The hardware keycodes from the wayland backend are already evdev keycodes */ *evdev_keycode = hardware_keycode; return TRUE; } static void clutter_input_device_wayland_class_init (ClutterInputDeviceWaylandClass *klass) { klass->keycode_to_evdev = clutter_input_device_wayland_keycode_to_evdev; } static void clutter_input_device_wayland_init (ClutterInputDeviceWayland *self) { } /** * clutter_wayland_input_device_get_wl_input_device: (skip) * * @device: a #ClutterInputDevice * * Access the underlying data structure representing the Wayland device that is * backing this #ClutterInputDevice. * * Note: this function can only be called when running on the Wayland platform. * Calling this function at any other time will return %NULL. * * Returns: (transfer none): the Wayland input device associated with the * @device * * Since: 1.10 */ struct wl_input_device * clutter_wayland_input_device_get_wl_input_device (ClutterInputDevice *device) { ClutterInputDeviceWayland *wayland_device; if (!CLUTTER_INPUT_DEVICE_WAYLAND (device)) return NULL; wayland_device = CLUTTER_INPUT_DEVICE_WAYLAND (device); return wayland_device->input_device; }