commit c592a9acbdccccf84009de2e0d68d0fca2d7a2d3
parent 852bc9bb1cf7bd8b0af65b5b3caa1378e6cda63c
Author: Louis Burda <quent.burda@gmail.com>
Date: Tue, 12 Apr 2022 22:39:49 +0200
Refactoring and added loader for usability
Diffstat:
M | .gitignore | | | 4 | +++- |
A | Makefile | | | 23 | +++++++++++++++++++++++ |
D | README | | | 13 | ------------- |
A | loader.c | | | 110 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
D | makefile | | | 5 | ----- |
D | test.sh | | | 5 | ----- |
A | winpl.c | | | 359 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
D | winpreload.c | | | 375 | ------------------------------------------------------------------------------- |
8 files changed, 495 insertions(+), 399 deletions(-)
diff --git a/.gitignore b/.gitignore
@@ -1 +1,3 @@
-winpreload.so
+winpl.so.o
+winpl.so
+winpl
diff --git a/Makefile b/Makefile
@@ -0,0 +1,23 @@
+CFLAGS = --std=gnu99 -Wmissing-prototypes -Wunused-variable -g
+LIB_FLAGS = $(CFLAGS) -nostartfiles -fPIC -shared -Wl,-soname,xwrap.so
+LOADER_FLAGS = $(CFLAGS)
+LDLIBS = -ldl -lX11 -lXinerama
+
+.PHONY: all clean
+
+all: winpl
+
+clean:
+ rm -f winpl winpl.so winpl.so.o
+
+winpl: loader.c winpl.so.o
+ $(CC) -o $@ $^ $(LOADER_FLAGS)
+
+winpl.so: winpl.c
+ $(CC) -o $@ $< $(LIB_FLAGS) $(LDLIBS)
+
+winpl.so.o: winpl.so
+ objcopy --input binary --output elf64-x86-64 \
+ --binary-architecture i386:x86-64 $< $@
+
+
diff --git a/README b/README
@@ -1,13 +0,0 @@
-winpreload
-==========
-
-
-Ideology
---------
-
-Winpreload is a non-invasive way of modifying window properties for
-windows created by a program through the use of LD_PRELOAD. This
-enables the user to set properties such as _NET_WM_WINDOW_TYPE to
-start the window as floating and adjust its position. Parameters
-are passed to winpreload via environment variables, which are
-prefixed with 'WINPRELOAD_'.
diff --git a/loader.c b/loader.c
@@ -0,0 +1,110 @@
+#include <stdlib.h>
+#include <stdbool.h>
+#include <string.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/stat.h>
+
+#define ARRLEN(x) (sizeof(x) / sizeof((x)[0]))
+
+#define ERROR(msg) { fprintf(stderr, "winpl: %s\n", msg); exit(1); }
+
+extern char _binary_winpl_so_start[];
+extern char _binary_winpl_so_end[];
+
+extern char **environ;
+
+static void write_lib(const char *filename);
+static bool parse_arg(const char *arg);
+
+static const char *conv[][2] = {
+ { "wx:", "WINPL_WX" },
+ { "wy:", "WINPL_WY" },
+ { "rwx:", "WINPL_RWX" },
+ { "rwy:", "WINPL_RWY" },
+ { "mwx:", "WINPL_MWX" },
+ { "mwy:", "WINPL_MWY" },
+ { "ww:", "WINPL_WW" },
+ { "wh:", "WINPL_WH" },
+ { "rww:", "WINPL_RWW" },
+ { "rwh:", "WINPL_RWH" },
+ { "center", "WINPL_CENTER" },
+ { "float", "WINPL_FLOAT" },
+};
+
+void
+write_lib(const char *filename)
+{
+ FILE *file;
+ void *data;
+ size_t expected, actual;
+
+ file = fopen(filename, "w+");
+ if (!file) ERROR("Failed to create temp file");
+
+ data = (void*) _binary_winpl_so_start;
+ expected = (size_t) (_binary_winpl_so_end - _binary_winpl_so_start);
+
+ actual = fwrite(data, 1, expected, file);
+ if (actual != expected) ERROR("Failed to write temp file");
+
+ fclose(file);
+}
+
+bool
+parse_arg(const char *arg)
+{
+ int i, len;
+
+ for (i = 0; i < ARRLEN(conv); i++) {
+ len = strlen(conv[i][0]);
+ if (strncmp(arg, conv[i][0], len))
+ continue;
+
+ if (conv[i][0][len-1] == ':') {
+ setenv(conv[i][1], arg + len, true);
+ } else if (!arg[len]) {
+ setenv(conv[i][1], "1", true);
+ } else {
+ return false;;
+ }
+
+ return true;
+ }
+
+ return false;
+}
+
+int
+main(int argc, char *const *argv)
+{
+ char *tmpfile = "/tmp/winpl.so";
+ struct stat st;
+ char *const *arg, *const *cmd;
+
+ if (argc < 1) return 0;
+
+ cmd = NULL;
+ for (arg = argv + 1; *arg; arg++) {
+ if (!strcmp(*arg, "--") && *(arg+1)) {
+ cmd = arg + 1;
+ break;
+ }
+
+ if (!parse_arg(*arg))
+ ERROR("Invalid argument");
+ }
+
+ if (cmd == NULL)
+ ERROR("Missing args separator");
+
+ if (stat(*cmd, &st))
+ ERROR("Binary not full path");
+
+ if (stat(tmpfile, &st))
+ write_lib(tmpfile);
+
+ setenv("LD_PRELOAD", tmpfile, true);
+
+ execve(*cmd, cmd, environ);
+}
diff --git a/makefile b/makefile
@@ -1,5 +0,0 @@
-CFLAGS = -nostartfiles -fPIC -shared -Wl,-soname,xwrap.so --std=gnu99
-LDLIBS = -ldl -lX11 -lXinerama
-
-winpreload.so: winpreload.c
- $(CC) -o $@ $< $(CFLAGS) $(LDLIBS)
diff --git a/test.sh b/test.sh
@@ -1,5 +0,0 @@
-#!/bin/bash
-
-SCRIPTPATH="$(dirname $(readlink -f "$0"))"
-LD_PRELOAD="$SCRIPTPATH/winpreload.so" xclock
-
diff --git a/winpl.c b/winpl.c
@@ -0,0 +1,359 @@
+/* original: https://www.mail-archive.com/devel@xfree86.org/msg05806.html */
+
+#include <X11/Xlib.h>
+#include <X11/X.h>
+#include <X11/Xatom.h>
+#include <X11/extensions/Xinerama.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/utsname.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <stdarg.h>
+#include <string.h>
+#include <dlfcn.h>
+#include <unistd.h>
+
+#define MAX(a,b) ((a > b) ? a : b)
+#define MIN(a,b) ((a < b) ? a : b)
+
+#define ERROR(msg) { fprintf(stderr, "winpl: %s\n", msg); exit(1); }
+
+extern char **environ;
+
+static const char prefix[] = "WINPL_";
+static const int prefixlen = sizeof(prefix) - 1;
+
+static void *lib_xlib = NULL;
+
+static char **iter_args(char **env, const char **key, size_t *keylen,
+ const char **val);
+
+static int intersection_area(XineramaScreenInfo *info, XWindowAttributes *wa);
+
+static int monitor_from_pointer(XineramaScreenInfo *info, int mcount,
+ Display *display, Window window);
+static int monitor_from_focussed(Display *display, XineramaScreenInfo *info,
+ int mcount);
+
+static void set_prop(Display *display, Window window, const char *name,
+ int type, size_t size, void *val);
+static void set_props(Display *display, Window window);
+
+char **
+iter_args(char **env, const char **key, size_t *keylen, const char **val)
+{
+ const char *tok;
+
+ for (; *env; env++) { \
+ if (strncmp(*env, prefix, prefixlen))
+ continue;
+ *key = *env + prefixlen;
+ tok = strchr(*env, '=');
+ if (!tok) continue;
+ *keylen = tok - *env - prefixlen;
+ *val = tok + 1;
+ return env + 1;
+ }
+
+ return NULL;
+}
+
+int
+intersection_area(XineramaScreenInfo *info, XWindowAttributes *wa)
+{
+ int dx, dy;
+
+ dx = MIN(wa->x + wa->width, info->x_org + info->width);
+ dx -= MAX(wa->x, info->x_org);
+
+ dy = MIN(wa->y + wa->height, info->y_org + info->height);
+ dy -= MAX(wa->y, info->y_org);
+
+ return MAX(0, dx) * MAX(0, dy);
+}
+
+int
+monitor_from_pointer(XineramaScreenInfo *info, int mcount,
+ Display *display, Window window)
+{
+ Window dummy;
+ int x = 0, y = 0, di, i, screen;
+ unsigned int dui;
+
+ screen = -1;
+ XQueryPointer(display, window, &dummy, &dummy,
+ &x, &y, &di, &di, &dui);
+
+ for (i = 0; i < mcount; i++) {
+ if (x >= info[i].x_org && y >= info[i].y_org
+ && x < info[i].x_org + info[i].width
+ && y < info[i].y_org + info[i].height) {
+ screen = i;
+ break;
+ }
+ }
+
+ return screen;
+}
+
+#define INTERSECT(x,y,w,h,r) (
+
+
+int
+monitor_from_focussed(Display *display, XineramaScreenInfo *info, int mcount)
+{
+ Window w, root, *dws, dw, pw;
+ XWindowAttributes wa;
+ int di, area, maxarea, i;
+ unsigned du;
+ int screen;
+
+ screen = -1;
+ root = XDefaultRootWindow(display);
+
+ /* check if a focussed window exists.. */
+ XGetInputFocus(display, &w, &di);
+
+ /* modified snippet from dmenu-4.9 source */
+ if (w != root && w != PointerRoot && w != None) {
+ do {
+ if (XQueryTree(display, (pw = w), &dw, &w, &dws, &du) && dws)
+ XFree(dws);
+ } while (w != root && w != pw);
+
+ /* find xinerama screen with largest screen intersection */
+ if (XGetWindowAttributes(display, pw, &wa)) {
+ for (i = 0; i < mcount; i++) {
+ area = intersection_area(&info[i], &wa);
+ if (area > maxarea) {
+ maxarea = area;
+ screen = i;
+ }
+ }
+ }
+ }
+
+ return screen;
+}
+
+void
+set_prop(Display *display, Window window, const char *name,
+ int type, size_t size, void *val)
+{
+ int atom;
+
+ atom = XInternAtom(display, name, False);
+ XChangeProperty(display, window, atom, type, size,
+ PropModeReplace, val, 1);
+}
+
+void
+set_props(Display *display, Window window)
+{
+ int wx, wy, mx, my;
+ unsigned int ww, wh, mw, mh;
+ const char *key, *val;
+ unsigned int border, depth;
+ size_t keylen;
+ char **env;
+ Window root;
+ Atom atom;
+ pid_t pid, ppid;
+ uid_t uid;
+
+ uid = getuid();
+ pid = getpid();
+ ppid = getppid();
+
+ if (!XGetGeometry(display, window, &root,
+ &wx, &wy, &ww, &wh, &border, &depth))
+ ERROR("Failed to get window geometry");
+
+ if (!XGetGeometry(display, root, &root,
+ &mx, &my, &mw, &mh, &border, &depth))
+ ERROR("Failed to get screen geometry");
+
+ if (XineramaIsActive(display)) {
+ XineramaScreenInfo *info;
+ int mcount, screen;
+
+ if (!(info = XineramaQueryScreens(display, &mcount)))
+ ERROR("Failed to query xinerama");
+
+ screen = -1;
+
+ env = environ;
+ while ((env = iter_args(env, &key, &keylen, &val))) {
+ if (!strncmp("SCREEN_NUM", key, keylen)) {
+ screen = strtoul(val, NULL, 0);
+ if (screen >= mcount || screen < 0)
+ ERROR("Screen out-of-bounds");
+ } else if (!strncmp("SCREEN_PTR", key, keylen)) {
+ screen = monitor_from_pointer(info,
+ mcount, display, window);
+ }
+ }
+
+ if (screen == -1)
+ screen = monitor_from_focussed(display,
+ info, mcount);
+
+ if (screen == -1)
+ screen = monitor_from_pointer(info, mcount,
+ display, window);
+
+ if (screen == -1)
+ ERROR("Failed to get screen");
+
+ mx = info[screen].x_org;
+ my = info[screen].y_org;
+ mw = info[screen].width;
+ mh = info[screen].height;
+ }
+
+ env = environ;
+ while ((env = iter_args(env, &key, &keylen, &val))) {
+ if (!strncmp(key, "WX", keylen)) {
+ /* absolute window x */
+ wx = strtoul(val, NULL, 0);
+ } else if (!strncmp(key, "WY", keylen)) {
+ /* absolute window y */
+ wy = strtoul(val, NULL, 0);
+ } else if (!strncmp(key, "RWX", keylen)) {
+ /* window x relative to monitor size */
+ wx = mw * strtof(val, NULL);
+ } else if (!strncmp(key, "RWY", keylen)) {
+ /* window y relative to monitor size */
+ wy = mh * strtof(val, NULL);
+ } else if (!strncmp(key, "MWX", keylen)) {
+ /* window x from monitor top left */
+ wx = mx + strtoul(val, NULL, 0);
+ } else if (!strncmp(key, "MWY", keylen)) {
+ /* window y from monitor top left */
+ wy = my + strtoul(val, NULL, 0);
+ } else if (!strncmp(key, "WW", keylen)) {
+ /* window width */
+ ww = strtoul(val, NULL, 0);
+ } else if (!strncmp(key, "WH", keylen)) {
+ /* window height */
+ wh = strtoul(val, NULL, 0);
+ } else if (!strncmp(key, "RWW", keylen)) {
+ /* window width relative to monitor size */
+ ww = mw * strtof(val, NULL);
+ } else if (!strncmp(key, "RWH", keylen)) {
+ /* window height relative to monitor size */
+ wh = mh * strtof(val, NULL);
+ } else if (!strncmp(key, "CENTER", keylen)) {
+ /* window centered in monitor */
+ wx = mx + (mw - ww) / 2.f;
+ wy = my + (mh - wh) / 2.f;
+ } else if (!strncmp(key, "FLOAT", keylen)) {
+ /* window 'floating' in tiled WM */
+ atom = XInternAtom(display,
+ "_NET_WM_WINDOW_TYPE_DIALOG", False);
+ set_prop(display, window, "_NET_WM_WINDOW_TYPE",
+ XA_ATOM, 32, &atom);
+ }
+ }
+
+ /* set basic properties */
+ set_prop(display, window, "_NET_WM_UID",
+ XA_CARDINAL, 32, &uid);
+ set_prop(display, window, "_NET_WM_PID",
+ XA_CARDINAL, 32, &pid);
+ set_prop(display, window, "_NET_WM_PPID",
+ XA_CARDINAL, 32, &ppid);
+
+ /* update window pos and geometry */
+ XMoveWindow(display, window, wx, wy);
+ XResizeWindow(display, window, ww, wh);
+}
+
+Window
+XCreateWindow(Display *display, Window parent, int x, int y,
+ unsigned int width, unsigned int height, unsigned int border_width,
+ int depth, unsigned int class, Visual *visual, unsigned long valuemask,
+ XSetWindowAttributes *attributes)
+{
+ static Window (*func)(Display *display, Window parent, int x, int y,
+ unsigned int width, unsigned int height,
+ unsigned int border_width, int depth, unsigned int class,
+ Visual *visual, unsigned long valuemask,
+ XSetWindowAttributes *attributes) = NULL;
+ Window window;
+ int i;
+
+ if (!lib_xlib) lib_xlib = dlopen("libX11.so", RTLD_GLOBAL | RTLD_LAZY);
+ if (!func) func = dlsym (lib_xlib, "XCreateWindow");
+
+ for (i = 0; i < ScreenCount(display); i++) {
+ /* for toplevel windows */
+ if (parent == RootWindow(display, i)) {
+ window = (*func) (display, parent, x, y, width, height,
+ border_width, depth, class, visual, valuemask, attributes);
+ set_props(display, window);
+ return window;
+ }
+ }
+
+ /* create window as usual */
+ return (*func) (display, parent, x, y, width, height, border_width, depth,
+ class, visual, valuemask, attributes);
+}
+
+Window
+XCreateSimpleWindow(Display *display, Window parent, int x, int y,
+ unsigned int width, unsigned int height, unsigned int border_width,
+ unsigned long border, unsigned long background)
+{
+ static Window (*func)(Display *display, Window parent, int x, int y,
+ unsigned int width, unsigned int height,
+ unsigned int border_width, unsigned long border,
+ unsigned long background) = NULL;
+ Window window;
+ int i;
+
+ if (!lib_xlib) lib_xlib = dlopen("libX11.so", RTLD_GLOBAL | RTLD_LAZY);
+ if (!func) func = dlsym (lib_xlib, "XCreateSimpleWindow");
+
+ for (i = 0; i < ScreenCount(display); i++) {
+ /* for toplevel windows */
+ if (parent == RootWindow(display, i)) {
+ window = (*func) (display, parent, x, y, width, height,
+ border_width, border, background);
+ set_props(display, window);
+ return window;
+ }
+ }
+
+ /* create window as usual */
+ return (*func) (display, parent, x, y, width, height,
+ border_width, border, background);
+}
+
+int
+XReparentWindow(Display *display, Window window, Window parent, int x, int y)
+{
+ static int (*func)(Display *display, Window window, Window parent,
+ int x, int y) = NULL;
+ int i;
+
+ if (!lib_xlib) lib_xlib = dlopen("libX11.so", RTLD_GLOBAL | RTLD_LAZY);
+ if (!func) func = dlsym (lib_xlib, "XReparentWindow");
+
+ for (i = 0; i < ScreenCount(display); i++) {
+ /* for toplevel windows */
+ if (parent == RootWindow(display, i)) {
+ set_props(display, window);
+ return (*func)(display, window, parent, x, y);
+ }
+ }
+
+ /* reparent as usual */
+ return (*func) (display, window, parent, x, y);
+}
+
diff --git a/winpreload.c b/winpreload.c
@@ -1,375 +0,0 @@
-/* original source by https://www.mail-archive.com/devel@xfree86.org/msg05806.html */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#include <string.h>
-#include <dlfcn.h>
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/utsname.h>
-#include <X11/Xlib.h>
-#include <X11/X.h>
-#include <X11/Xatom.h>
-#include <X11/extensions/Xinerama.h>
-
-extern char **environ;
-
-static const char env_prefix[] = "WINPL_";
-static const int env_prefixlen = sizeof(env_prefix) - 1;
-/* dlopened xlib so we can find the symbols in the real xlib to call them */
-static void *lib_xlib = NULL;
-
-#define MAX(a,b) ((a > b) ? a : b)
-#define MIN(a,b) ((a < b) ? a : b)
-#define INTERSECT(x,y,w,h,r) (MAX(0, MIN((x)+(w),(r).x_org+(r).width) \
- - MAX((x),(r).x_org)) \
- * MAX(0, MIN((y)+(h),(r).y_org+(r).height) \
- - MAX((y),(r).y_org)))
-#define ERRQUIT(msg) { fprintf(stderr, msg); exit(1); }
-#define ENVPARSE(...) \
- { \
- char **__envvar, *__enviter, *key, *value, __varbuf[256]; \
- for (__envvar = environ; *__envvar; __envvar++) { \
- strncpy(__varbuf, *__envvar, sizeof(__varbuf) - 1); \
- __varbuf[sizeof(__varbuf) - 1] = '\0'; \
- __enviter = strchr(__varbuf, '='); \
- if (!__enviter) continue; \
- *__enviter = '\0'; \
- key = __varbuf; \
- value = __enviter + 1; \
- if (strncmp(key, env_prefix, env_prefixlen)) \
- continue; \
- key = &key[env_prefixlen]; \
- __VA_ARGS__ \
- } \
- }
-#define SETFMTPROP(name, format, val) \
- { \
- int __atom; \
- char __buf[1024]; \
- snprintf(__buf, sizeof(__buf), format, val); \
- __atom = XInternAtom(display, name, False); \
- XChangeProperty(display, window, __atom, XA_STRING, 8, \
- PropModeReplace, (unsigned char*) __buf, strlen(__buf)); \
- }
-#define SETPROP(name, type, size, val) \
- { \
- int __atom; \
- __atom = XInternAtom(display, name, False); \
- XChangeProperty(display, window, __atom, type, size, \
- PropModeReplace, val, 1); \
- }
-
-/* prototypes */
-static void set_properties(Display *display, Window window);
-
-int
-monitor_by_pointer(XineramaScreenInfo *info, int mcount,
- Display *display, Window window)
-{
- Window dummy;
- int x = 0, y = 0, di, i, screen;
- unsigned int dui;
-
- /* determine monitor by where the pointer is */
- XQueryPointer(display, window, &dummy, &dummy,
- &x, &y, &di, &di, &dui);
-
- for (screen = i = 0; i < mcount; i++) {
- if (x >= info[i].x_org && y >= info[i].y_org
- && x < info[i].x_org + info[i].width
- && y < info[i].y_org + info[i].height) {
- screen = i;
- break;
- }
- }
-
- if (i == mcount)
- return -1;
- else
- return screen;
-}
-
-void
-set_properties(Display *display, Window window)
-{
- int wx, wy, mx, my;
- unsigned int ww, wh, mw, mh;
- char *env = NULL;
-
- {
- Window root;
- unsigned int border, depth;
-
- /* get window geometry */
- if (!XGetGeometry(display, window, &root,
- &wx, &wy, &ww, &wh, &border, &depth))
- ERRQUIT("winpreload: unable to determine window geometry\n");
-
- /* use root geometry for monitor as default */
- if (!XGetGeometry(display, root, &root,
- &mx, &my, &mw, &mh, &border, &depth))
- ERRQUIT("winpreload: unable to determine screen geometry\n");
- }
-
- /* parse env for screen-related vars first */
- if (XineramaIsActive(display)) {
- XineramaScreenInfo *info;
- int mcount, screen, set;
-
- if (!(info = XineramaQueryScreens(display, &mcount)))
- goto cleanup_xinerama;
-
- /* NOTE:
- * for dwm (tested ver 4.9), windows are contrained to the dimensions of
- * their monitor (which is the selected monitor on creation). Because of
- * this, it is not possible to init the screen position outside the
- * selected monitor.. a patch of dwm or some kind of signal that the
- * selected monitor should be changed is necessary
- */
- screen = 0;
- set = 0;
- ENVPARSE(
- if (!strcmp("SCREEN_NUM", key)) {
- set = 1;
- screen = strtoul(value, NULL, 0);
- if (screen >= mcount)
- ERRQUIT("winpreload: invalid screen number specified\n");
- } else if (!strcmp("SCREEN_PTR", key)) {
- set = 1;
- screen = monitor_by_pointer(info, mcount, display, window);
- if (screen == -1)
- goto cleanup_xinerama;
- }
- )
-
- if (!set) {
- Window w, root, *dws, dw, pw;
- XWindowAttributes wa;
- int di, a, area, i;
- unsigned du;
-
- root = XDefaultRootWindow(display);
- screen = -1;
-
- /* check if a focussed window exists.. */
- XGetInputFocus(display, &w, &di);
- /* modified snippet from dmenu-4.9 source */
- if (w != root && w != PointerRoot && w != None) {
- do {
- if (XQueryTree(display, (pw = w), &dw, &w, &dws, &du) && dws)
- XFree(dws);
- } while (w != root && w != pw);
- /* find xinerama screen with which the window intersects most */
- if (XGetWindowAttributes(display, pw, &wa)) {
- for (i = 0; i < mcount; i++) {
- a = INTERSECT(wa.x, wa.y, wa.width, wa.height, info[i]);
- if (a > area) {
- area = a;
- screen = i;
- }
- }
- }
- }
-
- /* ..else try by pointer */
- if (screen == -1) {
- screen = monitor_by_pointer(info, mcount, display, window);
- if (screen == -1)
- goto cleanup_xinerama;
- }
- }
-
- mx = info[screen].x_org;
- my = info[screen].y_org;
- mw = info[screen].width;
- mh = info[screen].height;
-
-cleanup_xinerama:
- XFree(info);
- }
-
- ENVPARSE(
- if (!strcmp(key, "WX")) { /* absolute window x */
- wx = strtoul(value, NULL, 0);
- } else if (!strcmp(key, "WY")) { /* absolute window y */
- wy = strtoul(value, NULL, 0);
- } else if (!strcmp(key, "RWX")) { /* window x relative to monitor rsize */
- wx = mw * strtof(value, NULL);
- } else if (!strcmp(key, "RWY")) { /* window y relative to monitor size */
- wy = mh * strtof(value, NULL);
- } else if (!strcmp(key, "MWX")) { /* window x from monitor top left */
- wx = mx + strtoul(value, NULL, 0);
- } else if (!strcmp(key, "MWY")) { /* window y from monitor top left */
- wy = my + strtoul(value, NULL, 0);
- } else if (!strcmp(key, "WW")) { /* window width */
- ww = strtoul(value, NULL, 0);
- } else if (!strcmp(key, "WH")) { /* window height */
- wh = strtoul(value, NULL, 0);
- } else if (!strcmp(key, "RWW")) { /* window width relative to monitor size */
- ww = mw * strtof(value, NULL);
- } else if (!strcmp(key, "RWH")) { /* window height relative to monitor size */
- wh = mh * strtof(value, NULL);
- } else if (!strcmp(key, "CENTER")) { /* window centered in monitor */
- wx = mx + (mw - ww) / 2.f;
- wy = my + (mh - wh) / 2.f;
- } else if (!strcmp(key, "FLOAT")) { /* window 'floating' in tiled WM */
- Atom atom;
-
- atom = XInternAtom(display, "_NET_WM_WINDOW_TYPE_DIALOG", False);
- SETPROP("_NET_WM_WINDOW_TYPE", XA_ATOM, 32, (void*) &atom);
- } else {
- SETFMTPROP(key, "%s", value);
- }
- )
-
- {
- uid_t uid;
- pid_t pid, ppid;
-
- uid = getuid();
- pid = getpid();
- ppid = getppid();
-
- /* set basic properties */
- SETPROP("_NET_WM_UID", XA_CARDINAL, 32, (void*) &uid);
- SETPROP("_NET_WM_PID", XA_CARDINAL, 32, (void*) &pid);
- SETPROP("_NET_WM_PPID", XA_CARDINAL, 32, (void*) &ppid);
- }
-
- /* update window pos and geometry */
- XMoveWindow(display, window, wx, wy);
- XResizeWindow(display, window, ww, wh);
-}
-
-/* XCreateWindow intercept */
-Window
-XCreateWindow(
- Display *display,
- Window parent,
- int x, int y,
- unsigned int width, unsigned int height,
- unsigned int border_width,
- int depth,
- unsigned int class,
- Visual *visual,
- unsigned long valuemask,
- XSetWindowAttributes *attributes)
-{
- static Window (*func)(
- Display *display,
- Window parent,
- int x, int y,
- unsigned int width, unsigned int height,
- unsigned int border_width,
- int depth,
- unsigned int class,
- Visual *visual,
- unsigned long valuemask,
- XSetWindowAttributes *attributes) = NULL;
- int i;
-
- /* find the real Xlib and the real X function */
- if (!lib_xlib) lib_xlib = dlopen("libX11.so", RTLD_GLOBAL | RTLD_LAZY);
- if (!func) func = dlsym (lib_xlib, "XCreateWindow");
-
- /* multihead screen handling loop */
- for (i = 0; i < ScreenCount(display); i++) {
- /* if the window is created as a toplevel window */
- if (parent == RootWindow(display, i)) {
- Window window;
-
- /* create and set properties */
- window = (*func) (display, parent, x, y, width, height,
- border_width, depth, class, visual, valuemask, attributes);
- set_properties(display, window);
-
- return window;
- }
- }
-
- /* normal child window - create without properties */
- return (*func) (display, parent, x, y, width, height, border_width, depth,
- class, visual, valuemask, attributes);
-}
-
-/* XCreateSimpleWindow intercept */
-Window
-XCreateSimpleWindow(
- Display *display,
- Window parent,
- int x, int y,
- unsigned int width, unsigned int height,
- unsigned int border_width,
- unsigned long border,
- unsigned long background)
-{
- static Window (*func)(
- Display *display,
- Window parent,
- int x, int y,
- unsigned int width, unsigned int height,
- unsigned int border_width,
- unsigned long border,
- unsigned long background) = NULL;
- int i;
-
- /* find the real Xlib and the real X function */
- if (!lib_xlib) lib_xlib = dlopen("libX11.so", RTLD_GLOBAL | RTLD_LAZY);
- if (!func) func = dlsym (lib_xlib, "XCreateSimpleWindow");
-
- /* multihead screen handling loop */
- for (i = 0; i < ScreenCount(display); i++) {
- /* if the window is created as a toplevel window */
- if (parent == RootWindow(display, i)) {
- Window window;
-
- /* create and set properties */
- window = (*func) (display, parent, x, y, width, height,
- border_width, border, background);
- set_properties(display, window);
- return window;
- }
- }
-
- /* normal child window - create as usual */
- return (*func) (display, parent, x, y, width, height,
- border_width, border, background);
-}
-
-/* XReparentWindow intercept */
-int
-XReparentWindow(
- Display *display,
- Window window,
- Window parent,
- int x, int y)
-{
- static int (*func)(
- Display *display,
- Window window,
- Window parent,
- int x, int y) = NULL;
- int i;
-
- /* find the real Xlib and the real X function */
- if (!lib_xlib) lib_xlib = dlopen("libX11.so", RTLD_GLOBAL | RTLD_LAZY);
- if (!func) func = dlsym (lib_xlib, "XReparentWindow");
-
- /* multihead screen handling loop */
- for (i = 0; i < ScreenCount(display); i++) {
- /* if the window is created as a toplevel window */
- if (parent == RootWindow(display, i)) {
-
- /* set properties and reparent */
- set_properties(display, window);
- return (*func) (display, window, parent, x, y);
- }
- }
-
- /* normal child window - reparent as usual */
- return (*func) (display, window, parent, x, y);
-}
-