]> git.lizzy.rs Git - bspwm.git/blob - stack.c
Implement sticky windows
[bspwm.git] / stack.c
1 #include <stdlib.h>
2 #include "bspwm.h"
3 #include "window.h"
4 #include "stack.h"
5
6 stack_t *make_stack(node_t *n)
7 {
8     stack_t *s = malloc(sizeof(stack_t));
9     s->node = n;
10     s->prev = s->next = NULL;
11     return s;
12 }
13
14 void stack_insert_after(stack_t *a, node_t *n)
15 {
16     stack_t *s = make_stack(n);
17     if (a == NULL) {
18         stack_head = stack_tail = s;
19     } else {
20         remove_stack_node(n);
21         stack_t *b = a->next;
22         if (b != NULL)
23             b->prev = s;
24         s->next = b;
25         s->prev = a;
26         a->next = s;
27         if (stack_tail == a)
28             stack_tail = s;
29     }
30 }
31
32 void stack_insert_before(stack_t *a, node_t *n)
33 {
34     stack_t *s = make_stack(n);
35     if (a == NULL) {
36         stack_head = stack_tail = s;
37     } else {
38         remove_stack_node(n);
39         stack_t *b = a->prev;
40         if (b != NULL)
41             b->next = s;
42         s->prev = b;
43         s->next = a;
44         a->prev = s;
45         if (stack_head == a)
46             stack_head = s;
47     }
48 }
49
50 void remove_stack(stack_t *s)
51 {
52     if (s == NULL)
53         return;
54     stack_t *a = s->prev;
55     stack_t *b = s->next;
56     if (a != NULL)
57         a->next = b;
58     if (b != NULL)
59         b->prev = a;
60     if (s == stack_head)
61         stack_head = b;
62     if (s == stack_tail)
63         stack_tail = a;
64     free(s);
65 }
66
67 void remove_stack_node(node_t *n)
68 {
69     for (stack_t *s = stack_head; s != NULL; s = s->next)
70         if (s->node == n) {
71             remove_stack(s);
72             return;
73         }
74 }
75
76 void stack(node_t *n)
77 {
78     PRINTF("stack %X\n", n->client->window);
79
80     if (stack_head == NULL) {
81         stack_insert_after(NULL, n);
82     } else if (n->client->fullscreen) {
83         stack_insert_after(stack_tail, n);
84         window_raise(n->client->window);
85     } else {
86         if (n->client->floating && !auto_raise)
87             return;
88         stack_t *latest_tiled = NULL;
89         stack_t *oldest_floating = NULL;
90         for (stack_t *s = stack_tail; s != NULL; s = s->prev) {
91             if (s->node != n) {
92                 if (s->node->client->floating == n->client->floating) {
93                     stack_insert_after(s, n);
94                     window_above(n->client->window, s->node->client->window);
95                     return;
96                 } else if (latest_tiled == NULL && !s->node->client->floating) {
97                     latest_tiled = s;
98                 } else if (s->node->client->floating) {
99                     oldest_floating = s;
100                 }
101             }
102         }
103         if (latest_tiled == NULL && oldest_floating == NULL)
104             return;
105         if (n->client->floating) {
106             window_above(n->client->window, latest_tiled->node->client->window);
107             stack_insert_after(latest_tiled, n);
108         } else {
109             window_below(n->client->window, oldest_floating->node->client->window);
110             stack_insert_before(oldest_floating, n);
111         }
112     }
113 }
114
115 void stack_under(node_t *n)
116 {
117     PRINTF("stack under %X\n", n->client->window);
118
119     if (stack_head == NULL) {
120         stack_insert_after(NULL, n);
121     } else if (n->client->fullscreen) {
122         ;
123     } else {
124         if (n->client->floating && !auto_raise)
125             return;
126         stack_t *latest_tiled = NULL;
127         stack_t *oldest_floating = NULL;
128         for (stack_t *s = stack_head; s != NULL; s = s->next) {
129             if (s->node != n) {
130                 if (s->node->client->floating == n->client->floating) {
131                     stack_insert_before(s, n);
132                     window_below(n->client->window, s->node->client->window);
133                     return;
134                 } else if (!s->node->client->floating) {
135                     latest_tiled = s;
136                 } else if (oldest_floating == NULL && s->node->client->floating) {
137                     oldest_floating = s;
138                 }
139             }
140         }
141         if (latest_tiled == NULL && oldest_floating == NULL)
142             return;
143         if (n->client->floating) {
144             window_above(n->client->window, latest_tiled->node->client->window);
145             stack_insert_after(latest_tiled, n);
146         } else {
147             window_below(n->client->window, oldest_floating->node->client->window);
148             stack_insert_before(oldest_floating, n);
149         }
150     }
151 }