shod

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

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:
MMakefile | 2+-
Mshod.c | 14+++++++++-----
Mshod.h | 8++++++++
Mxdock.c | 75+++++++++++++++++++++++++++++++++++++++++----------------------------------
Mxevents.c | 16----------------
Mxmon.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 */