*Criteria*
-*<windowRules><windowRule identifier="" title="" type="" matchOnce="">*
+*<windowRules><windowRule identifier="" title="" sandboxEngine=""
+sandboxAppId="" type="" matchOnce="">*
Define a window rule for any window which matches the criteria defined
by the attributes *identifier*, *title*, or *type*. If more than one
is defined, AND logic is used, so all have to match.
*title* is the title of the window.
+ *sandboxEngine* is a sandbox engine name from the security context.
+
+ *sandboxAppId* is a sandbox-specific identifier for an application
+ from the security context.
+
*type* [desktop|dock|toolbar|menu|utility|splash|dialog|dropdown_menu|
popup_menu|tooltip|notification|combo|dnd|normal] relates to
NET_WM_WINDOW_TYPE for XWayland clients. Native wayland clients have
<!--
# Window Rules
- # - Criteria can consist of 'identifier' or 'title' or both (in which
- # case AND logic is used).
+ # - Criteria can consist of 'identifier', 'title', 'sandboxEngine' or
+ # 'sandboxAppId'. AND logic is used when multiple options are specified.
# - 'identifier' relates to app_id for native Wayland windows and
# WM_CLASS for XWayland clients.
# - Criteria can also contain `matchOnce="true"` meaning that the rule
struct wlr_text_input_manager_v3 *text_input_manager;
struct wlr_tablet_manager_v2 *tablet_manager;
+ struct wlr_security_context_manager_v1 *security_context_manager_v1;
/* Set when in cycle (alt-tab) mode */
struct osd_state {
char *identifier;
char *title;
int window_type;
+ char *sandbox_engine;
+ char *sandbox_app_id;
};
struct xdg_toplevel_view {
char *identifier;
char *title;
int window_type;
+ char *sandbox_engine;
+ char *sandbox_app_id;
bool match_once;
enum window_rule_event event;
current_window_rule->window_type = parse_window_type(content);
} else if (!strcasecmp(nodename, "matchOnce")) {
set_bool(content, ¤t_window_rule->match_once);
+ } else if (!strcasecmp(nodename, "sandboxEngine")) {
+ free(current_window_rule->sandbox_engine);
+ current_window_rule->sandbox_engine = xstrdup(content);
+ } else if (!strcasecmp(nodename, "sandboxAppId")) {
+ free(current_window_rule->sandbox_app_id);
+ current_window_rule->sandbox_app_id = xstrdup(content);
/* Event */
} else if (!strcmp(nodename, "event")) {
current_view_query->title = xstrdup(content);
} else if (!strcmp(nodename, "type")) {
current_view_query->window_type = parse_window_type(content);
+ } else if (!strcasecmp(nodename, "sandboxEngine")) {
+ current_view_query->sandbox_engine = xstrdup(content);
+ } else if (!strcasecmp(nodename, "sandboxAppId")) {
+ current_view_query->sandbox_app_id = xstrdup(content);
}
}
wl_list_remove(&rule->link);
zfree(rule->identifier);
zfree(rule->title);
+ zfree(rule->sandbox_engine);
+ zfree(rule->sandbox_app_id);
action_list_free(&rule->actions);
zfree(rule);
}
/* Window-rule criteria */
struct window_rule *rule, *rule_tmp;
wl_list_for_each_safe(rule, rule_tmp, &rc.window_rules, link) {
- if (!rule->identifier && !rule->title && rule->window_type < 0) {
+ if (!rule->identifier && !rule->title && rule->window_type < 0
+ && !rule->sandbox_engine && !rule->sandbox_app_id) {
wlr_log(WLR_ERROR, "Deleting rule %p as it has no criteria", rule);
rule_destroy(rule);
}
#include <wlr/types/wlr_presentation_time.h>
#include <wlr/types/wlr_primary_selection_v1.h>
#include <wlr/types/wlr_screencopy_v1.h>
+#include <wlr/types/wlr_security_context_v1.h>
#include <wlr/types/wlr_single_pixel_buffer_v1.h>
#include <wlr/types/wlr_viewporter.h>
#include <wlr/types/wlr_tablet_v2.h>
}
#endif
+ /* 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(
+ server->security_context_manager_v1, (struct wl_client *)client);
+ if (security_context && global == server->security_context_manager_v1->global) {
+ wlr_log(WLR_DEBUG, "blocking security_context_manager_v1 for the sandboxed client");
+ return false;
+ }
+
return true;
}
wlr_export_dmabuf_manager_v1_create(server->wl_display);
wlr_screencopy_manager_v1_create(server->wl_display);
wlr_data_control_manager_v1_create(server->wl_display);
+ server->security_context_manager_v1 =
+ wlr_security_context_manager_v1_create(server->wl_display);
wlr_viewporter_create(server->wl_display);
wlr_single_pixel_buffer_manager_v1_create(server->wl_display);
wlr_fractional_scale_manager_v1_create(server->wl_display,
#include <stdio.h>
#include <strings.h>
#include <wlr/types/wlr_output_layout.h>
+#include <wlr/types/wlr_security_context_v1.h>
#include "common/macros.h"
#include "common/match.h"
#include "common/mem.h"
return NULL;
}
+static const struct wlr_security_context_v1_state *
+security_context_from_view(struct view *view)
+{
+ if (view && view->surface && view->surface->resource) {
+ struct wl_client *client = wl_resource_get_client(view->surface->resource);
+ return wlr_security_context_manager_v1_lookup_client(
+ view->server->security_context_manager_v1, client);
+ }
+ return NULL;
+}
+
struct view_query *
view_query_create(void)
{
wl_list_remove(&query->link);
free(query->identifier);
free(query->title);
+ free(query->sandbox_engine);
+ free(query->sandbox_app_id);
free(query);
}
match &= view_contains_window_type(view, query->window_type);
}
+ if (match && query->sandbox_engine) {
+ const struct wlr_security_context_v1_state *security_context =
+ security_context_from_view(view);
+ empty = false;
+ match &= security_context && security_context->sandbox_engine
+ && match_glob(query->sandbox_engine, security_context->sandbox_engine);
+ }
+
+ if (match && query->sandbox_app_id) {
+ const struct wlr_security_context_v1_state *security_context =
+ security_context_from_view(view);
+ empty = false;
+ match &= security_context && security_context->app_id
+ && match_glob(query->sandbox_app_id, security_context->app_id);
+ }
+
return !empty && match;
}
query.identifier = rule->identifier;
query.title = rule->title;
query.window_type = rule->window_type;
+ query.sandbox_engine = rule->sandbox_engine;
+ query.sandbox_app_id = rule->sandbox_app_id;
if (rule->match_once && other_instances_exist(view, &query)) {
return false;