1
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
5
* @short_description: Which windows cover which other windows
9
* Copyright (C) 2001 Havoc Pennington
10
* Copyright (C) 2002, 2003 Red Hat, Inc.
11
* Copyright (C) 2004 Rob Adams
12
* Copyright (C) 2004, 2005 Elijah Newren
14
* This program is free software; you can redistribute it and/or
15
* modify it under the terms of the GNU General Public License as
16
* published by the Free Software Foundation; either version 2 of the
17
* License, or (at your option) any later version.
19
* This program is distributed in the hope that it will be useful, but
20
* WITHOUT ANY WARRANTY; without even the implied warranty of
21
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22
* General Public License for more details.
24
* You should have received a copy of the GNU General Public License
25
* along with this program; if not, see <http://www.gnu.org/licenses/>.
30
#include "window-private.h"
31
#include <meta/errors.h>
33
#include <meta/group.h>
34
#include <meta/prefs.h>
35
#include <meta/workspace.h>
36
#include "backends/meta-logical-monitor.h"
38
#include <X11/Xatom.h>
40
#include "x11/group-private.h"
42
#define WINDOW_HAS_TRANSIENT_TYPE(w) \
43
(w->type == META_WINDOW_DIALOG || \
44
w->type == META_WINDOW_MODAL_DIALOG || \
45
w->type == META_WINDOW_TOOLBAR || \
46
w->type == META_WINDOW_MENU || \
47
w->type == META_WINDOW_UTILITY)
49
#define WINDOW_TRANSIENT_FOR_WHOLE_GROUP(w) \
50
(WINDOW_HAS_TRANSIENT_TYPE (w) && w->transient_for == NULL)
52
static void stack_sync_to_xserver (MetaStack *stack);
53
static void meta_window_set_stack_position_no_sync (MetaWindow *window,
55
static void stack_do_window_deletions (MetaStack *stack);
56
static void stack_do_window_additions (MetaStack *stack);
57
static void stack_do_relayer (MetaStack *stack);
58
static void stack_do_constrain (MetaStack *stack);
59
static void stack_do_resort (MetaStack *stack);
61
static void stack_ensure_sorted (MetaStack *stack);
64
meta_stack_new (MetaScreen *screen)
68
stack = g_new (MetaStack, 1);
70
stack->screen = screen;
71
stack->xwindows = g_array_new (FALSE, FALSE, sizeof (Window));
75
stack->removed = NULL;
77
stack->freeze_count = 0;
78
stack->n_positions = 0;
80
stack->need_resort = FALSE;
81
stack->need_relayer = FALSE;
82
stack->need_constrain = FALSE;
88
meta_stack_free (MetaStack *stack)
90
g_array_free (stack->xwindows, TRUE);
92
g_list_free (stack->sorted);
93
g_list_free (stack->added);
94
g_list_free (stack->removed);
100
meta_stack_add (MetaStack *stack,
103
g_return_if_fail (meta_window_is_stackable (window));
105
meta_topic (META_DEBUG_STACK, "Adding window %s to the stack\n", window->desc);
107
if (meta_window_is_in_stack (window))
108
meta_bug ("Window %s had stack position already\n", window->desc);
110
stack->added = g_list_prepend (stack->added, window);
112
window->stack_position = stack->n_positions;
113
stack->n_positions += 1;
114
meta_topic (META_DEBUG_STACK,
115
"Window %s has stack_position initialized to %d\n",
116
window->desc, window->stack_position);
118
stack_sync_to_xserver (stack);
119
meta_stack_update_window_tile_matches (stack, window->screen->active_workspace);
123
meta_stack_remove (MetaStack *stack,
126
meta_topic (META_DEBUG_STACK, "Removing window %s from the stack\n", window->desc);
128
/* Set window to top position, so removing it will not leave gaps
129
* in the set of positions
131
meta_window_set_stack_position_no_sync (window,
132
stack->n_positions - 1);
133
window->stack_position = -1;
134
stack->n_positions -= 1;
136
/* We don't know if it's been moved from "added" to "stack" yet */
137
stack->added = g_list_remove (stack->added, window);
138
stack->sorted = g_list_remove (stack->sorted, window);
140
/* stack->removed is only used to update stack->xwindows */
141
if (window->client_type == META_WINDOW_CLIENT_TYPE_X11)
143
/* Remember the window ID to remove it from the stack array.
144
* The macro is safe to use: Window is guaranteed to be 32 bits, and
145
* GUINT_TO_POINTER says it only works on 32 bits.
147
stack->removed = g_list_prepend (stack->removed,
148
GUINT_TO_POINTER (window->xwindow));
150
stack->removed = g_list_prepend (stack->removed,
151
GUINT_TO_POINTER (window->frame->xwindow));
154
stack_sync_to_xserver (stack);
155
meta_stack_update_window_tile_matches (stack, window->screen->active_workspace);
159
meta_stack_update_layer (MetaStack *stack,
162
stack->need_relayer = TRUE;
164
stack_sync_to_xserver (stack);
165
meta_stack_update_window_tile_matches (stack, window->screen->active_workspace);
169
meta_stack_update_transient (MetaStack *stack,
172
stack->need_constrain = TRUE;
174
stack_sync_to_xserver (stack);
175
meta_stack_update_window_tile_matches (stack, window->screen->active_workspace);
178
/* raise/lower within a layer */
180
meta_stack_raise (MetaStack *stack,
184
int max_stack_position = window->stack_position;
185
MetaWorkspace *workspace;
187
stack_ensure_sorted (stack);
189
workspace = meta_window_get_workspace (window);
190
for (l = stack->sorted; l; l = l->next)
192
MetaWindow *w = (MetaWindow *) l->data;
193
if (meta_window_located_on_workspace (w, workspace) &&
194
w->stack_position > max_stack_position)
195
max_stack_position = w->stack_position;
198
if (max_stack_position == window->stack_position)
201
meta_window_set_stack_position_no_sync (window, max_stack_position);
203
stack_sync_to_xserver (stack);
204
meta_stack_update_window_tile_matches (stack, window->screen->active_workspace);
208
meta_stack_lower (MetaStack *stack,
212
int min_stack_position = window->stack_position;
213
MetaWorkspace *workspace;
215
stack_ensure_sorted (stack);
217
workspace = meta_window_get_workspace (window);
218
for (l = stack->sorted; l; l = l->next)
220
MetaWindow *w = (MetaWindow *) l->data;
221
if (meta_window_located_on_workspace (w, workspace) &&
222
w->stack_position < min_stack_position)
223
min_stack_position = w->stack_position;
226
if (min_stack_position == window->stack_position)
229
meta_window_set_stack_position_no_sync (window, min_stack_position);
231
stack_sync_to_xserver (stack);
232
meta_stack_update_window_tile_matches (stack, window->screen->active_workspace);
236
meta_stack_freeze (MetaStack *stack)
238
stack->freeze_count += 1;
242
meta_stack_thaw (MetaStack *stack)
244
g_return_if_fail (stack->freeze_count > 0);
246
stack->freeze_count -= 1;
247
stack_sync_to_xserver (stack);
248
meta_stack_update_window_tile_matches (stack, NULL);
252
meta_stack_update_window_tile_matches (MetaStack *stack,
253
MetaWorkspace *workspace)
255
GList *windows, *tmp;
257
if (stack->freeze_count > 0)
260
windows = meta_stack_list_windows (stack, workspace);
264
meta_window_compute_tile_match ((MetaWindow *) tmp->data);
268
g_list_free (windows);
271
/* Get layer ignoring any transient or group relationships */
272
static MetaStackLayer
273
get_standalone_layer (MetaWindow *window)
275
MetaStackLayer layer;
277
switch (window->type)
279
case META_WINDOW_DESKTOP:
280
layer = META_LAYER_DESKTOP;
283
case META_WINDOW_DOCK:
284
if (window->wm_state_below ||
285
(window->monitor && window->monitor->in_fullscreen))
286
layer = META_LAYER_BOTTOM;
288
layer = META_LAYER_DOCK;
291
case META_WINDOW_DROPDOWN_MENU:
292
case META_WINDOW_POPUP_MENU:
293
case META_WINDOW_TOOLTIP:
294
case META_WINDOW_NOTIFICATION:
295
case META_WINDOW_COMBO:
296
case META_WINDOW_OVERRIDE_OTHER:
297
layer = META_LAYER_OVERRIDE_REDIRECT;
300
if (window->wm_state_below)
301
layer = META_LAYER_BOTTOM;
302
else if (window->wm_state_above && !META_WINDOW_MAXIMIZED (window))
303
layer = META_LAYER_TOP;
305
layer = META_LAYER_NORMAL;
312
/* Note that this function can never use window->layer only
313
* get_standalone_layer, or we'd have issues.
315
static MetaStackLayer
316
get_maximum_layer_in_group (MetaWindow *window)
322
MetaStackLayer layer;
324
max = META_LAYER_DESKTOP;
326
group = meta_window_get_group (window);
329
members = meta_group_list_windows (group);
336
MetaWindow *w = tmp->data;
338
if (!w->override_redirect)
340
layer = get_standalone_layer (w);
348
g_slist_free (members);
354
compute_layer (MetaWindow *window)
356
window->layer = get_standalone_layer (window);
358
/* We can only do promotion-due-to-group for dialogs and other
359
* transients, or weird stuff happens like the desktop window and
360
* nautilus windows getting in the same layer, or all gnome-terminal
361
* windows getting in fullscreen layer if any terminal is
364
if (window->layer != META_LAYER_DESKTOP &&
365
WINDOW_HAS_TRANSIENT_TYPE(window) &&
366
window->transient_for == NULL)
368
/* We only do the group thing if the dialog is NOT transient for
369
* a particular window. Imagine a group with a normal window, a dock,
370
* and a dialog transient for the normal window; you don't want the dialog
371
* above the dock if it wouldn't normally be.
374
MetaStackLayer group_max;
376
group_max = get_maximum_layer_in_group (window);
378
if (group_max > window->layer)
380
meta_topic (META_DEBUG_STACK,
381
"Promoting window %s from layer %u to %u due to group membership\n",
382
window->desc, window->layer, group_max);
383
window->layer = group_max;
387
meta_topic (META_DEBUG_STACK, "Window %s on layer %u type = %u has_focus = %d\n",
388
window->desc, window->layer,
389
window->type, window->has_focus);
392
/* Front of the layer list is the topmost window,
393
* so the lower stack position is later in the list
396
compare_window_position (void *a,
399
MetaWindow *window_a = a;
400
MetaWindow *window_b = b;
402
/* Go by layer, then stack_position */
403
if (window_a->layer < window_b->layer)
404
return 1; /* move window_a later in list */
405
else if (window_a->layer > window_b->layer)
407
else if (window_a->stack_position < window_b->stack_position)
408
return 1; /* move window_a later in list */
409
else if (window_a->stack_position > window_b->stack_position)
412
return 0; /* not reached */
416
* Stacking constraints
418
* Assume constraints of the form "AB" meaning "window A must be
421
* If we have windows stacked from bottom to top
422
* "ABC" then raise A we get "BCA". Say C is
423
* transient for B is transient for A. So
424
* we have constraints AB and BC.
426
* After raising A, we need to reapply the constraints.
427
* If we do this by raising one window at a time -
433
* but apply constraints in the wrong order and it breaks:
439
* We make a directed graph of the constraints by linking
440
* from "above windows" to "below windows as follows:
446
* If we then walk that graph and apply the constraints in the order
447
* that they appear, we will apply them correctly. Note that the
448
* graph MAY have cycles, so we have to guard against that.
452
typedef struct Constraint Constraint;
459
/* used to keep the constraint in the
460
* list of constraints for window "below"
464
/* used to create the graph. */
467
/* constraint has been applied, used
470
unsigned int applied : 1;
472
/* constraint has a previous node in the graph,
473
* used to find places to start in the graph.
474
* (I think this also has the side effect
475
* of preventing cycles, since cycles will
476
* have no starting point - so maybe
477
* the "applied" flag isn't needed.)
479
unsigned int has_prev : 1;
482
/* We index the array of constraints by window
483
* stack positions, just because the stack
484
* positions are a convenient index.
487
add_constraint (Constraint **constraints,
493
g_assert (above->screen == below->screen);
495
/* check if constraint is a duplicate */
496
c = constraints[below->stack_position];
499
if (c->above == above)
504
/* if not, add the constraint */
505
c = g_new (Constraint, 1);
508
c->next = constraints[below->stack_position];
509
c->next_nodes = NULL;
513
constraints[below->stack_position] = c;
517
create_constraints (Constraint **constraints,
525
MetaWindow *w = tmp->data;
527
if (!meta_window_is_in_stack (w))
529
meta_topic (META_DEBUG_STACK, "Window %s not in the stack, not constraining it\n",
535
if (WINDOW_TRANSIENT_FOR_WHOLE_GROUP (w))
537
GSList *group_windows;
541
group = meta_window_get_group (w);
544
group_windows = meta_group_list_windows (group);
546
group_windows = NULL;
548
tmp2 = group_windows;
552
MetaWindow *group_window = tmp2->data;
554
if (!meta_window_is_in_stack (group_window) ||
555
w->screen != group_window->screen ||
556
group_window->override_redirect)
563
/* old way of doing it */
564
if (!(meta_window_is_ancestor_of_transient (w, group_window)) &&
565
!WINDOW_TRANSIENT_FOR_WHOLE_GROUP (group_window)) /* note */;/*note*/
567
/* better way I think, so transient-for-group are constrained
568
* only above non-transient-type windows in their group
570
if (!WINDOW_HAS_TRANSIENT_TYPE (group_window))
573
meta_topic (META_DEBUG_STACK, "Constraining %s above %s as it's transient for its group\n",
574
w->desc, group_window->desc);
575
add_constraint (constraints, w, group_window);
581
g_slist_free (group_windows);
583
else if (w->transient_for != NULL)
587
parent = w->transient_for;
589
if (parent && meta_window_is_in_stack (parent))
591
meta_topic (META_DEBUG_STACK, "Constraining %s above %s due to transiency\n",
592
w->desc, parent->desc);
593
add_constraint (constraints, w, parent);
602
graph_constraints (Constraint **constraints,
608
while (i < n_constraints)
612
/* If we have "A below B" and "B below C" then AB -> BC so we
613
* add BC to next_nodes in AB.
621
g_assert (c->below->stack_position == i);
623
/* Constraints where ->above is below are our
624
* next_nodes and we are their previous
626
n = constraints[c->above->stack_position];
629
c->next_nodes = g_slist_prepend (c->next_nodes,
631
/* c is a previous node of n */
645
free_constraints (Constraint **constraints,
651
while (i < n_constraints)
658
Constraint *next = c->next;
660
g_slist_free (c->next_nodes);
672
ensure_above (MetaWindow *above,
675
if (WINDOW_HAS_TRANSIENT_TYPE(above) &&
676
above->layer < below->layer)
678
meta_topic (META_DEBUG_STACK,
679
"Promoting window %s from layer %u to %u due to contraint\n",
680
above->desc, above->layer, below->layer);
681
above->layer = below->layer;
684
if (above->stack_position < below->stack_position)
686
/* move above to below->stack_position bumping below down the stack */
687
meta_window_set_stack_position_no_sync (above, below->stack_position);
688
g_assert (below->stack_position + 1 == above->stack_position);
690
meta_topic (META_DEBUG_STACK, "%s above at %d > %s below at %d\n",
691
above->desc, above->stack_position,
692
below->desc, below->stack_position);
696
traverse_constraint (Constraint *c)
703
ensure_above (c->above, c->below);
709
traverse_constraint (tmp->data);
716
apply_constraints (Constraint **constraints,
723
/* List all heads in an ordered constraint chain */
726
while (i < n_constraints)
734
heads = g_slist_prepend (heads, c);
742
/* Now traverse the chain and apply constraints */
746
Constraint *c = tmp->data;
748
traverse_constraint (c);
753
g_slist_free (heads);
757
* stack_do_window_deletions:
759
* Go through "deleted" and take the matching windows
763
stack_do_window_deletions (MetaStack *stack)
765
/* Do removals before adds, with paranoid idea that we might re-add
766
* the same window IDs.
771
tmp = stack->removed;
775
xwindow = GPOINTER_TO_UINT (tmp->data);
777
/* We go from the end figuring removals are more
778
* likely to be recent.
780
i = stack->xwindows->len;
785
/* there's no guarantee we'll actually find windows to
786
* remove, e.g. the same xwindow could have been
787
* added/removed before we ever synced, and we put
788
* both the window->xwindow and window->frame->xwindow
789
* in the removal list.
791
if (xwindow == g_array_index (stack->xwindows, Window, i))
793
g_array_remove_index (stack->xwindows, i);
802
g_list_free (stack->removed);
803
stack->removed = NULL;
807
stack_do_window_additions (MetaStack *stack)
812
n_added = g_list_length (stack->added);
815
meta_topic (META_DEBUG_STACK,
816
"Adding %d windows to sorted list\n",
819
/* stack->added has the most recent additions at the
820
* front of the list, so we need to reverse it
822
stack->added = g_list_reverse (stack->added);
831
if (w->client_type == META_WINDOW_CLIENT_TYPE_X11)
832
g_array_append_val (stack->xwindows, w->xwindow);
834
/* add to the main list */
835
stack->sorted = g_list_prepend (stack->sorted, w);
840
stack->need_resort = TRUE; /* may not be needed as we add to top */
841
stack->need_constrain = TRUE;
842
stack->need_relayer = TRUE;
845
g_list_free (stack->added);
852
* Update the layers that windows are in
855
stack_do_relayer (MetaStack *stack)
859
if (!stack->need_relayer)
862
meta_topic (META_DEBUG_STACK,
863
"Recomputing layers\n");
870
MetaStackLayer old_layer;
873
old_layer = w->layer;
877
if (w->layer != old_layer)
879
meta_topic (META_DEBUG_STACK,
880
"Window %s moved from layer %u to %u\n",
881
w->desc, old_layer, w->layer);
882
stack->need_resort = TRUE;
883
stack->need_constrain = TRUE;
884
/* don't need to constrain as constraining
885
* purely operates in terms of stack_position
893
stack->need_relayer = FALSE;
897
* stack_do_constrain:
899
* Update stack_position and layer to reflect transiency
903
stack_do_constrain (MetaStack *stack)
905
Constraint **constraints;
907
/* It'd be nice if this were all faster, probably */
909
if (!stack->need_constrain)
912
meta_topic (META_DEBUG_STACK,
913
"Reapplying constraints\n");
915
constraints = g_new0 (Constraint*,
918
create_constraints (constraints, stack->sorted);
920
graph_constraints (constraints, stack->n_positions);
922
apply_constraints (constraints, stack->n_positions);
924
free_constraints (constraints, stack->n_positions);
925
g_free (constraints);
927
stack->need_constrain = FALSE;
933
* Sort stack->sorted with layers having priority over stack_position.
936
stack_do_resort (MetaStack *stack)
938
if (!stack->need_resort)
941
meta_topic (META_DEBUG_STACK,
942
"Sorting stack list\n");
944
stack->sorted = g_list_sort (stack->sorted,
945
(GCompareFunc) compare_window_position);
947
meta_screen_queue_check_fullscreen (stack->screen);
949
stack->need_resort = FALSE;
953
* stack_ensure_sorted:
955
* Puts the stack into canonical form.
957
* Honour the removed and added lists of the stack, and then recalculate
958
* all the layers (if the flag is set), re-run all the constraint calculations
959
* (if the flag is set), and finally re-sort the stack (if the flag is set,
960
* and if it wasn't already it might have become so during all the previous
964
stack_ensure_sorted (MetaStack *stack)
966
stack_do_window_deletions (stack);
967
stack_do_window_additions (stack);
968
stack_do_relayer (stack);
969
stack_do_constrain (stack);
970
stack_do_resort (stack);
974
* stack_sync_to_server:
976
* Order the windows on the X server to be the same as in our structure.
977
* We do this using XRestackWindows if we don't know the previous order,
978
* or XConfigureWindow on a few particular windows if we do and can figure
979
* out the minimum set of changes. After that, we set __NET_CLIENT_LIST
980
* and __NET_CLIENT_LIST_STACKING.
982
* FIXME: Now that we have a good view of the stacking order on the server
983
* with MetaStackTracker it should be possible to do a simpler and better
984
* job of computing the minimal set of stacking requests needed.
987
stack_sync_to_xserver (MetaStack *stack)
990
GArray *all_root_children_stacked; /* wayland OR x11 */
992
GArray *hidden_stack_ids;
994
/* Bail out if frozen */
995
if (stack->freeze_count > 0)
998
meta_topic (META_DEBUG_STACK, "Syncing window stack to server\n");
1000
stack_ensure_sorted (stack);
1002
/* Create stacked xwindow arrays, in bottom-to-top order
1004
x11_stacked = g_array_new (FALSE, FALSE, sizeof (Window));
1006
all_root_children_stacked = g_array_new (FALSE, FALSE, sizeof (guint64));
1007
hidden_stack_ids = g_array_new (FALSE, FALSE, sizeof (guint64));
1009
meta_topic (META_DEBUG_STACK, "Bottom to top: ");
1010
meta_push_no_msg_prefix ();
1012
for (tmp = g_list_last(stack->sorted); tmp != NULL; tmp = tmp->prev)
1014
MetaWindow *w = tmp->data;
1015
guint64 top_level_window;
1021
meta_topic (META_DEBUG_STACK, "%u:%d - %s ",
1022
w->layer, w->stack_position, w->desc);
1024
if (w->client_type == META_WINDOW_CLIENT_TYPE_X11)
1025
g_array_append_val (x11_stacked, w->xwindow);
1028
top_level_window = w->frame->xwindow;
1030
top_level_window = w->xwindow;
1032
if (w->client_type == META_WINDOW_CLIENT_TYPE_X11)
1033
stack_id = top_level_window;
1035
stack_id = w->stamp;
1037
/* We don't restack hidden windows along with the rest, though they are
1038
* reflected in the _NET hints. Hidden windows all get pushed below
1039
* the screens fullscreen guard_window. */
1042
g_array_append_val (hidden_stack_ids, stack_id);
1046
g_array_append_val (all_root_children_stacked, stack_id);
1049
meta_topic (META_DEBUG_STACK, "\n");
1050
meta_pop_no_msg_prefix ();
1052
/* The screen guard window sits above all hidden windows and acts as
1053
* a barrier to input reaching these windows. */
1054
guint64 guard_window_id = stack->screen->guard_window;
1055
g_array_append_val (hidden_stack_ids, guard_window_id);
1057
/* Sync to server */
1059
meta_topic (META_DEBUG_STACK, "Restacking %u windows\n",
1060
all_root_children_stacked->len);
1062
meta_stack_tracker_restack_managed (stack->screen->stack_tracker,
1063
(guint64 *)all_root_children_stacked->data,
1064
all_root_children_stacked->len);
1065
meta_stack_tracker_restack_at_bottom (stack->screen->stack_tracker,
1066
(guint64 *)hidden_stack_ids->data,
1067
hidden_stack_ids->len);
1069
/* Sync _NET_CLIENT_LIST and _NET_CLIENT_LIST_STACKING */
1071
XChangeProperty (stack->screen->display->xdisplay,
1072
stack->screen->xroot,
1073
stack->screen->display->atom__NET_CLIENT_LIST,
1075
32, PropModeReplace,
1076
(unsigned char *)stack->xwindows->data,
1077
stack->xwindows->len);
1078
XChangeProperty (stack->screen->display->xdisplay,
1079
stack->screen->xroot,
1080
stack->screen->display->atom__NET_CLIENT_LIST_STACKING,
1082
32, PropModeReplace,
1083
(unsigned char *)x11_stacked->data,
1086
g_array_free (x11_stacked, TRUE);
1087
g_array_free (hidden_stack_ids, TRUE);
1088
g_array_free (all_root_children_stacked, TRUE);
1092
meta_stack_get_top (MetaStack *stack)
1094
stack_ensure_sorted (stack);
1097
return stack->sorted->data;
1103
meta_stack_get_bottom (MetaStack *stack)
1107
stack_ensure_sorted (stack);
1109
link = g_list_last (stack->sorted);
1117
meta_stack_get_above (MetaStack *stack,
1119
gboolean only_within_layer)
1124
stack_ensure_sorted (stack);
1126
link = g_list_find (stack->sorted, window);
1129
if (link->prev == NULL)
1132
above = link->prev->data;
1134
if (only_within_layer &&
1135
above->layer != window->layer)
1142
meta_stack_get_below (MetaStack *stack,
1144
gboolean only_within_layer)
1149
stack_ensure_sorted (stack);
1151
link = g_list_find (stack->sorted, window);
1155
if (link->next == NULL)
1158
below = link->next->data;
1160
if (only_within_layer &&
1161
below->layer != window->layer)
1168
window_contains_point (MetaWindow *window,
1174
meta_window_get_frame_rect (window, &rect);
1176
return POINT_IN_RECT (root_x, root_y, rect);
1180
get_default_focus_window (MetaStack *stack,
1181
MetaWorkspace *workspace,
1182
MetaWindow *not_this_one,
1183
gboolean must_be_at_point,
1187
/* Find the topmost, focusable, mapped, window.
1188
* not_this_one is being unfocused or going away, so exclude it.
1193
stack_ensure_sorted (stack);
1195
/* top of this layer is at the front of the list */
1196
for (l = stack->sorted; l != NULL; l = l->next)
1198
MetaWindow *window = l->data;
1203
if (window == not_this_one)
1206
if (window->unmaps_pending > 0)
1209
if (window->unmanaging)
1212
if (!(window->input || window->take_focus))
1215
if (!meta_window_should_be_showing (window))
1218
if (must_be_at_point && !window_contains_point (window, root_x, root_y))
1221
if (window->type == META_WINDOW_DOCK)
1231
meta_stack_get_default_focus_window_at_point (MetaStack *stack,
1232
MetaWorkspace *workspace,
1233
MetaWindow *not_this_one,
1237
return get_default_focus_window (stack, workspace, not_this_one,
1238
TRUE, root_x, root_y);
1242
meta_stack_get_default_focus_window (MetaStack *stack,
1243
MetaWorkspace *workspace,
1244
MetaWindow *not_this_one)
1246
return get_default_focus_window (stack, workspace, not_this_one,
1251
meta_stack_list_windows (MetaStack *stack,
1252
MetaWorkspace *workspace)
1254
GList *workspace_windows = NULL;
1257
stack_ensure_sorted (stack); /* do adds/removes */
1259
link = stack->sorted;
1263
MetaWindow *window = link->data;
1266
(workspace == NULL || meta_window_located_on_workspace (window, workspace)))
1268
workspace_windows = g_list_prepend (workspace_windows,
1275
return workspace_windows;
1279
meta_stack_windows_cmp (MetaStack *stack,
1280
MetaWindow *window_a,
1281
MetaWindow *window_b)
1283
g_return_val_if_fail (window_a->screen == window_b->screen, 0);
1285
/* -1 means a below b */
1287
stack_ensure_sorted (stack); /* update constraints, layers */
1289
if (window_a->layer < window_b->layer)
1291
else if (window_a->layer > window_b->layer)
1293
else if (window_a->stack_position < window_b->stack_position)
1295
else if (window_a->stack_position > window_b->stack_position)
1298
return 0; /* not reached */
1302
compare_just_window_stack_position (void *a,
1305
MetaWindow *window_a = a;
1306
MetaWindow *window_b = b;
1308
if (window_a->stack_position < window_b->stack_position)
1309
return -1; /* move window_a earlier in list */
1310
else if (window_a->stack_position > window_b->stack_position)
1313
return 0; /* not reached */
1317
meta_stack_get_positions (MetaStack *stack)
1321
/* Make sure to handle any adds or removes */
1322
stack_ensure_sorted (stack);
1324
tmp = g_list_copy (stack->sorted);
1325
tmp = g_list_sort (tmp, (GCompareFunc) compare_just_window_stack_position);
1331
compare_pointers (gconstpointer a,
1343
lists_contain_same_windows (GList *a,
1346
GList *copy1, *copy2;
1349
if (g_list_length (a) != g_list_length (b))
1352
tmp1 = copy1 = g_list_sort (g_list_copy (a), compare_pointers);
1353
tmp2 = copy2 = g_list_sort (g_list_copy (b), compare_pointers);
1355
while (tmp1 && tmp1->data == tmp2->data) /* tmp2 is non-NULL if tmp1 is */
1361
g_list_free (copy1);
1362
g_list_free (copy2);
1364
return (tmp1 == NULL); /* tmp2 is non-NULL if tmp1 is */
1368
meta_stack_set_positions (MetaStack *stack,
1374
/* Make sure any adds or removes aren't in limbo -- is this needed? */
1375
stack_ensure_sorted (stack);
1377
if (!lists_contain_same_windows (windows, stack->sorted))
1379
meta_warning ("This list of windows has somehow changed; not resetting "
1380
"positions of the windows.\n");
1384
g_list_free (stack->sorted);
1385
stack->sorted = g_list_copy (windows);
1387
stack->need_resort = TRUE;
1388
stack->need_constrain = TRUE;
1394
MetaWindow *w = tmp->data;
1395
w->stack_position = i++;
1399
meta_topic (META_DEBUG_STACK,
1400
"Reset the stack positions of (nearly) all windows\n");
1402
stack_sync_to_xserver (stack);
1403
meta_stack_update_window_tile_matches (stack, NULL);
1407
meta_window_set_stack_position_no_sync (MetaWindow *window,
1410
int low, high, delta;
1413
g_return_if_fail (window->screen->stack != NULL);
1414
g_return_if_fail (window->stack_position >= 0);
1415
g_return_if_fail (position >= 0);
1416
g_return_if_fail (position < window->screen->stack->n_positions);
1418
if (position == window->stack_position)
1420
meta_topic (META_DEBUG_STACK, "Window %s already has position %d\n",
1421
window->desc, position);
1425
window->screen->stack->need_resort = TRUE;
1426
window->screen->stack->need_constrain = TRUE;
1428
if (position < window->stack_position)
1431
high = window->stack_position - 1;
1436
low = window->stack_position + 1;
1441
tmp = window->screen->stack->sorted;
1444
MetaWindow *w = tmp->data;
1446
if (w->stack_position >= low &&
1447
w->stack_position <= high)
1448
w->stack_position += delta;
1453
window->stack_position = position;
1455
meta_topic (META_DEBUG_STACK,
1456
"Window %s had stack_position set to %d\n",
1457
window->desc, window->stack_position);
1461
meta_window_set_stack_position (MetaWindow *window,
1464
meta_window_set_stack_position_no_sync (window, position);
1465
stack_sync_to_xserver (window->screen->stack);
1466
meta_stack_update_window_tile_matches (window->screen->stack,
1467
window->screen->active_workspace);