#define _POSIX_C_SOURCE 200809L #include #include #include #include /* MAJE_LDLIB=-lX11 */ #define WM_STATE_FORMAT 32 static Bool is_normal(Display *dpy, Window win) { static Atom state = None; if (state == None) { state = XInternAtom(dpy, "WM_STATE", True); if (state == None) { return False; } } Atom type = AnyPropertyType; int format = WM_STATE_FORMAT; unsigned long nitems = 0; unsigned long bytes = 0; unsigned char *prop = NULL; int r = XGetWindowProperty(dpy, win, state, 0, 0, False, type, &type, &format, &nitems, &bytes, &prop); if (r == Success && prop != NULL) { XFree(prop); return True; } return False; } static Window find_normal_parent(Display *dpy, Window win) { if (win == PointerRoot || win == None || is_normal(dpy, win)) { return win; } Window root = win, parent = win, *children = NULL; unsigned int nchildren = 0; if (!XQueryTree(dpy, win, &root, &parent, &children, &nchildren)) { return None; } if (parent == win || is_normal(dpy, parent)) { return parent; } return find_normal_parent(dpy, win); } static int xsnap_error(Display *dpy, XErrorEvent *e) { char buf[BUFSIZ]; XGetErrorText(dpy, e->error_code, buf, sizeof(buf)); fprintf(stderr, "xsnap: %s\n", buf); exit(1); } int main(int argc, char *argv[]) { enum { NONE, LEFT, RIGHT, UP, DOWN } dir = NONE; int c = 0; while ((c = getopt(argc, argv, "lrud")) != -1) { switch (c) { case 'l': dir = LEFT; break; case 'r': dir = RIGHT; break; case 'u': dir = UP; break; case 'd': dir = DOWN; break; default: return 1; } } if (dir == NONE) { fprintf(stderr, "xsnap: missing direction\n"); return 1; } /* TODO: if operand, use that, otherwise find focused */ Display *dpy = XOpenDisplay(NULL); XSetErrorHandler(xsnap_error); Window root = XDefaultRootWindow(dpy); Window focused = root; int revert = RevertToNone; XGetInputFocus(dpy, &focused, &revert); focused = find_normal_parent(dpy, focused); XWindowAttributes rootattr = { 0 }; XGetWindowAttributes(dpy, root, &rootattr); XWindowAttributes attributes = { 0 }; XGetWindowAttributes(dpy, focused, &attributes); if (!attributes.override_redirect) { fprintf(stderr, "can't override redirect\n"); exit(1); } int x = 0; int y = 0; unsigned w = 0; unsigned h = 0; switch (dir) { case LEFT: x = 0; y = 0; w = rootattr.width / 2; h = rootattr.height; break; case RIGHT: x = rootattr.width / 2; y = 0; w = rootattr.width / 2; h = rootattr.height; break; case UP: x = 0; y = 0; w = rootattr.width; h = rootattr.height / 2; break; case DOWN: x = 0; y = rootattr.height / 2; w = rootattr.width; h = rootattr.height / 2; break; default: fprintf(stderr, "somehow missing direction\n"); return 1; break; } int r = XMoveResizeWindow(dpy, focused, x, y, w ? w : 1, h ? h : 1); if (r != 0) { XErrorEvent e = { .error_code = r }; xsnap_error(dpy, &e); } return 0; }