]> git.lizzy.rs Git - bspwm.git/blob - stack.c
Fix initial tagging of windows
[bspwm.git] / stack.c
1 /* * Copyright (c) 2012-2013 Bastien Dejean
2  * All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without modification,
5  * are permitted provided that the following conditions are met:
6  *
7  *  * Redistributions of source code must retain the above copyright notice, this
8  * list of conditions and the following disclaimer.
9  *  * Redistributions in binary form must reproduce the above copyright notice,
10  * this list of conditions and the following disclaimer in the documentation and/or
11  * other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
16  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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 ON
20  * 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 "stack.h"
29
30 stacking_list_t *make_stack(node_t *n)
31 {
32     stacking_list_t *s = malloc(sizeof(stacking_list_t));
33     s->node = n;
34     s->prev = s->next = NULL;
35     return s;
36 }
37
38 void stack_insert_after(stacking_list_t *a, node_t *n)
39 {
40     stacking_list_t *s = make_stack(n);
41     if (a == NULL) {
42         stack_head = stack_tail = s;
43     } else {
44         remove_stack_node(n);
45         stacking_list_t *b = a->next;
46         if (b != NULL)
47             b->prev = s;
48         s->next = b;
49         s->prev = a;
50         a->next = s;
51         if (stack_tail == a)
52             stack_tail = s;
53     }
54 }
55
56 void stack_insert_before(stacking_list_t *a, node_t *n)
57 {
58     stacking_list_t *s = make_stack(n);
59     if (a == NULL) {
60         stack_head = stack_tail = s;
61     } else {
62         remove_stack_node(n);
63         stacking_list_t *b = a->prev;
64         if (b != NULL)
65             b->next = s;
66         s->prev = b;
67         s->next = a;
68         a->prev = s;
69         if (stack_head == a)
70             stack_head = s;
71     }
72 }
73
74 void remove_stack(stacking_list_t *s)
75 {
76     if (s == NULL)
77         return;
78     stacking_list_t *a = s->prev;
79     stacking_list_t *b = s->next;
80     if (a != NULL)
81         a->next = b;
82     if (b != NULL)
83         b->prev = a;
84     if (s == stack_head)
85         stack_head = b;
86     if (s == stack_tail)
87         stack_tail = a;
88     free(s);
89 }
90
91 void remove_stack_node(node_t *n)
92 {
93     for (stacking_list_t *s = stack_head; s != NULL; s = s->next)
94         if (s->node == n) {
95             remove_stack(s);
96             return;
97         }
98 }
99
100 void stack(node_t *n)
101 {
102     PRINTF("stack %X\n", n->client->window);
103
104     if (stack_head == NULL) {
105         stack_insert_after(NULL, n);
106     } else if (n->client->fullscreen) {
107         stack_insert_after(stack_tail, n);
108         window_raise(n->client->window);
109     } else {
110         if (n->client->floating && !auto_raise)
111             return;
112         stacking_list_t *latest_tiled = NULL;
113         stacking_list_t *oldest_floating = NULL;
114         for (stacking_list_t *s = stack_tail; s != NULL; s = s->prev) {
115             if (s->node != n) {
116                 if (s->node->client->floating == n->client->floating) {
117                     stack_insert_after(s, n);
118                     window_above(n->client->window, s->node->client->window);
119                     return;
120                 } else if (latest_tiled == NULL && !s->node->client->floating) {
121                     latest_tiled = s;
122                 } else if (s->node->client->floating) {
123                     oldest_floating = s;
124                 }
125             }
126         }
127         if (latest_tiled == NULL && oldest_floating == NULL)
128             return;
129         if (n->client->floating) {
130             if (latest_tiled == NULL)
131                 return;
132             window_above(n->client->window, latest_tiled->node->client->window);
133             stack_insert_after(latest_tiled, n);
134         } else {
135             if (oldest_floating == NULL)
136                 return;
137             window_below(n->client->window, oldest_floating->node->client->window);
138             stack_insert_before(oldest_floating, n);
139         }
140     }
141 }
142
143 void stack_under(node_t *n)
144 {
145     PRINTF("stack under %X\n", n->client->window);
146
147     if (stack_head == NULL) {
148         stack_insert_after(NULL, n);
149     } else if (n->client->fullscreen) {
150         ;
151     } else {
152         if (n->client->floating && !auto_raise)
153             return;
154         stacking_list_t *latest_tiled = NULL;
155         stacking_list_t *oldest_floating = NULL;
156         for (stacking_list_t *s = stack_head; s != NULL; s = s->next) {
157             if (s->node != n) {
158                 if (s->node->client->floating == n->client->floating) {
159                     stack_insert_before(s, n);
160                     window_below(n->client->window, s->node->client->window);
161                     return;
162                 } else if (!s->node->client->floating) {
163                     latest_tiled = s;
164                 } else if (oldest_floating == NULL && s->node->client->floating) {
165                     oldest_floating = s;
166                 }
167             }
168         }
169         if (latest_tiled == NULL && oldest_floating == NULL)
170             return;
171         if (n->client->floating) {
172             if (latest_tiled == NULL)
173                 return;
174             window_above(n->client->window, latest_tiled->node->client->window);
175             stack_insert_after(latest_tiled, n);
176         } else {
177             if (oldest_floating == NULL)
178                 return;
179             window_below(n->client->window, oldest_floating->node->client->window);
180             stack_insert_before(oldest_floating, n);
181         }
182     }
183 }