diff --git a/src/compositor/compositor.c b/src/compositor/compositor.c index f43d2da1b..694b27e3f 100644 --- a/src/compositor/compositor.c +++ b/src/compositor/compositor.c @@ -966,7 +966,7 @@ on_top_window_actor_destroyed (MetaWindowActor *window_actor, compositor->top_window_actor = NULL; compositor->windows = g_list_remove (compositor->windows, window_actor); - meta_stack_tracker_queue_sync_stack (compositor->display->screen->stack_tracker); + meta_stack_tracker_queue_sync_stack (compositor->display->stack_tracker); } void diff --git a/src/core/display-private.h b/src/core/display-private.h index aa4af0794..e025b2316 100644 --- a/src/core/display-private.h +++ b/src/core/display-private.h @@ -37,6 +37,7 @@ #include "keybindings-private.h" #include "startup-notification-private.h" #include "meta-gesture-tracker-private.h" +#include "stack-tracker.h" #include #include #include @@ -244,6 +245,9 @@ struct _MetaDisplay MetaRectangle rect; /* Size of screen; rect.x & rect.y are always 0 */ MetaCursor current_cursor; + + MetaStack *stack; + MetaStackTracker *stack_tracker; }; struct _MetaDisplayClass @@ -270,8 +274,9 @@ gboolean meta_display_open (void); void meta_display_close (MetaDisplay *display, guint32 timestamp); -void meta_display_unmanage_windows (MetaDisplay *display, - guint32 timestamp); +void meta_display_manage_all_windows (MetaDisplay *display); +void meta_display_unmanage_windows (MetaDisplay *display, + guint32 timestamp); /* Utility function to compare the stacking of two windows */ int meta_display_stack_cmp (const void *a, @@ -426,4 +431,6 @@ void meta_display_foreach_window (MetaDisplay *display, MetaDisplayWindowFunc func, gpointer data); +void meta_display_restacked (MetaDisplay *display); + #endif diff --git a/src/core/display.c b/src/core/display.c index 9193b3eef..2e7e6d064 100644 --- a/src/core/display.c +++ b/src/core/display.c @@ -137,6 +137,7 @@ enum SHOW_OSD, PAD_MODE_SWITCH, MONITORS_CHANGED, + RESTACKED, LAST_SIGNAL }; @@ -433,6 +434,13 @@ meta_display_class_init (MetaDisplayClass *klass) 0, NULL, NULL, NULL, G_TYPE_NONE, 0); + display_signals[RESTACKED] = + g_signal_new ("restacked", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, NULL, NULL, NULL, + G_TYPE_NONE, 0); + g_object_class_install_property (object_class, PROP_FOCUS_WINDOW, g_param_spec_object ("focus-window", @@ -709,6 +717,9 @@ meta_display_open (void) xdisplay = display->x11_display->xdisplay; + display->stack = meta_stack_new (display); + display->stack_tracker = meta_stack_tracker_new (display); + display->focus_serial = 0; display->server_focus_window = None; display->server_focus_serial = 0; @@ -820,7 +831,7 @@ meta_display_open (void) enable_compositor (display); - meta_screen_create_guard_window (screen); + meta_x11_display_create_guard_window (display->x11_display); /* Set up touch support */ display->gesture_tracker = meta_gesture_tracker_new (); @@ -831,7 +842,7 @@ meta_display_open (void) * we start out with no windows. */ if (!meta_is_wayland_compositor ()) - meta_screen_manage_all_windows (screen); + meta_display_manage_all_windows (display); if (old_active_xwindow != None) { @@ -985,6 +996,10 @@ meta_display_close (MetaDisplay *display, g_clear_object (&display->startup_notification); g_clear_object (&display->gesture_tracker); + g_clear_pointer (&display->stack, (GDestroyNotify) meta_stack_free); + g_clear_pointer (&display->stack_tracker, + (GDestroyNotify) meta_stack_tracker_free); + if (display->focus_timeout_id) g_source_remove (display->focus_timeout_id); display->focus_timeout_id = 0; @@ -1251,7 +1266,7 @@ window_raise_with_delay_callback (void *data) /* If we aren't already on top, check whether the pointer is inside * the window and raise the window if so. */ - if (meta_stack_get_top (window->screen->stack) != window) + if (meta_stack_get_top (window->display->stack) != window) { if (meta_window_has_pointer (window)) meta_window_raise (window); @@ -2564,6 +2579,30 @@ meta_display_unmanage_screen (MetaDisplay *display, meta_display_close (display, timestamp); } +void +meta_display_manage_all_windows (MetaDisplay *display) +{ + guint64 *_children; + guint64 *children; + int n_children, i; + + meta_stack_freeze (display->stack); + meta_stack_tracker_get_stack (display->stack_tracker, &_children, &n_children); + + /* Copy the stack as it will be modified as part of the loop */ + children = g_memdup (_children, sizeof (guint64) * n_children); + + for (i = 0; i < n_children; ++i) + { + g_assert (META_STACK_ID_IS_X11 (children[i])); + meta_window_x11_new (display, children[i], TRUE, + META_COMP_EFFECT_NONE); + } + + g_free (children); + meta_stack_thaw (display->stack); +} + void meta_display_unmanage_windows (MetaDisplay *display, guint32 timestamp) @@ -2602,7 +2641,7 @@ meta_display_stack_cmp (const void *a, MetaWindow *aw = (void*) a; MetaWindow *bw = (void*) b; - return meta_stack_windows_cmp (aw->screen->stack, aw, bw); + return meta_stack_windows_cmp (aw->display->stack, aw, bw); } /** @@ -3209,3 +3248,9 @@ on_monitors_changed (MetaMonitorManager *monitor_manager, { g_signal_emit (display, display_signals[MONITORS_CHANGED], 0); } + +void +meta_display_restacked (MetaDisplay *display) +{ + g_signal_emit (display, display_signals[RESTACKED], 0); +} diff --git a/src/core/edge-resistance.c b/src/core/edge-resistance.c index 56a667842..47ac4d1e0 100644 --- a/src/core/edge-resistance.c +++ b/src/core/edge-resistance.c @@ -1009,7 +1009,7 @@ compute_resistance_and_snapping_edges (MetaDisplay *display) * 1st: Get the list of relevant windows, from bottom to top */ stacked_windows = - meta_stack_list_windows (display->screen->stack, + meta_stack_list_windows (display->stack, display->screen->active_workspace); /* diff --git a/src/core/frame.c b/src/core/frame.c index 1fb885d06..be1f4e2bf 100644 --- a/src/core/frame.c +++ b/src/core/frame.c @@ -76,7 +76,7 @@ meta_window_ensure_frame (MetaWindow *window) &create_serial); frame->xwindow = frame->ui_frame->xwindow; - meta_stack_tracker_record_add (window->screen->stack_tracker, + meta_stack_tracker_record_add (window->display->stack_tracker, frame->xwindow, create_serial); @@ -98,7 +98,7 @@ meta_window_ensure_frame (MetaWindow *window) window->unmaps_pending += 1; } - meta_stack_tracker_record_remove (window->screen->stack_tracker, + meta_stack_tracker_record_remove (window->display->stack_tracker, window->xwindow, XNextRequest (x11_display->xdisplay)); XReparentWindow (x11_display->xdisplay, @@ -185,7 +185,7 @@ meta_window_destroy_frame (MetaWindow *window) "Incrementing unmaps_pending on %s for reparent back to root\n", window->desc); window->unmaps_pending += 1; } - meta_stack_tracker_record_add (window->screen->stack_tracker, + meta_stack_tracker_record_add (window->display->stack_tracker, window->xwindow, XNextRequest (x11_display->xdisplay)); XReparentWindow (x11_display->xdisplay, diff --git a/src/core/keybindings.c b/src/core/keybindings.c index a7c18eb47..cfcf5fa55 100644 --- a/src/core/keybindings.c +++ b/src/core/keybindings.c @@ -3454,7 +3454,7 @@ handle_raise_or_lower (MetaDisplay *display, MetaWindow *above = NULL; /* Check if top */ - if (meta_stack_get_top (window->screen->stack) == window) + if (meta_stack_get_top (window->display->stack) == window) { meta_window_lower (window); return; @@ -3462,7 +3462,7 @@ handle_raise_or_lower (MetaDisplay *display, /* else check if windows in same layer are intersecting it */ - above = meta_stack_get_above (window->screen->stack, window, TRUE); + above = meta_stack_get_above (window->display->stack, window, TRUE); while (above) { @@ -3481,7 +3481,7 @@ handle_raise_or_lower (MetaDisplay *display, } } - above = meta_stack_get_above (window->screen->stack, above, TRUE); + above = meta_stack_get_above (window->display->stack, above, TRUE); } /* window is not obscured */ diff --git a/src/core/screen-private.h b/src/core/screen-private.h index 4c853f2da..bf2fbb0fe 100644 --- a/src/core/screen-private.h +++ b/src/core/screen-private.h @@ -59,9 +59,6 @@ struct _MetaScreen GList *workspaces; - MetaStack *stack; - MetaStackTracker *stack_tracker; - Window wm_sn_selection_window; Atom wm_sn_atom; guint32 wm_sn_timestamp; @@ -84,11 +81,6 @@ struct _MetaScreen int closing; - /* Instead of unmapping withdrawn windows we can leave them mapped - * and restack them below a guard window. When using a compositor - * this allows us to provide live previews of unmapped windows */ - Window guard_window; - Window composite_overlay_window; }; @@ -96,7 +88,6 @@ struct _MetaScreenClass { GObjectClass parent_class; - void (*restacked) (MetaScreen *); void (*workareas_changed) (MetaScreen *); }; @@ -150,7 +141,6 @@ void meta_screen_update_showing_desktop_hint (MetaScreen *screen); gboolean meta_screen_apply_startup_properties (MetaScreen *screen, MetaWindow *window); -void meta_screen_restacked (MetaScreen *screen); void meta_screen_workspace_switched (MetaScreen *screen, int from, @@ -159,8 +149,6 @@ void meta_screen_workspace_switched (MetaScreen *screen, void meta_screen_set_active_workspace_hint (MetaScreen *screen); -void meta_screen_create_guard_window (MetaScreen *screen); - gboolean meta_screen_handle_xevent (MetaScreen *screen, XEvent *xevent); diff --git a/src/core/screen.c b/src/core/screen.c index 26bae29fe..70aa9169d 100644 --- a/src/core/screen.c +++ b/src/core/screen.c @@ -79,7 +79,6 @@ enum enum { - RESTACKED, WORKSPACE_ADDED, WORKSPACE_REMOVED, WORKSPACE_SWITCHED, @@ -156,14 +155,6 @@ meta_screen_class_init (MetaScreenClass *klass) object_class->set_property = meta_screen_set_property; object_class->finalize = meta_screen_finalize; - screen_signals[RESTACKED] = - g_signal_new ("restacked", - G_TYPE_FROM_CLASS (object_class), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (MetaScreenClass, restacked), - NULL, NULL, NULL, - G_TYPE_NONE, 0); - pspec = g_param_spec_int ("n-workspaces", "N Workspaces", "Number of workspaces", @@ -481,75 +472,6 @@ reload_logical_monitors (MetaScreen *screen) screen->has_xinerama_indices = FALSE; } -/* The guard window allows us to leave minimized windows mapped so - * that compositor code may provide live previews of them. - * Instead of being unmapped/withdrawn, they get pushed underneath - * the guard window. We also select events on the guard window, which - * should effectively be forwarded to events on the background actor, - * providing that the scene graph is set up correctly. - */ -static Window -create_guard_window (Display *xdisplay, MetaScreen *screen) -{ - XSetWindowAttributes attributes; - MetaX11Display *x11_display = screen->display->x11_display; - Window guard_window; - gulong create_serial; - - attributes.event_mask = NoEventMask; - attributes.override_redirect = True; - - /* We have to call record_add() after we have the new window ID, - * so save the serial for the CreateWindow request until then */ - create_serial = XNextRequest(xdisplay); - guard_window = - XCreateWindow (xdisplay, - x11_display->xroot, - 0, /* x */ - 0, /* y */ - screen->display->rect.width, - screen->display->rect.height, - 0, /* border width */ - 0, /* depth */ - InputOnly, /* class */ - CopyFromParent, /* visual */ - CWEventMask|CWOverrideRedirect, - &attributes); - - /* https://bugzilla.gnome.org/show_bug.cgi?id=710346 */ - XStoreName (xdisplay, guard_window, "mutter guard window"); - - { - if (!meta_is_wayland_compositor ()) - { - MetaBackendX11 *backend = META_BACKEND_X11 (meta_get_backend ()); - Display *backend_xdisplay = meta_backend_x11_get_xdisplay (backend); - unsigned char mask_bits[XIMaskLen (XI_LASTEVENT)] = { 0 }; - XIEventMask mask = { XIAllMasterDevices, sizeof (mask_bits), mask_bits }; - - XISetMask (mask.mask, XI_ButtonPress); - XISetMask (mask.mask, XI_ButtonRelease); - XISetMask (mask.mask, XI_Motion); - - /* Sync on the connection we created the window on to - * make sure it's created before we select on it on the - * backend connection. */ - XSync (xdisplay, False); - - XISelectEvents (backend_xdisplay, guard_window, &mask, 1); - } - } - - meta_stack_tracker_record_add (screen->stack_tracker, - guard_window, - create_serial); - - meta_stack_tracker_lower (screen->stack_tracker, - guard_window); - XMapWindow (xdisplay, guard_window); - return guard_window; -} - static Window take_manager_selection (MetaDisplay *display, Window xroot, @@ -695,7 +617,6 @@ meta_screen_new (MetaDisplay *display, screen->columns_of_workspaces = -1; screen->vertical_workspaces = FALSE; screen->starting_corner = META_SCREEN_TOPLEFT; - screen->guard_window = None; /* If we're a Wayland compositor, then we don't grab the COW, since it * will map it. */ @@ -740,9 +661,6 @@ meta_screen_new (MetaDisplay *display, screen->tile_preview_timeout_id = 0; - screen->stack = meta_stack_new (screen); - screen->stack_tracker = meta_stack_tracker_new (screen); - meta_prefs_add_listener (prefs_changed_callback, screen); meta_verbose ("Added screen %d ('%s') root 0x%lx\n", @@ -803,9 +721,6 @@ meta_screen_free (MetaScreen *screen, meta_ui_free (screen->ui); - meta_stack_free (screen->stack); - meta_stack_tracker_free (screen->stack_tracker); - unset_wm_check_hint (screen); XDestroyWindow (x11_display->xdisplay, @@ -822,39 +737,6 @@ meta_screen_free (MetaScreen *screen, g_object_unref (screen); } -void -meta_screen_create_guard_window (MetaScreen *screen) -{ - MetaX11Display *x11_display = screen->display->x11_display; - - if (screen->guard_window == None) - screen->guard_window = create_guard_window (x11_display->xdisplay, screen); -} - -void -meta_screen_manage_all_windows (MetaScreen *screen) -{ - guint64 *_children; - guint64 *children; - int n_children, i; - - meta_stack_freeze (screen->stack); - meta_stack_tracker_get_stack (screen->stack_tracker, &_children, &n_children); - - /* Copy the stack as it will be modified as part of the loop */ - children = g_memdup (_children, sizeof (guint64) * n_children); - - for (i = 0; i < n_children; ++i) - { - g_assert (META_STACK_ID_IS_X11 (children[i])); - meta_window_x11_new (screen->display, children[i], TRUE, - META_COMP_EFFECT_NONE); - } - - g_free (children); - meta_stack_thaw (screen->stack); -} - static void prefs_changed_callback (MetaPreference pref, gpointer data) @@ -1291,7 +1173,7 @@ meta_screen_get_mouse_window (MetaScreen *screen, meta_cursor_tracker_get_pointer (cursor_tracker, &x, &y, NULL); - window = meta_stack_get_default_focus_window_at_point (screen->stack, + window = meta_stack_get_default_focus_window_at_point (screen->display->stack, screen->active_workspace, not_this_one, x, y); @@ -2023,27 +1905,9 @@ meta_screen_free_workspace_layout (MetaWorkspaceLayout *layout) void meta_screen_on_monitors_changed (MetaScreen *screen) { - MetaDisplay *display = screen->display; - reload_logical_monitors (screen); set_desktop_geometry_hint (screen); - /* Resize the guard window to fill the screen again. */ - if (screen->guard_window != None) - { - XWindowChanges changes; - - changes.x = 0; - changes.y = 0; - changes.width = display->rect.width; - changes.height = display->rect.height; - - XConfigureWindow(display->x11_display->xdisplay, - screen->guard_window, - CWX | CWY | CWWidth | CWHeight, - &changes); - } - meta_screen_queue_check_fullscreen (screen); } @@ -2363,12 +2227,6 @@ meta_screen_focus_default_window (MetaScreen *screen, timestamp); } -void -meta_screen_restacked (MetaScreen *screen) -{ - g_signal_emit (screen, screen_signals[RESTACKED], 0); -} - void meta_screen_workspace_switched (MetaScreen *screen, int from, @@ -2430,9 +2288,9 @@ check_fullscreen_func (gpointer data) * however we make an exception for maximized windows above the fullscreen * one, as in that case window+chrome fully obscure the fullscreen window. */ - for (window = meta_stack_get_top (screen->stack); + for (window = meta_stack_get_top (screen->display->stack); window; - window = meta_stack_get_below (screen->stack, window, FALSE)) + window = meta_stack_get_below (screen->display->stack, window, FALSE)) { gboolean covers_monitors = FALSE; @@ -2506,9 +2364,9 @@ check_fullscreen_func (gpointer data) { /* DOCK window stacking depends on the monitor's fullscreen status so we need to trigger a re-layering. */ - MetaWindow *window = meta_stack_get_top (screen->stack); + MetaWindow *window = meta_stack_get_top (screen->display->stack); if (window) - meta_stack_update_layer (screen->stack, window); + meta_stack_update_layer (screen->display->stack, window); g_signal_emit (screen, screen_signals[IN_FULLSCREEN_CHANGED], 0, NULL); } diff --git a/src/core/stack-tracker.c b/src/core/stack-tracker.c index a5ef6de45..f6372dba7 100644 --- a/src/core/stack-tracker.c +++ b/src/core/stack-tracker.c @@ -37,7 +37,7 @@ #include #include "frame.h" -#include "screen-private.h" +#include "display-private.h" #include "stack-tracker.h" #include #include @@ -142,7 +142,7 @@ union _MetaStackOp struct _MetaStackTracker { - MetaScreen *screen; + MetaDisplay *display; /* This is the serial of the last request we made that was reflected * in xserver_stack @@ -177,7 +177,7 @@ static inline const char * get_window_desc (MetaStackTracker *tracker, guint64 window) { - return meta_display_describe_stack_id (tracker->screen->display, window); + return meta_display_describe_stack_id (tracker->display, window); } static void @@ -478,16 +478,16 @@ copy_stack (GArray *stack) static void query_xserver_stack (MetaStackTracker *tracker) { - MetaScreen *screen = tracker->screen; + MetaX11Display *x11_display = tracker->display->x11_display; Window ignored1, ignored2; Window *children; guint n_children; guint i; - tracker->xserver_serial = XNextRequest (screen->display->x11_display->xdisplay); + tracker->xserver_serial = XNextRequest (x11_display->xdisplay); - XQueryTree (screen->display->x11_display->xdisplay, - screen->display->x11_display->xroot, + XQueryTree (x11_display->xdisplay, + x11_display->xroot, &ignored1, &ignored2, &children, &n_children); tracker->verified_stack = g_array_sized_new (FALSE, FALSE, sizeof (guint64), n_children); @@ -500,12 +500,12 @@ query_xserver_stack (MetaStackTracker *tracker) } MetaStackTracker * -meta_stack_tracker_new (MetaScreen *screen) +meta_stack_tracker_new (MetaDisplay *display) { MetaStackTracker *tracker; tracker = g_new0 (MetaStackTracker, 1); - tracker->screen = screen; + tracker->display = display; query_xserver_stack (tracker); @@ -851,7 +851,7 @@ meta_stack_tracker_sync_stack (MetaStackTracker *tracker) if (META_STACK_ID_IS_X11 (window)) { - MetaX11Display *x11_display = tracker->screen->display->x11_display; + MetaX11Display *x11_display = tracker->display->x11_display; MetaWindow *meta_window = meta_x11_display_lookup_x_window (x11_display, (Window)window); @@ -868,14 +868,14 @@ meta_stack_tracker_sync_stack (MetaStackTracker *tracker) } else meta_windows = g_list_prepend (meta_windows, - meta_display_lookup_stamp (tracker->screen->display, window)); + meta_display_lookup_stamp (tracker->display, window)); } - meta_compositor_sync_stack (tracker->screen->display->compositor, + meta_compositor_sync_stack (tracker->display->compositor, meta_windows); g_list_free (meta_windows); - meta_screen_restacked (tracker->screen); + meta_display_restacked (tracker->display); } static gboolean @@ -980,7 +980,7 @@ meta_stack_tracker_lower_below (MetaStackTracker *tracker, guint64 sibling) { gulong serial = 0; - MetaX11Display *x11_display = tracker->screen->display->x11_display; + MetaX11Display *x11_display = tracker->display->x11_display; if (META_STACK_ID_IS_X11 (window)) { @@ -1015,7 +1015,7 @@ meta_stack_tracker_raise_above (MetaStackTracker *tracker, guint64 sibling) { gulong serial = 0; - MetaX11Display *x11_display = tracker->screen->display->x11_display; + MetaX11Display *x11_display = tracker->display->x11_display; if (META_STACK_ID_IS_X11 (window)) { @@ -1062,7 +1062,7 @@ meta_stack_tracker_keep_override_redirect_on_top (MetaStackTracker *tracker) for (i = n_windows - 1; i >= 0; i--) { - window = meta_display_lookup_stack_id (tracker->screen->display, stack[i]); + window = meta_display_lookup_stack_id (tracker->display, stack[i]); if (window && window->layer != META_LAYER_OVERRIDE_REDIRECT) break; } @@ -1071,7 +1071,7 @@ meta_stack_tracker_keep_override_redirect_on_top (MetaStackTracker *tracker) for (i -= 1; i >= 0; i--) { - window = meta_display_lookup_stack_id (tracker->screen->display, stack[i]); + window = meta_display_lookup_stack_id (tracker->display, stack[i]); if (window && window->layer == META_LAYER_OVERRIDE_REDIRECT) { meta_stack_tracker_raise_above (tracker, stack[i], stack[topmost_non_or]); @@ -1103,9 +1103,9 @@ meta_stack_tracker_restack_managed (MetaStackTracker *tracker, old_pos = n_windows - 1; for (old_pos = n_windows - 1; old_pos >= 0; old_pos--) { - MetaWindow *old_window = meta_display_lookup_stack_id (tracker->screen->display, windows[old_pos]); + MetaWindow *old_window = meta_display_lookup_stack_id (tracker->display, windows[old_pos]); if ((old_window && !old_window->override_redirect && !old_window->unmanaging) || - windows[old_pos] == tracker->screen->guard_window) + windows[old_pos] == tracker->display->x11_display->guard_window) break; } g_assert (old_pos >= 0); @@ -1124,7 +1124,7 @@ meta_stack_tracker_restack_managed (MetaStackTracker *tracker, while (old_pos >= 0 && new_pos >= 0) { - if (windows[old_pos] == tracker->screen->guard_window) + if (windows[old_pos] == tracker->display->x11_display->guard_window) break; if (windows[old_pos] == managed[new_pos]) @@ -1134,7 +1134,7 @@ meta_stack_tracker_restack_managed (MetaStackTracker *tracker, continue; } - MetaWindow *old_window = meta_display_lookup_stack_id (tracker->screen->display, windows[old_pos]); + MetaWindow *old_window = meta_display_lookup_stack_id (tracker->display, windows[old_pos]); if (!old_window || old_window->override_redirect || old_window->unmanaging) { old_pos--; diff --git a/src/core/stack-tracker.h b/src/core/stack-tracker.h index 12015ae23..e93b95b21 100644 --- a/src/core/stack-tracker.h +++ b/src/core/stack-tracker.h @@ -34,12 +34,12 @@ #ifndef META_STACK_TRACKER_H #define META_STACK_TRACKER_H -#include +#include #include typedef struct _MetaStackTracker MetaStackTracker; -MetaStackTracker *meta_stack_tracker_new (MetaScreen *screen); +MetaStackTracker *meta_stack_tracker_new (MetaDisplay *display); void meta_stack_tracker_free (MetaStackTracker *tracker); /* These functions are called when we make an X call that changes the diff --git a/src/core/stack.c b/src/core/stack.c index 217ba44ae..fc3b2ecfc 100644 --- a/src/core/stack.c +++ b/src/core/stack.c @@ -61,14 +61,14 @@ static void stack_do_resort (MetaStack *stack); static void stack_ensure_sorted (MetaStack *stack); -MetaStack* -meta_stack_new (MetaScreen *screen) +MetaStack * +meta_stack_new (MetaDisplay *display) { MetaStack *stack; stack = g_new (MetaStack, 1); - stack->screen = screen; + stack->display = display; stack->xwindows = g_array_new (FALSE, FALSE, sizeof (Window)); stack->sorted = NULL; @@ -945,7 +945,7 @@ stack_do_resort (MetaStack *stack) stack->sorted = g_list_sort (stack->sorted, (GCompareFunc) compare_window_position); - meta_screen_queue_check_fullscreen (stack->screen); + meta_screen_queue_check_fullscreen (stack->display->screen); stack->need_resort = FALSE; } @@ -1052,7 +1052,7 @@ stack_sync_to_xserver (MetaStack *stack) /* The screen guard window sits above all hidden windows and acts as * a barrier to input reaching these windows. */ - guint64 guard_window_id = stack->screen->guard_window; + guint64 guard_window_id = stack->display->x11_display->guard_window; g_array_append_val (hidden_stack_ids, guard_window_id); /* Sync to server */ @@ -1060,25 +1060,25 @@ stack_sync_to_xserver (MetaStack *stack) meta_topic (META_DEBUG_STACK, "Restacking %u windows\n", all_root_children_stacked->len); - meta_stack_tracker_restack_managed (stack->screen->stack_tracker, + meta_stack_tracker_restack_managed (stack->display->stack_tracker, (guint64 *)all_root_children_stacked->data, all_root_children_stacked->len); - meta_stack_tracker_restack_at_bottom (stack->screen->stack_tracker, + meta_stack_tracker_restack_at_bottom (stack->display->stack_tracker, (guint64 *)hidden_stack_ids->data, hidden_stack_ids->len); /* Sync _NET_CLIENT_LIST and _NET_CLIENT_LIST_STACKING */ - XChangeProperty (stack->screen->display->x11_display->xdisplay, - stack->screen->display->x11_display->xroot, - stack->screen->display->x11_display->atom__NET_CLIENT_LIST, + XChangeProperty (stack->display->x11_display->xdisplay, + stack->display->x11_display->xroot, + stack->display->x11_display->atom__NET_CLIENT_LIST, XA_WINDOW, 32, PropModeReplace, (unsigned char *)stack->xwindows->data, stack->xwindows->len); - XChangeProperty (stack->screen->display->x11_display->xdisplay, - stack->screen->display->x11_display->xroot, - stack->screen->display->x11_display->atom__NET_CLIENT_LIST_STACKING, + XChangeProperty (stack->display->x11_display->xdisplay, + stack->display->x11_display->xroot, + stack->display->x11_display->atom__NET_CLIENT_LIST_STACKING, XA_WINDOW, 32, PropModeReplace, (unsigned char *)x11_stacked->data, @@ -1411,10 +1411,10 @@ meta_window_set_stack_position_no_sync (MetaWindow *window, int low, high, delta; GList *tmp; - g_return_if_fail (window->screen->stack != NULL); + g_return_if_fail (window->display->stack != NULL); g_return_if_fail (window->stack_position >= 0); g_return_if_fail (position >= 0); - g_return_if_fail (position < window->screen->stack->n_positions); + g_return_if_fail (position < window->display->stack->n_positions); if (position == window->stack_position) { @@ -1423,8 +1423,8 @@ meta_window_set_stack_position_no_sync (MetaWindow *window, return; } - window->screen->stack->need_resort = TRUE; - window->screen->stack->need_constrain = TRUE; + window->display->stack->need_resort = TRUE; + window->display->stack->need_constrain = TRUE; if (position < window->stack_position) { @@ -1439,7 +1439,7 @@ meta_window_set_stack_position_no_sync (MetaWindow *window, delta = -1; } - tmp = window->screen->stack->sorted; + tmp = window->display->stack->sorted; while (tmp != NULL) { MetaWindow *w = tmp->data; @@ -1463,7 +1463,7 @@ meta_window_set_stack_position (MetaWindow *window, int position) { meta_window_set_stack_position_no_sync (window, position); - stack_sync_to_xserver (window->screen->stack); - meta_stack_update_window_tile_matches (window->screen->stack, + stack_sync_to_xserver (window->display->stack); + meta_stack_update_window_tile_matches (window->display->stack, window->screen->active_workspace); } diff --git a/src/core/stack.h b/src/core/stack.h index e82be0abe..d97606742 100644 --- a/src/core/stack.h +++ b/src/core/stack.h @@ -40,7 +40,7 @@ * by layer, then by stack_position within each layer. */ -#include "screen-private.h" +#include "display-private.h" /** * A sorted list of windows bearing some level of resemblance to the stack of @@ -51,8 +51,8 @@ */ struct _MetaStack { - /** The MetaScreen containing this stack. */ - MetaScreen *screen; + /** The MetaDisplay containing this stack. */ + MetaDisplay *display; /** * A sequence of all the Windows (X handles, not MetaWindows) of the windows @@ -123,13 +123,13 @@ struct _MetaStack /** * meta_stack_new: - * @screen: The MetaScreen which will be the parent of this stack. + * @display: The MetaDisplay which will be the parent of this stack. * * Creates and initialises a MetaStack. * - * Returns: The new screen. + * Returns: The new stack. */ -MetaStack *meta_stack_new (MetaScreen *screen); +MetaStack *meta_stack_new (MetaDisplay *display); /** * meta_stack_free: diff --git a/src/core/window.c b/src/core/window.c index 342d9650e..3f7224f59 100644 --- a/src/core/window.c +++ b/src/core/window.c @@ -982,7 +982,7 @@ _meta_window_shared_new (MetaDisplay *display, window->override_redirect = attrs->override_redirect; /* avoid tons of stack updates */ - meta_stack_freeze (window->screen->stack); + meta_stack_freeze (window->display->stack); window->rect.x = attrs->x; window->rect.y = attrs->y; @@ -1300,7 +1300,7 @@ _meta_window_shared_new (MetaDisplay *display, * means restacking it. */ if (meta_window_is_stackable (window)) - meta_stack_add (window->screen->stack, + meta_stack_add (window->display->stack, window); else if (window->override_redirect) window->layer = META_LAYER_OVERRIDE_REDIRECT; /* otherwise set by MetaStack */ @@ -1318,14 +1318,14 @@ _meta_window_shared_new (MetaDisplay *display, window->known_to_compositor = TRUE; /* Sync stack changes */ - meta_stack_thaw (window->screen->stack); + meta_stack_thaw (window->display->stack); /* Usually the we'll have queued a stack sync anyways, because we've * added a new frame window or restacked. But if an undecorated * window is mapped, already stacked in the right place, then we * might need to do this explicitly. */ - meta_stack_tracker_queue_sync_stack (window->screen->stack_tracker); + meta_stack_tracker_queue_sync_stack (window->display->stack_tracker); /* disable show desktop mode unless we're a desktop component */ maybe_leave_show_desktop_mode (window); @@ -1444,11 +1444,11 @@ meta_window_unmanage (MetaWindow *window, * other windows in its group to a higher layer */ - meta_stack_freeze (window->screen->stack); + meta_stack_freeze (window->display->stack); group = meta_window_get_group (window); if (group) meta_group_update_layers (group); - meta_stack_thaw (window->screen->stack); + meta_stack_thaw (window->display->stack); } meta_display_remove_pending_pings_for_window (window->display, window); @@ -1537,13 +1537,13 @@ meta_window_unmanage (MetaWindow *window, } if (meta_window_is_in_stack (window)) - meta_stack_remove (window->screen->stack, window); + meta_stack_remove (window->display->stack, window); /* If an undecorated window is being withdrawn, that will change the * stack as presented to the compositing manager, without actually * changing the stacking order of X windows. */ - meta_stack_tracker_queue_sync_stack (window->screen->stack_tracker); + meta_stack_tracker_queue_sync_stack (window->display->stack_tracker); if (window->display->autoraise_window == window) meta_display_remove_autoraise_callback (window->display); @@ -1701,7 +1701,7 @@ implement_showing (MetaWindow *window, /* Some windows are not stackable until being showed, so add those now. */ if (meta_window_is_stackable (window) && !meta_window_is_in_stack (window)) - meta_stack_add (window->screen->stack, window); + meta_stack_add (window->display->stack, window); if (!showing) { @@ -1743,7 +1743,7 @@ stackcmp (gconstpointer a, gconstpointer b) if (aw->screen != bw->screen) return 0; /* don't care how they sort with respect to each other */ else - return meta_stack_windows_cmp (aw->screen->stack, + return meta_stack_windows_cmp (aw->display->stack, aw, bw); } @@ -2460,9 +2460,9 @@ meta_window_show (MetaWindow *window) if (window->hidden) { - meta_stack_freeze (window->screen->stack); + meta_stack_freeze (window->display->stack); window->hidden = FALSE; - meta_stack_thaw (window->screen->stack); + meta_stack_thaw (window->display->stack); did_show = TRUE; } @@ -2591,9 +2591,9 @@ meta_window_hide (MetaWindow *window) if (!window->hidden) { - meta_stack_freeze (window->screen->stack); + meta_stack_freeze (window->display->stack); window->hidden = TRUE; - meta_stack_thaw (window->screen->stack); + meta_stack_thaw (window->display->stack); did_hide = TRUE; } @@ -3412,10 +3412,10 @@ meta_window_make_fullscreen_internal (MetaWindow *window) window->fullscreen = TRUE; - meta_stack_freeze (window->screen->stack); + meta_stack_freeze (window->display->stack); meta_window_raise (window); - meta_stack_thaw (window->screen->stack); + meta_stack_thaw (window->display->stack); meta_window_recalc_features (window); set_net_wm_state (window); @@ -4035,7 +4035,7 @@ meta_window_move_resize_internal (MetaWindow *window, meta_window_foreach_transient (window, maybe_move_attached_dialog, NULL); - meta_stack_update_window_tile_matches (window->screen->stack, + meta_stack_update_window_tile_matches (window->display->stack, window->screen->active_workspace); } @@ -4962,13 +4962,15 @@ meta_window_raise (MetaWindow *window) * constraints in stack.c then magically take care of raising all * the child windows appropriately. */ - if (window->screen->stack == ancestor->screen->stack) - meta_stack_raise (window->screen->stack, ancestor); + if (window->display->stack == ancestor->display->stack) + { + meta_stack_raise (window->display->stack, ancestor); + } else { meta_warning ( "Either stacks aren't per screen or some window has a weird " - "transient_for hint; window->screen->stack != " + "transient_for hint; window->display->stack != " "ancestor->screen->stack. window = %s, ancestor = %s.\n", window->desc, ancestor->desc); /* We could raise the window here, but don't want to do that twice and @@ -4982,7 +4984,7 @@ meta_window_raise (MetaWindow *window) * correct child. See bug 307875. */ if (window != ancestor) - meta_stack_raise (window->screen->stack, window); + meta_stack_raise (window->display->stack, window); g_signal_emit (window, window_signals[RAISED], 0); } @@ -4995,7 +4997,7 @@ meta_window_lower (MetaWindow *window) meta_topic (META_DEBUG_WINDOW_OPS, "Lowering window %s\n", window->desc); - meta_stack_lower (window->screen->stack, window); + meta_stack_lower (window->display->stack, window); } /* @@ -6856,13 +6858,13 @@ meta_window_update_layer (MetaWindow *window) { MetaGroup *group; - meta_stack_freeze (window->screen->stack); + meta_stack_freeze (window->display->stack); group = meta_window_get_group (window); if (group) meta_group_update_layers (group); else - meta_stack_update_layer (window->screen->stack, window); - meta_stack_thaw (window->screen->stack); + meta_stack_update_layer (window->display->stack, window); + meta_stack_thaw (window->display->stack); } /* ensure_mru_position_after ensures that window appears after @@ -7051,7 +7053,7 @@ void meta_window_set_demands_attention (MetaWindow *window) { MetaRectangle candidate_rect, other_rect; - GList *stack = window->screen->stack->sorted; + GList *stack = window->display->stack->sorted; MetaWindow *other_window; gboolean obscured = FALSE; @@ -7740,7 +7742,7 @@ meta_window_find_tile_match (MetaWindow *window, else return NULL; - stack = window->screen->stack; + stack = window->display->stack; for (match = meta_stack_get_top (stack); match; @@ -7759,7 +7761,7 @@ meta_window_find_tile_match (MetaWindow *window, MetaWindow *above, *bottommost, *topmost; MetaRectangle above_rect, bottommost_rect, topmost_rect; - if (meta_stack_windows_cmp (window->screen->stack, match, window) > 0) + if (meta_stack_windows_cmp (window->display->stack, match, window) > 0) { topmost = match; bottommost = window; @@ -7939,7 +7941,7 @@ meta_window_set_transient_for (MetaWindow *window, /* update stacking constraints */ if (!window->override_redirect) - meta_stack_update_transient (window->screen->stack, window); + meta_stack_update_transient (window->display->stack, window); /* possibly change its group. We treat being a window's transient as * equivalent to making it your group leader, to work around shortcomings diff --git a/src/core/workspace.c b/src/core/workspace.c index 24a9f92d3..5b44ce3d2 100644 --- a/src/core/workspace.c +++ b/src/core/workspace.c @@ -1367,7 +1367,7 @@ focus_ancestor_or_top_window (MetaWorkspace *workspace, } } - window = meta_stack_get_default_focus_window (workspace->screen->stack, + window = meta_stack_get_default_focus_window (workspace->screen->display->stack, workspace, not_this_one); diff --git a/src/tests/test-runner.c b/src/tests/test-runner.c index 2eb45b9b5..2471cf3a6 100644 --- a/src/tests/test-runner.c +++ b/src/tests/test-runner.c @@ -213,7 +213,7 @@ test_case_assert_stacking (TestCase *test, GString *expected_string = g_string_new (NULL); int i; - meta_stack_tracker_get_stack (display->screen->stack_tracker, &windows, &n_windows); + meta_stack_tracker_get_stack (display->stack_tracker, &windows, &n_windows); for (i = 0; i < n_windows; i++) { MetaWindow *window = meta_display_lookup_stack_id (display, windows[i]); @@ -234,7 +234,7 @@ test_case_assert_stacking (TestCase *test, else g_string_append_printf (stack_string, "(%s)", window->title); } - else if (windows[i] == display->screen->guard_window) + else if (windows[i] == display->x11_display->guard_window) { if (stack_string->len > 0) g_string_append_c (stack_string, ' '); @@ -285,7 +285,7 @@ test_case_check_xserver_stacking (TestCase *test, guint64 *windows; int n_windows; - meta_stack_tracker_get_stack (display->screen->stack_tracker, &windows, &n_windows); + meta_stack_tracker_get_stack (display->stack_tracker, &windows, &n_windows); for (i = 0; i < n_windows; i++) { diff --git a/src/wayland/meta-window-wayland.c b/src/wayland/meta-window-wayland.c index 3e82d3f78..e50af5c94 100644 --- a/src/wayland/meta-window-wayland.c +++ b/src/wayland/meta-window-wayland.c @@ -88,7 +88,7 @@ meta_window_wayland_manage (MetaWindow *window) meta_display_register_wayland_window (display, window); { - meta_stack_tracker_record_add (window->screen->stack_tracker, + meta_stack_tracker_record_add (window->display->stack_tracker, window->stamp, 0); } @@ -100,7 +100,7 @@ static void meta_window_wayland_unmanage (MetaWindow *window) { { - meta_stack_tracker_record_remove (window->screen->stack_tracker, + meta_stack_tracker_record_remove (window->display->stack_tracker, window->stamp, 0); } diff --git a/src/wayland/meta-xwayland-selection.c b/src/wayland/meta-xwayland-selection.c index f5fc257b6..e46d08ad9 100644 --- a/src/wayland/meta-xwayland-selection.c +++ b/src/wayland/meta-xwayland-selection.c @@ -1344,7 +1344,7 @@ pick_drop_surface (MetaWaylandCompositor *compositor, ClutterPoint pos; clutter_event_get_coords (event, &pos.x, &pos.y); - focus_window = meta_stack_get_default_focus_window_at_point (display->screen->stack, + focus_window = meta_stack_get_default_focus_window_at_point (display->stack, NULL, NULL, pos.x, pos.y); return focus_window ? focus_window->surface : NULL; diff --git a/src/x11/events.c b/src/x11/events.c index 18d530de2..f19e829e0 100644 --- a/src/x11/events.c +++ b/src/x11/events.c @@ -1285,7 +1285,7 @@ handle_other_xevent (MetaDisplay *display, case CreateNotify: { if (event->xcreatewindow.parent == x11_display->xroot) - meta_stack_tracker_create_event (display->screen->stack_tracker, + meta_stack_tracker_create_event (display->stack_tracker, &event->xcreatewindow); } break; @@ -1293,7 +1293,7 @@ handle_other_xevent (MetaDisplay *display, case DestroyNotify: { if (event->xdestroywindow.event == x11_display->xroot) - meta_stack_tracker_destroy_event (display->screen->stack_tracker, + meta_stack_tracker_destroy_event (display->stack_tracker, &event->xdestroywindow); } if (window) @@ -1411,7 +1411,7 @@ handle_other_xevent (MetaDisplay *display, case ReparentNotify: { if (event->xreparent.event == x11_display->xroot) - meta_stack_tracker_reparent_event (display->screen->stack_tracker, + meta_stack_tracker_reparent_event (display->stack_tracker, &event->xreparent); } break; @@ -1420,7 +1420,7 @@ handle_other_xevent (MetaDisplay *display, { if (event->xconfigure.event == x11_display->xroot && event->xconfigure.window != display->screen->composite_overlay_window) - meta_stack_tracker_configure_event (display->screen->stack_tracker, + meta_stack_tracker_configure_event (display->stack_tracker, &event->xconfigure); } diff --git a/src/x11/group.c b/src/x11/group.c index a867a470d..b69586de7 100644 --- a/src/x11/group.c +++ b/src/x11/group.c @@ -276,10 +276,10 @@ meta_group_update_layers (MetaGroup *group) * but doesn't hurt anything. have to handle * groups that span 2 screens. */ - meta_stack_freeze (window->screen->stack); - frozen_stacks = g_slist_prepend (frozen_stacks, window->screen->stack); + meta_stack_freeze (window->display->stack); + frozen_stacks = g_slist_prepend (frozen_stacks, window->display->stack); - meta_stack_update_layer (window->screen->stack, + meta_stack_update_layer (window->display->stack, window); tmp = tmp->next; diff --git a/src/x11/meta-x11-display-private.h b/src/x11/meta-x11-display-private.h index e2a255fdc..a0cee7123 100644 --- a/src/x11/meta-x11-display-private.h +++ b/src/x11/meta-x11-display-private.h @@ -61,6 +61,11 @@ struct _MetaX11Display #include "x11/atomnames.h" #undef item + /* Instead of unmapping withdrawn windows we can leave them mapped + * and restack them below a guard window. When using a compositor + * this allows us to provide live previews of unmapped windows */ + Window guard_window; + GHashTable *xids; /* Managed by group.c */ @@ -144,4 +149,6 @@ void meta_x11_display_set_alarm_filter (MetaX11Display *x11_display, MetaAlarmFilter filter, gpointer data); +void meta_x11_display_create_guard_window (MetaX11Display *x11_display); + #endif /* META_X11_DISPLAY_PRIVATE_H */ diff --git a/src/x11/meta-x11-display.c b/src/x11/meta-x11-display.c index f13620918..61be15d0a 100644 --- a/src/x11/meta-x11-display.c +++ b/src/x11/meta-x11-display.c @@ -64,6 +64,9 @@ G_DEFINE_TYPE (MetaX11Display, meta_x11_display, G_TYPE_OBJECT) static char *get_screen_name (Display *xdisplay, int number); +static void on_monitors_changed (MetaDisplay *display, + MetaX11Display *x11_display); + static void update_cursor_theme (MetaX11Display *x11_display); static void @@ -71,6 +74,26 @@ meta_x11_display_dispose (GObject *object) { MetaX11Display *x11_display = META_X11_DISPLAY (object); + if (x11_display->guard_window != None) + { + MetaStackTracker *stack_tracker = x11_display->display->stack_tracker; + + if (stack_tracker) + { + unsigned long serial; + + serial = XNextRequest (x11_display->xdisplay); + meta_stack_tracker_record_remove (stack_tracker, + x11_display->guard_window, + serial); + } + + XUnmapWindow (x11_display->xdisplay, x11_display->guard_window); + XDestroyWindow (x11_display->xdisplay, x11_display->guard_window); + + x11_display->guard_window = None; + } + if (x11_display->prop_hooks) { meta_x11_display_free_window_prop_hooks (x11_display); @@ -425,12 +448,19 @@ meta_x11_display_new (MetaDisplay *display, GError **error) meta_unsigned_long_equal); x11_display->groups_by_leader = NULL; + x11_display->guard_window = None; x11_display->prop_hooks = NULL; meta_x11_display_init_window_prop_hooks (x11_display); x11_display->group_prop_hooks = NULL; meta_x11_display_init_group_prop_hooks (x11_display); + g_signal_connect_object (display, + "monitors-changed", + G_CALLBACK (on_monitors_changed), + x11_display, + 0); + return x11_display; } @@ -659,3 +689,100 @@ meta_x11_display_set_alarm_filter (MetaX11Display *x11_display, x11_display->alarm_filter = filter; x11_display->alarm_filter_data = data; } + +/* The guard window allows us to leave minimized windows mapped so + * that compositor code may provide live previews of them. + * Instead of being unmapped/withdrawn, they get pushed underneath + * the guard window. We also select events on the guard window, which + * should effectively be forwarded to events on the background actor, + * providing that the scene graph is set up correctly. + */ +static Window +create_guard_window (MetaX11Display *x11_display) +{ + XSetWindowAttributes attributes; + Window guard_window; + gulong create_serial; + + attributes.event_mask = NoEventMask; + attributes.override_redirect = True; + + /* We have to call record_add() after we have the new window ID, + * so save the serial for the CreateWindow request until then */ + create_serial = XNextRequest (x11_display->xdisplay); + guard_window = + XCreateWindow (x11_display->xdisplay, + x11_display->xroot, + 0, /* x */ + 0, /* y */ + x11_display->display->rect.width, + x11_display->display->rect.height, + 0, /* border width */ + 0, /* depth */ + InputOnly, /* class */ + CopyFromParent, /* visual */ + CWEventMask | CWOverrideRedirect, + &attributes); + + /* https://bugzilla.gnome.org/show_bug.cgi?id=710346 */ + XStoreName (x11_display->xdisplay, guard_window, "mutter guard window"); + + { + if (!meta_is_wayland_compositor ()) + { + MetaBackendX11 *backend = META_BACKEND_X11 (meta_get_backend ()); + Display *backend_xdisplay = meta_backend_x11_get_xdisplay (backend); + unsigned char mask_bits[XIMaskLen (XI_LASTEVENT)] = { 0 }; + XIEventMask mask = { XIAllMasterDevices, sizeof (mask_bits), mask_bits }; + + XISetMask (mask.mask, XI_ButtonPress); + XISetMask (mask.mask, XI_ButtonRelease); + XISetMask (mask.mask, XI_Motion); + + /* Sync on the connection we created the window on to + * make sure it's created before we select on it on the + * backend connection. */ + XSync (x11_display->xdisplay, False); + + XISelectEvents (backend_xdisplay, guard_window, &mask, 1); + } + } + + meta_stack_tracker_record_add (x11_display->display->stack_tracker, + guard_window, + create_serial); + + meta_stack_tracker_lower (x11_display->display->stack_tracker, + guard_window); + + XMapWindow (x11_display->xdisplay, guard_window); + return guard_window; +} + +void +meta_x11_display_create_guard_window (MetaX11Display *x11_display) +{ + if (x11_display->guard_window == None) + x11_display->guard_window = create_guard_window (x11_display); +} + +static void +on_monitors_changed (MetaDisplay *display, + MetaX11Display *x11_display) +{ + /* Resize the guard window to fill the screen again. */ + if (x11_display->guard_window != None) + { + XWindowChanges changes; + + changes.x = 0; + changes.y = 0; + changes.width = display->rect.width; + changes.height = display->rect.height; + + XConfigureWindow (x11_display->xdisplay, + x11_display->guard_window, + CWX | CWY | CWWidth | CWHeight, + &changes); + } +} diff --git a/src/x11/window-x11.c b/src/x11/window-x11.c index 66bc8ae19..16b09b565 100644 --- a/src/x11/window-x11.c +++ b/src/x11/window-x11.c @@ -2984,7 +2984,7 @@ is_our_xwindow (MetaDisplay *display, if (xwindow == screen->wm_cm_selection_window) return TRUE; - if (xwindow == screen->guard_window) + if (xwindow == display->x11_display->guard_window) return TRUE; if (xwindow == screen->composite_overlay_window)