]> Dogcows Code - chaz/openbox/blob - openbox/focus.c
5560c3d43c1af21b7d9eb4cbb762a97506f271d1
[chaz/openbox] / openbox / focus.c
1 /* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
2
3 focus.c for the Openbox window manager
4 Copyright (c) 2003 Ben Jansens
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 See the COPYING file for a copy of the GNU General Public License.
17 */
18
19 #include "debug.h"
20 #include "event.h"
21 #include "openbox.h"
22 #include "grab.h"
23 #include "framerender.h"
24 #include "client.h"
25 #include "config.h"
26 #include "frame.h"
27 #include "screen.h"
28 #include "group.h"
29 #include "prop.h"
30 #include "focus.h"
31 #include "stacking.h"
32 #include "popup.h"
33 #include "render/render.h"
34
35 #include <X11/Xlib.h>
36 #include <glib.h>
37 #include <assert.h>
38
39 ObClient *focus_client, *focus_hilite;
40 GList **focus_order; /* these lists are created when screen_startup
41 sets the number of desktops */
42 ObClient *focus_cycle_target;
43
44 struct {
45 InternalWindow top;
46 InternalWindow left;
47 InternalWindow right;
48 InternalWindow bottom;
49 } focus_indicator;
50
51 RrAppearance *a_focus_indicator;
52 RrColor *color_white;
53
54 static ObIconPopup *focus_cycle_popup;
55
56 static void focus_cycle_destructor(ObClient *client, gpointer data)
57 {
58 /* end cycling if the target disappears */
59 if (focus_cycle_target == client)
60 focus_cycle(TRUE, TRUE, TRUE, TRUE, TRUE);
61 }
62
63 static Window createWindow(Window parent, gulong mask,
64 XSetWindowAttributes *attrib)
65 {
66 return XCreateWindow(ob_display, parent, 0, 0, 1, 1, 0,
67 RrDepth(ob_rr_inst), InputOutput,
68 RrVisual(ob_rr_inst), mask, attrib);
69
70 }
71
72 void focus_startup(gboolean reconfig)
73 {
74 focus_cycle_popup = icon_popup_new(TRUE);
75
76 if (!reconfig) {
77 XSetWindowAttributes attr;
78
79 client_add_destructor(focus_cycle_destructor, NULL);
80
81 /* start with nothing focused */
82 focus_set_client(NULL);
83
84 focus_indicator.top.obwin.type = Window_Internal;
85 focus_indicator.left.obwin.type = Window_Internal;
86 focus_indicator.right.obwin.type = Window_Internal;
87 focus_indicator.bottom.obwin.type = Window_Internal;
88
89 attr.save_under = True;
90 attr.override_redirect = True;
91 attr.background_pixel = BlackPixel(ob_display, ob_screen);
92 focus_indicator.top.win =
93 createWindow(RootWindow(ob_display, ob_screen),
94 CWOverrideRedirect | CWBackPixel | CWSaveUnder,
95 &attr);
96 focus_indicator.left.win =
97 createWindow(RootWindow(ob_display, ob_screen),
98 CWOverrideRedirect | CWBackPixel | CWSaveUnder,
99 &attr);
100 focus_indicator.right.win =
101 createWindow(RootWindow(ob_display, ob_screen),
102 CWOverrideRedirect | CWBackPixel | CWSaveUnder,
103 &attr);
104 focus_indicator.bottom.win =
105 createWindow(RootWindow(ob_display, ob_screen),
106 CWOverrideRedirect | CWBackPixel | CWSaveUnder,
107 &attr);
108
109 stacking_add(INTERNAL_AS_WINDOW(&focus_indicator.top));
110 stacking_add(INTERNAL_AS_WINDOW(&focus_indicator.left));
111 stacking_add(INTERNAL_AS_WINDOW(&focus_indicator.right));
112 stacking_add(INTERNAL_AS_WINDOW(&focus_indicator.bottom));
113
114 color_white = RrColorNew(ob_rr_inst, 0xff, 0xff, 0xff);
115
116 a_focus_indicator = RrAppearanceNew(ob_rr_inst, 4);
117 a_focus_indicator->surface.grad = RR_SURFACE_SOLID;
118 a_focus_indicator->surface.relief = RR_RELIEF_FLAT;
119 a_focus_indicator->surface.primary = RrColorNew(ob_rr_inst,
120 0, 0, 0);
121 a_focus_indicator->texture[0].type = RR_TEXTURE_LINE_ART;
122 a_focus_indicator->texture[0].data.lineart.color = color_white;
123 a_focus_indicator->texture[1].type = RR_TEXTURE_LINE_ART;
124 a_focus_indicator->texture[1].data.lineart.color = color_white;
125 a_focus_indicator->texture[2].type = RR_TEXTURE_LINE_ART;
126 a_focus_indicator->texture[2].data.lineart.color = color_white;
127 a_focus_indicator->texture[3].type = RR_TEXTURE_LINE_ART;
128 a_focus_indicator->texture[3].data.lineart.color = color_white;
129 }
130 }
131
132 void focus_shutdown(gboolean reconfig)
133 {
134 guint i;
135
136 icon_popup_free(focus_cycle_popup);
137
138 if (!reconfig) {
139 client_remove_destructor(focus_cycle_destructor);
140
141 for (i = 0; i < screen_num_desktops; ++i)
142 g_list_free(focus_order[i]);
143 g_free(focus_order);
144
145 /* reset focus to root */
146 XSetInputFocus(ob_display, PointerRoot, RevertToNone, event_lasttime);
147
148 RrColorFree(color_white);
149
150 RrAppearanceFree(a_focus_indicator);
151
152 XDestroyWindow(ob_display, focus_indicator.top.win);
153 XDestroyWindow(ob_display, focus_indicator.left.win);
154 XDestroyWindow(ob_display, focus_indicator.right.win);
155 XDestroyWindow(ob_display, focus_indicator.bottom.win);
156 }
157 }
158
159 static void push_to_top(ObClient *client)
160 {
161 guint desktop;
162
163 desktop = client->desktop;
164 if (desktop == DESKTOP_ALL) desktop = screen_desktop;
165 focus_order[desktop] = g_list_remove(focus_order[desktop], client);
166 focus_order[desktop] = g_list_prepend(focus_order[desktop], client);
167 }
168
169 void focus_set_client(ObClient *client)
170 {
171 Window active;
172 ObClient *old;
173
174 #ifdef DEBUG_FOCUS
175 ob_debug("focus_set_client 0x%lx\n", client ? client->window : 0);
176 #endif
177
178 /* uninstall the old colormap, and install the new one */
179 screen_install_colormap(focus_client, FALSE);
180 screen_install_colormap(client, TRUE);
181
182 if (client == NULL) {
183 #ifdef DEBUG_FOCUS
184 ob_debug("actively focusing NONWINDOW\n");
185 #endif
186 /* when nothing will be focused, send focus to the backup target */
187 XSetInputFocus(ob_display, screen_support_win, RevertToNone,
188 event_lasttime);
189 XSync(ob_display, FALSE);
190 }
191
192 /* in the middle of cycling..? kill it. */
193 if (focus_cycle_target)
194 focus_cycle(TRUE, TRUE, TRUE, TRUE, TRUE);
195
196 old = focus_client;
197 focus_client = client;
198
199 /* move to the top of the list */
200 if (client != NULL)
201 push_to_top(client);
202
203 /* set the NET_ACTIVE_WINDOW hint, but preserve it on shutdown */
204 if (ob_state() != OB_STATE_EXITING) {
205 active = client ? client->window : None;
206 PROP_SET32(RootWindow(ob_display, ob_screen),
207 net_active_window, window, active);
208 }
209 }
210
211 /* finds the first transient that isn't 'skip' and ensure's that client_normal
212 is true for it */
213 static ObClient *find_transient_recursive(ObClient *c, ObClient *top,
214 ObClient *skip)
215 {
216 GSList *it;
217 ObClient *ret;
218
219 for (it = c->transients; it; it = it->next) {
220 if (it->data == top) return NULL;
221 ret = find_transient_recursive(it->data, top, skip);
222 if (ret && ret != skip && client_normal(ret)) return ret;
223 if (it->data != skip && client_normal(it->data)) return it->data;
224 }
225 return NULL;
226 }
227
228 static ObClient* focus_fallback_transient(ObClient *top, ObClient *old)
229 {
230 ObClient *target = find_transient_recursive(top, top, old);
231 if (!target) {
232 /* make sure client_normal is true always */
233 if (!client_normal(top))
234 return NULL;
235 target = top; /* no transient, keep the top */
236 }
237 if (client_can_focus(target))
238 return target;
239 else
240 return NULL;
241 }
242
243 ObClient* focus_fallback_target(ObFocusFallbackType type)
244 {
245 GList *it;
246 ObClient *old = NULL;
247 ObClient *target = NULL;
248
249 old = focus_client;
250
251 if (type == OB_FOCUS_FALLBACK_UNFOCUSING && old) {
252 if (old->transient_for) {
253 gboolean trans = FALSE;
254
255 if (!config_focus_follow)
256 trans = TRUE;
257 else {
258 if ((target = client_under_pointer()) &&
259 client_search_transient
260 (client_search_top_transient(target), old))
261 {
262 trans = TRUE;
263 }
264 }
265
266 /* try for transient relations */
267 if (trans) {
268 if (old->transient_for == OB_TRAN_GROUP) {
269 for (it = focus_order[screen_desktop]; it; it = it->next) {
270 GSList *sit;
271
272 for (sit = old->group->members; sit; sit = sit->next)
273 if (sit->data == it->data)
274 if ((target =
275 focus_fallback_transient(sit->data, old)))
276 return target;
277 }
278 } else {
279 if ((target =
280 focus_fallback_transient(old->transient_for, old)))
281 return target;
282 }
283 }
284 }
285 }
286
287 if (config_focus_follow) {
288 if ((target = client_under_pointer()))
289 if (client_normal(target) && client_can_focus(target))
290 return target;
291 }
292
293 #if 0
294 /* try for group relations */
295 if (old->group) {
296 GSList *sit;
297
298 for (it = focus_order[screen_desktop]; it != NULL; it = it->next)
299 for (sit = old->group->members; sit; sit = sit->next)
300 if (sit->data == it->data)
301 if (sit->data != old && client_normal(sit->data))
302 if (client_can_focus(sit->data))
303 return sit->data;
304 }
305 #endif
306
307 for (it = focus_order[screen_desktop]; it != NULL; it = it->next)
308 if (type != OB_FOCUS_FALLBACK_UNFOCUSING || it->data != old)
309 if (client_normal(it->data) && client_can_focus(it->data))
310 return it->data;
311
312 return NULL;
313 }
314
315 void focus_fallback(ObFocusFallbackType type)
316 {
317 ObClient *new;
318
319 /* unfocus any focused clients.. they can be focused by Pointer events
320 and such, and then when I try focus them, I won't get a FocusIn event
321 at all for them.
322 */
323 focus_set_client(NULL);
324
325 if ((new = focus_fallback_target(type)))
326 client_focus(new);
327 }
328
329 static void popup_cycle(ObClient *c, gboolean show)
330 {
331 if (!show) {
332 icon_popup_hide(focus_cycle_popup);
333 } else {
334 Rect *a;
335 ObClient *p = c;
336 gchar *title = NULL;
337
338 a = screen_physical_area_monitor(0);
339 icon_popup_position(focus_cycle_popup, CenterGravity,
340 a->x + a->width / 2, a->y + a->height / 2);
341 /* icon_popup_size(focus_cycle_popup, a->height/2, a->height/16);
342 icon_popup_show(focus_cycle_popup, c->title,
343 client_icon(c, a->height/16, a->height/16));
344 */
345 /* XXX the size and the font extents need to be related on some level
346 */
347 icon_popup_size(focus_cycle_popup, POPUP_WIDTH, POPUP_HEIGHT);
348
349 /* use the transient's parent's title/icon */
350 while (p->transient_for && p->transient_for != OB_TRAN_GROUP)
351 p = p->transient_for;
352
353 /*
354 if (p != c)
355 title = g_strconcat((c->iconic ? c->icon_title : c->title),
356 " - ",
357 (p->iconic ? p->icon_title : p->title),
358 NULL);
359 */
360
361 icon_popup_show(focus_cycle_popup,
362 (title ? title :
363 (c->iconic ? c->icon_title : c->title)),
364 client_icon(p, 48, 48));
365 g_free(title);
366 }
367 }
368
369 void focus_cycle_draw_indicator()
370 {
371 if (!focus_cycle_target) {
372 XUnmapWindow(ob_display, focus_indicator.top.win);
373 XUnmapWindow(ob_display, focus_indicator.left.win);
374 XUnmapWindow(ob_display, focus_indicator.right.win);
375 XUnmapWindow(ob_display, focus_indicator.bottom.win);
376 } else {
377 /*
378 if (focus_cycle_target)
379 frame_adjust_focus(focus_cycle_target->frame, FALSE);
380 frame_adjust_focus(focus_cycle_target->frame, TRUE);
381 */
382 gint x, y, w, h;
383 gint wt, wl, wr, wb;
384
385 wt = wl = wr = wb = MAX(3,
386 ob_rr_theme->handle_height +
387 ob_rr_theme->bwidth * 2);
388
389 x = focus_cycle_target->frame->area.x;
390 y = focus_cycle_target->frame->area.y;
391 w = focus_cycle_target->frame->area.width;
392 h = wt;
393
394 XMoveResizeWindow(ob_display, focus_indicator.top.win,
395 x, y, w, h);
396 a_focus_indicator->texture[0].data.lineart.x1 = 0;
397 a_focus_indicator->texture[0].data.lineart.y1 = h-1;
398 a_focus_indicator->texture[0].data.lineart.x2 = 0;
399 a_focus_indicator->texture[0].data.lineart.y2 = 0;
400 a_focus_indicator->texture[1].data.lineart.x1 = 0;
401 a_focus_indicator->texture[1].data.lineart.y1 = 0;
402 a_focus_indicator->texture[1].data.lineart.x2 = w-1;
403 a_focus_indicator->texture[1].data.lineart.y2 = 0;
404 a_focus_indicator->texture[2].data.lineart.x1 = w-1;
405 a_focus_indicator->texture[2].data.lineart.y1 = 0;
406 a_focus_indicator->texture[2].data.lineart.x2 = w-1;
407 a_focus_indicator->texture[2].data.lineart.y2 = h-1;
408 a_focus_indicator->texture[3].data.lineart.x1 = (wl-1);
409 a_focus_indicator->texture[3].data.lineart.y1 = h-1;
410 a_focus_indicator->texture[3].data.lineart.x2 = w - wr;
411 a_focus_indicator->texture[3].data.lineart.y2 = h-1;
412 RrPaint(a_focus_indicator, focus_indicator.top.win,
413 w, h);
414
415 x = focus_cycle_target->frame->area.x;
416 y = focus_cycle_target->frame->area.y;
417 w = wl;
418 h = focus_cycle_target->frame->area.height;
419
420 XMoveResizeWindow(ob_display, focus_indicator.left.win,
421 x, y, w, h);
422 a_focus_indicator->texture[0].data.lineart.x1 = w-1;
423 a_focus_indicator->texture[0].data.lineart.y1 = 0;
424 a_focus_indicator->texture[0].data.lineart.x2 = 0;
425 a_focus_indicator->texture[0].data.lineart.y2 = 0;
426 a_focus_indicator->texture[1].data.lineart.x1 = 0;
427 a_focus_indicator->texture[1].data.lineart.y1 = 0;
428 a_focus_indicator->texture[1].data.lineart.x2 = 0;
429 a_focus_indicator->texture[1].data.lineart.y2 = h-1;
430 a_focus_indicator->texture[2].data.lineart.x1 = 0;
431 a_focus_indicator->texture[2].data.lineart.y1 = h-1;
432 a_focus_indicator->texture[2].data.lineart.x2 = w-1;
433 a_focus_indicator->texture[2].data.lineart.y2 = h-1;
434 a_focus_indicator->texture[3].data.lineart.x1 = w-1;
435 a_focus_indicator->texture[3].data.lineart.y1 = wt-1;
436 a_focus_indicator->texture[3].data.lineart.x2 = w-1;
437 a_focus_indicator->texture[3].data.lineart.y2 = h - wb;
438 RrPaint(a_focus_indicator, focus_indicator.left.win,
439 w, h);
440
441 x = focus_cycle_target->frame->area.x +
442 focus_cycle_target->frame->area.width - wr;
443 y = focus_cycle_target->frame->area.y;
444 w = wr;
445 h = focus_cycle_target->frame->area.height ;
446
447 XMoveResizeWindow(ob_display, focus_indicator.right.win,
448 x, y, w, h);
449 a_focus_indicator->texture[0].data.lineart.x1 = 0;
450 a_focus_indicator->texture[0].data.lineart.y1 = 0;
451 a_focus_indicator->texture[0].data.lineart.x2 = w-1;
452 a_focus_indicator->texture[0].data.lineart.y2 = 0;
453 a_focus_indicator->texture[1].data.lineart.x1 = w-1;
454 a_focus_indicator->texture[1].data.lineart.y1 = 0;
455 a_focus_indicator->texture[1].data.lineart.x2 = w-1;
456 a_focus_indicator->texture[1].data.lineart.y2 = h-1;
457 a_focus_indicator->texture[2].data.lineart.x1 = w-1;
458 a_focus_indicator->texture[2].data.lineart.y1 = h-1;
459 a_focus_indicator->texture[2].data.lineart.x2 = 0;
460 a_focus_indicator->texture[2].data.lineart.y2 = h-1;
461 a_focus_indicator->texture[3].data.lineart.x1 = 0;
462 a_focus_indicator->texture[3].data.lineart.y1 = wt-1;
463 a_focus_indicator->texture[3].data.lineart.x2 = 0;
464 a_focus_indicator->texture[3].data.lineart.y2 = h - wb;
465 RrPaint(a_focus_indicator, focus_indicator.right.win,
466 w, h);
467
468 x = focus_cycle_target->frame->area.x;
469 y = focus_cycle_target->frame->area.y +
470 focus_cycle_target->frame->area.height - wb;
471 w = focus_cycle_target->frame->area.width;
472 h = wb;
473
474 XMoveResizeWindow(ob_display, focus_indicator.bottom.win,
475 x, y, w, h);
476 a_focus_indicator->texture[0].data.lineart.x1 = 0;
477 a_focus_indicator->texture[0].data.lineart.y1 = 0;
478 a_focus_indicator->texture[0].data.lineart.x2 = 0;
479 a_focus_indicator->texture[0].data.lineart.y2 = h-1;
480 a_focus_indicator->texture[1].data.lineart.x1 = 0;
481 a_focus_indicator->texture[1].data.lineart.y1 = h-1;
482 a_focus_indicator->texture[1].data.lineart.x2 = w-1;
483 a_focus_indicator->texture[1].data.lineart.y2 = h-1;
484 a_focus_indicator->texture[2].data.lineart.x1 = w-1;
485 a_focus_indicator->texture[2].data.lineart.y1 = h-1;
486 a_focus_indicator->texture[2].data.lineart.x2 = w-1;
487 a_focus_indicator->texture[2].data.lineart.y2 = 0;
488 a_focus_indicator->texture[3].data.lineart.x1 = wl-1;
489 a_focus_indicator->texture[3].data.lineart.y1 = 0;
490 a_focus_indicator->texture[3].data.lineart.x2 = w - wr;
491 a_focus_indicator->texture[3].data.lineart.y2 = 0;
492 RrPaint(a_focus_indicator, focus_indicator.bottom.win,
493 w, h);
494
495 XMapWindow(ob_display, focus_indicator.top.win);
496 XMapWindow(ob_display, focus_indicator.left.win);
497 XMapWindow(ob_display, focus_indicator.right.win);
498 XMapWindow(ob_display, focus_indicator.bottom.win);
499 }
500 }
501
502 static gboolean valid_focus_target(ObClient *ft)
503 {
504 /* we don't use client_can_focus here, because that doesn't let you
505 focus an iconic window, but we want to be able to, so we just check
506 if the focus flags on the window allow it, and its on the current
507 desktop */
508 if ((ft->type == OB_CLIENT_TYPE_NORMAL ||
509 ft->type == OB_CLIENT_TYPE_DIALOG ||
510 (!client_has_group_siblings(ft) &&
511 (ft->type == OB_CLIENT_TYPE_TOOLBAR ||
512 ft->type == OB_CLIENT_TYPE_MENU ||
513 ft->type == OB_CLIENT_TYPE_UTILITY))) &&
514 ((ft->can_focus || ft->focus_notify) &&
515 !ft->skip_taskbar &&
516 (ft->desktop == screen_desktop || ft->desktop == DESKTOP_ALL)) &&
517 ft == client_focus_target(ft))
518 return TRUE;
519 /*
520 {
521 GSList *it;
522
523 for (it = ft->transients; it; it = g_slist_next(it)) {
524 ObClient *c = it->data;
525
526 if (c->frame->visible)
527 return FALSE;
528 }
529 return TRUE;
530 }
531 */
532
533 return FALSE;
534 }
535
536 void focus_cycle(gboolean forward, gboolean linear,
537 gboolean dialog, gboolean done, gboolean cancel)
538 {
539 static ObClient *first = NULL;
540 static ObClient *t = NULL;
541 static GList *order = NULL;
542 GList *it, *start, *list;
543 ObClient *ft = NULL;
544
545 if (cancel) {
546 focus_cycle_target = NULL;
547 goto done_cycle;
548 } else if (done)
549 goto done_cycle;
550
551 if (!focus_order[screen_desktop])
552 goto done_cycle;
553
554 if (!first) first = focus_client;
555 if (!focus_cycle_target) focus_cycle_target = focus_client;
556
557 if (linear) list = client_list;
558 else list = focus_order[screen_desktop];
559
560 start = it = g_list_find(list, focus_cycle_target);
561 if (!start) /* switched desktops or something? */
562 start = it = forward ? g_list_last(list) : g_list_first(list);
563 if (!start) goto done_cycle;
564
565 do {
566 if (forward) {
567 it = it->next;
568 if (it == NULL) it = g_list_first(list);
569 } else {
570 it = it->prev;
571 if (it == NULL) it = g_list_last(list);
572 }
573 ft = it->data;
574 if (valid_focus_target(ft)) {
575 if (ft != focus_cycle_target) { /* prevents flicker */
576 focus_cycle_target = ft;
577 focus_cycle_draw_indicator();
578 }
579 popup_cycle(ft, dialog);
580 return;
581 }
582 } while (it != start);
583
584 done_cycle:
585 if (done && focus_cycle_target)
586 client_activate(focus_cycle_target, FALSE);
587
588 t = NULL;
589 first = NULL;
590 focus_cycle_target = NULL;
591 g_list_free(order);
592 order = NULL;
593
594 focus_cycle_draw_indicator();
595 popup_cycle(ft, FALSE);
596
597 return;
598 }
599
600 void focus_directional_cycle(ObDirection dir,
601 gboolean dialog, gboolean done, gboolean cancel)
602 {
603 static ObClient *first = NULL;
604 ObClient *ft = NULL;
605
606 if (cancel) {
607 focus_cycle_target = NULL;
608 goto done_cycle;
609 } else if (done)
610 goto done_cycle;
611
612 if (!focus_order[screen_desktop])
613 goto done_cycle;
614
615 if (!first) first = focus_client;
616 if (!focus_cycle_target) focus_cycle_target = focus_client;
617
618 if (focus_cycle_target)
619 ft = client_find_directional(focus_cycle_target, dir);
620 else {
621 GList *it;
622
623 for (it = focus_order[screen_desktop]; it; it = g_list_next(it))
624 if (valid_focus_target(it->data))
625 ft = it->data;
626 }
627
628 if (ft) {
629 if (ft != focus_cycle_target) {/* prevents flicker */
630 focus_cycle_target = ft;
631 focus_cycle_draw_indicator();
632 }
633 }
634 if (focus_cycle_target) {
635 popup_cycle(focus_cycle_target, dialog);
636 if (dialog)
637 return;
638 }
639
640
641 done_cycle:
642 if (done && focus_cycle_target)
643 client_activate(focus_cycle_target, FALSE);
644
645 first = NULL;
646 focus_cycle_target = NULL;
647
648 focus_cycle_draw_indicator();
649 popup_cycle(ft, FALSE);
650
651 return;
652 }
653
654 void focus_order_add_new(ObClient *c)
655 {
656 guint d, i;
657
658 if (c->iconic)
659 focus_order_to_top(c);
660 else {
661 d = c->desktop;
662 if (d == DESKTOP_ALL) {
663 for (i = 0; i < screen_num_desktops; ++i) {
664 g_assert(!g_list_find(focus_order[i], c));
665 if (focus_order[i] && ((ObClient*)focus_order[i]->data)->iconic)
666 focus_order[i] = g_list_insert(focus_order[i], c, 0);
667 else
668 focus_order[i] = g_list_insert(focus_order[i], c, 1);
669 }
670 } else {
671 g_assert(!g_list_find(focus_order[d], c));
672 if (focus_order[d] && ((ObClient*)focus_order[d]->data)->iconic)
673 focus_order[d] = g_list_insert(focus_order[d], c, 0);
674 else
675 focus_order[d] = g_list_insert(focus_order[d], c, 1);
676 }
677 }
678 }
679
680 void focus_order_remove(ObClient *c)
681 {
682 guint d, i;
683
684 d = c->desktop;
685 if (d == DESKTOP_ALL) {
686 for (i = 0; i < screen_num_desktops; ++i)
687 focus_order[i] = g_list_remove(focus_order[i], c);
688 } else
689 focus_order[d] = g_list_remove(focus_order[d], c);
690 }
691
692 static void to_top(ObClient *c, guint d)
693 {
694 focus_order[d] = g_list_remove(focus_order[d], c);
695 if (!c->iconic) {
696 focus_order[d] = g_list_prepend(focus_order[d], c);
697 } else {
698 GList *it;
699
700 /* insert before first iconic window */
701 for (it = focus_order[d];
702 it && !((ObClient*)it->data)->iconic; it = it->next);
703 focus_order[d] = g_list_insert_before(focus_order[d], it, c);
704 }
705 }
706
707 void focus_order_to_top(ObClient *c)
708 {
709 guint d, i;
710
711 d = c->desktop;
712 if (d == DESKTOP_ALL) {
713 for (i = 0; i < screen_num_desktops; ++i)
714 to_top(c, i);
715 } else
716 to_top(c, d);
717 }
718
719 static void to_bottom(ObClient *c, guint d)
720 {
721 focus_order[d] = g_list_remove(focus_order[d], c);
722 if (c->iconic) {
723 focus_order[d] = g_list_append(focus_order[d], c);
724 } else {
725 GList *it;
726
727 /* insert before first iconic window */
728 for (it = focus_order[d];
729 it && !((ObClient*)it->data)->iconic; it = it->next);
730 g_list_insert_before(focus_order[d], it, c);
731 }
732 }
733
734 void focus_order_to_bottom(ObClient *c)
735 {
736 guint d, i;
737
738 d = c->desktop;
739 if (d == DESKTOP_ALL) {
740 for (i = 0; i < screen_num_desktops; ++i)
741 to_bottom(c, i);
742 } else
743 to_bottom(c, d);
744 }
This page took 0.067048 seconds and 3 git commands to generate.