]> Dogcows Code - chaz/openbox/blob - openbox/focus.c
va_start needs va_end
[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, unsigned long 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, ObClient *skip)
214 {
215 GSList *it;
216 ObClient *ret;
217
218 for (it = c->transients; it; it = it->next) {
219 if (it->data == top) return NULL;
220 ret = find_transient_recursive(it->data, top, skip);
221 if (ret && ret != skip && client_normal(ret)) return ret;
222 if (it->data != skip && client_normal(it->data)) return it->data;
223 }
224 return NULL;
225 }
226
227 static ObClient* focus_fallback_transient(ObClient *top, ObClient *old)
228 {
229 ObClient *target = find_transient_recursive(top, top, old);
230 if (!target) {
231 /* make sure client_normal is true always */
232 if (!client_normal(top))
233 return NULL;
234 target = top; /* no transient, keep the top */
235 }
236 if (client_can_focus(target))
237 return target;
238 else
239 return NULL;
240 }
241
242 ObClient* focus_fallback_target(ObFocusFallbackType type)
243 {
244 GList *it;
245 ObClient *old = NULL;
246 ObClient *target = NULL;
247
248 old = focus_client;
249
250 if (type == OB_FOCUS_FALLBACK_UNFOCUSING && old) {
251 if (old->transient_for) {
252 gboolean trans = FALSE;
253
254 if (!config_focus_follow)
255 trans = TRUE;
256 else {
257 if ((target = client_under_pointer()) &&
258 client_search_transient
259 (client_search_top_transient(target), old))
260 {
261 trans = TRUE;
262 }
263 }
264
265 /* try for transient relations */
266 if (trans) {
267 if (old->transient_for == OB_TRAN_GROUP) {
268 for (it = focus_order[screen_desktop]; it; it = it->next) {
269 GSList *sit;
270
271 for (sit = old->group->members; sit; sit = sit->next)
272 if (sit->data == it->data)
273 if ((target =
274 focus_fallback_transient(sit->data, old)))
275 return target;
276 }
277 } else {
278 if ((target =
279 focus_fallback_transient(old->transient_for, old)))
280 return target;
281 }
282 }
283 }
284 }
285
286 if (config_focus_follow) {
287 if ((target = client_under_pointer()))
288 if (client_normal(target) && client_can_focus(target))
289 return target;
290 }
291
292 #if 0
293 /* try for group relations */
294 if (old->group) {
295 GSList *sit;
296
297 for (it = focus_order[screen_desktop]; it != NULL; it = it->next)
298 for (sit = old->group->members; sit; sit = sit->next)
299 if (sit->data == it->data)
300 if (sit->data != old && client_normal(sit->data))
301 if (client_can_focus(sit->data))
302 return sit->data;
303 }
304 #endif
305
306 for (it = focus_order[screen_desktop]; it != NULL; it = it->next)
307 if (type != OB_FOCUS_FALLBACK_UNFOCUSING || it->data != old)
308 if (client_normal(it->data) && client_can_focus(it->data))
309 return it->data;
310
311 return NULL;
312 }
313
314 void focus_fallback(ObFocusFallbackType type)
315 {
316 ObClient *new;
317
318 /* unfocus any focused clients.. they can be focused by Pointer events
319 and such, and then when I try focus them, I won't get a FocusIn event
320 at all for them.
321 */
322 focus_set_client(NULL);
323
324 if ((new = focus_fallback_target(type)))
325 client_focus(new);
326 }
327
328 static void popup_cycle(ObClient *c, gboolean show)
329 {
330 if (!show) {
331 icon_popup_hide(focus_cycle_popup);
332 } else {
333 Rect *a;
334 ObClient *p = c;
335 char *title;
336
337 a = screen_physical_area_monitor(0);
338 icon_popup_position(focus_cycle_popup, CenterGravity,
339 a->x + a->width / 2, a->y + a->height / 2);
340 /* icon_popup_size(focus_cycle_popup, a->height/2, a->height/16);
341 icon_popup_show(focus_cycle_popup, c->title,
342 client_icon(c, a->height/16, a->height/16));
343 */
344 /* XXX the size and the font extents need to be related on some level
345 */
346 icon_popup_size(focus_cycle_popup, POPUP_WIDTH, POPUP_HEIGHT);
347
348 /* use the transient's parent's title/icon */
349 while (p->transient_for && p->transient_for != OB_TRAN_GROUP)
350 p = p->transient_for;
351
352 if (p == c)
353 title = NULL;
354 else
355 title = g_strconcat((c->iconic ? c->icon_title : c->title),
356 " - ",
357 (p->iconic ? p->icon_title : p->title),
358 NULL);
359
360 icon_popup_show(focus_cycle_popup,
361 (title ? title :
362 (c->iconic ? c->icon_title : c->title)),
363 client_icon(p, 48, 48));
364 g_free(title);
365 }
366 }
367
368 void focus_cycle_draw_indicator()
369 {
370 if (!focus_cycle_target) {
371 XUnmapWindow(ob_display, focus_indicator.top.win);
372 XUnmapWindow(ob_display, focus_indicator.left.win);
373 XUnmapWindow(ob_display, focus_indicator.right.win);
374 XUnmapWindow(ob_display, focus_indicator.bottom.win);
375 } else {
376 /*
377 if (focus_cycle_target)
378 frame_adjust_focus(focus_cycle_target->frame, FALSE);
379 frame_adjust_focus(focus_cycle_target->frame, TRUE);
380 */
381 int x, y, w, h;
382 int wt, wl, wr, wb;
383
384 wt = wl = wr = wb = MAX(3,
385 ob_rr_theme->handle_height +
386 ob_rr_theme->bwidth * 2);
387
388 x = focus_cycle_target->frame->area.x;
389 y = focus_cycle_target->frame->area.y;
390 w = focus_cycle_target->frame->area.width;
391 h = wt;
392
393 XMoveResizeWindow(ob_display, focus_indicator.top.win,
394 x, y, w, h);
395 a_focus_indicator->texture[0].data.lineart.x1 = 0;
396 a_focus_indicator->texture[0].data.lineart.y1 = h-1;
397 a_focus_indicator->texture[0].data.lineart.x2 = 0;
398 a_focus_indicator->texture[0].data.lineart.y2 = 0;
399 a_focus_indicator->texture[1].data.lineart.x1 = 0;
400 a_focus_indicator->texture[1].data.lineart.y1 = 0;
401 a_focus_indicator->texture[1].data.lineart.x2 = w-1;
402 a_focus_indicator->texture[1].data.lineart.y2 = 0;
403 a_focus_indicator->texture[2].data.lineart.x1 = w-1;
404 a_focus_indicator->texture[2].data.lineart.y1 = 0;
405 a_focus_indicator->texture[2].data.lineart.x2 = w-1;
406 a_focus_indicator->texture[2].data.lineart.y2 = h-1;
407 a_focus_indicator->texture[3].data.lineart.x1 = (wl-1);
408 a_focus_indicator->texture[3].data.lineart.y1 = h-1;
409 a_focus_indicator->texture[3].data.lineart.x2 = w - wr;
410 a_focus_indicator->texture[3].data.lineart.y2 = h-1;
411 RrPaint(a_focus_indicator, focus_indicator.top.win,
412 w, h);
413
414 x = focus_cycle_target->frame->area.x;
415 y = focus_cycle_target->frame->area.y;
416 w = wl;
417 h = focus_cycle_target->frame->area.height;
418
419 XMoveResizeWindow(ob_display, focus_indicator.left.win,
420 x, y, w, h);
421 a_focus_indicator->texture[0].data.lineart.x1 = w-1;
422 a_focus_indicator->texture[0].data.lineart.y1 = 0;
423 a_focus_indicator->texture[0].data.lineart.x2 = 0;
424 a_focus_indicator->texture[0].data.lineart.y2 = 0;
425 a_focus_indicator->texture[1].data.lineart.x1 = 0;
426 a_focus_indicator->texture[1].data.lineart.y1 = 0;
427 a_focus_indicator->texture[1].data.lineart.x2 = 0;
428 a_focus_indicator->texture[1].data.lineart.y2 = h-1;
429 a_focus_indicator->texture[2].data.lineart.x1 = 0;
430 a_focus_indicator->texture[2].data.lineart.y1 = h-1;
431 a_focus_indicator->texture[2].data.lineart.x2 = w-1;
432 a_focus_indicator->texture[2].data.lineart.y2 = h-1;
433 a_focus_indicator->texture[3].data.lineart.x1 = w-1;
434 a_focus_indicator->texture[3].data.lineart.y1 = wt-1;
435 a_focus_indicator->texture[3].data.lineart.x2 = w-1;
436 a_focus_indicator->texture[3].data.lineart.y2 = h - wb;
437 RrPaint(a_focus_indicator, focus_indicator.left.win,
438 w, h);
439
440 x = focus_cycle_target->frame->area.x +
441 focus_cycle_target->frame->area.width - wr;
442 y = focus_cycle_target->frame->area.y;
443 w = wr;
444 h = focus_cycle_target->frame->area.height ;
445
446 XMoveResizeWindow(ob_display, focus_indicator.right.win,
447 x, y, w, h);
448 a_focus_indicator->texture[0].data.lineart.x1 = 0;
449 a_focus_indicator->texture[0].data.lineart.y1 = 0;
450 a_focus_indicator->texture[0].data.lineart.x2 = w-1;
451 a_focus_indicator->texture[0].data.lineart.y2 = 0;
452 a_focus_indicator->texture[1].data.lineart.x1 = w-1;
453 a_focus_indicator->texture[1].data.lineart.y1 = 0;
454 a_focus_indicator->texture[1].data.lineart.x2 = w-1;
455 a_focus_indicator->texture[1].data.lineart.y2 = h-1;
456 a_focus_indicator->texture[2].data.lineart.x1 = w-1;
457 a_focus_indicator->texture[2].data.lineart.y1 = h-1;
458 a_focus_indicator->texture[2].data.lineart.x2 = 0;
459 a_focus_indicator->texture[2].data.lineart.y2 = h-1;
460 a_focus_indicator->texture[3].data.lineart.x1 = 0;
461 a_focus_indicator->texture[3].data.lineart.y1 = wt-1;
462 a_focus_indicator->texture[3].data.lineart.x2 = 0;
463 a_focus_indicator->texture[3].data.lineart.y2 = h - wb;
464 RrPaint(a_focus_indicator, focus_indicator.right.win,
465 w, h);
466
467 x = focus_cycle_target->frame->area.x;
468 y = focus_cycle_target->frame->area.y +
469 focus_cycle_target->frame->area.height - wb;
470 w = focus_cycle_target->frame->area.width;
471 h = wb;
472
473 XMoveResizeWindow(ob_display, focus_indicator.bottom.win,
474 x, y, w, h);
475 a_focus_indicator->texture[0].data.lineart.x1 = 0;
476 a_focus_indicator->texture[0].data.lineart.y1 = 0;
477 a_focus_indicator->texture[0].data.lineart.x2 = 0;
478 a_focus_indicator->texture[0].data.lineart.y2 = h-1;
479 a_focus_indicator->texture[1].data.lineart.x1 = 0;
480 a_focus_indicator->texture[1].data.lineart.y1 = h-1;
481 a_focus_indicator->texture[1].data.lineart.x2 = w-1;
482 a_focus_indicator->texture[1].data.lineart.y2 = h-1;
483 a_focus_indicator->texture[2].data.lineart.x1 = w-1;
484 a_focus_indicator->texture[2].data.lineart.y1 = h-1;
485 a_focus_indicator->texture[2].data.lineart.x2 = w-1;
486 a_focus_indicator->texture[2].data.lineart.y2 = 0;
487 a_focus_indicator->texture[3].data.lineart.x1 = wl-1;
488 a_focus_indicator->texture[3].data.lineart.y1 = 0;
489 a_focus_indicator->texture[3].data.lineart.x2 = w - wr;
490 a_focus_indicator->texture[3].data.lineart.y2 = 0;
491 RrPaint(a_focus_indicator, focus_indicator.bottom.win,
492 w, h);
493
494 XMapWindow(ob_display, focus_indicator.top.win);
495 XMapWindow(ob_display, focus_indicator.left.win);
496 XMapWindow(ob_display, focus_indicator.right.win);
497 XMapWindow(ob_display, focus_indicator.bottom.win);
498 }
499 }
500
501 static gboolean valid_focus_target(ObClient *ft)
502 {
503 /* we don't use client_can_focus here, because that doesn't let you
504 focus an iconic window, but we want to be able to, so we just check
505 if the focus flags on the window allow it, and its on the current
506 desktop */
507 if ((ft->type == OB_CLIENT_TYPE_NORMAL ||
508 ft->type == OB_CLIENT_TYPE_DIALOG ||
509 (!client_has_group_siblings(ft) &&
510 (ft->type == OB_CLIENT_TYPE_TOOLBAR ||
511 ft->type == OB_CLIENT_TYPE_MENU ||
512 ft->type == OB_CLIENT_TYPE_UTILITY))) &&
513 ((ft->can_focus || ft->focus_notify) &&
514 !ft->skip_taskbar &&
515 (ft->desktop == screen_desktop || ft->desktop == DESKTOP_ALL)))
516 {
517 GSList *it;
518
519 for (it = ft->transients; it; it = g_slist_next(it)) {
520 ObClient *c = it->data;
521
522 if (c->frame->visible)
523 return FALSE;
524 }
525 return TRUE;
526 }
527
528 return FALSE;
529 }
530
531 void focus_cycle(gboolean forward, gboolean linear,
532 gboolean dialog, gboolean done, gboolean cancel)
533 {
534 static ObClient *first = NULL;
535 static ObClient *t = NULL;
536 static GList *order = NULL;
537 GList *it, *start, *list;
538 ObClient *ft = NULL;
539
540 if (cancel) {
541 focus_cycle_target = NULL;
542 goto done_cycle;
543 } else if (done)
544 goto done_cycle;
545
546 if (!focus_order[screen_desktop])
547 goto done_cycle;
548
549 if (!first) first = focus_client;
550 if (!focus_cycle_target) focus_cycle_target = focus_client;
551
552 if (linear) list = client_list;
553 else list = focus_order[screen_desktop];
554
555 start = it = g_list_find(list, focus_cycle_target);
556 if (!start) /* switched desktops or something? */
557 start = it = forward ? g_list_last(list) : g_list_first(list);
558 if (!start) goto done_cycle;
559
560 do {
561 if (forward) {
562 it = it->next;
563 if (it == NULL) it = g_list_first(list);
564 } else {
565 it = it->prev;
566 if (it == NULL) it = g_list_last(list);
567 }
568 ft = it->data;
569 if (valid_focus_target(ft)) {
570 if (ft != focus_cycle_target) { /* prevents flicker */
571 focus_cycle_target = ft;
572 focus_cycle_draw_indicator();
573 }
574 popup_cycle(ft, dialog);
575 return;
576 }
577 } while (it != start);
578
579 done_cycle:
580 if (done && focus_cycle_target)
581 client_activate(focus_cycle_target, FALSE);
582
583 t = NULL;
584 first = NULL;
585 focus_cycle_target = NULL;
586 g_list_free(order);
587 order = NULL;
588
589 focus_cycle_draw_indicator();
590 popup_cycle(ft, FALSE);
591
592 return;
593 }
594
595 void focus_directional_cycle(ObDirection dir,
596 gboolean dialog, gboolean done, gboolean cancel)
597 {
598 static ObClient *first = NULL;
599 ObClient *ft = NULL;
600
601 if (cancel) {
602 focus_cycle_target = NULL;
603 goto done_cycle;
604 } else if (done)
605 goto done_cycle;
606
607 if (!focus_order[screen_desktop])
608 goto done_cycle;
609
610 if (!first) first = focus_client;
611 if (!focus_cycle_target) focus_cycle_target = focus_client;
612
613 if (focus_cycle_target)
614 ft = client_find_directional(focus_cycle_target, dir);
615 else {
616 GList *it;
617
618 for (it = focus_order[screen_desktop]; it; it = g_list_next(it))
619 if (valid_focus_target(it->data))
620 ft = it->data;
621 }
622
623 if (ft) {
624 if (ft != focus_cycle_target) {/* prevents flicker */
625 focus_cycle_target = ft;
626 focus_cycle_draw_indicator();
627 }
628 }
629 if (focus_cycle_target) {
630 popup_cycle(focus_cycle_target, dialog);
631 if (dialog)
632 return;
633 }
634
635
636 done_cycle:
637 if (done && focus_cycle_target)
638 client_activate(focus_cycle_target, FALSE);
639
640 first = NULL;
641 focus_cycle_target = NULL;
642
643 focus_cycle_draw_indicator();
644 popup_cycle(ft, FALSE);
645
646 return;
647 }
648
649 void focus_order_add_new(ObClient *c)
650 {
651 guint d, i;
652
653 if (c->iconic)
654 focus_order_to_top(c);
655 else {
656 d = c->desktop;
657 if (d == DESKTOP_ALL) {
658 for (i = 0; i < screen_num_desktops; ++i) {
659 if (focus_order[i] && ((ObClient*)focus_order[i]->data)->iconic)
660 focus_order[i] = g_list_insert(focus_order[i], c, 0);
661 else
662 focus_order[i] = g_list_insert(focus_order[i], c, 1);
663 }
664 } else
665 if (focus_order[d] && ((ObClient*)focus_order[d]->data)->iconic)
666 focus_order[d] = g_list_insert(focus_order[d], c, 0);
667 else
668 focus_order[d] = g_list_insert(focus_order[d], c, 1);
669 }
670 }
671
672 void focus_order_remove(ObClient *c)
673 {
674 guint d, i;
675
676 d = c->desktop;
677 if (d == DESKTOP_ALL) {
678 for (i = 0; i < screen_num_desktops; ++i)
679 focus_order[i] = g_list_remove(focus_order[i], c);
680 } else
681 focus_order[d] = g_list_remove(focus_order[d], c);
682 }
683
684 static void to_top(ObClient *c, guint d)
685 {
686 focus_order[d] = g_list_remove(focus_order[d], c);
687 if (!c->iconic) {
688 focus_order[d] = g_list_prepend(focus_order[d], c);
689 } else {
690 GList *it;
691
692 /* insert before first iconic window */
693 for (it = focus_order[d];
694 it && !((ObClient*)it->data)->iconic; it = it->next);
695 focus_order[d] = g_list_insert_before(focus_order[d], it, c);
696 }
697 }
698
699 void focus_order_to_top(ObClient *c)
700 {
701 guint d, i;
702
703 d = c->desktop;
704 if (d == DESKTOP_ALL) {
705 for (i = 0; i < screen_num_desktops; ++i)
706 to_top(c, i);
707 } else
708 to_top(c, d);
709 }
710
711 static void to_bottom(ObClient *c, guint d)
712 {
713 focus_order[d] = g_list_remove(focus_order[d], c);
714 if (c->iconic) {
715 focus_order[d] = g_list_append(focus_order[d], c);
716 } else {
717 GList *it;
718
719 /* insert before first iconic window */
720 for (it = focus_order[d];
721 it && !((ObClient*)it->data)->iconic; it = it->next);
722 g_list_insert_before(focus_order[d], it, c);
723 }
724 }
725
726 void focus_order_to_bottom(ObClient *c)
727 {
728 guint d, i;
729
730 d = c->desktop;
731 if (d == DESKTOP_ALL) {
732 for (i = 0; i < screen_num_desktops; ++i)
733 to_bottom(c, i);
734 } else
735 to_bottom(c, d);
736 }
This page took 0.068365 seconds and 4 git commands to generate.