diff --git a/docs/labwc-actions.5.scd b/docs/labwc-actions.5.scd
index fe468cd1..de1dc00d 100644
--- a/docs/labwc-actions.5.scd
+++ b/docs/labwc-actions.5.scd
@@ -424,6 +424,13 @@ Actions are used in menus and keyboard/mouse bindings.
Toggle the screen magnifier on or off at the last magnification level
used.
+**
+ Minimize all windows in the current workspace so that the desktop becomes
+ visible. On calling the action again the hidden windows are unminimized,
+ provided that - since the initial `ShowDesktop` - (a) no windows have been
+ unminimized; (b) workspaces have not been switched; and (c) no new
+ applications have been started.
+
**++
**
Increase or decrease the magnification level for the screen magnifier.
@@ -436,6 +443,10 @@ Actions are used in menus and keyboard/mouse bindings.
If used as the only action for a binding: clear an earlier defined
binding.
+**
+ Toggle visibility of key-state on-screen display (OSD). Note: This is for
+ debugging purposes only.
+
# CONDITIONAL ACTIONS
Actions that execute other actions. Used in keyboard/mouse bindings.
diff --git a/docs/labwc-config.5.scd b/docs/labwc-config.5.scd
index 09f7b3eb..ac94d54c 100644
--- a/docs/labwc-config.5.scd
+++ b/docs/labwc-config.5.scd
@@ -760,7 +760,8 @@ References:
Stores the keyboard layout either globally or per window and restores
it when switching back to the window. Default is global.
-**
+**
Define a *key* binding in the format *modifier-key*, where supported
modifiers are:
- S (shift)
@@ -808,6 +809,11 @@ References:
*allowWhenLocked* [yes|no]
Make this keybind work even if the screen is locked. Default is no.
+ *overrideInhibition* [yes|no]
+ Make this keybind work even if the view inhibits keybinds. Default is no.
+ This can be used to prevent W-Tab and similar keybinds from being
+ delivered to Virtual Machines, VNC clients or nested compositors.
+
*onRelease* [yes|no]
When yes, fires the keybind action when the key or key
combination is released, rather than first pressed. This is useful to
@@ -1445,6 +1451,52 @@ situation.
Whether to apply a bilinear filter to the magnified image, or
just to use nearest-neighbour. Default is true - bilinear filtered.
+## PRIVILEGED INTERFACES
+
+Labwc supports a small set of privileged wayland interfaces. All of these
+interfaces are enabled by default for applications unless they are running
+via a sandbox environment supporting the security-context-v1 protocol.
+
+Security conscious users are suggested to use a sandbox framework to run
+potentially untrusted applications as it additionally limits access to the
+filesystem (including labwc configuration) and other services like dbus.
+
+In addition to that, privileged protocols can be restricted for non-sandboxed
+clients by defining a `` block:
+
+```
+
+ zwlr_layer_shell_v1
+ zwlr_virtual_pointer_manager_v1
+
+```
+
+**
+ Name of the interface that should be allowed.
+
+This is the full list of interfaces that can be controlled with this mechanism:
+
+- `wp_drm_lease_device_v1`
+- `zwlr_gamma_control_manager_v1`
+- `zwlr_output_manager_v1`
+- `zwlr_output_power_manager_v1`
+- `zwp_input_method_manager_v2`
+- `zwlr_virtual_pointer_manager_v1`
+- `zwp_virtual_keyboard_manager_v1`
+- `zwlr_export_dmabuf_manager_v1`
+- `zwlr_screencopy_manager_v1`
+- `ext_data_control_manager_v1`
+- `zwlr_data_control_manager_v1`
+- `wp_security_context_manager_v1`
+- `ext_idle_notifier_v1`
+- `zwlr_foreign_toplevel_manager_v1`
+- `ext_foreign_toplevel_list_v1`
+- `ext_session_lock_manager_v1`
+- `zwlr_layer_shell_v1`
+- `ext_workspace_manager_v1`
+- `ext_image_copy_capture_manager_v1`
+- `ext_output_image_capture_source_manager_v1`
+
## ENVIRONMENT VARIABLES
*XCURSOR_PATH*
diff --git a/include/config/keybind.h b/include/config/keybind.h
index e3c9e21b..d02de387 100644
--- a/include/config/keybind.h
+++ b/include/config/keybind.h
@@ -23,6 +23,7 @@ struct keybind {
struct wl_list actions; /* struct action.link */
struct wl_list link; /* struct rcxml.keybinds */
bool on_release;
+ bool override_inhibition;
};
/**
diff --git a/include/config/rcxml.h b/include/config/rcxml.h
index 517cd907..8a2c606c 100644
--- a/include/config/rcxml.h
+++ b/include/config/rcxml.h
@@ -76,6 +76,7 @@ struct rcxml {
enum tearing_mode allow_tearing;
bool auto_enable_outputs;
bool reuse_output_mode;
+ uint32_t allowed_interfaces;
bool xwayland_persistence;
bool primary_selection;
char *prompt_command;
@@ -225,4 +226,6 @@ void rcxml_finish(void);
*/
void append_parsed_actions(xmlNode *node, struct wl_list *list);
+uint32_t parse_privileged_interface(const char *name);
+
#endif /* LABWC_RCXML_H */
diff --git a/include/input/key-state.h b/include/input/key-state.h
index d9971b74..81374b6c 100644
--- a/include/input/key-state.h
+++ b/include/input/key-state.h
@@ -5,12 +5,17 @@
#include
#include
+struct seat;
+
/*
* All keycodes in these functions are (Linux) libinput evdev scancodes which is
* what 'wlr_keyboard' uses (e.g. 'seat->keyboard_group->keyboard->keycodes').
* Note: These keycodes are different to XKB scancodes by a value of 8.
*/
+void key_state_indicator_update(struct seat *seat);
+void key_state_indicator_toggle(void);
+
/**
* key_state_pressed_sent_keycodes - generate array of pressed+sent keys
* Note: The array is generated by subtracting any bound keys from _all_ pressed
diff --git a/include/show-desktop.h b/include/show-desktop.h
new file mode 100644
index 00000000..cc86bcb4
--- /dev/null
+++ b/include/show-desktop.h
@@ -0,0 +1,8 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+#ifndef LABWC_SHOW_DESKTOP_H
+#define LABWC_SHOW_DESKTOP_H
+
+void show_desktop_toggle(void);
+void show_desktop_reset(void);
+
+#endif /* LABWC_SHOW_DESKTOP_H */
diff --git a/include/view.h b/include/view.h
index c2764f94..da7aef02 100644
--- a/include/view.h
+++ b/include/view.h
@@ -184,6 +184,7 @@ struct view {
enum ssd_preference ssd_preference;
bool shaded;
bool minimized;
+ bool was_minimized_by_show_desktop_action;
enum view_axis maximized;
bool fullscreen;
bool tearing_hint;
diff --git a/po/LINGUAS b/po/LINGUAS
index 33f036c9..70114b72 100644
--- a/po/LINGUAS
+++ b/po/LINGUAS
@@ -1 +1 @@
-ar ca cs da de el es et eu fa fi fr gl he hr hu id it ja ka kk ko lt ms nl pa pl pt pt_BR ru sk sv tr uk vi zh_CN zh_TW
+ar ca cs da de el es et eu fa fi fr gl he hr hu id it ja ka kab kk ko lt ms nl pa pl pt pt_BR ru sk sv tr uk vi zh_CN zh_TW
diff --git a/po/kab.po b/po/kab.po
new file mode 100644
index 00000000..44961f47
--- /dev/null
+++ b/po/kab.po
@@ -0,0 +1,80 @@
+# Labwc pot file
+# Copyright (C) 2024
+# This file is distributed under the same license as the labwc package.
+# FIRST AUTHOR , YEAR.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: labwc\n"
+"Report-Msgid-Bugs-To: https://github.com/labwc/labwc/issues\n"
+"POT-Creation-Date: 2024-09-19 21:09+1000\n"
+"PO-Revision-Date: 2026-03-31 08:01+0000\n"
+"Last-Translator: ButterflyOfFire \n"
+"Language-Team: Kabyle \n"
+"Language: kab\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=n > 1;\n"
+"X-Generator: Weblate 4.2.1\n"
+
+#: src/menu/menu.c:1016
+msgid "Go there..."
+msgstr ""
+
+#: src/menu/menu.c:1034
+msgid "Terminal"
+msgstr "Ixf"
+
+#: src/menu/menu.c:1040
+msgid "Reconfigure"
+msgstr ""
+
+#: src/menu/menu.c:1042
+msgid "Exit"
+msgstr "Ffeɣ"
+
+#: src/menu/menu.c:1056
+msgid "Minimize"
+msgstr ""
+
+#: src/menu/menu.c:1058
+msgid "Maximize"
+msgstr ""
+
+#: src/menu/menu.c:1060
+msgid "Fullscreen"
+msgstr "Agdil aččuran"
+
+#: src/menu/menu.c:1062
+msgid "Roll Up/Down"
+msgstr ""
+
+#: src/menu/menu.c:1064
+msgid "Decorations"
+msgstr ""
+
+#: src/menu/menu.c:1066
+msgid "Always on Top"
+msgstr ""
+
+#: src/menu/menu.c:1071
+msgid "Move Left"
+msgstr ""
+
+#: src/menu/menu.c:1078
+msgid "Move Right"
+msgstr ""
+
+#: src/menu/menu.c:1083
+msgid "Always on Visible Workspace"
+msgstr ""
+
+#: src/menu/menu.c:1086
+msgid "Workspace"
+msgstr ""
+
+#: src/menu/menu.c:1089
+msgid "Close"
+msgstr "Mdel"
diff --git a/src/action.c b/src/action.c
index 66fa9b20..34435e02 100644
--- a/src/action.c
+++ b/src/action.c
@@ -21,12 +21,14 @@
#include "cycle.h"
#include "debug.h"
#include "input/keyboard.h"
+#include "input/key-state.h"
#include "labwc.h"
#include "magnifier.h"
#include "menu/menu.h"
#include "output.h"
#include "output-virtual.h"
#include "regions.h"
+#include "show-desktop.h"
#include "ssd.h"
#include "theme.h"
#include "translate.h"
@@ -132,8 +134,10 @@ struct action_arg_list {
X(TOGGLE_MAGNIFY, "ToggleMagnify") \
X(ZOOM_IN, "ZoomIn") \
X(ZOOM_OUT, "ZoomOut") \
+ X(TOGGLE_SHOW_DESKTOP, "ToggleShowDesktop") \
X(WARP_CURSOR, "WarpCursor") \
- X(HIDE_CURSOR, "HideCursor")
+ X(HIDE_CURSOR, "HideCursor") \
+ X(DEBUG_TOGGLE_KEY_STATE_INDICATOR, "DebugToggleKeyStateIndicator")
/*
* Will expand to:
@@ -1560,6 +1564,9 @@ run_action(struct view *view, struct action *action,
case ACTION_TYPE_ZOOM_OUT:
magnifier_set_scale(MAGNIFY_DECREASE);
break;
+ case ACTION_TYPE_TOGGLE_SHOW_DESKTOP:
+ show_desktop_toggle();
+ break;
case ACTION_TYPE_WARP_CURSOR: {
const char *to = action_get_str(action, "to", "output");
const char *x = action_get_str(action, "x", "center");
@@ -1570,6 +1577,9 @@ run_action(struct view *view, struct action *action,
case ACTION_TYPE_HIDE_CURSOR:
cursor_set_visible(&server.seat, false);
break;
+ case ACTION_TYPE_DEBUG_TOGGLE_KEY_STATE_INDICATOR:
+ key_state_indicator_toggle();
+ break;
case ACTION_TYPE_INVALID:
wlr_log(WLR_ERROR, "Not executing unknown action");
break;
diff --git a/src/config/rcxml.c b/src/config/rcxml.c
index a3eeed63..20c236b4 100644
--- a/src/config/rcxml.c
+++ b/src/config/rcxml.c
@@ -94,6 +94,43 @@ parse_window_type(const char *type)
}
}
+uint32_t
+parse_privileged_interface(const char *name)
+{
+ static const char * const ifaces[] = {
+ "wp_drm_lease_device_v1",
+ "zwlr_gamma_control_manager_v1",
+ "zwlr_output_manager_v1",
+ "zwlr_output_power_manager_v1",
+ "zwp_input_method_manager_v2",
+ "zwlr_virtual_pointer_manager_v1",
+ "zwp_virtual_keyboard_manager_v1",
+ "zwlr_export_dmabuf_manager_v1",
+ "zwlr_screencopy_manager_v1",
+ "ext_data_control_manager_v1",
+ "zwlr_data_control_manager_v1",
+ "wp_security_context_manager_v1",
+ "ext_idle_notifier_v1",
+ "zwlr_foreign_toplevel_manager_v1",
+ "ext_foreign_toplevel_list_v1",
+ "ext_session_lock_manager_v1",
+ "zwlr_layer_shell_v1",
+ "ext_workspace_manager_v1",
+ "ext_image_copy_capture_manager_v1",
+ "ext_output_image_capture_source_manager_v1",
+ };
+
+ static_assert(ARRAY_SIZE(ifaces) <= 32,
+ "return type too small for amount of privileged protocols");
+
+ for (size_t i = 0; i < ARRAY_SIZE(ifaces); i++) {
+ if (!strcmp(name, ifaces[i])) {
+ return 1 << i;
+ }
+ }
+ return 0;
+}
+
/*
* Openbox/labwc comparison
*
@@ -565,6 +602,7 @@ fill_keybind(xmlNode *node)
lab_xml_get_bool(node, "onRelease", &keybind->on_release);
lab_xml_get_bool(node, "layoutDependent", &keybind->use_syms_only);
lab_xml_get_bool(node, "allowWhenLocked", &keybind->allow_when_locked);
+ lab_xml_get_bool(node, "overrideInhibition", &keybind->override_inhibition);
append_parsed_actions(node, &keybind->actions);
}
@@ -1377,6 +1415,16 @@ entry(xmlNode *node, char *nodename, char *content)
rc.mag_increment = MAX(0, rc.mag_increment);
} else if (!strcasecmp(nodename, "useFilter.magnifier")) {
set_bool(content, &rc.mag_filter);
+ } else if (!strcasecmp(nodename, "privilegedInterfaces")) {
+ rc.allowed_interfaces = 0;
+ } else if (!strcasecmp(nodename, "allow.privilegedInterfaces")) {
+ uint32_t iface_id = parse_privileged_interface(content);
+ if (iface_id) {
+ rc.allowed_interfaces |= iface_id;
+ } else {
+ wlr_log(WLR_ERROR, "invalid value for "
+ "");
+ }
}
return false;
@@ -1459,6 +1507,7 @@ rcxml_init(void)
rc.allow_tearing = LAB_TEARING_DISABLED;
rc.auto_enable_outputs = true;
rc.reuse_output_mode = false;
+ rc.allowed_interfaces = UINT32_MAX;
rc.xwayland_persistence = false;
rc.primary_selection = true;
@@ -1658,6 +1707,8 @@ deduplicate_key_bindings(void)
wl_list_remove(¤t->link);
keybind_destroy(current);
cleared++;
+ } else if (actions_contain_toggle_keybinds(¤t->actions)) {
+ current->override_inhibition = true;
}
}
if (replaced) {
diff --git a/src/cycle/osd-thumbnail.c b/src/cycle/osd-thumbnail.c
index eba0249e..7cd7ff9f 100644
--- a/src/cycle/osd-thumbnail.c
+++ b/src/cycle/osd-thumbnail.c
@@ -2,6 +2,7 @@
#include
#include
#include
+#include
#include
#include
#include "config/rcxml.h"
@@ -46,8 +47,12 @@ render_node(struct wlr_render_pass *pass,
if (!scene_buffer->buffer) {
break;
}
- struct wlr_texture *texture = wlr_texture_from_buffer(
- server.renderer, scene_buffer->buffer);
+ struct wlr_texture *texture = NULL;
+ struct wlr_client_buffer *client_buffer =
+ wlr_client_buffer_get(scene_buffer->buffer);
+ if (client_buffer) {
+ texture = client_buffer->texture;
+ }
if (!texture) {
break;
}
@@ -62,7 +67,6 @@ render_node(struct wlr_render_pass *pass,
},
.transform = scene_buffer->transform,
});
- wlr_texture_destroy(texture);
break;
}
case WLR_SCENE_NODE_RECT:
diff --git a/src/desktop.c b/src/desktop.c
index 28bf4464..4c7870f1 100644
--- a/src/desktop.c
+++ b/src/desktop.c
@@ -14,6 +14,7 @@
#include "layers.h"
#include "node.h"
#include "output.h"
+#include "show-desktop.h"
#include "ssd.h"
#include "view.h"
#include "workspaces.h"
@@ -113,6 +114,8 @@ desktop_focus_view(struct view *view, bool raise)
*/
struct view *dialog = view_get_modal_dialog(view);
set_or_offer_focus(dialog ? dialog : view);
+
+ show_desktop_reset();
}
/* TODO: focus layer-shell surfaces also? */
diff --git a/src/input/key-state.c b/src/input/key-state.c
index 492f7b0f..6d089891 100644
--- a/src/input/key-state.c
+++ b/src/input/key-state.c
@@ -4,10 +4,171 @@
#include
#include
#include
+#include
+#include
+#include
+#include "config/rcxml.h"
+#include "common/buf.h"
#include "common/set.h"
+#include "input/keyboard.h"
+#include "labwc.h"
+#include "scaled-buffer/scaled-font-buffer.h"
static struct lab_set pressed, bound, pressed_sent;
+static bool show_debug_indicator;
+static struct indicator_state {
+ struct wlr_scene_tree *tree;
+ struct scaled_font_buffer *sfb_pressed;
+ struct scaled_font_buffer *sfb_bound;
+ struct scaled_font_buffer *sfb_pressed_sent;
+ struct scaled_font_buffer *sfb_modifiers;
+ struct xkb_keymap *keymap;
+} indicator_state;
+
+static const char *
+keycode_to_keyname(struct xkb_keymap *keymap, uint32_t keycode)
+{
+ const xkb_keysym_t *syms;
+ int syms_len = xkb_keymap_key_get_syms_by_level(keymap, keycode + 8, 0, 0, &syms);
+ if (!syms_len) {
+ return NULL;
+ }
+
+ static char buf[256];
+ if (!xkb_keysym_get_name(syms[0], buf, sizeof(buf))) {
+ return NULL;
+ }
+
+ return buf;
+}
+
+static const char *
+modifier_to_name(uint32_t modifier)
+{
+ switch (modifier) {
+ case WLR_MODIFIER_SHIFT:
+ return "S";
+ case WLR_MODIFIER_CAPS:
+ return "caps";
+ case WLR_MODIFIER_CTRL:
+ return "C";
+ case WLR_MODIFIER_ALT:
+ return "A";
+ case WLR_MODIFIER_MOD2:
+ return "numlock";
+ case WLR_MODIFIER_MOD3:
+ return "H";
+ case WLR_MODIFIER_LOGO:
+ return "W";
+ case WLR_MODIFIER_MOD5:
+ return "M";
+ default:
+ return "?";
+ }
+}
+
+static void
+init_indicator(struct indicator_state *state)
+{
+ state->tree = wlr_scene_tree_create(&server.scene->tree);
+ wlr_scene_node_set_enabled(&state->tree->node, false);
+
+ state->sfb_pressed = scaled_font_buffer_create(state->tree);
+ wlr_scene_node_set_position(&state->sfb_pressed->scene_buffer->node, 0, 0);
+ state->sfb_bound = scaled_font_buffer_create(state->tree);
+ wlr_scene_node_set_position(&state->sfb_bound->scene_buffer->node, 0, 20);
+ state->sfb_pressed_sent = scaled_font_buffer_create(state->tree);
+ wlr_scene_node_set_position(&state->sfb_pressed_sent->scene_buffer->node, 0, 40);
+ state->sfb_modifiers = scaled_font_buffer_create(state->tree);
+ wlr_scene_node_set_position(&state->sfb_modifiers->scene_buffer->node, 0, 60);
+
+ struct xkb_rule_names rules = { 0 };
+ struct xkb_context *context = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
+ state->keymap = xkb_map_new_from_names(context, &rules, XKB_KEYMAP_COMPILE_NO_FLAGS);
+}
+
+static void
+update_key_indicator_callback(void *data)
+{
+ struct seat *seat = data;
+ uint32_t all_modifiers = keyboard_get_all_modifiers(seat);
+ float black[4] = {0, 0, 0, 1};
+ float white[4] = {1, 1, 1, 1};
+
+ if (!indicator_state.tree) {
+ init_indicator(&indicator_state);
+ }
+
+ if (show_debug_indicator) {
+ wlr_scene_node_set_enabled(&indicator_state.tree->node, true);
+ } else {
+ wlr_scene_node_set_enabled(&indicator_state.tree->node, false);
+ return;
+ }
+
+ struct buf buf = BUF_INIT;
+
+ buf_add(&buf, "pressed=");
+ for (int i = 0; i < pressed.size; i++) {
+ const char *keyname = keycode_to_keyname(indicator_state.keymap,
+ pressed.values[i]);
+ buf_add_fmt(&buf, "%s (%d), ", keyname, pressed.values[i]);
+ }
+ scaled_font_buffer_update(indicator_state.sfb_pressed, buf.data,
+ -1, &rc.font_osd, black, white);
+
+ buf_clear(&buf);
+ buf_add(&buf, "bound=");
+ for (int i = 0; i < bound.size; i++) {
+ const char *keyname = keycode_to_keyname(indicator_state.keymap,
+ bound.values[i]);
+ buf_add_fmt(&buf, "%s (%d), ", keyname, bound.values[i]);
+ }
+ scaled_font_buffer_update(indicator_state.sfb_bound, buf.data,
+ -1, &rc.font_osd, black, white);
+
+ buf_clear(&buf);
+ buf_add(&buf, "pressed_sent=");
+ for (int i = 0; i < pressed_sent.size; i++) {
+ const char *keyname = keycode_to_keyname(indicator_state.keymap,
+ pressed_sent.values[i]);
+ buf_add_fmt(&buf, "%s (%d), ", keyname, pressed_sent.values[i]);
+ }
+ scaled_font_buffer_update(indicator_state.sfb_pressed_sent, buf.data, -1,
+ &rc.font_osd, black, white);
+
+ buf_clear(&buf);
+ buf_add(&buf, "modifiers=");
+ for (int i = 0; i <= 7; i++) {
+ uint32_t mod = 1 << i;
+ if (all_modifiers & mod) {
+ buf_add_fmt(&buf, "%s, ", modifier_to_name(mod));
+ }
+ }
+ buf_add_fmt(&buf, "(%d)", all_modifiers);
+ scaled_font_buffer_update(indicator_state.sfb_modifiers, buf.data, -1,
+ &rc.font_osd, black, white);
+
+ buf_reset(&buf);
+}
+
+void
+key_state_indicator_update(struct seat *seat)
+{
+ if (!show_debug_indicator) {
+ return;
+ }
+ wl_event_loop_add_idle(server.wl_event_loop,
+ update_key_indicator_callback, seat);
+}
+
+void
+key_state_indicator_toggle(void)
+{
+ show_debug_indicator = !show_debug_indicator;
+}
+
static void
report(struct lab_set *key_set, const char *msg)
{
diff --git a/src/input/keyboard.c b/src/input/keyboard.c
index 16b51947..36884144 100644
--- a/src/input/keyboard.c
+++ b/src/input/keyboard.c
@@ -139,6 +139,8 @@ handle_modifiers(struct wl_listener *listener, void *data)
struct seat *seat = keyboard->base.seat;
struct wlr_keyboard *wlr_keyboard = keyboard->wlr_keyboard;
+ key_state_indicator_update(seat);
+
if (server.input_mode == LAB_INPUT_STATE_MOVE) {
/* Any change to the modifier state re-enable region snap */
seat->region_prevent_snap = false;
@@ -201,8 +203,10 @@ match_keybinding_for_sym(uint32_t modifiers,
if (modifiers ^ keybind->modifiers) {
continue;
}
- if (view_inhibits_actions(server.active_view, &keybind->actions)) {
- continue;
+ if (!(keybind->override_inhibition)) {
+ if (view_inhibits_actions(server.active_view, &keybind->actions)) {
+ continue;
+ }
}
if (sym == XKB_KEY_NoSymbol) {
/* Use keycodes */
@@ -631,6 +635,9 @@ handle_key(struct wl_listener *listener, void *data)
struct seat *seat = keyboard->base.seat;
struct wlr_keyboard_key_event *event = data;
struct wlr_seat *wlr_seat = seat->wlr_seat;
+
+ key_state_indicator_update(seat);
+
idle_manager_notify_activity(seat->wlr_seat);
/* any new press/release cancels current keybind repeat */
diff --git a/src/meson.build b/src/meson.build
index 40ec3170..05163cfa 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -22,6 +22,7 @@ labwc_sources = files(
'seat.c',
'server.c',
'session-lock.c',
+ 'show-desktop.c',
'snap-constraints.c',
'snap.c',
'tearing.c',
diff --git a/src/server.c b/src/server.c
index fd48efed..e4b27026 100644
--- a/src/server.c
+++ b/src/server.c
@@ -9,6 +9,8 @@
#include
#include
#include
+#include
+#include
#include
#include
#include
@@ -210,39 +212,6 @@ handle_drm_lease_request(struct wl_listener *listener, void *data)
}
#endif
-static bool
-protocol_is_privileged(const struct wl_interface *iface)
-{
- static const char * const rejected[] = {
- "wp_drm_lease_device_v1",
- "zwlr_gamma_control_manager_v1",
- "zwlr_output_manager_v1",
- "zwlr_output_power_manager_v1",
- "zwp_input_method_manager_v2",
- "zwlr_virtual_pointer_manager_v1",
- "zwp_virtual_keyboard_manager_v1",
- "zwlr_export_dmabuf_manager_v1",
- "zwlr_screencopy_manager_v1",
- "ext_data_control_manager_v1",
- "zwlr_data_control_manager_v1",
- "wp_security_context_manager_v1",
- "ext_idle_notifier_v1",
- "zwlr_foreign_toplevel_manager_v1",
- "ext_foreign_toplevel_list_v1",
- "ext_session_lock_manager_v1",
- "zwlr_layer_shell_v1",
- "ext_workspace_manager_v1",
- "ext_image_copy_capture_manager_v1",
- "ext_output_image_capture_source_manager_v1",
- };
- for (size_t i = 0; i < ARRAY_SIZE(rejected); i++) {
- if (!strcmp(iface->name, rejected[i])) {
- return true;
- }
- }
- return false;
-}
-
static bool
allow_for_sandbox(const struct wlr_security_context_v1_state *security_state,
const struct wl_interface *iface)
@@ -285,6 +254,8 @@ allow_for_sandbox(const struct wlr_security_context_v1_state *security_state,
"xdg_wm_dialog_v1",
/* plus */
"wp_alpha_modifier_v1",
+ "wp_color_manager_v1",
+ "wp_color_representation_manager_v1",
"wp_linux_drm_syncobj_manager_v1",
"zxdg_exporter_v1",
"zxdg_exporter_v2",
@@ -323,6 +294,11 @@ server_global_filter(const struct wl_client *client, const struct wl_global *glo
}
#endif
+ uint32_t iface_id = parse_privileged_interface(iface->name);
+ if (iface_id && !(iface_id & rc.allowed_interfaces)) {
+ return false;
+ }
+
/* Do not allow security_context_manager_v1 to clients with a security context attached */
const struct wlr_security_context_v1_state *security_context =
wlr_security_context_manager_v1_lookup_client(
@@ -338,11 +314,11 @@ server_global_filter(const struct wl_client *client, const struct wl_global *glo
/*
* TODO: The following call is basically useless right now
* and should be replaced with
- * assert(allow || protocol_is_privileged(iface));
+ * assert(allow || iface_id);
* This ensures that our lists are in sync with what
* protocols labwc supports.
*/
- if (!allow && !protocol_is_privileged(iface)) {
+ if (!allow && !iface_id) {
wlr_log(WLR_ERROR, "Blocking unknown protocol %s", iface->name);
} else if (!allow) {
wlr_log(WLR_DEBUG, "Blocking %s for security context %s->%s->%s",
@@ -592,6 +568,47 @@ server_init(void)
* | output->layer_tree[0] | background layer surfaces (e.g. swaybg)
*/
+ if (server.renderer->features.input_color_transform) {
+ const enum wp_color_manager_v1_render_intent render_intents[] = {
+ WP_COLOR_MANAGER_V1_RENDER_INTENT_PERCEPTUAL,
+ };
+ size_t transfer_functions_len = 0;
+ enum wp_color_manager_v1_transfer_function *transfer_functions =
+ wlr_color_manager_v1_transfer_function_list_from_renderer(
+ server.renderer, &transfer_functions_len);
+
+ size_t primaries_len = 0;
+ enum wp_color_manager_v1_primaries *primaries =
+ wlr_color_manager_v1_primaries_list_from_renderer(
+ server.renderer, &primaries_len);
+
+ struct wlr_color_manager_v1 *cm = wlr_color_manager_v1_create(
+ server.wl_display, 2, &(struct wlr_color_manager_v1_options){
+ .features = {
+ .parametric = true,
+ .set_mastering_display_primaries = true,
+ },
+ .render_intents = render_intents,
+ .render_intents_len = ARRAY_SIZE(render_intents),
+ .transfer_functions = transfer_functions,
+ .transfer_functions_len = transfer_functions_len,
+ .primaries = primaries,
+ .primaries_len = primaries_len,
+ });
+
+ free(transfer_functions);
+ free(primaries);
+
+ if (cm) {
+ wlr_scene_set_color_manager_v1(server.scene, cm);
+ } else {
+ wlr_log(WLR_ERROR, "unable to create color manager");
+ }
+ }
+
+ wlr_color_representation_manager_v1_create_with_renderer(
+ server.wl_display, 1, server.renderer);
+
server.workspace_tree = lab_wlr_scene_tree_create(&server.scene->tree);
server.xdg_popup_tree = lab_wlr_scene_tree_create(&server.scene->tree);
#if HAVE_XWAYLAND
diff --git a/src/show-desktop.c b/src/show-desktop.c
new file mode 100644
index 00000000..efddf2de
--- /dev/null
+++ b/src/show-desktop.c
@@ -0,0 +1,78 @@
+// SPDX-License-Identifier: GPL-2.0-only
+#include "show-desktop.h"
+#include
+#include "common/array.h"
+#include "config/types.h"
+#include "labwc.h"
+#include "view.h"
+
+static bool is_showing_desktop;
+
+static void
+minimize_views(struct wl_array *views, bool minimize)
+{
+ struct view **view;
+ wl_array_for_each_reverse(view, views) {
+ view_minimize(*view, minimize);
+ }
+}
+
+static void
+show(void)
+{
+ static struct wl_array views;
+ wl_array_init(&views);
+
+ /* Build array first as minimize changes server.views */
+ struct view *view;
+ for_each_view(view, &server.views, LAB_VIEW_CRITERIA_CURRENT_WORKSPACE) {
+ if (view->minimized) {
+ continue;
+ }
+ view->was_minimized_by_show_desktop_action = true;
+ array_add(&views, view);
+ }
+ minimize_views(&views, true);
+ is_showing_desktop = true;
+
+ wl_array_release(&views);
+}
+
+static void
+restore(void)
+{
+ static struct wl_array views;
+ wl_array_init(&views);
+
+ struct view *view;
+ for_each_view(view, &server.views, LAB_VIEW_CRITERIA_CURRENT_WORKSPACE) {
+ if (view->was_minimized_by_show_desktop_action) {
+ array_add(&views, view);
+ }
+ }
+ minimize_views(&views, false);
+ show_desktop_reset();
+
+ wl_array_release(&views);
+}
+
+void
+show_desktop_toggle(void)
+{
+ if (is_showing_desktop) {
+ restore();
+ } else {
+ show();
+ }
+}
+
+void
+show_desktop_reset(void)
+{
+ is_showing_desktop = false;
+
+ struct view *view;
+ for_each_view(view, &server.views, LAB_VIEW_CRITERIA_NONE) {
+ view->was_minimized_by_show_desktop_action = false;
+ }
+}
diff --git a/src/workspaces.c b/src/workspaces.c
index 7ff471a5..a1ed9112 100644
--- a/src/workspaces.c
+++ b/src/workspaces.c
@@ -21,6 +21,7 @@
#include "input/keyboard.h"
#include "labwc.h"
#include "output.h"
+#include "show-desktop.h"
#include "theme.h"
#include "view.h"
@@ -495,6 +496,8 @@ workspaces_switch_to(struct workspace *target, bool update_focus)
desktop_update_top_layer_visibility();
wlr_ext_workspace_handle_v1_set_active(target->ext_workspace, true);
+
+ show_desktop_reset();
}
void