mirror of
https://github.com/labwc/labwc.git
synced 2025-11-30 06:59:52 -05:00
osd: add multi-monitor support
Some checks failed
labwc.github.io / notify (push) Has been cancelled
Some checks failed
labwc.github.io / notify (push) Has been cancelled
Adds `output` attribute to control which monitor(s) display the window switcher OSD. Supports three modes: - "all": display on all monitors (default) - "pointer": display on monitor with mouse cursor - "keyboard": display on monitor with keyboard focus The configuration structure is also refactored to nest OSD-specific settings (show, style, output, thumbnailLabelFormat) under an <osd> element within <windowSwitcher>, improving logical organization.
This commit is contained in:
parent
79fbb611e0
commit
d65caf8bfd
6 changed files with 105 additions and 25 deletions
|
|
@ -339,7 +339,8 @@ this is for compatibility with Openbox.
|
||||||
## WINDOW SWITCHER
|
## WINDOW SWITCHER
|
||||||
|
|
||||||
```
|
```
|
||||||
<windowSwitcher show="yes" style="classic" preview="yes" outlines="yes" allWorkspaces="no" thumbnailLabelFormat="%T">
|
<windowSwitcher preview="yes" outlines="yes" allWorkspaces="no">
|
||||||
|
<osd show="yes" style="classic" output="all" thumbnailLabelFormat="%T" />
|
||||||
<fields>
|
<fields>
|
||||||
<field content="icon" width="5%" />
|
<field content="icon" width="5%" />
|
||||||
<field content="desktop_entry_name" width="30%" />
|
<field content="desktop_entry_name" width="30%" />
|
||||||
|
|
@ -348,14 +349,7 @@ this is for compatibility with Openbox.
|
||||||
</windowSwitcher>
|
</windowSwitcher>
|
||||||
```
|
```
|
||||||
|
|
||||||
*<windowSwitcher show="" style="" preview="" outlines="" allWorkspaces="" unshade="" thumbnailLabelFormat="">*
|
*<windowSwitcher preview="" outlines="" allWorkspaces="" unshade="">*
|
||||||
*show* [yes|no] Draw the OnScreenDisplay when switching between
|
|
||||||
windows. Default is yes.
|
|
||||||
|
|
||||||
*style* [classic|thumbnail] Configures the style of the OnScreenDisplay.
|
|
||||||
"classic" displays window information like icons and titles in a vertical list.
|
|
||||||
"thumbnail" shows window thumbnail, icon and title in grids.
|
|
||||||
|
|
||||||
*preview* [yes|no] Preview the contents of the selected window when
|
*preview* [yes|no] Preview the contents of the selected window when
|
||||||
switching between windows. Default is yes.
|
switching between windows. Default is yes.
|
||||||
|
|
||||||
|
|
@ -369,12 +363,26 @@ this is for compatibility with Openbox.
|
||||||
*unshade* [yes|no] Temporarily unshade windows when switching between
|
*unshade* [yes|no] Temporarily unshade windows when switching between
|
||||||
them and permanently unshade on the final selection. Default is yes.
|
them and permanently unshade on the final selection. Default is yes.
|
||||||
|
|
||||||
|
*<osd show="" style="" output="" thumbnailLabelFormat="" />*
|
||||||
|
*show* [yes|no] Draw the OnScreenDisplay when switching between
|
||||||
|
windows. Default is yes.
|
||||||
|
|
||||||
|
*style* [classic|thumbnail] Configures the style of the OSD.
|
||||||
|
"classic" displays window information like icons and titles in a vertical list.
|
||||||
|
"thumbnail" shows window thumbnail, icon and title in grids.
|
||||||
|
|
||||||
|
*output* [all|pointer|keyboard] Configures which monitor(s) show the OSD.
|
||||||
|
"all" displays the OSD on all monitors.
|
||||||
|
"pointer" displays the OSD on the monitor containing the mouse pointer.
|
||||||
|
"keyboard" displays the OSD on the monitor with keyboard focus.
|
||||||
|
Default is "all".
|
||||||
|
|
||||||
*thumbnailLabelFormat* Format to be used for the thumbnail label according to *custom*
|
*thumbnailLabelFormat* Format to be used for the thumbnail label according to *custom*
|
||||||
field below, only applied when using *<windowSwitcher style="thumbnail" />*.
|
field below, only applied when using *<osd style="thumbnail" />*.
|
||||||
Default is "%T".
|
Default is "%T".
|
||||||
|
|
||||||
*<windowSwitcher><fields><field content="" width="%">*
|
*<windowSwitcher><fields><field content="" width="%">*
|
||||||
Define window switcher fields when using *<windowSwitcher style="classic" />*.
|
Define window switcher fields when using *<osd style="classic" />*.
|
||||||
|
|
||||||
*content* defines what the field shows and can be any of:
|
*content* defines what the field shows and can be any of:
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -77,8 +77,8 @@
|
||||||
</font>
|
</font>
|
||||||
</theme>
|
</theme>
|
||||||
|
|
||||||
<windowSwitcher show="yes" style="classic" preview="yes"
|
<windowSwitcher preview="yes" outlines="yes" allWorkspaces="no" unshade="yes">
|
||||||
outlines="yes" allWorkspaces="no" unshade="yes">
|
<osd show="yes" style="classic" output="all" thumbnailLabelFormat="%T" />
|
||||||
<fields>
|
<fields>
|
||||||
<field content="icon" width="5%" />
|
<field content="icon" width="5%" />
|
||||||
<field content="desktop_entry_name" width="30%" />
|
<field content="desktop_entry_name" width="30%" />
|
||||||
|
|
@ -98,7 +98,8 @@
|
||||||
Some contents are fixed-length and others are variable-length.
|
Some contents are fixed-length and others are variable-length.
|
||||||
See "man 5 labwc-config" for details.
|
See "man 5 labwc-config" for details.
|
||||||
|
|
||||||
<windowSwitcher show="yes" preview="no" outlines="no" allWorkspaces="yes">
|
<windowSwitcher preview="no" outlines="no" allWorkspaces="yes">
|
||||||
|
<osd show="yes" />
|
||||||
<fields>
|
<fields>
|
||||||
<field content="workspace" width="5%" />
|
<field content="workspace" width="5%" />
|
||||||
<field content="state" width="3%" />
|
<field content="state" width="3%" />
|
||||||
|
|
@ -118,7 +119,8 @@
|
||||||
then workspace name, then identifier/app-id, then the window title.
|
then workspace name, then identifier/app-id, then the window title.
|
||||||
It uses 100% of OSD window width.
|
It uses 100% of OSD window width.
|
||||||
|
|
||||||
<windowSwitcher show="yes" preview="no" outlines="no" allWorkspaces="yes">
|
<windowSwitcher preview="no" outlines="no" allWorkspaces="yes">
|
||||||
|
<osd show="yes" />
|
||||||
<fields>
|
<fields>
|
||||||
<field content="custom" format="foobar %b %3s %-10o %-20W %-10i %t" width="100%" />
|
<field content="custom" format="foobar %b %3s %-10o %-20W %-10i %t" width="100%" />
|
||||||
</fields>
|
</fields>
|
||||||
|
|
|
||||||
|
|
@ -183,6 +183,7 @@ struct rcxml {
|
||||||
enum lab_view_criteria criteria;
|
enum lab_view_criteria criteria;
|
||||||
struct wl_list fields; /* struct window_switcher_field.link */
|
struct wl_list fields; /* struct window_switcher_field.link */
|
||||||
enum window_switcher_style style;
|
enum window_switcher_style style;
|
||||||
|
enum osd_output_criteria output_criteria;
|
||||||
char *thumbnail_label_format;
|
char *thumbnail_label_format;
|
||||||
} window_switcher;
|
} window_switcher;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -112,4 +112,10 @@ enum window_switcher_style {
|
||||||
WINDOW_SWITCHER_THUMBNAIL,
|
WINDOW_SWITCHER_THUMBNAIL,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum osd_output_criteria {
|
||||||
|
OSD_OUTPUT_ALL,
|
||||||
|
OSD_OUTPUT_POINTER,
|
||||||
|
OSD_OUTPUT_KEYBOARD,
|
||||||
|
};
|
||||||
|
|
||||||
#endif /* LABWC_CONFIG_TYPES_H */
|
#endif /* LABWC_CONFIG_TYPES_H */
|
||||||
|
|
|
||||||
|
|
@ -1068,7 +1068,7 @@ entry(xmlNode *node, char *nodename, char *content)
|
||||||
load_default_mouse_bindings();
|
load_default_mouse_bindings();
|
||||||
} else if (!strcasecmp(nodename, "prefix.desktops")) {
|
} else if (!strcasecmp(nodename, "prefix.desktops")) {
|
||||||
xstrdup_replace(rc.workspace_config.prefix, content);
|
xstrdup_replace(rc.workspace_config.prefix, content);
|
||||||
} else if (!strcasecmp(nodename, "thumbnailLabelFormat.windowSwitcher")) {
|
} else if (!strcasecmp(nodename, "thumbnailLabelFormat.osd.windowSwitcher")) {
|
||||||
xstrdup_replace(rc.window_switcher.thumbnail_label_format, content);
|
xstrdup_replace(rc.window_switcher.thumbnail_label_format, content);
|
||||||
|
|
||||||
} else if (!lab_xml_node_is_leaf(node)) {
|
} else if (!lab_xml_node_is_leaf(node)) {
|
||||||
|
|
@ -1201,15 +1201,50 @@ entry(xmlNode *node, char *nodename, char *content)
|
||||||
wlr_log(WLR_ERROR, "ignoring invalid value for notifyClient");
|
wlr_log(WLR_ERROR, "ignoring invalid value for notifyClient");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* <windowSwitcher show="" preview="" outlines="" /> */
|
/*
|
||||||
|
* <windowSwitcher preview="" outlines="">
|
||||||
|
* <osd show="" style="" output="" thumbnailLabelFormat="" />
|
||||||
|
* </windowSwitcher>
|
||||||
|
*
|
||||||
|
* thumnailLabelFormat is handled above to allow for an empty value
|
||||||
|
*/
|
||||||
|
} else if (!strcasecmp(nodename, "show.osd.windowSwitcher")) {
|
||||||
|
set_bool(content, &rc.window_switcher.show);
|
||||||
|
} else if (!strcasecmp(nodename, "style.osd.windowSwitcher")) {
|
||||||
|
if (!strcasecmp(content, "classic")) {
|
||||||
|
rc.window_switcher.style = WINDOW_SWITCHER_CLASSIC;
|
||||||
|
} else if (!strcasecmp(content, "thumbnail")) {
|
||||||
|
rc.window_switcher.style = WINDOW_SWITCHER_THUMBNAIL;
|
||||||
|
} else {
|
||||||
|
wlr_log(WLR_ERROR, "Invalid windowSwitcher style %s: "
|
||||||
|
"should be one of classic|thumbnail", content);
|
||||||
|
}
|
||||||
|
} else if (!strcasecmp(nodename, "output.osd.windowSwitcher")) {
|
||||||
|
if (!strcasecmp(content, "all")) {
|
||||||
|
rc.window_switcher.output_criteria = OSD_OUTPUT_ALL;
|
||||||
|
} else if (!strcasecmp(content, "pointer")) {
|
||||||
|
rc.window_switcher.output_criteria = OSD_OUTPUT_POINTER;
|
||||||
|
} else if (!strcasecmp(content, "keyboard")) {
|
||||||
|
rc.window_switcher.output_criteria = OSD_OUTPUT_KEYBOARD;
|
||||||
|
} else {
|
||||||
|
wlr_log(WLR_ERROR, "Invalid windowSwitcher output %s: "
|
||||||
|
"should be one of all|pointer|keyboard", content);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The following two are for backward compatibility only. */
|
||||||
} else if (!strcasecmp(nodename, "show.windowSwitcher")) {
|
} else if (!strcasecmp(nodename, "show.windowSwitcher")) {
|
||||||
set_bool(content, &rc.window_switcher.show);
|
set_bool(content, &rc.window_switcher.show);
|
||||||
|
wlr_log(WLR_ERROR, "<windowSwitcher show=\"\" /> is deprecated."
|
||||||
|
" Use <osd show=\"\" />");
|
||||||
} else if (!strcasecmp(nodename, "style.windowSwitcher")) {
|
} else if (!strcasecmp(nodename, "style.windowSwitcher")) {
|
||||||
if (!strcasecmp(content, "classic")) {
|
if (!strcasecmp(content, "classic")) {
|
||||||
rc.window_switcher.style = WINDOW_SWITCHER_CLASSIC;
|
rc.window_switcher.style = WINDOW_SWITCHER_CLASSIC;
|
||||||
} else if (!strcasecmp(content, "thumbnail")) {
|
} else if (!strcasecmp(content, "thumbnail")) {
|
||||||
rc.window_switcher.style = WINDOW_SWITCHER_THUMBNAIL;
|
rc.window_switcher.style = WINDOW_SWITCHER_THUMBNAIL;
|
||||||
}
|
}
|
||||||
|
wlr_log(WLR_ERROR, "<windowSwitcher style=\"\" /> is deprecated."
|
||||||
|
" Use <osd style=\"\" />");
|
||||||
|
|
||||||
} else if (!strcasecmp(nodename, "preview.windowSwitcher")) {
|
} else if (!strcasecmp(nodename, "preview.windowSwitcher")) {
|
||||||
set_bool(content, &rc.window_switcher.preview);
|
set_bool(content, &rc.window_switcher.preview);
|
||||||
} else if (!strcasecmp(nodename, "outlines.windowSwitcher")) {
|
} else if (!strcasecmp(nodename, "outlines.windowSwitcher")) {
|
||||||
|
|
@ -1431,6 +1466,7 @@ rcxml_init(void)
|
||||||
|
|
||||||
rc.window_switcher.show = true;
|
rc.window_switcher.show = true;
|
||||||
rc.window_switcher.style = WINDOW_SWITCHER_CLASSIC;
|
rc.window_switcher.style = WINDOW_SWITCHER_CLASSIC;
|
||||||
|
rc.window_switcher.output_criteria = OSD_OUTPUT_ALL;
|
||||||
rc.window_switcher.thumbnail_label_format = xstrdup("%T");
|
rc.window_switcher.thumbnail_label_format = xstrdup("%T");
|
||||||
rc.window_switcher.preview = true;
|
rc.window_switcher.preview = true;
|
||||||
rc.window_switcher.outlines = true;
|
rc.window_switcher.outlines = true;
|
||||||
|
|
|
||||||
|
|
@ -294,6 +294,20 @@ preview_cycled_view(struct view *view)
|
||||||
wlr_scene_node_raise_to_top(osd_state->preview_node);
|
wlr_scene_node_raise_to_top(osd_state->preview_node);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
update_osd_on_output(struct server *server, struct output *output,
|
||||||
|
struct osd_impl *osd_impl, struct wl_array *views)
|
||||||
|
{
|
||||||
|
if (!output_is_usable(output)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!output->osd_scene.tree) {
|
||||||
|
osd_impl->create(output, views);
|
||||||
|
assert(output->osd_scene.tree);
|
||||||
|
}
|
||||||
|
osd_impl->update(output);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
update_osd(struct server *server)
|
update_osd(struct server *server)
|
||||||
{
|
{
|
||||||
|
|
@ -318,16 +332,29 @@ update_osd(struct server *server)
|
||||||
|
|
||||||
if (rc.window_switcher.show) {
|
if (rc.window_switcher.show) {
|
||||||
/* Display the actual OSD */
|
/* Display the actual OSD */
|
||||||
|
switch (rc.window_switcher.output_criteria) {
|
||||||
|
case OSD_OUTPUT_ALL: {
|
||||||
struct output *output;
|
struct output *output;
|
||||||
wl_list_for_each(output, &server->outputs, link) {
|
wl_list_for_each(output, &server->outputs, link) {
|
||||||
if (!output_is_usable(output)) {
|
update_osd_on_output(server, output, osd_impl, &views);
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
if (!output->osd_scene.tree) {
|
break;
|
||||||
osd_impl->create(output, &views);
|
}
|
||||||
assert(output->osd_scene.tree);
|
case OSD_OUTPUT_POINTER:
|
||||||
|
update_osd_on_output(server,
|
||||||
|
output_nearest_to_cursor(server), osd_impl, &views);
|
||||||
|
break;
|
||||||
|
case OSD_OUTPUT_KEYBOARD: {
|
||||||
|
struct output *output;
|
||||||
|
if (server->active_view) {
|
||||||
|
output = server->active_view->output;
|
||||||
|
} else {
|
||||||
|
/* Fallback to pointer, if there is no active_view */
|
||||||
|
output = output_nearest_to_cursor(server);
|
||||||
|
}
|
||||||
|
update_osd_on_output(server, output, osd_impl, &views);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
osd_impl->update(output);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue