From 73573a85de50d2d8659755a90ffd22fa2f1119bd Mon Sep 17 00:00:00 2001 From: "Owen W. Taylor" Date: Mon, 8 Sep 2014 21:20:14 -0400 Subject: [PATCH] Replace MetaStackWindow with a 64-bit "stack ID" Putting X windows and pointers to MetaWindows into a union had a number of problems: - It caused awkward initialization and conditionalization - There was no way to refer to Wayland windows (represented by MetaWindow *) in the past, which is necessary for the MetaStackTracker algorithms - We never even cleaned up old MetaStackWindow so there could be records in MetaStackWindow pointing to freed MetaWindow. Replace MetaStackWindow with a 64-bit "stack ID" which is: - The XID for X Windows - a "window stamp" for Wayland windows - window stamps are assigned for all MetaWindow and are unique across the life of the process. https://bugzilla.gnome.org/show_bug.cgi?id=736559 --- src/core/display-private.h | 24 +++ src/core/display.c | 64 ++++++ src/core/frame.c | 13 +- src/core/screen.c | 16 +- src/core/stack-tracker.c | 390 ++++++++++++++--------------------- src/core/stack-tracker.h | 66 +++--- src/core/stack.c | 172 +++++++-------- src/core/window-private.h | 1 + src/core/window.c | 9 + src/tests/test-runner.c | 22 +- src/wayland/window-wayland.c | 10 +- 11 files changed, 373 insertions(+), 414 deletions(-) diff --git a/src/core/display-private.h b/src/core/display-private.h index 59ce08563..f13736317 100644 --- a/src/core/display-private.h +++ b/src/core/display-private.h @@ -166,6 +166,7 @@ struct _MetaDisplay /*< private-ish >*/ MetaScreen *screen; GHashTable *xids; + GHashTable *stamps; GHashTable *wayland_windows; /* serials of leave/unmap events that may @@ -341,6 +342,29 @@ void meta_display_register_x_window (MetaDisplay *display, void meta_display_unregister_x_window (MetaDisplay *display, Window xwindow); +/* Each MetaWindow is uniquely identified by a 64-bit "stamp"; unlike a + * a MetaWindow *, a stamp will never be recycled + */ +MetaWindow* meta_display_lookup_stamp (MetaDisplay *display, + guint64 stamp); +void meta_display_register_stamp (MetaDisplay *display, + guint64 *stampp, + MetaWindow *window); +void meta_display_unregister_stamp (MetaDisplay *display, + guint64 stamp); + +/* A "stack id" is a XID or a stamp */ + +#define META_STACK_ID_IS_X11(id) ((id) < G_GUINT64_CONSTANT(0x100000000)) +MetaWindow* meta_display_lookup_stack_id (MetaDisplay *display, + guint64 stack_id); + +/* for debug logging only; returns a human-description of the stack + * ID - a small number of buffers are recycled, so the result must + * be used immediately or copied */ +const char *meta_display_describe_stack_id (MetaDisplay *display, + guint64 stack_id); + void meta_display_register_wayland_window (MetaDisplay *display, MetaWindow *window); void meta_display_unregister_wayland_window (MetaDisplay *display, diff --git a/src/core/display.c b/src/core/display.c index 38630d606..11cab2daa 100644 --- a/src/core/display.c +++ b/src/core/display.c @@ -627,6 +627,8 @@ meta_display_open (void) display->xids = g_hash_table_new (meta_unsigned_long_hash, meta_unsigned_long_equal); + display->stamps = g_hash_table_new (g_int64_hash, + g_int64_equal); display->wayland_windows = g_hash_table_new (NULL, NULL); i = 0; @@ -1581,6 +1583,68 @@ meta_display_unregister_wayland_window (MetaDisplay *display, g_hash_table_remove (display->wayland_windows, window); } +MetaWindow* +meta_display_lookup_stamp (MetaDisplay *display, + guint64 stamp) +{ + return g_hash_table_lookup (display->stamps, &stamp); +} + +void +meta_display_register_stamp (MetaDisplay *display, + guint64 *stampp, + MetaWindow *window) +{ + g_return_if_fail (g_hash_table_lookup (display->stamps, stampp) == NULL); + + g_hash_table_insert (display->stamps, stampp, window); +} + +void +meta_display_unregister_stamp (MetaDisplay *display, + guint64 stamp) +{ + g_return_if_fail (g_hash_table_lookup (display->stamps, &stamp) != NULL); + + g_hash_table_remove (display->stamps, &stamp); +} + +MetaWindow* +meta_display_lookup_stack_id (MetaDisplay *display, + guint64 stack_id) +{ + if (META_STACK_ID_IS_X11 (stack_id)) + return meta_display_lookup_x_window (display, (Window)stack_id); + else + return meta_display_lookup_stamp (display, stack_id); +} + +/* We return a pointer into a ring of static buffers. This is to make + * using this function for debug-logging convenient and avoid tempory + * strings that must be freed. */ +const char * +meta_display_describe_stack_id (MetaDisplay *display, + guint64 stack_id) +{ + /* 0x<64-bit: 16 characters> (<10 characters of title>)\0' */ + static char buffer[5][32]; + MetaWindow *window; + static int pos = 0; + char *result; + + result = buffer[pos]; + pos = (pos + 1) % 5; + + window = meta_display_lookup_stack_id (display, stack_id); + + if (window && window->title) + snprintf (result, sizeof(buffer[0]), "%#" G_GINT64_MODIFIER "x (%.10s)", stack_id, window->title); + else + snprintf (result, sizeof(buffer[0]), "%#" G_GINT64_MODIFIER "x", stack_id); + + return result; +} + /* We store sync alarms in the window ID hash table, because they are * just more types of XIDs in the same global space, but we have * typesafe functions to register/unregister for readability. diff --git a/src/core/frame.c b/src/core/frame.c index 0ab7beef9..1b393718e 100644 --- a/src/core/frame.c +++ b/src/core/frame.c @@ -39,7 +39,6 @@ meta_window_ensure_frame (MetaWindow *window) XSetWindowAttributes attrs; Visual *visual; gulong create_serial; - MetaStackWindow stack_window; if (window->frame) return; @@ -95,10 +94,8 @@ meta_window_ensure_frame (MetaWindow *window) frame->rect.height, frame->window->screen->number, &create_serial); - stack_window.any.type = META_WINDOW_CLIENT_TYPE_X11; - stack_window.x11.xwindow = frame->xwindow; meta_stack_tracker_record_add (window->screen->stack_tracker, - &stack_window, + frame->xwindow, create_serial); meta_verbose ("Frame for %s is 0x%lx\n", frame->window->desc, frame->xwindow); @@ -132,9 +129,8 @@ meta_window_ensure_frame (MetaWindow *window) window->unmaps_pending += 1; } - stack_window.x11.xwindow = window->xwindow; meta_stack_tracker_record_remove (window->screen->stack_tracker, - &stack_window, + window->xwindow, XNextRequest (window->display->xdisplay)); XReparentWindow (window->display->xdisplay, window->xwindow, @@ -179,7 +175,6 @@ meta_window_destroy_frame (MetaWindow *window) { MetaFrame *frame; MetaFrameBorders borders; - MetaStackWindow stack_window; if (window->frame == NULL) return; @@ -206,10 +201,8 @@ meta_window_destroy_frame (MetaWindow *window) "Incrementing unmaps_pending on %s for reparent back to root\n", window->desc); window->unmaps_pending += 1; } - stack_window.any.type = META_WINDOW_CLIENT_TYPE_X11; - stack_window.x11.xwindow = window->xwindow; meta_stack_tracker_record_add (window->screen->stack_tracker, - &stack_window, + window->xwindow, XNextRequest (window->display->xdisplay)); XReparentWindow (window->display->xdisplay, window->xwindow, diff --git a/src/core/screen.c b/src/core/screen.c index 6051c5c98..00a0a52f6 100644 --- a/src/core/screen.c +++ b/src/core/screen.c @@ -441,7 +441,6 @@ create_guard_window (Display *xdisplay, MetaScreen *screen) XSetWindowAttributes attributes; Window guard_window; gulong create_serial; - MetaStackWindow stack_window; attributes.event_mask = NoEventMask; attributes.override_redirect = True; @@ -487,14 +486,12 @@ create_guard_window (Display *xdisplay, MetaScreen *screen) } } - stack_window.any.type = META_WINDOW_CLIENT_TYPE_X11; - stack_window.x11.xwindow = guard_window; meta_stack_tracker_record_add (screen->stack_tracker, - &stack_window, + guard_window, create_serial); meta_stack_tracker_record_lower (screen->stack_tracker, - &stack_window, + guard_window, XNextRequest (xdisplay)); XLowerWindow (xdisplay, guard_window); XMapWindow (xdisplay, guard_window); @@ -884,19 +881,20 @@ meta_screen_create_guard_window (MetaScreen *screen) void meta_screen_manage_all_windows (MetaScreen *screen) { - MetaStackWindow *_children; - MetaStackWindow *children; + 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 (MetaStackWindow) * n_children); + children = g_memdup (_children, sizeof (guint64) * n_children); for (i = 0; i < n_children; ++i) { - meta_window_x11_new (screen->display, children[i].x11.xwindow, TRUE, + g_assert (META_STACK_ID_IS_X11 (children[i])); + meta_window_x11_new (screen->display, children[i], TRUE, META_COMP_EFFECT_NONE); } diff --git a/src/core/stack-tracker.c b/src/core/stack-tracker.c index c692dda8f..afb38e4c3 100644 --- a/src/core/stack-tracker.c +++ b/src/core/stack-tracker.c @@ -96,29 +96,29 @@ union _MetaStackOp struct { MetaStackOpType type; gulong serial; - MetaStackWindow window; + guint64 window; } any; struct { MetaStackOpType type; gulong serial; - MetaStackWindow window; + guint64 window; } add; struct { MetaStackOpType type; gulong serial; - MetaStackWindow window; + guint64 window; } remove; struct { MetaStackOpType type; gulong serial; - MetaStackWindow window; - MetaStackWindow sibling; + guint64 window; + guint64 sibling; } raise_above; struct { MetaStackOpType type; gulong serial; - MetaStackWindow window; - MetaStackWindow sibling; + guint64 window; + guint64 sibling; } lower_below; }; @@ -157,95 +157,65 @@ struct _MetaStackTracker guint sync_stack_later; }; -static gboolean -meta_stack_window_is_set (const MetaStackWindow *window) +static inline const char * +get_window_desc (MetaStackTracker *tracker, + guint64 window) { - if (window->any.type == META_WINDOW_CLIENT_TYPE_X11) - return window->x11.xwindow == None ? FALSE : TRUE; - else - return window->wayland.meta_window ? TRUE : FALSE; -} - -gboolean -meta_stack_window_equal (const MetaStackWindow *a, - const MetaStackWindow *b) -{ - if (a->any.type == b->any.type) - { - if (a->any.type == META_WINDOW_CLIENT_TYPE_X11) - return a->x11.xwindow == b->x11.xwindow; - else - return a->wayland.meta_window == b->wayland.meta_window; - } - else - return FALSE; -} - -static char * -get_window_id (MetaStackWindow *window) -{ - if (window->any.type == META_WINDOW_CLIENT_TYPE_X11) - return g_strdup_printf ("X11:%lx", window->x11.xwindow); - else - return g_strdup_printf ("Wayland:%p", window->wayland.meta_window); + return meta_display_describe_stack_id (tracker->screen->display, window); } static void -meta_stack_op_dump (MetaStackOp *op, - const char *prefix, - const char *suffix) +meta_stack_op_dump (MetaStackTracker *tracker, + MetaStackOp *op, + const char *prefix, + const char *suffix) { - char *window_id = get_window_id (&op->any.window); + const char *window_desc = get_window_desc (tracker, op->any.window); switch (op->any.type) { case STACK_OP_ADD: meta_topic (META_DEBUG_STACK, "%sADD(%s; %ld)%s", - prefix, window_id, op->any.serial, suffix); + prefix, window_desc, op->any.serial, suffix); break; case STACK_OP_REMOVE: meta_topic (META_DEBUG_STACK, "%sREMOVE(%s; %ld)%s", - prefix, window_id, op->any.serial, suffix); + prefix, window_desc, op->any.serial, suffix); break; case STACK_OP_RAISE_ABOVE: { - char *sibling_id = get_window_id (&op->raise_above.sibling); meta_topic (META_DEBUG_STACK, "%sRAISE_ABOVE(%s, %s; %ld)%s", prefix, - window_id, sibling_id, + window_desc, + get_window_desc (tracker, op->raise_above.sibling), op->any.serial, suffix); - g_free (sibling_id); break; } case STACK_OP_LOWER_BELOW: { - char *sibling_id = get_window_id (&op->lower_below.sibling); meta_topic (META_DEBUG_STACK, "%sLOWER_BELOW(%s, %s; %ld)%s", prefix, - window_id, sibling_id, + window_desc, + get_window_desc (tracker, op->lower_below.sibling), op->any.serial, suffix); - g_free (sibling_id); break; } } - - g_free (window_id); } static void -stack_dump (GArray *stack) +stack_dump (MetaStackTracker *tracker, + GArray *stack) { guint i; meta_push_no_msg_prefix (); for (i = 0; i < stack->len; i++) { - MetaStackWindow *window = &g_array_index (stack, MetaStackWindow, i); - char *window_id = get_window_id (window); - meta_topic (META_DEBUG_STACK, " %s", window_id); - g_free (window_id); + guint64 window = g_array_index (stack, guint64, i); + meta_topic (META_DEBUG_STACK, " %s", get_window_desc (tracker, window)); } meta_topic (META_DEBUG_STACK, "\n"); meta_pop_no_msg_prefix (); @@ -260,20 +230,20 @@ meta_stack_tracker_dump (MetaStackTracker *tracker) meta_push_no_msg_prefix (); meta_topic (META_DEBUG_STACK, " xserver_serial: %ld\n", tracker->xserver_serial); meta_topic (META_DEBUG_STACK, " xserver_stack: "); - stack_dump (tracker->xserver_stack); + stack_dump (tracker, tracker->xserver_stack); meta_topic (META_DEBUG_STACK, " verfied_stack: "); - stack_dump (tracker->verified_stack); + stack_dump (tracker, tracker->verified_stack); meta_topic (META_DEBUG_STACK, " unverified_predictions: ["); for (l = tracker->unverified_predictions->head; l; l = l->next) { MetaStackOp *op = l->data; - meta_stack_op_dump (op, "", l->next ? ", " : ""); + meta_stack_op_dump (tracker, op, "", l->next ? ", " : ""); } meta_topic (META_DEBUG_STACK, "]\n"); if (tracker->predicted_stack) { meta_topic (META_DEBUG_STACK, "\n predicted_stack: "); - stack_dump (tracker->predicted_stack); + stack_dump (tracker, tracker->predicted_stack); } meta_pop_no_msg_prefix (); } @@ -285,23 +255,16 @@ meta_stack_op_free (MetaStackOp *op) } static int -find_window (GArray *window_stack, - MetaStackWindow *window) +find_window (GArray *window_stack, + guint64 window) { guint i; for (i = 0; i < window_stack->len; i++) { - MetaStackWindow *current = &g_array_index (window_stack, MetaStackWindow, i); - if (current->any.type == window->any.type) - { - if (current->any.type == META_WINDOW_CLIENT_TYPE_X11 && - current->x11.xwindow == window->x11.xwindow) - return i; - else - if (current->wayland.meta_window == window->wayland.meta_window) - return i; - } + guint64 current = g_array_index (window_stack, guint64, i); + if (current == window) + return i; } return -1; @@ -309,33 +272,30 @@ find_window (GArray *window_stack, /* Returns TRUE if stack was changed */ static gboolean -move_window_above (GArray *stack, - MetaStackWindow *window, - int old_pos, - int above_pos) +move_window_above (GArray *stack, + guint64 window, + int old_pos, + int above_pos) { - /* Copy the window by-value before we start shifting things around - * in the stack in case window points into the stack itself. */ - MetaStackWindow window_val = *window; int i; if (old_pos < above_pos) { for (i = old_pos; i < above_pos; i++) - g_array_index (stack, MetaStackWindow, i) = - g_array_index (stack, MetaStackWindow, i + 1); + g_array_index (stack, guint64, i) = + g_array_index (stack, guint64, i + 1); - g_array_index (stack, MetaStackWindow, above_pos) = window_val; + g_array_index (stack, guint64, above_pos) = window; return TRUE; } else if (old_pos > above_pos + 1) { for (i = old_pos; i > above_pos + 1; i--) - g_array_index (stack, MetaStackWindow, i) = - g_array_index (stack, MetaStackWindow, i - 1); + g_array_index (stack, guint64, i) = + g_array_index (stack, guint64, i - 1); - g_array_index (stack, MetaStackWindow, above_pos + 1) = window_val; + g_array_index (stack, guint64, above_pos + 1) = window; return TRUE; } @@ -345,20 +305,19 @@ move_window_above (GArray *stack, /* Returns TRUE if stack was changed */ static gboolean -meta_stack_op_apply (MetaStackOp *op, - GArray *stack) +meta_stack_op_apply (MetaStackTracker *tracker, + MetaStackOp *op, + GArray *stack) { switch (op->any.type) { case STACK_OP_ADD: { - int old_pos = find_window (stack, &op->add.window); + int old_pos = find_window (stack, op->add.window); if (old_pos >= 0) { - char *window_id = get_window_id (&op->add.window); g_warning ("STACK_OP_ADD: window %s already in stack", - window_id); - g_free (window_id); + get_window_desc (tracker, op->add.window)); return FALSE; } @@ -367,13 +326,11 @@ meta_stack_op_apply (MetaStackOp *op, } case STACK_OP_REMOVE: { - int old_pos = find_window (stack, &op->remove.window); + int old_pos = find_window (stack, op->remove.window); if (old_pos < 0) { - char *window_id = get_window_id (&op->remove.window); g_warning ("STACK_OP_REMOVE: window %s not in stack", - window_id); - g_free (window_id); + get_window_desc (tracker, op->remove.window)); return FALSE; } @@ -382,26 +339,22 @@ meta_stack_op_apply (MetaStackOp *op, } case STACK_OP_RAISE_ABOVE: { - int old_pos = find_window (stack, &op->raise_above.window); + int old_pos = find_window (stack, op->raise_above.window); int above_pos; if (old_pos < 0) { - char *window_id = get_window_id (&op->raise_above.window); g_warning ("STACK_OP_RAISE_ABOVE: window %s not in stack", - window_id); - g_free (window_id); + get_window_desc (tracker, op->raise_above.window)); return FALSE; } - if (meta_stack_window_is_set (&op->raise_above.sibling)) + if (op->raise_above.sibling) { - above_pos = find_window (stack, &op->raise_above.sibling); + above_pos = find_window (stack, op->raise_above.sibling); if (above_pos < 0) { - char *sibling_id = get_window_id (&op->raise_above.sibling); g_warning ("STACK_OP_RAISE_ABOVE: sibling window %s not in stack", - sibling_id); - g_free (sibling_id); + get_window_desc (tracker, op->raise_above.sibling)); return FALSE; } } @@ -410,30 +363,26 @@ meta_stack_op_apply (MetaStackOp *op, above_pos = -1; } - return move_window_above (stack, &op->raise_above.window, old_pos, above_pos); + return move_window_above (stack, op->raise_above.window, old_pos, above_pos); } case STACK_OP_LOWER_BELOW: { - int old_pos = find_window (stack, &op->lower_below.window); + int old_pos = find_window (stack, op->lower_below.window); int above_pos; if (old_pos < 0) { - char *window_id = get_window_id (&op->lower_below.window); g_warning ("STACK_OP_LOWER_BELOW: window %s not in stack", - window_id); - g_free (window_id); + get_window_desc (tracker, op->lower_below.window)); return FALSE; } - if (meta_stack_window_is_set (&op->lower_below.sibling)) + if (op->lower_below.sibling) { - int below_pos = find_window (stack, &op->lower_below.sibling); + int below_pos = find_window (stack, op->lower_below.sibling); if (below_pos < 0) { - char *sibling_id = get_window_id (&op->lower_below.sibling); g_warning ("STACK_OP_LOWER_BELOW: sibling window %s not in stack", - sibling_id); - g_free (sibling_id); + get_window_desc (tracker, op->lower_below.sibling)); return FALSE; } @@ -444,7 +393,7 @@ meta_stack_op_apply (MetaStackOp *op, above_pos = stack->len - 1; } - return move_window_above (stack, &op->lower_below.window, old_pos, above_pos); + return move_window_above (stack, op->lower_below.window, old_pos, above_pos); } } @@ -455,11 +404,11 @@ meta_stack_op_apply (MetaStackOp *op, static GArray * copy_stack (GArray *stack) { - GArray *copy = g_array_sized_new (FALSE, FALSE, sizeof (MetaStackWindow), stack->len); + GArray *copy = g_array_sized_new (FALSE, FALSE, sizeof (guint64), stack->len); g_array_set_size (copy, stack->len); - memcpy (copy->data, stack->data, sizeof (MetaStackWindow) * stack->len); + memcpy (copy->data, stack->data, sizeof (guint64) * stack->len); return copy; } @@ -482,15 +431,11 @@ requery_xserver_stack (MetaStackTracker *tracker) screen->xroot, &ignored1, &ignored2, &children, &n_children); - tracker->xserver_stack = g_array_sized_new (FALSE, FALSE, sizeof (MetaStackWindow), n_children); + tracker->xserver_stack = g_array_sized_new (FALSE, FALSE, sizeof (guint64), n_children); g_array_set_size (tracker->xserver_stack, n_children); for (i = 0; i < n_children; i++) - { - MetaStackWindow *window = &g_array_index (tracker->xserver_stack, MetaStackWindow, i); - window->any.type = META_WINDOW_CLIENT_TYPE_X11; - window->x11.xwindow = children[i]; - } + g_array_index (tracker->xserver_stack, guint64, i) = children[i]; XFree (children); } @@ -542,22 +487,22 @@ stack_tracker_apply_prediction (MetaStackTracker *tracker, * we can apply it immediately so long as it doesn't depend on any * unverified X operations... */ - if (op->any.window.any.type == META_WINDOW_CLIENT_TYPE_WAYLAND && + if (!META_STACK_ID_IS_X11 (op->any.window) && tracker->unverified_predictions->length == 0) { - if (meta_stack_op_apply (op, tracker->verified_stack)) + if (meta_stack_op_apply (tracker, op, tracker->verified_stack)) meta_stack_tracker_queue_sync_stack (tracker); free_at_end = TRUE; } else { - meta_stack_op_dump (op, "Predicting: ", "\n"); + meta_stack_op_dump (tracker, op, "Predicting: ", "\n"); g_queue_push_tail (tracker->unverified_predictions, op); } if (!tracker->predicted_stack || - meta_stack_op_apply (op, tracker->predicted_stack)) + meta_stack_op_apply (tracker, op, tracker->predicted_stack)) meta_stack_tracker_queue_sync_stack (tracker); if (free_at_end) @@ -567,38 +512,38 @@ stack_tracker_apply_prediction (MetaStackTracker *tracker, } void -meta_stack_tracker_record_add (MetaStackTracker *tracker, - const MetaStackWindow *window, - gulong serial) +meta_stack_tracker_record_add (MetaStackTracker *tracker, + guint64 window, + gulong serial) { MetaStackOp *op = g_slice_new (MetaStackOp); op->any.type = STACK_OP_ADD; op->any.serial = serial; - op->any.window = *window; + op->any.window = window; stack_tracker_apply_prediction (tracker, op); } void -meta_stack_tracker_record_remove (MetaStackTracker *tracker, - const MetaStackWindow *window, - gulong serial) +meta_stack_tracker_record_remove (MetaStackTracker *tracker, + guint64 window, + gulong serial) { MetaStackOp *op = g_slice_new (MetaStackOp); op->any.type = STACK_OP_REMOVE; op->any.serial = serial; - op->any.window = *window; + op->any.window = window; stack_tracker_apply_prediction (tracker, op); } void -meta_stack_tracker_record_restack_windows (MetaStackTracker *tracker, - const MetaStackWindow *windows, - int n_windows, - gulong serial) +meta_stack_tracker_record_restack_windows (MetaStackTracker *tracker, + const guint64 *windows, + int n_windows, + gulong serial) { int i; int n_x_windows = 0; @@ -619,14 +564,14 @@ meta_stack_tracker_record_restack_windows (MetaStackTracker *tracker, * events with intermediate serials, set n_complete rather than * removing the op from the queue. */ - if (n_windows && windows[0].any.type == META_WINDOW_CLIENT_TYPE_X11) + if (n_windows && META_STACK_ID_IS_X11 (windows[0])) n_x_windows++; for (i = 0; i < n_windows - 1; i++) { - const MetaStackWindow *lower = &windows[i + 1]; + guint64 lower = windows[i + 1]; gboolean involves_x = FALSE; - if (lower->any.type == META_WINDOW_CLIENT_TYPE_X11) + if (META_STACK_ID_IS_X11 (lower)) { n_x_windows++; @@ -637,61 +582,49 @@ meta_stack_tracker_record_restack_windows (MetaStackTracker *tracker, involves_x = TRUE; } - meta_stack_tracker_record_lower_below (tracker, lower, &windows[i], + meta_stack_tracker_record_lower_below (tracker, lower, windows[i], involves_x ? serial++ : 0); } } void -meta_stack_tracker_record_raise_above (MetaStackTracker *tracker, - const MetaStackWindow *window, - const MetaStackWindow *sibling, - gulong serial) +meta_stack_tracker_record_raise_above (MetaStackTracker *tracker, + guint64 window, + guint64 sibling, + gulong serial) { MetaStackOp *op = g_slice_new (MetaStackOp); op->any.type = STACK_OP_RAISE_ABOVE; op->any.serial = serial; - op->any.window = *window; - if (sibling) - op->raise_above.sibling = *sibling; - else - { - op->raise_above.sibling.any.type = META_WINDOW_CLIENT_TYPE_X11; - op->raise_above.sibling.x11.xwindow = None; - } + op->any.window = window; + op->raise_above.sibling = sibling; stack_tracker_apply_prediction (tracker, op); } void -meta_stack_tracker_record_lower_below (MetaStackTracker *tracker, - const MetaStackWindow *window, - const MetaStackWindow *sibling, - gulong serial) +meta_stack_tracker_record_lower_below (MetaStackTracker *tracker, + guint64 window, + guint64 sibling, + gulong serial) { MetaStackOp *op = g_slice_new (MetaStackOp); op->any.type = STACK_OP_LOWER_BELOW; op->any.serial = serial; - op->any.window = *window; - if (sibling) - op->lower_below.sibling = *sibling; - else - { - op->lower_below.sibling.any.type = META_WINDOW_CLIENT_TYPE_X11; - op->lower_below.sibling.x11.xwindow = None; - } + op->any.window = window; + op->lower_below.sibling = sibling; stack_tracker_apply_prediction (tracker, op); } void -meta_stack_tracker_record_lower (MetaStackTracker *tracker, - const MetaStackWindow *window, - gulong serial) +meta_stack_tracker_record_lower (MetaStackTracker *tracker, + guint64 window, + gulong serial) { - meta_stack_tracker_record_raise_above (tracker, window, NULL, serial); + meta_stack_tracker_record_raise_above (tracker, window, None, serial); } /* @op is an operation derived from an X event from the server and we @@ -720,7 +653,7 @@ stack_tracker_verify_predictions (MetaStackTracker *tracker, /* Wayland operations don't need to be verified and shouldn't end up * passed to this api. */ - g_return_val_if_fail (op->any.window.any.type == META_WINDOW_CLIENT_TYPE_X11, FALSE); + g_return_val_if_fail (META_STACK_ID_IS_X11 (op->any.window), FALSE); meta_topic (META_DEBUG_STACK, "Verifying predictions:\n"); @@ -737,69 +670,61 @@ stack_tracker_verify_predictions (MetaStackTracker *tracker, if (current_op->any.serial > op->any.serial) break; - modified_stack |= meta_stack_op_apply (current_op, predicted_stack); + modified_stack |= meta_stack_op_apply (tracker, current_op, predicted_stack); } } else predicted_stack = tracker->verified_stack; meta_topic (META_DEBUG_STACK, " predicted_stack: "); - stack_dump (predicted_stack); + stack_dump (tracker, predicted_stack); switch (op->any.type) { case STACK_OP_ADD: - if (!find_window (predicted_stack, &op->any.window)) + if (!find_window (predicted_stack, op->any.window)) { - char *window_id = get_window_id (&op->any.window); meta_topic (META_DEBUG_STACK, "Verify STACK_OP_ADD: window %s not found\n", - window_id); - g_free (window_id); + get_window_desc (tracker, op->any.window)); goto not_verified; } break; case STACK_OP_REMOVE: - if (find_window (predicted_stack, &op->any.window)) + if (find_window (predicted_stack, op->any.window)) { - char *window_id = get_window_id (&op->any.window); meta_topic (META_DEBUG_STACK, "Verify STACK_OP_REMOVE: window %s was unexpectedly found\n", - window_id); - g_free (window_id); + get_window_desc (tracker, op->any.window)); goto not_verified; } break; case STACK_OP_RAISE_ABOVE: { Window last_xwindow = None; - char *window_id; unsigned int i; /* This code is only intended for verifying operations based * on XEvents where we can assume the sibling refers to * another X window... */ - g_return_val_if_fail (op->raise_above.sibling.any.type == - META_WINDOW_CLIENT_TYPE_X11, FALSE); + g_return_val_if_fail (META_STACK_ID_IS_X11 (op->raise_above.sibling), FALSE); for (i = 0; i < predicted_stack->len; i++) { - MetaStackWindow *window = &g_array_index (predicted_stack, MetaStackWindow, i); + guint64 window = g_array_index (predicted_stack, guint64, i); - if (meta_stack_window_equal (window, &op->any.window)) + if (window == op->any.window) { - if (last_xwindow == op->raise_above.sibling.x11.xwindow) + if (last_xwindow == op->raise_above.sibling) goto verified; else goto not_verified; } - if (window->any.type == META_WINDOW_CLIENT_TYPE_X11) - last_xwindow = window->x11.xwindow; + if (META_STACK_ID_IS_X11 (window)) + last_xwindow = window; } - window_id = get_window_id (&op->any.window); meta_topic (META_DEBUG_STACK, "Verify STACK_OP_RAISE_ABOVE: window %s not found\n", - window_id); - g_free (window_id); + get_window_desc (tracker, op->any.window)); goto not_verified; } case STACK_OP_LOWER_BELOW: @@ -861,7 +786,7 @@ resync_verified_stack_with_xserver_stack (MetaStackTracker *tracker) { GList *l; unsigned int i, j; - MetaStackWindow *expected_xwindow; + guint64 expected_xwindow; gboolean modified_stack = FALSE; /* Overview of the algorithm: @@ -896,29 +821,28 @@ resync_verified_stack_with_xserver_stack (MetaStackTracker *tracker) for (l = tracker->unverified_predictions->head; l; l = l->next) { - meta_stack_op_apply (l->data, tracker->verified_stack); + meta_stack_op_apply (tracker, l->data, tracker->verified_stack); meta_stack_op_free (l->data); } g_queue_clear (tracker->unverified_predictions); j = 0; - expected_xwindow = &g_array_index (tracker->xserver_stack, MetaStackWindow, j); + expected_xwindow = g_array_index (tracker->xserver_stack, guint64, j); for (i = 0; i < tracker->verified_stack->len; ) { - MetaStackWindow *current = &g_array_index (tracker->verified_stack, MetaStackWindow, i); + guint64 current = g_array_index (tracker->verified_stack, guint64, i); - if (current->any.type != META_WINDOW_CLIENT_TYPE_X11) + if (!META_STACK_ID_IS_X11 (current)) { /* Progress i but not j */ i++; continue; } - if (current->x11.xwindow != expected_xwindow->x11.xwindow) + if (current != expected_xwindow) { - MetaStackWindow new; - MetaStackWindow *expected; + guint64 expected; int expected_index; /* If the current window corresponds to a window that's not @@ -947,17 +871,14 @@ resync_verified_stack_with_xserver_stack (MetaStackTracker *tracker) if (expected_index >= 0) { - expected = &g_array_index (tracker->verified_stack, - MetaStackWindow, expected_index); + expected = g_array_index (tracker->verified_stack, + guint64, expected_index); } else { - new.any.type = META_WINDOW_CLIENT_TYPE_X11; - new.x11.xwindow = expected_xwindow->x11.xwindow; + g_array_append_val (tracker->verified_stack, expected_xwindow); - g_array_append_val (tracker->verified_stack, new); - - expected = &new; + expected = expected_xwindow; expected_index = tracker->verified_stack->len - 1; } @@ -981,7 +902,7 @@ resync_verified_stack_with_xserver_stack (MetaStackTracker *tracker) i++; j++; - expected_xwindow = &g_array_index (tracker->xserver_stack, MetaStackWindow, j); + expected_xwindow = g_array_index (tracker->xserver_stack, guint64, j); if (j >= tracker->xserver_stack->len) break; @@ -991,9 +912,9 @@ resync_verified_stack_with_xserver_stack (MetaStackTracker *tracker) * xserver_stack and so we can remove them. */ while (i < tracker->verified_stack->len) { - MetaStackWindow *current = &g_array_index (tracker->verified_stack, MetaStackWindow, i); + guint64 current = g_array_index (tracker->verified_stack, guint64, i); - if (current->any.type == META_WINDOW_CLIENT_TYPE_X11) + if (META_STACK_ID_IS_X11 (current)) g_array_remove_index (tracker->verified_stack, i); else i++; @@ -1005,8 +926,8 @@ resync_verified_stack_with_xserver_stack (MetaStackTracker *tracker) * entries in xserver_stack then append them all to the end */ for (; j < tracker->xserver_stack->len; j++) { - MetaStackWindow *current = &g_array_index (tracker->xserver_stack, MetaStackWindow, j); - g_array_append_val (tracker->verified_stack, *current); + guint64 current = g_array_index (tracker->xserver_stack, guint64, j); + g_array_append_val (tracker->verified_stack, current); modified_stack = TRUE; } @@ -1034,7 +955,7 @@ stack_tracker_event_received (MetaStackTracker *tracker, if (op->any.serial < tracker->xserver_serial) return; - meta_stack_op_dump (op, "Stack op event received: ", "\n"); + meta_stack_op_dump (tracker, op, "Stack op event received: ", "\n"); tracker->xserver_serial = op->any.serial; @@ -1047,7 +968,7 @@ stack_tracker_event_received (MetaStackTracker *tracker, * * TODO: remove tracker->xserver_stack. */ - meta_stack_op_apply (op, tracker->xserver_stack); + meta_stack_op_apply (tracker, op, tracker->xserver_stack); if (!stack_tracker_verify_predictions (tracker, op)) resync_verified_stack_with_xserver_stack (tracker); @@ -1063,8 +984,7 @@ meta_stack_tracker_create_event (MetaStackTracker *tracker, op.any.type = STACK_OP_ADD; op.any.serial = event->serial; - op.add.window.any.type = META_WINDOW_CLIENT_TYPE_X11; - op.add.window.x11.xwindow = event->window; + op.add.window = event->window; stack_tracker_event_received (tracker, &op); } @@ -1077,8 +997,7 @@ meta_stack_tracker_destroy_event (MetaStackTracker *tracker, op.any.type = STACK_OP_REMOVE; op.any.serial = event->serial; - op.remove.window.any.type = META_WINDOW_CLIENT_TYPE_X11; - op.remove.window.x11.xwindow = event->window; + op.remove.window = event->window; stack_tracker_event_received (tracker, &op); } @@ -1093,8 +1012,7 @@ meta_stack_tracker_reparent_event (MetaStackTracker *tracker, op.any.type = STACK_OP_ADD; op.any.serial = event->serial; - op.add.window.any.type = META_WINDOW_CLIENT_TYPE_X11; - op.add.window.x11.xwindow = event->window; + op.add.window = event->window; stack_tracker_event_received (tracker, &op); } @@ -1104,8 +1022,7 @@ meta_stack_tracker_reparent_event (MetaStackTracker *tracker, op.any.type = STACK_OP_REMOVE; op.any.serial = event->serial; - op.remove.window.any.type = META_WINDOW_CLIENT_TYPE_X11; - op.remove.window.x11.xwindow = event->window; + op.remove.window = event->window; stack_tracker_event_received (tracker, &op); } @@ -1119,10 +1036,8 @@ meta_stack_tracker_configure_event (MetaStackTracker *tracker, op.any.type = STACK_OP_RAISE_ABOVE; op.any.serial = event->serial; - op.raise_above.window.any.type = META_WINDOW_CLIENT_TYPE_X11; - op.raise_above.window.x11.xwindow = event->window; - op.raise_above.sibling.any.type = META_WINDOW_CLIENT_TYPE_X11; - op.raise_above.sibling.x11.xwindow = event->above; + op.raise_above.window = event->window; + op.raise_above.sibling = event->above; stack_tracker_event_received (tracker, &op); } @@ -1146,7 +1061,7 @@ meta_stack_tracker_configure_event (MetaStackTracker *tracker, */ void meta_stack_tracker_get_stack (MetaStackTracker *tracker, - MetaStackWindow **windows, + guint64 **windows, int *n_windows) { GArray *stack; @@ -1165,7 +1080,7 @@ meta_stack_tracker_get_stack (MetaStackTracker *tracker, for (l = tracker->unverified_predictions->head; l; l = l->next) { MetaStackOp *op = l->data; - meta_stack_op_apply (op, tracker->predicted_stack); + meta_stack_op_apply (tracker, op, tracker->predicted_stack); } } @@ -1176,7 +1091,7 @@ meta_stack_tracker_get_stack (MetaStackTracker *tracker, meta_stack_tracker_dump (tracker); if (windows) - *windows = (MetaStackWindow *)stack->data; + *windows = (guint64 *)stack->data; if (n_windows) *n_windows = stack->len; } @@ -1191,7 +1106,7 @@ meta_stack_tracker_get_stack (MetaStackTracker *tracker, void meta_stack_tracker_sync_stack (MetaStackTracker *tracker) { - MetaStackWindow *windows; + guint64 *windows; GList *meta_windows; int n_windows; int i; @@ -1207,12 +1122,12 @@ meta_stack_tracker_sync_stack (MetaStackTracker *tracker) meta_windows = NULL; for (i = 0; i < n_windows; i++) { - MetaStackWindow *window = &windows[i]; + guint64 window = windows[i]; - if (window->any.type == META_WINDOW_CLIENT_TYPE_X11) + if (META_STACK_ID_IS_X11 (window)) { MetaWindow *meta_window = - meta_display_lookup_x_window (tracker->screen->display, windows[i].x11.xwindow); + meta_display_lookup_x_window (tracker->screen->display, (Window)window); /* When mapping back from xwindow to MetaWindow we have to be a bit careful; * children of the root could include unmapped windows created by toolkits @@ -1221,12 +1136,13 @@ meta_stack_tracker_sync_stack (MetaStackTracker *tracker) * see window-prop.c:reload_net_wm_user_time_window() for registration.) */ if (meta_window && - (windows[i].x11.xwindow == meta_window->xwindow || - (meta_window->frame && windows[i].x11.xwindow == meta_window->frame->xwindow))) + ((Window)window == meta_window->xwindow || + (meta_window->frame && (Window)window == meta_window->frame->xwindow))) meta_windows = g_list_prepend (meta_windows, meta_window); } else - meta_windows = g_list_prepend (meta_windows, window->wayland.meta_window); + meta_windows = g_list_prepend (meta_windows, + meta_display_lookup_stamp (tracker->screen->display, window)); } meta_compositor_sync_stack (tracker->screen->display->compositor, diff --git a/src/core/stack-tracker.h b/src/core/stack-tracker.h index f74400efa..d54d914e1 100644 --- a/src/core/stack-tracker.h +++ b/src/core/stack-tracker.h @@ -39,51 +39,33 @@ typedef struct _MetaStackTracker MetaStackTracker; -typedef union _MetaStackWindow -{ - struct { - MetaWindowClientType type; - } any; - struct { - MetaWindowClientType type; - Window xwindow; - } x11; - struct { - MetaWindowClientType type; - MetaWindow *meta_window; - } wayland; -} MetaStackWindow; - -gboolean meta_stack_window_equal (const MetaStackWindow *a, - const MetaStackWindow *b); - MetaStackTracker *meta_stack_tracker_new (MetaScreen *screen); void meta_stack_tracker_free (MetaStackTracker *tracker); /* These functions are called when we make an X call that changes the * stacking order; this allows MetaStackTracker to predict stacking * order before it receives events back from the X server */ -void meta_stack_tracker_record_add (MetaStackTracker *tracker, - const MetaStackWindow *window, - gulong serial); -void meta_stack_tracker_record_remove (MetaStackTracker *tracker, - const MetaStackWindow *window, - gulong serial); -void meta_stack_tracker_record_restack_windows (MetaStackTracker *tracker, - const MetaStackWindow *windows, - int n_windows, - gulong serial); -void meta_stack_tracker_record_raise_above (MetaStackTracker *tracker, - const MetaStackWindow *window, - const MetaStackWindow *sibling, - gulong serial); -void meta_stack_tracker_record_lower_below (MetaStackTracker *tracker, - const MetaStackWindow *window, - const MetaStackWindow *sibling, - gulong serial); -void meta_stack_tracker_record_lower (MetaStackTracker *tracker, - const MetaStackWindow *window, - gulong serial); +void meta_stack_tracker_record_add (MetaStackTracker *tracker, + guint64 window, + gulong serial); +void meta_stack_tracker_record_remove (MetaStackTracker *tracker, + guint64 window, + gulong serial); +void meta_stack_tracker_record_restack_windows (MetaStackTracker *tracker, + const guint64 *windows, + int n_windows, + gulong serial); +void meta_stack_tracker_record_raise_above (MetaStackTracker *tracker, + guint64 window, + guint64 sibling, + gulong serial); +void meta_stack_tracker_record_lower_below (MetaStackTracker *tracker, + guint64 window, + guint64 sibling, + gulong serial); +void meta_stack_tracker_record_lower (MetaStackTracker *tracker, + guint64 window, + gulong serial); /* These functions are used to update the stack when we get events * reflecting changes to the stacking order */ @@ -96,9 +78,9 @@ 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, - MetaStackWindow **windows, - int *n_entries); +void meta_stack_tracker_get_stack (MetaStackTracker *tracker, + guint64 **windows, + int *n_entries); void meta_stack_tracker_sync_stack (MetaStackTracker *tracker); void meta_stack_tracker_queue_sync_stack (MetaStackTracker *tracker); diff --git a/src/core/stack.c b/src/core/stack.c index 3e2654080..2ea144a94 100644 --- a/src/core/stack.c +++ b/src/core/stack.c @@ -1030,12 +1030,12 @@ stack_ensure_sorted (MetaStack *stack) stack_do_resort (stack); } -static MetaStackWindow * +static guint64 find_top_most_managed_window (MetaScreen *screen, - const MetaStackWindow *ignore) + guint64 ignore) { MetaStackTracker *stack_tracker = screen->stack_tracker; - MetaStackWindow *windows; + guint64 *windows; int n_windows; int i; @@ -1048,12 +1048,9 @@ find_top_most_managed_window (MetaScreen *screen, */ for (i = n_windows -1; i >= 0; i--) { - MetaStackWindow *other_window = &windows[i]; + guint64 other_window = windows[i]; - if (other_window->any.type == ignore->any.type && - ((other_window->any.type == META_WINDOW_CLIENT_TYPE_X11 && - other_window->x11.xwindow == ignore->x11.xwindow) || - other_window->wayland.meta_window == ignore->wayland.meta_window)) + if (other_window == ignore) { /* Do nothing. This means we're already the topmost managed * window, but it DOES NOT mean we are already just above @@ -1067,10 +1064,10 @@ find_top_most_managed_window (MetaScreen *screen, } else { - if (other_window->any.type == META_WINDOW_CLIENT_TYPE_X11) + if (META_STACK_ID_IS_X11 (other_window)) { MetaWindow *other = meta_display_lookup_x_window (screen->display, - other_window->x11.xwindow); + other_window); if (other != NULL && !other->override_redirect) return other_window; @@ -1085,7 +1082,7 @@ find_top_most_managed_window (MetaScreen *screen, } } - return NULL; + return 0; } /* When moving an X window we sometimes need an X based sibling. @@ -1094,17 +1091,17 @@ find_top_most_managed_window (MetaScreen *screen, * otherwise it searches downwards looking for the nearest X window. * * If no X based sibling could be found return NULL. */ -static MetaStackWindow * +static Window find_x11_sibling_downwards (MetaScreen *screen, - MetaStackWindow *sibling) + guint64 sibling) { MetaStackTracker *stack_tracker = screen->stack_tracker; - MetaStackWindow *windows; + guint64 *windows; int n_windows; int i; - if (sibling->any.type == META_WINDOW_CLIENT_TYPE_X11) - return sibling; + if (META_STACK_ID_IS_X11 (sibling)) + return (Window)sibling; meta_stack_tracker_get_stack (stack_tracker, &windows, &n_windows); @@ -1114,16 +1111,16 @@ find_x11_sibling_downwards (MetaScreen *screen, */ for (i = n_windows - 1; i >= 0; i--) - if (meta_stack_window_equal (&windows[i], sibling)) + if (windows[i] == sibling) break; for (; i >= 0; i--) { - if (windows[i].any.type == META_WINDOW_CLIENT_TYPE_X11) - return &windows[i]; + if (META_STACK_ID_IS_X11 (windows[i])) + return (Window)windows[i]; } - return NULL; + return None; } /** @@ -1150,20 +1147,20 @@ find_x11_sibling_downwards (MetaScreen *screen, */ static void raise_window_relative_to_managed_windows (MetaScreen *screen, - const MetaStackWindow *window) + guint64 stack_id) { gulong serial = 0; - MetaStackWindow *sibling; + guint64 sibling; - sibling = find_top_most_managed_window (screen, window); + sibling = find_top_most_managed_window (screen, stack_id); if (!sibling) { - if (window->any.type == META_WINDOW_CLIENT_TYPE_X11) + if (META_STACK_ID_IS_X11 (stack_id)) { serial = XNextRequest (screen->display->xdisplay); meta_error_trap_push (screen->display); XLowerWindow (screen->display->xdisplay, - window->x11.xwindow); + stack_id); meta_error_trap_pop (screen->display); } @@ -1171,31 +1168,31 @@ raise_window_relative_to_managed_windows (MetaScreen *screen, * to be sure we're below any override redirect windows. */ meta_stack_tracker_record_lower (screen->stack_tracker, - window, + stack_id, serial); return; } /* window is the topmost managed child */ meta_topic (META_DEBUG_STACK, - "Moving 0x%lx above topmost managed child window 0x%lx\n", - window->any.type == META_WINDOW_CLIENT_TYPE_X11 ? window->x11.xwindow: 0, - sibling->any.type == META_WINDOW_CLIENT_TYPE_X11 ? sibling->x11.xwindow: 0); + "Moving %s above topmost managed child window %s\n", + meta_display_describe_stack_id (screen->display, stack_id), + meta_display_describe_stack_id (screen->display, sibling)); - if (window->any.type == META_WINDOW_CLIENT_TYPE_X11) + if (META_STACK_ID_IS_X11 (stack_id)) { XWindowChanges changes; - MetaStackWindow *x11_sibling = find_x11_sibling_downwards (screen, sibling); + Window x11_sibling = find_x11_sibling_downwards (screen, sibling); serial = XNextRequest (screen->display->xdisplay); if (x11_sibling) { - changes.sibling = x11_sibling->x11.xwindow; + changes.sibling = x11_sibling; changes.stack_mode = Above; meta_error_trap_push (screen->display); XConfigureWindow (screen->display->xdisplay, - window->x11.xwindow, + (Window)stack_id, CWSibling | CWStackMode, &changes); meta_error_trap_pop (screen->display); @@ -1207,13 +1204,13 @@ raise_window_relative_to_managed_windows (MetaScreen *screen, */ meta_error_trap_push (screen->display); XLowerWindow (screen->display->xdisplay, - window->x11.xwindow); + (Window)stack_id); meta_error_trap_pop (screen->display); } } meta_stack_tracker_record_raise_above (screen->stack_tracker, - window, + stack_id, sibling, serial); } @@ -1239,9 +1236,8 @@ stack_sync_to_xserver (MetaStack *stack) GArray *all_root_children_stacked; /* wayland OR x11 */ GList *tmp; GArray *x11_hidden; - GArray *x11_hidden_stack_windows; + GArray *x11_hidden_stack_ids; int n_override_redirect = 0; - MetaStackWindow guard_stack_window; /* Bail out if frozen */ if (stack->freeze_count > 0) @@ -1258,10 +1254,10 @@ stack_sync_to_xserver (MetaStack *stack) */ x11_stacked = g_array_new (FALSE, FALSE, sizeof (Window)); - all_root_children_stacked = g_array_new (FALSE, FALSE, sizeof (MetaStackWindow)); + all_root_children_stacked = g_array_new (FALSE, FALSE, sizeof (guint64)); x11_root_children_stacked = g_array_new (FALSE, FALSE, sizeof (Window)); - x11_hidden_stack_windows = g_array_new (FALSE, FALSE, sizeof (MetaStackWindow)); + x11_hidden_stack_ids = g_array_new (FALSE, FALSE, sizeof (guint64)); x11_hidden = g_array_new (FALSE, FALSE, sizeof (Window)); /* The screen guard window sits above all hidden windows and acts as @@ -1275,9 +1271,7 @@ stack_sync_to_xserver (MetaStack *stack) { MetaWindow *w = tmp->data; Window top_level_window; - MetaStackWindow stack_window; - - stack_window.any.type = w->client_type; + guint64 stack_id; meta_topic (META_DEBUG_STACK, "%u:%d - %s ", w->layer, w->stack_position, w->desc); @@ -1294,9 +1288,9 @@ stack_sync_to_xserver (MetaStack *stack) top_level_window = w->xwindow; if (w->client_type == META_WINDOW_CLIENT_TYPE_X11) - stack_window.x11.xwindow = top_level_window; + stack_id = top_level_window; else - stack_window.wayland.meta_window = w; + stack_id = w->stamp; /* We don't restack hidden windows along with the rest, though they are * reflected in the _NET hints. Hidden windows all get pushed below @@ -1305,18 +1299,15 @@ stack_sync_to_xserver (MetaStack *stack) { if (w->client_type == META_WINDOW_CLIENT_TYPE_X11) { - MetaStackWindow stack_window; + guint64 stack_id = top_level_window; - stack_window.any.type = META_WINDOW_CLIENT_TYPE_X11; - stack_window.x11.xwindow = top_level_window; - - g_array_append_val (x11_hidden_stack_windows, stack_window); + g_array_append_val (x11_hidden_stack_ids, stack_id); g_array_append_val (x11_hidden, top_level_window); } continue; } - g_array_append_val (all_root_children_stacked, stack_window); + g_array_append_val (all_root_children_stacked, stack_id); /* build XRestackWindows() array from top to bottom */ if (w->client_type == META_WINDOW_CLIENT_TYPE_X11) @@ -1356,7 +1347,7 @@ stack_sync_to_xserver (MetaStack *stack) x11_root_children_stacked->len); } meta_stack_tracker_record_restack_windows (stack->screen->stack_tracker, - (MetaStackWindow *) all_root_children_stacked->data, + (guint64 *) all_root_children_stacked->data, all_root_children_stacked->len, serial); } @@ -1369,34 +1360,31 @@ stack_sync_to_xserver (MetaStack *stack) * was saved, then we may have inefficiency, but I don't think things * break... */ - const MetaStackWindow *old_stack = (MetaStackWindow *) stack->last_all_root_children_stacked->data; - const MetaStackWindow *new_stack = (MetaStackWindow *) all_root_children_stacked->data; + const guint64 *old_stack = (guint64 *) stack->last_all_root_children_stacked->data; + const guint64 *new_stack = (guint64 *) all_root_children_stacked->data; const int old_len = stack->last_all_root_children_stacked->len; const int new_len = all_root_children_stacked->len; - const MetaStackWindow *oldp = old_stack; - const MetaStackWindow *newp = new_stack; - const MetaStackWindow *old_end = old_stack + old_len; - const MetaStackWindow *new_end = new_stack + new_len; + const guint64 *oldp = old_stack; + const guint64 *newp = new_stack; + const guint64 *old_end = old_stack + old_len; + const guint64 *new_end = new_stack + new_len; Window last_xwindow = None; - const MetaStackWindow *last_window = NULL; + guint64 last_window = 0; while (oldp != old_end && newp != new_end) { - if (meta_stack_window_equal (oldp, newp)) + if (*oldp == *newp) { /* Stacks are the same here, move on */ ++oldp; - if (newp->any.type == META_WINDOW_CLIENT_TYPE_X11) - last_xwindow = newp->x11.xwindow; - last_window = newp; + if (META_STACK_ID_IS_X11 (*newp)) + last_xwindow = (Window)*newp; + last_window = *newp; ++newp; } - else if ((oldp->any.type == META_WINDOW_CLIENT_TYPE_X11 && - meta_display_lookup_x_window (stack->screen->display, - oldp->x11.xwindow) == NULL) || - (oldp->any.type == META_WINDOW_CLIENT_TYPE_WAYLAND && - oldp->wayland.meta_window == NULL)) + else if (meta_display_lookup_stack_id (stack->screen->display, + *oldp) == NULL) { /* *oldp is no longer known to us (probably destroyed), * so we can just skip it @@ -1408,12 +1396,12 @@ stack_sync_to_xserver (MetaStack *stack) /* Move *newp below the last_window */ if (!last_window) { - meta_topic (META_DEBUG_STACK, "Using window 0x%lx as topmost (but leaving it in-place)\n", - newp->x11.xwindow); + meta_topic (META_DEBUG_STACK, "Using window %s as topmost (but leaving it in-place)\n", + meta_display_describe_stack_id (stack->screen->display, *newp)); - raise_window_relative_to_managed_windows (stack->screen, newp); + raise_window_relative_to_managed_windows (stack->screen, *newp); } - else if (newp->any.type == META_WINDOW_CLIENT_TYPE_X11 && + else if (META_STACK_ID_IS_X11 (*newp) && last_xwindow == None) { /* In this case we have an X window that we need to @@ -1432,10 +1420,10 @@ stack_sync_to_xserver (MetaStack *stack) * know last_window isn't an X window). */ - raise_window_relative_to_managed_windows (stack->screen, newp); + raise_window_relative_to_managed_windows (stack->screen, *newp); meta_stack_tracker_record_lower_below (stack->screen->stack_tracker, - newp, last_window, + *newp, last_window, 0); /* no x request serial */ } else @@ -1447,11 +1435,11 @@ stack_sync_to_xserver (MetaStack *stack) * unmanaging last_xwindow, we'll fix it up. */ - meta_topic (META_DEBUG_STACK, "Placing window 0x%lx below 0x%lx\n", - newp->any.type == META_WINDOW_CLIENT_TYPE_X11 ? newp->x11.xwindow : 0, + meta_topic (META_DEBUG_STACK, "Placing window %s below 0x%lx\n", + meta_display_describe_stack_id (stack->screen->display, *newp), last_xwindow); - if (newp->any.type == META_WINDOW_CLIENT_TYPE_X11) + if (META_STACK_ID_IS_X11 (*newp)) { XWindowChanges changes; serial = XNextRequest (stack->screen->display->xdisplay); @@ -1460,26 +1448,26 @@ stack_sync_to_xserver (MetaStack *stack) changes.stack_mode = Below; XConfigureWindow (stack->screen->display->xdisplay, - newp->x11.xwindow, + (Window)*newp, CWSibling | CWStackMode, &changes); } meta_stack_tracker_record_lower_below (stack->screen->stack_tracker, - newp, last_window, + *newp, last_window, serial); } - if (newp->any.type == META_WINDOW_CLIENT_TYPE_X11) - last_xwindow = newp->x11.xwindow; - last_window = newp; + if (META_STACK_ID_IS_X11 (*newp)) + last_xwindow = *newp; + last_window = *newp; ++newp; } } if (newp != new_end) { - const MetaStackWindow *x_ref; + const guint64 *x_ref; unsigned long serial = 0; /* Restack remaining windows */ @@ -1490,7 +1478,7 @@ stack_sync_to_xserver (MetaStack *stack) * as a reference point for re-stacking remaining X windows */ if (newp != new_stack) for (x_ref = newp - 1; - x_ref->any.type != META_WINDOW_CLIENT_TYPE_X11 && x_ref > new_stack; + META_STACK_ID_IS_X11 (*x_ref) && x_ref > new_stack; x_ref--) ; else @@ -1499,16 +1487,16 @@ stack_sync_to_xserver (MetaStack *stack) /* If we didn't find an X window looking backwards then walk forwards * through the remaining windows to find the first remaining X window * instead. */ - if (x_ref->any.type != META_WINDOW_CLIENT_TYPE_X11) + if (META_STACK_ID_IS_X11 (*x_ref)) { for (x_ref = newp; - x_ref->any.type != META_WINDOW_CLIENT_TYPE_X11 && x_ref < new_end; + META_STACK_ID_IS_X11 (*x_ref) && x_ref < new_end; x_ref++) ; } /* If there are any X windows remaining unstacked then restack them */ - if (x_ref->any.type == META_WINDOW_CLIENT_TYPE_X11) + if (META_STACK_ID_IS_X11 (*x_ref)) { int i; @@ -1516,7 +1504,7 @@ stack_sync_to_xserver (MetaStack *stack) { Window *reference = &g_array_index (x11_root_children_stacked, Window, i); - if (*reference == x_ref->x11.xwindow) + if (*reference == (Window)*x_ref) { int n = x11_root_children_stacked->len - i; @@ -1545,21 +1533,19 @@ stack_sync_to_xserver (MetaStack *stack) } /* Push hidden X windows to the bottom of the stack under the guard window */ - guard_stack_window.any.type = META_WINDOW_CLIENT_TYPE_X11; - guard_stack_window.x11.xwindow = stack->screen->guard_window; meta_stack_tracker_record_lower (stack->screen->stack_tracker, - &guard_stack_window, + stack->screen->guard_window, XNextRequest (stack->screen->display->xdisplay)); XLowerWindow (stack->screen->display->xdisplay, stack->screen->guard_window); meta_stack_tracker_record_restack_windows (stack->screen->stack_tracker, - (MetaStackWindow *)x11_hidden_stack_windows->data, - x11_hidden_stack_windows->len, + (guint64 *)x11_hidden_stack_ids->data, + x11_hidden_stack_ids->len, XNextRequest (stack->screen->display->xdisplay)); XRestackWindows (stack->screen->display->xdisplay, (Window *)x11_hidden->data, x11_hidden->len); g_array_free (x11_hidden, TRUE); - g_array_free (x11_hidden_stack_windows, TRUE); + g_array_free (x11_hidden_stack_ids, TRUE); meta_error_trap_pop (stack->screen->display); /* on error, a window was destroyed; it should eventually diff --git a/src/core/window-private.h b/src/core/window-private.h index aa47d09fc..73174f2eb 100644 --- a/src/core/window-private.h +++ b/src/core/window-private.h @@ -92,6 +92,7 @@ struct _MetaWindow MetaDisplay *display; MetaScreen *screen; + guint64 stamp; const MetaMonitorInfo *monitor; MetaWorkspace *workspace; MetaWindowClientType client_type; diff --git a/src/core/window.c b/src/core/window.c index 956f0c353..abf66949a 100644 --- a/src/core/window.c +++ b/src/core/window.c @@ -71,6 +71,10 @@ static int destroying_windows_disallowed = 0; +// Each window has a "stamp" which is a non-recycled 64-bit ID. They +// start after the end of the XID space so that, for stacking +// we can keep a guint64 that represents one or the other +static guint64 next_window_stamp = G_GUINT64_CONSTANT(0x100000000); static void invalidate_work_areas (MetaWindow *window); static void set_wm_state (MetaWindow *window); @@ -642,6 +646,7 @@ meta_window_class_init (MetaWindowClass *klass) static void meta_window_init (MetaWindow *self) { + self->stamp = next_window_stamp++; meta_prefs_add_listener (prefs_changed_callback, self); } @@ -803,6 +808,8 @@ _meta_window_shared_new (MetaDisplay *display, * type */ window->display = display; + meta_display_register_stamp (window->display, &window->stamp, window); + window->workspace = NULL; window->sync_request_counter = None; @@ -1239,6 +1246,8 @@ meta_window_unmanage (MetaWindow *window, meta_bug ("Tried to destroy window %s while destruction was not allowed\n", window->desc); + meta_display_unregister_stamp (window->display, window->stamp); + window->unmanaging = TRUE; if (meta_prefs_get_attach_modal_dialogs ()) diff --git a/src/tests/test-runner.c b/src/tests/test-runner.c index 83c6ee491..7b2dae174 100644 --- a/src/tests/test-runner.c +++ b/src/tests/test-runner.c @@ -512,7 +512,7 @@ test_case_assert_stacking (TestCase *test, GError **error) { MetaDisplay *display = meta_get_display (); - MetaStackWindow *windows; + guint64 *windows; int n_windows; GString *stack_string = g_string_new (NULL); GString *expected_string = g_string_new (NULL); @@ -521,22 +521,14 @@ test_case_assert_stacking (TestCase *test, meta_stack_tracker_get_stack (display->screen->stack_tracker, &windows, &n_windows); for (i = 0; i < n_windows; i++) { - MetaWindow *window; - - if (windows[i].any.type == META_WINDOW_CLIENT_TYPE_X11) - window = meta_display_lookup_x_window (display, - windows[i].x11.xwindow); - else - window = windows[i].wayland.meta_window; - + MetaWindow *window = meta_display_lookup_stack_id (display, windows[i]); if (window != NULL && window->title) { - /* See comment in meta_ui_new() about why the dummy window for GTK+ theming * is managed as a MetaWindow. */ - if (windows[i].any.type == META_WINDOW_CLIENT_TYPE_X11 && - meta_ui_window_is_dummy (display->screen->ui, windows[i].x11.xwindow)) + if (META_STACK_ID_IS_X11 (windows[i]) && + meta_ui_window_is_dummy (display->screen->ui, windows[i])) continue; if (stack_string->len > 0) @@ -579,18 +571,18 @@ test_case_check_xserver_stacking (TestCase *test, GString *x11_string = g_string_new (NULL); int i; - MetaStackWindow *windows; + guint64 *windows; int n_windows; meta_stack_tracker_get_stack (display->screen->stack_tracker, &windows, &n_windows); for (i = 0; i < n_windows; i++) { - if (windows[i].any.type == META_WINDOW_CLIENT_TYPE_X11) + if (META_STACK_ID_IS_X11 (windows[i])) { if (local_string->len > 0) g_string_append_c (local_string, ' '); - g_string_append_printf (local_string, "%#lx", windows[i].x11.xwindow); + g_string_append_printf (local_string, "%#lx", (Window)windows[i]); } } diff --git a/src/wayland/window-wayland.c b/src/wayland/window-wayland.c index 3733bca52..9a82b354b 100644 --- a/src/wayland/window-wayland.c +++ b/src/wayland/window-wayland.c @@ -60,11 +60,8 @@ meta_window_wayland_manage (MetaWindow *window) meta_display_register_wayland_window (display, window); { - MetaStackWindow stack_window; - stack_window.any.type = META_WINDOW_CLIENT_TYPE_WAYLAND; - stack_window.wayland.meta_window = window; meta_stack_tracker_record_add (window->screen->stack_tracker, - &stack_window, + window->stamp, 0); } } @@ -73,11 +70,8 @@ static void meta_window_wayland_unmanage (MetaWindow *window) { { - MetaStackWindow stack_window; - stack_window.any.type = META_WINDOW_CLIENT_TYPE_WAYLAND; - stack_window.wayland.meta_window = window; meta_stack_tracker_record_remove (window->screen->stack_tracker, - &stack_window, + window->stamp, 0); }