keybindings: Move X11 bits to a separate header

Reduces the noise in terms of ifdef and makes it much easier
to spot which X11 bits are still mixed in the generic
keybindings file

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3776>
This commit is contained in:
Bilal Elmoussaoui
2024-06-10 12:06:16 +02:00
parent beae45a060
commit fd9957b81a
11 changed files with 575 additions and 532 deletions

View File

@ -28,6 +28,7 @@
#ifdef HAVE_X11_CLIENT #ifdef HAVE_X11_CLIENT
#include "x11/meta-x11-frame.h" #include "x11/meta-x11-frame.h"
#include "x11/meta-x11-keybindings-private.h"
#include "x11/window-x11.h" #include "x11/window-x11.h"
#endif #endif

View File

@ -39,6 +39,9 @@
#include "meta/common.h" #include "meta/common.h"
#include "meta/meta-selection.h" #include "meta/meta-selection.h"
#include "meta/prefs.h" #include "meta/prefs.h"
#ifdef HAVE_X11_CLIENT
#include "meta/meta-x11-types.h"
#endif
typedef struct _MetaBell MetaBell; typedef struct _MetaBell MetaBell;
typedef struct _MetaStack MetaStack; typedef struct _MetaStack MetaStack;
@ -229,17 +232,6 @@ void meta_display_notify_window_created (MetaDisplay *display,
META_EXPORT_TEST META_EXPORT_TEST
GSList* meta_display_list_windows (MetaDisplay *display, GSList* meta_display_list_windows (MetaDisplay *display,
MetaListWindowsFlags flags); MetaListWindowsFlags flags);
#ifdef HAVE_X11
void meta_display_grab_window_buttons (MetaDisplay *display,
MetaWindow *window);
void meta_display_ungrab_window_buttons (MetaDisplay *display,
MetaWindow *window);
void meta_display_grab_focus_window_button (MetaDisplay *display,
MetaWindow *window);
void meta_display_ungrab_focus_window_button (MetaDisplay *display,
MetaWindow *window);
#endif
void meta_display_ping_window (MetaWindow *window, void meta_display_ping_window (MetaWindow *window,
guint32 serial); guint32 serial);

View File

@ -31,9 +31,6 @@
#include "core/meta-accel-parse.h" #include "core/meta-accel-parse.h"
#include "meta/keybindings.h" #include "meta/keybindings.h"
#ifdef HAVE_X11
#include "meta/meta-x11-types.h"
#endif
typedef struct _MetaKeyHandler MetaKeyHandler; typedef struct _MetaKeyHandler MetaKeyHandler;
struct _MetaKeyHandler struct _MetaKeyHandler
@ -138,10 +135,6 @@ typedef struct
void meta_display_init_keys (MetaDisplay *display); void meta_display_init_keys (MetaDisplay *display);
void meta_display_shutdown_keys (MetaDisplay *display); void meta_display_shutdown_keys (MetaDisplay *display);
#ifdef HAVE_X11
void meta_window_grab_keys (MetaWindow *window);
void meta_window_ungrab_keys (MetaWindow *window);
#endif
gboolean meta_keybindings_process_event (MetaDisplay *display, gboolean meta_keybindings_process_event (MetaDisplay *display,
MetaWindow *window, MetaWindow *window,
const ClutterEvent *event); const ClutterEvent *event);
@ -159,11 +152,6 @@ void meta_prefs_get_locate_pointer_binding (MetaKeyCombo *combo);
const char *meta_prefs_get_iso_next_group_option (void); const char *meta_prefs_get_iso_next_group_option (void);
gboolean meta_prefs_is_locate_pointer_enabled (void); gboolean meta_prefs_is_locate_pointer_enabled (void);
#ifdef HAVE_X11
void meta_x11_display_grab_keys (MetaX11Display *x11_display);
void meta_x11_display_ungrab_keys (MetaX11Display *x11_display);
#endif
gboolean meta_display_process_keybinding_event (MetaDisplay *display, gboolean meta_display_process_keybinding_event (MetaDisplay *display,
const char *name, const char *name,
const ClutterEvent *event); const ClutterEvent *event);

View File

@ -43,12 +43,9 @@
#ifdef HAVE_X11 #ifdef HAVE_X11
#include "backends/x11/meta-backend-x11.h" #include "backends/x11/meta-backend-x11.h"
#include "backends/x11/meta-clutter-backend-x11.h"
#include "backends/x11/meta-input-device-x11.h" #include "backends/x11/meta-input-device-x11.h"
#include "mtk/mtk-x11.h"
#include "x11/meta-x11-display-private.h" #include "x11/meta-x11-display-private.h"
#include "x11/meta-x11-frame.h" #include "x11/meta-x11-keybindings-private.h"
#include "x11/window-x11-private.h"
#endif #endif
#ifdef HAVE_NATIVE_BACKEND #ifdef HAVE_NATIVE_BACKEND
@ -183,11 +180,6 @@ meta_key_binding_is_builtin (MetaKeyBinding *binding)
* handler functions and have some kind of flag to say they're unbindable. * handler functions and have some kind of flag to say they're unbindable.
*/ */
#ifdef HAVE_X11
static void maybe_update_locate_pointer_keygrab (MetaDisplay *display,
gboolean grab);
#endif
static GHashTable *key_handlers; static GHashTable *key_handlers;
static GHashTable *external_grabs; static GHashTable *external_grabs;
@ -901,44 +893,6 @@ rebuild_special_bindings (MetaKeyBindingManager *keys)
keys->locate_pointer_key_combo = combo; keys->locate_pointer_key_combo = combo;
} }
#ifdef HAVE_X11
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);
}
#endif
static MetaKeyBinding * static MetaKeyBinding *
get_keybinding (MetaKeyBindingManager *keys, get_keybinding (MetaKeyBindingManager *keys,
MetaResolvedKeyCombo *resolved_combo) MetaResolvedKeyCombo *resolved_combo)
@ -1167,7 +1121,7 @@ reload_keybindings (MetaDisplay *display)
MetaKeyBindingManager *keys = &display->key_binding_manager; MetaKeyBindingManager *keys = &display->key_binding_manager;
#ifdef HAVE_X11 #ifdef HAVE_X11
ungrab_key_bindings (display); meta_x11_keybindings_ungrab_key_bindings (display);
#endif #endif
/* Deciphering the modmap depends on the loaded keysyms to find out /* Deciphering the modmap depends on the loaded keysyms to find out
@ -1178,104 +1132,10 @@ reload_keybindings (MetaDisplay *display)
reload_combos (keys); reload_combos (keys);
#ifdef HAVE_X11 #ifdef HAVE_X11
grab_key_bindings (display); meta_x11_keybindings_grab_key_bindings (display);
#endif #endif
} }
#ifdef HAVE_X11
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,
MetaWindow *window,
gboolean grab,
gboolean sync,
int button,
int modmask)
{
MetaBackendX11 *backend;
Display *xdisplay;
unsigned char mask_bits[XIMaskLen (XI_LASTEVENT)] = { 0 };
XIEventMask mask = { XIAllMasterDevices, sizeof (mask_bits), mask_bits };
Window xwindow;
GArray *mods;
MetaFrame *frame;
if (meta_is_wayland_compositor ())
return;
if (window->client_type != META_WINDOW_CLIENT_TYPE_X11)
return;
backend = META_BACKEND_X11 (keys->backend);
xdisplay = meta_backend_x11_get_xdisplay (backend);
XISetMask (mask.mask, XI_ButtonPress);
XISetMask (mask.mask, XI_ButtonRelease);
XISetMask (mask.mask, XI_Motion);
mods = calc_grab_modifiers (keys, modmask);
mtk_x11_error_trap_push (xdisplay);
frame = meta_window_x11_get_frame (window);
if (frame)
xwindow = frame->xwindow;
else
xwindow = meta_window_x11_get_xwindow (window);
/* 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);
XSync (xdisplay, False);
mtk_x11_error_trap_pop (xdisplay);
g_array_free (mods, TRUE);
}
#endif
ClutterModifierType ClutterModifierType
meta_display_get_compositor_modifiers (MetaDisplay *display) meta_display_get_compositor_modifiers (MetaDisplay *display)
{ {
@ -1283,71 +1143,6 @@ meta_display_get_compositor_modifiers (MetaDisplay *display)
return keys->window_grab_modifiers; return keys->window_grab_modifiers;
} }
#ifdef HAVE_X11
static void
meta_change_buttons_grab (MetaKeyBindingManager *keys,
MetaWindow *window,
gboolean grab,
gboolean sync,
int modmask)
{
#define MAX_BUTTON 3
int i;
for (i = 1; i <= MAX_BUTTON; i++)
meta_change_button_grab (keys, window, grab, sync, i, modmask);
}
void
meta_display_grab_window_buttons (MetaDisplay *display,
MetaWindow *window)
{
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 %s", window->desc);
/* 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, window, 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, window,
TRUE,
FALSE,
1, keys->window_grab_modifiers | CLUTTER_SHIFT_MASK);
}
}
void
meta_display_ungrab_window_buttons (MetaDisplay *display,
MetaWindow *window)
{
MetaKeyBindingManager *keys = &display->key_binding_manager;
if (keys->window_grab_modifiers == 0)
return;
meta_change_buttons_grab (keys, window, FALSE, FALSE,
keys->window_grab_modifiers);
}
#endif
static void static void
update_window_grab_modifiers (MetaDisplay *display) update_window_grab_modifiers (MetaDisplay *display)
{ {
@ -1365,47 +1160,6 @@ update_window_grab_modifiers (MetaDisplay *display)
} }
} }
#ifdef HAVE_X11
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, 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, FALSE, FALSE, XIAnyModifier);
window->have_focus_click_grab = FALSE;
}
#endif
static void static void
prefs_changed_callback (MetaPreference pref, prefs_changed_callback (MetaPreference pref,
void *data) void *data)
@ -1417,19 +1171,19 @@ prefs_changed_callback (MetaPreference pref,
{ {
case META_PREF_LOCATE_POINTER: case META_PREF_LOCATE_POINTER:
#ifdef HAVE_X11 #ifdef HAVE_X11
maybe_update_locate_pointer_keygrab (display, meta_x11_keybindings_maybe_update_locate_pointer_keygrab (display,
meta_prefs_is_locate_pointer_enabled()); meta_prefs_is_locate_pointer_enabled ());
#endif #endif
break; break;
case META_PREF_KEYBINDINGS: case META_PREF_KEYBINDINGS:
#ifdef HAVE_X11 #ifdef HAVE_X11
ungrab_key_bindings (display); meta_x11_keybindings_ungrab_key_bindings (display);
#endif #endif
rebuild_key_binding_table (keys); rebuild_key_binding_table (keys);
rebuild_special_bindings (keys); rebuild_special_bindings (keys);
reload_combos (keys); reload_combos (keys);
#ifdef HAVE_X11 #ifdef HAVE_X11
grab_key_bindings (display); meta_x11_keybindings_grab_key_bindings (display);
#endif #endif
break; break;
case META_PREF_MOUSE_BUTTON_MODS: case META_PREF_MOUSE_BUTTON_MODS:
@ -1441,7 +1195,7 @@ prefs_changed_callback (MetaPreference pref,
for (l = windows; l; l = l->next) for (l = windows; l; l = l->next)
{ {
MetaWindow *w = l->data; MetaWindow *w = l->data;
meta_display_ungrab_window_buttons (display, w); meta_x11_keybindings_ungrab_window_buttons (&display->key_binding_manager, w);
} }
#endif #endif
@ -1452,7 +1206,7 @@ prefs_changed_callback (MetaPreference pref,
{ {
MetaWindow *w = l->data; MetaWindow *w = l->data;
if (w->type != META_WINDOW_DOCK) if (w->type != META_WINDOW_DOCK)
meta_display_grab_window_buttons (display, w); meta_x11_keybindings_grab_window_buttons (&display->key_binding_manager, w);
} }
g_slist_free (windows); g_slist_free (windows);
@ -1463,7 +1217,6 @@ prefs_changed_callback (MetaPreference pref,
} }
} }
void void
meta_display_shutdown_keys (MetaDisplay *display) meta_display_shutdown_keys (MetaDisplay *display)
{ {
@ -1477,247 +1230,6 @@ meta_display_shutdown_keys (MetaDisplay *display)
clear_active_keyboard_layouts (keys); clear_active_keyboard_layouts (keys);
} }
/* Grab/ungrab, ignoring all annoying modifiers like NumLock etc. */
#ifdef HAVE_X11
static void
meta_change_keygrab (MetaKeyBindingManager *keys,
Window xwindow,
gboolean grab,
MetaResolvedKeyCombo *resolved_combo)
{
MetaBackendX11 *backend_x11;
Display *xdisplay;
GArray *mods;
int i;
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;
backend_x11 = META_BACKEND_X11 (keys->backend);
xdisplay = meta_backend_x11_get_xdisplay (backend_x11);
/* 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);
mtk_x11_error_trap_push (xdisplay);
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);
}
XSync (xdisplay, False);
mtk_x11_error_trap_pop (xdisplay);
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;
MetaWindowX11Private *priv;
if (meta_is_wayland_compositor ())
return;
priv = meta_window_x11_get_private (META_WINDOW_X11 (window));
if (window->type == META_WINDOW_DOCK
|| window->override_redirect)
{
if (priv->keys_grabbed)
change_window_keygrabs (keys, meta_window_x11_get_xwindow (window), FALSE);
priv->keys_grabbed = FALSE;
return;
}
if (priv->keys_grabbed)
{
if (priv->frame && !priv->grab_on_frame)
change_window_keygrabs (keys, meta_window_x11_get_xwindow (window), FALSE);
else if (priv->frame == NULL &&
priv->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);
priv->keys_grabbed = TRUE;
priv->grab_on_frame = priv->frame != NULL;
}
void
meta_window_ungrab_keys (MetaWindow *window)
{
MetaWindowX11Private *priv;
if (meta_is_wayland_compositor ())
return;
priv = meta_window_x11_get_private (META_WINDOW_X11 (window));
if (priv->keys_grabbed)
{
MetaDisplay *display = window->display;
MetaKeyBindingManager *keys = &display->key_binding_manager;
MetaFrame *frame = meta_window_x11_get_frame (window);
if (priv->grab_on_frame && frame != NULL)
change_window_keygrabs (keys, frame->xwindow, FALSE);
else if (!priv->grab_on_frame)
change_window_keygrabs (keys, meta_window_x11_get_xwindow (window), FALSE);
priv->keys_grabbed = FALSE;
}
}
#endif
static void static void
handle_external_grab (MetaDisplay *display, handle_external_grab (MetaDisplay *display,
MetaWindow *window, MetaWindow *window,
@ -1768,8 +1280,8 @@ meta_display_grab_accelerator (MetaDisplay *display,
#ifdef HAVE_X11 #ifdef HAVE_X11
if (!meta_is_wayland_compositor ()) if (!meta_is_wayland_compositor ())
{ {
meta_change_keygrab (keys, display->x11_display->xroot, meta_x11_keybindings_change_keygrab (keys, display->x11_display->xroot,
TRUE, &resolved_combo); TRUE, &resolved_combo);
} }
#endif #endif
@ -1820,8 +1332,8 @@ meta_display_ungrab_accelerator (MetaDisplay *display,
#ifdef HAVE_X11 #ifdef HAVE_X11
if (!meta_is_wayland_compositor ()) if (!meta_is_wayland_compositor ())
{ {
meta_change_keygrab (keys, display->x11_display->xroot, meta_x11_keybindings_change_keygrab (keys, display->x11_display->xroot,
FALSE, &binding->resolved_combo); FALSE, &binding->resolved_combo);
} }
#endif #endif

View File

@ -87,6 +87,7 @@
#include "x11/meta-x11-display-private.h" #include "x11/meta-x11-display-private.h"
#include "x11/meta-x11-frame.h" #include "x11/meta-x11-frame.h"
#include "x11/meta-x11-group-private.h" #include "x11/meta-x11-group-private.h"
#include "x11/meta-x11-keybindings-private.h"
#include "x11/window-props.h" #include "x11/window-props.h"
#include "x11/window-x11-private.h" #include "x11/window-x11-private.h"
#include "x11/window-x11.h" #include "x11/window-x11.h"
@ -5274,10 +5275,12 @@ meta_window_set_focused_internal (MetaWindow *window,
if (meta_prefs_get_focus_mode () == G_DESKTOP_FOCUS_MODE_CLICK || if (meta_prefs_get_focus_mode () == G_DESKTOP_FOCUS_MODE_CLICK ||
!meta_prefs_get_raise_on_click()) !meta_prefs_get_raise_on_click())
{ {
meta_display_ungrab_focus_window_button (window->display, window); meta_x11_keybindings_ungrab_focus_window_button (&window->display->key_binding_manager,
window);
/* Since we ungrab with XIAnyModifier above, all button /* Since we ungrab with XIAnyModifier above, all button
grabs go way so we need to re-grab the window buttons. */ grabs go way so we need to re-grab the window buttons. */
meta_display_grab_window_buttons (window->display, window); meta_x11_keybindings_grab_window_buttons (&window->display->key_binding_manager,
window);
} }
#endif #endif
@ -5303,7 +5306,7 @@ meta_window_set_focused_internal (MetaWindow *window,
#ifdef HAVE_X11 #ifdef HAVE_X11
if (meta_prefs_get_focus_mode () == G_DESKTOP_FOCUS_MODE_CLICK || if (meta_prefs_get_focus_mode () == G_DESKTOP_FOCUS_MODE_CLICK ||
!meta_prefs_get_raise_on_click ()) !meta_prefs_get_raise_on_click ())
meta_display_grab_focus_window_button (window->display, window); meta_x11_keybindings_grab_focus_window_button (&window->display->key_binding_manager, window);
#endif #endif
} }
} }

View File

@ -482,6 +482,8 @@ if have_x11_client
'x11/meta-x11-frame.h', 'x11/meta-x11-frame.h',
'x11/meta-x11-group.c', 'x11/meta-x11-group.c',
'x11/meta-x11-group-private.h', 'x11/meta-x11-group-private.h',
'x11/meta-x11-keybindings-private.h',
'x11/meta-x11-keybindings.c',
'x11/meta-x11-selection.c', 'x11/meta-x11-selection.c',
'x11/meta-x11-selection-private.h', 'x11/meta-x11-selection-private.h',
'x11/meta-x11-selection-input-stream.c', 'x11/meta-x11-selection-input-stream.c',

View File

@ -61,6 +61,7 @@
#include "x11/events.h" #include "x11/events.h"
#include "x11/group-props.h" #include "x11/group-props.h"
#include "x11/meta-x11-frame.h" #include "x11/meta-x11-frame.h"
#include "x11/meta-x11-keybindings-private.h"
#include "x11/meta-x11-selection-private.h" #include "x11/meta-x11-selection-private.h"
#include "x11/window-props.h" #include "x11/window-props.h"
#include "x11/window-x11.h" #include "x11/window-x11.h"

View File

@ -26,10 +26,10 @@
#include "backends/x11/meta-backend-x11.h" #include "backends/x11/meta-backend-x11.h"
#include "compositor/compositor-private.h" #include "compositor/compositor-private.h"
#include "core/bell.h" #include "core/bell.h"
#include "core/keybindings-private.h"
#include "mtk/mtk-x11.h" #include "mtk/mtk-x11.h"
#include "x11/meta-x11-display-private.h" #include "x11/meta-x11-display-private.h"
#include "x11/meta-x11-frame.h" #include "x11/meta-x11-frame.h"
#include "x11/meta-x11-keybindings-private.h"
#include "x11/window-props.h" #include "x11/window-props.h"
#include "x11/window-x11-private.h" #include "x11/window-x11-private.h"

View File

@ -0,0 +1,58 @@
/*
* Copyright (C) 2024 Bilal Elmoussaoui
*
* 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/>.
*/
#include "backends/x11/meta-backend-x11.h"
#include "core/keybindings-private.h"
#include "core/window-private.h"
#include "mtk/mtk-x11-errors.h"
#include "x11/meta-x11-display-private.h"
#include "x11/meta-x11-frame.h"
#include "x11/window-x11-private.h"
#pragma once
void meta_x11_keybindings_grab_window_buttons (MetaKeyBindingManager *keys,
MetaWindow *window);
void meta_x11_keybindings_ungrab_window_buttons (MetaKeyBindingManager *keys,
MetaWindow *window);
void meta_x11_keybindings_grab_focus_window_button (MetaKeyBindingManager *keys,
MetaWindow *window);
void meta_x11_keybindings_ungrab_focus_window_button (MetaKeyBindingManager *keys,
MetaWindow *window);
void meta_x11_display_grab_keys (MetaX11Display *x11_display);
void meta_x11_display_ungrab_keys (MetaX11Display *x11_display);
void meta_x11_keybindings_change_keygrab (MetaKeyBindingManager *keys,
Window xwindow,
gboolean grab,
MetaResolvedKeyCombo *resolved_combo);
void meta_x11_keybindings_grab_key_bindings (MetaDisplay *display);
void meta_x11_keybindings_ungrab_key_bindings (MetaDisplay *display);
void meta_x11_keybindings_maybe_update_locate_pointer_keygrab (MetaDisplay *display,
gboolean grab);
void meta_window_grab_keys (MetaWindow *window);
void meta_window_ungrab_keys (MetaWindow *window);

View File

@ -0,0 +1,483 @@
/*
* Copyright (C) 2024 Bilal Elmoussaoui
*
* 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/>.
*/
/* Grab/ungrab, ignoring all annoying modifiers like NumLock etc. */
#include "meta-x11-keybindings-private.h"
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,
MetaWindow *window,
gboolean grab,
gboolean sync,
int button,
int modmask)
{
MetaBackendX11 *backend;
Display *xdisplay;
unsigned char mask_bits[XIMaskLen (XI_LASTEVENT)] = { 0 };
XIEventMask mask = { XIAllMasterDevices, sizeof (mask_bits), mask_bits };
Window xwindow;
GArray *mods;
MetaFrame *frame;
if (meta_is_wayland_compositor ())
return;
if (window->client_type != META_WINDOW_CLIENT_TYPE_X11)
return;
backend = META_BACKEND_X11 (keys->backend);
xdisplay = meta_backend_x11_get_xdisplay (backend);
XISetMask (mask.mask, XI_ButtonPress);
XISetMask (mask.mask, XI_ButtonRelease);
XISetMask (mask.mask, XI_Motion);
mods = calc_grab_modifiers (keys, modmask);
mtk_x11_error_trap_push (xdisplay);
frame = meta_window_x11_get_frame (window);
if (frame)
xwindow = frame->xwindow;
else
xwindow = meta_window_x11_get_xwindow (window);
/* 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);
XSync (xdisplay, False);
mtk_x11_error_trap_pop (xdisplay);
g_array_free (mods, TRUE);
}
static void
meta_change_buttons_grab (MetaKeyBindingManager *keys,
MetaWindow *window,
gboolean grab,
gboolean sync,
int modmask)
{
#define MAX_BUTTON 3
int i;
for (i = 1; i <= MAX_BUTTON; i++)
meta_change_button_grab (keys, window, grab, sync, i, modmask);
}
void
meta_x11_keybindings_change_keygrab (MetaKeyBindingManager *keys,
Window xwindow,
gboolean grab,
MetaResolvedKeyCombo *resolved_combo)
{
MetaBackendX11 *backend_x11;
Display *xdisplay;
GArray *mods;
int i;
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;
backend_x11 = META_BACKEND_X11 (keys->backend);
xdisplay = meta_backend_x11_get_xdisplay (backend_x11);
/* 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);
mtk_x11_error_trap_push (xdisplay);
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);
}
XSync (xdisplay, False);
mtk_x11_error_trap_pop (xdisplay);
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_x11_keybindings_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);
}
void
meta_x11_keybindings_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_x11_keybindings_change_keygrab (keys, display->x11_display->xroot,
(!!grab & !!meta_prefs_is_locate_pointer_enabled ()),
&keys->locate_pointer_resolved_key_combo);
}
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;
MetaWindowX11Private *priv;
if (meta_is_wayland_compositor ())
return;
priv = meta_window_x11_get_private (META_WINDOW_X11 (window));
if (window->type == META_WINDOW_DOCK
|| window->override_redirect)
{
if (priv->keys_grabbed)
change_window_keygrabs (keys, meta_window_x11_get_xwindow (window), FALSE);
priv->keys_grabbed = FALSE;
return;
}
if (priv->keys_grabbed)
{
if (priv->frame && !priv->grab_on_frame)
change_window_keygrabs (keys, meta_window_x11_get_xwindow (window), FALSE);
else if (priv->frame == NULL &&
priv->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);
priv->keys_grabbed = TRUE;
priv->grab_on_frame = priv->frame != NULL;
}
void
meta_window_ungrab_keys (MetaWindow *window)
{
MetaWindowX11Private *priv;
if (meta_is_wayland_compositor ())
return;
priv = meta_window_x11_get_private (META_WINDOW_X11 (window));
if (priv->keys_grabbed)
{
MetaDisplay *display = window->display;
MetaKeyBindingManager *keys = &display->key_binding_manager;
MetaFrame *frame = meta_window_x11_get_frame (window);
if (priv->grab_on_frame && frame != NULL)
change_window_keygrabs (keys, frame->xwindow, FALSE);
else if (!priv->grab_on_frame)
change_window_keygrabs (keys, meta_window_x11_get_xwindow (window), FALSE);
priv->keys_grabbed = FALSE;
}
}
void
meta_x11_keybindings_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);
}
void
meta_x11_keybindings_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);
}
void
meta_x11_keybindings_grab_window_buttons (MetaKeyBindingManager *keys,
MetaWindow *window)
{
/* 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 %s", window->desc);
/* 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, window, 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, window,
TRUE,
FALSE,
1, keys->window_grab_modifiers | CLUTTER_SHIFT_MASK);
}
}
void
meta_x11_keybindings_ungrab_window_buttons (MetaKeyBindingManager *keys,
MetaWindow *window)
{
if (keys->window_grab_modifiers == 0)
return;
meta_change_buttons_grab (keys, window, FALSE, FALSE,
keys->window_grab_modifiers);
}
void
meta_x11_keybindings_grab_focus_window_button (MetaKeyBindingManager *keys,
MetaWindow *window)
{
/* 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, TRUE, TRUE, XIAnyModifier);
window->have_focus_click_grab = TRUE;
}
void
meta_x11_keybindings_ungrab_focus_window_button (MetaKeyBindingManager *keys,
MetaWindow *window)
{
meta_verbose ("Ungrabbing unfocused window buttons for %s", window->desc);
if (!window->have_focus_click_grab)
return;
meta_change_buttons_grab (keys, window, FALSE, FALSE, XIAnyModifier);
window->have_focus_click_grab = FALSE;
}
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_x11_keybindings_change_keygrab (keys, x11_display->xroot,
grab, &keys->overlay_resolved_key_combo);
meta_x11_keybindings_maybe_update_locate_pointer_keygrab (x11_display->display,
grab);
for (i = 0; i < keys->n_iso_next_group_combos; i++)
meta_x11_keybindings_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;
}

View File

@ -55,6 +55,7 @@
#include "x11/meta-x11-display-private.h" #include "x11/meta-x11-display-private.h"
#include "x11/meta-x11-frame.h" #include "x11/meta-x11-frame.h"
#include "x11/meta-x11-group-private.h" #include "x11/meta-x11-group-private.h"
#include "x11/meta-x11-keybindings-private.h"
#include "x11/session.h" #include "x11/session.h"
#include "x11/window-props.h" #include "x11/window-props.h"
#include "x11/xprops.h" #include "x11/xprops.h"
@ -714,8 +715,10 @@ meta_window_x11_unmanage (MetaWindow *window)
XShapeSelectInput (x11_display->xdisplay, priv->xwindow, NoEventMask); XShapeSelectInput (x11_display->xdisplay, priv->xwindow, NoEventMask);
meta_window_ungrab_keys (window); meta_window_ungrab_keys (window);
meta_display_ungrab_window_buttons (window->display, window); meta_x11_keybindings_ungrab_window_buttons (&window->display->key_binding_manager,
meta_display_ungrab_focus_window_button (window->display, window); window);
meta_x11_keybindings_ungrab_focus_window_button (&window->display->key_binding_manager,
window);
mtk_x11_error_trap_pop (x11_display->xdisplay); mtk_x11_error_trap_pop (x11_display->xdisplay);
@ -4075,8 +4078,8 @@ meta_window_x11_new (MetaDisplay *display,
meta_window_grab_keys (window); meta_window_grab_keys (window);
if (window->type != META_WINDOW_DOCK && !window->override_redirect) if (window->type != META_WINDOW_DOCK && !window->override_redirect)
{ {
meta_display_grab_window_buttons (window->display, window); meta_x11_keybindings_grab_window_buttons (&window->display->key_binding_manager, window);
meta_display_grab_focus_window_button (window->display, window); meta_x11_keybindings_grab_focus_window_button (&window->display->key_binding_manager, window);
} }
mtk_x11_error_trap_pop (x11_display->xdisplay); /* pop the XSync()-reducing trap */ mtk_x11_error_trap_pop (x11_display->xdisplay); /* pop the XSync()-reducing trap */