1 /* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
2
3 stacking.c for the Openbox window manager
4 Copyright (c) 2006 Mikael Magnusson
5 Copyright (c) 2003-2007 Dana Jansens
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 See the COPYING file for a copy of the GNU General Public License.
18 */
19
20 #include "openbox.h"
21 #include "screen.h"
22 #include "focus.h"
23 #include "client.h"
24 #include "group.h"
25 #include "frame.h"
26 #include "window.h"
27 #include "event.h"
28 #include "debug.h"
29 #include "dock.h"
30 #include "config.h"
31 #include "obt/prop.h"
32
33 GList *stacking_list = NULL;
34 GList *stacking_list_tail = NULL;
35 /*! When true, stacking changes will not be reflected on the screen. This is
36 to freeze the on-screen stacking order while a window is being temporarily
37 raised during focus cycling */
38 static gboolean pause_changes = FALSE;
39
stacking_set_list(void)40 void stacking_set_list(void)
41 {
42 Window *windows = NULL;
43 GList *it;
44 guint i = 0;
45
46 /* on shutdown, don't update the properties, so that we can read it back
47 in on startup and re-stack the windows as they were before we shut down
48 */
49 if (ob_state() == OB_STATE_EXITING) return;
50
51 /* create an array of the window ids (from bottom to top,
52 reverse order!) */
53 if (stacking_list) {
54 windows = g_new(Window, g_list_length(stacking_list));
55 for (it = g_list_last(stacking_list); it; it = g_list_previous(it)) {
56 if (WINDOW_IS_CLIENT(it->data))
57 windows[i++] = WINDOW_AS_CLIENT(it->data)->window;
58 }
59 }
60
61 OBT_PROP_SETA32(obt_root(ob_screen), NET_CLIENT_LIST_STACKING, WINDOW,
62 (gulong*)windows, i);
63
64 g_free(windows);
65 }
66
do_restack(GList * wins,GList * before)67 static void do_restack(GList *wins, GList *before)
68 {
69 GList *it;
70 Window *win;
71 gint i;
72
73 #ifdef DEBUG
74 GList *next;
75
76 g_assert(wins);
77 /* pls only restack stuff in the same layer at a time */
78 for (it = wins; it; it = next) {
79 next = g_list_next(it);
80 if (!next) break;
81 g_assert (window_layer(it->data) == window_layer(next->data));
82 }
83 if (before)
84 g_assert(window_layer(it->data) >= window_layer(before->data));
85 #endif
86
87 win = g_new(Window, g_list_length(wins) + 1);
88
89 if (before == stacking_list)
90 win[0] = screen_support_win;
91 else if (!before)
92 win[0] = window_top(g_list_last(stacking_list)->data);
93 else
94 win[0] = window_top(g_list_previous(before)->data);
95
96 for (i = 1, it = wins; it; ++i, it = g_list_next(it)) {
97 win[i] = window_top(it->data);
98 g_assert(win[i] != None); /* better not call stacking shit before
99 setting your top level window value */
100 stacking_list = g_list_insert_before(stacking_list, before, it->data);
101 }
102
103 #ifdef DEBUG
104 /* some debug checking of the stacking list's order */
105 for (it = stacking_list; ; it = next) {
106 next = g_list_next(it);
107 if (!next) break;
108 g_assert(window_layer(it->data) >= window_layer(next->data));
109 }
110 #endif
111
112 if (!pause_changes)
113 XRestackWindows(obt_display, win, i);
114 g_free(win);
115
116 stacking_set_list();
117 }
118
stacking_temp_raise(ObWindow * window)119 void stacking_temp_raise(ObWindow *window)
120 {
121 Window win[2];
122 GList *it;
123 gulong start;
124
125 /* don't use this for internal windows..! it would lower them.. */
126 g_assert(window_layer(window) < OB_STACKING_LAYER_INTERNAL);
127
128 /* find the window to drop it underneath */
129 win[0] = screen_support_win;
130 for (it = stacking_list; it; it = g_list_next(it)) {
131 ObWindow *w = it->data;
132 if (window_layer(w) >= OB_STACKING_LAYER_INTERNAL)
133 win[0] = window_top(w);
134 else
135 break;
136 }
137
138 win[1] = window_top(window);
139 start = event_start_ignore_all_enters();
140 XRestackWindows(obt_display, win, 2);
141 event_end_ignore_all_enters(start);
142
143 pause_changes = TRUE;
144 }
145
stacking_restore(void)146 void stacking_restore(void)
147 {
148 Window *win;
149 GList *it;
150 gint i;
151 gulong start;
152
153 win = g_new(Window, g_list_length(stacking_list) + 1);
154 win[0] = screen_support_win;
155 for (i = 1, it = stacking_list; it; ++i, it = g_list_next(it))
156 win[i] = window_top(it->data);
157 start = event_start_ignore_all_enters();
158 XRestackWindows(obt_display, win, i);
159 event_end_ignore_all_enters(start);
160 g_free(win);
161
162 pause_changes = FALSE;
163 }
164
do_raise(GList * wins)165 static void do_raise(GList *wins)
166 {
167 GList *it;
168 GList *layer[OB_NUM_STACKING_LAYERS] = {NULL};
169 gint i;
170
171 for (it = wins; it; it = g_list_next(it)) {
172 ObStackingLayer l;
173
174 l = window_layer(it->data);
175 layer[l] = g_list_append(layer[l], it->data);
176 }
177
178 it = stacking_list;
179 for (i = OB_NUM_STACKING_LAYERS - 1; i >= 0; --i) {
180 if (layer[i]) {
181 for (; it; it = g_list_next(it)) {
182 /* look for the top of the layer */
183 if (window_layer(it->data) <= (ObStackingLayer) i)
184 break;
185 }
186 do_restack(layer[i], it);
187 g_list_free(layer[i]);
188 }
189 }
190 }
191
do_lower(GList * wins)192 static void do_lower(GList *wins)
193 {
194 GList *it;
195 GList *layer[OB_NUM_STACKING_LAYERS] = {NULL};
196 gint i;
197
198 for (it = wins; it; it = g_list_next(it)) {
199 ObStackingLayer l;
200
201 l = window_layer(it->data);
202 layer[l] = g_list_append(layer[l], it->data);
203 }
204
205 it = stacking_list;
206 for (i = OB_NUM_STACKING_LAYERS - 1; i >= 0; --i) {
207 if (layer[i]) {
208 for (; it; it = g_list_next(it)) {
209 /* look for the top of the next layer down */
210 if (window_layer(it->data) < (ObStackingLayer) i)
211 break;
212 }
213 do_restack(layer[i], it);
214 g_list_free(layer[i]);
215 }
216 }
217 }
218
restack_windows(ObClient * selected,gboolean raise)219 static void restack_windows(ObClient *selected, gboolean raise)
220 {
221 GList *it, *last, *below, *above, *next;
222 GList *wins = NULL;
223
224 GList *group_helpers = NULL;
225 GList *group_modals = NULL;
226 GList *group_trans = NULL;
227 GList *modals = NULL;
228 GList *trans = NULL;
229
230 if (raise) {
231 ObClient *p;
232
233 /* if a window is modal for another single window, then raise it to the
234 top too, the same is done with the focus order */
235 while (selected->modal && (p = client_direct_parent(selected)))
236 selected = p;
237 }
238
239 /* remove first so we can't run into ourself */
240 it = g_list_find(stacking_list, selected);
241 g_assert(it);
242 stacking_list = g_list_delete_link(stacking_list, it);
243
244 /* go from the bottom of the stacking list up. don't move any other windows
245 when lowering, we call this for each window independently */
246 if (raise) {
247 for (it = g_list_last(stacking_list); it; it = next) {
248 next = g_list_previous(it);
249
250 if (WINDOW_IS_CLIENT(it->data)) {
251 ObClient *ch = it->data;
252
253 /* only move windows in the same stacking layer */
254 if (ch->layer == selected->layer &&
255 /* looking for windows that are transients, and so would
256 remain above the selected window */
257 client_search_transient(selected, ch))
258 {
259 if (client_is_direct_child(selected, ch)) {
260 if (ch->modal)
261 modals = g_list_prepend(modals, ch);
262 else
263 trans = g_list_prepend(trans, ch);
264 }
265 else if (client_helper(ch)) {
266 if (selected->transient) {
267 /* helpers do not stay above transient windows */
268 continue;
269 }
270 group_helpers = g_list_prepend(group_helpers, ch);
271 }
272 else {
273 if (ch->modal)
274 group_modals = g_list_prepend(group_modals, ch);
275 else
276 group_trans = g_list_prepend(group_trans, ch);
277 }
278 stacking_list = g_list_delete_link(stacking_list, it);
279 }
280 }
281 }
282 }
283
284 /* put modals above other direct transients */
285 wins = g_list_concat(modals, trans);
286
287 /* put helpers below direct transients */
288 wins = g_list_concat(wins, group_helpers);
289
290 /* put the selected window right below these children */
291 wins = g_list_append(wins, selected);
292
293 /* if selected window is transient for group then raise it above others */
294 if (selected->transient_for_group) {
295 /* if it's modal, raise it above those also */
296 if (selected->modal) {
297 wins = g_list_concat(wins, group_modals);
298 group_modals = NULL;
299 }
300 wins = g_list_concat(wins, group_trans);
301 group_trans = NULL;
302 }
303
304 /* find where to put the selected window, start from bottom of list,
305 this is the window below everything we are re-adding to the list */
306 last = NULL;
307 for (it = g_list_last(stacking_list); it; it = g_list_previous(it))
308 {
309 if (window_layer(it->data) < selected->layer) {
310 last = it;
311 continue;
312 }
313 /* if lowering, stop at the beginning of the layer */
314 if (!raise)
315 break;
316 /* if raising, stop at the end of the layer */
317 if (window_layer(it->data) > selected->layer)
318 break;
319
320 last = it;
321 }
322
323 /* save this position in the stacking list */
324 below = last;
325
326 /* find where to put the group transients, start from the top of list */
327 for (it = stacking_list; it; it = g_list_next(it)) {
328 /* skip past higher layers */
329 if (window_layer(it->data) > selected->layer)
330 continue;
331 /* if we reach the end of the layer (how?) then don't go further */
332 if (window_layer(it->data) < selected->layer)
333 break;
334 /* stop when we reach the first window in the group */
335 if (WINDOW_IS_CLIENT(it->data)) {
336 ObClient *c = it->data;
337 if (c->group == selected->group)
338 break;
339 }
340 /* if we don't hit any other group members, stop here because this
341 is where we are putting the selected window (and its children) */
342 if (it == below)
343 break;
344 }
345
346 /* save this position, this is the top of the group of windows between the
347 group transient ones we're restacking and the others up above that we're
348 restacking
349
350 we actually want to save 1 position _above_ that, for for loops to work
351 nicely, so move back one position in the list while saving it
352 */
353 above = it ? g_list_previous(it) : g_list_last(stacking_list);
354
355 /* put the windows inside the gap to the other windows we're stacking
356 into the restacking list, go from the bottom up so that we can use
357 g_list_prepend */
358 if (below) it = g_list_previous(below);
359 else it = g_list_last(stacking_list);
360 for (; it != above; it = next) {
361 next = g_list_previous(it);
362 wins = g_list_prepend(wins, it->data);
363 stacking_list = g_list_delete_link(stacking_list, it);
364 }
365
366 /* group transients go above the rest of the stuff acquired to now */
367 wins = g_list_concat(group_trans, wins);
368 /* group modals go on the very top */
369 wins = g_list_concat(group_modals, wins);
370
371 do_restack(wins, below);
372 g_list_free(wins);
373
374 /* lower our parents after us, so they go below us */
375 if (!raise && selected->parents) {
376 GSList *parents_copy, *sit;
377 GSList *reorder = NULL;
378
379 parents_copy = g_slist_copy(selected->parents);
380
381 /* go thru stacking list backwards so we can use g_slist_prepend */
382 for (it = g_list_last(stacking_list); it && parents_copy;
383 it = g_list_previous(it))
384 if ((sit = g_slist_find(parents_copy, it->data))) {
385 reorder = g_slist_prepend(reorder, sit->data);
386 parents_copy = g_slist_delete_link(parents_copy, sit);
387 }
388 g_assert(parents_copy == NULL);
389
390 /* call restack for each of these to lower them */
391 for (sit = reorder; sit; sit = g_slist_next(sit))
392 restack_windows(sit->data, raise);
393 }
394 }
395
stacking_raise(ObWindow * window)396 void stacking_raise(ObWindow *window)
397 {
398 if (WINDOW_IS_CLIENT(window)) {
399 ObClient *selected;
400 selected = WINDOW_AS_CLIENT(window);
401 restack_windows(selected, TRUE);
402 } else {
403 GList *wins;
404 wins = g_list_append(NULL, window);
405 stacking_list = g_list_remove(stacking_list, window);
406 do_raise(wins);
407 g_list_free(wins);
408 }
409 stacking_list_tail = g_list_last(stacking_list);
410 }
411
stacking_lower(ObWindow * window)412 void stacking_lower(ObWindow *window)
413 {
414 if (WINDOW_IS_CLIENT(window)) {
415 ObClient *selected;
416 selected = WINDOW_AS_CLIENT(window);
417 restack_windows(selected, FALSE);
418 } else {
419 GList *wins;
420 wins = g_list_append(NULL, window);
421 stacking_list = g_list_remove(stacking_list, window);
422 do_lower(wins);
423 g_list_free(wins);
424 }
425 stacking_list_tail = g_list_last(stacking_list);
426 }
427
stacking_below(ObWindow * window,ObWindow * below)428 void stacking_below(ObWindow *window, ObWindow *below)
429 {
430 GList *wins, *before;
431
432 if (window_layer(window) != window_layer(below))
433 return;
434
435 wins = g_list_append(NULL, window);
436 stacking_list = g_list_remove(stacking_list, window);
437 before = g_list_next(g_list_find(stacking_list, below));
438 do_restack(wins, before);
439 g_list_free(wins);
440 stacking_list_tail = g_list_last(stacking_list);
441 }
442
stacking_add(ObWindow * win)443 void stacking_add(ObWindow *win)
444 {
445 g_assert(screen_support_win != None); /* make sure I dont break this in the
446 future */
447 /* don't add windows that are being unmanaged ! */
448 if (WINDOW_IS_CLIENT(win)) g_assert(WINDOW_AS_CLIENT(win)->managed);
449
450 stacking_list = g_list_append(stacking_list, win);
451
452 stacking_raise(win);
453 /* stacking_list_tail set by stacking_raise() */
454 }
455
find_highest_relative(ObClient * client)456 static GList *find_highest_relative(ObClient *client)
457 {
458 GList *ret = NULL;
459
460 if (client->parents) {
461 GList *it;
462 GSList *top;
463
464 /* get all top level relatives of this client */
465 top = client_search_all_top_parents_layer(client);
466
467 /* go from the top of the stacking order down */
468 for (it = stacking_list; !ret && it; it = g_list_next(it)) {
469 if (WINDOW_IS_CLIENT(it->data)) {
470 ObClient *c = it->data;
471 /* only look at windows in the same layer and that are
472 visible */
473 if (c->layer == client->layer &&
474 !c->iconic &&
475 (c->desktop == client->desktop ||
476 c->desktop == DESKTOP_ALL ||
477 client->desktop == DESKTOP_ALL))
478 {
479 GSList *sit;
480
481 /* go through each top level parent and see it this window
482 is related to them */
483 for (sit = top; !ret && sit; sit = g_slist_next(sit)) {
484 ObClient *topc = sit->data;
485
486 /* are they related ? */
487 if (topc == c || client_search_transient(topc, c))
488 ret = it;
489 }
490 }
491 }
492 }
493 }
494 return ret;
495 }
496
stacking_add_nonintrusive(ObWindow * win)497 void stacking_add_nonintrusive(ObWindow *win)
498 {
499 ObClient *client;
500 GList *it_below = NULL; /* this client will be below us */
501 GList *it_above;
502 GList *wins;
503
504 if (!WINDOW_IS_CLIENT(win)) {
505 stacking_add(win); /* no special rules for others */
506 return;
507 }
508
509 client = WINDOW_AS_CLIENT(win);
510
511 /* don't add windows that are being unmanaged ! */
512 g_assert(client->managed);
513
514 /* insert above its highest parent (or its highest child !) */
515 it_below = find_highest_relative(client);
516
517 if (!it_below) {
518 /* nothing to put it directly above, so try find the focused client
519 to put it underneath it */
520 if (focus_client && client != focus_client &&
521 focus_client->layer == client->layer)
522 {
523 it_below = g_list_find(stacking_list, focus_client);
524 /* this can give NULL, but it means the focused window is on the
525 bottom of the stacking order, so go to the bottom in that case,
526 below it */
527 it_below = g_list_next(it_below);
528 }
529 else {
530 /* There is no window to put this directly above, so put it at the
531 top, so you know it is there.
532
533 It used to do this only if the window was focused and lower
534 it otherwise.
535
536 We also put it at the top not the bottom to fix a bug with
537 fullscreen windows. When focusLast is off and followsMouse is
538 on, when you switch desktops, the fullscreen window loses
539 focus and goes into its lower layer. If this puts it at the
540 bottom then when you come back to the desktop, the window is
541 at the bottom and won't get focus back.
542 */
543 it_below = stacking_list;
544 }
545 }
546
547 /* make sure it's not in the wrong layer though ! */
548 for (; it_below; it_below = g_list_next(it_below)) {
549 /* stop when the window is not in a higher layer than the window
550 it is going above (it_below) */
551 if (client->layer >= window_layer(it_below->data))
552 break;
553 }
554 for (; it_below != stacking_list; it_below = it_above) {
555 /* stop when the window is not in a lower layer than the
556 window it is going under (it_above) */
557 it_above = it_below ?
558 g_list_previous(it_below) : g_list_last(stacking_list);
559 if (client->layer <= window_layer(it_above->data))
560 break;
561 }
562
563 wins = g_list_append(NULL, win);
564 do_restack(wins, it_below);
565 g_list_free(wins);
566 stacking_list_tail = g_list_last(stacking_list);
567 }
568
569 /*! Returns TRUE if client is occluded by the sibling. If sibling is NULL it
570 tries against all other clients.
571 */
stacking_occluded(ObClient * client,ObWindow * sibling_win)572 static gboolean stacking_occluded(ObClient *client, ObWindow *sibling_win)
573 {
574 GList *it;
575 gboolean occluded = FALSE;
576 ObClient *sibling = NULL;
577
578 if (sibling_win && WINDOW_IS_CLIENT(sibling_win))
579 sibling = WINDOW_AS_CLIENT(sibling_win);
580
581 /* no need for any looping in this case */
582 if (sibling && client->layer != sibling->layer)
583 return FALSE;
584
585 for (it = g_list_previous(g_list_find(stacking_list, client)); it;
586 it = g_list_previous(it))
587 if (WINDOW_IS_CLIENT(it->data)) {
588 ObClient *c = it->data;
589 if (!c->iconic &&
590 (c->desktop == DESKTOP_ALL || client->desktop == DESKTOP_ALL ||
591 c->desktop == client->desktop) &&
592 !client_search_transient(client, c))
593 {
594 if (RECT_INTERSECTS_RECT(c->frame->area, client->frame->area))
595 {
596 if (sibling != NULL) {
597 if (c == sibling) {
598 occluded = TRUE;
599 break;
600 }
601 }
602 else if (c->layer == client->layer) {
603 occluded = TRUE;
604 break;
605 }
606 else if (c->layer > client->layer)
607 break; /* we past its layer */
608 }
609 }
610 } else if (WINDOW_IS_DOCK(it->data)) {
611 ObDock *dock = it->data;
612 if (RECT_INTERSECTS_RECT(dock->area, client->frame->area))
613 {
614 if (sibling_win != NULL) {
615 if (DOCK_AS_WINDOW(dock) == sibling_win) {
616 occluded = TRUE;
617 break;
618 }
619 }
620 else if (config_dock_layer == client->layer) {
621 occluded = TRUE;
622 break;
623 }
624 }
625 }
626 return occluded;
627 }
628
629 /*! Returns TRUE if client occludes the sibling. If sibling is NULL it tries
630 against all other clients.
631 */
stacking_occludes(ObClient * client,ObWindow * sibling_win)632 static gboolean stacking_occludes(ObClient *client, ObWindow *sibling_win)
633 {
634 GList *it;
635 gboolean occludes = FALSE;
636 ObClient *sibling = NULL;
637
638 if (sibling_win && WINDOW_IS_CLIENT(sibling_win))
639 sibling = WINDOW_AS_CLIENT(sibling_win);
640
641 /* no need for any looping in this case */
642 if (sibling && client->layer != sibling->layer)
643 return FALSE;
644
645 for (it = g_list_next(g_list_find(stacking_list, client));
646 it; it = g_list_next(it))
647 if (WINDOW_IS_CLIENT(it->data)) {
648 ObClient *c = it->data;
649 if (!c->iconic &&
650 (c->desktop == DESKTOP_ALL || client->desktop == DESKTOP_ALL ||
651 c->desktop == client->desktop) &&
652 !client_search_transient(c, client))
653 {
654 if (RECT_INTERSECTS_RECT(c->frame->area, client->frame->area))
655 {
656 if (sibling != NULL) {
657 if (c == sibling) {
658 occludes = TRUE;
659 break;
660 }
661 }
662 else if (c->layer == client->layer) {
663 occludes = TRUE;
664 break;
665 }
666 else if (c->layer < client->layer)
667 break; /* we past its layer */
668 }
669 }
670 }
671 else if (WINDOW_IS_DOCK(it->data)) {
672 ObDock *dock = it->data;
673 if (RECT_INTERSECTS_RECT(dock->area, client->frame->area))
674 {
675 if (sibling_win != NULL) {
676 if (DOCK_AS_WINDOW(dock) == sibling_win) {
677 occludes = TRUE;
678 break;
679 }
680 }
681 else if (config_dock_layer == client->layer) {
682 occludes = TRUE;
683 break;
684 }
685 }
686 }
687 return occludes;
688 }
689
stacking_restack_request(ObClient * client,ObWindow * sibling_win,gint detail)690 gboolean stacking_restack_request(ObClient *client, ObWindow *sibling_win,
691 gint detail)
692 {
693 gboolean ret = FALSE;
694
695 ObClient *sibling = NULL;
696
697 if (sibling_win && WINDOW_IS_CLIENT(sibling_win))
698 sibling = WINDOW_AS_CLIENT(sibling_win);
699
700 if (sibling && ((client->desktop != sibling->desktop &&
701 client->desktop != DESKTOP_ALL &&
702 sibling->desktop != DESKTOP_ALL) ||
703 sibling->iconic))
704 {
705 ob_debug("Setting restack sibling to NULL, they are not on the same "
706 "desktop or it is iconified");
707 sibling = NULL;
708 }
709
710 switch (detail) {
711 case Below:
712 ob_debug("Restack request Below for client %s sibling %s",
713 client->title, sibling ? sibling->title : "(all)");
714 /* just lower it */
715 stacking_lower(CLIENT_AS_WINDOW(client));
716 ret = TRUE;
717 break;
718 case BottomIf:
719 ob_debug("Restack request BottomIf for client %s sibling %s",
720 client->title, sibling ? sibling->title : "(all)");
721 /* if this client occludes sibling (or anything if NULL), then
722 lower it to the bottom */
723 if (stacking_occludes(client, sibling_win)) {
724 stacking_lower(CLIENT_AS_WINDOW(client));
725 ret = TRUE;
726 }
727 break;
728 case Above:
729 ob_debug("Restack request Above for client %s sibling %s",
730 client->title, sibling ? sibling->title : "(all)");
731 stacking_raise(CLIENT_AS_WINDOW(client));
732 ret = TRUE;
733 break;
734 case TopIf:
735 ob_debug("Restack request TopIf for client %s sibling %s",
736 client->title, sibling ? sibling->title : "(all)");
737 if (stacking_occluded(client, sibling_win)) {
738 stacking_raise(CLIENT_AS_WINDOW(client));
739 ret = TRUE;
740 }
741 break;
742 case Opposite:
743 ob_debug("Restack request Opposite for client %s sibling %s",
744 client->title, sibling ? sibling->title : "(all)");
745 if (stacking_occluded(client, sibling_win)) {
746 stacking_raise(CLIENT_AS_WINDOW(client));
747 ret = TRUE;
748 }
749 else if (stacking_occludes(client, sibling_win)) {
750 stacking_lower(CLIENT_AS_WINDOW(client));
751 ret = TRUE;
752 }
753 break;
754 }
755 return ret;
756 }
757