mirror of
https://github.com/brl/mutter.git
synced 2024-12-23 19:42:05 +00:00
Move compositor-stack handling to MetaStackTracker
In order to properly track the stacking order for override-redirect windows, move meta_compositor_sync_stack() call into MetaStackTracker. In the new location, we sync the stack as a before-redraw idle function, rather then using the freeze-thaw facilities of MetaStack. This is simpler, and also properly compresses multiple stack changes on notifications received from the X server. http://bugzilla.gnome.org/show_bug.cgi?id=585984
This commit is contained in:
parent
a4cd66f599
commit
6314ee8780
@ -953,9 +953,8 @@ meta_screen_composite_all_windows (MetaScreen *screen)
|
||||
meta_compositor_add_window (display->compositor, tmp->data);
|
||||
g_slist_free (windows);
|
||||
|
||||
/* trigger a stack_sync_to_server: */
|
||||
meta_stack_freeze (screen->stack);
|
||||
meta_stack_thaw (screen->stack);
|
||||
/* initialize the compositor's view of the stacking order */
|
||||
meta_stack_tracker_sync_stack (screen->stack_tracker);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -27,6 +27,8 @@
|
||||
#include "stack-tracker.h"
|
||||
#include "util.h"
|
||||
|
||||
#include "compositor.h"
|
||||
|
||||
/* The complexity here comes from resolving two competing factors:
|
||||
*
|
||||
* - We need to have a view of the stacking order that takes into
|
||||
@ -128,6 +130,11 @@ struct _MetaStackTracker
|
||||
* on requests we've made subsequent to server_stack
|
||||
*/
|
||||
GArray *predicted_stack;
|
||||
|
||||
/* Idle function used to sync the compositor's view of the window
|
||||
* stack up with our best guess before a frame is drawn.
|
||||
*/
|
||||
guint sync_stack_idle;
|
||||
};
|
||||
|
||||
static void
|
||||
@ -209,7 +216,8 @@ find_window (GArray *stack,
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void
|
||||
/* Returns TRUE if stack was changed */
|
||||
static gboolean
|
||||
move_window_above (GArray *stack,
|
||||
Window window,
|
||||
int old_pos,
|
||||
@ -223,6 +231,8 @@ move_window_above (GArray *stack,
|
||||
g_array_index (stack, Window, i) = g_array_index (stack, Window, i + 1);
|
||||
|
||||
g_array_index (stack, Window, above_pos) = window;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
else if (old_pos > above_pos + 1)
|
||||
{
|
||||
@ -230,10 +240,15 @@ move_window_above (GArray *stack,
|
||||
g_array_index (stack, Window, i) = g_array_index (stack, Window, i - 1);
|
||||
|
||||
g_array_index (stack, Window, above_pos + 1) = window;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
/* Returns TRUE if stack was changed */
|
||||
static gboolean
|
||||
meta_stack_op_apply (MetaStackOp *op,
|
||||
GArray *stack)
|
||||
{
|
||||
@ -246,11 +261,11 @@ meta_stack_op_apply (MetaStackOp *op,
|
||||
{
|
||||
g_warning ("STACK_OP_ADD: window %#lx already in stack",
|
||||
op->add.window);
|
||||
return;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
g_array_append_val (stack, op->add.window);
|
||||
break;
|
||||
return TRUE;
|
||||
}
|
||||
case STACK_OP_REMOVE:
|
||||
{
|
||||
@ -259,11 +274,11 @@ meta_stack_op_apply (MetaStackOp *op,
|
||||
{
|
||||
g_warning ("STACK_OP_REMOVE: window %#lx not in stack",
|
||||
op->remove.window);
|
||||
return;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
g_array_remove_index (stack, old_pos);
|
||||
break;
|
||||
return TRUE;
|
||||
}
|
||||
case STACK_OP_RAISE_ABOVE:
|
||||
{
|
||||
@ -273,7 +288,7 @@ meta_stack_op_apply (MetaStackOp *op,
|
||||
{
|
||||
g_warning ("STACK_OP_RAISE_ABOVE: window %#lx not in stack",
|
||||
op->raise_above.window);
|
||||
return;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (op->raise_above.sibling != None)
|
||||
@ -283,7 +298,7 @@ meta_stack_op_apply (MetaStackOp *op,
|
||||
{
|
||||
g_warning ("STACK_OP_RAISE_ABOVE: sibling window %#lx not in stack",
|
||||
op->raise_above.sibling);
|
||||
return;
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -291,8 +306,7 @@ meta_stack_op_apply (MetaStackOp *op,
|
||||
above_pos = -1;
|
||||
}
|
||||
|
||||
move_window_above (stack, op->raise_above.window, old_pos, above_pos);
|
||||
break;
|
||||
return move_window_above (stack, op->raise_above.window, old_pos, above_pos);
|
||||
}
|
||||
case STACK_OP_LOWER_BELOW:
|
||||
{
|
||||
@ -302,7 +316,7 @@ meta_stack_op_apply (MetaStackOp *op,
|
||||
{
|
||||
g_warning ("STACK_OP_LOWER_BELOW: window %#lx not in stack",
|
||||
op->lower_below.window);
|
||||
return;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (op->lower_below.sibling != None)
|
||||
@ -312,7 +326,7 @@ meta_stack_op_apply (MetaStackOp *op,
|
||||
{
|
||||
g_warning ("STACK_OP_LOWER_BELOW: sibling window %#lx not in stack",
|
||||
op->lower_below.sibling);
|
||||
return;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
above_pos = below_pos - 1;
|
||||
@ -322,10 +336,12 @@ meta_stack_op_apply (MetaStackOp *op,
|
||||
above_pos = stack->len - 1;
|
||||
}
|
||||
|
||||
move_window_above (stack, op->lower_below.window, old_pos, above_pos);
|
||||
break;
|
||||
return move_window_above (stack, op->lower_below.window, old_pos, above_pos);
|
||||
}
|
||||
}
|
||||
|
||||
g_assert_not_reached ();
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static GArray *
|
||||
@ -367,6 +383,9 @@ meta_stack_tracker_new (MetaScreen *screen)
|
||||
void
|
||||
meta_stack_tracker_free (MetaStackTracker *tracker)
|
||||
{
|
||||
if (tracker->sync_stack_idle)
|
||||
g_source_remove (tracker->sync_stack_idle);
|
||||
|
||||
g_array_free (tracker->server_stack, TRUE);
|
||||
if (tracker->predicted_stack)
|
||||
g_array_free (tracker->predicted_stack, TRUE);
|
||||
@ -382,8 +401,10 @@ stack_tracker_queue_request (MetaStackTracker *tracker,
|
||||
{
|
||||
meta_stack_op_dump (op, "Queueing: ", "\n");
|
||||
g_queue_push_tail (tracker->queued_requests, op);
|
||||
if (tracker->predicted_stack)
|
||||
meta_stack_op_apply (op, tracker->predicted_stack);
|
||||
if (!tracker->predicted_stack ||
|
||||
meta_stack_op_apply (op, tracker->predicted_stack))
|
||||
meta_stack_tracker_queue_sync_stack (tracker);
|
||||
|
||||
meta_stack_tracker_dump (tracker);
|
||||
}
|
||||
|
||||
@ -509,6 +530,8 @@ stack_tracker_event_received (MetaStackTracker *tracker,
|
||||
}
|
||||
|
||||
meta_stack_tracker_dump (tracker);
|
||||
|
||||
meta_stack_tracker_queue_sync_stack (tracker);
|
||||
}
|
||||
|
||||
void
|
||||
@ -628,3 +651,78 @@ meta_stack_tracker_get_stack (MetaStackTracker *tracker,
|
||||
if (n_windows)
|
||||
*n_windows = stack->len;
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_stack_tracker_sync_stack:
|
||||
* @tracker: a #MetaStackTracker
|
||||
*
|
||||
* Informs the compositor of the current stacking order of windows,
|
||||
* based on the predicted view maintained by the #MetaStackTracker.
|
||||
*/
|
||||
void
|
||||
meta_stack_tracker_sync_stack (MetaStackTracker *tracker)
|
||||
{
|
||||
GList *meta_windows;
|
||||
Window *windows;
|
||||
int n_windows;
|
||||
int i;
|
||||
|
||||
if (tracker->sync_stack_idle)
|
||||
{
|
||||
g_source_remove (tracker->sync_stack_idle);
|
||||
tracker->sync_stack_idle = 0;
|
||||
}
|
||||
|
||||
meta_stack_tracker_get_stack (tracker, &windows, &n_windows);
|
||||
|
||||
meta_windows = NULL;
|
||||
for (i = 0; i < n_windows; i++)
|
||||
{
|
||||
MetaWindow *meta_window;
|
||||
|
||||
meta_window = meta_display_lookup_x_window (tracker->screen->display,
|
||||
windows[i]);
|
||||
if (meta_window)
|
||||
meta_windows = g_list_prepend (meta_windows, meta_window);
|
||||
}
|
||||
|
||||
meta_compositor_sync_stack (tracker->screen->display->compositor,
|
||||
tracker->screen,
|
||||
meta_windows);
|
||||
g_list_free (meta_windows);
|
||||
|
||||
meta_screen_restacked (tracker->screen);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
stack_tracker_sync_stack_idle (gpointer data)
|
||||
{
|
||||
meta_stack_tracker_sync_stack (data);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_stack_tracker_queue_sync_stack:
|
||||
* @tracker: a #MetaStackTracker
|
||||
*
|
||||
* Queue informing the compositor of the new stacking order before the
|
||||
* next redraw. (See meta_stack_tracker_sync_stack()). This is called
|
||||
* internally when the stack of X windows changes, but also needs be
|
||||
* called directly when we an undecorated window is first shown or
|
||||
* withdrawn since the compositor's stacking order (which contains only
|
||||
* the windows that have a corresponding MetaWindow) will change without
|
||||
* any change to the stacking order of the X windows, if we are creating
|
||||
* or destroying MetaWindows.
|
||||
*/
|
||||
void
|
||||
meta_stack_tracker_queue_sync_stack (MetaStackTracker *tracker)
|
||||
{
|
||||
if (tracker->sync_stack_idle == 0)
|
||||
{
|
||||
tracker->sync_stack_idle = g_idle_add_full (META_PRIORITY_BEFORE_REDRAW,
|
||||
stack_tracker_sync_stack_idle,
|
||||
tracker, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -79,8 +79,11 @@ void meta_stack_tracker_reparent_event (MetaStackTracker *tracker,
|
||||
void meta_stack_tracker_configure_event (MetaStackTracker *tracker,
|
||||
XConfigureEvent *event);
|
||||
|
||||
void meta_stack_tracker_get_stack (MetaStackTracker *tracker,
|
||||
Window **windows,
|
||||
int *n_windows);
|
||||
void meta_stack_tracker_get_stack (MetaStackTracker *tracker,
|
||||
Window **windows,
|
||||
int *n_windows);
|
||||
|
||||
void meta_stack_tracker_sync_stack (MetaStackTracker *tracker);
|
||||
void meta_stack_tracker_queue_sync_stack (MetaStackTracker *tracker);
|
||||
|
||||
#endif /* META_STACK_TRACKER_H */
|
||||
|
@ -35,10 +35,6 @@
|
||||
#include "prefs.h"
|
||||
#include "workspace.h"
|
||||
|
||||
#ifdef HAVE_COMPOSITE_EXTENSIONS
|
||||
#include "compositor.h"
|
||||
#endif
|
||||
|
||||
#include <X11/Xatom.h>
|
||||
|
||||
#define WINDOW_HAS_TRANSIENT_TYPE(w) \
|
||||
@ -1091,10 +1087,6 @@ stack_sync_to_server (MetaStack *stack)
|
||||
|
||||
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
|
||||
* _NET hints, and "root_children_stacked" is in top-to-bottom
|
||||
@ -1312,8 +1304,6 @@ stack_sync_to_server (MetaStack *stack)
|
||||
if (stack->last_root_children_stacked)
|
||||
g_array_free (stack->last_root_children_stacked, TRUE);
|
||||
stack->last_root_children_stacked = root_children_stacked;
|
||||
|
||||
meta_screen_restacked (stack->screen);
|
||||
|
||||
/* That was scary... */
|
||||
}
|
||||
|
@ -1001,6 +1001,13 @@ meta_window_new_with_attrs (MetaDisplay *display,
|
||||
/* Sync stack changes */
|
||||
meta_stack_thaw (window->screen->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);
|
||||
|
||||
/* disable show desktop mode unless we're a desktop component */
|
||||
maybe_leave_show_desktop_mode (window);
|
||||
|
||||
@ -1309,6 +1316,12 @@ meta_window_unmanage (MetaWindow *window,
|
||||
if (window->frame)
|
||||
meta_window_destroy_frame (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);
|
||||
|
||||
if (window->withdrawn)
|
||||
{
|
||||
/* We need to clean off the window's state so it
|
||||
|
Loading…
Reference in New Issue
Block a user