[metacity] move compositor-stack handling to MetaStackTracker
- From: Alberts Muktupāvels <muktupavels src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [metacity] move compositor-stack handling to MetaStackTracker
- Date: Tue, 28 Feb 2017 01:54:09 +0000 (UTC)
commit 553a135d7f9d944e0a4de9c15b98b87a8917b6cb
Author: Owen W. Taylor <otaylor fishsoup net>
Date: Sun Jun 14 08:04:28 2009 -0400
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
src/core/screen.c | 3 +
src/core/stack-tracker.c | 128 ++++++++++++++++++++++++++++++++++++++++------
src/core/stack-tracker.h | 3 +
src/core/window.c | 13 +++++
4 files changed, 131 insertions(+), 16 deletions(-)
---
diff --git a/src/core/screen.c b/src/core/screen.c
index fb077b8..caf254d 100644
--- a/src/core/screen.c
+++ b/src/core/screen.c
@@ -830,6 +830,9 @@ meta_screen_composite_all_windows (MetaScreen *screen)
g_list_foreach (windows, (GFunc)g_free, NULL);
g_list_free (windows);
+
+ /* initialize the compositor's view of the stacking order */
+ meta_stack_tracker_sync_stack (screen->stack_tracker);
}
MetaScreen*
diff --git a/src/core/stack-tracker.c b/src/core/stack-tracker.c
index e0b5dce..6152184 100644
--- a/src/core/stack-tracker.c
+++ b/src/core/stack-tracker.c
@@ -21,6 +21,7 @@
#include <string.h>
+#include "meta-compositor.h"
#include "screen-private.h"
#include "stack-tracker.h"
#include "util.h"
@@ -126,6 +127,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 +215,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 +230,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 +239,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,12 +260,13 @@ 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;
}
+ break;
case STACK_OP_REMOVE:
{
int old_pos = find_window (stack, op->remove.window);
@@ -259,12 +274,13 @@ 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;
}
+ break;
case STACK_OP_RAISE_ABOVE:
{
int old_pos = find_window (stack, op->raise_above.window);
@@ -273,7 +289,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 +299,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,9 +307,9 @@ 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);
}
+ break;
case STACK_OP_LOWER_BELOW:
{
int old_pos = find_window (stack, op->lower_below.window);
@@ -302,7 +318,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 +328,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,12 +338,15 @@ 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);
}
+ break;
default:
break;
}
+
+ g_assert_not_reached ();
+ return FALSE;
}
static GArray *
@@ -369,6 +388,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);
@@ -384,8 +406,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);
}
@@ -511,6 +535,8 @@ stack_tracker_event_received (MetaStackTracker *tracker,
}
meta_stack_tracker_dump (tracker);
+
+ meta_stack_tracker_queue_sync_stack (tracker);
}
void
@@ -630,3 +656,73 @@ 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, meta_windows);
+ g_list_free (meta_windows);
+}
+
+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);
+ }
+}
diff --git a/src/core/stack-tracker.h b/src/core/stack-tracker.h
index 7439253..c74bdb2 100644
--- a/src/core/stack-tracker.h
+++ b/src/core/stack-tracker.h
@@ -81,4 +81,7 @@ 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 */
diff --git a/src/core/window.c b/src/core/window.c
index 83d7c5c..2c7524e 100644
--- a/src/core/window.c
+++ b/src/core/window.c
@@ -774,6 +774,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);
@@ -1081,6 +1088,12 @@ meta_window_free (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
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]