]> git.lizzy.rs Git - bspwm.git/blob - ewmh.c
Version 0.9
[bspwm.git] / ewmh.c
1 /* Copyright (c) 2012, Bastien Dejean
2  * All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are met:
6  *
7  * 1. Redistributions of source code must retain the above copyright notice, this
8  *    list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright notice,
10  *    this list of conditions and the following disclaimer in the documentation
11  *    and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
14  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
15  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
16  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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
20  * ON 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 <string.h>
26 #include <unistd.h>
27 #include "bspwm.h"
28 #include "settings.h"
29 #include "tree.h"
30 #include "ewmh.h"
31
32 void ewmh_init(void)
33 {
34         ewmh = malloc(sizeof(xcb_ewmh_connection_t));
35         if (xcb_ewmh_init_atoms_replies(ewmh, xcb_ewmh_init_atoms(dpy, ewmh), NULL) == 0)
36                 err("Can't initialize EWMH atoms.\n");
37 }
38
39 void ewmh_update_active_window(void)
40 {
41         xcb_window_t win = (mon->desk->focus == NULL ? XCB_NONE : mon->desk->focus->client->window);
42         xcb_ewmh_set_active_window(ewmh, default_screen, win);
43 }
44
45 void ewmh_update_number_of_desktops(void)
46 {
47         xcb_ewmh_set_number_of_desktops(ewmh, default_screen, num_desktops);
48 }
49
50 uint32_t ewmh_get_desktop_index(desktop_t *d)
51 {
52         uint32_t i = 0;
53         for (monitor_t *m = mon_head; m != NULL; m = m->next)
54                 for (desktop_t *cd = m->desk_head; cd != NULL; cd = cd->next, i++)
55                         if (d == cd)
56                                 return i;
57         return 0;
58 }
59
60 bool ewmh_locate_desktop(uint32_t i, coordinates_t *loc)
61 {
62         for (monitor_t *m = mon_head; m != NULL; m = m->next)
63                 for (desktop_t *d = m->desk_head; d != NULL; d = d->next, i--)
64                         if (i == 0) {
65                                 loc->monitor = m;
66                                 loc->desktop = d;
67                                 loc->node = NULL;
68                                 return true;
69                         }
70         return false;
71 }
72
73 void ewmh_update_current_desktop(void)
74 {
75         uint32_t i = ewmh_get_desktop_index(mon->desk);
76         xcb_ewmh_set_current_desktop(ewmh, default_screen, i);
77 }
78
79 void ewmh_set_wm_desktop(node_t *n, desktop_t *d)
80 {
81         uint32_t i = ewmh_get_desktop_index(d);
82         xcb_ewmh_set_wm_desktop(ewmh, n->client->window, i);
83 }
84
85 void ewmh_update_wm_desktops(void)
86 {
87         for (monitor_t *m = mon_head; m != NULL; m = m->next)
88                 for (desktop_t *d = m->desk_head; d != NULL; d = d->next) {
89                         uint32_t i = ewmh_get_desktop_index(d);
90                         for (node_t *n = first_extrema(d->root); n != NULL; n = next_leaf(n, d->root))
91                                 xcb_ewmh_set_wm_desktop(ewmh, n->client->window, i);
92                 }
93 }
94
95 void ewmh_update_desktop_names(void)
96 {
97         char names[MAXLEN];
98         unsigned int i, j;
99         uint32_t names_len;
100         i = 0;
101
102         for (monitor_t *m = mon_head; m != NULL; m = m->next)
103                 for (desktop_t *d = m->desk_head; d != NULL; d = d->next) {
104                         for (j = 0; d->name[j] != '\0' && (i + j) < sizeof(names); j++)
105                                 names[i + j] = d->name[j];
106                         i += j;
107                         if (i < sizeof(names))
108                                 names[i++] = '\0';
109                 }
110
111         if (i < 1)
112                 return;
113
114         names_len = i - 1;
115         xcb_ewmh_set_desktop_names(ewmh, default_screen, names_len, names);
116 }
117
118 void ewmh_update_client_list(void)
119 {
120         if (num_clients == 0) {
121                 xcb_ewmh_set_client_list(ewmh, default_screen, 0, NULL);
122                 xcb_ewmh_set_client_list_stacking(ewmh, default_screen, 0, NULL);
123                 return;
124         }
125
126         xcb_window_t wins[num_clients];
127         unsigned int i = 0;
128
129         for (monitor_t *m = mon_head; m != NULL; m = m->next)
130                 for (desktop_t *d = m->desk_head; d != NULL; d = d->next)
131                         for (node_t *n = first_extrema(d->root); n != NULL; n = next_leaf(n, d->root))
132                                 wins[i++] = n->client->window;
133
134         xcb_ewmh_set_client_list(ewmh, default_screen, num_clients, wins);
135         xcb_ewmh_set_client_list_stacking(ewmh, default_screen, num_clients, wins);
136 }
137
138 bool ewmh_wm_state_add(client_t *c, xcb_atom_t state)
139 {
140         if (c->num_states >= MAX_STATE)
141                 return false;
142         for (int i = 0; i < c->num_states; i++)
143                 if (c->wm_state[i] == state)
144                         return false;
145         c->wm_state[c->num_states] = state;
146         c->num_states++;
147         xcb_ewmh_set_wm_state(ewmh, c->window, c->num_states, c->wm_state);
148         return true;
149 }
150
151 bool ewmh_wm_state_remove(client_t *c, xcb_atom_t state)
152 {
153         for (int i = 0; i < c->num_states; i++)
154                 if (c->wm_state[i] == state)
155                 {
156                         for (int j = i; j < (c->num_states - 1); j++)
157                                 c->wm_state[j] = c->wm_state[j + 1];
158                         c->num_states--;
159                         xcb_ewmh_set_wm_state(ewmh, c->window, c->num_states, c->wm_state);
160                         return true;
161                 }
162         return false;
163 }
164
165 void ewmh_set_supporting(xcb_window_t win)
166 {
167         pid_t wm_pid = getpid();
168         xcb_ewmh_set_supporting_wm_check(ewmh, root, win);
169         xcb_ewmh_set_supporting_wm_check(ewmh, win, win);
170         xcb_ewmh_set_wm_name(ewmh, win, strlen(WM_NAME), WM_NAME);
171         xcb_ewmh_set_wm_pid(ewmh, win, wm_pid);
172 }