4 #include <xcb/xcb_icccm.h>
5 #include <xcb/xcb_event.h>
17 void handle_event(xcb_generic_event_t *evt)
19 switch (XCB_EVENT_RESPONSE_TYPE(evt)) {
23 case XCB_DESTROY_NOTIFY:
26 case XCB_UNMAP_NOTIFY:
29 case XCB_CLIENT_MESSAGE:
32 case XCB_CONFIGURE_REQUEST:
33 configure_request(evt);
35 case XCB_BUTTON_PRESS:
39 /* PRINTF("received event %i\n", XCB_EVENT_RESPONSE_TYPE(evt)); */
44 void map_request(xcb_generic_event_t *evt)
46 xcb_map_request_event_t *e = (xcb_map_request_event_t *) evt;
48 PRINTF("map request %X\n", e->window);
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);
55 if ((wa != NULL && wa->override_redirect) || locate_window(win, &loc))
60 client_t *c = make_client(win);
62 xcb_get_geometry_reply_t *geom = xcb_get_geometry_reply(dpy, xcb_get_geometry(dpy, win), NULL);
65 c->rectangle = (xcb_rectangle_t) {geom->x, geom->y, geom->width, geom->height};
68 c->rectangle = (xcb_rectangle_t) {0, 0, 320, 240};
71 bool floating = false, transient = false, fullscreen = false, takes_focus = true;
73 handle_rules(win, &floating, &transient, &fullscreen, &takes_focus);
78 node_t *birth = make_node();
80 insert_node(desk, birth);
83 toggle_floating(birth);
85 if (desk->focus != NULL && desk->focus->client->fullscreen)
86 toggle_fullscreen(desk->focus->client);
89 toggle_fullscreen(birth->client);
91 c->transient = transient;
94 focus_node(desk, birth, false);
96 apply_layout(desk, desk->root, root_rect);
98 xcb_map_window(dpy, c->window);
101 xcb_set_input_focus(dpy, XCB_INPUT_FOCUS_POINTER_ROOT, win, XCB_CURRENT_TIME);
104 ewmh_update_client_list();
107 void configure_request(xcb_generic_event_t *evt)
109 xcb_configure_request_event_t *e = (xcb_configure_request_event_t *) evt;
111 PRINTF("configure request %X\n", e->window);
113 window_location_t loc;
114 bool is_managed = locate_window(e->window, &loc);
116 if (!is_managed || is_floating(loc.node->client)) {
119 unsigned short i = 0;
121 if (e->value_mask & XCB_CONFIG_WINDOW_X) {
122 mask |= XCB_CONFIG_WINDOW_X;
125 loc.node->client->rectangle.x = e->x;
128 if (e->value_mask & XCB_CONFIG_WINDOW_Y) {
129 mask |= XCB_CONFIG_WINDOW_Y;
132 loc.node->client->rectangle.y = e->y;
135 if (e->value_mask & XCB_CONFIG_WINDOW_WIDTH) {
136 mask |= XCB_CONFIG_WINDOW_WIDTH;
137 values[i++] = e->width;
139 loc.node->client->rectangle.width = e->width;
142 if (e->value_mask & XCB_CONFIG_WINDOW_HEIGHT) {
143 mask |= XCB_CONFIG_WINDOW_HEIGHT;
144 values[i++] = e->height;
146 loc.node->client->rectangle.height = e->height;
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;
154 if (e->value_mask & XCB_CONFIG_WINDOW_SIBLING) {
155 mask |= XCB_CONFIG_WINDOW_SIBLING;
156 values[i++] = e->sibling;
159 if (e->value_mask & XCB_CONFIG_WINDOW_STACK_MODE) {
160 mask |= XCB_CONFIG_WINDOW_STACK_MODE;
161 values[i++] = e->stack_mode;
164 xcb_configure_window(dpy, e->window, mask, values);
167 if (is_managed && is_floating(loc.node->client))
168 apply_layout(loc.desktop, loc.node, root_rect);
171 void destroy_notify(xcb_generic_event_t *evt)
173 xcb_destroy_notify_event_t *e = (xcb_destroy_notify_event_t *) evt;
174 window_location_t loc;
176 PRINTF("destroy notify %X\n", e->window);
178 if (locate_window(e->window, &loc)) {
179 remove_node(loc.desktop, loc.node);
180 apply_layout(loc.desktop, loc.desktop->root, root_rect);
184 void unmap_notify(xcb_generic_event_t *evt)
186 xcb_unmap_notify_event_t *e = (xcb_unmap_notify_event_t *) evt;
188 PRINTF("unmap notify %X\n", e->window);
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);
199 void client_message(xcb_generic_event_t *evt)
201 xcb_client_message_event_t *e = (xcb_client_message_event_t *) evt;
203 PRINTF("client message %X\n", e->window);
205 window_location_t loc;
207 if (!locate_window(e->window, &loc))
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);
220 void handle_state(node_t *n, xcb_atom_t state, unsigned int action)
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);