diff options
Diffstat (limited to 'xsnap.c')
-rw-r--r-- | xsnap.c | 178 |
1 files changed, 178 insertions, 0 deletions
@@ -0,0 +1,178 @@ +#define _POSIX_C_SOURCE 200809L +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <X11/Xlib.h> + +/* 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; +} |