commit fc07478b5613836acf8bdf0d5435991fbf74fb26
parent 5091f8cafd069f478f5dfc4e2e611cb81f5d50eb
Author: Lucas de Sena <lucas@seninha.org>
Date: Sat, 14 Jan 2023 19:09:02 -0300
replace xinerama with xrandr; fix dock placement
Diffstat:
M | Makefile | | | 2 | +- |
M | shod.c | | | 14 | +++++++++----- |
M | shod.h | | | 8 | ++++++++ |
M | xdock.c | | | 75 | +++++++++++++++++++++++++++++++++++++++++---------------------------------- |
M | xevents.c | | | 16 | ---------------- |
M | xmon.c | | | 149 | ++++++++++++++++++++++++++++++++++++++----------------------------------------- |
6 files changed, 130 insertions(+), 134 deletions(-)
diff --git a/Makefile b/Makefile
@@ -8,7 +8,7 @@ X11LIB ?= /usr/X11R6/lib
# includes and libs
XCPPFLAGS = -I${LOCALINC} -I${X11INC} -I/usr/include/freetype2 -I${X11INC}/freetype2
-XLDFLAGS = -L${LOCALLIB} -L${X11LIB} -lfontconfig -lXft -lX11 -lXinerama -lXrender
+XLDFLAGS = -L${LOCALLIB} -L${X11LIB} -lfontconfig -lXft -lX11 -lXrandr -lXrender
SHOD_OBJS = shod.o config.o xhints.o xmon.o xdraw.o xevents.o \
xcontainer.o xmenu.o xbar.o xdock.o xsplash.o xnotif.o xprompt.o
diff --git a/shod.c b/shod.c
@@ -9,6 +9,8 @@
#include <string.h>
#include <unistd.h>
+#include <X11/extensions/Xrandr.h>
+
#include "shod.h"
#define WMNAME "shod"
@@ -345,6 +347,7 @@ main(int argc, char *argv[])
warnx("warning: no locale support");
xinit();
checkotherwm();
+ moninit();
xinitvisual();
XrmInitialize();
xrm = XResourceManagerString(dpy);
@@ -406,12 +409,13 @@ main(int argc, char *argv[])
/* run main event loop */
while (running && !XNextEvent(dpy, &ev)) {
- if (xevents[ev.type]) {
- wm.setclientlist = 0;
+ wm.setclientlist = 0;
+ if (wm.xrandr && ev.type - wm.xrandrev == RRScreenChangeNotify)
+ monevent(&ev);
+ else if (ev.type < LASTEvent && xevents[ev.type] != NULL)
(*xevents[ev.type])(&ev);
- if (wm.setclientlist) {
- ewmhsetclients();
- }
+ if (wm.setclientlist) {
+ ewmhsetclients();
}
}
diff --git a/shod.h b/shod.h
@@ -538,6 +538,12 @@ struct WM {
int nclients; /* total number of container windows */
/*
+ * Xrandr information.
+ */
+ int xrandr; /* whether Xrandr is being used */
+ int xrandrev; /* event base for Xrandr */
+
+ /*
* Containers are listed by the focusq queue; they are also
* listed under the stackq list, ordered by its position on
* the Z-axis.
@@ -713,6 +719,8 @@ void mondel(struct Monitor *mon);
void monupdate(void);
void monupdatearea(void);
void fitmonitor(struct Monitor *mon, int *x, int *y, int *w, int *h, float factor);
+void moninit(void);
+void monevent(XEvent *e);
/* wm hints and messages routines */
void icccmdeletestate(Window win);
diff --git a/xdock.c b/xdock.c
@@ -91,10 +91,12 @@ dockapppos(int pos)
void
dockupdateresizeable(void)
{
+ struct Monitor *mon;
struct Object *p;
struct Dockapp *dapp;
int size;
+ mon = TAILQ_FIRST(&wm.monq);
size = 0;
TAILQ_FOREACH(p, &dock.dappq, entry) {
dapp = (struct Dockapp *)p;
@@ -137,60 +139,63 @@ dockupdateresizeable(void)
switch (config.dockgravity[0]) {
case 'N':
dock.h = config.dockwidth;
- dock.y = 0;
+ dock.x = mon->mx;
+ dock.y = mon->my;
break;
case 'S':
dock.h = config.dockwidth;
- dock.y = TAILQ_FIRST(&wm.monq)->mh - config.dockwidth;
+ dock.x = mon->mx;
+ dock.y = mon->my + mon->mh - config.dockwidth;
break;
case 'W':
dock.w = config.dockwidth;
- dock.x = 0;
+ dock.x = mon->mx;
+ dock.y = mon->my;
break;
case 'E':
default:
dock.w = config.dockwidth;
- dock.x = TAILQ_FIRST(&wm.monq)->mw - config.dockwidth;
- dock.h = min(size, TAILQ_FIRST(&wm.monq)->mh);
- dock.y = TAILQ_FIRST(&wm.monq)->mh / 2 - size / 2;
+ dock.x = mon->mx + mon->mw - config.dockwidth;
+ dock.h = min(size, mon->mh);
+ dock.y = mon->my + mon->mh / 2 - size / 2;
break;
}
if (config.dockgravity[0] == 'N' || config.dockgravity[0] == 'S') {
switch (config.dockgravity[1]) {
case 'F':
- dock.x = 0;
- dock.w = TAILQ_FIRST(&wm.monq)->mw;
+ dock.x = mon->mx;
+ dock.w = mon->mw;
break;
case 'W':
- dock.w = min(size, TAILQ_FIRST(&wm.monq)->mw);
- dock.x = 0;
+ dock.w = min(size, mon->mw);
+ dock.x = mon->mx;
break;
case 'E':
- dock.w = min(size, TAILQ_FIRST(&wm.monq)->mw);
- dock.x = TAILQ_FIRST(&wm.monq)->mw - size;
+ dock.w = min(size, mon->mw);
+ dock.x = mon->mx + mon->mw - size;
break;
default:
- dock.w = min(size, TAILQ_FIRST(&wm.monq)->mw);
- dock.x = TAILQ_FIRST(&wm.monq)->mw / 2 - size / 2;
+ dock.w = min(size, mon->mw);
+ dock.x = mon->mx + mon->mw / 2 - size / 2;
break;
}
} else if (config.dockgravity[0] != '\0') {
switch (config.dockgravity[1]) {
case 'F':
- dock.h = TAILQ_FIRST(&wm.monq)->mh;
- dock.y = 0;
+ dock.h = mon->mh;
+ dock.y = mon->my;
break;
case 'N':
- dock.h = min(size, TAILQ_FIRST(&wm.monq)->mh);
- dock.y = 0;
+ dock.h = min(size, mon->mh);
+ dock.y = mon->my;
break;
case 'S':
- dock.h = min(size, TAILQ_FIRST(&wm.monq)->mh);
- dock.y = TAILQ_FIRST(&wm.monq)->mh - size;
+ dock.h = min(size, mon->mh);
+ dock.y = mon->my + mon->mh - size;
break;
default:
- dock.h = min(size, TAILQ_FIRST(&wm.monq)->mh);
- dock.y = TAILQ_FIRST(&wm.monq)->mh / 2 - size / 2;
+ dock.h = min(size, mon->mh);
+ dock.y = mon->my + mon->mh / 2 - size / 2;
break;
}
}
@@ -206,10 +211,12 @@ void
dockupdatefull(void)
{
struct Object *p;
+ struct Monitor *mon;
struct Dockapp *dapp;
int part, nextend, size;
int i, n;
+ mon = TAILQ_FIRST(&wm.monq);
if (TAILQ_FIRST(&dock.dappq) == NULL) {
XUnmapWindow(dpy, dock.win);
dock.mapped = 0;
@@ -218,32 +225,32 @@ dockupdatefull(void)
dock.mapped = 1;
switch (config.dockgravity[0]) {
case 'N':
- dock.x = 0;
- dock.y = 0;
- dock.w = TAILQ_FIRST(&wm.monq)->mw;
+ dock.x = mon->mx;
+ dock.y = mon->my;
+ dock.w = mon->mw;
dock.h = config.dockwidth;
part = dock.w;
break;
case 'S':
- dock.x = 0;
- dock.y = TAILQ_FIRST(&wm.monq)->mh - config.dockwidth;
- dock.w = TAILQ_FIRST(&wm.monq)->mw;
+ dock.x = mon->mx;
+ dock.y = mon->my + mon->mh - config.dockwidth;
+ dock.w = mon->mw;
dock.h = config.dockwidth;
part = dock.w;
break;
case 'W':
- dock.x = 0;
- dock.y = 0;
+ dock.x = mon->mx;
+ dock.y = mon->my;
dock.w = config.dockwidth;
- dock.h = TAILQ_FIRST(&wm.monq)->mh;
+ dock.h = mon->mh;
part = dock.h;
break;
case 'E':
default:
- dock.x = TAILQ_FIRST(&wm.monq)->mw - config.dockwidth;
- dock.y = 0;
+ dock.x = mon->mx + mon->mw - config.dockwidth;
+ dock.y = mon->my;
dock.w = config.dockwidth;
- dock.h = TAILQ_FIRST(&wm.monq)->mh;
+ dock.h = mon->mh;
part = dock.h;
break;
}
diff --git a/xevents.c b/xevents.c
@@ -1533,21 +1533,6 @@ xeventclientmessage(XEvent *e)
}
}
-/* handle configure notify event */
-static void
-xeventconfigurenotify(XEvent *e)
-{
- XConfigureEvent *ev;
-
- ev = &e->xconfigure;
- if (ev->window == root) {
- monupdate();
- monupdatearea();
- notifplace();
- dockupdate();
- }
-}
-
/* handle configure request event */
static void
xeventconfigurerequest(XEvent *e)
@@ -1863,7 +1848,6 @@ void (*xevents[LASTEvent])(XEvent *) = {
[ButtonPress] = xeventbuttonpress,
[ButtonRelease] = xeventbuttonrelease,
[ClientMessage] = xeventclientmessage,
- [ConfigureNotify] = xeventconfigurenotify,
[ConfigureRequest] = xeventconfigurerequest,
[DestroyNotify] = xeventdestroynotify,
[EnterNotify] = xevententernotify,
diff --git a/xmon.c b/xmon.c
@@ -1,37 +1,30 @@
#include "shod.h"
-#include <X11/extensions/Xinerama.h>
+#include <X11/extensions/Xrandr.h>
-/* check if monitor geometry is unique */
-static int
-monisuniquegeom(XineramaScreenInfo *unique, size_t n, XineramaScreenInfo *info)
+void
+moninit(void)
{
- while (n--)
- if (unique[n].x_org == info->x_org && unique[n].y_org == info->y_org
- && unique[n].width == info->width && unique[n].height == info->height)
- return 0;
- return 1;
+ int i;
+
+ if ((wm.xrandr = XRRQueryExtension(dpy, &wm.xrandrev, &i))) {
+ XRRSelectInput(dpy, root, RRScreenChangeNotifyMask);
+ }
}
-/* add monitor */
-static void
-monnew(XineramaScreenInfo *info)
+void
+monevent(XEvent *e)
{
- struct Monitor *mon;
-
- mon = emalloc(sizeof *mon);
- *mon = (struct Monitor){
- .mx = info->x_org,
- .my = info->y_org,
- .mw = info->width,
- .mh = info->height,
- .wx = info->x_org,
- .wy = info->y_org,
- .ww = info->width,
- .wh = info->height,
- };
- mon->seldesk = 0;
- TAILQ_INSERT_TAIL(&wm.monq, mon, entry);
+ XRRScreenChangeNotifyEvent *ev;
+
+ ev = (XRRScreenChangeNotifyEvent *)e;
+ if (ev->root == root) {
+ (void)XRRUpdateConfiguration(e);
+ monupdate();
+ monupdatearea();
+ notifplace();
+ dockupdate();
+ }
}
/* delete monitor and set monitor of clients on it to NULL */
@@ -70,64 +63,65 @@ getmon(int x, int y)
void
monupdate(void)
{
- XineramaScreenInfo *info = NULL;
- XineramaScreenInfo *unique = NULL;
- struct Monitor *mon, *tmp;
+ XRRScreenResources *sr;
+ XRRCrtcInfo *ci;
+ struct MonitorQueue monq; /* queue of monitors */
+ struct Monitor *mon;
struct Container *c, *focus;
struct Object *m, *s;
- int delselmon = 0;
- int del, add;
- int i, j, n;
- int moncount;
-
- info = XineramaQueryScreens(dpy, &n);
- unique = ecalloc(n, sizeof *unique);
-
- /* only consider unique geometries as separate screens */
- for (i = 0, j = 0; i < n; i++)
- if (monisuniquegeom(unique, j, &info[i]))
- memcpy(&unique[j++], &info[i], sizeof *unique);
- XFree(info);
- moncount = j;
-
- /* look for monitors that do not exist anymore and delete them */
- mon = TAILQ_FIRST(&wm.monq);
- while (mon != NULL) {
- del = 1;
- for (i = 0; i < moncount; i++) {
- if (unique[i].x_org == mon->mx && unique[i].y_org == mon->my &&
- unique[i].width == mon->mw && unique[i].height == mon->mh) {
- del = 0;
+ int delselmon, i;
+
+ TAILQ_INIT(&monq);
+ sr = XRRGetScreenResources(dpy, root);
+ for (i = 0, ci = NULL; i < sr->ncrtc; i++) {
+ if ((ci = XRRGetCrtcInfo(dpy, sr, sr->crtcs[i])) == NULL)
+ continue;
+ if (ci->noutput == 0)
+ goto next;
+
+ TAILQ_FOREACH(mon, &wm.monq, entry)
+ if (ci->x == mon->mx && ci->y == mon->my &&
+ (int)ci->width == mon->mw && (int)ci->height == mon->mh)
break;
- }
- }
- tmp = mon;
- mon = TAILQ_NEXT(mon, entry);
- if (del) {
- if (tmp == wm.selmon)
- delselmon = 1;
- mondel(tmp);
+ if (mon != NULL) {
+ TAILQ_REMOVE(&wm.monq, mon, entry);
+ } else {
+ mon = emalloc(sizeof(*mon));
+ *mon = (struct Monitor){
+ .mx = ci->x,
+ .wx = ci->x,
+ .my = ci->y,
+ .wy = ci->y,
+ .mw = ci->width,
+ .ww = ci->width,
+ .mh = ci->height,
+ .wh = ci->height,
+ };
}
+ TAILQ_INSERT_TAIL(&monq, mon, entry);
+next:
+ XRRFreeCrtcInfo(ci);
}
-
- /* look for new monitors and add them */
- for (i = 0; i < moncount; i++) {
- add = 1;
- TAILQ_FOREACH(mon, &wm.monq, entry) {
- if (unique[i].x_org == mon->mx && unique[i].y_org == mon->my &&
- unique[i].width == mon->mw && unique[i].height == mon->mh) {
- add = 0;
- break;
- }
- }
- if (add) {
- monnew(&unique[i]);
- }
+ XRRFreeScreenResources(sr);
+
+ /* delete monitors that do not exist anymore */
+ delselmon = 0;
+ while ((mon = TAILQ_FIRST(&wm.monq)) != NULL) {
+ if (mon == wm.selmon)
+ delselmon = 1;
+ mondel(mon);
}
- if (delselmon)
+ if (delselmon) {
wm.selmon = TAILQ_FIRST(&wm.monq);
+ }
+
+ /* commit new list of monitor */
+ while ((mon = TAILQ_FIRST(&monq)) != NULL) {
+ TAILQ_REMOVE(&monq, mon, entry);
+ TAILQ_INSERT_TAIL(&wm.monq, mon, entry);
+ }
- /* send containers which do not belong to a window to selected desktop */
+ /* send containers which do not belong to a monitor to selected desktop */
focus = NULL;
TAILQ_FOREACH(c, &wm.focusq, entry) {
if (!c->isminimized && c->mon == NULL) {
@@ -149,7 +143,6 @@ monupdate(void)
if (focus != NULL) /* if a contained changed desktop, focus it */
tabfocus(focus->selcol->selrow->seltab, 1);
wm.setclientlist = 1;
- free(unique);
}
/* update window area and dock area of monitor */