diff options
| author | Owen W. Taylor <otaylor@fishsoup.net> | 2014-09-09 15:44:26 -0400 |
|---|---|---|
| committer | Owen W. Taylor <otaylor@fishsoup.net> | 2014-09-12 13:42:56 -0400 |
| commit | 34573660665ba4134451cc82a596367dbf3989d0 (patch) | |
| tree | 1246b081cf60f8eab0e33bbd7fad823e393ed140 /src/core/stack-tracker.c | |
| parent | cb66cf6398f4a870ff6e7c0f7acab5b71a3f98ad (diff) | |
| download | mutter-34573660665ba4134451cc82a596367dbf3989d0.tar.gz | |
Move manipulation of the X stack to MetaStackTracker
Since MetaStackTracker is the code that knows about the current X stacking order
and the relationship between X windows and Wayland windows, it's cleaner to
encapsulate stack manipulation in MetaStackTracker rather than have the calling
code make the X calls and only call into MetaStackTracker to inform it about
the changes.
https://bugzilla.gnome.org/show_bug.cgi?id=736559
Diffstat (limited to 'src/core/stack-tracker.c')
| -rw-r--r-- | src/core/stack-tracker.c | 195 |
1 files changed, 147 insertions, 48 deletions
diff --git a/src/core/stack-tracker.c b/src/core/stack-tracker.c index c3ec5ccc7..4ef4026e0 100644 --- a/src/core/stack-tracker.c +++ b/src/core/stack-tracker.c @@ -39,6 +39,7 @@ #include "frame.h" #include "screen-private.h" #include "stack-tracker.h" +#include <meta/errors.h> #include <meta/util.h> #include <meta/compositor.h> @@ -590,54 +591,6 @@ meta_stack_tracker_record_remove (MetaStackTracker *tracker, } void -meta_stack_tracker_record_restack_windows (MetaStackTracker *tracker, - const guint64 *windows, - int n_windows, - gulong serial) -{ - int i; - int n_x_windows = 0; - - /* XRestackWindows() isn't actually a X requests - it's broken down - * by XLib into a series of XConfigureWindow(StackMode=below); we - * mirror that here. - * - * Since there may be a mixture of X and wayland windows in the - * stack it's ambiguous which operations we should associate with an - * X serial number. One thing we do know though is that there will - * be (n_x_window - 1) X requests made. - * - * Aside: Having a separate StackOp for this would be possible to - * get some extra efficiency in memory allocation and in applying - * the op, at the expense of a code complexity. Implementation hint - * for that - keep op->restack_window.n_complete, and when receiving - * events with intermediate serials, set n_complete rather than - * removing the op from the queue. - */ - if (n_windows && META_STACK_ID_IS_X11 (windows[0])) - n_x_windows++; - for (i = 0; i < n_windows - 1; i++) - { - guint64 lower = windows[i + 1]; - gboolean involves_x = FALSE; - - if (META_STACK_ID_IS_X11 (lower)) - { - n_x_windows++; - - /* Since the first X window is a reference point we only - * assoicate a serial number with the operations involving - * later X windows. */ - if (n_x_windows > 1) - involves_x = TRUE; - } - - meta_stack_tracker_record_lower_below (tracker, lower, windows[i], - involves_x ? serial++ : 0); - } -} - -void meta_stack_tracker_record_raise_above (MetaStackTracker *tracker, guint64 window, guint64 sibling, @@ -960,3 +913,149 @@ meta_stack_tracker_queue_sync_stack (MetaStackTracker *tracker) } } +/* When moving an X window we sometimes need an X based sibling. + * + * If the given sibling is X based this function returns it back + * otherwise it searches downwards looking for the nearest X window. + * + * If no X based sibling could be found return NULL. */ +static Window +find_x11_sibling_downwards (MetaStackTracker *tracker, + guint64 sibling) +{ + guint64 *windows; + int n_windows; + int i; + + if (META_STACK_ID_IS_X11 (sibling)) + return (Window)sibling; + + meta_stack_tracker_get_stack (tracker, + &windows, &n_windows); + + /* NB: Children are in order from bottom to top and we + * want to search downwards for the nearest X window. + */ + + for (i = n_windows - 1; i >= 0; i--) + if (windows[i] == sibling) + break; + + for (; i >= 0; i--) + { + if (META_STACK_ID_IS_X11 (windows[i])) + return (Window)windows[i]; + } + + return None; +} + +static Window +find_x11_sibling_upwards (MetaStackTracker *tracker, + guint64 sibling) +{ + guint64 *windows; + int n_windows; + int i; + + if (META_STACK_ID_IS_X11 (sibling)) + return (Window)sibling; + + meta_stack_tracker_get_stack (tracker, + &windows, &n_windows); + + for (i = 0; i < n_windows; i++) + if (windows[i] == sibling) + break; + + for (; i < n_windows; i++) + { + if (META_STACK_ID_IS_X11 (windows[i])) + return (Window)windows[i]; + } + + return None; +} + +void +meta_stack_tracker_lower_below (MetaStackTracker *tracker, + guint64 window, + guint64 sibling) +{ + gulong serial = 0; + + if (META_STACK_ID_IS_X11 (window)) + { + XWindowChanges changes; + serial = XNextRequest (tracker->screen->display->xdisplay); + + meta_error_trap_push (tracker->screen->display); + + changes.sibling = sibling ? find_x11_sibling_upwards (tracker,sibling) : None; + changes.stack_mode = changes.sibling ? Below : Above; + + XConfigureWindow (tracker->screen->display->xdisplay, + window, + (changes.sibling ? CWSibling : 0) | CWStackMode, + &changes); + + meta_error_trap_pop (tracker->screen->display); + } + + meta_stack_tracker_record_lower_below (tracker, + window, sibling, + serial); +} + +void +meta_stack_tracker_lower (MetaStackTracker *tracker, + guint64 window) +{ + meta_stack_tracker_raise_above (tracker, window, None); +} + +void +meta_stack_tracker_raise_above (MetaStackTracker *tracker, + guint64 window, + guint64 sibling) +{ + gulong serial = 0; + + if (META_STACK_ID_IS_X11 (window)) + { + XWindowChanges changes; + serial = XNextRequest (tracker->screen->display->xdisplay); + + meta_error_trap_push (tracker->screen->display); + + changes.sibling = sibling ? find_x11_sibling_downwards (tracker, sibling) : None; + changes.stack_mode = changes.sibling ? Above : Below; + + XConfigureWindow (tracker->screen->display->xdisplay, + (Window)window, + (changes.sibling ? CWSibling : 0) | CWStackMode, + &changes); + + meta_error_trap_pop (tracker->screen->display); + } + + meta_stack_tracker_record_raise_above (tracker, window, + sibling, serial); +} + +void +meta_stack_tracker_restack_windows (MetaStackTracker *tracker, + const guint64 *windows, + int n_windows) +{ + int i; + + /* XRestackWindows() isn't actually a X requests - it's broken down + * by XLib into a series of XConfigureWindow(StackMode=below); we + * just do the same here directly. The main disadvantage of is that + * we allocate individual ops for each lower, and also that we are + * grabbing the libX11 lock separately for individual component. + */ + for (i = 0; i < n_windows - 1; i++) + meta_stack_tracker_lower_below (tracker, windows[i + 1], windows[i]); +} |
