summaryrefslogtreecommitdiff
path: root/src/core/keybindings.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/keybindings.c')
-rw-r--r--src/core/keybindings.c4578
1 files changed, 0 insertions, 4578 deletions
diff --git a/src/core/keybindings.c b/src/core/keybindings.c
deleted file mode 100644
index a6e16f084..000000000
--- a/src/core/keybindings.c
+++ /dev/null
@@ -1,4578 +0,0 @@
-/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
-
-/* Mutter Keybindings */
-/*
- * Copyright (C) 2001 Havoc Pennington
- * Copyright (C) 2002 Red Hat Inc.
- * Copyright (C) 2003 Rob Adams
- * Copyright (C) 2004-2006 Elijah Newren
- *
- * 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, see <http://www.gnu.org/licenses/>.
- */
-
-/**
- * SECTION:keybindings
- * @Title: MetaKeybinding
- * @Short_Description: Key bindings
- */
-
-#include "config.h"
-
-#include "backends/meta-backend-private.h"
-#include "backends/meta-keymap-utils.h"
-#include "backends/meta-logical-monitor.h"
-#include "backends/meta-monitor-manager-private.h"
-#include "backends/x11/meta-backend-x11.h"
-#include "backends/x11/meta-input-device-x11.h"
-#include "compositor/compositor-private.h"
-#include "core/edge-resistance.h"
-#include "core/frame.h"
-#include "core/keybindings-private.h"
-#include "core/meta-accel-parse.h"
-#include "core/meta-workspace-manager-private.h"
-#include "core/workspace-private.h"
-#include "meta/compositor.h"
-#include "meta/meta-x11-errors.h"
-#include "meta/prefs.h"
-#include "x11/meta-x11-display-private.h"
-#include "x11/window-x11.h"
-
-#ifdef HAVE_NATIVE_BACKEND
-#include "backends/native/meta-backend-native.h"
-#endif
-
-#ifdef __linux__
-#include <linux/input.h>
-#elif !defined KEY_GRAVE
-#define KEY_GRAVE 0x29 /* assume the use of xf86-input-keyboard */
-#endif
-
-#define SCHEMA_COMMON_KEYBINDINGS "org.gnome.desktop.wm.keybindings"
-#define SCHEMA_MUTTER_KEYBINDINGS "org.gnome.mutter.keybindings"
-#define SCHEMA_MUTTER_WAYLAND_KEYBINDINGS "org.gnome.mutter.wayland.keybindings"
-
-#define META_KEY_BINDING_PRIMARY_LAYOUT 0
-#define META_KEY_BINDING_SECONDARY_LAYOUT 1
-
-/* Only for special modifier keys */
-#define IGNORED_MODIFIERS (CLUTTER_LOCK_MASK | \
- CLUTTER_MOD2_MASK | \
- CLUTTER_BUTTON1_MASK | \
- CLUTTER_BUTTON2_MASK | \
- CLUTTER_BUTTON3_MASK | \
- CLUTTER_BUTTON4_MASK | \
- CLUTTER_BUTTON5_MASK)
-
-static gboolean add_builtin_keybinding (MetaDisplay *display,
- const char *name,
- GSettings *settings,
- MetaKeyBindingFlags flags,
- MetaKeyBindingAction action,
- MetaKeyHandlerFunc handler,
- int handler_arg);
-
-static void
-resolved_key_combo_reset (MetaResolvedKeyCombo *resolved_combo)
-{
- g_free (resolved_combo->keycodes);
- resolved_combo->len = 0;
- resolved_combo->keycodes = NULL;
-}
-
-static void
-resolved_key_combo_copy (MetaResolvedKeyCombo *from,
- MetaResolvedKeyCombo *to)
-{
- to->len = from->len;
- to->keycodes = g_memdup2 (from->keycodes,
- from->len * sizeof (xkb_keycode_t));
-}
-
-static gboolean
-resolved_key_combo_has_keycode (MetaResolvedKeyCombo *resolved_combo,
- int keycode)
-{
- int i;
-
- for (i = 0; i < resolved_combo->len; i++)
- if ((int) resolved_combo->keycodes[i] == keycode)
- return TRUE;
-
- return FALSE;
-}
-
-static gboolean
-resolved_key_combo_intersect (MetaResolvedKeyCombo *a,
- MetaResolvedKeyCombo *b)
-{
- int i;
-
- for (i = 0; i < a->len; i++)
- if (resolved_key_combo_has_keycode (b, a->keycodes[i]))
- return TRUE;
-
- return FALSE;
-}
-
-static void
-meta_key_binding_free (MetaKeyBinding *binding)
-{
- resolved_key_combo_reset (&binding->resolved_combo);
- g_free (binding);
-}
-
-static MetaKeyBinding *
-meta_key_binding_copy (MetaKeyBinding *binding)
-{
- MetaKeyBinding *clone = g_memdup2 (binding, sizeof (MetaKeyBinding));
- resolved_key_combo_copy (&binding->resolved_combo,
- &clone->resolved_combo);
- return clone;
-}
-
-G_DEFINE_BOXED_TYPE(MetaKeyBinding,
- meta_key_binding,
- meta_key_binding_copy,
- meta_key_binding_free)
-
-const char *
-meta_key_binding_get_name (MetaKeyBinding *binding)
-{
- return binding->name;
-}
-
-MetaVirtualModifier
-meta_key_binding_get_modifiers (MetaKeyBinding *binding)
-{
- return binding->combo.modifiers;
-}
-
-gboolean
-meta_key_binding_is_reversed (MetaKeyBinding *binding)
-{
- return (binding->handler->flags & META_KEY_BINDING_IS_REVERSED) != 0;
-}
-
-guint
-meta_key_binding_get_mask (MetaKeyBinding *binding)
-{
- return binding->resolved_combo.mask;
-}
-
-gboolean
-meta_key_binding_is_builtin (MetaKeyBinding *binding)
-{
- return binding->handler->flags & META_KEY_BINDING_BUILTIN;
-}
-
-/* These can't be bound to anything, but they are used to handle
- * various other events. TODO: Possibly we should include them as event
- * handler functions and have some kind of flag to say they're unbindable.
- */
-
-static gboolean process_mouse_move_resize_grab (MetaDisplay *display,
- MetaWindow *window,
- ClutterKeyEvent *event);
-
-static gboolean process_keyboard_move_grab (MetaDisplay *display,
- MetaWindow *window,
- ClutterKeyEvent *event);
-
-static gboolean process_keyboard_resize_grab (MetaDisplay *display,
- MetaWindow *window,
- ClutterKeyEvent *event);
-
-static void maybe_update_locate_pointer_keygrab (MetaDisplay *display,
- gboolean grab);
-
-static GHashTable *key_handlers;
-static GHashTable *external_grabs;
-
-#define HANDLER(name) g_hash_table_lookup (key_handlers, (name))
-
-static void
-key_handler_free (MetaKeyHandler *handler)
-{
- g_free (handler->name);
- if (handler->user_data_free_func && handler->user_data)
- handler->user_data_free_func (handler->user_data);
- g_free (handler);
-}
-
-typedef struct _MetaKeyGrab MetaKeyGrab;
-struct _MetaKeyGrab {
- char *name;
- guint action;
- MetaKeyCombo combo;
- gint flags;
-};
-
-static void
-meta_key_grab_free (MetaKeyGrab *grab)
-{
- g_free (grab->name);
- g_free (grab);
-}
-
-static guint32
-key_combo_key (MetaResolvedKeyCombo *resolved_combo,
- int i)
-{
- /* On X, keycodes are only 8 bits while libxkbcommon supports 32 bit
- keycodes, but since we're using the same XKB keymaps that X uses,
- we won't find keycodes bigger than 8 bits in practice. The bits
- that mutter cares about in the modifier mask are also all in the
- lower 8 bits both on X and clutter key events. This means that we
- can use a 32 bit integer to safely concatenate both keycode and
- mask and thus making it easy to use them as an index in a
- GHashTable. */
- guint32 key = resolved_combo->keycodes[i] & 0xffff;
- return (key << 16) | (resolved_combo->mask & 0xffff);
-}
-
-static void
-reload_modmap (MetaKeyBindingManager *keys)
-{
- struct xkb_keymap *keymap = meta_backend_get_keymap (keys->backend);
- struct xkb_state *scratch_state;
- xkb_mod_mask_t scroll_lock_mask;
- xkb_mod_mask_t dummy_mask;
-
- /* Modifiers to find. */
- struct {
- const char *name;
- xkb_mod_mask_t *mask_p;
- xkb_mod_mask_t *virtual_mask_p;
- } mods[] = {
- { "ScrollLock", &scroll_lock_mask, &dummy_mask },
- { "Meta", &keys->meta_mask, &keys->virtual_meta_mask },
- { "Hyper", &keys->hyper_mask, &keys->virtual_hyper_mask },
- { "Super", &keys->super_mask, &keys->virtual_super_mask },
- };
-
- scratch_state = xkb_state_new (keymap);
-
- gsize i;
- for (i = 0; i < G_N_ELEMENTS (mods); i++)
- {
- xkb_mod_mask_t *mask_p = mods[i].mask_p;
- xkb_mod_mask_t *virtual_mask_p = mods[i].virtual_mask_p;
- xkb_mod_index_t idx = xkb_keymap_mod_get_index (keymap, mods[i].name);
-
- if (idx != XKB_MOD_INVALID)
- {
- xkb_mod_mask_t vmodmask = (1 << idx);
- xkb_state_update_mask (scratch_state, vmodmask, 0, 0, 0, 0, 0);
- *mask_p = xkb_state_serialize_mods (scratch_state, XKB_STATE_MODS_DEPRESSED) & ~vmodmask;
- *virtual_mask_p = vmodmask;
- }
- else
- {
- *mask_p = 0;
- *virtual_mask_p = 0;
- }
- }
-
- xkb_state_unref (scratch_state);
-
- keys->ignored_modifier_mask = (scroll_lock_mask | Mod2Mask | LockMask);
-
- meta_topic (META_DEBUG_KEYBINDINGS,
- "Ignoring modmask 0x%x scroll lock 0x%x hyper 0x%x super 0x%x meta 0x%x",
- keys->ignored_modifier_mask,
- scroll_lock_mask,
- keys->hyper_mask,
- keys->super_mask,
- keys->meta_mask);
-}
-
-static gboolean
-is_keycode_for_keysym (struct xkb_keymap *keymap,
- xkb_layout_index_t layout,
- xkb_level_index_t level,
- xkb_keycode_t keycode,
- xkb_keysym_t keysym)
-{
- const xkb_keysym_t *syms;
- int num_syms, k;
-
- num_syms = xkb_keymap_key_get_syms_by_level (keymap, keycode, layout, level, &syms);
- for (k = 0; k < num_syms; k++)
- {
- if (syms[k] == keysym)
- return TRUE;
- }
-
- return FALSE;
-}
-
-typedef struct
-{
- GArray *keycodes;
- xkb_keysym_t keysym;
- xkb_layout_index_t layout;
- xkb_level_index_t level;
-} FindKeysymData;
-
-static void
-get_keycodes_for_keysym_iter (struct xkb_keymap *keymap,
- xkb_keycode_t keycode,
- void *data)
-{
- FindKeysymData *search_data = data;
- GArray *keycodes = search_data->keycodes;
- xkb_keysym_t keysym = search_data->keysym;
- xkb_layout_index_t layout = search_data->layout;
- xkb_level_index_t level = search_data->level;
-
- if (is_keycode_for_keysym (keymap, layout, level, keycode, keysym))
- {
- guint i;
- gboolean missing = TRUE;
-
- /* duplicate keycode detection */
- for (i = 0; i < keycodes->len; i++)
- if (g_array_index (keycodes, xkb_keysym_t, i) == keycode)
- {
- missing = FALSE;
- break;
- }
-
- if (missing)
- g_array_append_val (keycodes, keycode);
- }
-}
-
-static void
-add_keysym_keycodes_from_layout (int keysym,
- MetaKeyBindingKeyboardLayout *layout,
- GArray *keycodes)
-{
- xkb_level_index_t layout_level;
-
- for (layout_level = 0;
- layout_level < layout->n_levels && keycodes->len == 0;
- layout_level++)
- {
- FindKeysymData search_data = (FindKeysymData) {
- .keycodes = keycodes,
- .keysym = keysym,
- .layout = layout->index,
- .level = layout_level
- };
- xkb_keymap_key_for_each (layout->keymap,
- get_keycodes_for_keysym_iter,
- &search_data);
- }
-}
-
-/* Original code from gdk_x11_keymap_get_entries_for_keyval() in
- * gdkkeys-x11.c */
-static void
-get_keycodes_for_keysym (MetaKeyBindingManager *keys,
- int keysym,
- MetaResolvedKeyCombo *resolved_combo)
-{
- unsigned int i;
- GArray *keycodes;
- int keycode;
-
- keycodes = g_array_new (FALSE, FALSE, sizeof (xkb_keysym_t));
-
- /* Special-case: Fake mutter keysym */
- if (keysym == META_KEY_ABOVE_TAB)
- {
- keycode = KEY_GRAVE + 8;
- g_array_append_val (keycodes, keycode);
- goto out;
- }
-
- for (i = 0; i < G_N_ELEMENTS (keys->active_layouts); i++)
- {
- MetaKeyBindingKeyboardLayout *layout = &keys->active_layouts[i];
-
- if (!layout->keymap)
- continue;
-
- add_keysym_keycodes_from_layout (keysym, layout, keycodes);
- }
-
- out:
- resolved_combo->len = keycodes->len;
- resolved_combo->keycodes =
- (xkb_keycode_t *) g_array_free (keycodes,
- keycodes->len == 0 ? TRUE : FALSE);
-}
-
-typedef struct _CalculateLayoutLevelsState
-{
- struct xkb_keymap *keymap;
- xkb_layout_index_t layout_index;
-
- xkb_level_index_t out_n_levels;
-} CalculateLayoutLevelState;
-
-static void
-calculate_n_layout_levels_iter (struct xkb_keymap *keymap,
- xkb_keycode_t keycode,
- void *data)
-{
- CalculateLayoutLevelState *state = data;
- xkb_level_index_t n_levels;
-
- n_levels = xkb_keymap_num_levels_for_key (keymap,
- keycode,
- state->layout_index);
-
- state->out_n_levels = MAX (n_levels, state->out_n_levels);
-}
-
-static xkb_level_index_t
-calculate_n_layout_levels (struct xkb_keymap *keymap,
- xkb_layout_index_t layout_index)
-
-{
- CalculateLayoutLevelState state = {
- .keymap = keymap,
- .layout_index = layout_index,
-
- .out_n_levels = 0
- };
-
- xkb_keymap_key_for_each (keymap, calculate_n_layout_levels_iter, &state);
-
- return state.out_n_levels;
-}
-
-static void
-reload_iso_next_group_combos (MetaKeyBindingManager *keys)
-{
- const char *iso_next_group_option;
- int i;
-
- for (i = 0; i < keys->n_iso_next_group_combos; i++)
- resolved_key_combo_reset (&keys->iso_next_group_combo[i]);
-
- keys->n_iso_next_group_combos = 0;
-
- iso_next_group_option = meta_prefs_get_iso_next_group_option ();
- if (iso_next_group_option == NULL)
- return;
-
- get_keycodes_for_keysym (keys, XKB_KEY_ISO_Next_Group, keys->iso_next_group_combo);
-
- if (keys->iso_next_group_combo[0].len == 0)
- return;
-
- keys->n_iso_next_group_combos = 1;
-
- if (g_str_equal (iso_next_group_option, "toggle") ||
- g_str_equal (iso_next_group_option, "lalt_toggle") ||
- g_str_equal (iso_next_group_option, "lwin_toggle") ||
- g_str_equal (iso_next_group_option, "rwin_toggle") ||
- g_str_equal (iso_next_group_option, "lshift_toggle") ||
- g_str_equal (iso_next_group_option, "rshift_toggle") ||
- g_str_equal (iso_next_group_option, "lctrl_toggle") ||
- g_str_equal (iso_next_group_option, "rctrl_toggle") ||
- g_str_equal (iso_next_group_option, "sclk_toggle") ||
- g_str_equal (iso_next_group_option, "menu_toggle") ||
- g_str_equal (iso_next_group_option, "caps_toggle"))
- {
- keys->iso_next_group_combo[0].mask = 0;
- }
- else if (g_str_equal (iso_next_group_option, "shift_caps_toggle") ||
- g_str_equal (iso_next_group_option, "shifts_toggle"))
- {
- keys->iso_next_group_combo[0].mask = ShiftMask;
- }
- else if (g_str_equal (iso_next_group_option, "alt_caps_toggle") ||
- g_str_equal (iso_next_group_option, "alt_space_toggle"))
- {
- keys->iso_next_group_combo[0].mask = Mod1Mask;
- }
- else if (g_str_equal (iso_next_group_option, "ctrl_shift_toggle") ||
- g_str_equal (iso_next_group_option, "lctrl_lshift_toggle") ||
- g_str_equal (iso_next_group_option, "rctrl_rshift_toggle"))
- {
- resolved_key_combo_copy (&keys->iso_next_group_combo[0],
- &keys->iso_next_group_combo[1]);
-
- keys->iso_next_group_combo[0].mask = ShiftMask;
- keys->iso_next_group_combo[1].mask = ControlMask;
- keys->n_iso_next_group_combos = 2;
- }
- else if (g_str_equal (iso_next_group_option, "ctrl_alt_toggle"))
- {
- resolved_key_combo_copy (&keys->iso_next_group_combo[0],
- &keys->iso_next_group_combo[1]);
-
- keys->iso_next_group_combo[0].mask = Mod1Mask;
- keys->iso_next_group_combo[1].mask = ControlMask;
- keys->n_iso_next_group_combos = 2;
- }
- else if (g_str_equal (iso_next_group_option, "alt_shift_toggle") ||
- g_str_equal (iso_next_group_option, "lalt_lshift_toggle"))
- {
- resolved_key_combo_copy (&keys->iso_next_group_combo[0],
- &keys->iso_next_group_combo[1]);
-
- keys->iso_next_group_combo[0].mask = Mod1Mask;
- keys->iso_next_group_combo[1].mask = ShiftMask;
- keys->n_iso_next_group_combos = 2;
- }
- else
- {
- resolved_key_combo_reset (keys->iso_next_group_combo);
- keys->n_iso_next_group_combos = 0;
- }
-}
-
-static void
-devirtualize_modifiers (MetaKeyBindingManager *keys,
- MetaVirtualModifier modifiers,
- unsigned int *mask)
-{
- *mask = 0;
-
- if (modifiers & META_VIRTUAL_SHIFT_MASK)
- *mask |= ShiftMask;
- if (modifiers & META_VIRTUAL_CONTROL_MASK)
- *mask |= ControlMask;
- if (modifiers & META_VIRTUAL_ALT_MASK)
- *mask |= Mod1Mask;
- if (modifiers & META_VIRTUAL_META_MASK)
- *mask |= keys->meta_mask;
- if (modifiers & META_VIRTUAL_HYPER_MASK)
- *mask |= keys->hyper_mask;
- if (modifiers & META_VIRTUAL_SUPER_MASK)
- *mask |= keys->super_mask;
- if (modifiers & META_VIRTUAL_MOD2_MASK)
- *mask |= Mod2Mask;
- if (modifiers & META_VIRTUAL_MOD3_MASK)
- *mask |= Mod3Mask;
- if (modifiers & META_VIRTUAL_MOD4_MASK)
- *mask |= Mod4Mask;
- if (modifiers & META_VIRTUAL_MOD5_MASK)
- *mask |= Mod5Mask;
-}
-
-static void
-index_binding (MetaKeyBindingManager *keys,
- MetaKeyBinding *binding)
-{
- int i;
-
- for (i = 0; i < binding->resolved_combo.len; i++)
- {
- MetaKeyBinding *existing;
- guint32 index_key;
-
- index_key = key_combo_key (&binding->resolved_combo, i);
-
- existing = g_hash_table_lookup (keys->key_bindings_index,
- GINT_TO_POINTER (index_key));
- if (existing != NULL)
- {
- /* Overwrite already indexed keycodes only for the first
- * keycode, i.e. we give those primary keycodes precedence
- * over non-first ones. */
- if (i > 0)
- continue;
-
- meta_warning ("Overwriting existing binding of keysym %x"
- " with keysym %x (keycode %x).",
- binding->combo.keysym,
- existing->combo.keysym,
- binding->resolved_combo.keycodes[i]);
- }
-
- g_hash_table_replace (keys->key_bindings_index,
- GINT_TO_POINTER (index_key), binding);
- }
-}
-
-static void
-resolve_key_combo (MetaKeyBindingManager *keys,
- MetaKeyCombo *combo,
- MetaResolvedKeyCombo *resolved_combo)
-{
-
- resolved_key_combo_reset (resolved_combo);
-
- if (combo->keysym != 0)
- {
- get_keycodes_for_keysym (keys, combo->keysym, resolved_combo);
- }
- else if (combo->keycode != 0)
- {
- resolved_combo->keycodes = g_new0 (xkb_keycode_t, 1);
- resolved_combo->keycodes[0] = combo->keycode;
- resolved_combo->len = 1;
- }
-
- devirtualize_modifiers (keys, combo->modifiers, &resolved_combo->mask);
-}
-
-static void
-binding_reload_combos_foreach (gpointer key,
- gpointer value,
- gpointer data)
-{
- MetaKeyBindingManager *keys = data;
- MetaKeyBinding *binding = value;
-
- resolve_key_combo (keys, &binding->combo, &binding->resolved_combo);
- index_binding (keys, binding);
-}
-
-typedef struct _FindLatinKeysymsState
-{
- MetaKeyBindingKeyboardLayout *layout;
- gboolean *required_keysyms_found;
- int n_required_keysyms;
-} FindLatinKeysymsState;
-
-static void
-find_latin_keysym (struct xkb_keymap *keymap,
- xkb_keycode_t key,
- void *data)
-{
- FindLatinKeysymsState *state = data;
- int n_keysyms, i;
- const xkb_keysym_t *keysyms;
-
- n_keysyms = xkb_keymap_key_get_syms_by_level (state->layout->keymap,
- key,
- state->layout->index,
- 0,
- &keysyms);
- for (i = 0; i < n_keysyms; i++)
- {
- xkb_keysym_t keysym = keysyms[i];
-
- if (keysym >= XKB_KEY_a && keysym <= XKB_KEY_z)
- {
- unsigned int keysym_index = keysym - XKB_KEY_a;
-
- if (!state->required_keysyms_found[keysym_index])
- {
- state->required_keysyms_found[keysym_index] = TRUE;
- state->n_required_keysyms--;
- }
- }
- }
-}
-
-static gboolean
-needs_secondary_layout (MetaKeyBindingKeyboardLayout *layout)
-{
- gboolean required_keysyms_found[] = {
- FALSE, /* XKB_KEY_a */
- FALSE, /* XKB_KEY_b */
- FALSE, /* XKB_KEY_c */
- FALSE, /* XKB_KEY_d */
- FALSE, /* XKB_KEY_e */
- FALSE, /* XKB_KEY_f */
- FALSE, /* XKB_KEY_g */
- FALSE, /* XKB_KEY_h */
- FALSE, /* XKB_KEY_i */
- FALSE, /* XKB_KEY_j */
- FALSE, /* XKB_KEY_k */
- FALSE, /* XKB_KEY_l */
- FALSE, /* XKB_KEY_m */
- FALSE, /* XKB_KEY_n */
- FALSE, /* XKB_KEY_o */
- FALSE, /* XKB_KEY_p */
- FALSE, /* XKB_KEY_q */
- FALSE, /* XKB_KEY_r */
- FALSE, /* XKB_KEY_s */
- FALSE, /* XKB_KEY_t */
- FALSE, /* XKB_KEY_u */
- FALSE, /* XKB_KEY_v */
- FALSE, /* XKB_KEY_w */
- FALSE, /* XKB_KEY_x */
- FALSE, /* XKB_KEY_y */
- FALSE, /* XKB_KEY_z */
- };
- FindLatinKeysymsState state = {
- .layout = layout,
- .required_keysyms_found = required_keysyms_found,
- .n_required_keysyms = G_N_ELEMENTS (required_keysyms_found),
- };
-
- xkb_keymap_key_for_each (layout->keymap, find_latin_keysym, &state);
-
- return state.n_required_keysyms != 0;
-}
-
-static void
-clear_active_keyboard_layouts (MetaKeyBindingManager *keys)
-{
- unsigned int i;
-
- for (i = 0; i < G_N_ELEMENTS (keys->active_layouts); i++)
- {
- MetaKeyBindingKeyboardLayout *layout = &keys->active_layouts[i];
-
- g_clear_pointer (&layout->keymap, xkb_keymap_unref);
- *layout = (MetaKeyBindingKeyboardLayout) { 0 };
- }
-}
-
-static MetaKeyBindingKeyboardLayout
-create_us_layout (void)
-{
- struct xkb_rule_names names;
- struct xkb_keymap *keymap;
- struct xkb_context *context;
-
- names.rules = DEFAULT_XKB_RULES_FILE;
- names.model = DEFAULT_XKB_MODEL;
- names.layout = "us";
- names.variant = "";
- names.options = "";
-
- context = meta_create_xkb_context ();
- keymap = xkb_keymap_new_from_names (context, &names, XKB_KEYMAP_COMPILE_NO_FLAGS);
- xkb_context_unref (context);
-
- return (MetaKeyBindingKeyboardLayout) {
- .keymap = keymap,
- .n_levels = calculate_n_layout_levels (keymap, 0),
- };
-}
-
-static void
-reload_active_keyboard_layouts (MetaKeyBindingManager *keys)
-{
- struct xkb_keymap *keymap;
- xkb_layout_index_t layout_index;
- MetaKeyBindingKeyboardLayout primary_layout;
-
- clear_active_keyboard_layouts (keys);
-
- keymap = meta_backend_get_keymap (keys->backend);
- layout_index = meta_backend_get_keymap_layout_group (keys->backend);
- primary_layout = (MetaKeyBindingKeyboardLayout) {
- .keymap = xkb_keymap_ref (keymap),
- .index = layout_index,
- .n_levels = calculate_n_layout_levels (keymap, layout_index),
- };
-
- keys->active_layouts[META_KEY_BINDING_PRIMARY_LAYOUT] = primary_layout;
-
- if (needs_secondary_layout (&primary_layout))
- {
- MetaKeyBindingKeyboardLayout us_layout;
-
- us_layout = create_us_layout ();
- keys->active_layouts[META_KEY_BINDING_SECONDARY_LAYOUT] = us_layout;
- }
-}
-
-static void
-reload_combos (MetaKeyBindingManager *keys)
-{
- g_hash_table_remove_all (keys->key_bindings_index);
-
- reload_active_keyboard_layouts (keys);
-
- resolve_key_combo (keys,
- &keys->overlay_key_combo,
- &keys->overlay_resolved_key_combo);
-
- resolve_key_combo (keys,
- &keys->locate_pointer_key_combo,
- &keys->locate_pointer_resolved_key_combo);
-
- reload_iso_next_group_combos (keys);
-
- g_hash_table_foreach (keys->key_bindings, binding_reload_combos_foreach, keys);
-}
-
-static void
-rebuild_binding_table (MetaKeyBindingManager *keys,
- GList *prefs,
- GList *grabs)
-{
- MetaKeyBinding *b;
- GList *p, *g;
-
- g_hash_table_remove_all (keys->key_bindings);
-
- p = prefs;
- while (p)
- {
- MetaKeyPref *pref = (MetaKeyPref*)p->data;
- GSList *tmp = pref->combos;
-
- while (tmp)
- {
- MetaKeyCombo *combo = tmp->data;
-
- if (combo && (combo->keysym != None || combo->keycode != 0))
- {
- MetaKeyHandler *handler = HANDLER (pref->name);
-
- b = g_new0 (MetaKeyBinding, 1);
- b->name = pref->name;
- b->handler = handler;
- b->flags = handler->flags;
- b->combo = *combo;
-
- g_hash_table_add (keys->key_bindings, b);
- }
-
- tmp = tmp->next;
- }
-
- p = p->next;
- }
-
- g = grabs;
- while (g)
- {
- MetaKeyGrab *grab = (MetaKeyGrab*)g->data;
- if (grab->combo.keysym != None || grab->combo.keycode != 0)
- {
- MetaKeyHandler *handler = HANDLER ("external-grab");
-
- b = g_new0 (MetaKeyBinding, 1);
- b->name = grab->name;
- b->handler = handler;
- b->flags = grab->flags;
- b->combo = grab->combo;
-
- g_hash_table_add (keys->key_bindings, b);
- }
-
- g = g->next;
- }
-
- meta_topic (META_DEBUG_KEYBINDINGS,
- " %d bindings in table",
- g_hash_table_size (keys->key_bindings));
-}
-
-static void
-rebuild_key_binding_table (MetaKeyBindingManager *keys)
-{
- GList *prefs, *grabs;
-
- meta_topic (META_DEBUG_KEYBINDINGS,
- "Rebuilding key binding table from preferences");
-
- prefs = meta_prefs_get_keybindings ();
- grabs = g_hash_table_get_values (external_grabs);
- rebuild_binding_table (keys, prefs, grabs);
- g_list_free (prefs);
- g_list_free (grabs);
-}
-
-static void
-rebuild_special_bindings (MetaKeyBindingManager *keys)
-{
- MetaKeyCombo combo;
-
- meta_prefs_get_overlay_binding (&combo);
- keys->overlay_key_combo = combo;
-
- meta_prefs_get_locate_pointer_binding (&combo);
- keys->locate_pointer_key_combo = combo;
-}
-
-static void
-ungrab_key_bindings (MetaDisplay *display)
-{
- GSList *windows, *l;
-
- if (display->x11_display)
- meta_x11_display_ungrab_keys (display->x11_display);
-
- windows = meta_display_list_windows (display, META_LIST_DEFAULT);
- for (l = windows; l; l = l->next)
- {
- MetaWindow *w = l->data;
- meta_window_ungrab_keys (w);
- }
-
- g_slist_free (windows);
-}
-
-static void
-grab_key_bindings (MetaDisplay *display)
-{
- GSList *windows, *l;
-
- if (display->x11_display)
- meta_x11_display_grab_keys (display->x11_display);
-
- windows = meta_display_list_windows (display, META_LIST_DEFAULT);
- for (l = windows; l; l = l->next)
- {
- MetaWindow *w = l->data;
- meta_window_grab_keys (w);
- }
-
- g_slist_free (windows);
-}
-
-static MetaKeyBinding *
-get_keybinding (MetaKeyBindingManager *keys,
- MetaResolvedKeyCombo *resolved_combo)
-{
- MetaKeyBinding *binding = NULL;
- int i;
-
- for (i = 0; i < resolved_combo->len; i++)
- {
- guint32 key;
-
- key = key_combo_key (resolved_combo, i);
- binding = g_hash_table_lookup (keys->key_bindings_index,
- GINT_TO_POINTER (key));
-
- if (binding != NULL)
- break;
- }
-
- return binding;
-}
-
-static guint
-next_dynamic_keybinding_action (void)
-{
- static guint num_dynamic_bindings = 0;
- return META_KEYBINDING_ACTION_LAST + (++num_dynamic_bindings);
-}
-
-static gboolean
-add_keybinding_internal (MetaDisplay *display,
- const char *name,
- GSettings *settings,
- MetaKeyBindingFlags flags,
- MetaKeyBindingAction action,
- MetaKeyHandlerFunc func,
- int data,
- gpointer user_data,
- GDestroyNotify free_data)
-{
- MetaKeyHandler *handler;
-
- if (!meta_prefs_add_keybinding (name, settings, action, flags))
- return FALSE;
-
- handler = g_new0 (MetaKeyHandler, 1);
- handler->name = g_strdup (name);
- handler->func = func;
- handler->default_func = func;
- handler->data = data;
- handler->flags = flags;
- handler->user_data = user_data;
- handler->user_data_free_func = free_data;
-
- g_hash_table_insert (key_handlers, g_strdup (name), handler);
-
- return TRUE;
-}
-
-static gboolean
-add_builtin_keybinding (MetaDisplay *display,
- const char *name,
- GSettings *settings,
- MetaKeyBindingFlags flags,
- MetaKeyBindingAction action,
- MetaKeyHandlerFunc handler,
- int handler_arg)
-{
- return add_keybinding_internal (display, name, settings,
- flags | META_KEY_BINDING_BUILTIN,
- action, handler, handler_arg, NULL, NULL);
-}
-
-/**
- * meta_display_add_keybinding:
- * @display: a #MetaDisplay
- * @name: the binding's name
- * @settings: the #GSettings object where @name is stored
- * @flags: flags to specify binding details
- * @handler: function to run when the keybinding is invoked
- * @user_data: the data to pass to @handler
- * @free_data: function to free @user_data
- *
- * Add a keybinding at runtime. The key @name in @schema needs to be of
- * type %G_VARIANT_TYPE_STRING_ARRAY, with each string describing a
- * keybinding in the form of "&lt;Control&gt;a" or "&lt;Shift&gt;&lt;Alt&gt;F1". The parser
- * is fairly liberal and allows lower or upper case, and also abbreviations
- * such as "&lt;Ctl&gt;" and "&lt;Ctrl&gt;". If the key is set to the empty list or a
- * list with a single element of either "" or "disabled", the keybinding is
- * disabled.
- *
- * Use meta_display_remove_keybinding() to remove the binding.
- *
- * Returns: the corresponding keybinding action if the keybinding was
- * added successfully, otherwise %META_KEYBINDING_ACTION_NONE
- */
-guint
-meta_display_add_keybinding (MetaDisplay *display,
- const char *name,
- GSettings *settings,
- MetaKeyBindingFlags flags,
- MetaKeyHandlerFunc handler,
- gpointer user_data,
- GDestroyNotify free_data)
-{
- guint new_action = next_dynamic_keybinding_action ();
-
- if (!add_keybinding_internal (display, name, settings, flags, new_action,
- handler, 0, user_data, free_data))
- return META_KEYBINDING_ACTION_NONE;
-
- return new_action;
-}
-
-/**
- * meta_display_remove_keybinding:
- * @display: the #MetaDisplay
- * @name: name of the keybinding to remove
- *
- * Remove keybinding @name; the function will fail if @name is not a known
- * keybinding or has not been added with meta_display_add_keybinding().
- *
- * Returns: %TRUE if the binding has been removed successfully,
- * otherwise %FALSE
- */
-gboolean
-meta_display_remove_keybinding (MetaDisplay *display,
- const char *name)
-{
- if (!meta_prefs_remove_keybinding (name))
- return FALSE;
-
- g_hash_table_remove (key_handlers, name);
-
- return TRUE;
-}
-
-static guint
-get_keybinding_action (MetaKeyBindingManager *keys,
- MetaResolvedKeyCombo *resolved_combo)
-{
- MetaKeyBinding *binding;
-
- /* This is much more vague than the MetaDisplay::overlay-key signal,
- * which is only emitted if the overlay-key is the only key pressed;
- * as this method is primarily intended for plugins to allow processing
- * of mutter keybindings while holding a grab, the overlay-key-only-pressed
- * tracking is left to the plugin here.
- */
- if (resolved_key_combo_intersect (resolved_combo,
- &keys->overlay_resolved_key_combo))
- return META_KEYBINDING_ACTION_OVERLAY_KEY;
-
- if (resolved_key_combo_intersect (resolved_combo,
- &keys->locate_pointer_resolved_key_combo))
- return META_KEYBINDING_ACTION_LOCATE_POINTER_KEY;
-
- binding = get_keybinding (keys, resolved_combo);
- if (binding)
- {
- MetaKeyGrab *grab = g_hash_table_lookup (external_grabs, binding->name);
- if (grab)
- return grab->action;
- else
- return (guint) meta_prefs_get_keybinding_action (binding->name);
- }
- else
- {
- return META_KEYBINDING_ACTION_NONE;
- }
-}
-
-static xkb_mod_mask_t
-mask_from_event_params (MetaKeyBindingManager *keys,
- unsigned long mask)
-{
- return mask & 0xff & ~keys->ignored_modifier_mask;
-}
-
-/**
- * meta_display_get_keybinding_action:
- * @display: A #MetaDisplay
- * @keycode: Raw keycode
- * @mask: Event mask
- *
- * Get the keybinding action bound to @keycode. Builtin keybindings
- * have a fixed associated #MetaKeyBindingAction, for bindings added
- * dynamically the function will return the keybinding action
- * meta_display_add_keybinding() returns on registration.
- *
- * Returns: The action that should be taken for the given key, or
- * %META_KEYBINDING_ACTION_NONE.
- */
-guint
-meta_display_get_keybinding_action (MetaDisplay *display,
- unsigned int keycode,
- unsigned long mask)
-{
- MetaKeyBindingManager *keys = &display->key_binding_manager;
- xkb_keycode_t code = (xkb_keycode_t) keycode;
- MetaResolvedKeyCombo resolved_combo = { &code, 1 };
-
- resolved_combo.mask = mask_from_event_params (keys, mask);
- return get_keybinding_action (keys, &resolved_combo);
-}
-
-static void
-reload_keybindings (MetaDisplay *display)
-{
- MetaKeyBindingManager *keys = &display->key_binding_manager;
-
- ungrab_key_bindings (display);
-
- /* Deciphering the modmap depends on the loaded keysyms to find out
- * what modifiers is Super and so forth, so we need to reload it
- * even when only the keymap changes */
- reload_modmap (keys);
-
- reload_combos (keys);
-
- grab_key_bindings (display);
-}
-
-static GArray *
-calc_grab_modifiers (MetaKeyBindingManager *keys,
- unsigned int modmask)
-{
- unsigned int ignored_mask;
- XIGrabModifiers mods;
- GArray *mods_array = g_array_new (FALSE, TRUE, sizeof (XIGrabModifiers));
-
- /* The X server crashes if XIAnyModifier gets passed in with any
- other bits. It doesn't make sense to ask for a grab of
- XIAnyModifier plus other bits anyway so we avoid that. */
- if (modmask & XIAnyModifier)
- {
- mods = (XIGrabModifiers) { XIAnyModifier, 0 };
- g_array_append_val (mods_array, mods);
- return mods_array;
- }
-
- mods = (XIGrabModifiers) { modmask, 0 };
- g_array_append_val (mods_array, mods);
-
- for (ignored_mask = 1;
- ignored_mask <= keys->ignored_modifier_mask;
- ++ignored_mask)
- {
- if (ignored_mask & keys->ignored_modifier_mask)
- {
- mods = (XIGrabModifiers) { modmask | ignored_mask, 0 };
- g_array_append_val (mods_array, mods);
- }
- }
-
- return mods_array;
-}
-
-static void
-meta_change_button_grab (MetaKeyBindingManager *keys,
- Window xwindow,
- gboolean grab,
- gboolean sync,
- int button,
- int modmask)
-{
- if (meta_is_wayland_compositor ())
- return;
-
- MetaBackendX11 *backend = META_BACKEND_X11 (keys->backend);
- Display *xdisplay = meta_backend_x11_get_xdisplay (backend);
-
- unsigned char mask_bits[XIMaskLen (XI_LASTEVENT)] = { 0 };
- XIEventMask mask = { XIAllMasterDevices, sizeof (mask_bits), mask_bits };
- GArray *mods;
-
- XISetMask (mask.mask, XI_ButtonPress);
- XISetMask (mask.mask, XI_ButtonRelease);
- XISetMask (mask.mask, XI_Motion);
-
- mods = calc_grab_modifiers (keys, modmask);
-
- /* GrabModeSync means freeze until XAllowEvents */
- if (grab)
- XIGrabButton (xdisplay,
- META_VIRTUAL_CORE_POINTER_ID,
- button, xwindow, None,
- sync ? XIGrabModeSync : XIGrabModeAsync,
- XIGrabModeAsync, False,
- &mask, mods->len, (XIGrabModifiers *)mods->data);
- else
- XIUngrabButton (xdisplay,
- META_VIRTUAL_CORE_POINTER_ID,
- button, xwindow, mods->len, (XIGrabModifiers *)mods->data);
-
- g_array_free (mods, TRUE);
-}
-
-ClutterModifierType
-meta_display_get_compositor_modifiers (MetaDisplay *display)
-{
- MetaKeyBindingManager *keys = &display->key_binding_manager;
- return keys->window_grab_modifiers;
-}
-
-static void
-meta_change_buttons_grab (MetaKeyBindingManager *keys,
- Window xwindow,
- gboolean grab,
- gboolean sync,
- int modmask)
-{
-#define MAX_BUTTON 3
-
- int i;
- for (i = 1; i <= MAX_BUTTON; i++)
- meta_change_button_grab (keys, xwindow, grab, sync, i, modmask);
-}
-
-void
-meta_display_grab_window_buttons (MetaDisplay *display,
- Window xwindow)
-{
- MetaKeyBindingManager *keys = &display->key_binding_manager;
-
- /* Grab Alt + button1 for moving window.
- * Grab Alt + button2 for resizing window.
- * Grab Alt + button3 for popping up window menu.
- * Grab Alt + Shift + button1 for snap-moving window.
- */
- meta_verbose ("Grabbing window buttons for 0x%lx", xwindow);
-
- /* FIXME If we ignored errors here instead of spewing, we could
- * put one big error trap around the loop and avoid a bunch of
- * XSync()
- */
-
- if (keys->window_grab_modifiers != 0)
- {
- meta_change_buttons_grab (keys, xwindow, TRUE, FALSE,
- keys->window_grab_modifiers);
-
- /* In addition to grabbing Alt+Button1 for moving the window,
- * grab Alt+Shift+Button1 for snap-moving the window. See bug
- * 112478. Unfortunately, this doesn't work with
- * Shift+Alt+Button1 for some reason; so at least part of the
- * order still matters, which sucks (please FIXME).
- */
- meta_change_button_grab (keys, xwindow,
- TRUE,
- FALSE,
- 1, keys->window_grab_modifiers | ShiftMask);
- }
-}
-
-void
-meta_display_ungrab_window_buttons (MetaDisplay *display,
- Window xwindow)
-{
- MetaKeyBindingManager *keys = &display->key_binding_manager;
-
- if (keys->window_grab_modifiers == 0)
- return;
-
- meta_change_buttons_grab (keys, xwindow, FALSE, FALSE,
- keys->window_grab_modifiers);
-}
-
-static void
-update_window_grab_modifiers (MetaDisplay *display)
-{
- MetaKeyBindingManager *keys = &display->key_binding_manager;
- MetaVirtualModifier virtual_mods;
- unsigned int mods;
-
- virtual_mods = meta_prefs_get_mouse_button_mods ();
- devirtualize_modifiers (keys, virtual_mods, &mods);
-
- if (keys->window_grab_modifiers != mods)
- {
- keys->window_grab_modifiers = mods;
- g_object_notify (G_OBJECT (display), "compositor-modifiers");
- }
-}
-
-void
-meta_display_grab_focus_window_button (MetaDisplay *display,
- MetaWindow *window)
-{
- MetaKeyBindingManager *keys = &display->key_binding_manager;
-
- /* Grab button 1 for activating unfocused windows */
- meta_verbose ("Grabbing unfocused window buttons for %s", window->desc);
-
- if (window->have_focus_click_grab)
- {
- meta_verbose (" (well, not grabbing since we already have the grab)");
- return;
- }
-
- /* FIXME If we ignored errors here instead of spewing, we could
- * put one big error trap around the loop and avoid a bunch of
- * XSync()
- */
-
- meta_change_buttons_grab (keys, window->xwindow, TRUE, TRUE, XIAnyModifier);
- window->have_focus_click_grab = TRUE;
-}
-
-void
-meta_display_ungrab_focus_window_button (MetaDisplay *display,
- MetaWindow *window)
-{
- MetaKeyBindingManager *keys = &display->key_binding_manager;
-
- meta_verbose ("Ungrabbing unfocused window buttons for %s", window->desc);
-
- if (!window->have_focus_click_grab)
- return;
-
- meta_change_buttons_grab (keys, window->xwindow, FALSE, FALSE, XIAnyModifier);
- window->have_focus_click_grab = FALSE;
-}
-
-static void
-prefs_changed_callback (MetaPreference pref,
- void *data)
-{
- MetaDisplay *display = data;
- MetaKeyBindingManager *keys = &display->key_binding_manager;
-
- switch (pref)
- {
- case META_PREF_LOCATE_POINTER:
- maybe_update_locate_pointer_keygrab (display,
- meta_prefs_is_locate_pointer_enabled());
- break;
- case META_PREF_KEYBINDINGS:
- ungrab_key_bindings (display);
- rebuild_key_binding_table (keys);
- rebuild_special_bindings (keys);
- reload_combos (keys);
- grab_key_bindings (display);
- break;
- case META_PREF_MOUSE_BUTTON_MODS:
- {
- GSList *windows, *l;
- windows = meta_display_list_windows (display, META_LIST_DEFAULT);
-
- for (l = windows; l; l = l->next)
- {
- MetaWindow *w = l->data;
- meta_display_ungrab_window_buttons (display, w->xwindow);
- }
-
- update_window_grab_modifiers (display);
-
- for (l = windows; l; l = l->next)
- {
- MetaWindow *w = l->data;
- if (w->type != META_WINDOW_DOCK)
- meta_display_grab_window_buttons (display, w->xwindow);
- }
-
- g_slist_free (windows);
- }
- default:
- break;
- }
-}
-
-
-void
-meta_display_shutdown_keys (MetaDisplay *display)
-{
- MetaKeyBindingManager *keys = &display->key_binding_manager;
-
- meta_prefs_remove_listener (prefs_changed_callback, display);
-
- g_hash_table_destroy (keys->key_bindings_index);
- g_hash_table_destroy (keys->key_bindings);
-
- clear_active_keyboard_layouts (keys);
-}
-
-/* Grab/ungrab, ignoring all annoying modifiers like NumLock etc. */
-static void
-meta_change_keygrab (MetaKeyBindingManager *keys,
- Window xwindow,
- gboolean grab,
- MetaResolvedKeyCombo *resolved_combo)
-{
- unsigned char mask_bits[XIMaskLen (XI_LASTEVENT)] = { 0 };
- XIEventMask mask = { XIAllMasterDevices, sizeof (mask_bits), mask_bits };
-
- XISetMask (mask.mask, XI_KeyPress);
- XISetMask (mask.mask, XI_KeyRelease);
-
- if (meta_is_wayland_compositor ())
- return;
-
- MetaBackendX11 *backend = META_BACKEND_X11 (meta_get_backend ());
- Display *xdisplay = meta_backend_x11_get_xdisplay (backend);
- GArray *mods;
- int i;
-
- /* Grab keycode/modmask, together with
- * all combinations of ignored modifiers.
- * X provides no better way to do this.
- */
-
- mods = calc_grab_modifiers (keys, resolved_combo->mask);
-
- for (i = 0; i < resolved_combo->len; i++)
- {
- xkb_keycode_t keycode = resolved_combo->keycodes[i];
-
- meta_topic (META_DEBUG_KEYBINDINGS,
- "%s keybinding keycode %d mask 0x%x on 0x%lx",
- grab ? "Grabbing" : "Ungrabbing",
- keycode, resolved_combo->mask, xwindow);
-
- if (grab)
- XIGrabKeycode (xdisplay,
- META_VIRTUAL_CORE_KEYBOARD_ID,
- keycode, xwindow,
- XIGrabModeSync, XIGrabModeAsync,
- False, &mask, mods->len, (XIGrabModifiers *)mods->data);
- else
- XIUngrabKeycode (xdisplay,
- META_VIRTUAL_CORE_KEYBOARD_ID,
- keycode, xwindow,
- mods->len, (XIGrabModifiers *)mods->data);
- }
-
- g_array_free (mods, TRUE);
-}
-
-typedef struct
-{
- MetaKeyBindingManager *keys;
- Window xwindow;
- gboolean only_per_window;
- gboolean grab;
-} ChangeKeygrabData;
-
-static void
-change_keygrab_foreach (gpointer key,
- gpointer value,
- gpointer user_data)
-{
- ChangeKeygrabData *data = user_data;
- MetaKeyBinding *binding = value;
- gboolean binding_is_per_window = (binding->flags & META_KEY_BINDING_PER_WINDOW) != 0;
-
- if (data->only_per_window != binding_is_per_window)
- return;
-
- /* Ignore the key bindings marked as META_KEY_BINDING_NO_AUTO_GRAB,
- * those are handled separately
- */
- if (binding->flags & META_KEY_BINDING_NO_AUTO_GRAB)
- return;
-
- if (binding->resolved_combo.len == 0)
- return;
-
- meta_change_keygrab (data->keys, data->xwindow, data->grab, &binding->resolved_combo);
-}
-
-static void
-change_binding_keygrabs (MetaKeyBindingManager *keys,
- Window xwindow,
- gboolean only_per_window,
- gboolean grab)
-{
- ChangeKeygrabData data;
-
- data.keys = keys;
- data.xwindow = xwindow;
- data.only_per_window = only_per_window;
- data.grab = grab;
-
- g_hash_table_foreach (keys->key_bindings, change_keygrab_foreach, &data);
-}
-
-static void
-maybe_update_locate_pointer_keygrab (MetaDisplay *display,
- gboolean grab)
-{
- MetaKeyBindingManager *keys = &display->key_binding_manager;
-
- if (!display->x11_display)
- return;
-
- if (keys->locate_pointer_resolved_key_combo.len != 0)
- meta_change_keygrab (keys, display->x11_display->xroot,
- (!!grab & !!meta_prefs_is_locate_pointer_enabled()),
- &keys->locate_pointer_resolved_key_combo);
-}
-
-static void
-meta_x11_display_change_keygrabs (MetaX11Display *x11_display,
- gboolean grab)
-{
- MetaKeyBindingManager *keys = &x11_display->display->key_binding_manager;
- int i;
-
- if (keys->overlay_resolved_key_combo.len != 0)
- meta_change_keygrab (keys, x11_display->xroot,
- grab, &keys->overlay_resolved_key_combo);
-
- maybe_update_locate_pointer_keygrab (x11_display->display, grab);
-
- for (i = 0; i < keys->n_iso_next_group_combos; i++)
- meta_change_keygrab (keys, x11_display->xroot,
- grab, &keys->iso_next_group_combo[i]);
-
- change_binding_keygrabs (keys, x11_display->xroot,
- FALSE, grab);
-}
-
-void
-meta_x11_display_grab_keys (MetaX11Display *x11_display)
-{
- if (x11_display->keys_grabbed)
- return;
-
- meta_x11_display_change_keygrabs (x11_display, TRUE);
-
- x11_display->keys_grabbed = TRUE;
-}
-
-void
-meta_x11_display_ungrab_keys (MetaX11Display *x11_display)
-{
- if (!x11_display->keys_grabbed)
- return;
-
- meta_x11_display_change_keygrabs (x11_display, FALSE);
-
- x11_display->keys_grabbed = FALSE;
-}
-
-static void
-change_window_keygrabs (MetaKeyBindingManager *keys,
- Window xwindow,
- gboolean grab)
-{
- change_binding_keygrabs (keys, xwindow, TRUE, grab);
-}
-
-void
-meta_window_grab_keys (MetaWindow *window)
-{
- MetaDisplay *display = window->display;
- MetaKeyBindingManager *keys = &display->key_binding_manager;
-
- if (meta_is_wayland_compositor ())
- return;
- if (window->all_keys_grabbed)
- return;
-
- if (window->type == META_WINDOW_DOCK
- || window->override_redirect)
- {
- if (window->keys_grabbed)
- change_window_keygrabs (keys, window->xwindow, FALSE);
- window->keys_grabbed = FALSE;
- return;
- }
-
- if (window->keys_grabbed)
- {
- if (window->frame && !window->grab_on_frame)
- change_window_keygrabs (keys, window->xwindow, FALSE);
- else if (window->frame == NULL &&
- window->grab_on_frame)
- ; /* continue to regrab on client window */
- else
- return; /* already all good */
- }
-
- change_window_keygrabs (keys,
- meta_window_x11_get_toplevel_xwindow (window),
- TRUE);
-
- window->keys_grabbed = TRUE;
- window->grab_on_frame = window->frame != NULL;
-}
-
-void
-meta_window_ungrab_keys (MetaWindow *window)
-{
- if (!meta_is_wayland_compositor () && window->keys_grabbed)
- {
- MetaDisplay *display = window->display;
- MetaKeyBindingManager *keys = &display->key_binding_manager;
-
- if (window->grab_on_frame &&
- window->frame != NULL)
- change_window_keygrabs (keys, window->frame->xwindow, FALSE);
- else if (!window->grab_on_frame)
- change_window_keygrabs (keys, window->xwindow, FALSE);
-
- window->keys_grabbed = FALSE;
- }
-}
-
-static void
-handle_external_grab (MetaDisplay *display,
- MetaWindow *window,
- ClutterKeyEvent *event,
- MetaKeyBinding *binding,
- gpointer user_data)
-{
- MetaKeyBindingManager *keys = &display->key_binding_manager;
- guint action = get_keybinding_action (keys, &binding->resolved_combo);
- meta_display_accelerator_activate (display, action, event);
-}
-
-
-guint
-meta_display_grab_accelerator (MetaDisplay *display,
- const char *accelerator,
- MetaKeyBindingFlags flags)
-{
- MetaKeyBindingManager *keys = &display->key_binding_manager;
- MetaKeyBinding *binding;
- MetaKeyGrab *grab;
- MetaKeyCombo combo = { 0 };
- MetaResolvedKeyCombo resolved_combo = { NULL, 0 };
-
- if (!meta_parse_accelerator (accelerator, &combo))
- {
- meta_topic (META_DEBUG_KEYBINDINGS,
- "Failed to parse accelerator");
- meta_warning ("\"%s\" is not a valid accelerator", accelerator);
-
- return META_KEYBINDING_ACTION_NONE;
- }
-
- resolve_key_combo (keys, &combo, &resolved_combo);
-
- if (resolved_combo.len == 0)
- return META_KEYBINDING_ACTION_NONE;
-
- if (get_keybinding (keys, &resolved_combo))
- {
- resolved_key_combo_reset (&resolved_combo);
- return META_KEYBINDING_ACTION_NONE;
- }
-
- if (!meta_is_wayland_compositor ())
- {
- meta_change_keygrab (keys, display->x11_display->xroot,
- TRUE, &resolved_combo);
- }
-
- grab = g_new0 (MetaKeyGrab, 1);
- grab->action = next_dynamic_keybinding_action ();
- grab->name = meta_external_binding_name_for_action (grab->action);
- grab->combo = combo;
- grab->flags = flags;
-
- g_hash_table_insert (external_grabs, grab->name, grab);
-
- binding = g_new0 (MetaKeyBinding, 1);
- binding->name = grab->name;
- binding->handler = HANDLER ("external-grab");
- binding->combo = combo;
- binding->resolved_combo = resolved_combo;
- binding->flags = flags;
-
- g_hash_table_add (keys->key_bindings, binding);
- index_binding (keys, binding);
-
- return grab->action;
-}
-
-gboolean
-meta_display_ungrab_accelerator (MetaDisplay *display,
- guint action)
-{
- MetaKeyBindingManager *keys = &display->key_binding_manager;
- MetaKeyBinding *binding;
- MetaKeyGrab *grab;
- g_autofree char *key = NULL;
- MetaResolvedKeyCombo resolved_combo = { NULL, 0 };
-
- g_return_val_if_fail (action != META_KEYBINDING_ACTION_NONE, FALSE);
-
- key = meta_external_binding_name_for_action (action);
- grab = g_hash_table_lookup (external_grabs, key);
- if (!grab)
- return FALSE;
-
- resolve_key_combo (keys, &grab->combo, &resolved_combo);
- binding = get_keybinding (keys, &resolved_combo);
- if (binding)
- {
- int i;
-
- if (!meta_is_wayland_compositor ())
- {
- meta_change_keygrab (keys, display->x11_display->xroot,
- FALSE, &binding->resolved_combo);
- }
-
- for (i = 0; i < binding->resolved_combo.len; i++)
- {
- guint32 index_key = key_combo_key (&binding->resolved_combo, i);
- g_hash_table_remove (keys->key_bindings_index, GINT_TO_POINTER (index_key));
- }
-
- g_hash_table_remove (keys->key_bindings, binding);
- }
-
- g_hash_table_remove (external_grabs, key);
- resolved_key_combo_reset (&resolved_combo);
-
- return TRUE;
-}
-
-static gboolean
-grab_keyboard (Window xwindow,
- guint32 timestamp,
- int grab_mode)
-{
- int grab_status;
-
- unsigned char mask_bits[XIMaskLen (XI_LASTEVENT)] = { 0 };
- XIEventMask mask = { XIAllMasterDevices, sizeof (mask_bits), mask_bits };
-
- XISetMask (mask.mask, XI_KeyPress);
- XISetMask (mask.mask, XI_KeyRelease);
-
- if (meta_is_wayland_compositor ())
- return TRUE;
-
- /* Grab the keyboard, so we get key releases and all key
- * presses
- */
-
- MetaBackendX11 *backend = META_BACKEND_X11 (meta_get_backend ());
- Display *xdisplay = meta_backend_x11_get_xdisplay (backend);
-
- /* Strictly, we only need to set grab_mode on the keyboard device
- * while the pointer should always be XIGrabModeAsync. Unfortunately
- * there is a bug in the X server, only fixed (link below) in 1.15,
- * which swaps these arguments for keyboard devices. As such, we set
- * both the device and the paired device mode which works around
- * that bug and also works on fixed X servers.
- *
- * http://cgit.freedesktop.org/xorg/xserver/commit/?id=9003399708936481083424b4ff8f18a16b88b7b3
- */
- grab_status = XIGrabDevice (xdisplay,
- META_VIRTUAL_CORE_KEYBOARD_ID,
- xwindow,
- timestamp,
- None,
- grab_mode, grab_mode,
- False, /* owner_events */
- &mask);
-
- return (grab_status == Success);
-}
-
-static void
-ungrab_keyboard (guint32 timestamp)
-{
- if (meta_is_wayland_compositor ())
- return;
-
- MetaBackendX11 *backend = META_BACKEND_X11 (meta_get_backend ());
- Display *xdisplay = meta_backend_x11_get_xdisplay (backend);
-
- XIUngrabDevice (xdisplay, META_VIRTUAL_CORE_KEYBOARD_ID, timestamp);
-}
-
-gboolean
-meta_window_grab_all_keys (MetaWindow *window,
- guint32 timestamp)
-{
- Window grabwindow;
- gboolean retval = TRUE;
-
- if (window->all_keys_grabbed)
- return FALSE;
-
- if (window->keys_grabbed)
- meta_window_ungrab_keys (window);
-
- /* Make sure the window is focused, otherwise the grab
- * won't do a lot of good.
- */
- meta_topic (META_DEBUG_FOCUS,
- "Focusing %s because we're grabbing all its keys",
- window->desc);
- meta_window_focus (window, timestamp);
-
- if (!meta_is_wayland_compositor ())
- {
- grabwindow = meta_window_x11_get_toplevel_xwindow (window);
-
- meta_topic (META_DEBUG_KEYBINDINGS,
- "Grabbing all keys on window %s", window->desc);
- retval = grab_keyboard (grabwindow, timestamp, XIGrabModeAsync);
- }
- if (retval)
- {
- window->keys_grabbed = FALSE;
- window->all_keys_grabbed = TRUE;
- window->grab_on_frame = window->frame != NULL;
- }
-
- return retval;
-}
-
-void
-meta_window_ungrab_all_keys (MetaWindow *window,
- guint32 timestamp)
-{
- if (window->all_keys_grabbed)
- {
- if (!meta_is_wayland_compositor())
- ungrab_keyboard (timestamp);
-
- window->grab_on_frame = FALSE;
- window->all_keys_grabbed = FALSE;
- window->keys_grabbed = FALSE;
-
- /* Re-establish our standard bindings */
- meta_window_grab_keys (window);
- }
-}
-
-void
-meta_display_freeze_keyboard (MetaDisplay *display, guint32 timestamp)
-{
- MetaBackend *backend = meta_get_backend ();
-
- if (!META_IS_BACKEND_X11 (backend))
- return;
-
- Window window = meta_backend_x11_get_xwindow (META_BACKEND_X11 (backend));
- grab_keyboard (window, timestamp, XIGrabModeSync);
-}
-
-void
-meta_display_ungrab_keyboard (MetaDisplay *display, guint32 timestamp)
-{
- ungrab_keyboard (timestamp);
-}
-
-void
-meta_display_unfreeze_keyboard (MetaDisplay *display, guint32 timestamp)
-{
- MetaBackend *backend = meta_get_backend ();
-
- if (!META_IS_BACKEND_X11 (backend))
- return;
-
- Display *xdisplay = meta_backend_x11_get_xdisplay (META_BACKEND_X11 (backend));
-
- XIAllowEvents (xdisplay, META_VIRTUAL_CORE_KEYBOARD_ID,
- XIAsyncDevice, timestamp);
- /* We shouldn't need to unfreeze the pointer device here, however we
- * have to, due to the workaround we do in grab_keyboard().
- */
- XIAllowEvents (xdisplay, META_VIRTUAL_CORE_POINTER_ID,
- XIAsyncDevice, timestamp);
-}
-
-static gboolean
-is_modifier (xkb_keysym_t keysym)
-{
- switch (keysym)
- {
- case XKB_KEY_Shift_L:
- case XKB_KEY_Shift_R:
- case XKB_KEY_Control_L:
- case XKB_KEY_Control_R:
- case XKB_KEY_Caps_Lock:
- case XKB_KEY_Shift_Lock:
- case XKB_KEY_Meta_L:
- case XKB_KEY_Meta_R:
- case XKB_KEY_Alt_L:
- case XKB_KEY_Alt_R:
- case XKB_KEY_Super_L:
- case XKB_KEY_Super_R:
- case XKB_KEY_Hyper_L:
- case XKB_KEY_Hyper_R:
- return TRUE;
- default:
- return FALSE;
- }
-}
-
-static void
-invoke_handler (MetaDisplay *display,
- MetaKeyHandler *handler,
- MetaWindow *window,
- ClutterKeyEvent *event,
- MetaKeyBinding *binding)
-{
- if (handler->func)
- (* handler->func) (display,
- handler->flags & META_KEY_BINDING_PER_WINDOW ?
- window : NULL,
- event,
- binding,
- handler->user_data);
- else
- (* handler->default_func) (display,
- handler->flags & META_KEY_BINDING_PER_WINDOW ?
- window: NULL,
- event,
- binding,
- NULL);
-}
-
-static gboolean
-meta_key_binding_has_handler_func (MetaKeyBinding *binding)
-{
- return (!!binding->handler->func || !!binding->handler->default_func);
-}
-
-static gboolean
-process_event (MetaDisplay *display,
- MetaWindow *window,
- ClutterKeyEvent *event)
-{
- MetaKeyBindingManager *keys = &display->key_binding_manager;
- xkb_keycode_t keycode = (xkb_keycode_t) event->hardware_keycode;
- MetaResolvedKeyCombo resolved_combo = { &keycode, 1 };
- MetaKeyBinding *binding;
-
- /* we used to have release-based bindings but no longer. */
- if (event->type == CLUTTER_KEY_RELEASE)
- return FALSE;
-
- resolved_combo.mask = mask_from_event_params (keys, event->modifier_state);
-
- binding = get_keybinding (keys, &resolved_combo);
-
- if (!binding ||
- (!window && binding->flags & META_KEY_BINDING_PER_WINDOW))
- goto not_found;
-
- if (binding->handler == NULL)
- meta_bug ("Binding %s has no handler", binding->name);
-
- if (!meta_key_binding_has_handler_func (binding))
- goto not_found;
-
- if (display->focus_window &&
- !(binding->handler->flags & META_KEY_BINDING_NON_MASKABLE))
- {
- ClutterInputDevice *source;
-
- source = clutter_event_get_source_device ((ClutterEvent *) event);
- if (meta_window_shortcuts_inhibited (display->focus_window, source))
- goto not_found;
- }
-
- /* If the compositor filtered out the keybindings, that
- * means they don't want the binding to trigger, so we do
- * the same thing as if the binding didn't exist. */
- if (meta_compositor_filter_keybinding (display->compositor, binding))
- goto not_found;
-
- if (event->flags & CLUTTER_EVENT_FLAG_REPEATED &&
- binding->flags & META_KEY_BINDING_IGNORE_AUTOREPEAT)
- {
- meta_topic (META_DEBUG_KEYBINDINGS,
- "Ignore autorepeat for handler %s",
- binding->name);
- return TRUE;
- }
-
- meta_topic (META_DEBUG_KEYBINDINGS,
- "Running handler for %s",
- binding->name);
-
- /* Global keybindings count as a let-the-terminal-lose-focus
- * due to new window mapping until the user starts
- * interacting with the terminal again.
- */
- display->allow_terminal_deactivation = TRUE;
-
- invoke_handler (display, binding->handler, window, event, binding);
-
- return TRUE;
-
- not_found:
- meta_topic (META_DEBUG_KEYBINDINGS,
- "No handler found for this event in this binding table");
- return FALSE;
-}
-
-static gboolean
-process_special_modifier_key (MetaDisplay *display,
- ClutterKeyEvent *event,
- MetaWindow *window,
- gboolean *modifier_press_only,
- MetaResolvedKeyCombo *resolved_key_combo,
- GFunc trigger_callback)
-{
- MetaKeyBindingManager *keys = &display->key_binding_manager;
- MetaBackend *backend = keys->backend;
- Display *xdisplay;
-
- if (META_IS_BACKEND_X11 (backend))
- xdisplay = meta_backend_x11_get_xdisplay (META_BACKEND_X11 (backend));
- else
- xdisplay = NULL;
-
- if (*modifier_press_only)
- {
- if (! resolved_key_combo_has_keycode (resolved_key_combo,
- event->hardware_keycode))
- {
- *modifier_press_only = FALSE;
-
- /* If this is a wayland session, we can avoid the shenanigans
- * about passive grabs below, and let the event continue to
- * be processed through the regular paths.
- */
- if (!xdisplay)
- return FALSE;
-
- /* OK, the user hit modifier+key rather than pressing and
- * releasing the modifier key alone. We want to handle the key
- * sequence "normally". Unfortunately, using
- * XAllowEvents(..., ReplayKeyboard, ...) doesn't quite
- * work, since global keybindings won't be activated ("this
- * time, however, the function ignores any passive grabs at
- * above (toward the root of) the grab_window of the grab
- * just released.") So, we first explicitly check for one of
- * our global keybindings, and if not found, we then replay
- * the event. Other clients with global grabs will be out of
- * luck.
- */
- if (process_event (display, window, event))
- {
- /* As normally, after we've handled a global key
- * binding, we unfreeze the keyboard but keep the grab
- * (this is important for something like cycling
- * windows */
-
- if (xdisplay)
- XIAllowEvents (xdisplay,
- meta_input_device_x11_get_device_id (event->device),
- XIAsyncDevice, event->time);
- }
- else
- {
- /* Replay the event so it gets delivered to our
- * per-window key bindings or to the application */
- if (xdisplay)
- XIAllowEvents (xdisplay,
- meta_input_device_x11_get_device_id (event->device),
- XIReplayDevice, event->time);
- }
- }
- else if (event->type == CLUTTER_KEY_RELEASE)
- {
- MetaKeyBinding *binding;
-
- *modifier_press_only = FALSE;
-
- /* We want to unfreeze events, but keep the grab so that if the user
- * starts typing into the overlay we get all the keys */
- if (xdisplay)
- XIAllowEvents (xdisplay,
- meta_input_device_x11_get_device_id (event->device),
- XIAsyncDevice, event->time);
-
- binding = get_keybinding (keys, resolved_key_combo);
- if (binding &&
- meta_compositor_filter_keybinding (display->compositor, binding))
- return TRUE;
- trigger_callback (display, NULL);
- }
- else
- {
- /* In some rare race condition, mutter might not receive the Super_L
- * KeyRelease event because:
- * - the compositor might end the modal mode and call XIUngrabDevice
- * while the key is still down
- * - passive grabs are only activated on KeyPress and not KeyRelease.
- *
- * In this case, modifier_press_only might be wrong.
- * Mutter still ought to acknowledge events, otherwise the X server
- * will not send the next events.
- *
- * https://bugzilla.gnome.org/show_bug.cgi?id=666101
- */
- if (xdisplay)
- XIAllowEvents (xdisplay,
- meta_input_device_x11_get_device_id (event->device),
- XIAsyncDevice, event->time);
- }
-
- return TRUE;
- }
- else if (event->type == CLUTTER_KEY_PRESS &&
- ((event->modifier_state & ~(IGNORED_MODIFIERS)) & CLUTTER_MODIFIER_MASK) == 0 &&
- resolved_key_combo_has_keycode (resolved_key_combo,
- event->hardware_keycode))
- {
- *modifier_press_only = TRUE;
- /* We keep the keyboard frozen - this allows us to use ReplayKeyboard
- * on the next event if it's not the release of the modifier key */
- if (xdisplay)
- XIAllowEvents (xdisplay,
- meta_input_device_x11_get_device_id (event->device),
- XISyncDevice, event->time);
-
- return TRUE;
- }
- else
- return FALSE;
-}
-
-
-static gboolean
-process_overlay_key (MetaDisplay *display,
- ClutterKeyEvent *event,
- MetaWindow *window)
-{
- MetaKeyBindingManager *keys = &display->key_binding_manager;
-
- if (display->focus_window && !keys->overlay_key_only_pressed)
- {
- ClutterInputDevice *source;
-
- source = clutter_event_get_source_device ((ClutterEvent *) event);
- if (meta_window_shortcuts_inhibited (display->focus_window, source))
- return FALSE;
- }
-
- return process_special_modifier_key (display,
- event,
- window,
- &keys->overlay_key_only_pressed,
- &keys->overlay_resolved_key_combo,
- (GFunc) meta_display_overlay_key_activate);
-}
-
-static void
-handle_locate_pointer (MetaDisplay *display)
-{
- meta_compositor_locate_pointer (display->compositor);
-}
-
-static gboolean
-process_locate_pointer_key (MetaDisplay *display,
- ClutterKeyEvent *event,
- MetaWindow *window)
-{
- MetaKeyBindingManager *keys = &display->key_binding_manager;
-
- return process_special_modifier_key (display,
- event,
- window,
- &keys->locate_pointer_key_only_pressed,
- &keys->locate_pointer_resolved_key_combo,
- (GFunc) handle_locate_pointer);
-}
-
-static gboolean
-process_iso_next_group (MetaDisplay *display,
- ClutterKeyEvent *event)
-{
- MetaKeyBindingManager *keys = &display->key_binding_manager;
- gboolean activate;
- xkb_keycode_t keycode = (xkb_keycode_t) event->hardware_keycode;
- xkb_mod_mask_t mask;
- int i, j;
-
- if (event->type == CLUTTER_KEY_RELEASE)
- return FALSE;
-
- activate = FALSE;
- mask = mask_from_event_params (keys, event->modifier_state);
-
- for (i = 0; i < keys->n_iso_next_group_combos; ++i)
- {
- for (j = 0; j < keys->iso_next_group_combo[i].len; ++j)
- {
- if (keycode == keys->iso_next_group_combo[i].keycodes[j] &&
- mask == keys->iso_next_group_combo[i].mask)
- {
- /* If the signal handler returns TRUE the keyboard will
- remain frozen. It's the signal handler's responsibility
- to unfreeze it. */
- if (!meta_display_modifiers_accelerator_activate (display))
- meta_display_unfreeze_keyboard (display, event->time);
- activate = TRUE;
- break;
- }
- }
- }
-
- return activate;
-}
-
-static gboolean
-process_key_event (MetaDisplay *display,
- MetaWindow *window,
- ClutterKeyEvent *event)
-{
- gboolean keep_grab;
- gboolean all_keys_grabbed;
-
- all_keys_grabbed = window ? window->all_keys_grabbed : FALSE;
- if (!all_keys_grabbed)
- {
- if (process_overlay_key (display, event, window))
- return TRUE;
-
- if (process_locate_pointer_key (display, event, window))
- return FALSE; /* Continue with the event even if handled */
-
- if (process_iso_next_group (display, event))
- return TRUE;
- }
-
- {
- MetaBackend *backend = meta_get_backend ();
- if (META_IS_BACKEND_X11 (backend))
- {
- Display *xdisplay = meta_backend_x11_get_xdisplay (META_BACKEND_X11 (backend));
- XIAllowEvents (xdisplay,
- meta_input_device_x11_get_device_id (event->device),
- XIAsyncDevice, event->time);
- }
- }
-
- keep_grab = TRUE;
- if (all_keys_grabbed)
- {
- if (display->grab_op == META_GRAB_OP_NONE)
- return TRUE;
-
- /* If we get here we have a global grab, because
- * we're in some special keyboard mode such as window move
- * mode.
- */
- if (window == display->grab_window)
- {
- if (display->grab_op & META_GRAB_OP_WINDOW_FLAG_KEYBOARD)
- {
- if (display->grab_op == META_GRAB_OP_KEYBOARD_MOVING)
- {
- meta_topic (META_DEBUG_KEYBINDINGS,
- "Processing event for keyboard move");
- keep_grab = process_keyboard_move_grab (display, window, event);
- }
- else
- {
- meta_topic (META_DEBUG_KEYBINDINGS,
- "Processing event for keyboard resize");
- keep_grab = process_keyboard_resize_grab (display, window, event);
- }
- }
- else
- {
- meta_topic (META_DEBUG_KEYBINDINGS,
- "Processing event for mouse-only move/resize");
- keep_grab = process_mouse_move_resize_grab (display, window, event);
- }
- }
- if (!keep_grab)
- meta_display_end_grab_op (display, event->time);
-
- return TRUE;
- }
-
- /* Do the normal keybindings */
- return process_event (display, window, event);
-}
-
-/* Handle a key event. May be called recursively: some key events cause
- * grabs to be ended and then need to be processed again in their own
- * right. This cannot cause infinite recursion because we never call
- * ourselves when there wasn't a grab, and we always clear the grab
- * first; the invariant is enforced using an assertion. See #112560.
- *
- * The return value is whether we handled the key event.
- *
- * FIXME: We need to prove there are no race conditions here.
- * FIXME: Does it correctly handle alt-Tab being followed by another
- * grabbing keypress without letting go of alt?
- * FIXME: An iterative solution would probably be simpler to understand
- * (and help us solve the other fixmes).
- */
-gboolean
-meta_keybindings_process_event (MetaDisplay *display,
- MetaWindow *window,
- const ClutterEvent *event)
-{
- MetaKeyBindingManager *keys = &display->key_binding_manager;
-
- switch (event->type)
- {
- case CLUTTER_BUTTON_PRESS:
- case CLUTTER_BUTTON_RELEASE:
- case CLUTTER_TOUCH_BEGIN:
- case CLUTTER_TOUCH_END:
- case CLUTTER_SCROLL:
- keys->overlay_key_only_pressed = FALSE;
- keys->locate_pointer_key_only_pressed = FALSE;
- return FALSE;
-
- case CLUTTER_KEY_PRESS:
- case CLUTTER_KEY_RELEASE:
- return process_key_event (display, window, (ClutterKeyEvent *) event);
-
- default:
- return FALSE;
- }
-}
-
-static gboolean
-process_mouse_move_resize_grab (MetaDisplay *display,
- MetaWindow *window,
- ClutterKeyEvent *event)
-{
- /* don't care about releases, but eat them, don't end grab */
- if (event->type == CLUTTER_KEY_RELEASE)
- return TRUE;
-
- if (event->keyval == CLUTTER_KEY_Escape)
- {
- MetaTileMode tile_mode;
-
- /* Hide the tiling preview if necessary */
- if (display->preview_tile_mode != META_TILE_NONE)
- meta_display_hide_tile_preview (display);
-
- /* Restore the original tile mode */
- tile_mode = display->grab_tile_mode;
- window->tile_monitor_number = display->grab_tile_monitor_number;
-
- /* End move or resize and restore to original state. If the
- * window was a maximized window that had been "shaken loose" we
- * need to remaximize it. In normal cases, we need to do a
- * moveresize now to get the position back to the original.
- */
- if (window->shaken_loose || tile_mode == META_TILE_MAXIMIZED)
- meta_window_maximize (window, META_MAXIMIZE_BOTH);
- else if (tile_mode != META_TILE_NONE)
- meta_window_restore_tile (window,
- tile_mode,
- display->grab_initial_window_pos.width,
- display->grab_initial_window_pos.height);
- else
- meta_window_move_resize_frame (display->grab_window,
- TRUE,
- display->grab_initial_window_pos.x,
- display->grab_initial_window_pos.y,
- display->grab_initial_window_pos.width,
- display->grab_initial_window_pos.height);
-
- /* End grab */
- return FALSE;
- }
-
- return TRUE;
-}
-
-static gboolean
-process_keyboard_move_grab (MetaDisplay *display,
- MetaWindow *window,
- ClutterKeyEvent *event)
-{
- MetaEdgeResistanceFlags flags;
- gboolean handled;
- MetaRectangle frame_rect;
- int x, y;
- int incr;
-
- handled = FALSE;
-
- /* don't care about releases, but eat them, don't end grab */
- if (event->type == CLUTTER_KEY_RELEASE)
- return TRUE;
-
- /* don't end grab on modifier key presses */
- if (is_modifier (event->keyval))
- return TRUE;
-
- meta_window_get_frame_rect (window, &frame_rect);
- x = frame_rect.x;
- y = frame_rect.y;
-
- flags = META_EDGE_RESISTANCE_KEYBOARD_OP | META_EDGE_RESISTANCE_WINDOWS;
-
- if ((event->modifier_state & CLUTTER_SHIFT_MASK) != 0)
- flags |= META_EDGE_RESISTANCE_SNAP;
-
-#define SMALL_INCREMENT 1
-#define NORMAL_INCREMENT 10
-
- if (flags & META_EDGE_RESISTANCE_SNAP)
- incr = 1;
- else if (event->modifier_state & CLUTTER_CONTROL_MASK)
- incr = SMALL_INCREMENT;
- else
- incr = NORMAL_INCREMENT;
-
- if (event->keyval == CLUTTER_KEY_Escape)
- {
- /* End move and restore to original state. If the window was a
- * maximized window that had been "shaken loose" we need to
- * remaximize it. In normal cases, we need to do a moveresize
- * now to get the position back to the original.
- */
- if (window->shaken_loose)
- meta_window_maximize (window, META_MAXIMIZE_BOTH);
- else
- meta_window_move_resize_frame (display->grab_window,
- TRUE,
- display->grab_initial_window_pos.x,
- display->grab_initial_window_pos.y,
- display->grab_initial_window_pos.width,
- display->grab_initial_window_pos.height);
- }
-
- /* When moving by increments, we still snap to edges if the move
- * to the edge is smaller than the increment. This is because
- * Shift + arrow to snap is sort of a hidden feature. This way
- * people using just arrows shouldn't get too frustrated.
- */
- switch (event->keyval)
- {
- case CLUTTER_KEY_KP_Home:
- case CLUTTER_KEY_KP_Prior:
- case CLUTTER_KEY_Up:
- case CLUTTER_KEY_KP_Up:
- y -= incr;
- handled = TRUE;
- break;
- case CLUTTER_KEY_KP_End:
- case CLUTTER_KEY_KP_Next:
- case CLUTTER_KEY_Down:
- case CLUTTER_KEY_KP_Down:
- y += incr;
- handled = TRUE;
- break;
- }
-
- switch (event->keyval)
- {
- case CLUTTER_KEY_KP_Home:
- case CLUTTER_KEY_KP_End:
- case CLUTTER_KEY_Left:
- case CLUTTER_KEY_KP_Left:
- x -= incr;
- handled = TRUE;
- break;
- case CLUTTER_KEY_KP_Prior:
- case CLUTTER_KEY_KP_Next:
- case CLUTTER_KEY_Right:
- case CLUTTER_KEY_KP_Right:
- x += incr;
- handled = TRUE;
- break;
- }
-
- if (handled)
- {
- meta_topic (META_DEBUG_KEYBINDINGS,
- "Computed new window location %d,%d due to keypress",
- x, y);
-
- meta_window_edge_resistance_for_move (window,
- &x,
- &y,
- NULL,
- flags);
-
- meta_window_move_frame (window, TRUE, x, y);
- meta_window_update_keyboard_move (window);
- }
-
- return handled;
-}
-
-static gboolean
-process_keyboard_resize_grab_op_change (MetaDisplay *display,
- MetaWindow *window,
- ClutterKeyEvent *event)
-{
- gboolean handled;
-
- handled = FALSE;
- switch (display->grab_op)
- {
- case META_GRAB_OP_KEYBOARD_RESIZING_UNKNOWN:
- switch (event->keyval)
- {
- case CLUTTER_KEY_Up:
- case CLUTTER_KEY_KP_Up:
- display->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_N;
- handled = TRUE;
- break;
- case CLUTTER_KEY_Down:
- case CLUTTER_KEY_KP_Down:
- display->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_S;
- handled = TRUE;
- break;
- case CLUTTER_KEY_Left:
- case CLUTTER_KEY_KP_Left:
- display->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_W;
- handled = TRUE;
- break;
- case CLUTTER_KEY_Right:
- case CLUTTER_KEY_KP_Right:
- display->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_E;
- handled = TRUE;
- break;
- }
- break;
-
- case META_GRAB_OP_KEYBOARD_RESIZING_S:
- switch (event->keyval)
- {
- case CLUTTER_KEY_Left:
- case CLUTTER_KEY_KP_Left:
- display->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_W;
- handled = TRUE;
- break;
- case CLUTTER_KEY_Right:
- case CLUTTER_KEY_KP_Right:
- display->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_E;
- handled = TRUE;
- break;
- }
- break;
-
- case META_GRAB_OP_KEYBOARD_RESIZING_N:
- switch (event->keyval)
- {
- case CLUTTER_KEY_Left:
- case CLUTTER_KEY_KP_Left:
- display->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_W;
- handled = TRUE;
- break;
- case CLUTTER_KEY_Right:
- case CLUTTER_KEY_KP_Right:
- display->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_E;
- handled = TRUE;
- break;
- }
- break;
-
- case META_GRAB_OP_KEYBOARD_RESIZING_W:
- switch (event->keyval)
- {
- case CLUTTER_KEY_Up:
- case CLUTTER_KEY_KP_Up:
- display->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_N;
- handled = TRUE;
- break;
- case CLUTTER_KEY_Down:
- case CLUTTER_KEY_KP_Down:
- display->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_S;
- handled = TRUE;
- break;
- }
- break;
-
- case META_GRAB_OP_KEYBOARD_RESIZING_E:
- switch (event->keyval)
- {
- case CLUTTER_KEY_Up:
- case CLUTTER_KEY_KP_Up:
- display->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_N;
- handled = TRUE;
- break;
- case CLUTTER_KEY_Down:
- case CLUTTER_KEY_KP_Down:
- display->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_S;
- handled = TRUE;
- break;
- }
- break;
-
- case META_GRAB_OP_KEYBOARD_RESIZING_SE:
- case META_GRAB_OP_KEYBOARD_RESIZING_NE:
- case META_GRAB_OP_KEYBOARD_RESIZING_SW:
- case META_GRAB_OP_KEYBOARD_RESIZING_NW:
- break;
-
- default:
- g_assert_not_reached ();
- break;
- }
-
- if (handled)
- {
- meta_window_update_keyboard_resize (window, TRUE);
- return TRUE;
- }
-
- return FALSE;
-}
-
-static gboolean
-process_keyboard_resize_grab (MetaDisplay *display,
- MetaWindow *window,
- ClutterKeyEvent *event)
-{
- MetaRectangle frame_rect;
- gboolean handled;
- int height_inc;
- int width_inc;
- int width, height;
- MetaEdgeResistanceFlags flags;
- MetaGravity gravity;
-
- handled = FALSE;
-
- /* don't care about releases, but eat them, don't end grab */
- if (event->type == CLUTTER_KEY_RELEASE)
- return TRUE;
-
- /* don't end grab on modifier key presses */
- if (is_modifier (event->keyval))
- return TRUE;
-
- if (event->keyval == CLUTTER_KEY_Escape)
- {
- /* End resize and restore to original state. */
- meta_window_move_resize_frame (display->grab_window,
- TRUE,
- display->grab_initial_window_pos.x,
- display->grab_initial_window_pos.y,
- display->grab_initial_window_pos.width,
- display->grab_initial_window_pos.height);
-
- return FALSE;
- }
-
- if (process_keyboard_resize_grab_op_change (display, window, event))
- return TRUE;
-
- width = window->rect.width;
- height = window->rect.height;
-
- meta_window_get_frame_rect (window, &frame_rect);
- width = frame_rect.width;
- height = frame_rect.height;
-
- gravity = meta_resize_gravity_from_grab_op (display->grab_op);
-
- flags = META_EDGE_RESISTANCE_KEYBOARD_OP;
-
- if ((event->modifier_state & CLUTTER_SHIFT_MASK) != 0)
- flags |= META_EDGE_RESISTANCE_SNAP;
-
-#define SMALL_INCREMENT 1
-#define NORMAL_INCREMENT 10
-
- if (flags & META_EDGE_RESISTANCE_SNAP)
- {
- height_inc = 1;
- width_inc = 1;
- }
- else if (event->modifier_state & CLUTTER_CONTROL_MASK)
- {
- width_inc = SMALL_INCREMENT;
- height_inc = SMALL_INCREMENT;
- }
- else
- {
- width_inc = NORMAL_INCREMENT;
- height_inc = NORMAL_INCREMENT;
- }
-
- /* If this is a resize increment window, make the amount we resize
- * the window by match that amount (well, unless snap resizing...)
- */
- if (window->size_hints.width_inc > 1)
- width_inc = window->size_hints.width_inc;
- if (window->size_hints.height_inc > 1)
- height_inc = window->size_hints.height_inc;
-
- switch (event->keyval)
- {
- case CLUTTER_KEY_Up:
- case CLUTTER_KEY_KP_Up:
- switch (gravity)
- {
- case META_GRAVITY_NORTH:
- case META_GRAVITY_NORTH_WEST:
- case META_GRAVITY_NORTH_EAST:
- /* Move bottom edge up */
- height -= height_inc;
- break;
-
- case META_GRAVITY_SOUTH:
- case META_GRAVITY_SOUTH_WEST:
- case META_GRAVITY_SOUTH_EAST:
- /* Move top edge up */
- height += height_inc;
- break;
-
- case META_GRAVITY_EAST:
- case META_GRAVITY_WEST:
- case META_GRAVITY_CENTER:
- case META_GRAVITY_NONE:
- case META_GRAVITY_STATIC:
- g_assert_not_reached ();
- break;
- }
-
- handled = TRUE;
- break;
-
- case CLUTTER_KEY_Down:
- case CLUTTER_KEY_KP_Down:
- switch (gravity)
- {
- case META_GRAVITY_NORTH:
- case META_GRAVITY_NORTH_WEST:
- case META_GRAVITY_NORTH_EAST:
- /* Move bottom edge down */
- height += height_inc;
- break;
-
- case META_GRAVITY_SOUTH:
- case META_GRAVITY_SOUTH_WEST:
- case META_GRAVITY_SOUTH_EAST:
- /* Move top edge down */
- height -= height_inc;
- break;
-
- case META_GRAVITY_EAST:
- case META_GRAVITY_WEST:
- case META_GRAVITY_CENTER:
- case META_GRAVITY_NONE:
- case META_GRAVITY_STATIC:
- g_assert_not_reached ();
- break;
- }
-
- handled = TRUE;
- break;
-
- case CLUTTER_KEY_Left:
- case CLUTTER_KEY_KP_Left:
- switch (gravity)
- {
- case META_GRAVITY_EAST:
- case META_GRAVITY_SOUTH_EAST:
- case META_GRAVITY_NORTH_EAST:
- /* Move left edge left */
- width += width_inc;
- break;
-
- case META_GRAVITY_WEST:
- case META_GRAVITY_SOUTH_WEST:
- case META_GRAVITY_NORTH_WEST:
- /* Move right edge left */
- width -= width_inc;
- break;
-
- case META_GRAVITY_NORTH:
- case META_GRAVITY_SOUTH:
- case META_GRAVITY_CENTER:
- case META_GRAVITY_NONE:
- case META_GRAVITY_STATIC:
- g_assert_not_reached ();
- break;
- }
-
- handled = TRUE;
- break;
-
- case CLUTTER_KEY_Right:
- case CLUTTER_KEY_KP_Right:
- switch (gravity)
- {
- case META_GRAVITY_EAST:
- case META_GRAVITY_SOUTH_EAST:
- case META_GRAVITY_NORTH_EAST:
- /* Move left edge right */
- width -= width_inc;
- break;
-
- case META_GRAVITY_WEST:
- case META_GRAVITY_SOUTH_WEST:
- case META_GRAVITY_NORTH_WEST:
- /* Move right edge right */
- width += width_inc;
- break;
-
- case META_GRAVITY_NORTH:
- case META_GRAVITY_SOUTH:
- case META_GRAVITY_CENTER:
- case META_GRAVITY_NONE:
- case META_GRAVITY_STATIC:
- g_assert_not_reached ();
- break;
- }
-
- handled = TRUE;
- break;
-
- default:
- break;
- }
-
- /* fixup hack (just paranoia, not sure it's required) */
- if (height < 1)
- height = 1;
- if (width < 1)
- width = 1;
-
- if (handled)
- {
- meta_topic (META_DEBUG_KEYBINDINGS,
- "Computed new window size due to keypress: "
- "%dx%d, gravity %s",
- width, height, meta_gravity_to_string (gravity));
-
- /* Do any edge resistance/snapping */
- meta_window_edge_resistance_for_resize (window,
- &width,
- &height,
- gravity,
- NULL,
- flags);
-
- meta_window_resize_frame_with_gravity (window,
- TRUE,
- width,
- height,
- gravity);
-
- meta_window_update_keyboard_resize (window, FALSE);
- }
-
- return handled;
-}
-
-static void
-handle_switch_to_last_workspace (MetaDisplay *display,
- MetaWindow *event_window,
- ClutterKeyEvent *event,
- MetaKeyBinding *binding,
- gpointer dummy)
-{
- MetaWorkspaceManager *workspace_manager = display->workspace_manager;
- gint target = meta_workspace_manager_get_n_workspaces (workspace_manager) - 1;
- MetaWorkspace *workspace = meta_workspace_manager_get_workspace_by_index (workspace_manager, target);
- meta_workspace_activate (workspace, event->time);
-}
-
-static void
-handle_switch_to_workspace (MetaDisplay *display,
- MetaWindow *event_window,
- ClutterKeyEvent *event,
- MetaKeyBinding *binding,
- gpointer dummy)
-{
- gint which = binding->handler->data;
- MetaWorkspaceManager *workspace_manager = display->workspace_manager;
- MetaWorkspace *workspace;
-
- if (which < 0)
- {
- /* Negative workspace numbers are directions with respect to the
- * current workspace.
- */
-
- workspace = meta_workspace_get_neighbor (workspace_manager->active_workspace,
- which);
- }
- else
- {
- workspace = meta_workspace_manager_get_workspace_by_index (workspace_manager, which);
- }
-
- if (workspace)
- {
- meta_workspace_activate (workspace, event->time);
- }
- else
- {
- /* We could offer to create it I suppose */
- }
-}
-
-
-static void
-handle_maximize_vertically (MetaDisplay *display,
- MetaWindow *window,
- ClutterKeyEvent *event,
- MetaKeyBinding *binding,
- gpointer dummy)
-{
- if (window->has_resize_func)
- {
- if (window->maximized_vertically)
- meta_window_unmaximize (window, META_MAXIMIZE_VERTICAL);
- else
- meta_window_maximize (window, META_MAXIMIZE_VERTICAL);
- }
-}
-
-static void
-handle_maximize_horizontally (MetaDisplay *display,
- MetaWindow *window,
- ClutterKeyEvent *event,
- MetaKeyBinding *binding,
- gpointer dummy)
-{
- if (window->has_resize_func)
- {
- if (window->maximized_horizontally)
- meta_window_unmaximize (window, META_MAXIMIZE_HORIZONTAL);
- else
- meta_window_maximize (window, META_MAXIMIZE_HORIZONTAL);
- }
-}
-
-static void
-handle_always_on_top (MetaDisplay *display,
- MetaWindow *window,
- ClutterKeyEvent *event,
- MetaKeyBinding *binding,
- gpointer dummy)
-{
- if (window->wm_state_above == FALSE)
- meta_window_make_above (window);
- else
- meta_window_unmake_above (window);
-}
-
-static void
-handle_move_to_corner_backend (MetaDisplay *display,
- MetaWindow *window,
- MetaGravity gravity)
-{
- MetaRectangle work_area;
- MetaRectangle frame_rect;
- int new_x, new_y;
-
- if (!window->monitor)
- return;
-
- meta_window_get_work_area_current_monitor (window, &work_area);
- meta_window_get_frame_rect (window, &frame_rect);
-
- switch (gravity)
- {
- case META_GRAVITY_NORTH_WEST:
- case META_GRAVITY_WEST:
- case META_GRAVITY_SOUTH_WEST:
- new_x = work_area.x;
- break;
- case META_GRAVITY_NORTH:
- case META_GRAVITY_SOUTH:
- new_x = frame_rect.x;
- break;
- case META_GRAVITY_NORTH_EAST:
- case META_GRAVITY_EAST:
- case META_GRAVITY_SOUTH_EAST:
- new_x = work_area.x + work_area.width - frame_rect.width;
- break;
- default:
- g_assert_not_reached ();
- }
-
- switch (gravity)
- {
- case META_GRAVITY_NORTH_WEST:
- case META_GRAVITY_NORTH:
- case META_GRAVITY_NORTH_EAST:
- new_y = work_area.y;
- break;
- case META_GRAVITY_WEST:
- case META_GRAVITY_EAST:
- new_y = frame_rect.y;
- break;
- case META_GRAVITY_SOUTH_WEST:
- case META_GRAVITY_SOUTH:
- case META_GRAVITY_SOUTH_EAST:
- new_y = work_area.y + work_area.height - frame_rect.height;
- break;
- default:
- g_assert_not_reached ();
- }
-
- meta_window_move_frame (window,
- TRUE,
- new_x,
- new_y);
-}
-
-static void
-handle_move_to_corner_nw (MetaDisplay *display,
- MetaWindow *window,
- ClutterKeyEvent *event,
- MetaKeyBinding *binding,
- gpointer dummy)
-{
- handle_move_to_corner_backend (display, window, META_GRAVITY_NORTH_WEST);
-}
-
-static void
-handle_move_to_corner_ne (MetaDisplay *display,
- MetaWindow *window,
- ClutterKeyEvent *event,
- MetaKeyBinding *binding,
- gpointer dummy)
-{
- handle_move_to_corner_backend (display, window, META_GRAVITY_NORTH_EAST);
-}
-
-static void
-handle_move_to_corner_sw (MetaDisplay *display,
- MetaWindow *window,
- ClutterKeyEvent *event,
- MetaKeyBinding *binding,
- gpointer dummy)
-{
- handle_move_to_corner_backend (display, window, META_GRAVITY_SOUTH_WEST);
-}
-
-static void
-handle_move_to_corner_se (MetaDisplay *display,
- MetaWindow *window,
- ClutterKeyEvent *event,
- MetaKeyBinding *binding,
- gpointer dummy)
-{
- handle_move_to_corner_backend (display, window, META_GRAVITY_SOUTH_EAST);
-}
-
-static void
-handle_move_to_side_n (MetaDisplay *display,
- MetaWindow *window,
- ClutterKeyEvent *event,
- MetaKeyBinding *binding,
- gpointer dummy)
-{
- handle_move_to_corner_backend (display, window, META_GRAVITY_NORTH);
-}
-
-static void
-handle_move_to_side_s (MetaDisplay *display,
- MetaWindow *window,
- ClutterKeyEvent *event,
- MetaKeyBinding *binding,
- gpointer dummy)
-{
- handle_move_to_corner_backend (display, window, META_GRAVITY_SOUTH);
-}
-
-static void
-handle_move_to_side_e (MetaDisplay *display,
- MetaWindow *window,
- ClutterKeyEvent *event,
- MetaKeyBinding *binding,
- gpointer dummy)
-{
- handle_move_to_corner_backend (display, window, META_GRAVITY_EAST);
-}
-
-static void
-handle_move_to_side_w (MetaDisplay *display,
- MetaWindow *window,
- ClutterKeyEvent *event,
- MetaKeyBinding *binding,
- gpointer dummy)
-{
- handle_move_to_corner_backend (display, window, META_GRAVITY_WEST);
-}
-
-static void
-handle_move_to_center (MetaDisplay *display,
- MetaWindow *window,
- ClutterKeyEvent *event,
- MetaKeyBinding *binding,
- gpointer dummy)
-{
- MetaRectangle work_area;
- MetaRectangle frame_rect;
-
- meta_window_get_work_area_current_monitor (window, &work_area);
- meta_window_get_frame_rect (window, &frame_rect);
-
- meta_window_move_frame (window,
- TRUE,
- work_area.x + (work_area.width - frame_rect.width ) / 2,
- work_area.y + (work_area.height - frame_rect.height) / 2);
-}
-
-static void
-handle_show_desktop (MetaDisplay *display,
- MetaWindow *window,
- ClutterKeyEvent *event,
- MetaKeyBinding *binding,
- gpointer dummy)
-{
- MetaWorkspaceManager *workspace_manager = display->workspace_manager;
-
- if (workspace_manager->active_workspace->showing_desktop)
- {
- meta_workspace_manager_unshow_desktop (workspace_manager);
- meta_workspace_focus_default_window (workspace_manager->active_workspace,
- NULL,
- event->time);
- }
- else
- meta_workspace_manager_show_desktop (workspace_manager, event->time);
-}
-
-static void
-handle_panel (MetaDisplay *display,
- MetaWindow *window,
- ClutterKeyEvent *event,
- MetaKeyBinding *binding,
- gpointer dummy)
-{
- MetaKeyBindingAction action = binding->handler->data;
- MetaX11Display *x11_display = display->x11_display;
- Atom action_atom;
- XClientMessageEvent ev;
-
- action_atom = None;
- switch (action)
- {
- /* FIXME: The numbers are wrong */
- case META_KEYBINDING_ACTION_PANEL_MAIN_MENU:
- action_atom = x11_display->atom__GNOME_PANEL_ACTION_MAIN_MENU;
- break;
- case META_KEYBINDING_ACTION_PANEL_RUN_DIALOG:
- action_atom = x11_display->atom__GNOME_PANEL_ACTION_RUN_DIALOG;
- break;
- default:
- return;
- }
-
- ev.type = ClientMessage;
- ev.window = x11_display->xroot;
- ev.message_type = x11_display->atom__GNOME_PANEL_ACTION;
- ev.format = 32;
- ev.data.l[0] = action_atom;
- ev.data.l[1] = event->time;
-
- meta_topic (META_DEBUG_KEYBINDINGS,
- "Sending panel message with timestamp %u, and turning mouse_mode "
- "off due to keybinding press", event->time);
- display->mouse_mode = FALSE;
-
- meta_x11_error_trap_push (x11_display);
-
- /* Release the grab for the panel before sending the event */
- XUngrabKeyboard (x11_display->xdisplay, event->time);
-
- XSendEvent (x11_display->xdisplay,
- x11_display->xroot,
- False,
- StructureNotifyMask,
- (XEvent*) &ev);
-
- meta_x11_error_trap_pop (x11_display);
-}
-
-static void
-handle_activate_window_menu (MetaDisplay *display,
- MetaWindow *event_window,
- ClutterKeyEvent *event,
- MetaKeyBinding *binding,
- gpointer dummy)
-{
- if (display->focus_window)
- {
- int x, y;
- MetaRectangle frame_rect;
- cairo_rectangle_int_t child_rect;
-
- meta_window_get_frame_rect (display->focus_window, &frame_rect);
- meta_window_get_client_area_rect (display->focus_window, &child_rect);
-
- x = frame_rect.x + child_rect.x;
- if (meta_get_locale_direction () == META_LOCALE_DIRECTION_RTL)
- x += child_rect.width;
-
- y = frame_rect.y + child_rect.y;
- meta_window_show_menu (display->focus_window, META_WINDOW_MENU_WM, x, y);
- }
-}
-
-static void
-do_choose_window (MetaDisplay *display,
- MetaWindow *event_window,
- ClutterKeyEvent *event,
- MetaKeyBinding *binding,
- gboolean backward)
-{
- MetaWorkspaceManager *workspace_manager = display->workspace_manager;
- MetaTabList type = binding->handler->data;
- MetaWindow *window;
-
- meta_topic (META_DEBUG_KEYBINDINGS,
- "Tab list = %u", type);
-
- window = meta_display_get_tab_next (display,
- type,
- workspace_manager->active_workspace,
- NULL,
- backward);
-
- if (window)
- meta_window_activate (window, event->time);
-}
-
-static void
-handle_switch (MetaDisplay *display,
- MetaWindow *event_window,
- ClutterKeyEvent *event,
- MetaKeyBinding *binding,
- gpointer dummy)
-{
- gboolean backwards = meta_key_binding_is_reversed (binding);
- do_choose_window (display, event_window, event, binding, backwards);
-}
-
-static void
-handle_cycle (MetaDisplay *display,
- MetaWindow *event_window,
- ClutterKeyEvent *event,
- MetaKeyBinding *binding,
- gpointer dummy)
-{
- gboolean backwards = meta_key_binding_is_reversed (binding);
- do_choose_window (display, event_window, event, binding, backwards);
-}
-
-static void
-handle_toggle_fullscreen (MetaDisplay *display,
- MetaWindow *window,
- ClutterKeyEvent *event,
- MetaKeyBinding *binding,
- gpointer dummy)
-{
- if (window->fullscreen)
- meta_window_unmake_fullscreen (window);
- else if (window->has_fullscreen_func)
- meta_window_make_fullscreen (window);
-}
-
-static void
-handle_toggle_above (MetaDisplay *display,
- MetaWindow *window,
- ClutterKeyEvent *event,
- MetaKeyBinding *binding,
- gpointer dummy)
-{
- if (window->wm_state_above)
- meta_window_unmake_above (window);
- else
- meta_window_make_above (window);
-}
-
-static void
-handle_toggle_tiled (MetaDisplay *display,
- MetaWindow *window,
- ClutterKeyEvent *event,
- MetaKeyBinding *binding,
- gpointer dummy)
-{
- MetaTileMode mode = binding->handler->data;
-
- if ((META_WINDOW_TILED_LEFT (window) && mode == META_TILE_LEFT) ||
- (META_WINDOW_TILED_RIGHT (window) && mode == META_TILE_RIGHT))
- {
- meta_window_untile (window);
- }
- else if (meta_window_can_tile_side_by_side (window))
- {
- window->tile_monitor_number = window->monitor->number;
- /* Maximization constraints beat tiling constraints, so if the window
- * is maximized, tiling won't have any effect unless we unmaximize it
- * horizontally first; rather than calling meta_window_unmaximize(),
- * we just set the flag and rely on meta_window_tile() syncing it to
- * save an additional roundtrip.
- */
- window->maximized_horizontally = FALSE;
- meta_window_tile (window, mode);
- }
-}
-
-static void
-handle_toggle_maximized (MetaDisplay *display,
- MetaWindow *window,
- ClutterKeyEvent *event,
- MetaKeyBinding *binding,
- gpointer dummy)
-{
- if (META_WINDOW_MAXIMIZED (window))
- meta_window_unmaximize (window, META_MAXIMIZE_BOTH);
- else if (window->has_maximize_func)
- meta_window_maximize (window, META_MAXIMIZE_BOTH);
-}
-
-static void
-handle_maximize (MetaDisplay *display,
- MetaWindow *window,
- ClutterKeyEvent *event,
- MetaKeyBinding *binding,
- gpointer dummy)
-{
- if (window->has_maximize_func)
- meta_window_maximize (window, META_MAXIMIZE_BOTH);
-}
-
-static void
-handle_unmaximize (MetaDisplay *display,
- MetaWindow *window,
- ClutterKeyEvent *event,
- MetaKeyBinding *binding,
- gpointer dummy)
-{
- if (window->maximized_vertically || window->maximized_horizontally)
- meta_window_unmaximize (window, META_MAXIMIZE_BOTH);
-}
-
-static void
-handle_toggle_shaded (MetaDisplay *display,
- MetaWindow *window,
- ClutterKeyEvent *event,
- MetaKeyBinding *binding,
- gpointer dummy)
-{
- if (window->shaded)
- meta_window_unshade (window, event->time);
- else if (window->has_shade_func)
- meta_window_shade (window, event->time);
-}
-
-static void
-handle_close (MetaDisplay *display,
- MetaWindow *window,
- ClutterKeyEvent *event,
- MetaKeyBinding *binding,
- gpointer dummy)
-{
- if (window->has_close_func)
- meta_window_delete (window, event->time);
-}
-
-static void
-handle_minimize (MetaDisplay *display,
- MetaWindow *window,
- ClutterKeyEvent *event,
- MetaKeyBinding *binding,
- gpointer dummy)
-{
- if (window->has_minimize_func)
- meta_window_minimize (window);
-}
-
-static void
-handle_begin_move (MetaDisplay *display,
- MetaWindow *window,
- ClutterKeyEvent *event,
- MetaKeyBinding *binding,
- gpointer dummy)
-{
- if (window->has_move_func)
- {
- meta_window_begin_grab_op (window,
- META_GRAB_OP_KEYBOARD_MOVING,
- FALSE,
- event->time);
- }
-}
-
-static void
-handle_begin_resize (MetaDisplay *display,
- MetaWindow *window,
- ClutterKeyEvent *event,
- MetaKeyBinding *binding,
- gpointer dummy)
-{
- if (window->has_resize_func)
- {
- meta_window_begin_grab_op (window,
- META_GRAB_OP_KEYBOARD_RESIZING_UNKNOWN,
- FALSE,
- event->time);
- }
-}
-
-static void
-handle_toggle_on_all_workspaces (MetaDisplay *display,
- MetaWindow *window,
- ClutterKeyEvent *event,
- MetaKeyBinding *binding,
- gpointer dummy)
-{
- if (window->on_all_workspaces_requested)
- meta_window_unstick (window);
- else
- meta_window_stick (window);
-}
-
-static void
-handle_move_to_workspace_last (MetaDisplay *display,
- MetaWindow *window,
- ClutterKeyEvent *event,
- MetaKeyBinding *binding,
- gpointer dummy)
-{
- MetaWorkspaceManager *workspace_manager = display->workspace_manager;
- gint which;
- MetaWorkspace *workspace;
-
- if (window->always_sticky)
- return;
-
- which = meta_workspace_manager_get_n_workspaces (workspace_manager) - 1;
- workspace = meta_workspace_manager_get_workspace_by_index (workspace_manager, which);
- meta_window_change_workspace (window, workspace);
-}
-
-
-static void
-handle_move_to_workspace (MetaDisplay *display,
- MetaWindow *window,
- ClutterKeyEvent *event,
- MetaKeyBinding *binding,
- gpointer dummy)
-{
- MetaWorkspaceManager *workspace_manager = display->workspace_manager;
- gint which = binding->handler->data;
- gboolean flip = (which < 0);
- MetaWorkspace *workspace;
-
- /* If which is zero or positive, it's a workspace number, and the window
- * should move to the workspace with that number.
- *
- * However, if it's negative, it's a direction with respect to the current
- * position; it's expressed as a member of the MetaMotionDirection enum,
- * all of whose members are negative. Such a change is called a flip.
- */
-
- if (window->always_sticky)
- return;
-
- workspace = NULL;
- if (flip)
- {
- workspace = meta_workspace_get_neighbor (workspace_manager->active_workspace,
- which);
- }
- else
- {
- workspace = meta_workspace_manager_get_workspace_by_index (workspace_manager, which);
- }
-
- if (workspace)
- {
- /* Activate second, so the window is never unmapped */
- meta_window_change_workspace (window, workspace);
- if (flip)
- {
- meta_topic (META_DEBUG_FOCUS,
- "Resetting mouse_mode to FALSE due to "
- "handle_move_to_workspace() call with flip set.");
- meta_display_clear_mouse_mode (workspace->display);
- meta_workspace_activate_with_focus (workspace,
- window,
- event->time);
- }
- }
- else
- {
- /* We could offer to create it I suppose */
- }
-}
-
-static void
-handle_move_to_monitor (MetaDisplay *display,
- MetaWindow *window,
- ClutterKeyEvent *event,
- MetaKeyBinding *binding,
- gpointer dummy)
-{
- MetaBackend *backend = meta_get_backend ();
- MetaMonitorManager *monitor_manager =
- meta_backend_get_monitor_manager (backend);
- gint which = binding->handler->data;
- MetaLogicalMonitor *current, *new;
-
- current = window->monitor;
- new = meta_monitor_manager_get_logical_monitor_neighbor (monitor_manager,
- current, which);
-
- if (new == NULL)
- return;
-
- meta_window_move_to_monitor (window, new->number);
-}
-
-static void
-handle_raise_or_lower (MetaDisplay *display,
- MetaWindow *window,
- ClutterKeyEvent *event,
- MetaKeyBinding *binding,
- gpointer dummy)
-{
- /* Get window at pointer */
-
- MetaWindow *above = NULL;
-
- /* Check if top */
- if (meta_stack_get_top (window->display->stack) == window)
- {
- meta_window_lower (window);
- return;
- }
-
- /* else check if windows in same layer are intersecting it */
-
- above = meta_stack_get_above (window->display->stack, window, TRUE);
-
- while (above)
- {
- MetaRectangle tmp, win_rect, above_rect;
-
- if (above->mapped && meta_window_should_be_showing (above))
- {
- meta_window_get_frame_rect (window, &win_rect);
- meta_window_get_frame_rect (above, &above_rect);
-
- /* Check if obscured */
- if (meta_rectangle_intersect (&win_rect, &above_rect, &tmp))
- {
- meta_window_raise (window);
- return;
- }
- }
-
- above = meta_stack_get_above (window->display->stack, above, TRUE);
- }
-
- /* window is not obscured */
- meta_window_lower (window);
-}
-
-static void
-handle_raise (MetaDisplay *display,
- MetaWindow *window,
- ClutterKeyEvent *event,
- MetaKeyBinding *binding,
- gpointer dummy)
-{
- meta_window_raise (window);
-}
-
-static void
-handle_lower (MetaDisplay *display,
- MetaWindow *window,
- ClutterKeyEvent *event,
- MetaKeyBinding *binding,
- gpointer dummy)
-{
- meta_window_lower (window);
-}
-
-static void
-handle_set_spew_mark (MetaDisplay *display,
- MetaWindow *window,
- ClutterKeyEvent *event,
- MetaKeyBinding *binding,
- gpointer dummy)
-{
- meta_verbose ("-- MARK MARK MARK MARK --");
-}
-
-#ifdef HAVE_NATIVE_BACKEND
-static void
-handle_switch_vt (MetaDisplay *display,
- MetaWindow *window,
- ClutterKeyEvent *event,
- MetaKeyBinding *binding,
- gpointer dummy)
-{
- gint vt = binding->handler->data;
- GError *error = NULL;
-
- if (!meta_activate_vt (vt, &error))
- {
- g_warning ("Failed to switch VT: %s", error->message);
- g_error_free (error);
- }
-}
-#endif /* HAVE_NATIVE_BACKEND */
-
-static void
-handle_switch_monitor (MetaDisplay *display,
- MetaWindow *window,
- ClutterKeyEvent *event,
- MetaKeyBinding *binding,
- gpointer dummy)
-{
- MetaBackend *backend = meta_get_backend ();
- MetaMonitorManager *monitor_manager =
- meta_backend_get_monitor_manager (backend);
- MetaMonitorSwitchConfigType config_type =
- meta_monitor_manager_get_switch_config (monitor_manager);
-
- if (!meta_monitor_manager_can_switch_config (monitor_manager))
- return;
-
- config_type = (config_type + 1) % (META_MONITOR_SWITCH_CONFIG_UNKNOWN);
- meta_monitor_manager_switch_config (monitor_manager, config_type);
-}
-
-static void
-handle_rotate_monitor (MetaDisplay *display,
- MetaWindow *window,
- ClutterKeyEvent *event,
- MetaKeyBinding *binding,
- gpointer dummy)
-{
- MetaBackend *backend = meta_get_backend ();
- MetaMonitorManager *monitor_manager =
- meta_backend_get_monitor_manager (backend);
-
- meta_monitor_manager_rotate_monitor (monitor_manager);
-}
-
-static void
-handle_restore_shortcuts (MetaDisplay *display,
- MetaWindow *window,
- ClutterKeyEvent *event,
- MetaKeyBinding *binding,
- gpointer dummy)
-{
- ClutterInputDevice *source;
-
- if (!display->focus_window)
- return;
-
- source = clutter_event_get_source_device ((ClutterEvent *) event);
-
- meta_topic (META_DEBUG_KEYBINDINGS, "Restoring normal keyboard shortcuts");
-
- meta_window_force_restore_shortcuts (display->focus_window, source);
-}
-
-/**
- * meta_keybindings_set_custom_handler:
- * @name: The name of the keybinding to set
- * @handler: (nullable): The new handler function
- * @user_data: User data to pass to the callback
- * @free_data: Will be called when this handler is overridden.
- *
- * Allows users to register a custom handler for a
- * builtin key binding.
- *
- * Returns: %TRUE if the binding known as @name was found,
- * %FALSE otherwise.
- */
-gboolean
-meta_keybindings_set_custom_handler (const gchar *name,
- MetaKeyHandlerFunc handler,
- gpointer user_data,
- GDestroyNotify free_data)
-{
- MetaKeyHandler *key_handler = HANDLER (name);
-
- if (!key_handler)
- return FALSE;
-
- if (key_handler->user_data_free_func && key_handler->user_data)
- key_handler->user_data_free_func (key_handler->user_data);
-
- key_handler->func = handler;
- key_handler->user_data = user_data;
- key_handler->user_data_free_func = free_data;
-
- return TRUE;
-}
-
-static void
-init_builtin_key_bindings (MetaDisplay *display)
-{
- GSettings *common_keybindings = g_settings_new (SCHEMA_COMMON_KEYBINDINGS);
- GSettings *mutter_keybindings = g_settings_new (SCHEMA_MUTTER_KEYBINDINGS);
- GSettings *mutter_wayland_keybindings = g_settings_new (SCHEMA_MUTTER_WAYLAND_KEYBINDINGS);
-
- add_builtin_keybinding (display,
- "switch-to-workspace-1",
- common_keybindings,
- META_KEY_BINDING_NONE |
- META_KEY_BINDING_IGNORE_AUTOREPEAT,
- META_KEYBINDING_ACTION_WORKSPACE_1,
- handle_switch_to_workspace, 0);
- add_builtin_keybinding (display,
- "switch-to-workspace-2",
- common_keybindings,
- META_KEY_BINDING_NONE |
- META_KEY_BINDING_IGNORE_AUTOREPEAT,
- META_KEYBINDING_ACTION_WORKSPACE_2,
- handle_switch_to_workspace, 1);
- add_builtin_keybinding (display,
- "switch-to-workspace-3",
- common_keybindings,
- META_KEY_BINDING_NONE |
- META_KEY_BINDING_IGNORE_AUTOREPEAT,
- META_KEYBINDING_ACTION_WORKSPACE_3,
- handle_switch_to_workspace, 2);
- add_builtin_keybinding (display,
- "switch-to-workspace-4",
- common_keybindings,
- META_KEY_BINDING_NONE |
- META_KEY_BINDING_IGNORE_AUTOREPEAT,
- META_KEYBINDING_ACTION_WORKSPACE_4,
- handle_switch_to_workspace, 3);
- add_builtin_keybinding (display,
- "switch-to-workspace-5",
- common_keybindings,
- META_KEY_BINDING_NONE |
- META_KEY_BINDING_IGNORE_AUTOREPEAT,
- META_KEYBINDING_ACTION_WORKSPACE_5,
- handle_switch_to_workspace, 4);
- add_builtin_keybinding (display,
- "switch-to-workspace-6",
- common_keybindings,
- META_KEY_BINDING_NONE |
- META_KEY_BINDING_IGNORE_AUTOREPEAT,
- META_KEYBINDING_ACTION_WORKSPACE_6,
- handle_switch_to_workspace, 5);
- add_builtin_keybinding (display,
- "switch-to-workspace-7",
- common_keybindings,
- META_KEY_BINDING_NONE |
- META_KEY_BINDING_IGNORE_AUTOREPEAT,
- META_KEYBINDING_ACTION_WORKSPACE_7,
- handle_switch_to_workspace, 6);
- add_builtin_keybinding (display,
- "switch-to-workspace-8",
- common_keybindings,
- META_KEY_BINDING_NONE |
- META_KEY_BINDING_IGNORE_AUTOREPEAT,
- META_KEYBINDING_ACTION_WORKSPACE_8,
- handle_switch_to_workspace, 7);
- add_builtin_keybinding (display,
- "switch-to-workspace-9",
- common_keybindings,
- META_KEY_BINDING_NONE |
- META_KEY_BINDING_IGNORE_AUTOREPEAT,
- META_KEYBINDING_ACTION_WORKSPACE_9,
- handle_switch_to_workspace, 8);
- add_builtin_keybinding (display,
- "switch-to-workspace-10",
- common_keybindings,
- META_KEY_BINDING_NONE |
- META_KEY_BINDING_IGNORE_AUTOREPEAT,
- META_KEYBINDING_ACTION_WORKSPACE_10,
- handle_switch_to_workspace, 9);
- add_builtin_keybinding (display,
- "switch-to-workspace-11",
- common_keybindings,
- META_KEY_BINDING_NONE |
- META_KEY_BINDING_IGNORE_AUTOREPEAT,
- META_KEYBINDING_ACTION_WORKSPACE_11,
- handle_switch_to_workspace, 10);
- add_builtin_keybinding (display,
- "switch-to-workspace-12",
- common_keybindings,
- META_KEY_BINDING_NONE |
- META_KEY_BINDING_IGNORE_AUTOREPEAT,
- META_KEYBINDING_ACTION_WORKSPACE_12,
- handle_switch_to_workspace, 11);
-
- add_builtin_keybinding (display,
- "switch-to-workspace-left",
- common_keybindings,
- META_KEY_BINDING_NONE,
- META_KEYBINDING_ACTION_WORKSPACE_LEFT,
- handle_switch_to_workspace, META_MOTION_LEFT);
-
- add_builtin_keybinding (display,
- "switch-to-workspace-right",
- common_keybindings,
- META_KEY_BINDING_NONE,
- META_KEYBINDING_ACTION_WORKSPACE_RIGHT,
- handle_switch_to_workspace, META_MOTION_RIGHT);
-
- add_builtin_keybinding (display,
- "switch-to-workspace-up",
- common_keybindings,
- META_KEY_BINDING_NONE,
- META_KEYBINDING_ACTION_WORKSPACE_UP,
- handle_switch_to_workspace, META_MOTION_UP);
-
- add_builtin_keybinding (display,
- "switch-to-workspace-down",
- common_keybindings,
- META_KEY_BINDING_NONE,
- META_KEYBINDING_ACTION_WORKSPACE_DOWN,
- handle_switch_to_workspace, META_MOTION_DOWN);
-
- add_builtin_keybinding (display,
- "switch-to-workspace-last",
- common_keybindings,
- META_KEY_BINDING_NONE,
- META_KEYBINDING_ACTION_WORKSPACE_LAST,
- handle_switch_to_last_workspace, 0);
-
-
-
- /* The ones which have inverses. These can't be bound to any keystroke
- * containing Shift because Shift will invert their "backward" state.
- *
- * TODO: "NORMAL" and "DOCKS" should be renamed to the same name as their
- * action, for obviousness.
- *
- * TODO: handle_switch and handle_cycle should probably really be the
- * same function checking a bit in the parameter for difference.
- */
-
- add_builtin_keybinding (display,
- "switch-group",
- common_keybindings,
- META_KEY_BINDING_NONE,
- META_KEYBINDING_ACTION_SWITCH_GROUP,
- handle_switch, META_TAB_LIST_GROUP);
-
- add_builtin_keybinding (display,
- "switch-group-backward",
- common_keybindings,
- META_KEY_BINDING_IS_REVERSED,
- META_KEYBINDING_ACTION_SWITCH_GROUP_BACKWARD,
- handle_switch, META_TAB_LIST_GROUP);
-
- add_builtin_keybinding (display,
- "switch-applications",
- common_keybindings,
- META_KEY_BINDING_NONE,
- META_KEYBINDING_ACTION_SWITCH_APPLICATIONS,
- handle_switch, META_TAB_LIST_NORMAL);
-
- add_builtin_keybinding (display,
- "switch-applications-backward",
- common_keybindings,
- META_KEY_BINDING_IS_REVERSED,
- META_KEYBINDING_ACTION_SWITCH_APPLICATIONS_BACKWARD,
- handle_switch, META_TAB_LIST_NORMAL);
-
- add_builtin_keybinding (display,
- "switch-windows",
- common_keybindings,
- META_KEY_BINDING_NONE,
- META_KEYBINDING_ACTION_SWITCH_WINDOWS,
- handle_switch, META_TAB_LIST_NORMAL);
-
- add_builtin_keybinding (display,
- "switch-windows-backward",
- common_keybindings,
- META_KEY_BINDING_IS_REVERSED,
- META_KEYBINDING_ACTION_SWITCH_WINDOWS_BACKWARD,
- handle_switch, META_TAB_LIST_NORMAL);
-
- add_builtin_keybinding (display,
- "switch-panels",
- common_keybindings,
- META_KEY_BINDING_NONE,
- META_KEYBINDING_ACTION_SWITCH_PANELS,
- handle_switch, META_TAB_LIST_DOCKS);
-
- add_builtin_keybinding (display,
- "switch-panels-backward",
- common_keybindings,
- META_KEY_BINDING_IS_REVERSED,
- META_KEYBINDING_ACTION_SWITCH_PANELS_BACKWARD,
- handle_switch, META_TAB_LIST_DOCKS);
-
- add_builtin_keybinding (display,
- "cycle-group",
- common_keybindings,
- META_KEY_BINDING_NONE,
- META_KEYBINDING_ACTION_CYCLE_GROUP,
- handle_cycle, META_TAB_LIST_GROUP);
-
- add_builtin_keybinding (display,
- "cycle-group-backward",
- common_keybindings,
- META_KEY_BINDING_IS_REVERSED,
- META_KEYBINDING_ACTION_CYCLE_GROUP_BACKWARD,
- handle_cycle, META_TAB_LIST_GROUP);
-
- add_builtin_keybinding (display,
- "cycle-windows",
- common_keybindings,
- META_KEY_BINDING_NONE,
- META_KEYBINDING_ACTION_CYCLE_WINDOWS,
- handle_cycle, META_TAB_LIST_NORMAL);
-
- add_builtin_keybinding (display,
- "cycle-windows-backward",
- common_keybindings,
- META_KEY_BINDING_IS_REVERSED,
- META_KEYBINDING_ACTION_CYCLE_WINDOWS_BACKWARD,
- handle_cycle, META_TAB_LIST_NORMAL);
-
- add_builtin_keybinding (display,
- "cycle-panels",
- common_keybindings,
- META_KEY_BINDING_NONE,
- META_KEYBINDING_ACTION_CYCLE_PANELS,
- handle_cycle, META_TAB_LIST_DOCKS);
-
- add_builtin_keybinding (display,
- "cycle-panels-backward",
- common_keybindings,
- META_KEY_BINDING_IS_REVERSED,
- META_KEYBINDING_ACTION_CYCLE_PANELS_BACKWARD,
- handle_cycle, META_TAB_LIST_DOCKS);
-
- /***********************************/
-
- add_builtin_keybinding (display,
- "show-desktop",
- common_keybindings,
- META_KEY_BINDING_NONE,
- META_KEYBINDING_ACTION_SHOW_DESKTOP,
- handle_show_desktop, 0);
-
- add_builtin_keybinding (display,
- "panel-main-menu",
- common_keybindings,
- META_KEY_BINDING_NONE,
- META_KEYBINDING_ACTION_PANEL_MAIN_MENU,
- handle_panel, META_KEYBINDING_ACTION_PANEL_MAIN_MENU);
-
- add_builtin_keybinding (display,
- "panel-run-dialog",
- common_keybindings,
- META_KEY_BINDING_NONE,
- META_KEYBINDING_ACTION_PANEL_RUN_DIALOG,
- handle_panel, META_KEYBINDING_ACTION_PANEL_RUN_DIALOG);
-
- add_builtin_keybinding (display,
- "set-spew-mark",
- common_keybindings,
- META_KEY_BINDING_NONE,
- META_KEYBINDING_ACTION_SET_SPEW_MARK,
- handle_set_spew_mark, 0);
-
- add_builtin_keybinding (display,
- "switch-monitor",
- mutter_keybindings,
- META_KEY_BINDING_NONE,
- META_KEYBINDING_ACTION_SWITCH_MONITOR,
- handle_switch_monitor, 0);
-
- add_builtin_keybinding (display,
- "rotate-monitor",
- mutter_keybindings,
- META_KEY_BINDING_NONE,
- META_KEYBINDING_ACTION_ROTATE_MONITOR,
- handle_rotate_monitor, 0);
-
-#ifdef HAVE_NATIVE_BACKEND
- MetaBackend *backend = meta_get_backend ();
- if (META_IS_BACKEND_NATIVE (backend))
- {
- add_builtin_keybinding (display,
- "switch-to-session-1",
- mutter_wayland_keybindings,
- META_KEY_BINDING_NON_MASKABLE,
- META_KEYBINDING_ACTION_NONE,
- handle_switch_vt, 1);
-
- add_builtin_keybinding (display,
- "switch-to-session-2",
- mutter_wayland_keybindings,
- META_KEY_BINDING_NON_MASKABLE,
- META_KEYBINDING_ACTION_NONE,
- handle_switch_vt, 2);
-
- add_builtin_keybinding (display,
- "switch-to-session-3",
- mutter_wayland_keybindings,
- META_KEY_BINDING_NON_MASKABLE,
- META_KEYBINDING_ACTION_NONE,
- handle_switch_vt, 3);
-
- add_builtin_keybinding (display,
- "switch-to-session-4",
- mutter_wayland_keybindings,
- META_KEY_BINDING_NON_MASKABLE,
- META_KEYBINDING_ACTION_NONE,
- handle_switch_vt, 4);
-
- add_builtin_keybinding (display,
- "switch-to-session-5",
- mutter_wayland_keybindings,
- META_KEY_BINDING_NON_MASKABLE,
- META_KEYBINDING_ACTION_NONE,
- handle_switch_vt, 5);
-
- add_builtin_keybinding (display,
- "switch-to-session-6",
- mutter_wayland_keybindings,
- META_KEY_BINDING_NON_MASKABLE,
- META_KEYBINDING_ACTION_NONE,
- handle_switch_vt, 6);
-
- add_builtin_keybinding (display,
- "switch-to-session-7",
- mutter_wayland_keybindings,
- META_KEY_BINDING_NON_MASKABLE,
- META_KEYBINDING_ACTION_NONE,
- handle_switch_vt, 7);
-
- add_builtin_keybinding (display,
- "switch-to-session-8",
- mutter_wayland_keybindings,
- META_KEY_BINDING_NON_MASKABLE,
- META_KEYBINDING_ACTION_NONE,
- handle_switch_vt, 8);
-
- add_builtin_keybinding (display,
- "switch-to-session-9",
- mutter_wayland_keybindings,
- META_KEY_BINDING_NON_MASKABLE,
- META_KEYBINDING_ACTION_NONE,
- handle_switch_vt, 9);
-
- add_builtin_keybinding (display,
- "switch-to-session-10",
- mutter_wayland_keybindings,
- META_KEY_BINDING_NON_MASKABLE,
- META_KEYBINDING_ACTION_NONE,
- handle_switch_vt, 10);
-
- add_builtin_keybinding (display,
- "switch-to-session-11",
- mutter_wayland_keybindings,
- META_KEY_BINDING_NON_MASKABLE,
- META_KEYBINDING_ACTION_NONE,
- handle_switch_vt, 11);
-
- add_builtin_keybinding (display,
- "switch-to-session-12",
- mutter_wayland_keybindings,
- META_KEY_BINDING_NON_MASKABLE,
- META_KEYBINDING_ACTION_NONE,
- handle_switch_vt, 12);
- }
-#endif /* HAVE_NATIVE_BACKEND */
-
- add_builtin_keybinding (display,
- "restore-shortcuts",
- mutter_wayland_keybindings,
- META_KEY_BINDING_NON_MASKABLE,
- META_KEYBINDING_ACTION_NONE,
- handle_restore_shortcuts, 0);
-
- /************************ PER WINDOW BINDINGS ************************/
-
- /* These take a window as an extra parameter; they have no effect
- * if no window is active.
- */
-
- add_builtin_keybinding (display,
- "activate-window-menu",
- common_keybindings,
- META_KEY_BINDING_PER_WINDOW |
- META_KEY_BINDING_IGNORE_AUTOREPEAT,
- META_KEYBINDING_ACTION_ACTIVATE_WINDOW_MENU,
- handle_activate_window_menu, 0);
-
- add_builtin_keybinding (display,
- "toggle-fullscreen",
- common_keybindings,
- META_KEY_BINDING_PER_WINDOW |
- META_KEY_BINDING_IGNORE_AUTOREPEAT,
- META_KEYBINDING_ACTION_TOGGLE_FULLSCREEN,
- handle_toggle_fullscreen, 0);
-
- add_builtin_keybinding (display,
- "toggle-maximized",
- common_keybindings,
- META_KEY_BINDING_PER_WINDOW |
- META_KEY_BINDING_IGNORE_AUTOREPEAT,
- META_KEYBINDING_ACTION_TOGGLE_MAXIMIZED,
- handle_toggle_maximized, 0);
-
- add_builtin_keybinding (display,
- "toggle-tiled-left",
- mutter_keybindings,
- META_KEY_BINDING_PER_WINDOW |
- META_KEY_BINDING_IGNORE_AUTOREPEAT,
- META_KEYBINDING_ACTION_TOGGLE_TILED_LEFT,
- handle_toggle_tiled, META_TILE_LEFT);
-
- add_builtin_keybinding (display,
- "toggle-tiled-right",
- mutter_keybindings,
- META_KEY_BINDING_PER_WINDOW |
- META_KEY_BINDING_IGNORE_AUTOREPEAT,
- META_KEYBINDING_ACTION_TOGGLE_TILED_RIGHT,
- handle_toggle_tiled, META_TILE_RIGHT);
-
- add_builtin_keybinding (display,
- "toggle-above",
- common_keybindings,
- META_KEY_BINDING_PER_WINDOW |
- META_KEY_BINDING_IGNORE_AUTOREPEAT,
- META_KEYBINDING_ACTION_TOGGLE_ABOVE,
- handle_toggle_above, 0);
-
- add_builtin_keybinding (display,
- "maximize",
- common_keybindings,
- META_KEY_BINDING_PER_WINDOW |
- META_KEY_BINDING_IGNORE_AUTOREPEAT,
- META_KEYBINDING_ACTION_MAXIMIZE,
- handle_maximize, 0);
-
- add_builtin_keybinding (display,
- "unmaximize",
- common_keybindings,
- META_KEY_BINDING_PER_WINDOW |
- META_KEY_BINDING_IGNORE_AUTOREPEAT,
- META_KEYBINDING_ACTION_UNMAXIMIZE,
- handle_unmaximize, 0);
-
- add_builtin_keybinding (display,
- "toggle-shaded",
- common_keybindings,
- META_KEY_BINDING_PER_WINDOW |
- META_KEY_BINDING_IGNORE_AUTOREPEAT,
- META_KEYBINDING_ACTION_TOGGLE_SHADED,
- handle_toggle_shaded, 0);
-
- add_builtin_keybinding (display,
- "minimize",
- common_keybindings,
- META_KEY_BINDING_PER_WINDOW |
- META_KEY_BINDING_IGNORE_AUTOREPEAT,
- META_KEYBINDING_ACTION_MINIMIZE,
- handle_minimize, 0);
-
- add_builtin_keybinding (display,
- "close",
- common_keybindings,
- META_KEY_BINDING_PER_WINDOW |
- META_KEY_BINDING_IGNORE_AUTOREPEAT,
- META_KEYBINDING_ACTION_CLOSE,
- handle_close, 0);
-
- add_builtin_keybinding (display,
- "begin-move",
- common_keybindings,
- META_KEY_BINDING_PER_WINDOW |
- META_KEY_BINDING_IGNORE_AUTOREPEAT,
- META_KEYBINDING_ACTION_BEGIN_MOVE,
- handle_begin_move, 0);
-
- add_builtin_keybinding (display,
- "begin-resize",
- common_keybindings,
- META_KEY_BINDING_PER_WINDOW |
- META_KEY_BINDING_IGNORE_AUTOREPEAT,
- META_KEYBINDING_ACTION_BEGIN_RESIZE,
- handle_begin_resize, 0);
-
- add_builtin_keybinding (display,
- "toggle-on-all-workspaces",
- common_keybindings,
- META_KEY_BINDING_PER_WINDOW |
- META_KEY_BINDING_IGNORE_AUTOREPEAT,
- META_KEYBINDING_ACTION_TOGGLE_ON_ALL_WORKSPACES,
- handle_toggle_on_all_workspaces, 0);
-
- add_builtin_keybinding (display,
- "move-to-workspace-1",
- common_keybindings,
- META_KEY_BINDING_PER_WINDOW |
- META_KEY_BINDING_IGNORE_AUTOREPEAT,
- META_KEYBINDING_ACTION_MOVE_TO_WORKSPACE_1,
- handle_move_to_workspace, 0);
-
- add_builtin_keybinding (display,
- "move-to-workspace-2",
- common_keybindings,
- META_KEY_BINDING_PER_WINDOW |
- META_KEY_BINDING_IGNORE_AUTOREPEAT,
- META_KEYBINDING_ACTION_MOVE_TO_WORKSPACE_2,
- handle_move_to_workspace, 1);
-
- add_builtin_keybinding (display,
- "move-to-workspace-3",
- common_keybindings,
- META_KEY_BINDING_PER_WINDOW |
- META_KEY_BINDING_IGNORE_AUTOREPEAT,
- META_KEYBINDING_ACTION_MOVE_TO_WORKSPACE_3,
- handle_move_to_workspace, 2);
-
- add_builtin_keybinding (display,
- "move-to-workspace-4",
- common_keybindings,
- META_KEY_BINDING_PER_WINDOW |
- META_KEY_BINDING_IGNORE_AUTOREPEAT,
- META_KEYBINDING_ACTION_MOVE_TO_WORKSPACE_4,
- handle_move_to_workspace, 3);
-
- add_builtin_keybinding (display,
- "move-to-workspace-5",
- common_keybindings,
- META_KEY_BINDING_PER_WINDOW |
- META_KEY_BINDING_IGNORE_AUTOREPEAT,
- META_KEYBINDING_ACTION_MOVE_TO_WORKSPACE_5,
- handle_move_to_workspace, 4);
-
- add_builtin_keybinding (display,
- "move-to-workspace-6",
- common_keybindings,
- META_KEY_BINDING_PER_WINDOW |
- META_KEY_BINDING_IGNORE_AUTOREPEAT,
- META_KEYBINDING_ACTION_MOVE_TO_WORKSPACE_6,
- handle_move_to_workspace, 5);
-
- add_builtin_keybinding (display,
- "move-to-workspace-7",
- common_keybindings,
- META_KEY_BINDING_PER_WINDOW |
- META_KEY_BINDING_IGNORE_AUTOREPEAT,
- META_KEYBINDING_ACTION_MOVE_TO_WORKSPACE_7,
- handle_move_to_workspace, 6);
-
- add_builtin_keybinding (display,
- "move-to-workspace-8",
- common_keybindings,
- META_KEY_BINDING_PER_WINDOW |
- META_KEY_BINDING_IGNORE_AUTOREPEAT,
- META_KEYBINDING_ACTION_MOVE_TO_WORKSPACE_8,
- handle_move_to_workspace, 7);
-
- add_builtin_keybinding (display,
- "move-to-workspace-9",
- common_keybindings,
- META_KEY_BINDING_PER_WINDOW |
- META_KEY_BINDING_IGNORE_AUTOREPEAT,
- META_KEYBINDING_ACTION_MOVE_TO_WORKSPACE_9,
- handle_move_to_workspace, 8);
-
- add_builtin_keybinding (display,
- "move-to-workspace-10",
- common_keybindings,
- META_KEY_BINDING_PER_WINDOW |
- META_KEY_BINDING_IGNORE_AUTOREPEAT,
- META_KEYBINDING_ACTION_MOVE_TO_WORKSPACE_10,
- handle_move_to_workspace, 9);
-
- add_builtin_keybinding (display,
- "move-to-workspace-11",
- common_keybindings,
- META_KEY_BINDING_PER_WINDOW |
- META_KEY_BINDING_IGNORE_AUTOREPEAT,
- META_KEYBINDING_ACTION_MOVE_TO_WORKSPACE_11,
- handle_move_to_workspace, 10);
-
- add_builtin_keybinding (display,
- "move-to-workspace-12",
- common_keybindings,
- META_KEY_BINDING_PER_WINDOW |
- META_KEY_BINDING_IGNORE_AUTOREPEAT,
- META_KEYBINDING_ACTION_MOVE_TO_WORKSPACE_12,
- handle_move_to_workspace, 11);
-
- add_builtin_keybinding (display,
- "move-to-workspace-last",
- common_keybindings,
- META_KEY_BINDING_PER_WINDOW |
- META_KEY_BINDING_IGNORE_AUTOREPEAT,
- META_KEYBINDING_ACTION_MOVE_TO_WORKSPACE_LAST,
- handle_move_to_workspace_last, 0);
-
- add_builtin_keybinding (display,
- "move-to-workspace-left",
- common_keybindings,
- META_KEY_BINDING_PER_WINDOW,
- META_KEYBINDING_ACTION_MOVE_TO_WORKSPACE_LEFT,
- handle_move_to_workspace, META_MOTION_LEFT);
-
- add_builtin_keybinding (display,
- "move-to-workspace-right",
- common_keybindings,
- META_KEY_BINDING_PER_WINDOW,
- META_KEYBINDING_ACTION_MOVE_TO_WORKSPACE_RIGHT,
- handle_move_to_workspace, META_MOTION_RIGHT);
-
- add_builtin_keybinding (display,
- "move-to-workspace-up",
- common_keybindings,
- META_KEY_BINDING_PER_WINDOW,
- META_KEYBINDING_ACTION_MOVE_TO_WORKSPACE_UP,
- handle_move_to_workspace, META_MOTION_UP);
-
- add_builtin_keybinding (display,
- "move-to-workspace-down",
- common_keybindings,
- META_KEY_BINDING_PER_WINDOW,
- META_KEYBINDING_ACTION_MOVE_TO_WORKSPACE_DOWN,
- handle_move_to_workspace, META_MOTION_DOWN);
-
- add_builtin_keybinding (display,
- "move-to-monitor-left",
- common_keybindings,
- META_KEY_BINDING_PER_WINDOW,
- META_KEYBINDING_ACTION_MOVE_TO_MONITOR_LEFT,
- handle_move_to_monitor, META_DISPLAY_LEFT);
-
- add_builtin_keybinding (display,
- "move-to-monitor-right",
- common_keybindings,
- META_KEY_BINDING_PER_WINDOW,
- META_KEYBINDING_ACTION_MOVE_TO_MONITOR_RIGHT,
- handle_move_to_monitor, META_DISPLAY_RIGHT);
-
- add_builtin_keybinding (display,
- "move-to-monitor-down",
- common_keybindings,
- META_KEY_BINDING_PER_WINDOW,
- META_KEYBINDING_ACTION_MOVE_TO_MONITOR_DOWN,
- handle_move_to_monitor, META_DISPLAY_DOWN);
-
- add_builtin_keybinding (display,
- "move-to-monitor-up",
- common_keybindings,
- META_KEY_BINDING_PER_WINDOW,
- META_KEYBINDING_ACTION_MOVE_TO_MONITOR_UP,
- handle_move_to_monitor, META_DISPLAY_UP);
-
- add_builtin_keybinding (display,
- "raise-or-lower",
- common_keybindings,
- META_KEY_BINDING_PER_WINDOW |
- META_KEY_BINDING_IGNORE_AUTOREPEAT,
- META_KEYBINDING_ACTION_RAISE_OR_LOWER,
- handle_raise_or_lower, 0);
-
- add_builtin_keybinding (display,
- "raise",
- common_keybindings,
- META_KEY_BINDING_PER_WINDOW |
- META_KEY_BINDING_IGNORE_AUTOREPEAT,
- META_KEYBINDING_ACTION_RAISE,
- handle_raise, 0);
-
- add_builtin_keybinding (display,
- "lower",
- common_keybindings,
- META_KEY_BINDING_PER_WINDOW |
- META_KEY_BINDING_IGNORE_AUTOREPEAT,
- META_KEYBINDING_ACTION_LOWER,
- handle_lower, 0);
-
- add_builtin_keybinding (display,
- "maximize-vertically",
- common_keybindings,
- META_KEY_BINDING_PER_WINDOW |
- META_KEY_BINDING_IGNORE_AUTOREPEAT,
- META_KEYBINDING_ACTION_MAXIMIZE_VERTICALLY,
- handle_maximize_vertically, 0);
-
- add_builtin_keybinding (display,
- "maximize-horizontally",
- common_keybindings,
- META_KEY_BINDING_PER_WINDOW |
- META_KEY_BINDING_IGNORE_AUTOREPEAT,
- META_KEYBINDING_ACTION_MAXIMIZE_HORIZONTALLY,
- handle_maximize_horizontally, 0);
-
- add_builtin_keybinding (display,
- "always-on-top",
- common_keybindings,
- META_KEY_BINDING_PER_WINDOW |
- META_KEY_BINDING_IGNORE_AUTOREPEAT,
- META_KEYBINDING_ACTION_ALWAYS_ON_TOP,
- handle_always_on_top, 0);
-
- add_builtin_keybinding (display,
- "move-to-corner-nw",
- common_keybindings,
- META_KEY_BINDING_PER_WINDOW |
- META_KEY_BINDING_IGNORE_AUTOREPEAT,
- META_KEYBINDING_ACTION_MOVE_TO_CORNER_NW,
- handle_move_to_corner_nw, 0);
-
- add_builtin_keybinding (display,
- "move-to-corner-ne",
- common_keybindings,
- META_KEY_BINDING_PER_WINDOW |
- META_KEY_BINDING_IGNORE_AUTOREPEAT,
- META_KEYBINDING_ACTION_MOVE_TO_CORNER_NE,
- handle_move_to_corner_ne, 0);
-
- add_builtin_keybinding (display,
- "move-to-corner-sw",
- common_keybindings,
- META_KEY_BINDING_PER_WINDOW |
- META_KEY_BINDING_IGNORE_AUTOREPEAT,
- META_KEYBINDING_ACTION_MOVE_TO_CORNER_SW,
- handle_move_to_corner_sw, 0);
-
- add_builtin_keybinding (display,
- "move-to-corner-se",
- common_keybindings,
- META_KEY_BINDING_PER_WINDOW |
- META_KEY_BINDING_IGNORE_AUTOREPEAT,
- META_KEYBINDING_ACTION_MOVE_TO_CORNER_SE,
- handle_move_to_corner_se, 0);
-
- add_builtin_keybinding (display,
- "move-to-side-n",
- common_keybindings,
- META_KEY_BINDING_PER_WINDOW |
- META_KEY_BINDING_IGNORE_AUTOREPEAT,
- META_KEYBINDING_ACTION_MOVE_TO_SIDE_N,
- handle_move_to_side_n, 0);
-
- add_builtin_keybinding (display,
- "move-to-side-s",
- common_keybindings,
- META_KEY_BINDING_PER_WINDOW |
- META_KEY_BINDING_IGNORE_AUTOREPEAT,
- META_KEYBINDING_ACTION_MOVE_TO_SIDE_S,
- handle_move_to_side_s, 0);
-
- add_builtin_keybinding (display,
- "move-to-side-e",
- common_keybindings,
- META_KEY_BINDING_PER_WINDOW |
- META_KEY_BINDING_IGNORE_AUTOREPEAT,
- META_KEYBINDING_ACTION_MOVE_TO_SIDE_E,
- handle_move_to_side_e, 0);
-
- add_builtin_keybinding (display,
- "move-to-side-w",
- common_keybindings,
- META_KEY_BINDING_PER_WINDOW |
- META_KEY_BINDING_IGNORE_AUTOREPEAT,
- META_KEYBINDING_ACTION_MOVE_TO_SIDE_W,
- handle_move_to_side_w, 0);
-
- add_builtin_keybinding (display,
- "move-to-center",
- common_keybindings,
- META_KEY_BINDING_PER_WINDOW |
- META_KEY_BINDING_IGNORE_AUTOREPEAT,
- META_KEYBINDING_ACTION_MOVE_TO_CENTER,
- handle_move_to_center, 0);
-
- g_object_unref (common_keybindings);
- g_object_unref (mutter_keybindings);
- g_object_unref (mutter_wayland_keybindings);
-}
-
-void
-meta_display_init_keys (MetaDisplay *display)
-{
- MetaKeyBindingManager *keys = &display->key_binding_manager;
- MetaBackend *backend = meta_get_backend ();
- MetaKeyHandler *handler;
-
- keys->backend = backend;
-
- /* Keybindings */
- keys->ignored_modifier_mask = 0;
- keys->hyper_mask = 0;
- keys->super_mask = 0;
- keys->meta_mask = 0;
-
- keys->key_bindings = g_hash_table_new_full (NULL, NULL, NULL, (GDestroyNotify) meta_key_binding_free);
- keys->key_bindings_index = g_hash_table_new (NULL, NULL);
-
- reload_modmap (keys);
-
- key_handlers = g_hash_table_new_full (g_str_hash, g_str_equal, g_free,
- (GDestroyNotify) key_handler_free);
-
- handler = g_new0 (MetaKeyHandler, 1);
- handler->name = g_strdup ("overlay-key");
- handler->flags = META_KEY_BINDING_BUILTIN | META_KEY_BINDING_NO_AUTO_GRAB;
-
- g_hash_table_insert (key_handlers, g_strdup (handler->name), handler);
-
- handler = g_new0 (MetaKeyHandler, 1);
- handler->name = g_strdup ("locate-pointer-key");
- handler->flags = META_KEY_BINDING_BUILTIN | META_KEY_BINDING_NO_AUTO_GRAB;
-
- g_hash_table_insert (key_handlers, g_strdup (handler->name), handler);
-
- handler = g_new0 (MetaKeyHandler, 1);
- handler->name = g_strdup ("iso-next-group");
- handler->flags = META_KEY_BINDING_BUILTIN;
-
- g_hash_table_insert (key_handlers, g_strdup (handler->name), handler);
-
- handler = g_new0 (MetaKeyHandler, 1);
- handler->name = g_strdup ("external-grab");
- handler->func = handle_external_grab;
- handler->default_func = handle_external_grab;
-
- g_hash_table_insert (key_handlers, g_strdup (handler->name), handler);
-
- external_grabs = g_hash_table_new_full (g_str_hash, g_str_equal,
- NULL,
- (GDestroyNotify)meta_key_grab_free);
-
- init_builtin_key_bindings (display);
-
- rebuild_key_binding_table (keys);
- rebuild_special_bindings (keys);
-
- reload_combos (keys);
-
- update_window_grab_modifiers (display);
-
- /* Keys are actually grabbed in meta_screen_grab_keys() */
-
- meta_prefs_add_listener (prefs_changed_callback, display);
-
- g_signal_connect_swapped (backend, "keymap-changed",
- G_CALLBACK (reload_keybindings), display);
- g_signal_connect_swapped (backend, "keymap-layout-group-changed",
- G_CALLBACK (reload_keybindings), display);
-}