Sort screens by origin

Doing a multi-head setup using other means than Xinerama may lead to
XineramaQueryScreens() returning the screens in an order that does not
actually represent the actual screen layout. This in turn may result
in dwm using the "wrong" monitor in monitor related
functions (focusmon(), tagmon(), applying rules, ...).

This change sorts the list of unique screens by their origin to
alleviate this problem.
This commit is contained in:
Sebastian Sareyko
2019-09-27 12:32:41 +02:00
committed by Zoe Roux
parent bf50709a2c
commit 19e1fe6378

24
dwm.c
View File

@@ -99,6 +99,8 @@ if (XrmGetResource(xrdb, R, NULL, &type, &value) == True) { \
#define MWM_DECOR_ALL (1 << 0)
#define MWM_DECOR_BORDER (1 << 1)
#define MWM_DECOR_TITLE (1 << 3)
#define RIGHTOF(a,b) (a.y_org > b.y_org) || \
((a.y_org == b.y_org) && (a.x_org > b.x_org))
/* enums */
enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */
@@ -346,6 +348,9 @@ static void setviewport(void);
static void seturgent(Client *c, int urg);
static void showhide(Client *c);
static void sigchld(int unused);
#ifdef XINERAMA
static void sortscreens(XineramaScreenInfo *screens, int n);
#endif /* XINERAMA */
static void spawn(const Arg *arg);
static int stackpos(const Arg *arg);
static void tag(const Arg *arg);
@@ -2627,6 +2632,24 @@ sigchld(int unused)
while (0 < waitpid(-1, NULL, WNOHANG));
}
#ifdef XINERAMA
void
sortscreens(XineramaScreenInfo *screens, int n)
{
int i, j;
XineramaScreenInfo *screen = ecalloc(1, sizeof(XineramaScreenInfo));
for (i = 0; i < n; i++)
for (j = i + 1; j < n; j++)
if (RIGHTOF(screens[i], screens[j])) {
memcpy(&screen[0], &screens[i], sizeof(XineramaScreenInfo));
memcpy(&screens[i], &screens[j], sizeof(XineramaScreenInfo));
memcpy(&screens[j], &screen[0], sizeof(XineramaScreenInfo));
}
XFree(screen);
}
#endif /* XINERAMA */
void
spawn(const Arg *arg)
{
@@ -3029,6 +3052,7 @@ updategeom(void)
memcpy(&unique[j++], &info[i], sizeof(XineramaScreenInfo));
XFree(info);
nn = j;
sortscreens(unique, nn);
if (n <= nn) { /* new monitors available */
for (i = 0; i < (nn - n); i++) {
for (m = mons; m && m->next; m = m->next);