/* Client Handling
*****************************************************************************/
-void client_setstate(XConf* x, Client* c, int state) {
- uint32_t data[2] = { state, None };
- Atom wm_state = atom(x, "WM_STATE");
- XChangeProperty(x->display, c->win, wm_state, wm_state, 32, PropModeReplace, (unsigned char *)data, 2);
-}
-
-void client_config(XConf* x, Client *c) {
- XConfigureEvent e = {0};
- e.type = ConfigureNotify;
- e.event = c->win;
- e.window = c->win;
- e.x = c->x;
- e.y = c->y;
- e.width = c->w;
- e.height = c->h;
- e.border_width = 0;
- e.above = None;
- e.override_redirect = 0;
- XSendEvent(x->display, c->win, False, StructureNotifyMask, (XEvent *)&e);
-}
-
void client_add(XConf* x, Window win) {
Client* c = calloc(1, sizeof(Client));
c->win = win;
XGrabServer(x->display);
XFetchName(x->display, win, &c->name);
+ /* create the frame window */
XWindowAttributes attr;
XGetWindowAttributes(x->display, win, &attr);
c->x = attr.x, c->y = attr.y;
c->w = attr.width, c->h = attr.height;
- client_setstate(x, c, NormalState);
XSetWindowAttributes pattr = {0};
pattr.override_redirect = True;
c->frame = XCreateWindow(
x->depth, CopyFromParent, x->visual,
CWOverrideRedirect|CWBackPixel|CWBorderPixel|CWEventMask, &pattr);
c->xft = XftDrawCreate(x->display, (Drawable) c->frame, x->visual, x->colormap);
-// XSetWindowBorderWidth(x->display, c->frame, 1);
-// XSetWindowBorderWidth(x->display, c->win, 1);
+
+ /* setup event handling on both windows */
XSelectInput(x->display, c->frame,
ButtonPressMask|ButtonReleaseMask|FocusChangeMask|StructureNotifyMask);
XSelectInput(x->display, c->win,
EnterWindowMask|FocusChangeMask|PropertyChangeMask|StructureNotifyMask);
-#if 0
- XSetWindowBorderWidth(x->display, c->win, 0);
- XResizeWindow(x->display, c->win, c->w, c->h);
- XReparentWindow(x->display, c->win, c->frame, 0, 20);
- client_config(x, c);
- c->xft = XftDrawCreate(x->display, (Drawable) c->frame, x->visual, x->colormap);
- XMapWindow(x->display, c->win);
- XMapRaised(x->display, c->frame);
-#else
+ /* position the window and frame */
XSetWindowBorderWidth(x->display, c->win, 0);
XMoveResizeWindow(x->display, c->frame, 100, 100 - x->font->height, c->w, x->font->height);
XMoveResizeWindow(x->display, c->win, 100, 100, c->w, c->h);
- client_config(x, c);
XMapRaised(x->display, c->frame);
XMapRaised(x->display, c->win);
-#endif
XSync(x->display, False);
XUngrabServer(x->display);
} else if (curr == c) {
Client* next = c->next;
XGrabServer(x->display);
- client_setstate(x, c, WithdrawnState);
XftDrawDestroy(c->xft);
XDestroyWindow(x->display, c->frame);
xfree(c->name);
static void xconfigrequest(XConf* x, XEvent* e) {
dbg("config\n");
+ /*
+ Check if it's a window we care about. If it is, and it's floating, just
+ grant the request. Otherwise, deny it as we have it tiled already. All
+ other windows have their requests granted.
+ */
Client* c = client_find(e->xconfigurerequest.window);
XWindowChanges wc;
- if (c != NULL) {
- wc.x = c->x;
- wc.y = c->y - 20;
- wc.width = c->w;
- wc.height = c->h + 20;
- wc.border_width = 1;
- XConfigureWindow(x->display, c->frame, e->xconfigurerequest.value_mask, &wc);
- client_config(x, c);
- wc.x = 0;
- wc.y = 20;
- } else {
- wc.x = e->xconfigurerequest.x;
- wc.y = e->xconfigurerequest.y;
- }
+ wc.x = e->xconfigurerequest.x;
+ wc.y = e->xconfigurerequest.y;
wc.width = e->xconfigurerequest.width;
wc.height = e->xconfigurerequest.height;
+ wc.border_width = e->xconfigurerequest.border_width;
+ wc.sibling = e->xconfigurerequest.above;
+ wc.stack_mode = e->xconfigurerequest.detail;
+ if (c /* && !(c->flags & FLOATING) */)
+ return;
XConfigureWindow(x->display, e->xconfigurerequest.window, e->xconfigurerequest.value_mask, &wc);
- XSync(x->display, False);
}
static void xmaprequest(XConf* x, XEvent* e) {
dbg("map\n");
static XWindowAttributes attr = {0};
if (XGetWindowAttributes(x->display, e->xmaprequest.window, &attr)) {
- if (attr.override_redirect) return; /* ??? */
+ if (attr.override_redirect) return; /* ignore certain windows (like frames) */
if (!client_find(e->xmaprequest.window))
client_add(x, e->xmaprequest.window);
}
static void xunmapnotify(XConf* x, XEvent* e) {
dbg("unmap\n");
- Client* c = client_find(e->xunmap.window);
- if (c) Clients = client_del(x, Clients, c);
}
static void xdestroynotify(XConf* x, XEvent* e) {
dbg("destroy\n");
+ /*
+ This is where we cleanup windows we care about. destroy them and their frames.
+ */
Client* c = client_find(e->xdestroywindow.window);
if (c) Clients = client_del(x, Clients, c);
}
static void xpropnotify(XConf* x, XEvent* e) {
dbg("prop\n");
+ /*
+ We only care about updating the window titles here for now
+ */
}
static void xenternotify(XConf* x, XEvent* e) {
dbg("enter\n");
+ /*
+ Handle focus follows mouse here.
+ */
}
static void xexpose(XConf* x, XEvent* e) {
#pragma GCC diagnostic pop
int main(void) {
-// dbg("start\n");
x11_init(&X);
X.font = x11_font_load(&X, Fonts[0]);
- XSelectInput(X.display, X.root, SubstructureRedirectMask);
+ XSelectInput(X.display, X.root, SubstructureRedirectMask|SubstructureNotifyMask);
XSync(X.display, False);
if (x11_error_get())
die("Could not start. Is another WM running?\n");
X.eventfns[PropertyNotify] = xpropnotify;
X.eventfns[EnterNotify] = xenternotify;
X.eventfns[Expose] = xexpose;
-// dbg("loop\n");
x11_event_loop(&X, 0);
return 0;
}
}
}
+void x11_mapnotify(XConf* x, XEvent* e) {
+ x11_resize(x, e);
+ XWarpPointer(x->display, None, x->self, 0, 0, x->width, x->height, x->width/2, x->height/2);
+}
+
void x11_init_gc(XConf* x) {
/* set input methods */
if ((x->xim = XOpenIM(x->display, 0, 0, 0)))
x->eventfns[FocusIn] = xfocus;
x->eventfns[FocusOut] = xfocus;
x->eventfns[ConfigureNotify] = x11_resize;
+ x->eventfns[MappingNotify] = x11_mapnotify;
}
void x11_centerwin(XConf* x) {
XSendEvent(x->display, x->self, False, StructureNotifyMask, (XEvent *)&ce);
XMapWindow(x->display, x->self);
XSync(x->display, False);
-
- /* Waiting for window mapping */
- XEvent ev;
- do {
- XNextEvent(x->display, &ev);
- if (XFilterEvent(&ev, None))
- continue;
- x11_resize(x, &ev);
- } while (ev.type != MapNotify);
- XWarpPointer(x->display, None, x->self, 0, 0, x->width, x->height, x->width/2, x->height/2);
}
XftFont* x11_font_load(XConf* x, char* name) {