]> git.lizzy.rs Git - bspwm.git/blob - history.c
Implement sticky windows
[bspwm.git] / history.c
1 #include <stdlib.h>
2 #include "bspwm.h"
3 #include "query.h"
4
5 history_t *make_history(monitor_t *m, desktop_t *d, node_t *n)
6 {
7     history_t *h = malloc(sizeof(history_t));
8     h->loc = (coordinates_t) {m, d, n};
9     h->prev = h->next = NULL;
10     h->latest = true;
11     return h;
12 }
13
14 void history_add(monitor_t *m, desktop_t *d, node_t *n)
15 {
16     history_t *h = make_history(m, d, n);
17     if (history_head == NULL) {
18         history_head = history_tail = h;
19     } else if ((n != NULL && history_tail->loc.node != n) || (n == NULL && d != history_tail->loc.desktop)) {
20         for (history_t *hh = history_tail; hh != NULL; hh = hh->prev)
21             if ((n != NULL && hh->loc.node == n) || (n == NULL && d == hh->loc.desktop))
22                 hh->latest = false;
23         history_tail->next = h;
24         h->prev = history_tail;
25         history_tail = h;
26     } else {
27         free(h);
28     }
29 }
30
31 void history_transfer_node(monitor_t *m, desktop_t *d, node_t *n)
32 {
33     for (history_t *h = history_head; h != NULL; h = h->next)
34         if (h->loc.node == n) {
35             h->loc.monitor = m;
36             h->loc.desktop = d;
37         }
38 }
39
40 void history_transfer_desktop(monitor_t *m, desktop_t *d)
41 {
42     for (history_t *h = history_head; h != NULL; h = h->next)
43         if (h->loc.desktop == d)
44             h->loc.monitor = m;
45 }
46
47 void history_swap_nodes(monitor_t *m1, desktop_t *d1, node_t *n1, monitor_t *m2, desktop_t *d2, node_t *n2)
48 {
49     for (history_t *h = history_head; h != NULL; h = h->next)
50         if (h->loc.node == n1) {
51             h->loc.monitor = m2;
52             h->loc.desktop = d2;
53         } else if (h->loc.node == n2) {
54             h->loc.monitor = m1;
55             h->loc.desktop = d1;
56         }
57 }
58
59 void history_swap_desktops(monitor_t *m1, desktop_t *d1, monitor_t *m2, desktop_t *d2)
60 {
61     for (history_t *h = history_head; h != NULL; h = h->next)
62         if (h->loc.desktop == d1)
63             h->loc.monitor = m2;
64         else if (h->loc.desktop == d2)
65             h->loc.monitor = m1;
66 }
67
68 void history_remove(desktop_t *d, node_t *n)
69 {
70    /* removing from the newest to the oldest is required */
71    /* for maintaining the *latest* attribute */
72     history_t *b = history_tail;
73     while (b != NULL) {
74         if ((n != NULL && n == b->loc.node) || (n == NULL && d == b->loc.desktop)) {
75             history_t *a = b->next;
76             history_t *c = b->prev;
77             if (a != NULL) {
78                 /* remove duplicate entries */
79                 while (c != NULL && ((a->loc.node != NULL && a->loc.node == c->loc.node)
80                             || (a->loc.node == NULL && a->loc.desktop == c->loc.desktop))) {
81                     history_t *d = c->prev;
82                     if (history_head == c)
83                         history_head = history_tail;
84                     free(c);
85                     c = d;
86                 }
87                 a->prev = c;
88             }
89             if (c != NULL)
90                 c->next = a;
91             if (history_tail == b)
92                 history_tail = c;
93             if (history_head == b)
94                 history_head = a;
95             free(b);
96             b = c;
97         } else {
98             b = b->prev;
99         }
100     }
101 }
102
103 void empty_history(void)
104 {
105     history_t *h = history_head;
106     while (h != NULL) {
107         history_t *next = h->next;
108         free(h);
109         h = next;
110     }
111     history_head = history_tail = NULL;
112 }
113
114 node_t *history_get_node(desktop_t *d, node_t *n)
115 {
116     for (history_t *h = history_tail; h != NULL; h = h->prev)
117         if (h->latest && h->loc.node != NULL && h->loc.node != n && h->loc.desktop == d)
118             return h->loc.node;
119     return NULL;
120 }
121
122 desktop_t *history_get_desktop(monitor_t *m, desktop_t *d)
123 {
124     for (history_t *h = history_tail; h != NULL; h = h->prev)
125         if (h->latest && h->loc.desktop != d && h->loc.monitor == m)
126             return h->loc.desktop;
127     return NULL;
128 }
129
130 monitor_t *history_get_monitor(monitor_t *m)
131 {
132     for (history_t *h = history_tail; h != NULL; h = h->prev)
133         if (h->latest && h->loc.monitor != m)
134             return h->loc.monitor;
135     return NULL;
136 }
137
138 bool history_last_node(node_t *n, client_select_t sel, coordinates_t *loc)
139 {
140     for (history_t *h = history_tail; h != NULL; h = h->prev) {
141         if (!h->latest || h->loc.node == NULL || h->loc.node == n || !node_matches(n, h->loc.node, sel))
142             continue;
143         *loc = h->loc;
144         return true;
145     }
146     return false;
147 }
148
149 bool history_last_desktop(desktop_t *d, desktop_select_t sel, coordinates_t *loc)
150 {
151     for (history_t *h = history_tail; h != NULL; h = h->prev) {
152         if (!h->latest || h->loc.desktop == d || !desktop_matches(h->loc.desktop, sel))
153             continue;
154         *loc = h->loc;
155         return true;
156     }
157     return false;
158 }
159
160 bool history_last_monitor(monitor_t *m, desktop_select_t sel, coordinates_t *loc)
161 {
162     for (history_t *h = history_tail; h != NULL; h = h->prev) {
163         if (!h->latest || h->loc.monitor == m || !desktop_matches(h->loc.monitor->desk, sel))
164             continue;
165         *loc = h->loc;
166         return true;
167     }
168     return false;
169 }
170
171 int history_rank(desktop_t *d, node_t *n)
172 {
173     int i = 0;
174     history_t *h = history_tail;
175     while (h != NULL && (!h->latest || h->loc.node != n || h->loc.desktop != d)) {
176         h = h->prev;
177         i++;
178     }
179     if (h == NULL)
180         return -1;
181     else
182         return i;
183 }