]> git.lizzy.rs Git - bspwm.git/blob - history.c
Set proper socket option to allow fast restart
[bspwm.git] / history.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 "query.h"
28
29 history_t *make_history(monitor_t *m, desktop_t *d, node_t *n)
30 {
31     history_t *h = malloc(sizeof(history_t));
32     h->loc = (coordinates_t) {m, d, n};
33     h->prev = h->next = NULL;
34     h->latest = true;
35     return h;
36 }
37
38 void history_add(monitor_t *m, desktop_t *d, node_t *n)
39 {
40     if (!record_history)
41         return;
42     history_needle = NULL;
43     history_t *h = make_history(m, d, n);
44     if (history_head == NULL) {
45         history_head = history_tail = h;
46     } else if ((n != NULL && history_tail->loc.node != n) || (n == NULL && d != history_tail->loc.desktop)) {
47         for (history_t *hh = history_tail; hh != NULL; hh = hh->prev)
48             if ((n != NULL && hh->loc.node == n) || (n == NULL && d == hh->loc.desktop))
49                 hh->latest = false;
50         history_tail->next = h;
51         h->prev = history_tail;
52         history_tail = h;
53     } else {
54         free(h);
55     }
56 }
57
58 void history_transfer_node(monitor_t *m, desktop_t *d, node_t *n)
59 {
60     for (history_t *h = history_head; h != NULL; h = h->next)
61         if (h->loc.node == n) {
62             h->loc.monitor = m;
63             h->loc.desktop = d;
64         }
65 }
66
67 void history_transfer_desktop(monitor_t *m, desktop_t *d)
68 {
69     for (history_t *h = history_head; h != NULL; h = h->next)
70         if (h->loc.desktop == d)
71             h->loc.monitor = m;
72 }
73
74 void history_swap_nodes(monitor_t *m1, desktop_t *d1, node_t *n1, monitor_t *m2, desktop_t *d2, node_t *n2)
75 {
76     for (history_t *h = history_head; h != NULL; h = h->next)
77         if (h->loc.node == n1) {
78             h->loc.monitor = m2;
79             h->loc.desktop = d2;
80         } else if (h->loc.node == n2) {
81             h->loc.monitor = m1;
82             h->loc.desktop = d1;
83         }
84 }
85
86 void history_swap_desktops(monitor_t *m1, desktop_t *d1, monitor_t *m2, desktop_t *d2)
87 {
88     for (history_t *h = history_head; h != NULL; h = h->next)
89         if (h->loc.desktop == d1)
90             h->loc.monitor = m2;
91         else if (h->loc.desktop == d2)
92             h->loc.monitor = m1;
93 }
94
95 void history_remove(desktop_t *d, node_t *n)
96 {
97    /* removing from the newest to the oldest is required */
98    /* for maintaining the *latest* attribute */
99     history_t *b = history_tail;
100     while (b != NULL) {
101         if ((n != NULL && n == b->loc.node) || (n == NULL && d == b->loc.desktop)) {
102             history_t *a = b->next;
103             history_t *c = b->prev;
104             if (a != NULL) {
105                 /* remove duplicate entries */
106                 while (c != NULL && ((a->loc.node != NULL && a->loc.node == c->loc.node)
107                             || (a->loc.node == NULL && a->loc.desktop == c->loc.desktop))) {
108                     history_t *d = c->prev;
109                     if (history_head == c)
110                         history_head = history_tail;
111                     if (history_needle == c)
112                         history_needle = history_tail;
113                     free(c);
114                     c = d;
115                 }
116                 a->prev = c;
117             }
118             if (c != NULL)
119                 c->next = a;
120             if (history_tail == b)
121                 history_tail = c;
122             if (history_head == b)
123                 history_head = a;
124             if (history_needle == b)
125                 history_needle = c;
126             free(b);
127             b = c;
128         } else {
129             b = b->prev;
130         }
131     }
132 }
133
134 void empty_history(void)
135 {
136     history_t *h = history_head;
137     while (h != NULL) {
138         history_t *next = h->next;
139         free(h);
140         h = next;
141     }
142     history_head = history_tail = NULL;
143 }
144
145 node_t *history_get_node(desktop_t *d, node_t *n)
146 {
147     for (history_t *h = history_tail; h != NULL; h = h->prev)
148         if (h->latest && h->loc.node != NULL && h->loc.node != n && h->loc.desktop == d)
149             return h->loc.node;
150     return NULL;
151 }
152
153 desktop_t *history_get_desktop(monitor_t *m, desktop_t *d)
154 {
155     for (history_t *h = history_tail; h != NULL; h = h->prev)
156         if (h->latest && h->loc.desktop != d && h->loc.monitor == m)
157             return h->loc.desktop;
158     return NULL;
159 }
160
161 monitor_t *history_get_monitor(monitor_t *m)
162 {
163     for (history_t *h = history_tail; h != NULL; h = h->prev)
164         if (h->latest && h->loc.monitor != m)
165             return h->loc.monitor;
166     return NULL;
167 }
168
169 bool history_find_node(history_dir_t hdi, coordinates_t *ref, coordinates_t *dst, client_select_t sel)
170 {
171     if (history_needle == NULL || record_history)
172         history_needle = history_tail;
173
174     history_t *h;
175     for (h = history_needle; h != NULL; h = (hdi == HISTORY_OLDER ? h->prev : h->next)) {
176         if (!h->latest
177                 || h->loc.node == NULL
178                 || h->loc.node == ref->node
179                 || !node_matches(&h->loc, ref, sel))
180             continue;
181         if (!record_history)
182             history_needle = h;
183         *dst = h->loc;
184         return true;
185     }
186     return false;
187 }
188
189 bool history_find_desktop(history_dir_t hdi, coordinates_t *ref, coordinates_t *dst, desktop_select_t sel)
190 {
191     if (history_needle == NULL || record_history)
192         history_needle = history_tail;
193
194     history_t *h;
195     for (h = history_needle; h != NULL; h = (hdi == HISTORY_OLDER ? h->prev : h->next)) {
196         if (!h->latest
197                 || h->loc.desktop == ref->desktop
198                 || !desktop_matches(&h->loc, ref, sel))
199             continue;
200         if (!record_history)
201             history_needle = h;
202         *dst = h->loc;
203         return true;
204     }
205     return false;
206 }
207
208 bool history_find_monitor(history_dir_t hdi, coordinates_t *ref, coordinates_t *dst, desktop_select_t sel)
209 {
210     if (history_needle == NULL || record_history)
211         history_needle = history_tail;
212
213     history_t *h;
214     for (h = history_needle; h != NULL; h = (hdi == HISTORY_OLDER ? h->prev : h->next)) {
215         if (!h->latest
216                 || h->loc.monitor == ref->monitor
217                 || !desktop_matches(&h->loc, ref, sel))
218             continue;
219         if (!record_history)
220             history_needle = h;
221         *dst = h->loc;
222         return true;
223     }
224     return false;
225 }
226
227 int history_rank(desktop_t *d, node_t *n)
228 {
229     int i = 0;
230     history_t *h = history_tail;
231     while (h != NULL && (!h->latest || h->loc.node != n || h->loc.desktop != d)) {
232         h = h->prev;
233         i++;
234     }
235     if (h == NULL)
236         return -1;
237     else
238         return i;
239 }