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)) {
21 PUTS("map request\n");
24 case XCB_DESTROY_NOTIFY:
25 PUTS("destroy notify\n");
28 case XCB_UNMAP_NOTIFY:
29 PUTS("unmap notify\n");
32 case XCB_CLIENT_MESSAGE:
33 PUTS("client message\n");
36 case XCB_CONFIGURE_REQUEST:
37 PUTS("configure request\n");
38 configure_request(evt);
40 case XCB_BUTTON_PRESS:
41 PUTS("button press\n");
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, takes_focus = true;
75 handle_rules(win, &floating, &transient, &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);
90 c->transient = transient;
93 focus_node(desk, birth, false);
95 apply_layout(desk, desk->root, root_rect);
97 xcb_map_window(dpy, c->window);
99 xcb_set_input_focus(dpy, XCB_INPUT_FOCUS_POINTER_ROOT, win, XCB_CURRENT_TIME);
102 void configure_request(xcb_generic_event_t *evt)
104 xcb_configure_request_event_t *e = (xcb_configure_request_event_t *) evt;
105 window_location_t loc;
106 bool is_managed = locate_window(e->window, &loc);
108 if (!is_managed || (is_managed && !is_tiled(loc.node->client))) {
111 unsigned short i = 0;
113 if (e->value_mask & XCB_CONFIG_WINDOW_X) {
114 mask |= XCB_CONFIG_WINDOW_X;
117 loc.node->client->rectangle.x = e->x;
120 if (e->value_mask & XCB_CONFIG_WINDOW_Y) {
121 mask |= XCB_CONFIG_WINDOW_Y;
124 loc.node->client->rectangle.y = e->y;
127 if (e->value_mask & XCB_CONFIG_WINDOW_WIDTH) {
128 mask |= XCB_CONFIG_WINDOW_WIDTH;
129 values[i++] = e->width;
131 loc.node->client->rectangle.width = e->width;
134 if (e->value_mask & XCB_CONFIG_WINDOW_HEIGHT) {
135 mask |= XCB_CONFIG_WINDOW_HEIGHT;
136 values[i++] = e->height;
138 loc.node->client->rectangle.height = e->height;
141 if (!is_managed && e->value_mask & XCB_CONFIG_WINDOW_BORDER_WIDTH) {
142 mask |= XCB_CONFIG_WINDOW_BORDER_WIDTH;
143 values[i++] = e->border_width;
146 if (e->value_mask & XCB_CONFIG_WINDOW_SIBLING) {
147 mask |= XCB_CONFIG_WINDOW_SIBLING;
148 values[i++] = e->sibling;
151 if (e->value_mask & XCB_CONFIG_WINDOW_STACK_MODE) {
152 mask |= XCB_CONFIG_WINDOW_STACK_MODE;
153 values[i++] = e->stack_mode;
156 xcb_configure_window(dpy, e->window, mask, values);
159 if (is_managed && is_floating(loc.node->client))
160 apply_layout(loc.desktop, loc.node, root_rect);
163 void destroy_notify(xcb_generic_event_t *evt)
165 xcb_destroy_notify_event_t *e = (xcb_destroy_notify_event_t *) evt;
166 window_location_t loc;
168 if (locate_window(e->window, &loc)) {
169 remove_node(loc.desktop, loc.node);
170 apply_layout(loc.desktop, loc.desktop->root, root_rect);
174 void unmap_notify(xcb_generic_event_t *evt)
176 xcb_unmap_notify_event_t *e = (xcb_unmap_notify_event_t *) evt;
177 if (e->event != screen->root) {
178 window_location_t loc;
179 if (locate_window(e->window, &loc)) {
180 remove_node(loc.desktop, loc.node);
181 apply_layout(loc.desktop, loc.desktop->root, root_rect);
186 void client_message(xcb_generic_event_t *evt)
188 xcb_client_message_event_t *e = (xcb_client_message_event_t *) evt;
189 window_location_t loc;
191 if (!locate_window(e->window, &loc))
194 if (e->type == ewmh->_NET_WM_STATE) {
195 handle_state(loc.node, e->data.data32[1], e->data.data32[0]);
196 handle_state(loc.node, e->data.data32[2], e->data.data32[0]);
197 } else if (e->type == ewmh->_NET_ACTIVE_WINDOW) {
198 focus_node(loc.desktop, loc.node, true);
202 void handle_state(node_t *n, xcb_atom_t state, unsigned int action)
204 if (state == ewmh->_NET_WM_STATE_FULLSCREEN) {
205 bool fs = n->client->fullscreen;
206 if (action == XCB_EWMH_WM_STATE_TOGGLE
207 || (fs && action == XCB_EWMH_WM_STATE_REMOVE)
208 || (!fs && action == XCB_EWMH_WM_STATE_ADD))
209 toggle_fullscreen(n->client);