winpl

LD_PRELOAD-based X11 window manipulator
git clone https://git.sinitax.com/sinitax/winpl
Log | Files | Refs | LICENSE | sfeed.txt

commit 38bb70b47cbceaba2a2ce515edbb4251f8ed4841
parent 9db814afb5690daef79b7494625dd12165ccc786
Author: Louis Burda <quent.burda@gmail.com>
Date:   Sat,  3 Oct 2020 12:19:12 +0200

Fix WINPRELOAD_POS_CENTER for single monitor

Diffstat:
MREADME | 2+-
Ddwm-scraps.c | 74--------------------------------------------------------------------------
Mmakefile | 2+-
Mwinpreload.c | 53+++++++++++++++++++++++++++++++++++++++--------------
4 files changed, 41 insertions(+), 90 deletions(-)

diff --git a/README b/README @@ -10,4 +10,4 @@ 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+'. +prefixed with 'WINPRELOAD_'. diff --git a/dwm-scraps.c b/dwm-scraps.c @@ -1,74 +0,0 @@ -#ifdef XINERAMA - if (XineramaIsActive(dpy)) { - int i, j, n, nn; - Client *c; - Monitor *m; - XineramaScreenInfo *info = XineramaQueryScreens(dpy, &nn); - XineramaScreenInfo *unique = NULL; - - for (n = 0, m = mons; m; m = m->next, n++); - /* only consider unique geometries as separate screens */ - unique = ecalloc(nn, sizeof(XineramaScreenInfo)); - for (i = 0, j = 0; i < nn; i++) - if (isuniquegeom(unique, j, &info[i])) - memcpy(&unique[j++], &info[i], sizeof(XineramaScreenInfo)); - XFree(info); - nn = j; - if (n <= nn) { /* new monitors available */ - for (i = 0; i < (nn - n); i++) { - for (m = mons; m && m->next; m = m->next); - if (m) - m->next = createmon(); - else - mons = createmon(); - } - for (i = 0, m = mons; i < nn && m; m = m->next, i++) - if (i >= n - || unique[i].x_org != m->mx || unique[i].y_org != m->my - || unique[i].width != m->mw || unique[i].height != m->mh) - { - dirty = 1; - m->num = i; - m->mx = m->wx = unique[i].x_org; - m->my = m->wy = unique[i].y_org; - m->mw = m->ww = unique[i].width; - m->mh = m->wh = unique[i].height; - updatebarpos(m); - } - } else { /* less monitors available nn < n */ - for (i = nn; i < n; i++) { - for (m = mons; m && m->next; m = m->next); - while ((c = m->clients)) { - dirty = 1; - m->clients = c->next; - detachstack(c); - c->mon = mons; - attach(c); - attachstack(c); - } - if (m == selmon) - selmon = mons; - cleanupmon(m); - } - } - free(unique); - } else -#endif /* XINERAMA */ - { /* default monitor setup */ - if (!mons) - mons = createmon(); - if (mons->mw != sw || mons->mh != sh) { - dirty = 1; - mons->mw = mons->ww = sw; - mons->mh = mons->wh = sh; - updatebarpos(mons); - } - } - if (dirty) { - selmon = mons; - selmon = wintomon(root); - } - return dirty; - -could use intersection of window rectangle and monitor to get which. -for new windows is probably always the first monitor. diff --git a/makefile b/makefile @@ -1,5 +1,5 @@ CFLAGS = -nostartfiles -fPIC -shared -Wl,-soname,xwrap.so -LDLIBS = -ldl -lX11 +LDLIBS = -ldl -lX11 -lXinerama winpreload.so: winpreload.c $(CC) -o $@ $< $(CFLAGS) $(LDLIBS) diff --git a/winpreload.c b/winpreload.c @@ -12,6 +12,7 @@ #include <X11/Xlib.h> #include <X11/X.h> #include <X11/Xatom.h> +#include <X11/extensions/Xinerama.h> extern char **environ; @@ -41,25 +42,45 @@ static void set_properties(Display *display, Window window); void set_properties(Display *display, Window window) { - int wx, wy, dx, dy, atom = 0; - unsigned int ww, wh, dw, dh; + int wx, wy, mx, my, atom = 0; + unsigned int ww, wh, mw, mh; char *env = NULL; { Window root; unsigned int width, height, border, depth; - Screen *screen = XDefaultScreenOfDisplay(display); - dw = screen->width; - dh = screen->height; - - XGetGeometry(display, screen->root, - &root, &dx, &dy, &width, &height, &border, &depth); XGetGeometry(display, window, &root, &wx, &wy, &ww, &wh, &border, &depth); - } - printf("%i %i %i %i\n", dx, dy, dw, dh); + /* get monitor that intersects window rect */ + if (XineramaIsActive(display)) { + int mcount, i; + XineramaScreenInfo *info, target; + + info = XineramaQueryScreens(display, &mcount); + + for (i = 0; i < mcount; i++) { + if ((target.x_org != info[i].x_org + || target.y_org != info[i].y_org) + && wx >= info[i].x_org && wy >= info[i].y_org + && wx < info[i].x_org + info[i].width + && wy < info[i].y_org + info[i].height) { + target = info[i]; + } + } + + mx = target.x_org; + my = target.y_org; + mw = target.width; + mh = target.height; + + XFree(info); + } else { + XGetGeometry(display, root, &root, &mx, &my, + &mw, &mh, &border, &depth); + } + } char **s, *iter, *key, *value; for (s = environ; *s; s++) { @@ -77,12 +98,16 @@ set_properties(Display *display, Window window) key = &key[env_prefixlen]; if (!strcmp(key, "POS_X")) { - wx = dx + atoi(value); + wx = mx + atoi(value); } else if (!strcmp(key, "POS_Y")) { - wy = dy + atoi(value); + wy = my + atoi(value); + } else if (!strcmp(key, "RPOS_X")) { + wx = atoi(value); + } else if (!strcmp(key, "RPOS_Y")) { + wy = atoi(value); } else if (!strcmp(key, "POS_CENTER")) { - wx = dx + dw / 2.f; - wy = dy + dh / 2.f; + wx = mx + (mw - ww) / 2.f; + wy = my + (mh - ww) / 2.f; } else if (!strcmp(key, "DIALOG")) { Atom a;