From 656b4e8eccdcd0ef171c21290308516973f21e8d Mon Sep 17 00:00:00 2001 From: Thomas Adam Date: Sat, 23 Dec 2023 23:02:56 +0000 Subject: [PATCH 1/4] randr: allow geometry strings to include @n When geometry string contain @n, where n is a number from 0..INT_MAX, treat that number as a monitor's assigned number to use. This is similar to how fvwm used to handle these geometry strings with Xinerama, except that the designation of monitor numbers is now derived via a deterministic algorithm. See 'RANDR SUPPORT' in "man fvwm3all" --- doc/fvwm3_manpage_source.adoc | 10 ++++++++++ libs/FScreen.c | 20 ++++++++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/doc/fvwm3_manpage_source.adoc b/doc/fvwm3_manpage_source.adoc index 1c9489f7c..583d93e24 100644 --- a/doc/fvwm3_manpage_source.adoc +++ b/doc/fvwm3_manpage_source.adoc @@ -341,6 +341,16 @@ the window's upper right hand corner 5 pixels above and to the left of the upper left hand corner of the screen; others may do just plain bizarre things. +There is a fvwm-specific extension to geometry strings which can also +enforce the geometry is relative to the given screen. For example: + +.... +xterm -geometry +0+0@n +.... + +Where 'n' can be one of a RandR monitor name, or an assigned monitor number. +For more details, see the RANDR SUPPORT section. + There are several ways to cause a window to map onto a desktop or page other than the currently active one. The geometry technique mentioned above (specifying x,y coordinates larger than the physical screen size), diff --git a/libs/FScreen.c b/libs/FScreen.c index 3188eea9f..de2b4bc83 100644 --- a/libs/FScreen.c +++ b/libs/FScreen.c @@ -29,6 +29,7 @@ #include "FScreen.h" #include "FEvent.h" #include "queue.h" +#include "strtonum.h" #define GLOBAL_SCREEN_NAME "_global" @@ -217,11 +218,30 @@ struct monitor * monitor_resolve_name(const char *scr) { struct monitor *m = NULL; + int pos = -1; + const char *errstr; if (scr == NULL) { return NULL; } + + /* Try and look up the monitor as a number. If that succeeds, + * try and match that number as something valid in the monitor + * information we have. + */ + pos = strtonum(scr, 0, INT_MAX, &errstr); + if (errstr == NULL) { + /* We have a valid number. Look it up. */ + struct monitor *m_loop; + + RB_FOREACH(m_loop, monitors, &monitor_q) { + if (m_loop->number == pos) + return (m_loop); + } + return (NULL); + } + /* "@g" is for the global screen. */ if (strcmp(scr, "g") == 0) { m = monitor_get_global(); From 4489f144f7523e02fe4ba77c85ce663cf912e90b Mon Sep 17 00:00:00 2001 From: Thomas Adam Date: Mon, 25 Dec 2023 21:12:46 +0000 Subject: [PATCH 2/4] FScreen: add helper function monitor_by_number Centralise looking up a monitor based on its number, so that callers are able to use this. --- libs/FScreen.c | 12 ++++++++++++ libs/FScreen.h | 1 + 2 files changed, 13 insertions(+) diff --git a/libs/FScreen.c b/libs/FScreen.c index de2b4bc83..339b7078f 100644 --- a/libs/FScreen.c +++ b/libs/FScreen.c @@ -115,6 +115,18 @@ monitor_scan_edges(struct monitor *m) } } +struct monitor * +monitor_by_number(int n) +{ + struct monitor *m_loop; + + RB_FOREACH(m_loop, monitors, &monitor_q) { + if (m_loop->number == n) + return (m_loop); + } + return (NULL); +} + void monitor_refresh_global(void) { diff --git a/libs/FScreen.h b/libs/FScreen.h index aec9dd963..6a6084098 100644 --- a/libs/FScreen.h +++ b/libs/FScreen.h @@ -156,6 +156,7 @@ RB_PROTOTYPE(monitors, monitor, entry, monitor_compare); struct monitor *monitor_resolve_name(const char *); struct monitor *monitor_by_xy(int, int); struct monitor *monitor_by_output(int); +struct monitor *monitor_by_number(int); struct monitor *monitor_by_primary(void); struct monitor *monitor_by_last_primary(void); struct monitor *monitor_get_current(void); From 798f97eaa6229ae377aa02f8e2d4a5da3563caab Mon Sep 17 00:00:00 2001 From: Thomas Adam Date: Mon, 25 Dec 2023 21:13:42 +0000 Subject: [PATCH 3/4] monitor_resolve_name: use monitor_by_number Switch the hand-rolled code in monitor_resolve_name to use monitor_by_number. --- libs/FScreen.c | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/libs/FScreen.c b/libs/FScreen.c index 339b7078f..041c6fd74 100644 --- a/libs/FScreen.c +++ b/libs/FScreen.c @@ -243,16 +243,8 @@ monitor_resolve_name(const char *scr) * information we have. */ pos = strtonum(scr, 0, INT_MAX, &errstr); - if (errstr == NULL) { - /* We have a valid number. Look it up. */ - struct monitor *m_loop; - - RB_FOREACH(m_loop, monitors, &monitor_q) { - if (m_loop->number == pos) - return (m_loop); - } - return (NULL); - } + if (errstr == NULL) + return (monitor_by_number(pos)); /* "@g" is for the global screen. */ if (strcmp(scr, "g") == 0) { From 297c2fd1f7c8c9e00f7c2b0ba8ab4633a9faabaf Mon Sep 17 00:00:00 2001 From: Thomas Adam Date: Mon, 25 Dec 2023 21:14:43 +0000 Subject: [PATCH 4/4] expand: simplify monitor.* lookups Now that monitor_resolve_name understands how to look up monitors based on a number, simply the code to make use of that. --- fvwm/expand.c | 20 +------------------- 1 file changed, 1 insertion(+), 19 deletions(-) diff --git a/fvwm/expand.c b/fvwm/expand.c index bceeabab9..3a8970e39 100644 --- a/fvwm/expand.c +++ b/fvwm/expand.c @@ -25,7 +25,6 @@ #include "libs/ColorUtils.h" #include "libs/safemalloc.h" #include "libs/FEvent.h" -#include "libs/strtonum.h" #include "fvwm.h" #include "externs.h" #include "cursor.h" @@ -543,12 +542,10 @@ static signed int expand_vars_extended( /* We could be left with ".?" */ char *m_name = NULL; - struct monitor *mon2 = NULL, *m_loop; + struct monitor *mon2 = NULL; char *rest_s; - const char *errstr; char *p_free; int got_string; - int pos = -1; /* The first word is the monitor name: * @@ -560,22 +557,7 @@ static signed int expand_vars_extended( p_free = rest_s; got_string = 0; while ((m_name = strsep(&rest_s, ".")) != NULL) { - /* Try parsing the name as a number. If that fails, - * then treat it as a valid name. - */ - pos = strtonum(m_name, 0, INT_MAX, &errstr); - if (errstr != NULL) - pos = -1; - - RB_FOREACH(m_loop, monitors, &monitor_q) { - if (m_loop->number == pos) { - mon2 = m_loop; - goto rest; - } - } - mon2 = monitor_resolve_name(m_name); -rest: if (mon2 == NULL) { free(p_free);