]> git.lizzy.rs Git - bspwm.git/blob - rule.c
Set proper socket option to allow fast restart
[bspwm.git] / rule.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 <stdio.h>
26 #include <string.h>
27 #include <unistd.h>
28 #include "bspwm.h"
29 #include "ewmh.h"
30 #include "window.h"
31 #include "messages.h"
32 #include "settings.h"
33 #include "query.h"
34 #include "rule.h"
35
36 rule_consequence_t *make_rule_conquence(void)
37 {
38     rule_consequence_t *rc = calloc(1, sizeof(rule_consequence_t));
39     rc->manage = rc->focus = true;
40     return rc;
41 }
42
43 pending_rule_t *make_pending_rule(int fd, xcb_window_t win, rule_consequence_t *csq)
44 {
45     pending_rule_t *pr = malloc(sizeof(pending_rule_t));
46     pr->prev = pr->next = NULL;
47     pr->fd = fd;
48     pr->win = win;
49     pr->csq = csq;
50     return pr;
51 }
52
53 void add_pending_rule(pending_rule_t *pr)
54 {
55     if (pr == NULL)
56         return;
57     PRINTF("add pending rule %i\n", pr->fd);
58     if (pending_rule_head == NULL) {
59         pending_rule_head = pending_rule_tail = pr;
60     } else {
61         pending_rule_tail->next = pr;
62         pr->prev = pending_rule_tail;
63         pending_rule_tail = pr;
64     }
65 }
66
67 void remove_pending_rule(pending_rule_t *pr)
68 {
69     if (pr == NULL)
70         return;
71     PRINTF("remove pending rule %i\n", pr->fd);
72     pending_rule_t *a = pr->prev;
73     pending_rule_t *b = pr->next;
74     if (a != NULL)
75         a->next = b;
76     if (b != NULL)
77         b->prev = a;
78     if (pr == pending_rule_head)
79         pending_rule_head = b;
80     if (pr == pending_rule_tail)
81         pending_rule_tail = a;
82     close(pr->fd);
83     free(pr->csq);
84     free(pr);
85 }
86
87 void apply_rules(xcb_window_t win, rule_consequence_t *csq)
88 {
89     xcb_ewmh_get_atoms_reply_t win_type;
90
91     if (xcb_ewmh_get_wm_window_type_reply(ewmh, xcb_ewmh_get_wm_window_type(ewmh, win), &win_type, NULL) == 1) {
92         for (unsigned int i = 0; i < win_type.atoms_len; i++) {
93             xcb_atom_t a = win_type.atoms[i];
94             if (a == ewmh->_NET_WM_WINDOW_TYPE_TOOLBAR
95                     || a == ewmh->_NET_WM_WINDOW_TYPE_UTILITY) {
96                 csq->focus = false;
97             } else if (a == ewmh->_NET_WM_WINDOW_TYPE_DIALOG) {
98                 csq->floating = true;
99             } else if (a == ewmh->_NET_WM_WINDOW_TYPE_DOCK || a == ewmh->_NET_WM_WINDOW_TYPE_DESKTOP || a == ewmh->_NET_WM_WINDOW_TYPE_NOTIFICATION) {
100                 csq->manage = false;
101                 if (a == ewmh->_NET_WM_WINDOW_TYPE_DESKTOP)
102                     window_lower(win);
103             }
104         }
105         xcb_ewmh_get_atoms_reply_wipe(&win_type);
106     }
107
108     xcb_ewmh_get_atoms_reply_t win_state;
109
110     if (xcb_ewmh_get_wm_state_reply(ewmh, xcb_ewmh_get_wm_state(ewmh, win), &win_state, NULL) == 1) {
111         for (unsigned int i = 0; i < win_state.atoms_len; i++) {
112             xcb_atom_t a = win_state.atoms[i];
113             if (a == ewmh->_NET_WM_STATE_FULLSCREEN)
114                 csq->fullscreen = true;
115             else if (a == ewmh->_NET_WM_STATE_STICKY)
116                 csq->sticky = true;
117         }
118         xcb_ewmh_get_atoms_reply_wipe(&win_state);
119     }
120
121     xcb_size_hints_t size_hints;
122     if (xcb_icccm_get_wm_normal_hints_reply(dpy, xcb_icccm_get_wm_normal_hints(dpy, win), &size_hints, NULL) == 1) {
123         if (size_hints.min_width > 0 && size_hints.min_height > 0
124                 && size_hints.min_width == size_hints.max_width
125                 && size_hints.min_height == size_hints.max_height)
126             csq->floating = true;
127     }
128
129     xcb_window_t transient_for = XCB_NONE;
130     xcb_icccm_get_wm_transient_for_reply(dpy, xcb_icccm_get_wm_transient_for(dpy, win), &transient_for, NULL);
131     if (transient_for != XCB_NONE)
132         csq->transient = csq->floating = true;
133 }
134
135 bool schedule_rules(xcb_window_t win, rule_consequence_t *csq)
136 {
137     int fds[2];
138     if (pipe(fds) == -1)
139         return false;
140     pid_t pid = fork();
141     if (pid == 0) {
142         if (dpy != NULL)
143             close(xcb_get_file_descriptor(dpy));
144         dup2(fds[1], 1);
145         close(fds[0]);
146         char wid[SMALEN];
147         snprintf(wid, sizeof(wid), "%i", win);
148         setsid();
149         execl(rule_command, rule_command, wid, NULL);
150         err("Couldn't spawn rule command.\n");
151     } else if (pid > 0) {
152         close(fds[1]);
153         pending_rule_t *pr = make_pending_rule(fds[0], win, csq);
154         add_pending_rule(pr);
155     }
156     return (pid != -1);
157 }
158
159 void parse_rule_consequence(int fd, rule_consequence_t *csq, monitor_t **m, desktop_t **d)
160 {
161     if (fd == -1)
162         return;
163     char data[BUFSIZ];
164     int nb;
165     bool v;
166     while ((nb = read(fd, data, sizeof(data))) > 0) {
167         int end = MIN(nb, (int) sizeof(data) - 1);
168         data[end] = '\0';
169         char *key = strtok(data, CSQ_BLK);
170         char *value = strtok(NULL, CSQ_BLK);
171         while (key != NULL && value != NULL) {
172             PRINTF("%s = %s\n", key, value);
173             if (streq("desktop", key)) {
174                 coordinates_t ref = {mon, mon->desk, NULL};
175                 coordinates_t trg = {NULL, NULL, NULL};
176                 if (desktop_from_desc(value, &ref, &trg)) {
177                     *m = trg.monitor;
178                     *d = trg.desktop;
179                 }
180             } else if (streq("monitor", key)) {
181                 coordinates_t ref = {mon, NULL, NULL};
182                 coordinates_t trg = {NULL, NULL, NULL};
183                 if (monitor_from_desc(value, &ref, &trg)) {
184                     *m = trg.monitor;
185                     *d = trg.monitor->desk;
186                 }
187             } else if (parse_bool(value, &v)) {
188                 if (streq("floating", key))
189                     csq->floating = v;
190 #define SETCSQ(name) \
191                 else if (streq(#name, key)) \
192                     csq->name = v;
193                 SETCSQ(fullscreen)
194                 SETCSQ(locked)
195                 SETCSQ(sticky)
196                 SETCSQ(private)
197                 SETCSQ(frame)
198                 SETCSQ(center)
199                 SETCSQ(lower)
200                 SETCSQ(follow)
201                 SETCSQ(manage)
202                 SETCSQ(focus)
203 #undef SETCSQ
204
205             }
206             key = strtok(NULL, CSQ_BLK);
207             value = strtok(NULL, CSQ_BLK);
208         }
209     }
210     if (csq->sticky) {
211         *m = mon;
212         *d = mon->desk;
213     }
214 }