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)) {
24 case XCB_DESTROY_NOTIFY:
25 PUTS("destroy notify");
28 case XCB_UNMAP_NOTIFY:
32 case XCB_CLIENT_MESSAGE:
33 PUTS("client message");
36 case XCB_CONFIGURE_REQUEST:
37 PUTS("configure request");
38 configure_request(evt);
40 case XCB_BUTTON_PRESS:
44 /* PRINTF("received event %i\n", XCB_EVENT_RESPONSE_TYPE(evt)); */
49 void map_request(xcb_generic_event_t *evt)
51 xcb_map_request_event_t *e = (xcb_map_request_event_t *) evt;
52 xcb_get_window_attributes_reply_t *wa;
53 xcb_window_t win = e->window;
54 window_location_t loc;
55 wa = xcb_get_window_attributes_reply(dpy, xcb_get_window_attributes(dpy, win), NULL);
57 if ((wa != NULL && wa->override_redirect) || locate_window(win, &loc))
62 client_t *c = make_client(win);
64 xcb_get_geometry_reply_t *geom = xcb_get_geometry_reply(dpy, xcb_get_geometry(dpy, win), NULL);
67 c->rectangle = (xcb_rectangle_t) {geom->x, geom->y, geom->width, geom->height};
70 c->rectangle = (xcb_rectangle_t) {0, 0, 320, 240};
73 bool floating = false, transient = false, fullscreen = false, takes_focus = true;
75 handle_rules(win, &floating, &transient, &fullscreen, &takes_focus);
80 node_t *birth = make_node();
82 insert_node(desk, birth);
85 toggle_floating(birth);
87 if (desk->focus != NULL && desk->focus->client->fullscreen)
88 toggle_fullscreen(desk->focus->client);
91 toggle_fullscreen(birth->client);
93 c->transient = transient;
96 focus_node(desk, birth, false);
98 apply_layout(desk, desk->root, root_rect);
100 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;
110 window_location_t loc;
111 bool is_managed = locate_window(e->window, &loc);
113 if (!is_managed || is_floating(loc.node->client)) {
116 unsigned short i = 0;
118 if (e->value_mask & XCB_CONFIG_WINDOW_X) {
119 mask |= XCB_CONFIG_WINDOW_X;
122 loc.node->client->rectangle.x = e->x;
125 if (e->value_mask & XCB_CONFIG_WINDOW_Y) {
126 mask |= XCB_CONFIG_WINDOW_Y;
129 loc.node->client->rectangle.y = e->y;
132 if (e->value_mask & XCB_CONFIG_WINDOW_WIDTH) {
133 mask |= XCB_CONFIG_WINDOW_WIDTH;
134 values[i++] = e->width;
136 loc.node->client->rectangle.width = e->width;
139 if (e->value_mask & XCB_CONFIG_WINDOW_HEIGHT) {
140 mask |= XCB_CONFIG_WINDOW_HEIGHT;
141 values[i++] = e->height;
143 loc.node->client->rectangle.height = e->height;
146 if (!is_managed && e->value_mask & XCB_CONFIG_WINDOW_BORDER_WIDTH) {
147 mask |= XCB_CONFIG_WINDOW_BORDER_WIDTH;
148 values[i++] = e->border_width;
151 if (e->value_mask & XCB_CONFIG_WINDOW_SIBLING) {
152 mask |= XCB_CONFIG_WINDOW_SIBLING;
153 values[i++] = e->sibling;
156 if (e->value_mask & XCB_CONFIG_WINDOW_STACK_MODE) {
157 mask |= XCB_CONFIG_WINDOW_STACK_MODE;
158 values[i++] = e->stack_mode;
161 xcb_configure_window(dpy, e->window, mask, values);
164 if (is_managed && is_floating(loc.node->client))
165 apply_layout(loc.desktop, loc.node, root_rect);
168 void destroy_notify(xcb_generic_event_t *evt)
170 xcb_destroy_notify_event_t *e = (xcb_destroy_notify_event_t *) evt;
171 window_location_t loc;
173 if (locate_window(e->window, &loc)) {
174 remove_node(loc.desktop, loc.node);
175 apply_layout(loc.desktop, loc.desktop->root, root_rect);
179 void unmap_notify(xcb_generic_event_t *evt)
181 xcb_unmap_notify_event_t *e = (xcb_unmap_notify_event_t *) evt;
182 if (e->event != screen->root) {
183 window_location_t loc;
184 if (locate_window(e->window, &loc)) {
185 remove_node(loc.desktop, loc.node);
186 apply_layout(loc.desktop, loc.desktop->root, root_rect);
191 void client_message(xcb_generic_event_t *evt)
193 xcb_client_message_event_t *e = (xcb_client_message_event_t *) evt;
194 window_location_t loc;
196 if (!locate_window(e->window, &loc))
199 if (e->type == ewmh->_NET_WM_STATE) {
200 handle_state(loc.node, e->data.data32[1], e->data.data32[0]);
201 handle_state(loc.node, e->data.data32[2], e->data.data32[0]);
202 } else if (e->type == ewmh->_NET_ACTIVE_WINDOW) {
203 if (desk != loc.desktop)
204 select_desktop(loc.desktop);
205 focus_node(loc.desktop, loc.node, true);
209 void handle_state(node_t *n, xcb_atom_t state, unsigned int action)
211 if (state == ewmh->_NET_WM_STATE_FULLSCREEN) {
212 bool fs = n->client->fullscreen;
213 if (action == XCB_EWMH_WM_STATE_TOGGLE
214 || (fs && action == XCB_EWMH_WM_STATE_REMOVE)
215 || (!fs && action == XCB_EWMH_WM_STATE_ADD))
216 toggle_fullscreen(n->client);