Index: mutter-45.1/src/core/display.c =================================================================== --- mutter-45.1.orig/src/core/display.c +++ mutter-45.1/src/core/display.c @@ -956,6 +956,8 @@ meta_display_new (MetaContext *context, display->check_fullscreen_later = 0; display->work_area_later = 0; + display->server_grab_count = 0; + display->mouse_mode = TRUE; /* Only relevant for mouse or sloppy focus */ display->current_time = META_CURRENT_TIME; @@ -1308,6 +1310,50 @@ meta_grab_op_is_moving (MetaGrabOp op) return !meta_grab_op_is_resizing (op); } +/* Grab/ungrab routines taken from fvwm. + * Calling this function will cause X to ignore all other clients until + * you ungrab. This may not be quite as bad as it sounds, yet there is + * agreement that avoiding server grabs except when they are clearly needed + * is a good thing. + * + * If you do use such grabs, please clearly explain the necessity for their + * usage in a comment. Try to keep their scope extremely limited. In + * particular, try to avoid emitting any signals or notifications while + * a grab is active (if the signal receiver tries to block on an X request + * from another client at this point, you will have a deadlock). + */ +void +meta_display_grab (MetaDisplay *display) +{ + if (display->server_grab_count == 0) + { + XGrabServer (display->x11_display->xdisplay); + } + display->server_grab_count += 1; + meta_verbose ("Grabbing display, grab count now %d\n", + display->server_grab_count); +} + +void +meta_display_ungrab (MetaDisplay *display) +{ + if (display->server_grab_count == 0) + meta_bug ("Ungrabbed non-grabbed server\n"); + + display->server_grab_count -= 1; + if (display->server_grab_count == 0) + { + /* FIXME we want to purge all pending "queued" stuff + * at this point, such as window hide/show + */ + XUngrabServer (display->x11_display->xdisplay); + XFlush (display->x11_display->xdisplay); + } + + meta_verbose ("Ungrabbing display, grab count now %d\n", + display->server_grab_count); +} + /** * meta_display_windows_are_interactable: * @op: A #MetaGrabOp Index: mutter-45.1/src/core/display-private.h =================================================================== --- mutter-45.1.orig/src/core/display-private.h +++ mutter-45.1/src/core/display-private.h @@ -95,6 +95,8 @@ struct _MetaDisplay GHashTable *stamps; GHashTable *wayland_windows; + int server_grab_count; + guint32 current_time; /* We maintain a sequence counter, incremented for each #MetaWindow @@ -179,6 +181,8 @@ struct _MetaDisplayClass MetaDisplay * meta_display_new (MetaContext *context, GError **error); +void meta_display_grab (MetaDisplay *display); +void meta_display_ungrab (MetaDisplay *display); #ifdef HAVE_X11_CLIENT void meta_display_manage_all_xwindows (MetaDisplay *display); #endif Index: mutter-45.1/src/core/keybindings.c =================================================================== --- mutter-45.1.orig/src/core/keybindings.c +++ mutter-45.1/src/core/keybindings.c @@ -1257,6 +1257,9 @@ meta_display_grab_window_buttons (MetaDi { MetaKeyBindingManager *keys = &display->key_binding_manager; + if (display->server_grab_count > 0) + return; + /* Grab Alt + button1 for moving window. * Grab Alt + button2 for resizing window. * Grab Alt + button3 for popping up window menu. @@ -1293,6 +1296,9 @@ meta_display_ungrab_window_buttons (Meta { MetaKeyBindingManager *keys = &display->key_binding_manager; + if (display->server_grab_count > 0) + return; + if (keys->window_grab_modifiers == 0) return; @@ -1323,6 +1329,9 @@ meta_display_grab_focus_window_button (M { MetaKeyBindingManager *keys = &display->key_binding_manager; + if (display->server_grab_count > 0) + return; + /* Grab button 1 for activating unfocused windows */ meta_verbose ("Grabbing unfocused window buttons for %s", window->desc); @@ -1347,6 +1356,9 @@ meta_display_ungrab_focus_window_button { MetaKeyBindingManager *keys = &display->key_binding_manager; + if (display->server_grab_count > 0) + return; + meta_verbose ("Ungrabbing unfocused window buttons for %s", window->desc); if (!window->have_focus_click_grab) @@ -1601,6 +1613,9 @@ meta_window_grab_keys (MetaWindow *wind if (meta_is_wayland_compositor ()) return; + if (display->server_grab_count > 0) + return; + if (window->type == META_WINDOW_DOCK || window->override_redirect) { @@ -1637,6 +1652,9 @@ meta_window_ungrab_keys (MetaWindow *wi MetaDisplay *display = window->display; MetaKeyBindingManager *keys = &display->key_binding_manager; + if (display->server_grab_count > 0) + return; + if (window->grab_on_frame && window->frame != NULL) change_window_keygrabs (keys, window->frame->xwindow, FALSE); Index: mutter-45.1/src/x11/meta-x11-display.c =================================================================== --- mutter-45.1.orig/src/x11/meta-x11-display.c +++ mutter-45.1/src/x11/meta-x11-display.c @@ -1990,7 +1990,7 @@ meta_x11_display_set_input_focus_interna * we know which is which by making two requests that the server will * process at the same time. */ - XGrabServer (x11_display->xdisplay); + meta_display_grab(x11_display->display); XSetInputFocus (x11_display->xdisplay, xwindow, @@ -2002,8 +2002,7 @@ meta_x11_display_set_input_focus_interna x11_display->atom__MUTTER_FOCUS_SET, XA_STRING, 8, PropModeAppend, NULL, 0); - XUngrabServer (x11_display->xdisplay); - XFlush (x11_display->xdisplay); + meta_display_ungrab(x11_display->display); meta_x11_error_trap_pop (x11_display); } Index: mutter-45.1/src/x11/window-x11.c =================================================================== --- mutter-45.1.orig/src/x11/window-x11.c +++ mutter-45.1/src/x11/window-x11.c @@ -548,6 +548,8 @@ meta_window_x11_manage (MetaWindow *wind meta_sync_counter_init (&priv->sync_counter, window, window->xwindow); meta_icon_cache_init (&priv->icon_cache); + meta_display_grab (display); + meta_x11_display_register_x_window (display->x11_display, &window->xwindow, window); @@ -565,11 +567,11 @@ meta_window_x11_manage (MetaWindow *wind if (window->decorated) meta_window_ensure_frame (window); else - meta_window_x11_initialize_state (window); + meta_window_x11_initialize_state (window, display); } void -meta_window_x11_initialize_state (MetaWindow *window) +meta_window_x11_initialize_state (MetaWindow *window, MetaDisplay *display) { MetaWindowX11 *window_x11 = META_WINDOW_X11 (window); MetaWindowX11Private *priv = meta_window_x11_get_instance_private (window_x11); @@ -620,6 +622,13 @@ meta_window_x11_initialize_state (MetaWi meta_window_x11_update_shape_region (window); meta_window_x11_update_input_region (window); + + meta_display_ungrab (display); + + /* Perform operations prevented by grab */ + if (window->frame) + meta_display_grab_window_buttons (display, window->frame->xwindow); + meta_window_grab_keys (window); } static void Index: mutter-45.1/src/x11/events.c =================================================================== --- mutter-45.1.orig/src/x11/events.c +++ mutter-45.1/src/x11/events.c @@ -1485,7 +1485,7 @@ handle_other_xevent (MetaX11Display *x11 { meta_window_set_frame_xwindow (window, event->xmaprequest.window); - meta_window_x11_initialize_state (window); + meta_window_x11_initialize_state (window, display); meta_window_update_visibility (window); } Index: mutter-45.1/src/x11/window-x11-private.h =================================================================== --- mutter-45.1.orig/src/x11/window-x11-private.h +++ mutter-45.1/src/x11/window-x11-private.h @@ -94,6 +94,6 @@ void meta_window_x11_set_bypass_composit void meta_window_x11_queue_update_icon (MetaWindowX11 *window_x11); -void meta_window_x11_initialize_state (MetaWindow *window); +void meta_window_x11_initialize_state (MetaWindow *window, MetaDisplay *display); G_END_DECLS