]> git.lizzy.rs Git - bspwm.git/blob - src/stack.c
bspwm: port rounded corners patch to latest version
[bspwm.git] / src / stack.c
1 /* Copyright (c) 2012, Bastien Dejean
2  * All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are met:
6  *
7  * 1. Redistributions of source code must retain the above copyright notice, this
8  *    list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright notice,
10  *    this list of conditions and the following disclaimer in the documentation
11  *    and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
14  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
15  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
16  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
17  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
18  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
19  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
20  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
22  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23  */
24
25 #include <stdlib.h>
26 #include "bspwm.h"
27 #include "window.h"
28 #include "subscribe.h"
29 #include "ewmh.h"
30 #include "tree.h"
31 #include "stack.h"
32
33 stacking_list_t *make_stack(node_t *n)
34 {
35         stacking_list_t *s = calloc(1, sizeof(stacking_list_t));
36         s->node = n;
37         s->prev = s->next = NULL;
38         return s;
39 }
40
41 void stack_insert_after(stacking_list_t *a, node_t *n)
42 {
43         stacking_list_t *s = make_stack(n);
44         if (a == NULL) {
45                 stack_head = stack_tail = s;
46         } else {
47                 if (a->node == n) {
48                         free(s);
49                         return;
50                 }
51                 remove_stack_node(n);
52                 stacking_list_t *b = a->next;
53                 if (b != NULL) {
54                         b->prev = s;
55                 }
56                 s->next = b;
57                 s->prev = a;
58                 a->next = s;
59                 if (stack_tail == a) {
60                         stack_tail = s;
61                 }
62         }
63 }
64
65 void stack_insert_before(stacking_list_t *a, node_t *n)
66 {
67         stacking_list_t *s = make_stack(n);
68         if (a == NULL) {
69                 stack_head = stack_tail = s;
70         } else {
71                 if (a->node == n) {
72                         free(s);
73                         return;
74                 }
75                 remove_stack_node(n);
76                 stacking_list_t *b = a->prev;
77                 if (b != NULL) {
78                         b->next = s;
79                 }
80                 s->prev = b;
81                 s->next = a;
82                 a->prev = s;
83                 if (stack_head == a) {
84                         stack_head = s;
85                 }
86         }
87 }
88
89 void remove_stack(stacking_list_t *s)
90 {
91         if (s == NULL) {
92                 return;
93         }
94         stacking_list_t *a = s->prev;
95         stacking_list_t *b = s->next;
96         if (a != NULL) {
97                 a->next = b;
98         }
99         if (b != NULL) {
100                 b->prev = a;
101         }
102         if (s == stack_head) {
103                 stack_head = b;
104         }
105         if (s == stack_tail) {
106                 stack_tail = a;
107         }
108         free(s);
109 }
110
111 void remove_stack_node(node_t *n)
112 {
113         for (node_t *f = first_extrema(n); f != NULL; f = next_leaf(f, n)) {
114                 for (stacking_list_t *s = stack_head; s != NULL; s = s->next) {
115                         if (s->node == f) {
116                                 remove_stack(s);
117                                 break;
118                         }
119                 }
120         }
121 }
122
123 int stack_level(client_t *c)
124 {
125         int layer_level = (c->layer == LAYER_NORMAL ? 1 : (c->layer == LAYER_BELOW ? 0 : 2));
126         int state_level = (IS_TILED(c) ? 0 : (IS_FLOATING(c) ? 1 : 2));
127         return 3 * layer_level + state_level;
128 }
129
130 int stack_cmp(client_t *c1, client_t *c2)
131 {
132         return stack_level(c1) - stack_level(c2);
133 }
134
135 stacking_list_t *limit_above(node_t *n)
136 {
137         stacking_list_t *s = stack_head;
138         while (s != NULL && stack_cmp(n->client, s->node->client) >= 0) {
139                 s = s->next;
140         }
141         if (s == NULL) {
142                 s = stack_tail;
143         }
144         if (s->node == n) {
145                 s = s->prev;
146         }
147         return s;
148 }
149
150 stacking_list_t *limit_below(node_t *n)
151 {
152         stacking_list_t *s = stack_tail;
153         while (s != NULL && stack_cmp(n->client, s->node->client) <= 0) {
154                 s = s->prev;
155         }
156         if (s == NULL) {
157                 s = stack_head;
158         }
159         if (s->node == n) {
160                 s = s->next;
161         }
162         return s;
163 }
164
165 void stack(desktop_t *d, node_t *n, bool focused)
166 {
167         for (node_t *f = first_extrema(n); f != NULL; f = next_leaf(f, n)) {
168                 if (f->client == NULL || (IS_FLOATING(f->client) && !auto_raise)) {
169                         continue;
170                 }
171
172                 if (stack_head == NULL) {
173                         stack_insert_after(NULL, f);
174                 } else {
175                         stacking_list_t *s = (focused ? limit_above(f) : limit_below(f));
176                         if (s == NULL) {
177                                 continue;
178                         }
179                         int i = stack_cmp(f->client, s->node->client);
180                         if (i < 0 || (i == 0 && !focused)) {
181                                 stack_insert_before(s, f);
182                                 window_below(f->id, s->node->id);
183                                 put_status(SBSC_MASK_NODE_STACK, "node_stack 0x%08X below 0x%08X\n", f->id, s->node->id);
184                         } else {
185                                 stack_insert_after(s, f);
186                                 window_above(f->id, s->node->id);
187                                 put_status(SBSC_MASK_NODE_STACK, "node_stack 0x%08X above 0x%08X\n", f->id, s->node->id);
188                         }
189                 }
190         }
191
192         ewmh_update_client_list(true);
193         restack_presel_feedbacks(d);
194 }
195
196 void restack_presel_feedbacks(desktop_t *d)
197 {
198         stacking_list_t *s = stack_tail;
199         while (s != NULL && !IS_TILED(s->node->client)) {
200                 s = s->prev;
201         }
202         if (s != NULL) {
203                 restack_presel_feedbacks_in(d->root, s->node);
204         }
205 }
206
207 void restack_presel_feedbacks_in(node_t *r, node_t *n)
208 {
209         if (r == NULL) {
210                 return;
211         } else {
212                 if (r->presel != NULL) {
213                         window_above(r->presel->feedback, n->id);
214                 }
215                 restack_presel_feedbacks_in(r->first_child, n);
216                 restack_presel_feedbacks_in(r->second_child, n);
217         }
218 }