X-Git-Url: http://pileus.org/git/?a=blobdiff_plain;f=sys-x11.c;h=75c2edd8a88b600a82f4e4e73c1bf22dfe657c56;hb=e396d3e091801135cf20b76d69199a9955ff3dc9;hp=7ba9b693ce385a5c698f613c62c4f719a8a947f2;hpb=6e0abca515f58cb87c0c0310bc98ed7d84536344;p=wmpus diff --git a/sys-x11.c b/sys-x11.c index 7ba9b69..75c2edd 100644 --- a/sys-x11.c +++ b/sys-x11.c @@ -4,6 +4,7 @@ #include #include +#include #include #include "util.h" @@ -14,6 +15,9 @@ struct win_sys { Window xid; Display *dpy; + struct { + int left, right, top, bottom; + } strut; }; typedef struct { @@ -22,16 +26,16 @@ typedef struct { } keymap_t; typedef enum { - wm_proto, wm_focus, natoms + wm_proto, wm_focus, net_strut, natoms } atom_t; -Atom atoms[natoms]; - /* Global data */ -void *win_cache = NULL; +static void *win_cache = NULL; +static Atom atoms[natoms]; +static int (*xerrorxlib)(Display *, XErrorEvent *); /* Conversion functions */ -keymap_t key2sym[] = { +static keymap_t key2sym[] = { {key_left , XK_Left }, {key_right , XK_Right}, {key_up , XK_Up }, @@ -55,7 +59,7 @@ keymap_t key2sym[] = { }; /* - Modifiers */ -mod_t x2mod(unsigned int state, int up) +static mod_t x2mod(unsigned int state, int up) { return (mod_t){ .alt = !!(state & Mod1Mask ), @@ -66,7 +70,7 @@ mod_t x2mod(unsigned int state, int up) }; } -unsigned int mod2x(mod_t mod) +static unsigned int mod2x(mod_t mod) { return (mod.alt ? Mod1Mask : 0) | (mod.ctrl ? ControlMask : 0) @@ -75,35 +79,36 @@ unsigned int mod2x(mod_t mod) } /* - Keycodes */ -Key_t x2key(KeySym sym) +static Key_t x2key(KeySym sym) { keymap_t *km = map_getr(key2sym,sym); return km ? km->key : sym; } -KeySym key2x(Key_t key) +static KeySym key2x(Key_t key) { keymap_t *km = map_get(key2sym,key); return km ? km->sym : key; } -Key_t x2btn(int btn) +static Key_t x2btn(int btn) { return btn + key_mouse0; } -int btn2x(Key_t key) +static int btn2x(Key_t key) { return key - key_mouse0; } /* - Pointers */ -ptr_t x2ptr(XEvent *_ev) +static ptr_t x2ptr(XEvent *_ev) { XKeyEvent *ev = &_ev->xkey; return (ptr_t){ev->x, ev->y, ev->x_root, ev->y_root}; } -Window getfocus(win_t *root, XEvent *event) + +static Window getfocus(win_t *root, XEvent *event) { int revert; Window focus = PointerRoot; @@ -116,8 +121,56 @@ Window getfocus(win_t *root, XEvent *event) return focus; } +/* Helpers */ +static int add_strut(win_t *root, win_t *win) +{ + /* Get X11 strut data */ + Atom ret_type; + int ret_size; + unsigned long ret_items, bytes_left; + unsigned char *xdata; + int status = XGetWindowProperty(win->sys->dpy, win->sys->xid, + atoms[net_strut], 0L, 4L, False, XA_CARDINAL, + &ret_type, &ret_size, &ret_items, &bytes_left, &xdata); + if (status != Success || ret_size != 32 || ret_items != 4) + return 0; + + int left = ((int*)xdata)[0]; + int right = ((int*)xdata)[1]; + int top = ((int*)xdata)[2]; + int bottom = ((int*)xdata)[3]; + if (left == 0 && right == 0 && top == 0 && bottom == 0) + return 0; + + win->sys->strut.left = left; + win->sys->strut.right = right; + win->sys->strut.top = top; + win->sys->strut.bottom = bottom; + root->x += left; + root->y += top; + root->w -= left+right; + root->h -= top+bottom; + return 1; +} + +static int del_strut(win_t *root, win_t *win) +{ + int left = win->sys->strut.left; + int right = win->sys->strut.right; + int top = win->sys->strut.top; + int bottom = win->sys->strut.bottom; + if (left == 0 && right == 0 && top == 0 && bottom == 0) + return 0; + + root->x -= left; + root->y -= top; + root->w += left+right; + root->h += top+bottom; + return 1; +} + /* Window functions */ -win_t *win_new(Display *dpy, Window xid) +static win_t *win_new(Display *dpy, Window xid) { XWindowAttributes attr; if (XGetWindowAttributes(dpy, xid, &attr)) @@ -135,7 +188,7 @@ win_t *win_new(Display *dpy, Window xid) return win; } -int win_cmp(const void *_a, const void *_b) +static int win_cmp(const void *_a, const void *_b) { const win_t *a = _a, *b = _b; if (a->sys->dpy < b->sys->dpy) return -1; @@ -145,7 +198,7 @@ int win_cmp(const void *_a, const void *_b) return 0; } -win_t *win_find(Display *dpy, Window xid, int create) +static win_t *win_find(Display *dpy, Window xid, int create) { if (!dpy || !xid) return NULL; @@ -160,14 +213,14 @@ win_t *win_find(Display *dpy, Window xid, int create) return new; } -void win_remove(win_t *win) +static void win_remove(win_t *win) { tdelete(win, &win_cache, win_cmp); free(win->sys); free(win); } -int win_viewable(win_t *win) +static int win_viewable(win_t *win) { XWindowAttributes attr; if (XGetWindowAttributes(win->sys->dpy, win->sys->xid, &attr)) @@ -177,7 +230,7 @@ int win_viewable(win_t *win) } /* Callbacks */ -void process_event(int type, XEvent *ev, win_t *root) +static void process_event(int type, XEvent *ev, win_t *root) { Display *dpy = root->sys->dpy; win_t *win = NULL; @@ -230,20 +283,20 @@ void process_event(int type, XEvent *ev, win_t *root) wm_handle_key(win, key, MOD(), PTR()); } else if (type == ConfigureNotify) { - //printf("configure: %d\n", type); + printf("configure: %d\n", type); } else if (type == MapNotify) { - //printf("map: %d\n", type); - } - else if (type == DestroyNotify) { - //printf("destory: %d\n", type); - if ((win = win_find(dpy,ev->xdestroywindow.window,0))) - win_remove(win); + printf("map: %d\n", type); } else if (type == UnmapNotify) { //printf("unmap: %d\n", type); - if ((win = win_find(dpy,ev->xmap.window,0))) - wm_remove(win); + if ((win = win_find(dpy,ev->xunmap.window,0))) { + if (!del_strut(root, win)) + wm_remove(win); + else + wm_update(); + win_remove(win); + } } else if (type == ConfigureRequest) { XConfigureRequestEvent *cre = &ev->xconfigurerequest; @@ -251,6 +304,12 @@ void process_event(int type, XEvent *ev, win_t *root) .x = cre->x, .y = cre->y, .width = cre->width, .height = cre->height, }; + if ((win = win_find(dpy,ev->xmaprequest.window,1))) { + wc.x = win->x; + wc.y = win->y; + wc.width = win->w; + wc.height = win->h; + } printf("configure_req: %d - %x, (0x%lx) %dx%d @ %d,%d\n", type, (int)cre->window, cre->value_mask, cre->height, cre->width, cre->x, cre->y); @@ -258,8 +317,12 @@ void process_event(int type, XEvent *ev, win_t *root) } else if (type == MapRequest) { printf("map_req: %d\n", type); - if ((win = win_find(dpy,ev->xmaprequest.window,1))) - wm_insert(win); + if ((win = win_find(dpy,ev->xmaprequest.window,1))) { + if (!add_strut(root, win)) + wm_insert(win); + else + wm_update(); + } XMapWindow(dpy,ev->xmaprequest.window); } else { @@ -267,9 +330,19 @@ void process_event(int type, XEvent *ev, win_t *root) } } -int xwmerror(Display *dpy, XErrorEvent *err) +static int xerror(Display *dpy, XErrorEvent *err) { - return error("another window manager is running?"); + if (err->error_code == BadWindow || + (err->request_code == X_SetInputFocus && err->error_code == BadMatch ) || + (err->request_code == X_PolyText8 && err->error_code == BadDrawable) || + (err->request_code == X_PolyFillRectangle && err->error_code == BadDrawable) || + (err->request_code == X_PolySegment && err->error_code == BadDrawable) || + (err->request_code == X_ConfigureWindow && err->error_code == BadMatch ) || + (err->request_code == X_GrabButton && err->error_code == BadAccess ) || + (err->request_code == X_GrabKey && err->error_code == BadAccess ) || + (err->request_code == X_CopyArea && err->error_code == BadDrawable)) + return 0; + return xerrorxlib(dpy, err); } /***************** @@ -278,9 +351,10 @@ int xwmerror(Display *dpy, XErrorEvent *err) void sys_move(win_t *win, int x, int y, int w, int h) { //printf("sys_move: %p - %d,%d %dx%d\n", win, x, y, w, h); - win->x = x; win->y = y; - win->w = w; win->h = h; - XMoveResizeWindow(win->sys->dpy, win->sys->xid, x, y, w, h); + win->x = MAX(x,0); win->y = MAX(y,0); + win->w = MAX(w,1); win->h = MAX(h,1); + XMoveResizeWindow(win->sys->dpy, win->sys->xid, + win->x, win->y, win->w, win->h); /* Flush events, so moving window doesn't cuase re-focus * There's probably a better way to do this */ @@ -343,10 +417,12 @@ win_t *sys_init(void) error("Unable to get display"); if (!(xid = DefaultRootWindow(dpy))) error("Unable to get root window"); - atoms[wm_proto] = XInternAtom(dpy, "WM_PROTOCOLS", False); - atoms[wm_focus] = XInternAtom(dpy, "WM_TAKE_FOCUS", False); + atoms[wm_proto] = XInternAtom(dpy, "WM_PROTOCOLS", False); + atoms[wm_focus] = XInternAtom(dpy, "WM_TAKE_FOCUS", False); + atoms[net_strut] = XInternAtom(dpy, "_NET_WM_STRUT", False); XSelectInput(dpy, xid, SubstructureRedirectMask|SubstructureNotifyMask); XSetInputFocus(dpy, None, RevertToNone, CurrentTime); + xerrorxlib = XSetErrorHandler(xerror); return win_find(dpy, xid, 1); } @@ -359,9 +435,10 @@ void sys_run(win_t *root) &par, &xid, &kids, &nkids)) for(int i = 0; i < nkids; i++) { win_t *win = win_find(root->sys->dpy, kids[i], 1); - if (win && win_viewable(win)) + if (win && win_viewable(win) && !add_strut(root,win)) wm_insert(win); } + wm_update(); // For struts /* Main loop */ for(;;)