diff options
Diffstat (limited to '1')
-rw-r--r-- | 1 | 166 |
1 files changed, 166 insertions, 0 deletions
@@ -0,0 +1,166 @@ +/* + xdeadzone - create a window and don't allow the mouse pointer to enter it. + + compile me with: + + gcc -Wall -o xdeadzone xdeadzone.c -lX11 + + run me with ./xdeadzone, and be prepared to hit ^C or use kill to exit, + since it doesn't have any other way to exit (currently). +*/ + +#include <X11/Xlib.h> +#include <X11/Xatom.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + +#ifndef VERSION +# define VERSION "UnknownVersion" +#endif + +#define NAME "XDeadZone" + +const char *exename; + +void set_exename(const char *p) { + exename = p; + while(*p) { + if(*p == '/') exename = p + 1; + p++; + } + printf("exename: %s\n", exename); +} + +void usage(char *name, int ret) { + printf( + NAME " " VERSION "\n" + "Usage:\n %s " + "[-nw | -ne | -sw | -se | -abs xpos ypos] [width] [height]" + "\n", + name); + exit(ret); +} + +void errmsg(char *name, char *msg) { + fprintf(stderr, "%s: %s\n", name, msg); + usage(name, 1); +} + +int main(int argc, char **argv) { + Display *d; + Window w; + XEvent ev; + Atom dock_atom; + XWindowAttributes attr; + XSetWindowAttributes setattr; + int screen; + + int done = 0; + int x = 0, y = 0, width = 0, height = 0; + + if(argc == 2 && strcmp(argv[1], "--help") == 0) + usage(argv[0], 0); + + if(strcmp(argv[1], "-abs") == 0) { + if(argc != 6) + errmsg(argv[0], "wrong number of arguments for -abs"); + x = atoi(argv[2]); + y = atoi(argv[3]); + width = atoi(argv[4]); + height = atoi(argv[5]); + } else { + if(argc != 4) + errmsg(argv[0], "wrong number of arguments for -nw/-ne/-sw/-se"); + width = atoi(argv[2]); + height = atoi(argv[3]); + if(strcmp(argv[1], "-nw") == 0) { + x = 0; y = 0; + } else if(strcmp(argv[1], "-ne") == 0) { + x = -width; y = 0; + } else if(strcmp(argv[1], "-sw") == 0) { + x = 0; y = -height; + } else if(strcmp(argv[1], "-se") == 0) { + x = -width; y = -height; + } else { + errmsg(argv[0], "invalid 1st argument (not -abs/-nw/-ne/-sw/-se)"); + } + } + + if(width <= 0 || height <= 0) + errmsg(argv[0], "width and height must be positive and non-zero"); + + if(!(d = XOpenDisplay(NULL))) + errmsg(argv[0], "can't open X display"); + + XGetWindowAttributes(d, DefaultRootWindow(d), &attr); + if(x < 0) x = attr.width + x; + if(y < 0) y = attr.height + y; + + printf("X size %d x %d, x %d, y %d, width %d, height %d\n", attr.width, attr.height, x, y, width, height); + + /* Create window with override_redirect enabled, to tell the window + manager not to decorate it with a titlebar or resize frame. + Also, we really only care about EnterNotify events. + Set the window to solid white, to make it easy to see during testing. + In actual use, the window won't be visible, it'll be in the dead zone, + right? + */ + screen = DefaultScreen(d); + setattr.override_redirect = True; + setattr.background_pixel = WhitePixel(d, screen); + setattr.event_mask = EnterWindowMask; + + w = XCreateWindow(d, + RootWindow(d, screen), + x, y, width, height, 0, + DefaultDepth(d, screen), + InputOutput, + DefaultVisual(d, screen), + CWBackPixel | CWOverrideRedirect | CWEventMask, + &setattr); + + XStoreName(d, w, NAME); + + /* On most window managers, this makes the window stay on top and + be present on all virtual desktops. Tested, works with WindowMaker, Fvwm2, + KDE5, XFCE4, BlackBox, and FluxBox. On all but Fvwm2, it also + disappears the titlebar and resize frame... but we already took + care of that with override_redirect, above. + ref: http://standards.freedesktop.org/wm-spec/wm-spec-latest.html + */ + dock_atom = XInternAtom(d, "_NET_WM_WINDOW_TYPE_DOCK", False); + XChangeProperty(d, + w, + XInternAtom(d, "_NET_WM_WINDOW_TYPE", False), + XA_ATOM, + 32, + PropModeReplace, + (unsigned char *) &dock_atom, + 1); + + XMapWindow(d, w); + + /* have to do this after it's mapped, since the window manager might have + ignored the x and y in the XCreateWindow(). */ + XMoveWindow(d, w, x, y); + + while(!done) { + XNextEvent(d, &ev); + if(ev.type == EnterNotify) { + // printf("entered at %d, %d\n", ev.xcrossing.x_root, ev.xcrossing.y_root); + XWarpPointer(d, + None, + DefaultRootWindow(d), + 0, 0, 0, 0, + ev.xcrossing.x_root, + (y == 0 ? y + height : y - 1)); + } + } + + XUnmapWindow(d, w); + XDestroyWindow(d, w); + XCloseDisplay(d); + + return 0; +} |