Skip to content

Commit 73626ef

Browse files
garnachoMarge Bot
authored and
Marge Bot
committed
compositor/x11: Take over issuing passive key grabs
Handle passive key grabs for all keybindings on client windows and the root window at MetaCompositorX11, ensuring preferences are honored. In order to do this, some per-window state tracking has to be performed on window type and decorated changes, in order to ensure only windows of the expected type get keygrabs, and these keygrabs happen always on the toplevel window. This drops a bit of code in src/core and src/x11 that were actually specific to the c-m X11 backend. Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/4191>
1 parent 89daa18 commit 73626ef

13 files changed

+305
-473
lines changed

src/compositor/meta-compositor-x11.c

Lines changed: 234 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ struct _MetaCompositorX11
5252

5353
gboolean frame_has_updated_xsurfaces;
5454
gboolean have_x11_sync_object;
55+
gboolean have_root_window_key_grab;
5556

5657
MetaWindow *unredirected_window;
5758
MetaWindow *focus_window;
@@ -61,8 +62,17 @@ struct _MetaCompositorX11
6162
int64_t xserver_time_offset_us;
6263
};
6364

65+
typedef struct
66+
{
67+
MetaCompositorX11 *compositor_x11;
68+
Window xwindow;
69+
gboolean grab;
70+
} KeyGrabData;
71+
6472
G_DEFINE_TYPE (MetaCompositorX11, meta_compositor_x11, META_TYPE_COMPOSITOR)
6573

74+
static void meta_compositor_x11_grab_root_window_keys (MetaCompositorX11 *compositor_x11);
75+
6676
static void
6777
process_damage (MetaCompositorX11 *compositor_x11,
6878
XDamageNotifyEvent *damage_xevent,
@@ -202,6 +212,8 @@ meta_compositor_x11_manage (MetaCompositor *compositor,
202212

203213
meta_x11_display_redirect_windows (x11_display, display);
204214

215+
meta_compositor_x11_grab_root_window_keys (compositor_x11);
216+
205217
return TRUE;
206218
}
207219

@@ -528,6 +540,135 @@ meta_compositor_x11_ungrab_focus_window_button (MetaCompositorX11 *compositor_x1
528540
META_GRAB_MODE_ASYNC, 0);
529541
}
530542

543+
static void
544+
meta_compositor_x11_change_keygrab (MetaCompositorX11 *compositor_x11,
545+
Window xwindow,
546+
gboolean grab,
547+
MetaResolvedKeyCombo *resolved_combo)
548+
{
549+
MetaBackend *backend =
550+
meta_compositor_get_backend (META_COMPOSITOR (compositor_x11));
551+
MetaBackendX11 *backend_x11 = META_BACKEND_X11 (backend);
552+
int i;
553+
554+
for (i = 0; i < resolved_combo->len; i++)
555+
{
556+
xkb_keycode_t keycode = resolved_combo->keycodes[i];
557+
558+
meta_topic (META_DEBUG_KEYBINDINGS,
559+
"%s keybinding keycode %d mask 0x%x on 0x%lx",
560+
grab ? "Grabbing" : "Ungrabbing",
561+
keycode, resolved_combo->mask, xwindow);
562+
563+
if (grab)
564+
{
565+
meta_backend_x11_passive_key_grab (backend_x11, xwindow,
566+
keycode,
567+
META_GRAB_MODE_SYNC,
568+
resolved_combo->mask);
569+
}
570+
else
571+
{
572+
meta_backend_x11_passive_key_ungrab (backend_x11, xwindow,
573+
keycode,
574+
resolved_combo->mask);
575+
}
576+
}
577+
}
578+
579+
static void
580+
passive_key_grab_foreach (MetaDisplay *display,
581+
MetaKeyBindingFlags flags,
582+
MetaResolvedKeyCombo *resolved_combo,
583+
gpointer user_data)
584+
{
585+
MetaX11Display *x11_display = display->x11_display;
586+
Window xroot = x11_display->xroot;
587+
KeyGrabData *data = user_data;
588+
589+
/* Ignore the key bindings marked as META_KEY_BINDING_NO_AUTO_GRAB. */
590+
if ((flags & META_KEY_BINDING_NO_AUTO_GRAB) != 0 &&
591+
data->grab)
592+
return;
593+
594+
if ((flags & META_KEY_BINDING_PER_WINDOW) != 0 &&
595+
data->xwindow == xroot)
596+
return;
597+
598+
meta_compositor_x11_change_keygrab (data->compositor_x11,
599+
data->xwindow,
600+
data->grab,
601+
resolved_combo);
602+
}
603+
604+
static void
605+
meta_compositor_x11_grab_window_keys (MetaCompositorX11 *compositor_x11,
606+
Window xwindow)
607+
{
608+
MetaCompositor *compositor = META_COMPOSITOR (compositor_x11);
609+
MetaDisplay *display = meta_compositor_get_display (compositor);
610+
KeyGrabData data = { compositor_x11, xwindow, TRUE };
611+
612+
meta_display_keybinding_foreach (display,
613+
passive_key_grab_foreach,
614+
&data);
615+
}
616+
617+
static void
618+
meta_compositor_x11_ungrab_window_keys (MetaCompositorX11 *compositor_x11,
619+
Window xwindow)
620+
{
621+
MetaCompositor *compositor = META_COMPOSITOR (compositor_x11);
622+
MetaDisplay *display = meta_compositor_get_display (compositor);
623+
KeyGrabData data = { compositor_x11, xwindow, FALSE };
624+
625+
meta_display_keybinding_foreach (display,
626+
passive_key_grab_foreach,
627+
&data);
628+
}
629+
630+
static void
631+
meta_compositor_x11_grab_root_window_keys (MetaCompositorX11 *compositor_x11)
632+
{
633+
MetaCompositor *compositor = META_COMPOSITOR (compositor_x11);
634+
MetaDisplay *display = meta_compositor_get_display (compositor);
635+
MetaX11Display *x11_display = display->x11_display;
636+
Window xroot = x11_display->xroot;
637+
KeyGrabData data = { compositor_x11, xroot, TRUE };
638+
639+
if (compositor_x11->have_root_window_key_grab)
640+
return;
641+
642+
meta_display_keybinding_foreach (display,
643+
passive_key_grab_foreach,
644+
&data);
645+
compositor_x11->have_root_window_key_grab = TRUE;
646+
}
647+
648+
static void
649+
meta_compositor_x11_ungrab_root_window_keys (MetaCompositorX11 *compositor_x11)
650+
{
651+
MetaCompositor *compositor = META_COMPOSITOR (compositor_x11);
652+
MetaDisplay *display = meta_compositor_get_display (compositor);
653+
MetaX11Display *x11_display = display->x11_display;
654+
Window xroot = x11_display->xroot;
655+
KeyGrabData data = { compositor_x11, xroot, FALSE };
656+
657+
if (!compositor_x11->have_root_window_key_grab)
658+
return;
659+
660+
meta_display_keybinding_foreach (display,
661+
passive_key_grab_foreach,
662+
&data);
663+
compositor_x11->have_root_window_key_grab = FALSE;
664+
}
665+
666+
static gboolean
667+
should_have_passive_grab (MetaWindow *window)
668+
{
669+
return window->type != META_WINDOW_DOCK && !window->override_redirect;
670+
}
671+
531672
static void
532673
on_focus_window_change (MetaDisplay *display,
533674
GParamSpec *pspec,
@@ -540,7 +681,7 @@ on_focus_window_change (MetaDisplay *display,
540681
old_focus = compositor_x11->focus_window;
541682
focus = meta_display_get_focus_window (display);
542683

543-
if (focus && (focus->type == META_WINDOW_DOCK || focus->override_redirect))
684+
if (focus && !should_have_passive_grab (focus))
544685
focus = NULL;
545686

546687
if (focus == old_focus)
@@ -579,6 +720,51 @@ on_focus_window_change (MetaDisplay *display,
579720
compositor_x11->focus_window = focus;
580721
}
581722

723+
static void
724+
on_window_type_changed (MetaWindow *window,
725+
GParamSpec *pspec,
726+
MetaCompositorX11 *compositor_x11)
727+
{
728+
Window xwindow;
729+
730+
xwindow = meta_window_x11_get_toplevel_xwindow (window);
731+
732+
if (should_have_passive_grab (window))
733+
meta_compositor_x11_grab_window_keys (compositor_x11, xwindow);
734+
else
735+
meta_compositor_x11_ungrab_window_keys (compositor_x11, xwindow);
736+
}
737+
738+
static void
739+
on_window_decorated_changed (MetaWindow *window,
740+
GParamSpec *pspec,
741+
MetaCompositorX11 *compositor_x11)
742+
{
743+
Window old_effective_toplevel = None, xwindow;
744+
745+
/* We must clean up the passive grab on the prior effective toplevel */
746+
if (window->decorated)
747+
{
748+
old_effective_toplevel = meta_window_x11_get_xwindow (window);
749+
}
750+
else
751+
{
752+
MetaFrame *frame;
753+
754+
frame = meta_window_x11_get_frame (window);
755+
old_effective_toplevel = meta_frame_get_xwindow (frame);
756+
}
757+
758+
if (old_effective_toplevel != None)
759+
{
760+
meta_compositor_x11_ungrab_window_keys (compositor_x11,
761+
old_effective_toplevel);
762+
}
763+
764+
xwindow = meta_window_x11_get_toplevel_xwindow (window);
765+
meta_compositor_x11_grab_window_keys (compositor_x11, xwindow);
766+
}
767+
582768
static void
583769
meta_compositor_x11_before_paint (MetaCompositor *compositor,
584770
MetaCompositorView *compositor_view)
@@ -614,9 +800,24 @@ meta_compositor_x11_add_window (MetaCompositor *compositor,
614800
{
615801
MetaCompositorX11 *compositor_x11 = META_COMPOSITOR_X11 (compositor);
616802
MetaCompositorClass *parent_class;
803+
Window xwindow;
617804

618-
if (window->type != META_WINDOW_DOCK && !window->override_redirect)
619-
meta_compositor_x11_grab_focus_window_button (compositor_x11, window);
805+
if (should_have_passive_grab (window))
806+
{
807+
xwindow = meta_window_x11_get_toplevel_xwindow (window);
808+
809+
meta_compositor_x11_grab_focus_window_button (compositor_x11, window);
810+
meta_compositor_x11_grab_window_keys (compositor_x11, xwindow);
811+
812+
g_signal_connect_object (window, "notify::window-type",
813+
G_CALLBACK (on_window_type_changed),
814+
compositor,
815+
G_CONNECT_DEFAULT);
816+
g_signal_connect_object (window, "notify::decorated",
817+
G_CALLBACK (on_window_decorated_changed),
818+
compositor,
819+
G_CONNECT_DEFAULT);
820+
}
620821

621822
parent_class = META_COMPOSITOR_CLASS (meta_compositor_x11_parent_class);
622823
parent_class->add_window (compositor, window);
@@ -628,6 +829,7 @@ meta_compositor_x11_remove_window (MetaCompositor *compositor,
628829
{
629830
MetaCompositorX11 *compositor_x11 = META_COMPOSITOR_X11 (compositor);
630831
MetaCompositorClass *parent_class;
832+
Window xwindow;
631833

632834
if (compositor_x11->unredirected_window == window)
633835
set_unredirected_window (compositor_x11, NULL);
@@ -637,11 +839,19 @@ meta_compositor_x11_remove_window (MetaCompositor *compositor,
637839
meta_compositor_x11_ungrab_window_buttons (compositor_x11, window);
638840
compositor_x11->focus_window = NULL;
639841
}
640-
else if (window->type != META_WINDOW_DOCK && !window->override_redirect)
842+
else if (should_have_passive_grab (window))
641843
{
642844
meta_compositor_x11_ungrab_focus_window_button (compositor_x11, window);
643845
}
644846

847+
xwindow = meta_window_x11_get_toplevel_xwindow (window);
848+
meta_compositor_x11_ungrab_window_keys (compositor_x11, xwindow);
849+
850+
g_signal_handlers_disconnect_by_func (window, on_window_type_changed,
851+
compositor);
852+
g_signal_handlers_disconnect_by_func (window, on_window_decorated_changed,
853+
compositor);
854+
645855
parent_class = META_COMPOSITOR_CLASS (meta_compositor_x11_parent_class);
646856
parent_class->remove_window (compositor, window);
647857
}
@@ -745,7 +955,24 @@ meta_compositor_x11_notify_mapping_change (MetaCompositor *compositor,
745955
}
746956

747957
break;
748-
default:
958+
case META_MAPPING_TYPE_KEY:
959+
windows = meta_display_list_windows (display, META_LIST_DEFAULT);
960+
961+
if (grab)
962+
meta_compositor_x11_grab_root_window_keys (compositor_x11);
963+
else
964+
meta_compositor_x11_ungrab_root_window_keys (compositor_x11);
965+
966+
for (l = windows; l; l = l->next)
967+
{
968+
MetaWindow *window = l->data;
969+
Window xwindow = meta_window_x11_get_toplevel_xwindow (window);
970+
971+
if (grab)
972+
meta_compositor_x11_grab_window_keys (compositor_x11, xwindow);
973+
else
974+
meta_compositor_x11_ungrab_window_keys (compositor_x11, xwindow);
975+
}
749976
break;
750977
}
751978
}
@@ -806,6 +1033,8 @@ meta_compositor_x11_dispose (GObject *object)
8061033
g_clear_signal_handler (&compositor_x11->after_update_handler_id, stage);
8071034
g_clear_signal_handler (&compositor_x11->focus_window_handler_id, display);
8081035

1036+
meta_compositor_x11_ungrab_root_window_keys (compositor_x11);
1037+
8091038
G_OBJECT_CLASS (meta_compositor_x11_parent_class)->dispose (object);
8101039
}
8111040

src/compositor/meta-window-drag.c

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@
2828

2929
#ifdef HAVE_X11_CLIENT
3030
#include "x11/meta-x11-frame.h"
31-
#include "x11/meta-x11-keybindings-private.h"
3231
#include "x11/window-x11.h"
3332
#endif
3433

@@ -402,12 +401,6 @@ meta_window_drag_end (MetaWindowDrag *window_drag)
402401
g_clear_signal_handler (&window_drag->unmanaged_id, grab_window);
403402
g_clear_signal_handler (&window_drag->size_changed_id, grab_window);
404403

405-
meta_topic (META_DEBUG_WINDOW_OPS,
406-
"Restoring passive key grabs on %s", grab_window->desc);
407-
#ifdef HAVE_X11
408-
meta_window_grab_keys (grab_window);
409-
#endif
410-
411404
meta_display_set_cursor (display, META_CURSOR_DEFAULT);
412405

413406
clear_move_resize_later (window_drag);
@@ -1889,11 +1882,6 @@ meta_window_drag_begin (MetaWindowDrag *window_drag,
18891882
}
18901883
}
18911884

1892-
/* Temporarily release the passive key grabs on the window */
1893-
#ifdef HAVE_X11
1894-
meta_window_ungrab_keys (grab_window);
1895-
#endif
1896-
18971885
g_set_object (&window_drag->effective_grab_window, grab_window);
18981886
window_drag->unmanaged_id =
18991887
g_signal_connect (grab_window, "unmanaged",

src/core/keybindings-private.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,11 @@ typedef struct
131131
ClutterModifierType window_grab_modifiers;
132132
} MetaKeyBindingManager;
133133

134+
typedef void (* MetaKeyBindingForeach) (MetaDisplay *display,
135+
MetaKeyBindingFlags flags,
136+
MetaResolvedKeyCombo *resolved_key_binding,
137+
gpointer user_data);
138+
134139
void meta_display_init_keys (MetaDisplay *display);
135140
void meta_display_shutdown_keys (MetaDisplay *display);
136141
gboolean meta_keybindings_process_event (MetaDisplay *display,
@@ -153,3 +158,7 @@ gboolean meta_prefs_is_locate_pointer_enabled (void);
153158
gboolean meta_display_process_keybinding_event (MetaDisplay *display,
154159
const char *name,
155160
const ClutterEvent *event);
161+
162+
void meta_display_keybinding_foreach (MetaDisplay *display,
163+
MetaKeyBindingForeach func,
164+
gpointer user_data);

0 commit comments

Comments
 (0)