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