From a377a1a11082ed138a519707a41aa47982428ea5 Mon Sep 17 00:00:00 2001 From: "Jasper St. Pierre" Date: Wed, 19 Mar 2014 09:36:15 -0400 Subject: [PATCH] window: Move client-type-specific managing / unmanaging to a vfunc --- src/core/window-private.h | 2 + src/core/window.c | 240 +---------------------------------- src/wayland/window-wayland.c | 38 ++++++ src/x11/window-x11.c | 206 ++++++++++++++++++++++++++++++ 4 files changed, 250 insertions(+), 236 deletions(-) diff --git a/src/core/window-private.h b/src/core/window-private.h index b70e04fb9..d706ff9c9 100644 --- a/src/core/window-private.h +++ b/src/core/window-private.h @@ -454,6 +454,8 @@ struct _MetaWindowClass { GObjectClass parent_class; + void (*manage) (MetaWindow *window); + void (*unmanage) (MetaWindow *window); void (*get_default_skip_hints) (MetaWindow *window, gboolean *skip_taskbar_out, gboolean *skip_pager_out); diff --git a/src/core/window.c b/src/core/window.c index 852321a7e..4e930dc53 100644 --- a/src/core/window.c +++ b/src/core/window.c @@ -73,7 +73,6 @@ static int destroying_windows_disallowed = 0; -static void update_sm_hints (MetaWindow *window); static void update_net_frame_extents (MetaWindow *window); static void invalidate_work_areas (MetaWindow *window); static void set_wm_state (MetaWindow *window); @@ -971,25 +970,9 @@ _meta_window_shared_new (MetaDisplay *display, */ window->stable_sequence = ++display->window_sequence_counter; - if (client_type == META_WINDOW_CLIENT_TYPE_X11) - { - meta_display_register_x_window (display, &window->xwindow, window); - meta_window_x11_update_shape_region (window); - meta_window_x11_update_input_region (window); - } - else - meta_display_register_wayland_window (display, window); - window->opacity = 0xFF; - /* assign the window to its group, or create a new group if needed - */ - window->group = NULL; - window->xgroup_leader = None; - meta_window_compute_group (window); - - if (client_type == META_WINDOW_CLIENT_TYPE_X11) - meta_window_load_initial_properties (window); + META_WINDOW_GET_CLASS (window)->manage (window); if (window->override_redirect) { @@ -1001,13 +984,6 @@ _meta_window_shared_new (MetaDisplay *display, window->has_resize_func = FALSE; } - if (!window->override_redirect && - client_type == META_WINDOW_CLIENT_TYPE_X11) - update_sm_hints (window); /* must come after transient_for */ - - if (client_type == META_WINDOW_CLIENT_TYPE_X11) - meta_window_x11_update_net_wm_type (window); - if (!window->override_redirect) meta_window_update_icon_now (window); @@ -1068,16 +1044,6 @@ _meta_window_shared_new (MetaDisplay *display, if (window->decorated) meta_window_ensure_frame (window); - if (window->client_type == META_WINDOW_CLIENT_TYPE_WAYLAND) - { - MetaStackWindow stack_window; - stack_window.any.type = META_WINDOW_CLIENT_TYPE_WAYLAND; - stack_window.wayland.meta_window = window; - meta_stack_tracker_record_add (window->screen->stack_tracker, - &stack_window, - 0); - } - meta_window_grab_keys (window); if (window->type != META_WINDOW_DOCK && !window->override_redirect) { @@ -1502,19 +1468,11 @@ meta_window_unmanage (MetaWindow *window, meta_verbose ("Unmanaging 0x%lx\n", window->xwindow); + /* This needs to happen for both Wayland and XWayland clients, + * so it can't be in MetaWindowWayland. */ if (window->surface) meta_wayland_surface_window_unmanaged (window->surface); - if (window->client_type == META_WINDOW_CLIENT_TYPE_WAYLAND) - { - MetaStackWindow stack_window; - stack_window.any.type = META_WINDOW_CLIENT_TYPE_WAYLAND; - stack_window.wayland.meta_window = window; - meta_stack_tracker_record_remove (window->screen->stack_tracker, - &stack_window, - 0); - } - if (window->visible_to_compositor) meta_compositor_hide_window (window->display->compositor, window, META_COMP_EFFECT_DESTROY); @@ -1670,105 +1628,15 @@ meta_window_unmanage (MetaWindow *window, */ meta_stack_tracker_queue_sync_stack (window->screen->stack_tracker); - if (window->withdrawn) - { - /* We need to clean off the window's state so it - * won't be restored if the app maps it again. - */ - meta_error_trap_push (window->display); - meta_verbose ("Cleaning state from window %s\n", window->desc); - XDeleteProperty (window->display->xdisplay, - window->xwindow, - window->display->atom__NET_WM_DESKTOP); - XDeleteProperty (window->display->xdisplay, - window->xwindow, - window->display->atom__NET_WM_STATE); - XDeleteProperty (window->display->xdisplay, - window->xwindow, - window->display->atom__NET_WM_FULLSCREEN_MONITORS); - set_wm_state (window); - meta_error_trap_pop (window->display); - } - else - { - /* We need to put WM_STATE so that others will understand it on - * restart. - */ - if (!window->minimized) - { - meta_error_trap_push (window->display); - set_wm_state (window); - meta_error_trap_pop (window->display); - } - - /* If we're unmanaging a window that is not withdrawn, then - * either (a) mutter is exiting, in which case we need to map - * the window so the next WM will know that it's not Withdrawn, - * or (b) we want to create a new MetaWindow to replace the - * current one, which will happen automatically if we re-map - * the X Window. - */ - meta_error_trap_push (window->display); - XMapWindow (window->display->xdisplay, - window->xwindow); - meta_error_trap_pop (window->display); - } - meta_window_ungrab_keys (window); meta_display_ungrab_window_buttons (window->display, window->xwindow); meta_display_ungrab_focus_window_button (window->display, window); if (window->display->autoraise_window == window) meta_display_remove_autoraise_callback (window->display); - if (window->client_type == META_WINDOW_CLIENT_TYPE_X11) - { - meta_display_unregister_x_window (window->display, window->xwindow); - - meta_error_trap_push (window->display); - - /* Put back anything we messed up */ - if (window->border_width != 0) - XSetWindowBorderWidth (window->display->xdisplay, - window->xwindow, - window->border_width); - - /* No save set */ - XRemoveFromSaveSet (window->display->xdisplay, - window->xwindow); - - /* Even though the window is now unmanaged, we can't unselect events. This - * window might be a window from this process, like a GdkMenu, in - * which case it will have pointer events and so forth selected - * for it by GDK. There's no way to disentangle those events from the events - * we've selected. Even for a window from a different X client, - * GDK could also have selected events for it for IPC purposes, so we - * can't unselect in that case either. - * - * Similarly, we can't unselected for events on window->user_time_window. - * It might be our own GDK focus window, or it might be a window that a - * different client is using for multiple different things: - * _NET_WM_USER_TIME_WINDOW and IPC, perhaps. - */ - - if (window->user_time_window != None) - { - meta_display_unregister_x_window (window->display, - window->user_time_window); - window->user_time_window = None; - } - -#ifdef HAVE_SHAPE - if (META_DISPLAY_HAS_SHAPE (window->display)) - XShapeSelectInput (window->display->xdisplay, window->xwindow, NoEventMask); -#endif - - meta_error_trap_pop (window->display); - } - else - meta_display_unregister_wayland_window (window->display, window); + META_WINDOW_GET_CLASS (window)->unmanage (window); meta_prefs_remove_listener (prefs_changed_callback, window); - meta_screen_queue_check_fullscreen (window->screen); g_signal_emit (window, window_signals[UNMANAGED], 0); @@ -6541,106 +6409,6 @@ meta_window_set_icon_geometry (MetaWindow *window, } } -static Window -read_client_leader (MetaDisplay *display, - Window xwindow) -{ - Window retval = None; - - meta_prop_get_window (display, xwindow, - display->atom_WM_CLIENT_LEADER, - &retval); - - return retval; -} - -typedef struct -{ - Window leader; -} ClientLeaderData; - -static gboolean -find_client_leader_func (MetaWindow *ancestor, - void *data) -{ - ClientLeaderData *d; - - d = data; - - d->leader = read_client_leader (ancestor->display, - ancestor->xwindow); - - /* keep going if no client leader found */ - return d->leader == None; -} - -static void -update_sm_hints (MetaWindow *window) -{ - Window leader; - - window->xclient_leader = None; - window->sm_client_id = NULL; - - /* If not on the current window, we can get the client - * leader from transient parents. If we find a client - * leader, we read the SM_CLIENT_ID from it. - */ - leader = read_client_leader (window->display, window->xwindow); - if (leader == None) - { - ClientLeaderData d; - d.leader = None; - meta_window_foreach_ancestor (window, find_client_leader_func, - &d); - leader = d.leader; - } - - if (leader != None) - { - char *str; - - window->xclient_leader = leader; - - if (meta_prop_get_latin1_string (window->display, leader, - window->display->atom_SM_CLIENT_ID, - &str)) - { - window->sm_client_id = g_strdup (str); - meta_XFree (str); - } - } - else - { - meta_verbose ("Didn't find a client leader for %s\n", window->desc); - - if (!meta_prefs_get_disable_workarounds ()) - { - /* Some broken apps (kdelibs fault?) set SM_CLIENT_ID on the app - * instead of the client leader - */ - char *str; - - str = NULL; - if (meta_prop_get_latin1_string (window->display, window->xwindow, - window->display->atom_SM_CLIENT_ID, - &str)) - { - if (window->sm_client_id == NULL) /* first time through */ - meta_warning ("Window %s sets SM_CLIENT_ID on itself, instead of on the WM_CLIENT_LEADER window as specified in the ICCCM.\n", - window->desc); - - window->sm_client_id = g_strdup (str); - meta_XFree (str); - } - } - } - - meta_verbose ("Window %s client leader: 0x%lx SM_CLIENT_ID: '%s'\n", - window->desc, window->xclient_leader, - window->sm_client_id ? window->sm_client_id : "none"); -} - static void redraw_icon (MetaWindow *window) { diff --git a/src/wayland/window-wayland.c b/src/wayland/window-wayland.c index 627755ddf..9a0a15c7d 100644 --- a/src/wayland/window-wayland.c +++ b/src/wayland/window-wayland.c @@ -27,6 +27,8 @@ #include "window-wayland.h" #include "window-private.h" +#include "stack-tracker.h" +#include "meta-wayland-surface.h" struct _MetaWindowWayland { @@ -40,6 +42,38 @@ struct _MetaWindowWaylandClass G_DEFINE_TYPE (MetaWindowWayland, meta_window_wayland, META_TYPE_WINDOW) +static void +meta_window_wayland_manage (MetaWindow *window) +{ + MetaDisplay *display = window->display; + + meta_display_register_wayland_window (display, window); + + { + MetaStackWindow stack_window; + stack_window.any.type = META_WINDOW_CLIENT_TYPE_WAYLAND; + stack_window.wayland.meta_window = window; + meta_stack_tracker_record_add (window->screen->stack_tracker, + &stack_window, + 0); + } +} + +static void +meta_window_wayland_unmanage (MetaWindow *window) +{ + { + MetaStackWindow stack_window; + stack_window.any.type = META_WINDOW_CLIENT_TYPE_WAYLAND; + stack_window.wayland.meta_window = window; + meta_stack_tracker_record_remove (window->screen->stack_tracker, + &stack_window, + 0); + } + + meta_display_unregister_wayland_window (window->display, window); +} + static void meta_window_wayland_init (MetaWindowWayland *window_wayland) { @@ -48,4 +82,8 @@ meta_window_wayland_init (MetaWindowWayland *window_wayland) static void meta_window_wayland_class_init (MetaWindowWaylandClass *klass) { + MetaWindowClass *window_class = META_WINDOW_CLASS (klass); + + window_class->manage = meta_window_wayland_manage; + window_class->unmanage = meta_window_wayland_unmanage; } diff --git a/src/x11/window-x11.c b/src/x11/window-x11.c index ec8749453..f1f98b240 100644 --- a/src/x11/window-x11.c +++ b/src/x11/window-x11.c @@ -58,6 +58,210 @@ meta_window_x11_init (MetaWindowX11 *window_x11) window_x11->priv = meta_window_x11_get_instance_private (window_x11); } +static Window +read_client_leader (MetaDisplay *display, + Window xwindow) +{ + Window retval = None; + + meta_prop_get_window (display, xwindow, + display->atom_WM_CLIENT_LEADER, + &retval); + + return retval; +} + +typedef struct +{ + Window leader; +} ClientLeaderData; + +static gboolean +find_client_leader_func (MetaWindow *ancestor, + void *data) +{ + ClientLeaderData *d; + + d = data; + + d->leader = read_client_leader (ancestor->display, + ancestor->xwindow); + + /* keep going if no client leader found */ + return d->leader == None; +} + +static void +update_sm_hints (MetaWindow *window) +{ + Window leader; + + window->xclient_leader = None; + window->sm_client_id = NULL; + + /* If not on the current window, we can get the client + * leader from transient parents. If we find a client + * leader, we read the SM_CLIENT_ID from it. + */ + leader = read_client_leader (window->display, window->xwindow); + if (leader == None) + { + ClientLeaderData d; + d.leader = None; + meta_window_foreach_ancestor (window, find_client_leader_func, + &d); + leader = d.leader; + } + + if (leader != None) + { + char *str; + + window->xclient_leader = leader; + + if (meta_prop_get_latin1_string (window->display, leader, + window->display->atom_SM_CLIENT_ID, + &str)) + { + window->sm_client_id = g_strdup (str); + meta_XFree (str); + } + } + else + { + meta_verbose ("Didn't find a client leader for %s\n", window->desc); + + if (!meta_prefs_get_disable_workarounds ()) + { + /* Some broken apps (kdelibs fault?) set SM_CLIENT_ID on the app + * instead of the client leader + */ + char *str; + + str = NULL; + if (meta_prop_get_latin1_string (window->display, window->xwindow, + window->display->atom_SM_CLIENT_ID, + &str)) + { + if (window->sm_client_id == NULL) /* first time through */ + meta_warning ("Window %s sets SM_CLIENT_ID on itself, instead of on the WM_CLIENT_LEADER window as specified in the ICCCM.\n", + window->desc); + + window->sm_client_id = g_strdup (str); + meta_XFree (str); + } + } + } + + meta_verbose ("Window %s client leader: 0x%lx SM_CLIENT_ID: '%s'\n", + window->desc, window->xclient_leader, + window->sm_client_id ? window->sm_client_id : "none"); +} + +static void +meta_window_x11_manage (MetaWindow *window) +{ + MetaDisplay *display = window->display; + + meta_display_register_x_window (display, &window->xwindow, window); + meta_window_x11_update_shape_region (window); + meta_window_x11_update_input_region (window); + + /* assign the window to its group, or create a new group if needed */ + window->group = NULL; + window->xgroup_leader = None; + meta_window_compute_group (window); + + meta_window_load_initial_properties (window); + + if (!window->override_redirect) + update_sm_hints (window); /* must come after transient_for */ + + meta_window_x11_update_net_wm_type (window); +} + +static void +meta_window_x11_unmanage (MetaWindow *window) +{ + meta_error_trap_push (window->display); + + if (window->withdrawn) + { + /* We need to clean off the window's state so it + * won't be restored if the app maps it again. + */ + meta_verbose ("Cleaning state from window %s\n", window->desc); + XDeleteProperty (window->display->xdisplay, + window->xwindow, + window->display->atom__NET_WM_DESKTOP); + XDeleteProperty (window->display->xdisplay, + window->xwindow, + window->display->atom__NET_WM_STATE); + XDeleteProperty (window->display->xdisplay, + window->xwindow, + window->display->atom__NET_WM_FULLSCREEN_MONITORS); + meta_window_x11_set_wm_state (window); + } + else + { + /* We need to put WM_STATE so that others will understand it on + * restart. + */ + if (!window->minimized) + meta_window_x11_set_wm_state (window); + + /* If we're unmanaging a window that is not withdrawn, then + * either (a) mutter is exiting, in which case we need to map + * the window so the next WM will know that it's not Withdrawn, + * or (b) we want to create a new MetaWindow to replace the + * current one, which will happen automatically if we re-map + * the X Window. + */ + XMapWindow (window->display->xdisplay, + window->xwindow); + } + + meta_display_unregister_x_window (window->display, window->xwindow); + + /* Put back anything we messed up */ + if (window->border_width != 0) + XSetWindowBorderWidth (window->display->xdisplay, + window->xwindow, + window->border_width); + + /* No save set */ + XRemoveFromSaveSet (window->display->xdisplay, + window->xwindow); + + /* Even though the window is now unmanaged, we can't unselect events. This + * window might be a window from this process, like a GdkMenu, in + * which case it will have pointer events and so forth selected + * for it by GDK. There's no way to disentangle those events from the events + * we've selected. Even for a window from a different X client, + * GDK could also have selected events for it for IPC purposes, so we + * can't unselect in that case either. + * + * Similarly, we can't unselected for events on window->user_time_window. + * It might be our own GDK focus window, or it might be a window that a + * different client is using for multiple different things: + * _NET_WM_USER_TIME_WINDOW and IPC, perhaps. + */ + + if (window->user_time_window != None) + { + meta_display_unregister_x_window (window->display, + window->user_time_window); + window->user_time_window = None; + } + +#ifdef HAVE_SHAPE + if (META_DISPLAY_HAS_SHAPE (window->display)) + XShapeSelectInput (window->display->xdisplay, window->xwindow, NoEventMask); +#endif + + meta_error_trap_pop (window->display); +} + static void meta_window_x11_get_default_skip_hints (MetaWindow *window, gboolean *skip_taskbar_out, @@ -75,6 +279,8 @@ meta_window_x11_class_init (MetaWindowX11Class *klass) { MetaWindowClass *window_class = META_WINDOW_CLASS (klass); + window_class->manage = meta_window_x11_manage; + window_class->unmanage = meta_window_x11_unmanage; window_class->get_default_skip_hints = meta_window_x11_get_default_skip_hints; }