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