aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore3
-rw-r--r--1166
-rw-r--r--Makefile29
-rw-r--r--README13
-rw-r--r--version.h1
-rw-r--r--version.rst1
-rw-r--r--xdeadzone.1160
-rw-r--r--xdeadzone.c197
-rw-r--r--xdeadzone.rst136
9 files changed, 706 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..c0ebefd
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,3 @@
+*.o
+core
+xdeadzone
diff --git a/1 b/1
new file mode 100644
index 0000000..d0725da
--- /dev/null
+++ b/1
@@ -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;
+}
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..b0ccfc2
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,29 @@
+# GNU Makefile for xdeadzone(1). May also work with BSD make, since I
+# don't use any GNU-specific features.
+
+# Optimization flags for $(CC)
+OPTFLAGS=-O2 -fPIC
+
+# Add any extra libraries you need here.
+LIBS=
+
+# Shouldn't need to override these.
+VERSION=0.1
+CFLAGS=-Wall -DVERSION="\"$(VERSION)"\" $(OPTFLAGS)
+LDFLAGS=-lX11 $(LIBS)
+
+all: xdeadzone xdeadzone.1
+
+xdeadzone: xdeadzone.c
+
+xdeadzone.1: xdeadzone.rst
+ echo ".. |version| replace:: $(VERSION)" > version.rst
+ rst2man xdeadzone.rst > xdeadzone.1
+
+clean:
+ rm -f xdeadzone *.o core
+
+realclean: clean
+ rm -f xdeadzone.1 version.rst
+
+.PHONY: all clean realclean
diff --git a/README b/README
new file mode 100644
index 0000000..f912277
--- /dev/null
+++ b/README
@@ -0,0 +1,13 @@
+README for XDeadZone
+====================
+
+xdeadzone's job is to create a window of a specified size, and prevent
+the mouse pointer from entering it.
+
+The intended use for it is to keep the mouse out of the "dead zone"
+of a multi-head X display where the monitors don't all have the same
+resolution. It could also be useful for covering annoying parts of
+the screen, e.g. advertisements in ad-driven software like the Opera
+browser, or Adobe Reader.
+
+See the man page for more information.
diff --git a/version.h b/version.h
new file mode 100644
index 0000000..1eeff9a
--- /dev/null
+++ b/version.h
@@ -0,0 +1 @@
+#define VERSION "0.1"
diff --git a/version.rst b/version.rst
new file mode 100644
index 0000000..f502eab
--- /dev/null
+++ b/version.rst
@@ -0,0 +1 @@
+.. |version| replace:: 0.1
diff --git a/xdeadzone.1 b/xdeadzone.1
new file mode 100644
index 0000000..0e4a61d
--- /dev/null
+++ b/xdeadzone.1
@@ -0,0 +1,160 @@
+.\" Man page generated from reStructuredText.
+.
+.
+.nr rst2man-indent-level 0
+.
+.de1 rstReportMargin
+\\$1 \\n[an-margin]
+level \\n[rst2man-indent-level]
+level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
+-
+\\n[rst2man-indent0]
+\\n[rst2man-indent1]
+\\n[rst2man-indent2]
+..
+.de1 INDENT
+.\" .rstReportMargin pre:
+. RS \\$1
+. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
+. nr rst2man-indent-level +1
+.\" .rstReportMargin post:
+..
+.de UNINDENT
+. RE
+.\" indent \\n[an-margin]
+.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.nr rst2man-indent-level -1
+.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
+..
+.TH "XDEADZONE" 1 "2024-01-31" "0.1" "Urchlay's Misc Stuff"
+.SH NAME
+xdeadzone \- keep the mouse pointer out of the dead zone, on mismatched multihead displays.
+.\" RST source for xdeadzone(1) man page. Convert with:
+.
+.\" rst2man.py xdeadzone.rst > xdeadzone.1
+.
+.SH SYNOPSIS
+.sp
+xdeadzone [\fB\-nw\fP | \fB\-ne\fP | \fB\-sw\fP | \fB\-se\fP | \fB\-abs\fP \fIx\-position\fP \fIy\-position\fP] \fIwidth\fP \fIheight\fP
+.sp
+xdeadzone \fB\-\-help\fP | \fB\-\-version\fP
+.SH DESCRIPTION
+.sp
+xdeadzone\(aqs job is to create a window of a specified size, and prevent
+the mouse pointer from entering it.
+.sp
+The intended use for it is to keep the mouse out of the "dead zone"
+of a multi\-head X display where the monitors don\(aqt all have the same
+resolution.
+.sp
+It could also be useful for covering annoying parts of the screen,
+e.g. advertisements in ad\-driven software like the Opera browser, or
+Adobe Reader.
+.SH OPTIONS
+.INDENT 0.0
+.TP
+.B \-\-help
+Print built\-in help message and exit.
+.TP
+.B \-\-version
+Print the application name and version number, and exit.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \fB\-nw\fP
+Place window at northwest (top left) corner of display.
+.TP
+.B \fB\-ne\fP
+Place window at northeast (top right) corner of display.
+.TP
+.B \fB\-sw\fP
+Place window at southwest (bottom left) corner of display.
+.TP
+.B \fB\-se\fP
+Place window at southeast (bottom right) corner of display.
+.TP
+.B \fB\-abs\fP \fIx\-position\fP \fIy\-position\fP
+Place window at the given coordinates. Negative numbers will be
+treated as offsets from the right/bottom of the display.
+.TP
+.B \fBwidth\fP
+Width of the dead zone. Required; must be a positive integer.
+.TP
+.B \fBheight\fP
+Height of the dead zone. Required; must be a positive integer.
+.UNINDENT
+.SH ENVIRONMENT
+.INDENT 0.0
+.TP
+.B \fBDISPLAY\fP
+As usual for X applications: the X server to connect to.
+.UNINDENT
+.SH EXIT STATUS
+.sp
+With \fB\-\-help\fP or \fB\-\-version\fP, exit status is 0 (success).
+.sp
+If there\(aqs an error in the arguments, exit status is non\-zero (failure).
+.sp
+In normal operation, \fBxdeadzone\fP never exits.
+.SH EXAMPLES
+.sp
+You have a 1920x1080 LCD monitor on the left, and a 1280x1024
+one on the right. This gives you a nice 3200x1080 X display... but the
+mouse can "vanish", because X pretends the right\-hand monitor has
+1080 vertical pixels. So there\(aqs a 1280x56 horizontal strip "below" the
+bottom of the right\-hand monitor that doesn\(aqt get displayed. If the
+mouse moves into this area, the pointer disappears, and it\(aqs not
+obvious what happened to it.
+.sp
+To avoid losing the pointer, you can run this:
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+xdeadzone \-se 1280 56 &
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+\&...from your ~/.xinitrc (or whatever you use to run commands at X startup).
+.sp
+If you instead have the same two monitors in a vertical arrangement,
+with the 1280x1024 one on top, you\(aqll have a 640x1024 vertical strip
+of \(aqdead zone\(aq beyond the right edge of the top monitor. To avoid
+losing the mouse there:
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+xdeadzone \-ne 640 1024 &
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+If the dead zone were on the left of the top monitor, you\(aqd use \fB\-nw\fP instead
+of \fB\-ne\fP\&.
+.SH BUGS
+.sp
+There isn\(aqt much error\-checking for the numeric arguments. Anything
+non\-numeric will be read as zero. If you include a decimal point,
+that should be an error, but instead it\(aqs silently ignored (the value
+is truncated).
+.sp
+Maybe it should background (daemonize) itself. However, it works
+fine with & to background it, and this is pretty common practice for
+starting X software from ~/.xinitrc.
+.SH COPYRIGHT
+.sp
+WTFPL. Do WTF you want to with this.
+.sp
+See \fI\%http://www.wtfpl.net/txt/copying/\fP for details.
+.SH AUTHORS
+.sp
+\fBxdeadzone\fP was written by B. Watson (\fI\%urchlay@slackware.uk\fP).
+.\" Generated by docutils manpage writer.
+.
diff --git a/xdeadzone.c b/xdeadzone.c
new file mode 100644
index 0000000..ab36f8c
--- /dev/null
+++ b/xdeadzone.c
@@ -0,0 +1,197 @@
+/*
+ xdeadzone - create a window and don't allow the mouse pointer to enter it.
+
+ Operation is simple: set up our window, wait for events, and if we get
+ an EnterNotify event, warp the pointer out of our window.
+*/
+
+#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"
+
+/* define this to print some debug info at runtime. */
+// #define DEBUG
+
+#ifdef DEBUG
+# define DBG(x) x
+#else
+# define DBG(x)
+#endif
+
+const char *exe_name;
+
+void set_exe_name(const char *p) {
+ exe_name = p;
+ while(*p) {
+ if(*p == '/') exe_name = p + 1;
+ p++;
+ }
+}
+
+void banner(void) {
+ printf(NAME " " VERSION "\n");
+}
+
+void usage(const int ret) {
+ banner();
+ printf(
+ "Usage:\n %s "
+ "[-nw | -ne | -sw | -se | -abs xpos ypos] [width] [height]"
+ "\n",
+ exe_name);
+ exit(ret);
+}
+
+void errmsg(const char *msg) {
+ fprintf(stderr, "%s: %s\n", exe_name, msg);
+ usage(1);
+}
+
+int streq(const char *s1, const char *s2) {
+ return !strcmp(s1, s2);
+}
+
+int main(int argc, char **argv) {
+ Display *d;
+ Window w;
+ XEvent ev;
+ Atom dock_atom;
+ XWindowAttributes attr;
+ XSetWindowAttributes setattr;
+
+ int x = 0, y = 0, width = 0, height = 0;
+
+ set_exe_name(argv[0]);
+
+ if(argc < 2)
+ usage(1);
+
+ if(argc == 2) {
+ if(streq(argv[1], "--help")) {
+ usage(0);
+ } else if(streq(argv[1], "--version")) {
+ banner();
+ exit(0);
+ } else {
+ usage(1);
+ }
+ }
+
+ if(streq(argv[1], "-abs")) {
+ if(argc != 6)
+ errmsg("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("wrong number of arguments for non-abs mode");
+ width = atoi(argv[2]);
+ height = atoi(argv[3]);
+ if(streq(argv[1], "-nw")) {
+ x = 0; y = 0;
+ } else if(streq(argv[1], "-ne")) {
+ x = -width; y = 0;
+ } else if(streq(argv[1], "-sw")) {
+ x = 0; y = -height;
+ } else if(streq(argv[1], "-se")) {
+ x = -width; y = -height;
+ } else {
+ errmsg("invalid first argument (not -abs/-nw/-ne/-sw/-se)");
+ }
+ }
+
+ if(width <= 0 || height <= 0)
+ errmsg("width and height must be positive and non-zero");
+
+ if(!(d = XOpenDisplay(NULL)))
+ errmsg("can't open X display");
+
+ XGetWindowAttributes(d, DefaultRootWindow(d), &attr);
+ if(x < 0) x = attr.width + x;
+ if(y < 0) y = attr.height + y;
+
+ DBG(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?
+ */
+ setattr.override_redirect = True;
+ setattr.background_pixel = WhitePixel(d, DefaultScreen(d));
+ setattr.event_mask = EnterWindowMask;
+
+ w = XCreateWindow(d,
+ DefaultRootWindow(d),
+ x, y, width, height, 0,
+ CopyFromParent,
+ InputOutput,
+ CopyFromParent,
+ CWBackPixel | CWOverrideRedirect | CWEventMask,
+ &setattr);
+
+ DBG(printf("window created\n"));
+
+ 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(1) {
+ XNextEvent(d, &ev);
+ if(ev.type == EnterNotify) {
+ /* warp down if at top of screen */
+ int new_y = (y == 0 ? y + height : y - 1);
+
+ DBG(printf("Got EnterNotify, coords %d, %d, new Y is %d\n",
+ ev.xcrossing.x_root, ev.xcrossing.y_root, new_y));
+ XWarpPointer(d,
+ None,
+ DefaultRootWindow(d),
+ 0, 0, 0, 0,
+ ev.xcrossing.x_root,
+ new_y);
+ }
+ }
+
+ /* We should never get here (the loop above never exits).
+ The only way out is for us or the X server to be killed. */
+ XUnmapWindow(d, w);
+ XDestroyWindow(d, w);
+ XCloseDisplay(d);
+
+ return 0;
+}
diff --git a/xdeadzone.rst b/xdeadzone.rst
new file mode 100644
index 0000000..ff12bd7
--- /dev/null
+++ b/xdeadzone.rst
@@ -0,0 +1,136 @@
+.. RST source for xdeadzone(1) man page. Convert with:
+.. rst2man.py xdeadzone.rst > xdeadzone.1
+
+.. include:: version.rst
+.. |date| date::
+
+=========
+xdeadzone
+=========
+
+------------------------------------------------------------------------------
+keep the mouse pointer out of the dead zone, on mismatched multihead displays.
+------------------------------------------------------------------------------
+
+:Manual section: 1
+:Manual group: Urchlay's Misc Stuff
+:Date: |date|
+:Version: |version|
+
+SYNOPSIS
+========
+
+xdeadzone [**-nw** | **-ne** | **-sw** | **-se** | **-abs** *x-position* *y-position*] *width* *height*
+
+xdeadzone **--help** | **--version**
+
+DESCRIPTION
+===========
+
+xdeadzone's job is to create a window of a specified size, and prevent
+the mouse pointer from entering it.
+
+The intended use for it is to keep the mouse out of the "dead zone"
+of a multi-head X display where the monitors don't all have the same
+resolution.
+
+It could also be useful for covering annoying parts of the screen,
+e.g. advertisements in ad-driven software like the Opera browser, or
+Adobe Reader.
+
+OPTIONS
+=======
+
+--help
+ Print built-in help message and exit.
+
+--version
+ Print the application name and version number, and exit.
+
+**-nw**
+ Place window at northwest (top left) corner of display.
+
+**-ne**
+ Place window at northeast (top right) corner of display.
+
+**-sw**
+ Place window at southwest (bottom left) corner of display.
+
+**-se**
+ Place window at southeast (bottom right) corner of display.
+
+**-abs** *x-position* *y-position*
+ Place window at the given coordinates. Negative numbers will be
+ treated as offsets from the right/bottom of the display.
+
+**width**
+ Width of the dead zone. Required; must be a positive integer.
+
+**height**
+ Height of the dead zone. Required; must be a positive integer.
+
+ENVIRONMENT
+===========
+
+**DISPLAY**
+ As usual for X applications: the X server to connect to.
+
+EXIT STATUS
+===========
+
+With **--help** or **--version**, exit status is 0 (success).
+
+If there's an error in the arguments, exit status is non-zero (failure).
+
+In normal operation, **xdeadzone** never exits.
+
+EXAMPLES
+========
+
+You have a 1920x1080 LCD monitor on the left, and a 1280x1024
+one on the right. This gives you a nice 3200x1080 X display... but the
+mouse can "vanish", because X pretends the right-hand monitor has
+1080 vertical pixels. So there's a 1280x56 horizontal strip "below" the
+bottom of the right-hand monitor that doesn't get displayed. If the
+mouse moves into this area, the pointer disappears, and it's not
+obvious what happened to it.
+
+To avoid losing the pointer, you can run this::
+
+ xdeadzone -se 1280 56 &
+
+...from your ~/.xinitrc (or whatever you use to run commands at X startup).
+
+If you instead have the same two monitors in a vertical arrangement,
+with the 1280x1024 one on top, you'll have a 640x1024 vertical strip
+of 'dead zone' beyond the right edge of the top monitor. To avoid
+losing the mouse there::
+
+ xdeadzone -ne 640 1024 &
+
+If the dead zone were on the left of the top monitor, you'd use **-nw** instead
+of **-ne**.
+
+BUGS
+====
+
+There isn't much error-checking for the numeric arguments. Anything
+non-numeric will be read as zero. If you include a decimal point,
+that should be an error, but instead it's silently ignored (the value
+is truncated).
+
+Maybe it should background (daemonize) itself. However, it works
+fine with & to background it, and this is pretty common practice for
+starting X software from ~/.xinitrc.
+
+COPYRIGHT
+=========
+
+WTFPL. Do WTF you want to with this.
+
+See http://www.wtfpl.net/txt/copying/ for details.
+
+AUTHORS
+=======
+
+**xdeadzone** was written by B. Watson (urchlay@slackware.uk).