Add allOutputs option to window switcher

Introduces a new configuration option for the window switcher
that allows users to filter windows by output (monitor).

Changes:
- Added `allOutputs` attribute to <windowSwitcher>
  - Default is "no" (only shows windows on the cursor's output)
  - When set to "yes", shows windows from all outputs

- Introduced LAB_VIEW_CRITERIA_CURSOR_OUTPUT flag to filter views by output
  - Windows are matched against the output nearest to the cursor
  - Bit positions of existing criteria flags shifted to accommodate new flag

- Modified OSD display behavior to show only on the cursor's output
  - Previously, the OSD would appear on all outputs simultaneously
  - Now displays only on the output nearest to the cursor location

This provides better multi-monitor support by allowing users to focus on
windows relevant to their current screen, reducing visual clutter when
working across multiple displays.
This commit is contained in:
Samet Aylak 2025-11-02 08:54:29 -05:00
parent 0f62648d39
commit 764cd942eb
No known key found for this signature in database
GPG key ID: E5DEF544B937EE49
6 changed files with 43 additions and 16 deletions

View file

@ -339,7 +339,7 @@ this is for compatibility with Openbox.
## WINDOW SWITCHER
```
<windowSwitcher show="yes" style="classic" preview="yes" outlines="yes" allWorkspaces="no">
<windowSwitcher show="yes" style="classic" preview="yes" outlines="yes" allWorkspaces="no" allOutputs="no">
<fields>
<field content="icon" width="5%" />
<field content="desktop_entry_name" width="30%" />
@ -348,7 +348,7 @@ this is for compatibility with Openbox.
</windowSwitcher>
```
*<windowSwitcher show="" style="" preview="" outlines="" allWorkspaces="" unshade="">*
*<windowSwitcher show="" style="" preview="" outlines="" allWorkspaces="" allOutputs="" unshade="">*
*show* [yes|no] Draw the OnScreenDisplay when switching between
windows. Default is yes.
@ -366,6 +366,10 @@ this is for compatibility with Openbox.
they are on. Default no (that is only windows on the current workspace
are shown).
*allOutputs* [yes|no] Show windows regardless of what output
they are on. Default no (that is only windows on the cursor output
are shown).
*unshade* [yes|no] Temporarily unshade windows when switching between
them and permanently unshade on the final selection. Default is yes.

View file

@ -78,7 +78,7 @@
</theme>
<windowSwitcher show="yes" style="classic" preview="yes"
outlines="yes" allWorkspaces="no" unshade="yes">
outlines="yes" allWorkspaces="no" allOutputs="no" unshade="yes">
<fields>
<field content="icon" width="5%" />
<field content="desktop_entry_name" width="30%" />
@ -98,7 +98,7 @@
Some contents are fixed-length and others are variable-length.
See "man 5 labwc-config" for details.
<windowSwitcher show="yes" preview="no" outlines="no" allWorkspaces="yes">
<windowSwitcher show="yes" preview="no" outlines="no" allWorkspaces="yes" allOutputs="no">
<fields>
<field content="workspace" width="5%" />
<field content="state" width="3%" />
@ -118,7 +118,7 @@
then workspace name, then identifier/app-id, then the window title.
It uses 100% of OSD window width.
<windowSwitcher show="yes" preview="no" outlines="no" allWorkspaces="yes">
<windowSwitcher show="yes" preview="no" outlines="no" allWorkspaces="yes" allOutputs="no">
<fields>
<field content="custom" format="foobar %b %3s %-10o %-20W %-10i %t" width="100%" />
</fields>

View file

@ -67,16 +67,17 @@ enum lab_view_criteria {
* what is visible on the current workspace
*/
LAB_VIEW_CRITERIA_CURRENT_WORKSPACE = 1 << 0,
LAB_VIEW_CRITERIA_CURSOR_OUTPUT = 1 << 1,
/* Positive criteria */
LAB_VIEW_CRITERIA_FULLSCREEN = 1 << 1,
LAB_VIEW_CRITERIA_ALWAYS_ON_TOP = 1 << 2,
LAB_VIEW_CRITERIA_ROOT_TOPLEVEL = 1 << 3,
LAB_VIEW_CRITERIA_FULLSCREEN = 1 << 2,
LAB_VIEW_CRITERIA_ALWAYS_ON_TOP = 1 << 3,
LAB_VIEW_CRITERIA_ROOT_TOPLEVEL = 1 << 4,
/* Negative criteria */
LAB_VIEW_CRITERIA_NO_ALWAYS_ON_TOP = 1 << 6,
LAB_VIEW_CRITERIA_NO_SKIP_WINDOW_SWITCHER = 1 << 7,
LAB_VIEW_CRITERIA_NO_OMNIPRESENT = 1 << 8,
LAB_VIEW_CRITERIA_NO_ALWAYS_ON_TOP = 1 << 7,
LAB_VIEW_CRITERIA_NO_SKIP_WINDOW_SWITCHER = 1 << 8,
LAB_VIEW_CRITERIA_NO_OMNIPRESENT = 1 << 9,
};
/*

View file

@ -1217,6 +1217,11 @@ entry(xmlNode *node, char *nodename, char *content)
rc.window_switcher.criteria &=
~LAB_VIEW_CRITERIA_CURRENT_WORKSPACE;
}
} else if (!strcasecmp(nodename, "allOutputs.windowSwitcher")) {
if (parse_bool(content, -1) == true) {
rc.window_switcher.criteria &=
~LAB_VIEW_CRITERIA_CURSOR_OUTPUT;
}
} else if (!strcasecmp(nodename, "unshade.windowSwitcher")) {
set_bool(content, &rc.window_switcher.unshade);
@ -1433,6 +1438,7 @@ rcxml_init(void)
rc.window_switcher.outlines = true;
rc.window_switcher.unshade = true;
rc.window_switcher.criteria = LAB_VIEW_CRITERIA_CURRENT_WORKSPACE
| LAB_VIEW_CRITERIA_CURSOR_OUTPUT
| LAB_VIEW_CRITERIA_ROOT_TOPLEVEL
| LAB_VIEW_CRITERIA_NO_SKIP_WINDOW_SWITCHER;

View file

@ -292,11 +292,20 @@ update_osd(struct server *server)
if (rc.window_switcher.show) {
/* Display the actual OSD */
struct output *output;
wl_list_for_each(output, &server->outputs, link) {
if (!output_is_usable(output)) {
continue;
}
// struct output *output;
// wl_list_for_each(output, &server->outputs, link) {
// if (!output_is_usable(output)) {
// continue;
// }
// if (!output->osd_scene.tree) {
// osd_impl->create(output, &views);
// assert(output->osd_scene.tree);
// }
// osd_impl->update(output);
// }
struct output *output = output_nearest_to_cursor(server);
if (output_is_usable(output)) {
if (!output->osd_scene.tree) {
osd_impl->create(output, &views);
assert(output->osd_scene.tree);

View file

@ -277,6 +277,13 @@ matches_criteria(struct view *view, enum lab_view_criteria criteria)
return false;
}
}
if (criteria & LAB_VIEW_CRITERIA_CURSOR_OUTPUT) {
struct server *server = view->server;
struct output *output = output_nearest_to_cursor(server);
if (view->output != output) {
return false;
}
}
if (criteria & LAB_VIEW_CRITERIA_FULLSCREEN) {
if (!view->fullscreen) {
return false;