On Sat, Sep 13, 2014 at 10:32:42PM +0100, Dominik Vogt wrote:
> It's perfectly allright if the *User* specifies these strings, but
> it would greatly simplify the internal logic if the strings could
> be translated to numbers in FScreen.
Hmm. Maybe see the patch below? It won't (yet) alleviate the need to
change your configuration file, but it does provide:
$[screennum.NAME]
Where NAME is some monitor name defined by XRandR. This would in theory
allow for use of monitor names translated to number, or a direct number
once I resurrect the code to support that (think in terms of extended
geometry string specifiers: XxY+A-B@somescreen).
I've no idea if this is a good way to go or not. See comments in-line
as for the massive assumption I'm making, but Works For Me (tm).
diff --git a/libs/FScreen.c b/libs/FScreen.c
index 0ed5bcb..acceb29 100644
--- a/libs/FScreen.c
+++ b/libs/FScreen.c
@@ -50,6 +50,24 @@ static int no_of_screens;
static struct monitor *FindScreenOfXY(int x, int y);
static struct monitor *monitor_new(void);
static void init_monitor_contents(void);
+static void monitor_print_debug(struct monitor *);
+
+static void monitor_print_debug(struct monitor *m)
+{
+ if (m == NULL)
+ return;
+
+ fprintf(stderr, "XRandR: Added monitor:\n"
+ " name: %s\n"
+ " num: %d\n"
+ " x: %d\n"
+ " y: %d\n"
+ " w: %d\n"
+ " h: %d\n\n",
+ m->name, m->number,
+ m->coord.x, m->coord.y,
+ m->coord.w, m->coord.h);
+}
static void GetMouseXY(XEvent *eventp, int *x, int *y)
{
@@ -131,6 +149,7 @@ void FScreenInit(Display *dpy)
int i;
int err_base = 0, event = 0;
int is_randr_present = 0;
+ int monitor_number = 0;
disp = dpy;
@@ -150,6 +169,7 @@ void FScreenInit(Display *dpy)
TAILQ_INIT(&monitor_q);
m = monitor_new();
+ m->number = monitor_number;
m->coord.x = 0;
m->coord.y = 0;
m->coord.w = DisplayWidth(disp, DefaultScreen(disp));
@@ -157,15 +177,42 @@ void FScreenInit(Display *dpy)
m->name = mvwm_strdup("global");
TAILQ_INSERT_HEAD(&monitor_q, m, entry);
+ monitor_print_debug(m);
+
if (!is_randr_present)
goto done;
/* XRandR is present, so query the screens we have. */
+ /* TA: 2014-09-13: FIXME FIXME FIXME:
+ *
+ * How do we handle this crude ordering with monitors being
+ * added/removed?
+ */
res = XRRGetScreenResources(dpy, DefaultRootWindow(dpy));
if (res != NULL) {
crtc = NULL;
no_of_screens = res->noutput;
- for (i = 0; i < res->noutput; i++) {
+ /* TA: 2014-09-13: XXX: The XRandR API is completely geared
+ * towards using outputs referred to by string (names) as
+ * found in either one's xorg.conf or via EDID.
+ *
+ * Unfortunately, Xinerama didn't have this, and hence
+ * maintained a screen ordering instead; outputs were numbered,
+ * in fvwm's case: 1 -> n, where "0" was reserved for the
+ * "global" screen (entire root window combined across all
+ * outputs).
+ *
+ * XRandR doesn't seem to offer any means of querying outputs
+ * based on logical ordering (such as whether they're
+ * left/right/up/down of one another respectively), despite
+ * being allowed to configure display outputs to have position
+ * information.
+ *
+ * So for now, rather crudely, iterate over the output display
+ * in reverse. This seems to work OK in simple layout cases,
+ * and will allow screens to be referred to by number: 1 -> n)
+ */
+ for (i = res->noutput - 1; i > -1; i--) {
oinfo = XRRGetOutputInfo(dpy, res, res->outputs[i]);
if (oinfo->crtc == None) {
@@ -177,6 +224,7 @@ void FScreenInit(Display *dpy)
continue;
m = monitor_new();
+ m->number = ++monitor_number;
m->coord.x = crtc->x;
m->coord.y = crtc->y;
m->coord.w = crtc->width;
@@ -185,6 +233,8 @@ void FScreenInit(Display *dpy)
TAILQ_INSERT_TAIL(&monitor_q, m, entry);
+ monitor_print_debug(m);
+
XRRFreeCrtcInfo(crtc);
}
XRRFreeScreenResources(res);
@@ -236,6 +286,24 @@ init_monitor_contents(void)
}
}
+int
+monitor_number_by_name(const char *name)
+{
+ struct monitor *m;
+
+ m = monitor_by_name(name);
+
+ /* XXX: What if 'm' is NULL? Return first screen? That's what the old
+ * Xinerama code would have done.
+ *
+ * We'll return -1 to indicate failure.
+ */
+ if (m == NULL)
+ return (-1);
+
+ return (m->number);
+}
+
/* Intended to be called by modules. Simply pass in the parameter from the
* config string sent by mvwm. */
void FScreenConfigureModule(char *args)
diff --git a/libs/FScreen.h b/libs/FScreen.h
index 624d8ab..f726ea6 100644
--- a/libs/FScreen.h
+++ b/libs/FScreen.h
@@ -29,6 +29,7 @@ typedef enum
struct monitor {
char *name;
+ int number;
struct {
int x;
int y;
@@ -68,6 +69,7 @@ struct monitors monitor_q;
struct monitor *monitor_get_current(void);
struct monitor *monitor_by_name(const char *);
struct monitor *monitor_by_xy(int, int);
+int monitor_number_by_name(const char *);
int monitor_should_ignore_global(struct monitor *);
#define FSCREEN_MANGLE_USPOS_HINTS_MAGIC ((short)-32109)
diff --git a/mvwm/expand.c b/mvwm/expand.c
index c0538e1..93e6cf3 100644
--- a/mvwm/expand.c
+++ b/mvwm/expand.c
@@ -68,6 +68,7 @@ static char *partial_function_vars[] =
"hilight.cs",
"infostore.",
"shadow.cs",
+ "screennum.",
NULL
};
@@ -151,7 +152,8 @@ enum
VAR_GT_,
VAR_HILIGHT_CS,
VAR_INFOSTORE_,
- VAR_SHADOW_CS
+ VAR_SHADOW_CS,
+ VAR_SCREEN_NUM_NAME
} partial_extended_vars;
enum
@@ -446,6 +448,19 @@ static signed int expand_vars_extended(
string = allocated_string;
}
goto GOT_STRING;
+ case VAR_SCREEN_NUM_NAME:
+ is_numeric = True;
+
+ if (rest == NULL)
+ return -1;
+
+ /* Can't fail; always returns an int. */
+ val = monitor_number_by_name(rest);
+
+ if (val == -1)
+ return -1;
+
+ goto GOT_STRING;
default:
break;
}
-- Thomas Adam
--
"Deep in my heart I wish I was wrong. But deep in my heart I know I am
not." -- Morrissey ("Girl Least Likely To" -- off of Viva Hate.)