mirror of
https://github.com/brl/mutter.git
synced 2025-08-07 09:04:41 +00:00
Merge branch 'fix-stacking' into clutter
This commit is contained in:
@@ -132,6 +132,11 @@ struct _MetaScreen
|
||||
|
||||
/* Managed by compositor.c */
|
||||
gpointer compositor_data;
|
||||
|
||||
/* 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;
|
||||
};
|
||||
|
||||
MetaScreen* meta_screen_new (MetaDisplay *display,
|
||||
|
@@ -311,6 +311,38 @@ reload_xinerama_infos (MetaScreen *screen)
|
||||
g_assert (screen->xinerama_infos != NULL);
|
||||
}
|
||||
|
||||
/* 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. */
|
||||
static Window
|
||||
create_guard_window (Display *xdisplay, MetaScreen *screen)
|
||||
{
|
||||
XSetWindowAttributes attributes;
|
||||
Window guard_window;
|
||||
|
||||
attributes.event_mask = NoEventMask;
|
||||
attributes.override_redirect = True;
|
||||
attributes.background_pixel = BlackPixel (xdisplay, screen->number);
|
||||
|
||||
guard_window =
|
||||
XCreateWindow (xdisplay,
|
||||
screen->xroot,
|
||||
0, /* x */
|
||||
0, /* y */
|
||||
screen->rect.width,
|
||||
screen->rect.height,
|
||||
0, /* border width */
|
||||
CopyFromParent, /* depth */
|
||||
CopyFromParent, /* class */
|
||||
CopyFromParent, /* visual */
|
||||
CWEventMask|CWOverrideRedirect|CWBackPixel,
|
||||
&attributes);
|
||||
XLowerWindow (xdisplay, guard_window);
|
||||
XMapWindow (xdisplay, guard_window);
|
||||
return guard_window;
|
||||
}
|
||||
|
||||
MetaScreen*
|
||||
meta_screen_new (MetaDisplay *display,
|
||||
int number,
|
||||
@@ -490,6 +522,8 @@ meta_screen_new (MetaDisplay *display,
|
||||
screen->vertical_workspaces = FALSE;
|
||||
screen->starting_corner = META_SCREEN_TOPLEFT;
|
||||
screen->compositor_data = NULL;
|
||||
|
||||
screen->guard_window = create_guard_window (xdisplay, screen);
|
||||
|
||||
{
|
||||
XFontStruct *font_info;
|
||||
@@ -760,6 +794,7 @@ meta_screen_manage_all_windows (MetaScreen *screen)
|
||||
info->xwindow == screen->flash_window ||
|
||||
#ifdef HAVE_COMPOSITE_EXTENSIONS
|
||||
info->xwindow == screen->wm_cm_selection_window ||
|
||||
info->xwindow == screen->guard_window ||
|
||||
#endif
|
||||
info->xwindow == screen->wm_sn_selection_window) {
|
||||
meta_verbose ("Not managing our own windows\n");
|
||||
@@ -772,17 +807,6 @@ meta_screen_manage_all_windows (MetaScreen *screen)
|
||||
}
|
||||
meta_stack_thaw (screen->stack);
|
||||
|
||||
/*
|
||||
* Because the windows have already been created/mapped/etc, if the compositor
|
||||
* maintains a separate stack based on ConfigureNotify restack messages, it
|
||||
* will not necessarily get what it needs; we explicitely notify the
|
||||
* compositor to fix up its stacking order.
|
||||
*
|
||||
* For more on this issue, see comments in meta_window_hide().
|
||||
*/
|
||||
if (screen->display->compositor)
|
||||
meta_compositor_ensure_stack_order (screen->display->compositor, screen);
|
||||
|
||||
g_list_foreach (windows, (GFunc)g_free, NULL);
|
||||
g_list_free (windows);
|
||||
|
||||
|
@@ -35,6 +35,10 @@
|
||||
#include "prefs.h"
|
||||
#include "workspace.h"
|
||||
|
||||
#ifdef HAVE_COMPOSITE_EXTENSIONS
|
||||
#include "compositor.h"
|
||||
#endif
|
||||
|
||||
#include <X11/Xatom.h>
|
||||
|
||||
#define WINDOW_HAS_TRANSIENT_TYPE(w) \
|
||||
@@ -1057,6 +1061,7 @@ stack_sync_to_server (MetaStack *stack)
|
||||
GArray *stacked;
|
||||
GArray *root_children_stacked;
|
||||
GList *tmp;
|
||||
GArray *all_hidden;
|
||||
|
||||
/* Bail out if frozen */
|
||||
if (stack->freeze_count > 0)
|
||||
@@ -1065,6 +1070,10 @@ stack_sync_to_server (MetaStack *stack)
|
||||
meta_topic (META_DEBUG_STACK, "Syncing window stack to server\n");
|
||||
|
||||
stack_ensure_sorted (stack);
|
||||
|
||||
meta_compositor_sync_stack (stack->screen->display->compositor,
|
||||
stack->screen,
|
||||
stack->sorted);
|
||||
|
||||
/* Create stacked xwindow arrays.
|
||||
* Painfully, "stacked" is in bottom-to-top order for the
|
||||
@@ -1073,29 +1082,42 @@ stack_sync_to_server (MetaStack *stack)
|
||||
*/
|
||||
stacked = g_array_new (FALSE, FALSE, sizeof (Window));
|
||||
root_children_stacked = g_array_new (FALSE, FALSE, sizeof (Window));
|
||||
all_hidden = g_array_new (FALSE, FALSE, sizeof (Window));
|
||||
|
||||
/* The screen guard window sits above all hidden windows and acts as
|
||||
* a barrier to input reaching these windows. */
|
||||
g_array_append_val (all_hidden, stack->screen->guard_window);
|
||||
|
||||
meta_topic (META_DEBUG_STACK, "Top to bottom: ");
|
||||
meta_push_no_msg_prefix ();
|
||||
|
||||
tmp = stack->sorted;
|
||||
while (tmp != NULL)
|
||||
|
||||
for (tmp = stack->sorted; tmp != NULL; tmp = tmp->next)
|
||||
{
|
||||
MetaWindow *w;
|
||||
|
||||
w = tmp->data;
|
||||
MetaWindow *w = tmp->data;
|
||||
Window top_level_window;
|
||||
|
||||
meta_topic (META_DEBUG_STACK, "%u:%d - %s ",
|
||||
w->layer, w->stack_position, w->desc);
|
||||
|
||||
/* remember, stacked is in reverse order (bottom to top) */
|
||||
g_array_prepend_val (stacked, w->xwindow);
|
||||
|
||||
/* build XRestackWindows() array from top to bottom */
|
||||
if (w->frame)
|
||||
g_array_append_val (root_children_stacked, w->frame->xwindow);
|
||||
top_level_window = w->frame->xwindow;
|
||||
else
|
||||
g_array_append_val (root_children_stacked, w->xwindow);
|
||||
|
||||
meta_topic (META_DEBUG_STACK, "%u:%d - %s ", w->layer, w->stack_position, w->desc);
|
||||
|
||||
tmp = tmp->next;
|
||||
top_level_window = w->xwindow;
|
||||
|
||||
/* We don't restack hidden windows along with the rest, though they are
|
||||
* reflected in the _NET hints. Hidden windows all get pushed below
|
||||
* the screens fullscreen guard_window. */
|
||||
if (w->hidden)
|
||||
{
|
||||
g_array_append_val (all_hidden, top_level_window);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* build XRestackWindows() array from top to bottom */
|
||||
g_array_append_val (root_children_stacked, top_level_window);
|
||||
}
|
||||
|
||||
meta_topic (META_DEBUG_STACK, "\n");
|
||||
@@ -1213,6 +1235,13 @@ stack_sync_to_server (MetaStack *stack)
|
||||
}
|
||||
}
|
||||
|
||||
/* Push hidden windows to the bottom of the stack under the guard window */
|
||||
XLowerWindow (stack->screen->display->xdisplay, stack->screen->guard_window);
|
||||
XRestackWindows (stack->screen->display->xdisplay,
|
||||
(Window *)all_hidden->data,
|
||||
all_hidden->len);
|
||||
g_array_free (all_hidden, TRUE);
|
||||
|
||||
meta_error_trap_pop (stack->screen->display, FALSE);
|
||||
/* on error, a window was destroyed; it should eventually
|
||||
* get removed from the stacking list when we unmanage it
|
||||
|
@@ -348,6 +348,10 @@ struct _MetaWindow
|
||||
|
||||
/* maintained by group.c */
|
||||
MetaGroup *group;
|
||||
|
||||
#ifdef HAVE_COMPOSITE_EXTENSIONS
|
||||
void *compositor_private;
|
||||
#endif
|
||||
};
|
||||
|
||||
/* These differ from window->has_foo_func in that they consider
|
||||
@@ -424,9 +428,6 @@ void meta_window_resize_with_gravity (MetaWindow *window,
|
||||
int gravity);
|
||||
|
||||
|
||||
/* Return whether the window would be showing if we were on its workspace */
|
||||
gboolean meta_window_showing_on_its_workspace (MetaWindow *window);
|
||||
|
||||
/* Return whether the window should be currently mapped */
|
||||
gboolean meta_window_should_be_showing (MetaWindow *window);
|
||||
|
||||
|
@@ -476,7 +476,7 @@ meta_window_new_with_attrs (MetaDisplay *display,
|
||||
/* if already mapped, no need to worry about focus-on-first-time-showing */
|
||||
window->showing_for_first_time = !window->mapped;
|
||||
/* if already mapped we don't want to do the placement thing */
|
||||
window->placed = window->mapped;
|
||||
window->placed = (window->mapped && !window->hidden);
|
||||
if (window->placed)
|
||||
meta_topic (META_DEBUG_PLACEMENT,
|
||||
"Not placing window 0x%lx since it's already mapped\n",
|
||||
@@ -558,6 +558,8 @@ meta_window_new_with_attrs (MetaDisplay *display,
|
||||
window->stack_position = -1;
|
||||
window->initial_workspace = 0; /* not used */
|
||||
window->initial_timestamp = 0; /* not used */
|
||||
|
||||
window->compositor_private = NULL;
|
||||
|
||||
meta_display_register_x_window (display, &window->xwindow, window);
|
||||
|
||||
@@ -1459,7 +1461,7 @@ implement_showing (MetaWindow *window,
|
||||
* be minimized, and we are on the current workspace.
|
||||
*/
|
||||
if (on_workspace && window->minimized && window->mapped &&
|
||||
!meta_prefs_get_reduced_resources ())
|
||||
!window->hidden && !meta_prefs_get_reduced_resources ())
|
||||
{
|
||||
MetaRectangle icon_rect, window_rect;
|
||||
gboolean result;
|
||||
@@ -2244,38 +2246,41 @@ meta_window_show (MetaWindow *window)
|
||||
XMapWindow (window->display->xdisplay, window->xwindow);
|
||||
meta_error_trap_pop (window->display, FALSE);
|
||||
did_show = TRUE;
|
||||
window->hidden = FALSE;
|
||||
}
|
||||
else if (meta_prefs_get_live_hidden_windows ())
|
||||
|
||||
if (meta_prefs_get_live_hidden_windows ())
|
||||
{
|
||||
if (window->hidden && window->type != META_WINDOW_DESKTOP)
|
||||
if (window->hidden)
|
||||
{
|
||||
window->hidden = FALSE;
|
||||
meta_stack_freeze (window->screen->stack);
|
||||
meta_window_update_layer (window);
|
||||
meta_window_raise (window);
|
||||
window->hidden = FALSE;
|
||||
/* Inform the compositor that the window isn't hidden */
|
||||
meta_compositor_set_window_hidden (window->display->compositor,
|
||||
window->screen,
|
||||
window,
|
||||
window->hidden);
|
||||
meta_stack_thaw (window->screen->stack);
|
||||
did_show = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if (did_show && window->was_minimized)
|
||||
{
|
||||
MetaRectangle window_rect;
|
||||
MetaRectangle icon_rect;
|
||||
|
||||
window->was_minimized = FALSE;
|
||||
|
||||
if (meta_window_get_icon_geometry (window, &icon_rect))
|
||||
{
|
||||
meta_window_get_outer_rect (window, &window_rect);
|
||||
|
||||
meta_effect_run_unminimize (window,
|
||||
&window_rect,
|
||||
&icon_rect,
|
||||
NULL, NULL);
|
||||
}
|
||||
}
|
||||
{
|
||||
MetaRectangle window_rect;
|
||||
MetaRectangle icon_rect;
|
||||
|
||||
window->was_minimized = FALSE;
|
||||
|
||||
if (meta_window_get_icon_geometry (window, &icon_rect))
|
||||
{
|
||||
meta_window_get_outer_rect (window, &window_rect);
|
||||
|
||||
meta_effect_run_unminimize (window,
|
||||
&window_rect,
|
||||
&icon_rect,
|
||||
NULL, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
if (window->iconic)
|
||||
{
|
||||
@@ -2331,50 +2336,34 @@ meta_window_hide (MetaWindow *window)
|
||||
|
||||
if (meta_prefs_get_live_hidden_windows ())
|
||||
{
|
||||
gboolean was_mapped;
|
||||
|
||||
if (window->hidden)
|
||||
return;
|
||||
|
||||
was_mapped = window->mapped;
|
||||
|
||||
if (!was_mapped)
|
||||
meta_window_show (window);
|
||||
|
||||
window->hidden = TRUE;
|
||||
did_hide = TRUE;
|
||||
if (!window->mapped)
|
||||
{
|
||||
Window top_level_window;
|
||||
meta_topic (META_DEBUG_WINDOW_STATE,
|
||||
"%s actually needs map\n", window->desc);
|
||||
window->mapped = TRUE;
|
||||
meta_error_trap_push (window->display);
|
||||
if (window->frame)
|
||||
top_level_window = window->frame->xwindow;
|
||||
else
|
||||
top_level_window = window->xwindow;
|
||||
XMapWindow (window->display->xdisplay, top_level_window);
|
||||
meta_error_trap_pop (window->display, FALSE);
|
||||
}
|
||||
|
||||
meta_stack_freeze (window->screen->stack);
|
||||
meta_window_update_layer (window);
|
||||
meta_window_lower (window);
|
||||
window->hidden = TRUE;
|
||||
/* Tell the compositor this window is now hidden */
|
||||
meta_compositor_set_window_hidden (window->display->compositor,
|
||||
window->screen,
|
||||
window,
|
||||
window->hidden);
|
||||
meta_stack_thaw (window->screen->stack);
|
||||
|
||||
/*
|
||||
* The X server does not implement lower-below semantics for restacking
|
||||
* windows, only raise-above; consequently each single lower-bottom call
|
||||
* gets translated to a bunch of raise-above moves, and often there will
|
||||
* be no ConfigureNotify at all for the window we are lowering (only for
|
||||
* its siblings). If we mix the lower-bottom sequence of calls with
|
||||
* mapping of windows, the batch of ConfigureNotify events that is
|
||||
* generated does not correctly reflect the stack order, and if the
|
||||
* Compositor relies on these for its own internal stack, it will
|
||||
* invariably end up with wrong stacking order.
|
||||
*
|
||||
* I have not been able to find a way to get this just work so that the
|
||||
* resulting ConfigureNotify messages would reflect the actual state of
|
||||
* the stack, so in the special case we map a window while hiding it, we
|
||||
* explitely notify the compositor that it should ensure its stacking
|
||||
* matches the cannonical stack of the WM.
|
||||
*
|
||||
* NB: this is uncommon, and generally only happens on the WM start up,
|
||||
* when we are taking over pre-existing windows, so this brute-force
|
||||
* fix is OK performance wise.
|
||||
*/
|
||||
if (!was_mapped && window->display->compositor)
|
||||
{
|
||||
meta_compositor_ensure_stack_order (window->display->compositor,
|
||||
window->screen);
|
||||
}
|
||||
did_hide = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -4149,7 +4138,7 @@ meta_window_focus (MetaWindow *window,
|
||||
|
||||
meta_window_flush_calc_showing (window);
|
||||
|
||||
if (!window->mapped && !window->shaded)
|
||||
if ((!window->mapped || window->hidden) && !window->shaded)
|
||||
{
|
||||
meta_topic (META_DEBUG_FOCUS,
|
||||
"Window %s is not showing, not focusing after all\n",
|
||||
@@ -8038,7 +8027,7 @@ meta_window_update_layer (MetaWindow *window)
|
||||
|
||||
meta_stack_freeze (window->screen->stack);
|
||||
group = meta_window_get_group (window);
|
||||
if (!window->hidden && group)
|
||||
if (group)
|
||||
meta_group_update_layers (group);
|
||||
else
|
||||
meta_stack_update_layer (window->screen->stack, window);
|
||||
|
Reference in New Issue
Block a user