Skip to content

Commit

Permalink
Extend FvwmIconMan Resolution configuration.
Browse files Browse the repository at this point in the history
Expands the FvwmIconMan Resolution typedef to be a strut that can store
desk and page numbers. Then modifies the Resolution configuration to be
a list of filters to limit what windows are shown. There are three base
filters, plus their negation, and an invert filter for a total of 7.

*FvwmIconMan: Resolution [!]desk [n]
*FvwmIconMan: Resolution [!]page [x] [y]
*FvwmIconMan: Resolution [!]screen [S]
*FvwmIconMan: Resolution invert

These filters will either show (or not show) windows on the stated
desk, page, or screen. If no parameters are provided the current
desk, or page are used. Multiple filters can be given to
control which desk, page, and screen are shown. The invert filter
inverts the whole filter. For example.

*FvwmIconMan: Resolution screen p desk 1 !page 0 2

Shows all windows on the primary monitor, on desk 1, and not on page 0 2.

BREAKING: Due to resolutions now being filters, the 'page' resolution
no longer works the same. The page resolution by itself will show all
windows on that page on all desks. To get the old behavior (new default)
you need to use both the desk and page filter, 'desk page'. Similar the
old '!page' resolution is achieved with 'invert desk page'.

Fixes #455
  • Loading branch information
somiaj committed Jun 25, 2021
1 parent 1fe936a commit 18ec44e
Show file tree
Hide file tree
Showing 6 changed files with 223 additions and 196 deletions.
69 changes: 42 additions & 27 deletions doc/modules/FvwmIconMan.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -110,8 +110,8 @@ NoIconAction animate iconification NOP
PlainButton style for normal buttons up black grey
PlainColorset
ReliefThickness size of button relief 2
Resolution global/desk/page/screen page
Reverse normal, icon or none none
Resolution window filters desk page
Reverse normal, icon or none none
SelectButton style for selected buttons flat black grey
SelectColorset
Shape use shape extension false
Expand Down Expand Up @@ -271,33 +271,48 @@ The following options may be specified:
_IconButton_, _PlainButton_, _SelectButton_, and _TitleButton_ were
all set to _flat_. If _num_ is negative, the button will be inverted
as if you had used _Reverse_ for all classes.
*FvwmIconMan: [id] Resolution resolution::
Specifies when the manager will display an entry for a certain window.
_resolution_ may take one of the following values: global, desk, page,
screen, !desk, !page, or !screen. If global, then all windows of the
appropriate type (see the show and dontshow options below) will be
shown. If desk, then only those windows on the current desk are shown.
If page, then only those windows on the current page are shown. If
screen, then only those windows on the current RandR screen are
shown. Note that the specific RandR screen can be specified:
*FvwmIconMan: [id] Resolution [_filter(s)_]::
Specifies a list of _filters_, separated by spaces, that configure which
windows are displayed. If no filters are given, then all windows of the
appropriate type are shown (see the show and dontshow options below).
Each _filter_ then limits the windows that are displayed and may take
one of the following values: desk, page, screen, !desk, !page, !screen,
or invert. _desk_ only shows windows on the current desk, and _page_
only shows windows on the current page. _!desk_ and _!page_ only show
windows not on the current desk or page respectively. _invert_ reverses
the filter displaying the windows that did not match.
+
Notes: _page_ and _desk_ are independent. If the only filter is _page_,
then you will see windows on the current page on all desks. To only see
windows on the current page and desk (the default) you need both filters,
'desk page'. You can only have one of desk/!desk, page/!page, or
screen/!screen, the last one issued take precedence. The invert filter
reverses the whole filter so 'invert desk page' is not the same as
'!desk !page'. Sticky windows are visible on all pages and desks, so
they match all page and desk filters, but won't match the inverted filter.
+
The filters can take additional parameters to state which desk, page,
or screen to show (or not show). _[!]desk [n]_ can take the desk number,
which will only show windows (not) on the stated desk. _[!]page [x] [y]_
can take the horizontal, _x_, and vertical, _y_, page numbers, which will
only show windows (not) on the stated page.
+
_[!]screen [S]_ shows windows (not) on monitor _S_, which can be:
+
> _NAME_: The "NAME" of the specific RandR monitor.
+
> _c_: The current RandR monitor (containing the pointer)
+
> _p_: The primary RandR monitor
+
> _g_: The global monitor
+
Since all windows are on the global monitor, _screen g_ effectively does
nothing. _c_ is the current monitor at the time resolution is issued, and
once set will not change. This filter is best used with a RandR _NAME_.
+
_NAME_:::
The "NAME" of the specific RandR monitor (HDMI, for example)
_c_:::
The current RandR monitor (the monitor containing the pointer)
_p_:::
The primary RandR monitor
_g_:::
The global monitor

!desk reverses the sense of desk, displaying only those windows
not on the current desk. Likewise, !page shows only those windows not
on the current page and !screen shows only those windows not on the
current RandR screen. The default is **page**. If only a single screen is
used, page and screen are equivalent.

This configuration line is respected when FvwmIconMan is running as
well, the resolution is changed dynamically.
well, the resolution is changed dynamically when sent to fvwm.

*FvwmIconMan: [id] Reverse class::
Causes certain classes of buttons to have their relief lines reversed
Expand Down
26 changes: 17 additions & 9 deletions modules/FvwmIconMan/FvwmIconMan.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,14 +54,22 @@ typedef unsigned char Uchar;

typedef signed char Schar;

typedef enum {
SHOW_GLOBAL,
SHOW_DESKTOP,
SHOW_PAGE,
SHOW_SCREEN,
NO_SHOW_DESKTOP, /* "!desk" Show windows not on the current desk */
NO_SHOW_PAGE, /* "!page" Show windows not on the current page */
NO_SHOW_SCREEN, /* "!screen" Show windows not on the current screen */
typedef struct Resolution {
/* Page/Desk/Screen to show. -1 is current. */
int pagex_n;
int pagey_n;
int desk_n;
bool invert;
enum {
SHOW_ALL = 0x00,
SHOW_DESK = 0x01,
SHOW_PAGE = 0x02,
SHOW_SCREEN = 0x04,
NO_SHOW_DESK = 0x10,
NO_SHOW_PAGE = 0x20,
NO_SHOW_SCREEN = 0x40,
} type;

} Resolution;

typedef enum {
Expand Down Expand Up @@ -269,10 +277,10 @@ typedef struct {
typedef struct win_manager {
unsigned int magic;
int index;
char *scr;

/* .fvwm2rc options or things set as a result of options */
Resolution res;
char *scr; /* RandR monitor name */
Reverse rev;
Pixel backcolor[NUM_CONTEXTS], forecolor[NUM_CONTEXTS];
Pixel hicolor[NUM_CONTEXTS], shadowcolor[NUM_CONTEXTS];
Expand Down
14 changes: 9 additions & 5 deletions modules/FvwmIconMan/globals.c
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,11 @@ static void init_win_manager(int id)
memset(&globals.managers[id], 0, sizeof(WinManager));
globals.managers[id].magic = 0x12344321;
globals.managers[id].index = id;
globals.managers[id].res = SHOW_PAGE;
globals.managers[id].scr = NULL;
globals.managers[id].res.type = SHOW_DESK | SHOW_PAGE;
globals.managers[id].res.invert = false;
globals.managers[id].res.desk_n = -1;
globals.managers[id].res.pagex_n = -1;
globals.managers[id].rev = REVERSE_NONE;
globals.managers[id].titlename = alloc_string("FvwmIconMan");
globals.managers[id].iconname = alloc_string("FvwmIconMan");
Expand Down Expand Up @@ -100,13 +104,13 @@ void print_managers(void)
for (i = 0; i < globals.num_managers; i++)
{
ConsoleDebug(CORE, "Manager %d:\n", i + 1);
if (globals.managers[i].res == SHOW_GLOBAL)
if (globals.managers[i].res.type == SHOW_GLOBAL)
ConsoleDebug(CORE, "ShowGlobal\n");
else if (globals.managers[i].res == SHOW_DESKTOP)
else if (globals.managers[i].res.type == SHOW_DESKTOP)
ConsoleDebug(CORE, "ShowDesktop\n");
else if (globals.managers[i].res == SHOW_PAGE)
else if (globals.managers[i].res.type == SHOW_PAGE)
ConsoleDebug(CORE, "ShowPage\n");
else if (globals.managers[i].res == SHOW_SCREEN)
else if (globals.managers[i].res.type == SHOW_SCREEN)
ConsoleDebug(CORE, "ShowScreen\n");

ConsoleDebug(CORE, "DontShow:\n");
Expand Down
173 changes: 89 additions & 84 deletions modules/FvwmIconMan/readconfig.c
Original file line number Diff line number Diff line change
Expand Up @@ -1133,6 +1133,92 @@ static void handle_button_config(int manager, int context, char *option)
copy_string(&globals.managers[id].backColorName[context], p));
}

static void handle_resolution_config(int man, char *line)
{
char *token = NULL, *nline;
int n, type;
Resolution r;

/* Reset to initial state of no filters */
r.type = SHOW_ALL;
r.invert = false;
r.desk_n = -1;
r.pagex_n = -1;
r.pagey_n = -1;

/* Apply filters */
while ((token = PeekToken(line, &line)) != NULL)
{
/* Since multiple filters can be sent, ensure
* only the last one takes precedence.
*/
if (!strcasecmp(token, "invert")) {
r.invert = true;
continue;
} else if (!strcasecmp(token, "desk")) {
type = SHOW_DESK;
r.type = (r.type | SHOW_DESK) & ~(NO_SHOW_DESK);
} else if (!strcasecmp(token, "page")) {
type = SHOW_PAGE;
r.type = (r.type | SHOW_PAGE) & ~(NO_SHOW_PAGE);
} else if (!strcasecmp(token, "screen")) {
type = SHOW_SCREEN;
r.type = (r.type | SHOW_SCREEN) & ~(NO_SHOW_SCREEN);
} else if (!strcasecmp(token, "!desk")) {
type = SHOW_DESK;
r.type = (r.type | NO_SHOW_DESK) & ~(SHOW_DESK);
} else if (!strcasecmp(token, "!page")) {
type = SHOW_PAGE;
r.type = (r.type | NO_SHOW_PAGE) & ~(SHOW_PAGE);
} else if (!strcasecmp(token, "!screen")) {
type = SHOW_SCREEN;
r.type = (r.type | NO_SHOW_SCREEN) & ~(SHOW_SCREEN);
} else {
continue;
}
token = PeekToken(line, &nline);

switch (type)
{
case SHOW_DESK:
if (token && extract_int(token, &n) && n >= 0) {
r.desk_n = n;
line = nline;
}
break;
case SHOW_PAGE:
if (token && extract_int(token, &n) && n >= 0) {
r.pagex_n = n;
line = nline;
}
token = PeekToken(line, &nline);
if (token && extract_int(token, &n) && n >= 0) {
r.pagey_n = n;
line = nline;
}
break;
case SHOW_SCREEN:
if (token == NULL) {
SET_MANAGER(man, scr, NULL);
break;
}
struct monitor *mon = monitor_resolve_name(token);
if (strcasecmp(token, "g") != 0 && mon != NULL) {
SET_MANAGER(man, scr, (char *)mon->si->name);
line = nline;
} else {
SET_MANAGER(man, scr, NULL);
if (strcasecmp(token, "g"))
line = nline;
}
break;
default:
break;
}
}
SET_MANAGER(man, res, r);
}

static void add_weighted_sort(WinManager *man, WeightedSort *weighted_sort)
{
WeightedSort *p;
Expand Down Expand Up @@ -1175,7 +1261,6 @@ void read_in_resources(void)
int i, n, manager;
char *option1;
Binding *binding = NULL;
Resolution r;
Reverse rv;

InitGetConfigLine(fvwm_fd, Module);
Expand Down Expand Up @@ -1640,44 +1725,8 @@ void read_in_resources(void)
copy_string(&globals.managers[id].geometry_str, p));
}
else if (!strcasecmp(option1, "resolution")) {
p = read_next_cmd(READ_ARG);
if (!p) {
ConsoleMessage("Bad line: %s\n", current_line);
continue;
}
ConsoleDebug(CONFIG, "resolution: %s\n", p);
if (!strcasecmp(p, "global"))
r = SHOW_GLOBAL;
else if (!strcasecmp(p, "desk"))
r = SHOW_DESKTOP;
else if (!strcasecmp(p, "page"))
r = SHOW_PAGE;
else if (!strcasecmp(p, "screen")) {
r = SHOW_SCREEN;
p = read_next_cmd(READ_ARG);
if (p != NULL) {
struct monitor *mon = monitor_resolve_name(p);
if (strcasecmp(p, "g") == 0) {
r = SHOW_GLOBAL;
} else {
SET_MANAGER(manager, scr,
copy_string(&globals.managers[id].scr, mon->si->name));
}
}
}
else if (!strcasecmp(p, "!desk"))
r = NO_SHOW_DESKTOP;
else if (!strcasecmp(p, "!page"))
r = NO_SHOW_PAGE;
else if (!strcasecmp(p, "!screen"))
r = NO_SHOW_SCREEN;
else {
ConsoleMessage("Bad line: %s\n", current_line);
ConsoleMessage("What kind of resolution is this?\n");
continue;
}

SET_MANAGER(manager, res, r);
p = read_next_cmd(READ_REST_OF_LINE);
handle_resolution_config(manager, p);
}
else if (!strcasecmp(option1, "reverse")) {
p = read_next_cmd(READ_ARG);
Expand Down Expand Up @@ -2306,51 +2355,7 @@ void process_dynamic_config_line(char *line)
/* currently supports only "resolution" and "tips" */
if (strcasecmp(token, "resolution") == 0)
{
int value;

free(token);
line = GetNextToken(line, &token);
if (!token)
{
return;
}
if (!strcasecmp(token, "global"))
value = SHOW_GLOBAL;
else if (!strcasecmp(token, "desk"))
value = SHOW_DESKTOP;
else if (!strcasecmp(token, "page"))
value = SHOW_PAGE;
else if (!strcasecmp(token, "screen")) {
value = SHOW_SCREEN;

free(token);
line = GetNextToken(line, &token);

if (token == NULL)
goto done;

struct monitor *mon = monitor_resolve_name(token);
if (strcasecmp(token, "g") == 0) {
value = SHOW_GLOBAL;
goto done;
}
SET_MANAGER(manager, scr, (char *)mon->si->name);
}
else if (!strcasecmp(token, "!desk"))
value = NO_SHOW_DESKTOP;
else if (!strcasecmp(token, "!page"))
value = NO_SHOW_PAGE;
else if (!strcasecmp(token, "!screen"))
value = NO_SHOW_SCREEN;
else
{
fvwm_debug(__func__, "%s: unknown resolution %s.\n",
MyName, token);
free(token);
return;
}
done:
SET_MANAGER(manager, res, value);
handle_resolution_config(manager, line);
remanage_winlist();
}
else if (strcasecmp(token, "tips") == 0)
Expand Down
Loading

0 comments on commit 18ec44e

Please sign in to comment.