]> git.lizzy.rs Git - bspwm.git/blob - ewmh.c
Handle _NET_WM_STATE more carefully
[bspwm.git] / ewmh.c
1 #include <string.h>
2 #include <unistd.h>
3 #include "bspwm.h"
4 #include "settings.h"
5 #include "tree.h"
6 #include "ewmh.h"
7
8 void ewmh_init(void)
9 {
10     ewmh = malloc(sizeof(xcb_ewmh_connection_t));
11     if (xcb_ewmh_init_atoms_replies(ewmh, xcb_ewmh_init_atoms(dpy, ewmh), NULL) == 0)
12         err("Can't initialize EWMH atoms.\n");
13 }
14
15 void ewmh_update_active_window(void)
16 {
17     xcb_window_t win = (mon->desk->focus == NULL ? XCB_NONE : mon->desk->focus->client->window);
18     xcb_ewmh_set_active_window(ewmh, default_screen, win);
19 }
20
21 void ewmh_update_number_of_desktops(void)
22 {
23     xcb_ewmh_set_number_of_desktops(ewmh, default_screen, num_desktops);
24 }
25
26 uint32_t ewmh_get_desktop_index(desktop_t *d)
27 {
28     uint32_t i = 0;
29     for (monitor_t *m = mon_head; m != NULL; m = m->next)
30         for (desktop_t *cd = m->desk_head; cd != NULL; cd = cd->next, i++)
31             if (d == cd)
32                 return i;
33     return 0;
34 }
35
36 bool ewmh_locate_desktop(uint32_t i, coordinates_t *loc)
37 {
38     for (monitor_t *m = mon_head; m != NULL; m = m->next)
39         for (desktop_t *d = m->desk_head; d != NULL; d = d->next, i--)
40             if (i == 0) {
41                 loc->monitor = m;
42                 loc->desktop = d;
43                 loc->node = NULL;
44                 return true;
45             }
46     return false;
47 }
48
49 void ewmh_update_current_desktop(void)
50 {
51     uint32_t i = ewmh_get_desktop_index(mon->desk);
52     xcb_ewmh_set_current_desktop(ewmh, default_screen, i);
53 }
54
55 void ewmh_set_wm_desktop(node_t *n, desktop_t *d)
56 {
57     uint32_t i = ewmh_get_desktop_index(d);
58     xcb_ewmh_set_wm_desktop(ewmh, n->client->window, i);
59 }
60
61 void ewmh_update_wm_desktops(void)
62 {
63     for (monitor_t *m = mon_head; m != NULL; m = m->next)
64         for (desktop_t *d = m->desk_head; d != NULL; d = d->next) {
65             uint32_t i = ewmh_get_desktop_index(d);
66             for (node_t *n = first_extrema(d->root); n != NULL; n = next_leaf(n, d->root))
67                 xcb_ewmh_set_wm_desktop(ewmh, n->client->window, i);
68         }
69 }
70
71 void ewmh_update_desktop_names(void)
72 {
73     char names[MAXLEN];
74     unsigned int i, j;
75     uint32_t names_len;
76     i = 0;
77
78     for (monitor_t *m = mon_head; m != NULL; m = m->next)
79         for (desktop_t *d = m->desk_head; d != NULL; d = d->next) {
80             for (j = 0; d->name[j] != '\0' && (i + j) < sizeof(names); j++)
81                 names[i + j] = d->name[j];
82             i += j;
83             if (i < sizeof(names))
84                 names[i++] = '\0';
85         }
86
87     if (i < 1)
88         return;
89
90     names_len = i - 1;
91     xcb_ewmh_set_desktop_names(ewmh, default_screen, names_len, names);
92 }
93
94 void ewmh_update_client_list(void)
95 {
96     if (num_clients == 0) {
97         xcb_ewmh_set_client_list(ewmh, default_screen, 0, NULL);
98         xcb_ewmh_set_client_list_stacking(ewmh, default_screen, 0, NULL);
99         return;
100     }
101
102     xcb_window_t wins[num_clients];
103     unsigned int i = 0;
104
105     for (monitor_t *m = mon_head; m != NULL; m = m->next)
106         for (desktop_t *d = m->desk_head; d != NULL; d = d->next)
107             for (node_t *n = first_extrema(d->root); n != NULL; n = next_leaf(n, d->root))
108                 wins[i++] = n->client->window;
109
110     xcb_ewmh_set_client_list(ewmh, default_screen, num_clients, wins);
111     xcb_ewmh_set_client_list_stacking(ewmh, default_screen, num_clients, wins);
112 }
113
114 bool ewmh_wm_state_add(client_t *c, xcb_atom_t state)
115 {
116     if (c->num_states >= MAX_STATE)
117         return false;
118     for (int i = 0; i < c->num_states; i++)
119         if (c->wm_state[i] == state)
120             return false;
121     c->wm_state[c->num_states] = state;
122     c->num_states++;
123     xcb_ewmh_set_wm_state(ewmh, c->window, c->num_states, c->wm_state);
124     return true;
125 }
126
127 bool ewmh_wm_state_remove(client_t *c, xcb_atom_t state)
128 {
129     for (int i = 0; i < c->num_states; i++)
130         if (c->wm_state[i] == state)
131         {
132             for (int j = i; j < (c->num_states - 1); j++)
133                 c->wm_state[j] = c->wm_state[j + 1];
134             c->num_states--;
135             xcb_ewmh_set_wm_state(ewmh, c->window, c->num_states, c->wm_state);
136             return true;
137         }
138     return false;
139 }
140
141 void ewmh_set_supporting(xcb_window_t win)
142 {
143     pid_t wm_pid = getpid();
144     xcb_ewmh_set_supporting_wm_check(ewmh, root, win);
145     xcb_ewmh_set_supporting_wm_check(ewmh, win, win);
146     xcb_ewmh_set_wm_name(ewmh, win, strlen(WM_NAME), WM_NAME);
147     xcb_ewmh_set_wm_pid(ewmh, win, wm_pid);
148 }