]> Dogcows Code - chaz/openbox/blob - c/stacking.c
merge the C branch into HEAD
[chaz/openbox] / c / stacking.c
1 #include "openbox.h"
2 #include "prop.h"
3 #include "focus.h"
4 #include "client.h"
5 #include "frame.h"
6 #include <glib.h>
7
8 GList *stacking_list = NULL;
9
10 void stacking_set_list()
11 {
12 Window *windows, *win_it;
13 GList *it;
14 guint size = g_list_length(stacking_list);
15
16 /* create an array of the window ids (from bottom to top,
17 reverse order!) */
18 if (size > 0) {
19 windows = g_new(Window, size);
20 win_it = windows;
21 for (it = g_list_last(stacking_list); it; it = it->prev, ++win_it)
22 *win_it = ((Client*)it->data)->window;
23 } else
24 windows = NULL;
25
26 PROP_SET32A(ob_root, net_client_list_stacking, window, windows, size);
27
28 if (windows)
29 g_free(windows);
30 }
31
32 void stacking_raise(Client *client)
33 {
34 Window wins[2]; /* only ever restack 2 windows. */
35 GList *it;
36 Client *m;
37
38 g_assert(stacking_list != NULL); /* this would be bad */
39
40 m = client_find_modal_child(client);
41 /* if we have a modal child, raise it instead, we'll go along tho later */
42 if (m) stacking_raise(m);
43
44 /* remove the client before looking so we can't run into ourselves */
45 stacking_list = g_list_remove(stacking_list, client);
46
47 /* the stacking list is from highest to lowest */
48 it = stacking_list;
49 while (it) {
50 Client *c = it->data;
51 if (client->layer >= c->layer && m != c)
52 break;
53 it = it->next;
54 }
55
56 /*
57 if our new position is the top, we want to stack under the focus_backup.
58 otherwise, we want to stack under the previous window in the stack.
59 */
60 if (it == stacking_list)
61 wins[0] = focus_backup;
62 else if (it != NULL)
63 wins[0] = ((Client*)it->prev->data)->frame->window;
64 else
65 wins[0] = ((Client*)g_list_last(stacking_list)->data)->frame->window;
66 wins[1] = client->frame->window;
67
68 stacking_list = g_list_insert_before(stacking_list, it, client);
69
70 XRestackWindows(ob_display, wins, 2);
71
72 stacking_set_list();
73 }
74
75 void stacking_lower(Client *client)
76 {
77 Window wins[2]; /* only ever restack 2 windows. */
78 GList *it;
79
80 g_assert(stacking_list != NULL); /* this would be bad */
81
82 it = g_list_last(stacking_list);
83
84 if (client->modal && client->transient_for) {
85 /* don't let a modal window lower below its transient_for */
86 it = g_list_find(stacking_list, client->transient_for);
87 g_assert(it != NULL);
88
89 wins[0] = (it == stacking_list ? focus_backup :
90 ((Client*)it->prev->data)->frame->window);
91 wins[1] = client->frame->window;
92 if (wins[0] == wins[1]) return; /* already right above the window */
93
94 stacking_list = g_list_remove(stacking_list, client);
95 stacking_list = g_list_insert_before(stacking_list, it, client);
96 } else {
97 while (it != stacking_list) {
98 Client *c = it->data;
99 if (client->layer >= c->layer)
100 break;
101 it = it->prev;
102 }
103 if (it->data == client) return; /* already the bottom, return */
104
105 wins[0] = ((Client*)it->data)->frame->window;
106 wins[1] = client->frame->window;
107
108 stacking_list = g_list_remove(stacking_list, client);
109 stacking_list = g_list_insert_before(stacking_list,
110 it->next, client);
111 }
112
113 XRestackWindows(ob_display, wins, 2);
114 stacking_set_list();
115 }
116
This page took 0.037493 seconds and 4 git commands to generate.