#include <xcb/xcb.h>
#include <xcb/xcb_event.h>
#include <xcb/xcb_keysyms.h>
+#include <xcb/xcb_ewmh.h>
#include <xcb/xinerama.h>
#include "util.h"
static int no_capture = 0;
/* Internal structures */
+typedef struct {
+ int left;
+ int right;
+ int top;
+ int bottom;
+} strut_t;
+
struct win_sys {
xcb_window_t xcb; // xcb window id
xcb_event_mask_t events; // currently watch events
- int override; // normal vs override redirect
- int mapped; // window is currently mapped
+ strut_t strut; // toolbar struts
+ int managed; // window is managed by wm
};
typedef enum {
} color_t;
/* Global data */
-static xcb_connection_t *conn;
-static xcb_key_symbols_t *keysyms;
-static xcb_colormap_t colormap;
-static xcb_window_t root;
-static xcb_event_mask_t events;
-static list_t *screens;
-static void *cache;
-static xcb_pixmap_t colors[NCOLORS];
-static unsigned int grabbed;
+static xcb_connection_t *conn;
+static xcb_ewmh_connection_t ewmh;
+static xcb_key_symbols_t *keysyms;
+static xcb_colormap_t colormap;
+static xcb_window_t root;
+static xcb_event_mask_t events;
+static list_t *screens;
+static void *cache;
+static xcb_pixmap_t colors[NCOLORS];
+static unsigned int grabbed;
/************************
* Conversion functions *
return reply->focus;
}
+static int do_ewmh_init_atoms(void)
+{
+ xcb_intern_atom_cookie_t *cookies =
+ xcb_ewmh_init_atoms(conn, &ewmh);
+ if (!cookies)
+ return warn("do_ewmh_init_atoms: no cookies");
+
+ int status =
+ xcb_ewmh_init_atoms_replies(&ewmh, cookies, NULL);
+ if (!status)
+ return warn("do_ewmh_init_atoms: no status");
+ return status;
+}
+
+static int do_get_strut(xcb_window_t win, strut_t *strut)
+{
+ xcb_get_property_cookie_t cookie =
+ xcb_ewmh_get_wm_strut(&ewmh, win);
+ if (!cookie.sequence)
+ return warn("do_get_strut: bad cookie");
+
+ xcb_ewmh_get_extents_reply_t ext = {};
+ int status =
+ xcb_ewmh_get_wm_strut_reply(&ewmh, cookie, &ext, NULL);
+ if (!status)
+ return warn("do_get_strut: no status");
+
+ strut->left = ext.left;
+ strut->right = ext.right;
+ strut->top = ext.top;
+ strut->bottom = ext.bottom;
+
+ return ext.left || ext.right || ext.top || ext.bottom;
+}
+
static xcb_pixmap_t do_alloc_color(uint32_t rgb)
{
uint16_t r = (rgb & 0xFF0000) >> 8;
}
/* Send window state info */
-static int send_state(void)
+static void send_manage(win_t *win, int managed)
{
- return 0;
+ if (win->sys->managed == managed)
+ return;
+ if (managed)
+ wm_insert(win);
+ else
+ wm_remove(win);
+ win->sys->managed = managed;
}
+/* Send window state info */
+static void send_state(win_t *win, state_t next)
+{
+ if (!win->sys->managed)
+ return;
+ if (win->state == next)
+ return;
+ state_t prev = win->state;
+ win->state = next;
+ wm_handle_state(win, prev, next);
+}
/**********************
* X11 Event Handlers *
win->sys = sys;
sys->xcb = event->window;
- sys->override = event->override_redirect;
+
+ if (!event->override_redirect)
+ send_manage(win, 1);
tsearch(win, &cache, win_cmp);
}
-static void on_destroy_notify(win_t *win, xcb_destroy_notify_event_t *event)
+static void on_destroy_notify(xcb_destroy_notify_event_t *event)
{
+ win_t *win = win_get(event->window);
printf("on_destroy_notify: xcb=%-8u -> win=%p\n",
event->window, win);
+ if (!win) return;
+
+ send_manage(win, 0);
tdelete(win, &cache, win_cmp);
free(win);
}
-static void on_map_request(win_t *win, xcb_map_request_event_t *event)
+static void on_unmap_notify(xcb_unmap_notify_event_t *event)
{
+ win_t *win = win_get(event->window);
+ printf("on_unmap_notify: xcb=%-8u -> win=%p\n",
+ event->window, win);
+ if (!win) return;
+
+ send_state(win, ST_HIDE);
+}
+
+static void on_map_notify(xcb_map_notify_event_t *event)
+{
+ win_t *win = win_get(event->window);
+ printf("on_map_notify: xcb=%-8u -> win=%p\n",
+ event->window, win);
+ if (!win) return;
+
+ send_state(win, ST_SHOW);
+}
+
+static void on_map_request(xcb_map_request_event_t *event)
+{
+ win_t *win = win_get(event->window);
printf("on_map_request: xcb=%-8u -> win=%p\n",
event->window, win);
+ if (!win) return;
- if (!win->sys->override && !win->sys->mapped)
- wm_insert(win);
- win->sys->mapped = 1;
+ if (do_get_strut(win->sys->xcb, &win->sys->strut))
+ printf("Map: Got a strut!\n");
+ else
+ printf("Map: No struts here!\n");
+ send_state(win, ST_SHOW);
xcb_map_window(conn, win->sys->xcb);
sys_move(win, win->x, win->y, win->w, win->h);
}
-static void on_configure_request(win_t *win, xcb_configure_request_event_t *event)
+static void on_configure_request(xcb_configure_request_event_t *event)
{
+ win_t *win = win_get(event->window);
printf("on_configure_request: xcb=%-8u -> win=%p -- %dx%d @ %d,%d\n",
event->window, win,
event->width, event->height,
event->x, event->y);
+ if (!win) return;
win->x = event->x;
win->y = event->y;
/* Generic Event */
static void on_event(xcb_generic_event_t *event)
{
- win_t *win = NULL;
-
int type = XCB_EVENT_RESPONSE_TYPE(event);
- int sent = XCB_EVENT_SENT(event);
- const char *name = NULL;
switch (type) {
/* Input handling */
on_create_notify((xcb_create_notify_event_t *)event);
break;
case XCB_DESTROY_NOTIFY:
- if ((win = win_get(((xcb_destroy_notify_event_t *)event)->window)))
- on_destroy_notify(win, (xcb_destroy_notify_event_t *)event);
+ on_destroy_notify((xcb_destroy_notify_event_t *)event);
+ break;
+ case XCB_UNMAP_NOTIFY:
+ on_unmap_notify((xcb_unmap_notify_event_t *)event);
+ break;
+ case XCB_MAP_NOTIFY:
+ on_map_notify((xcb_map_notify_event_t *)event);
break;
case XCB_MAP_REQUEST:
- if ((win = win_get(((xcb_map_request_event_t *)event)->window)))
- on_map_request(win, (xcb_map_request_event_t *)event);
+ on_map_request((xcb_map_request_event_t *)event);
break;
case XCB_CONFIGURE_REQUEST:
- if ((win = win_get(((xcb_configure_request_event_t *)event)->window)))
- on_configure_request(win, (xcb_configure_request_event_t *)event);
+ on_configure_request((xcb_configure_request_event_t *)event);
break;
/* Unknown events */
default:
- name = xcb_event_get_label(type);
printf("on_event: %d:%02X -> %s\n",
- !!sent, type, name?:"unknown_event");
+ XCB_EVENT_SENT(event) != 0,
+ XCB_EVENT_RESPONSE_TYPE(event),
+ xcb_event_get_label(type) ?: "unknown_event");
break;
}
}
break;
case ST_CLOSE:
- // TODO
- // if (!win_msg(win, WM_DELETE)) {
- // XGrabServer(win->sys->dpy);
- // XSetErrorHandler(xnoerror);
- // XSetCloseDownMode(win->sys->dpy, DestroyAll);
- // XKillClient(win->sys->dpy, win->sys->xid);
- // XSync(win->sys->dpy, False);
- // XSetErrorHandler(xerror);
- // XUngrabServer(win->sys->dpy);
- // }
+ xcb_kill_client(conn, xcb);
break;
}
root = iter.data->root;
colormap = iter.data->default_colormap;
+ /* Setup EWMH connection */
+ if (!do_ewmh_init_atoms())
+ error("ewmh setup failed");
+
+ /* Setup for for ST_CLOSE */
+ xcb_set_close_down_mode(conn, XCB_CLOSE_DOWN_DESTROY_ALL);
+
/* Allocate key symbols */
if (!(keysyms = xcb_key_symbols_alloc(conn)))
error("cannot allocate key symbols");
xcb_window_t *kids = NULL;
int nkids = do_query_tree(root, &kids);
for(int i = 0; i < nkids; i++) {
+ int override=0, mapped=0;
win_t *win = new0(win_t);
win->sys = new0(win_sys_t);
win->sys->xcb = kids[i];
- do_get_geometry(kids[i], &win->x, &win->y, &win->w, &win->h);
- do_get_window_attributes(kids[i],
- &win->sys->override, &win->sys->mapped);
tsearch(win, &cache, win_cmp);
- if (!win->sys->override && win->sys->mapped)
- wm_insert(win);
+ do_get_geometry(kids[i], &win->x, &win->y, &win->w, &win->h);
+ do_get_window_attributes(kids[i], &override, &mapped);
+ if (!override)
+ send_manage(win, 1);
+ if (mapped)
+ send_state(win, ST_SHOW);
}
xcb_flush(conn);
}