summaryrefslogtreecommitdiff
path: root/src/wayland/meta-wayland-keyboard.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/wayland/meta-wayland-keyboard.c')
-rw-r--r--src/wayland/meta-wayland-keyboard.c873
1 files changed, 0 insertions, 873 deletions
diff --git a/src/wayland/meta-wayland-keyboard.c b/src/wayland/meta-wayland-keyboard.c
deleted file mode 100644
index 836939c9d..000000000
--- a/src/wayland/meta-wayland-keyboard.c
+++ /dev/null
@@ -1,873 +0,0 @@
-/*
- * Wayland Support
- *
- * Copyright (C) 2013 Intel Corporation
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This program 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
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- * 02111-1307, USA.
- */
-
-/*
- * Copyright © 2010-2011 Intel Corporation
- * Copyright © 2008-2011 Kristian Høgsberg
- * Copyright © 2012 Collabora, Ltd.
- *
- * 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.
- */
-
-/* The file is based on src/input.c from Weston */
-
-#include "config.h"
-
-#include <errno.h>
-#include <glib.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#include "backends/meta-backend-private.h"
-#include "core/display-private.h"
-#include "core/meta-anonymous-file.h"
-#include "wayland/meta-wayland-private.h"
-
-#define GSD_KEYBOARD_SCHEMA "org.gnome.settings-daemon.peripherals.keyboard"
-
-G_DEFINE_TYPE (MetaWaylandKeyboard, meta_wayland_keyboard,
- META_TYPE_WAYLAND_INPUT_DEVICE)
-
-static void meta_wayland_keyboard_update_xkb_state (MetaWaylandKeyboard *keyboard);
-static void notify_modifiers (MetaWaylandKeyboard *keyboard);
-
-static void
-unbind_resource (struct wl_resource *resource)
-{
- wl_list_remove (wl_resource_get_link (resource));
-}
-
-static void
-send_keymap (MetaWaylandKeyboard *keyboard,
- struct wl_resource *resource)
-{
- MetaWaylandXkbInfo *xkb_info = &keyboard->xkb_info;
- int fd;
- size_t size;
- MetaAnonymousFileMapmode mapmode;
-
- if (wl_resource_get_version (resource) < 7)
- mapmode = META_ANONYMOUS_FILE_MAPMODE_SHARED;
- else
- mapmode = META_ANONYMOUS_FILE_MAPMODE_PRIVATE;
-
- fd = meta_anonymous_file_open_fd (xkb_info->keymap_rofile, mapmode);
- size = meta_anonymous_file_size (xkb_info->keymap_rofile);
-
- if (fd == -1)
- {
- g_warning ("Creating a keymap file failed: %s", strerror (errno));
- return;
- }
-
- wl_keyboard_send_keymap (resource,
- WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1,
- fd, size);
-
- meta_anonymous_file_close_fd (fd);
-}
-
-static void
-inform_clients_of_new_keymap (MetaWaylandKeyboard *keyboard)
-{
- struct wl_resource *keyboard_resource;
-
- wl_resource_for_each (keyboard_resource, &keyboard->resource_list)
- send_keymap (keyboard, keyboard_resource);
- wl_resource_for_each (keyboard_resource, &keyboard->focus_resource_list)
- send_keymap (keyboard, keyboard_resource);
-}
-
-static void
-meta_wayland_keyboard_take_keymap (MetaWaylandKeyboard *keyboard,
- struct xkb_keymap *keymap)
-{
- MetaWaylandXkbInfo *xkb_info = &keyboard->xkb_info;
- char *keymap_string;
- size_t keymap_size;
-
- if (keymap == NULL)
- {
- g_warning ("Attempting to set null keymap (compilation probably failed)");
- return;
- }
-
- xkb_keymap_unref (xkb_info->keymap);
- xkb_info->keymap = xkb_keymap_ref (keymap);
-
- meta_wayland_keyboard_update_xkb_state (keyboard);
-
- keymap_string =
- xkb_keymap_get_as_string (xkb_info->keymap, XKB_KEYMAP_FORMAT_TEXT_V1);
- if (!keymap_string)
- {
- g_warning ("Failed to get string version of keymap");
- return;
- }
- keymap_size = strlen (keymap_string) + 1;
-
- g_clear_pointer (&xkb_info->keymap_rofile, meta_anonymous_file_free);
- xkb_info->keymap_rofile =
- meta_anonymous_file_new (keymap_size, (const uint8_t *) keymap_string);
-
- free (keymap_string);
-
- if (!xkb_info->keymap_rofile)
- {
- g_warning ("Failed to create anonymous file for keymap");
- return;
- }
-
- inform_clients_of_new_keymap (keyboard);
-
- notify_modifiers (keyboard);
-}
-
-static xkb_mod_mask_t
-kbd_a11y_apply_mask (MetaWaylandKeyboard *keyboard)
-{
- xkb_mod_mask_t latched, locked, depressed, group;
- xkb_mod_mask_t update_mask = 0;
-
- depressed = xkb_state_serialize_mods(keyboard->xkb_info.state, XKB_STATE_DEPRESSED);
- latched = xkb_state_serialize_mods (keyboard->xkb_info.state, XKB_STATE_MODS_LATCHED);
- locked = xkb_state_serialize_mods (keyboard->xkb_info.state, XKB_STATE_MODS_LOCKED);
- group = xkb_state_serialize_layout (keyboard->xkb_info.state, XKB_STATE_LAYOUT_EFFECTIVE);
-
- if ((latched & keyboard->kbd_a11y_latched_mods) != keyboard->kbd_a11y_latched_mods)
- update_mask |= XKB_STATE_MODS_LATCHED;
-
- if ((locked & keyboard->kbd_a11y_locked_mods) != keyboard->kbd_a11y_locked_mods)
- update_mask |= XKB_STATE_MODS_LOCKED;
-
- if (update_mask)
- {
- latched |= keyboard->kbd_a11y_latched_mods;
- locked |= keyboard->kbd_a11y_locked_mods;
- xkb_state_update_mask (keyboard->xkb_info.state, depressed, latched, locked, 0, 0, group);
- }
-
- return update_mask;
-}
-
-static void
-on_keymap_changed (MetaBackend *backend,
- gpointer data)
-{
- MetaWaylandKeyboard *keyboard = data;
-
- meta_wayland_keyboard_take_keymap (keyboard, meta_backend_get_keymap (backend));
-}
-
-static void
-on_keymap_layout_group_changed (MetaBackend *backend,
- guint idx,
- gpointer data)
-{
- MetaWaylandKeyboard *keyboard = data;
- xkb_mod_mask_t depressed_mods;
- xkb_mod_mask_t latched_mods;
- xkb_mod_mask_t locked_mods;
- struct xkb_state *state;
-
- state = keyboard->xkb_info.state;
-
- depressed_mods = xkb_state_serialize_mods (state, XKB_STATE_MODS_DEPRESSED);
- latched_mods = xkb_state_serialize_mods (state, XKB_STATE_MODS_LATCHED);
- locked_mods = xkb_state_serialize_mods (state, XKB_STATE_MODS_LOCKED);
-
- xkb_state_update_mask (state, depressed_mods, latched_mods, locked_mods, 0, 0, idx);
- kbd_a11y_apply_mask (keyboard);
-
- notify_modifiers (keyboard);
-}
-
-static void
-keyboard_handle_focus_surface_destroy (struct wl_listener *listener, void *data)
-{
- MetaWaylandKeyboard *keyboard = wl_container_of (listener, keyboard,
- focus_surface_listener);
-
- meta_wayland_keyboard_set_focus (keyboard, NULL);
-}
-
-static gboolean
-meta_wayland_keyboard_broadcast_key (MetaWaylandKeyboard *keyboard,
- uint32_t time,
- uint32_t key,
- uint32_t state)
-{
- struct wl_resource *resource;
-
- if (!wl_list_empty (&keyboard->focus_resource_list))
- {
- MetaWaylandInputDevice *input_device =
- META_WAYLAND_INPUT_DEVICE (keyboard);
- uint32_t serial;
-
- serial = meta_wayland_input_device_next_serial (input_device);
-
- if (state)
- {
- keyboard->key_down_serial = serial;
- keyboard->key_down_keycode = key;
- }
- else
- {
- keyboard->key_up_serial = serial;
- keyboard->key_up_keycode = key;
- }
-
- wl_resource_for_each (resource, &keyboard->focus_resource_list)
- wl_keyboard_send_key (resource, serial, time, key, state);
- }
-
- /* Eat the key events if we have a focused surface. */
- return (keyboard->focus_surface != NULL);
-}
-
-static gboolean
-notify_key (MetaWaylandKeyboard *keyboard,
- const ClutterEvent *event)
-{
- return keyboard->grab->interface->key (keyboard->grab, event);
-}
-
-static xkb_mod_mask_t
-add_vmod (xkb_mod_mask_t mask,
- xkb_mod_mask_t mod,
- xkb_mod_mask_t vmod,
- xkb_mod_mask_t *added)
-{
- if ((mask & mod) && !(mod & *added))
- {
- mask |= vmod;
- *added |= mod;
- }
- return mask;
-}
-
-static xkb_mod_mask_t
-add_virtual_mods (xkb_mod_mask_t mask)
-{
- MetaKeyBindingManager *keys = &(meta_get_display ()->key_binding_manager);
- xkb_mod_mask_t added;
- guint i;
- /* Order is important here: if multiple vmods share the same real
- modifier we only want to add the first. */
- struct {
- xkb_mod_mask_t mod;
- xkb_mod_mask_t vmod;
- } mods[] = {
- { keys->super_mask, keys->virtual_super_mask },
- { keys->hyper_mask, keys->virtual_hyper_mask },
- { keys->meta_mask, keys->virtual_meta_mask },
- };
-
- added = 0;
- for (i = 0; i < G_N_ELEMENTS (mods); ++i)
- mask = add_vmod (mask, mods[i].mod, mods[i].vmod, &added);
-
- return mask;
-}
-
-static void
-keyboard_send_modifiers (MetaWaylandKeyboard *keyboard,
- struct wl_resource *resource,
- uint32_t serial)
-{
- struct xkb_state *state = keyboard->xkb_info.state;
- xkb_mod_mask_t depressed, latched, locked;
-
- depressed = add_virtual_mods (xkb_state_serialize_mods (state, XKB_STATE_MODS_DEPRESSED));
- latched = add_virtual_mods (xkb_state_serialize_mods (state, XKB_STATE_MODS_LATCHED));
- locked = add_virtual_mods (xkb_state_serialize_mods (state, XKB_STATE_MODS_LOCKED));
-
- wl_keyboard_send_modifiers (resource, serial, depressed, latched, locked,
- xkb_state_serialize_layout (state, XKB_STATE_LAYOUT_EFFECTIVE));
-}
-
-static void
-meta_wayland_keyboard_broadcast_modifiers (MetaWaylandKeyboard *keyboard)
-{
- struct wl_resource *resource;
-
- if (!wl_list_empty (&keyboard->focus_resource_list))
- {
- MetaWaylandInputDevice *input_device =
- META_WAYLAND_INPUT_DEVICE (keyboard);
- uint32_t serial;
-
- serial = meta_wayland_input_device_next_serial (input_device);
-
- wl_resource_for_each (resource, &keyboard->focus_resource_list)
- keyboard_send_modifiers (keyboard, resource, serial);
- }
-}
-
-static void
-notify_modifiers (MetaWaylandKeyboard *keyboard)
-{
- struct xkb_state *state;
-
- state = keyboard->xkb_info.state;
- keyboard->grab->interface->modifiers (keyboard->grab,
- xkb_state_serialize_mods (state, XKB_STATE_MODS_EFFECTIVE));
-}
-
-static void
-meta_wayland_keyboard_update_xkb_state (MetaWaylandKeyboard *keyboard)
-{
- MetaWaylandXkbInfo *xkb_info = &keyboard->xkb_info;
- xkb_mod_mask_t latched, locked, numlock;
- MetaBackend *backend = meta_get_backend ();
- xkb_layout_index_t layout_idx;
- ClutterKeymap *keymap;
- ClutterSeat *seat;
-
- /* Preserve latched/locked modifiers state */
- if (xkb_info->state)
- {
- latched = xkb_state_serialize_mods (xkb_info->state, XKB_STATE_MODS_LATCHED);
- locked = xkb_state_serialize_mods (xkb_info->state, XKB_STATE_MODS_LOCKED);
- xkb_state_unref (xkb_info->state);
- }
- else
- {
- latched = locked = 0;
- }
-
- seat = clutter_backend_get_default_seat (clutter_get_default_backend ());
- keymap = clutter_seat_get_keymap (seat);
- numlock = (1 << xkb_keymap_mod_get_index (xkb_info->keymap, "Mod2"));
-
- if (clutter_keymap_get_num_lock_state (keymap))
- locked |= numlock;
- else
- locked &= ~numlock;
-
- xkb_info->state = xkb_state_new (xkb_info->keymap);
-
- layout_idx = meta_backend_get_keymap_layout_group (backend);
- xkb_state_update_mask (xkb_info->state, 0, latched, locked, 0, 0, layout_idx);
-
- kbd_a11y_apply_mask (keyboard);
-}
-
-static void
-on_kbd_a11y_mask_changed (ClutterSeat *seat,
- xkb_mod_mask_t new_latched_mods,
- xkb_mod_mask_t new_locked_mods,
- MetaWaylandKeyboard *keyboard)
-{
- xkb_mod_mask_t latched, locked, depressed, group;
-
- if (keyboard->xkb_info.state == NULL)
- return;
-
- depressed = xkb_state_serialize_mods(keyboard->xkb_info.state, XKB_STATE_DEPRESSED);
- latched = xkb_state_serialize_mods (keyboard->xkb_info.state, XKB_STATE_MODS_LATCHED);
- locked = xkb_state_serialize_mods (keyboard->xkb_info.state, XKB_STATE_MODS_LOCKED);
- group = xkb_state_serialize_layout (keyboard->xkb_info.state, XKB_STATE_LAYOUT_EFFECTIVE);
-
- /* Clear previous masks */
- latched &= ~keyboard->kbd_a11y_latched_mods;
- locked &= ~keyboard->kbd_a11y_locked_mods;
- xkb_state_update_mask (keyboard->xkb_info.state, depressed, latched, locked, 0, 0, group);
-
- /* Apply new masks */
- keyboard->kbd_a11y_latched_mods = new_latched_mods;
- keyboard->kbd_a11y_locked_mods = new_locked_mods;
- kbd_a11y_apply_mask (keyboard);
-
- notify_modifiers (keyboard);
-}
-
-static void
-notify_key_repeat_for_resource (MetaWaylandKeyboard *keyboard,
- struct wl_resource *keyboard_resource)
-{
- if (wl_resource_get_version (keyboard_resource) >= WL_KEYBOARD_REPEAT_INFO_SINCE_VERSION)
- {
- gboolean repeat;
- unsigned int delay, rate;
-
- repeat = g_settings_get_boolean (keyboard->settings, "repeat");
-
- if (repeat)
- {
- unsigned int interval;
- interval = g_settings_get_uint (keyboard->settings, "repeat-interval");
- /* Our setting is in the milliseconds between keys. "rate" is the number
- * of keys per second. */
- if (interval > 0)
- rate = (1000 / interval);
- else
- rate = 0;
-
- delay = g_settings_get_uint (keyboard->settings, "delay");
- }
- else
- {
- rate = 0;
- delay = 0;
- }
-
- wl_keyboard_send_repeat_info (keyboard_resource, rate, delay);
- }
-}
-
-static void
-notify_key_repeat (MetaWaylandKeyboard *keyboard)
-{
- struct wl_resource *keyboard_resource;
-
- wl_resource_for_each (keyboard_resource, &keyboard->resource_list)
- {
- notify_key_repeat_for_resource (keyboard, keyboard_resource);
- }
-
- wl_resource_for_each (keyboard_resource, &keyboard->focus_resource_list)
- {
- notify_key_repeat_for_resource (keyboard, keyboard_resource);
- }
-}
-
-static void
-settings_changed (GSettings *settings,
- const char *key,
- gpointer data)
-{
- MetaWaylandKeyboard *keyboard = data;
-
- notify_key_repeat (keyboard);
-}
-
-static gboolean
-default_grab_key (MetaWaylandKeyboardGrab *grab,
- const ClutterEvent *event)
-{
- MetaWaylandKeyboard *keyboard = grab->keyboard;
- gboolean is_press = event->type == CLUTTER_KEY_PRESS;
- guint32 code = 0;
-
- /* Ignore autorepeat events, as autorepeat in Wayland is done on the client
- * side. */
- if (event->key.flags & CLUTTER_EVENT_FLAG_REPEATED)
- return FALSE;
-
- code = clutter_event_get_event_code (event);
-
- return meta_wayland_keyboard_broadcast_key (keyboard, event->key.time,
- code, is_press);
-}
-
-static void
-default_grab_modifiers (MetaWaylandKeyboardGrab *grab,
- ClutterModifierType modifiers)
-{
- meta_wayland_keyboard_broadcast_modifiers (grab->keyboard);
-}
-
-static const MetaWaylandKeyboardGrabInterface default_keyboard_grab_interface = {
- default_grab_key,
- default_grab_modifiers
-};
-
-void
-meta_wayland_keyboard_enable (MetaWaylandKeyboard *keyboard)
-{
- MetaBackend *backend = meta_get_backend ();
- ClutterBackend *clutter_backend = clutter_get_default_backend ();
-
- keyboard->settings = g_settings_new ("org.gnome.desktop.peripherals.keyboard");
- g_signal_connect (keyboard->settings, "changed",
- G_CALLBACK (settings_changed), keyboard);
-
- g_signal_connect (backend, "keymap-changed",
- G_CALLBACK (on_keymap_changed), keyboard);
- g_signal_connect (backend, "keymap-layout-group-changed",
- G_CALLBACK (on_keymap_layout_group_changed), keyboard);
-
- g_signal_connect (clutter_backend_get_default_seat (clutter_backend),
- "kbd-a11y-mods-state-changed",
- G_CALLBACK (on_kbd_a11y_mask_changed), keyboard);
-
- meta_wayland_keyboard_take_keymap (keyboard, meta_backend_get_keymap (backend));
-}
-
-static void
-meta_wayland_xkb_info_destroy (MetaWaylandXkbInfo *xkb_info)
-{
- g_clear_pointer (&xkb_info->keymap, xkb_keymap_unref);
- g_clear_pointer (&xkb_info->state, xkb_state_unref);
- g_clear_pointer (&xkb_info->keymap_rofile, meta_anonymous_file_free);
-}
-
-void
-meta_wayland_keyboard_disable (MetaWaylandKeyboard *keyboard)
-{
- MetaBackend *backend = meta_get_backend ();
-
- g_signal_handlers_disconnect_by_func (backend, on_keymap_changed, keyboard);
- g_signal_handlers_disconnect_by_func (backend, on_keymap_layout_group_changed, keyboard);
-
- meta_wayland_keyboard_end_grab (keyboard);
- meta_wayland_keyboard_set_focus (keyboard, NULL);
-
- wl_list_remove (&keyboard->resource_list);
- wl_list_init (&keyboard->resource_list);
- wl_list_remove (&keyboard->focus_resource_list);
- wl_list_init (&keyboard->focus_resource_list);
-
- g_clear_object (&keyboard->settings);
-}
-
-void
-meta_wayland_keyboard_update (MetaWaylandKeyboard *keyboard,
- const ClutterKeyEvent *event)
-{
- gboolean is_press = event->type == CLUTTER_KEY_PRESS;
-
- /* Only handle real, non-synthetic, events here. The IM is free to reemit
- * key events (incl. modifiers), handling those additionally will result
- * in doubly-pressed keys.
- */
- if ((event->flags &
- (CLUTTER_EVENT_FLAG_SYNTHETIC | CLUTTER_EVENT_FLAG_INPUT_METHOD)) != 0)
- return;
-
- /* If we get a key event but still have pending modifier state
- * changes from a previous event that didn't get cleared, we need to
- * send that state right away so that the new key event can be
- * interpreted by clients correctly modified. */
- if (keyboard->mods_changed)
- notify_modifiers (keyboard);
-
- keyboard->mods_changed = xkb_state_update_key (keyboard->xkb_info.state,
- event->hardware_keycode,
- is_press ? XKB_KEY_DOWN : XKB_KEY_UP);
- keyboard->mods_changed |= kbd_a11y_apply_mask (keyboard);
-}
-
-gboolean
-meta_wayland_keyboard_handle_event (MetaWaylandKeyboard *keyboard,
- const ClutterKeyEvent *event)
-{
-#ifdef WITH_VERBOSE_MODE
- gboolean is_press = event->type == CLUTTER_KEY_PRESS;
-#endif
- gboolean handled;
-
- /* Synthetic key events are for autorepeat. Ignore those, as
- * autorepeat in Wayland is done on the client side. */
- if ((event->flags & CLUTTER_EVENT_FLAG_SYNTHETIC) &&
- !(event->flags & CLUTTER_EVENT_FLAG_INPUT_METHOD))
- return FALSE;
-
- meta_verbose ("Handling key %s event code %d",
- is_press ? "press" : "release",
- event->hardware_keycode);
-
- handled = notify_key (keyboard, (const ClutterEvent *) event);
-
- if (handled)
- meta_verbose ("Sent event to wayland client");
- else
- meta_verbose ("No wayland surface is focused, continuing normal operation");
-
- if (keyboard->mods_changed != 0)
- {
- notify_modifiers (keyboard);
- keyboard->mods_changed = 0;
- }
-
- return handled;
-}
-
-void
-meta_wayland_keyboard_update_key_state (MetaWaylandKeyboard *keyboard,
- char *key_vector,
- int key_vector_len,
- int offset)
-{
- gboolean mods_changed = FALSE;
-
- int i;
- for (i = offset; i < key_vector_len * 8; i++)
- {
- gboolean set = (key_vector[i/8] & (1 << (i % 8))) != 0;
-
- /* The 'offset' parameter allows the caller to have the indices
- * into key_vector to either be X-style (base 8) or evdev (base 0), or
- * something else (unlikely). We subtract 'offset' to convert to evdev
- * style, then add 8 to convert the "evdev" style keycode back to
- * the X-style that xkbcommon expects.
- */
- mods_changed |= xkb_state_update_key (keyboard->xkb_info.state,
- i - offset + 8,
- set ? XKB_KEY_DOWN : XKB_KEY_UP);
- }
-
- mods_changed |= kbd_a11y_apply_mask (keyboard);
- if (mods_changed)
- notify_modifiers (keyboard);
-}
-
-static void
-move_resources (struct wl_list *destination, struct wl_list *source)
-{
- wl_list_insert_list (destination, source);
- wl_list_init (source);
-}
-
-static void
-move_resources_for_client (struct wl_list *destination,
- struct wl_list *source,
- struct wl_client *client)
-{
- struct wl_resource *resource, *tmp;
- wl_resource_for_each_safe (resource, tmp, source)
- {
- if (wl_resource_get_client (resource) == client)
- {
- wl_list_remove (wl_resource_get_link (resource));
- wl_list_insert (destination, wl_resource_get_link (resource));
- }
- }
-}
-
-static void
-broadcast_focus (MetaWaylandKeyboard *keyboard,
- struct wl_resource *resource)
-{
- struct wl_array fake_keys;
-
- /* We never want to send pressed keys to wayland clients on
- * enter. The protocol says that we should send them, presumably so
- * that clients can trigger their own key repeat routine in case
- * they are given focus and a key is physically pressed.
- *
- * Unfortunately this causes some clients, in particular Xwayland,
- * to register key events that they really shouldn't handle,
- * e.g. on an Alt+Tab keybinding, where Alt is released before Tab,
- * clients would see Tab being pressed on enter followed by a key
- * release event for Tab, meaning that Tab would be processed by
- * the client when it really shouldn't.
- *
- * Since the use case for the pressed keys array on enter seems weak
- * to us, we'll just fake that there are no pressed keys instead
- * which should be spec compliant even if it might not be true.
- */
- wl_array_init (&fake_keys);
-
- keyboard_send_modifiers (keyboard, resource, keyboard->focus_serial);
- wl_keyboard_send_enter (resource, keyboard->focus_serial,
- keyboard->focus_surface->resource,
- &fake_keys);
-}
-
-void
-meta_wayland_keyboard_set_focus (MetaWaylandKeyboard *keyboard,
- MetaWaylandSurface *surface)
-{
- MetaWaylandInputDevice *input_device = META_WAYLAND_INPUT_DEVICE (keyboard);
-
- if (keyboard->focus_surface == surface)
- return;
-
- if (keyboard->focus_surface != NULL)
- {
- if (!wl_list_empty (&keyboard->focus_resource_list))
- {
- struct wl_resource *resource;
- uint32_t serial;
-
- serial = meta_wayland_input_device_next_serial (input_device);
-
- wl_resource_for_each (resource, &keyboard->focus_resource_list)
- {
- wl_keyboard_send_leave (resource, serial,
- keyboard->focus_surface->resource);
- }
-
- move_resources (&keyboard->resource_list,
- &keyboard->focus_resource_list);
- }
-
- wl_list_remove (&keyboard->focus_surface_listener.link);
- keyboard->focus_surface = NULL;
- }
-
- if (surface != NULL)
- {
- struct wl_resource *focus_surface_resource;
-
- keyboard->focus_surface = surface;
- focus_surface_resource = keyboard->focus_surface->resource;
- wl_resource_add_destroy_listener (focus_surface_resource,
- &keyboard->focus_surface_listener);
-
- move_resources_for_client (&keyboard->focus_resource_list,
- &keyboard->resource_list,
- wl_resource_get_client (focus_surface_resource));
-
- /* Make sure a11y masks are applied before braodcasting modifiers */
- kbd_a11y_apply_mask (keyboard);
-
- if (!wl_list_empty (&keyboard->focus_resource_list))
- {
- struct wl_resource *resource;
-
- keyboard->focus_serial =
- meta_wayland_input_device_next_serial (input_device);
-
- wl_resource_for_each (resource, &keyboard->focus_resource_list)
- {
- broadcast_focus (keyboard, resource);
- }
- }
- }
-}
-
-struct wl_client *
-meta_wayland_keyboard_get_focus_client (MetaWaylandKeyboard *keyboard)
-{
- if (keyboard->focus_surface)
- return wl_resource_get_client (keyboard->focus_surface->resource);
- else
- return NULL;
-}
-
-static void
-keyboard_release (struct wl_client *client,
- struct wl_resource *resource)
-{
- wl_resource_destroy (resource);
-}
-
-static const struct wl_keyboard_interface keyboard_interface = {
- keyboard_release,
-};
-
-void
-meta_wayland_keyboard_create_new_resource (MetaWaylandKeyboard *keyboard,
- struct wl_client *client,
- struct wl_resource *seat_resource,
- uint32_t id)
-{
- struct wl_resource *resource;
-
- resource = wl_resource_create (client, &wl_keyboard_interface,
- wl_resource_get_version (seat_resource), id);
- wl_resource_set_implementation (resource, &keyboard_interface,
- keyboard, unbind_resource);
-
- send_keymap (keyboard, resource);
-
- notify_key_repeat_for_resource (keyboard, resource);
-
- if (keyboard->focus_surface &&
- wl_resource_get_client (keyboard->focus_surface->resource) == client)
- {
- wl_list_insert (&keyboard->focus_resource_list,
- wl_resource_get_link (resource));
- broadcast_focus (keyboard, resource);
- }
- else
- {
- wl_list_insert (&keyboard->resource_list,
- wl_resource_get_link (resource));
- }
-}
-
-gboolean
-meta_wayland_keyboard_can_popup (MetaWaylandKeyboard *keyboard,
- uint32_t serial)
-{
- return (keyboard->key_down_serial == serial ||
- ((keyboard->key_down_keycode == keyboard->key_up_keycode) &&
- keyboard->key_up_serial == serial));
-}
-
-void
-meta_wayland_keyboard_start_grab (MetaWaylandKeyboard *keyboard,
- MetaWaylandKeyboardGrab *grab)
-{
- meta_wayland_keyboard_set_focus (keyboard, NULL);
- keyboard->grab = grab;
- grab->keyboard = keyboard;
-}
-
-void
-meta_wayland_keyboard_end_grab (MetaWaylandKeyboard *keyboard)
-{
- keyboard->grab = &keyboard->default_grab;
-}
-
-static void
-meta_wayland_keyboard_init (MetaWaylandKeyboard *keyboard)
-{
- wl_list_init (&keyboard->resource_list);
- wl_list_init (&keyboard->focus_resource_list);
-
- keyboard->default_grab.interface = &default_keyboard_grab_interface;
- keyboard->default_grab.keyboard = keyboard;
- keyboard->grab = &keyboard->default_grab;
-
- keyboard->focus_surface_listener.notify =
- keyboard_handle_focus_surface_destroy;
-}
-
-static void
-meta_wayland_keyboard_finalize (GObject *object)
-{
- MetaWaylandKeyboard *keyboard = META_WAYLAND_KEYBOARD (object);
-
- meta_wayland_xkb_info_destroy (&keyboard->xkb_info);
-
- G_OBJECT_CLASS (meta_wayland_keyboard_parent_class)->finalize (object);
-}
-
-static void
-meta_wayland_keyboard_class_init (MetaWaylandKeyboardClass *klass)
-{
- GObjectClass *object_class = G_OBJECT_CLASS (klass);
-
- object_class->finalize = meta_wayland_keyboard_finalize;
-}