]> git.lizzy.rs Git - bspwm.git/blob - events.c
Fix desktop_cyle, try to handle unmap_notify
[bspwm.git] / events.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <xcb/xcb.h>
4 #include <xcb/xcb_icccm.h>
5 #include <xcb/xcb_event.h>
6 #include "helpers.h"
7 #include "types.h"
8 #include "bspwm.h"
9 #include "settings.h"
10 #include "utils.h"
11 #include "window.h"
12 #include "events.h"
13 #include "tree.h"
14 #include "rules.h"
15 #include "ewmh.h"
16
17 void handle_event(xcb_generic_event_t *evt)
18 {
19     switch (XCB_EVENT_RESPONSE_TYPE(evt)) {
20         case XCB_MAP_REQUEST:
21             map_request(evt);
22             break;
23         case XCB_DESTROY_NOTIFY:
24             destroy_notify(evt);
25             break;
26         case XCB_UNMAP_NOTIFY:
27             unmap_notify(evt);
28             break;
29         case XCB_CLIENT_MESSAGE:
30             client_message(evt);
31             break;
32         case XCB_CONFIGURE_REQUEST:
33             configure_request(evt);
34             break;
35         case XCB_BUTTON_PRESS:
36             PUTS("button press");
37             break;
38         default:
39             /* PRINTF("received event %i\n", XCB_EVENT_RESPONSE_TYPE(evt)); */
40             break;
41     }
42 }
43
44 void map_request(xcb_generic_event_t *evt)
45 {
46     xcb_map_request_event_t *e = (xcb_map_request_event_t *) evt;
47
48     PRINTF("map request %X\n", e->window);
49
50     xcb_get_window_attributes_reply_t  *wa;
51     xcb_window_t win = e->window;
52     window_location_t loc;
53     wa = xcb_get_window_attributes_reply(dpy, xcb_get_window_attributes(dpy, win), NULL);
54
55     if ((wa != NULL && wa->override_redirect) || locate_window(win, &loc))
56         return;
57
58     free(wa);
59
60     client_t *c = make_client(win);
61
62     xcb_get_geometry_reply_t *geom = xcb_get_geometry_reply(dpy, xcb_get_geometry(dpy, win), NULL);
63
64     if (geom) {
65         c->rectangle = (xcb_rectangle_t) {geom->x, geom->y, geom->width, geom->height};
66         free(geom);
67     } else {
68         c->rectangle = (xcb_rectangle_t) {0, 0, 320, 240};
69     }
70
71     bool floating = false, transient = false, fullscreen = false, takes_focus = true;
72
73     handle_rules(win, &floating, &transient, &fullscreen, &takes_focus);
74
75     if (c->transient)
76         floating = true;
77
78     node_t *birth = make_node();
79     birth->client = c;
80     insert_node(desk, birth);
81
82     if (floating)
83         toggle_floating(birth);
84
85     if (desk->focus != NULL && desk->focus->client->fullscreen)
86         toggle_fullscreen(desk->focus->client);
87
88     if (fullscreen)
89         toggle_fullscreen(birth->client);
90
91     c->transient = transient;
92
93     if (takes_focus)
94         focus_node(desk, birth, false);
95
96     apply_layout(desk, desk->root, root_rect);
97
98     xcb_map_window(dpy, c->window);
99
100     if (takes_focus)
101         xcb_set_input_focus(dpy, XCB_INPUT_FOCUS_POINTER_ROOT, win, XCB_CURRENT_TIME);
102
103     num_clients++;
104     ewmh_update_client_list();
105 }
106
107 void configure_request(xcb_generic_event_t *evt)
108 {
109     xcb_configure_request_event_t *e = (xcb_configure_request_event_t *) evt;
110
111     PRINTF("configure request %X\n", e->window);
112
113     window_location_t loc;
114     bool is_managed = locate_window(e->window, &loc);
115
116     if (!is_managed || is_floating(loc.node->client)) {
117         uint16_t mask = 0;
118         uint32_t values[7];
119         unsigned short i = 0;
120
121         if (e->value_mask & XCB_CONFIG_WINDOW_X) {
122             mask |= XCB_CONFIG_WINDOW_X;
123             values[i++] = e->x;
124             if (is_managed)
125                 loc.node->client->rectangle.x = e->x;
126         }
127
128         if (e->value_mask & XCB_CONFIG_WINDOW_Y) {
129             mask |= XCB_CONFIG_WINDOW_Y;
130             values[i++] = e->y;
131             if (is_managed)
132                 loc.node->client->rectangle.y = e->y;
133         }
134
135         if (e->value_mask & XCB_CONFIG_WINDOW_WIDTH) {
136             mask |= XCB_CONFIG_WINDOW_WIDTH;
137             values[i++] = e->width;
138             if (is_managed)
139                 loc.node->client->rectangle.width = e->width;
140         }
141
142         if (e->value_mask & XCB_CONFIG_WINDOW_HEIGHT) {
143             mask |= XCB_CONFIG_WINDOW_HEIGHT;
144             values[i++] = e->height;
145             if (is_managed)
146                 loc.node->client->rectangle.height = e->height;
147         }
148
149         if (!is_managed && e->value_mask & XCB_CONFIG_WINDOW_BORDER_WIDTH) {
150             mask |= XCB_CONFIG_WINDOW_BORDER_WIDTH;
151             values[i++] = e->border_width;
152         }
153
154         if (e->value_mask & XCB_CONFIG_WINDOW_SIBLING) {
155             mask |= XCB_CONFIG_WINDOW_SIBLING;
156             values[i++] = e->sibling;
157         }
158
159         if (e->value_mask & XCB_CONFIG_WINDOW_STACK_MODE) {
160             mask |= XCB_CONFIG_WINDOW_STACK_MODE;
161             values[i++] = e->stack_mode;
162         }
163
164         xcb_configure_window(dpy, e->window, mask, values);
165     }
166
167     if (is_managed && is_floating(loc.node->client))
168         apply_layout(loc.desktop, loc.node, root_rect);
169 }
170
171 void destroy_notify(xcb_generic_event_t *evt)
172 {
173     xcb_destroy_notify_event_t *e = (xcb_destroy_notify_event_t *) evt;
174     window_location_t loc;
175
176     PRINTF("destroy notify %X\n", e->window);
177
178     if (locate_window(e->window, &loc)) {
179         remove_node(loc.desktop, loc.node);
180         apply_layout(loc.desktop, loc.desktop->root, root_rect);
181     }
182 }
183
184 void unmap_notify(xcb_generic_event_t *evt)
185 {
186     xcb_unmap_notify_event_t *e = (xcb_unmap_notify_event_t *) evt;
187
188     PRINTF("unmap notify %X\n", e->window);
189
190     return;
191
192     window_location_t loc;
193     if (locate_window(e->window, &loc) && !loc.node->client->hidden) {
194         remove_node(loc.desktop, loc.node);
195         apply_layout(loc.desktop, loc.desktop->root, root_rect);
196     }
197 }
198
199 void client_message(xcb_generic_event_t *evt)
200 {
201     xcb_client_message_event_t *e = (xcb_client_message_event_t *) evt;
202
203     PRINTF("client message %X\n", e->window);
204
205     window_location_t loc;
206
207     if (!locate_window(e->window, &loc))
208         return;
209
210     if (e->type == ewmh->_NET_WM_STATE) {
211         handle_state(loc.node, e->data.data32[1], e->data.data32[0]);
212         handle_state(loc.node, e->data.data32[2], e->data.data32[0]);
213     } else if (e->type == ewmh->_NET_ACTIVE_WINDOW) {
214         if (desk != loc.desktop)
215             select_desktop(loc.desktop);
216         focus_node(loc.desktop, loc.node, true);
217     }
218 }
219
220 void handle_state(node_t *n, xcb_atom_t state, unsigned int action)
221 {
222     if (state == ewmh->_NET_WM_STATE_FULLSCREEN) {
223         bool fs = n->client->fullscreen;
224         if (action == XCB_EWMH_WM_STATE_TOGGLE
225                 || (fs && action == XCB_EWMH_WM_STATE_REMOVE)
226                 || (!fs && action == XCB_EWMH_WM_STATE_ADD))
227             toggle_fullscreen(n->client);
228     }
229 }