Merge branch 'fix-stacking' into clutter
This commit is contained in:
commit
3211fb04d3
@ -79,8 +79,14 @@ struct _MetaCompositor
|
||||
MetaWorkspace *to,
|
||||
MetaMotionDirection direction);
|
||||
|
||||
void (*ensure_stack_order) (MetaCompositor *compositor,
|
||||
MetaScreen *screen);
|
||||
void (*sync_stack) (MetaCompositor *compositor,
|
||||
MetaScreen *screen,
|
||||
GList *stack);
|
||||
|
||||
void (*set_window_hidden) (MetaCompositor *compositor,
|
||||
MetaScreen *screen,
|
||||
MetaWindow *window,
|
||||
gboolean hidden);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -243,11 +243,25 @@ meta_compositor_switch_workspace (MetaCompositor *compositor,
|
||||
}
|
||||
|
||||
void
|
||||
meta_compositor_ensure_stack_order (MetaCompositor *compositor,
|
||||
MetaScreen *screen)
|
||||
meta_compositor_sync_stack (MetaCompositor *compositor,
|
||||
MetaScreen *screen,
|
||||
GList *stack)
|
||||
{
|
||||
#ifdef HAVE_COMPOSITE_EXTENSIONS
|
||||
if (compositor && compositor->ensure_stack_order)
|
||||
compositor->ensure_stack_order (compositor, screen);
|
||||
if (compositor && compositor->sync_stack)
|
||||
compositor->sync_stack (compositor, screen, stack);
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
meta_compositor_set_window_hidden (MetaCompositor *compositor,
|
||||
MetaScreen *screen,
|
||||
MetaWindow *window,
|
||||
gboolean hidden)
|
||||
{
|
||||
#ifdef HAVE_COMPOSITE_EXTENSIONS
|
||||
if (compositor && compositor->set_window_hidden)
|
||||
compositor->set_window_hidden (compositor, screen, window, hidden);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -142,6 +142,7 @@ typedef struct _MetaCompScreen
|
||||
MetaScreen *screen;
|
||||
|
||||
ClutterActor *stage, *window_group, *overlay_group;
|
||||
ClutterActor *hidden_group;
|
||||
GList *windows;
|
||||
GHashTable *windows_by_xid;
|
||||
MetaWindow *focus_window;
|
||||
@ -474,6 +475,13 @@ static MutterWindow *
|
||||
find_window_in_display (MetaDisplay *display, Window xwindow)
|
||||
{
|
||||
GSList *index;
|
||||
MetaWindow *window = meta_display_lookup_x_window (display, xwindow);
|
||||
|
||||
if (window)
|
||||
{
|
||||
if (window->compositor_private)
|
||||
return window->compositor_private;
|
||||
}
|
||||
|
||||
for (index = meta_display_get_screens (display);
|
||||
index;
|
||||
@ -777,22 +785,18 @@ mutter_window_get_workspace (MutterWindow *mcw)
|
||||
}
|
||||
|
||||
gboolean
|
||||
mutter_window_is_hidden (MutterWindow *mcw)
|
||||
mutter_window_showing_on_its_workspace (MutterWindow *mcw)
|
||||
{
|
||||
MutterWindowPrivate *priv;
|
||||
|
||||
if (!mcw)
|
||||
return FALSE;
|
||||
|
||||
/* If override redirect: */
|
||||
if (!mcw->priv->window)
|
||||
return TRUE;
|
||||
|
||||
priv = mcw->priv;
|
||||
|
||||
if (!priv->window)
|
||||
return FALSE;
|
||||
|
||||
return meta_window_is_hidden (priv->window);
|
||||
return meta_window_showing_on_its_workspace (mcw->priv->window);
|
||||
}
|
||||
|
||||
|
||||
static void repair_win (MutterWindow *cw);
|
||||
static void map_win (MutterWindow *cw);
|
||||
static void unmap_win (MutterWindow *cw);
|
||||
@ -831,7 +835,8 @@ mutter_finish_workspace_switch (MetaCompScreen *info)
|
||||
l = l->prev;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
/*
|
||||
* Fix up stacking order in case the plugin messed it up.
|
||||
*/
|
||||
@ -871,6 +876,7 @@ mutter_finish_workspace_switch (MetaCompScreen *info)
|
||||
|
||||
l = l->prev;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* printf ("... FINISHED DESKTOP SWITCH\n"); */
|
||||
|
||||
@ -1028,6 +1034,7 @@ mutter_window_detach (MutterWindow *self)
|
||||
static void
|
||||
destroy_win (MutterWindow *cw, gboolean no_effect)
|
||||
{
|
||||
MetaWindow *window;
|
||||
MetaCompScreen *info;
|
||||
MutterWindowPrivate *priv;
|
||||
MetaScreen *screen;
|
||||
@ -1037,6 +1044,14 @@ destroy_win (MutterWindow *cw, gboolean no_effect)
|
||||
|
||||
priv = cw->priv;
|
||||
|
||||
window = meta_display_lookup_x_window (priv->screen->display, priv->xwindow);
|
||||
if (window)
|
||||
window->compositor_private = NULL;
|
||||
|
||||
/* If not override redirect */
|
||||
if (window)
|
||||
window->compositor_private = NULL;
|
||||
|
||||
screen = priv->screen;
|
||||
info = meta_screen_get_compositor_data (screen);
|
||||
|
||||
@ -1073,157 +1088,6 @@ destroy_win (MutterWindow *cw, gboolean no_effect)
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
restack_win (MutterWindow *cw, Window above)
|
||||
{
|
||||
MutterWindowPrivate *priv = cw->priv;
|
||||
MetaScreen *screen = priv->screen;
|
||||
MetaCompScreen *info = meta_screen_get_compositor_data (screen);
|
||||
Window previous_above;
|
||||
GList *sibling, *next;
|
||||
gboolean hide = FALSE;
|
||||
gboolean live_mode;
|
||||
|
||||
live_mode = meta_prefs_get_live_hidden_windows ();
|
||||
|
||||
if (priv->window && meta_window_is_hidden (priv->window))
|
||||
hide = TRUE;
|
||||
|
||||
sibling = g_list_find (info->windows, (gconstpointer) cw);
|
||||
next = g_list_next (sibling);
|
||||
previous_above = None;
|
||||
|
||||
if (next)
|
||||
{
|
||||
MutterWindow *ncw = next->data;
|
||||
previous_above = ncw->priv->xwindow;
|
||||
}
|
||||
|
||||
/* If above is set to None, the window whose state was changed is on
|
||||
* the bottom of the stack with respect to sibling.
|
||||
*/
|
||||
if (above == None)
|
||||
{
|
||||
#if 0
|
||||
printf ("Raising to top %p [0x%x] (%s)\n",
|
||||
cw, (guint) priv->xwindow,
|
||||
priv->window ? priv->window->desc : "unknown");
|
||||
#endif
|
||||
/* Insert at bottom of window stack */
|
||||
CHECK_LIST_INTEGRITY_START(info->windows)
|
||||
info->windows = g_list_delete_link (info->windows, sibling);
|
||||
info->windows = g_list_append (info->windows, cw);
|
||||
CHECK_LIST_INTEGRITY_END(info->windows)
|
||||
|
||||
if (!info->switch_workspace_in_progress)
|
||||
{
|
||||
clutter_actor_raise_top (CLUTTER_ACTOR (cw));
|
||||
}
|
||||
}
|
||||
else if (previous_above != above)
|
||||
{
|
||||
GList *index;
|
||||
|
||||
/* Find the window that matches 'above'; if the window is hidden (i.e.,
|
||||
* minimized, on a different desktop) find the first window above it tha
|
||||
* is not and use it instead; if we cannot find any such window then
|
||||
* fallback to raise to top (without this, we end up stacking up the act
|
||||
* in the wrong place, and it probably will not be visible at all).
|
||||
*/
|
||||
for (index = info->windows; index; index = index->next)
|
||||
{
|
||||
MutterWindow *cw2 = (MutterWindow *) index->data;
|
||||
if (cw2->priv->xwindow == above)
|
||||
{
|
||||
if (live_mode && !hide && cw2->priv->window &&
|
||||
meta_window_is_hidden (cw2->priv->window))
|
||||
{
|
||||
index = index->prev;
|
||||
|
||||
while (index)
|
||||
{
|
||||
MutterWindow *prev = index->data;
|
||||
|
||||
if (!prev->priv->window ||
|
||||
!meta_window_is_hidden (prev->priv->window))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
index = index->prev;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (index != NULL)
|
||||
{
|
||||
if (index != sibling)
|
||||
{
|
||||
ClutterActor *above_win = index->data;
|
||||
|
||||
CHECK_LIST_INTEGRITY_START(info->windows)
|
||||
info->windows = g_list_delete_link (info->windows, sibling);
|
||||
|
||||
info->windows = g_list_insert_before (info->windows, index, cw);
|
||||
CHECK_LIST_INTEGRITY_END(info->windows)
|
||||
|
||||
#if 0
|
||||
printf ("Raising %p [0x%x] (%s) hidden %d, above %p [0x%x] (%s)\n",
|
||||
cw, (guint) priv->xwindow,
|
||||
priv->window ? priv->window->desc : "unknown", hide,
|
||||
cw2, (guint) cw2->priv->xwindow,
|
||||
cw2->priv->window ? cw2->priv->window->desc : "unknown");
|
||||
#endif
|
||||
if (!info->switch_workspace_in_progress)
|
||||
{
|
||||
clutter_actor_raise (CLUTTER_ACTOR (cw), above_win);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (live_mode)
|
||||
{
|
||||
if (!hide)
|
||||
{
|
||||
#if 0
|
||||
printf ("Raising to top as fallback %p [0x%x] (%s)\n",
|
||||
cw, (guint) priv->xwindow,
|
||||
priv->window ? priv->window->desc : "unknown");
|
||||
#endif
|
||||
/* Insert at bottom of window stack */
|
||||
CHECK_LIST_INTEGRITY_START(info->windows)
|
||||
info->windows = g_list_delete_link (info->windows, sibling);
|
||||
info->windows = g_list_append (info->windows, cw);
|
||||
CHECK_LIST_INTEGRITY_END(info->windows)
|
||||
|
||||
if (!info->switch_workspace_in_progress)
|
||||
{
|
||||
clutter_actor_raise_top (CLUTTER_ACTOR (cw));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
#if 0
|
||||
printf ("Lowering to bottom as fallback %p [0x%x] (%s)\n",
|
||||
cw, (guint) priv->xwindow,
|
||||
priv->window ? priv->window->desc : "unknown");
|
||||
#endif
|
||||
/* Insert at bottom of window stack */
|
||||
CHECK_LIST_INTEGRITY_START(info->windows)
|
||||
info->windows = g_list_delete_link (info->windows, sibling);
|
||||
info->windows = g_list_prepend (info->windows, cw);
|
||||
CHECK_LIST_INTEGRITY_END(info->windows)
|
||||
|
||||
if (!info->switch_workspace_in_progress)
|
||||
{
|
||||
clutter_actor_lower_bottom (CLUTTER_ACTOR (cw));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
resize_win (MutterWindow *cw,
|
||||
int x,
|
||||
@ -1361,6 +1225,20 @@ add_win (MetaScreen *screen, MetaWindow *window, Window xwindow)
|
||||
Display *xdisplay = meta_display_get_xdisplay (display);
|
||||
XWindowAttributes attrs;
|
||||
gulong events_needed;
|
||||
|
||||
/* Note: this blacklist internal windows is copied from screen.c
|
||||
* Ideally add_win shouldn't be driven by CreateNotify events and
|
||||
* should instead be an event directly from metacity core. */
|
||||
if (xwindow == screen->no_focus_window ||
|
||||
xwindow == screen->flash_window ||
|
||||
#ifdef HAVE_COMPOSITE_EXTENSIONS
|
||||
xwindow == screen->wm_cm_selection_window ||
|
||||
xwindow == screen->guard_window ||
|
||||
#endif
|
||||
xwindow == screen->wm_sn_selection_window) {
|
||||
meta_verbose ("Not managing our own windows\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (info == NULL)
|
||||
return;
|
||||
@ -1446,6 +1324,11 @@ add_win (MetaScreen *screen, MetaWindow *window, Window xwindow)
|
||||
|
||||
printf("\n");
|
||||
#endif
|
||||
|
||||
/* Hang our compositor window state off the MetaWindow for fast retrieval
|
||||
* if we have one */
|
||||
if (window)
|
||||
window->compositor_private = cw;
|
||||
|
||||
/*
|
||||
* Add this to the list at the top of the stack before it is mapped so that
|
||||
@ -1530,7 +1413,7 @@ repair_win (MutterWindow *cw)
|
||||
full = TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
/*
|
||||
* TODO -- on some gfx hardware updating the whole texture instead of
|
||||
* the individual rectangles is actually quicker, so we might want to
|
||||
* make this a configurable option (on desktop HW with multiple pipelines
|
||||
@ -1601,7 +1484,7 @@ process_create (Mutter *compositor,
|
||||
{
|
||||
MetaScreen *screen;
|
||||
Window xwindow = event->window;
|
||||
MutterWindow *mw;
|
||||
MutterWindow *cw;
|
||||
|
||||
screen = meta_display_screen_for_root (compositor->display, event->parent);
|
||||
|
||||
@ -1612,18 +1495,18 @@ process_create (Mutter *compositor,
|
||||
* This is quite silly as we end up creating windows as then immediatly
|
||||
* destroying them as they (likely) become framed and thus reparented.
|
||||
*/
|
||||
mw = find_window_for_screen (screen, xwindow);
|
||||
cw = find_window_for_screen (screen, xwindow);
|
||||
|
||||
if (!mw && window)
|
||||
if (!cw && window)
|
||||
{
|
||||
xwindow = meta_window_get_xwindow (window);
|
||||
|
||||
mw = find_window_for_screen (screen, xwindow);
|
||||
cw = find_window_for_screen (screen, xwindow);
|
||||
}
|
||||
|
||||
if (mw)
|
||||
if (cw)
|
||||
{
|
||||
destroy_win (mw, TRUE);
|
||||
destroy_win (cw, TRUE);
|
||||
}
|
||||
|
||||
add_win (screen, window, event->window);
|
||||
@ -1635,7 +1518,7 @@ process_reparent (Mutter *compositor,
|
||||
MetaWindow *window)
|
||||
{
|
||||
MetaScreen *screen;
|
||||
MutterWindow *mw;
|
||||
MutterWindow *cw;
|
||||
Window xwindow = event->window;
|
||||
gboolean viewable = FALSE;
|
||||
|
||||
@ -1643,28 +1526,16 @@ process_reparent (Mutter *compositor,
|
||||
|
||||
if (!screen)
|
||||
return;
|
||||
|
||||
if (window)
|
||||
cw = window->compositor_private;
|
||||
else
|
||||
cw = find_window_for_screen (screen, xwindow);
|
||||
|
||||
mw = find_window_for_screen (screen, xwindow);
|
||||
|
||||
if (!mw && window)
|
||||
if (cw)
|
||||
{
|
||||
xwindow = meta_window_get_xwindow (window);
|
||||
|
||||
mw = find_window_for_screen (screen, xwindow);
|
||||
}
|
||||
|
||||
if (!mw && window)
|
||||
{
|
||||
xwindow = meta_window_get_xwindow (window);
|
||||
|
||||
mw = find_window_for_screen (screen, xwindow);
|
||||
}
|
||||
|
||||
|
||||
if (mw)
|
||||
{
|
||||
viewable = (mw->priv->attrs.map_state == IsViewable);
|
||||
destroy_win (mw, TRUE);
|
||||
viewable = (cw->priv->attrs.map_state == IsViewable);
|
||||
destroy_win (cw, TRUE);
|
||||
}
|
||||
|
||||
add_win (screen, window, event->window);
|
||||
@ -1755,11 +1626,11 @@ update_shape (Mutter *compositor,
|
||||
|
||||
#ifdef HAVE_SHAPE
|
||||
static void
|
||||
process_shape (Mutter *compositor,
|
||||
XShapeEvent *event)
|
||||
process_shape (Mutter *compositor,
|
||||
XShapeEvent *event)
|
||||
{
|
||||
MutterWindow *cw = find_window_in_display (compositor->display,
|
||||
event->window);
|
||||
event->window);
|
||||
MutterWindowPrivate *priv = cw->priv;
|
||||
|
||||
if (cw == NULL)
|
||||
@ -1793,7 +1664,6 @@ process_configure_notify (Mutter *compositor,
|
||||
|
||||
if (cw)
|
||||
{
|
||||
restack_win (cw, event->above);
|
||||
resize_win (cw,
|
||||
event->x, event->y, event->width, event->height,
|
||||
event->border_width, event->override_redirect);
|
||||
@ -1831,47 +1701,20 @@ process_configure_notify (Mutter *compositor,
|
||||
}
|
||||
|
||||
static void
|
||||
process_circulate_notify (Mutter *compositor,
|
||||
XCirculateEvent *event)
|
||||
process_unmap (Mutter *compositor,
|
||||
XUnmapEvent *event)
|
||||
{
|
||||
MutterWindow *cw = find_window_in_display (compositor->display,
|
||||
event->window);
|
||||
MutterWindow *top;
|
||||
MetaCompScreen *info;
|
||||
Window above;
|
||||
MutterWindowPrivate *priv;
|
||||
|
||||
if (!cw)
|
||||
return;
|
||||
|
||||
priv = cw->priv;
|
||||
|
||||
info = meta_screen_get_compositor_data (priv->screen);
|
||||
top = info->windows->data;
|
||||
|
||||
if ((event->place == PlaceOnTop) && top)
|
||||
above = top->priv->xwindow;
|
||||
else
|
||||
above = None;
|
||||
|
||||
restack_win (cw, above);
|
||||
}
|
||||
|
||||
static void
|
||||
process_unmap (Mutter *compositor,
|
||||
XUnmapEvent *event)
|
||||
{
|
||||
MutterWindow *cw;
|
||||
Window xwin = event->window;
|
||||
Display *dpy = event->display;
|
||||
MutterWindow *cw;
|
||||
Window xwin = event->window;
|
||||
Display *dpy = event->display;
|
||||
|
||||
if (event->from_configure)
|
||||
{
|
||||
/* Ignore unmap caused by parent's resize */
|
||||
return;
|
||||
}
|
||||
|
||||
cw = find_window_in_display (compositor->display, xwin);
|
||||
|
||||
cw = find_window_in_display (compositor->display, event->window);
|
||||
|
||||
if (cw)
|
||||
{
|
||||
@ -1899,8 +1742,11 @@ process_map (Mutter *compositor,
|
||||
{
|
||||
MutterWindow *cw;
|
||||
Window xwindow = event->window;
|
||||
|
||||
cw = find_window_in_display (compositor->display, xwindow);
|
||||
|
||||
if (window)
|
||||
cw = window->compositor_private;
|
||||
else
|
||||
cw = find_window_in_display (compositor->display, xwindow);
|
||||
|
||||
if (cw)
|
||||
{
|
||||
@ -1909,8 +1755,8 @@ process_map (Mutter *compositor,
|
||||
}
|
||||
|
||||
static void
|
||||
process_property_notify (Mutter *compositor,
|
||||
XPropertyEvent *event)
|
||||
process_property_notify (Mutter *compositor,
|
||||
XPropertyEvent *event)
|
||||
{
|
||||
MetaDisplay *display = compositor->display;
|
||||
|
||||
@ -1918,7 +1764,7 @@ process_property_notify (Mutter *compositor,
|
||||
if (event->atom == compositor->atom_net_wm_window_opacity)
|
||||
{
|
||||
MutterWindow *cw = find_window_in_display (display, event->window);
|
||||
gulong value;
|
||||
gulong value;
|
||||
|
||||
if (!cw)
|
||||
{
|
||||
@ -2103,13 +1949,18 @@ clutter_cmp_manage_screen (MetaCompositor *compositor,
|
||||
KeyPressMask | KeyReleaseMask);
|
||||
|
||||
info->window_group = clutter_group_new ();
|
||||
g_object_set_property (G_OBJECT (info->window_group),
|
||||
"show-on-set-parent", FALSE);
|
||||
info->overlay_group = clutter_group_new ();
|
||||
info->hidden_group = clutter_group_new ();
|
||||
|
||||
clutter_container_add (CLUTTER_CONTAINER (info->stage),
|
||||
info->window_group,
|
||||
info->overlay_group,
|
||||
info->hidden_group,
|
||||
NULL);
|
||||
|
||||
clutter_actor_hide (info->hidden_group);
|
||||
|
||||
/*
|
||||
* Must do this *before* creating the plugin manager, in case any of the
|
||||
@ -2224,10 +2075,6 @@ clutter_cmp_process_event (MetaCompositor *compositor,
|
||||
meta_error_trap_push (xrc->display);
|
||||
switch (event->type)
|
||||
{
|
||||
case CirculateNotify:
|
||||
process_circulate_notify (xrc, (XCirculateEvent *) event);
|
||||
break;
|
||||
|
||||
case ConfigureNotify:
|
||||
process_configure_notify (xrc, (XConfigureEvent *) event);
|
||||
break;
|
||||
@ -2460,9 +2307,11 @@ clutter_cmp_switch_workspace (MetaCompositor *compositor,
|
||||
info = meta_screen_get_compositor_data (screen);
|
||||
to_indx = meta_workspace_index (to);
|
||||
from_indx = meta_workspace_index (from);
|
||||
|
||||
|
||||
if (!meta_prefs_get_live_hidden_windows ())
|
||||
{
|
||||
GList *l;
|
||||
|
||||
/*
|
||||
* We are in the traditional mode where hidden windows get unmapped,
|
||||
* we need to pre-calculate the map status of each window so that once
|
||||
@ -2470,14 +2319,12 @@ clutter_cmp_switch_workspace (MetaCompositor *compositor,
|
||||
* (we need to ignore the map notifications during the effect so that
|
||||
* actors do not just disappear while the effect is running).
|
||||
*/
|
||||
GList *l = info->windows;
|
||||
|
||||
while (l)
|
||||
for (l = info->windows; l != NULL; l = l->next)
|
||||
{
|
||||
MutterWindow *cw = l->data;
|
||||
MetaWindow *mw = cw->priv->window;
|
||||
gboolean sticky;
|
||||
gint workspace = -1;
|
||||
MetaWindow *mw = cw->priv->window;
|
||||
gboolean sticky;
|
||||
gint workspace = -1;
|
||||
|
||||
sticky = (!mw || meta_window_is_on_all_workspaces (mw));
|
||||
|
||||
@ -2502,8 +2349,6 @@ clutter_cmp_switch_workspace (MetaCompositor *compositor,
|
||||
cw->priv->needs_unmap = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
l = l->next;
|
||||
}
|
||||
}
|
||||
|
||||
@ -2529,33 +2374,58 @@ clutter_cmp_switch_workspace (MetaCompositor *compositor,
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_cmp_ensure_stack_order (MetaCompositor *compositor,
|
||||
MetaScreen *screen)
|
||||
clutter_cmp_sync_stack (MetaCompositor *compositor,
|
||||
MetaScreen *screen,
|
||||
GList *stack)
|
||||
{
|
||||
GList *tmp;
|
||||
MetaCompScreen *info = meta_screen_get_compositor_data (screen);
|
||||
GList *l = g_list_last (info->windows);
|
||||
|
||||
while (l)
|
||||
|
||||
for (tmp = stack; tmp != NULL; tmp = tmp->next)
|
||||
{
|
||||
ClutterActor *a = l->data;
|
||||
MutterWindow *mw = l->data;
|
||||
MetaWindow *window = mw->priv->window;
|
||||
MetaWindow *window = tmp->data;
|
||||
MutterWindow *cw = window->compositor_private;
|
||||
GList *link;
|
||||
|
||||
/*
|
||||
* If this window is not marked as hidden, we raise it.
|
||||
* If it has no MetaWindow associated (i.e., override redirect), we
|
||||
* raise it too. Everything else we push to the bottom.
|
||||
*/
|
||||
if (!window || !meta_window_is_hidden (window))
|
||||
if (!cw)
|
||||
{
|
||||
clutter_actor_raise_top (a);
|
||||
}
|
||||
else
|
||||
{
|
||||
clutter_actor_lower_bottom (a);
|
||||
meta_verbose ("Failed to find corresponding MutterWindow "
|
||||
"for window %p\n", window);
|
||||
continue;
|
||||
}
|
||||
|
||||
clutter_actor_lower_bottom (CLUTTER_ACTOR (cw));
|
||||
|
||||
l = l->prev;
|
||||
/* Also maintain the order of info->windows */
|
||||
info->windows = g_list_remove (info->windows, (gconstpointer)cw);
|
||||
info->windows = g_list_prepend (info->windows, cw);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_cmp_set_window_hidden (MetaCompositor *compositor,
|
||||
MetaScreen *screen,
|
||||
MetaWindow *window,
|
||||
gboolean hidden)
|
||||
{
|
||||
MutterWindow *cw = window->compositor_private;
|
||||
MetaCompScreen *info = meta_screen_get_compositor_data (screen);
|
||||
|
||||
g_return_if_fail (cw);
|
||||
|
||||
if (hidden)
|
||||
{
|
||||
/* FIXME: There needs to be a way to queue this if there is an effect
|
||||
* in progress for this window */
|
||||
if (clutter_actor_get_parent (CLUTTER_ACTOR (cw)) != info->hidden_group)
|
||||
clutter_actor_reparent (CLUTTER_ACTOR (cw),
|
||||
info->hidden_group);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (clutter_actor_get_parent (CLUTTER_ACTOR (cw)) != info->window_group)
|
||||
clutter_actor_reparent (CLUTTER_ACTOR (cw),
|
||||
info->window_group);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2575,7 +2445,8 @@ static MetaCompositor comp_info = {
|
||||
clutter_cmp_unmaximize_window,
|
||||
clutter_cmp_update_workspace_geometry,
|
||||
clutter_cmp_switch_workspace,
|
||||
clutter_cmp_ensure_stack_order,
|
||||
clutter_cmp_sync_stack,
|
||||
clutter_cmp_set_window_hidden
|
||||
};
|
||||
|
||||
MetaCompositor *
|
||||
|
@ -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);
|
||||
|
@ -65,6 +65,7 @@ MetaWindow * mutter_window_get_meta_window (MutterWindow *mcw);
|
||||
ClutterActor * mutter_window_get_texture (MutterWindow *mcw);
|
||||
gboolean mutter_window_is_override_redirect (MutterWindow *mcw);
|
||||
const char * mutter_window_get_description (MutterWindow *mcw);
|
||||
gboolean mutter_window_showing_on_its_workspace (MutterWindow *mcw);
|
||||
|
||||
/* Compositor API */
|
||||
MetaCompositor *mutter_new (MetaDisplay *display);
|
||||
|
@ -129,9 +129,9 @@ meta_compositor_switch_workspace (MetaCompositor *compositor,
|
||||
MetaMotionDirection direction);
|
||||
|
||||
void
|
||||
meta_compositor_ensure_stack_order (MetaCompositor *compositor,
|
||||
MetaScreen *screen);
|
||||
|
||||
meta_compositor_sync_stack (MetaCompositor *compositor,
|
||||
MetaScreen *screen,
|
||||
GList *stack);
|
||||
#endif
|
||||
|
||||
|
||||
|
@ -64,5 +64,8 @@ void meta_window_activate_with_workspace (MetaWindow *window,
|
||||
guint32 current_time,
|
||||
MetaWorkspace *workspace);
|
||||
const char * meta_window_get_description (MetaWindow *window);
|
||||
/* Return whether the window would be showing if we were on its workspace */
|
||||
gboolean meta_window_showing_on_its_workspace (MetaWindow *window);
|
||||
|
||||
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user