Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Expose sandbox properties via IPC JSON, criteria, title format #8521

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions include/sway/criteria.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,9 @@ struct criteria {
char urgent; // 'l' for latest or 'o' for oldest
struct pattern *workspace;
pid_t pid;
struct pattern *sandbox_engine;
struct pattern *sandbox_app_id;
struct pattern *sandbox_instance_id;
};

bool criteria_is_empty(struct criteria *criteria);
Expand Down
9 changes: 9 additions & 0 deletions include/sway/tree/view.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@ enum sway_view_prop {
VIEW_PROP_X11_WINDOW_ID,
VIEW_PROP_X11_PARENT_ID,
#endif
VIEW_PROP_SANDBOX_ENGINE,
VIEW_PROP_SANDBOX_APP_ID,
VIEW_PROP_SANDBOX_INSTANCE_ID,
};

enum sway_view_tearing_mode {
Expand Down Expand Up @@ -221,6 +224,12 @@ const char *view_get_window_role(struct sway_view *view);

uint32_t view_get_window_type(struct sway_view *view);

const char *view_get_sandbox_engine(struct sway_view *view);

const char *view_get_sandbox_app_id(struct sway_view *view);

const char *view_get_sandbox_instance_id(struct sway_view *view);

const char *view_get_shell(struct sway_view *view);

void view_get_constraints(struct sway_view *view, double *min_width,
Expand Down
86 changes: 85 additions & 1 deletion sway/criteria.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,10 @@ bool criteria_is_empty(struct criteria *criteria) {
&& !criteria->tiling
&& !criteria->urgent
&& !criteria->workspace
&& !criteria->pid;
&& !criteria->pid
&& !criteria->sandbox_engine
&& !criteria->sandbox_app_id
&& !criteria->sandbox_instance_id;
}

// The error pointer is used for parsing functions, and saves having to pass it
Expand Down Expand Up @@ -98,6 +101,9 @@ void criteria_destroy(struct criteria *criteria) {
#endif
pattern_destroy(criteria->con_mark);
pattern_destroy(criteria->workspace);
pattern_destroy(criteria->sandbox_engine);
pattern_destroy(criteria->sandbox_app_id);
pattern_destroy(criteria->sandbox_instance_id);
free(criteria->target);
free(criteria->cmdlist);
free(criteria->raw);
Expand Down Expand Up @@ -248,6 +254,66 @@ static bool criteria_matches_view(struct criteria *criteria,
}
}

if (criteria->sandbox_engine) {
const char *sandbox_engine = view_get_sandbox_engine(view);
if (!sandbox_engine) {
return false;
}

switch (criteria->sandbox_engine->match_type) {
case PATTERN_FOCUSED:
if (focused && lenient_strcmp(sandbox_engine, view_get_sandbox_engine(focused))) {
return false;
}
break;
case PATTERN_PCRE2:
if (regex_cmp(sandbox_engine, criteria->sandbox_engine->regex) < 0) {
return false;
}
break;
}
}

if (criteria->sandbox_app_id) {
const char *sandbox_app_id = view_get_sandbox_app_id(view);
if (!sandbox_app_id) {
return false;
}

switch (criteria->sandbox_app_id->match_type) {
case PATTERN_FOCUSED:
if (focused && lenient_strcmp(sandbox_app_id, view_get_sandbox_app_id(focused))) {
return false;
}
break;
case PATTERN_PCRE2:
if (regex_cmp(sandbox_app_id, criteria->sandbox_app_id->regex) < 0) {
return false;
}
break;
}
}

if (criteria->sandbox_instance_id) {
const char *sandbox_instance_id = view_get_sandbox_instance_id(view);
if (!sandbox_instance_id) {
return false;
}

switch (criteria->sandbox_instance_id->match_type) {
case PATTERN_FOCUSED:
if (focused && lenient_strcmp(sandbox_instance_id, view_get_sandbox_instance_id(focused))) {
return false;
}
break;
case PATTERN_PCRE2:
if (regex_cmp(sandbox_instance_id, criteria->sandbox_instance_id->regex) < 0) {
return false;
}
break;
}
}

if (!criteria_matches_container(criteria, view->container)) {
return false;
}
Expand Down Expand Up @@ -475,6 +541,9 @@ enum criteria_token {
T_URGENT,
T_WORKSPACE,
T_PID,
T_SANDBOX_ENGINE,
T_SANDBOX_APP_ID,
T_SANDBOX_INSTANCE_ID,

T_INVALID,
};
Expand Down Expand Up @@ -514,6 +583,12 @@ static enum criteria_token token_from_name(char *name) {
return T_FLOATING;
} else if (strcmp(name, "pid") == 0) {
return T_PID;
} else if (strcmp(name, "sandbox_engine") == 0) {
return T_SANDBOX_ENGINE;
} else if (strcmp(name, "sandbox_app_id") == 0) {
return T_SANDBOX_APP_ID;
} else if (strcmp(name, "sandbox_instance_id") == 0) {
return T_SANDBOX_INSTANCE_ID;
}
return T_INVALID;
}
Expand Down Expand Up @@ -617,6 +692,15 @@ static bool parse_token(struct criteria *criteria, char *name, char *value) {
error = strdup("The value for 'pid' should be numeric");
}
break;
case T_SANDBOX_ENGINE:
pattern_create(&criteria->sandbox_engine, value);
break;
case T_SANDBOX_APP_ID:
pattern_create(&criteria->sandbox_app_id, value);
break;
case T_SANDBOX_INSTANCE_ID:
pattern_create(&criteria->sandbox_instance_id, value);
break;
case T_INVALID:
break;
}
Expand Down
27 changes: 27 additions & 0 deletions sway/desktop/xdg_shell.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#include <stdbool.h>
#include <stdlib.h>
#include <wayland-server-core.h>
#include <wlr/types/wlr_security_context_v1.h>
#include <wlr/types/wlr_xdg_shell.h>
#include <wlr/util/edges.h>
#include "log.h"
Expand All @@ -12,6 +13,7 @@
#include "sway/input/input-manager.h"
#include "sway/input/seat.h"
#include "sway/output.h"
#include "sway/server.h"
#include "sway/tree/arrange.h"
#include "sway/tree/container.h"
#include "sway/tree/view.h"
Expand Down Expand Up @@ -139,6 +141,16 @@ static struct sway_xdg_shell_view *xdg_shell_view_from_view(
return (struct sway_xdg_shell_view *)view;
}

static const struct wlr_security_context_v1_state *security_context_from_view(
struct sway_view *view) {
const struct wl_client *client =
wl_resource_get_client(view->surface->resource);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems like this has nothing xdg-shell specific - do we really need to get through the view->impl abstraction, or can we just put this logic in generic view code?

const struct wlr_security_context_v1_state *security_context =
wlr_security_context_manager_v1_lookup_client(
server.security_context_manager_v1, client);
return security_context;
}

static void get_constraints(struct sway_view *view, double *min_width,
double *max_width, double *min_height, double *max_height) {
struct wlr_xdg_toplevel_state *state =
Expand All @@ -159,6 +171,21 @@ static const char *get_string_prop(struct sway_view *view,
return view->wlr_xdg_toplevel->title;
case VIEW_PROP_APP_ID:
return view->wlr_xdg_toplevel->app_id;
case VIEW_PROP_SANDBOX_ENGINE: {
const struct wlr_security_context_v1_state *security_context =
security_context_from_view(view);
return security_context ? security_context->sandbox_engine : NULL;
}
case VIEW_PROP_SANDBOX_APP_ID: {
const struct wlr_security_context_v1_state *security_context =
security_context_from_view(view);
return security_context ? security_context->app_id : NULL;
}
case VIEW_PROP_SANDBOX_INSTANCE_ID: {
const struct wlr_security_context_v1_state *security_context =
security_context_from_view(view);
return security_context ? security_context->instance_id : NULL;
}
default:
return NULL;
}
Expand Down
12 changes: 12 additions & 0 deletions sway/ipc-json.c
Original file line number Diff line number Diff line change
Expand Up @@ -602,6 +602,18 @@ static void ipc_json_describe_view(struct sway_container *c, json_object *object
json_object_object_add(object, "inhibit_idle",
json_object_new_boolean(view_inhibit_idle(c->view)));

const char *sandbox_engine = view_get_sandbox_engine(c->view);
json_object_object_add(object, "sandbox_engine",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems like we should be adding these new props to the IPC man page as well.

sandbox_engine ? json_object_new_string(sandbox_engine) : NULL);

const char *sandbox_app_id = view_get_sandbox_app_id(c->view);
json_object_object_add(object, "sandbox_app_id",
sandbox_app_id ? json_object_new_string(sandbox_app_id) : NULL);

const char *sandbox_instance_id = view_get_sandbox_instance_id(c->view);
json_object_object_add(object, "sandbox_instance_id",
sandbox_instance_id ? json_object_new_string(sandbox_instance_id) : NULL);

json_object *idle_inhibitors = json_object_new_object();

struct sway_idle_inhibitor_v1 *user_inhibitor =
Expand Down
10 changes: 10 additions & 0 deletions sway/sway-ipc.7.scd
Original file line number Diff line number Diff line change
Expand Up @@ -403,6 +403,16 @@ node and will have the following properties:
: (Only views) An object containing the state of the _application_ and _user_ idle inhibitors.
_application_ can be _enabled_ or _none_.
_user_ can be _focus_, _fullscreen_, _open_, _visible_ or _none_.
|- sandbox_engine
: string
: (Only views) The associated sandbox engine (or _null_)
|- sandbox_app_id
: string
: (Only views) The app ID provided by the associated sandbox engine (or _null_)
|- sandbox_instance_id
: string
: (Only views) The instance ID provided by the associated sandbox engine (or
_null_)
|- window
: integer
: (Only xwayland views) The X11 window ID for the xwayland view
Expand Down
45 changes: 39 additions & 6 deletions sway/sway.5.scd
Original file line number Diff line number Diff line change
Expand Up @@ -372,12 +372,29 @@ set|plus|minus|toggle <amount>
*title_format* <format>
Sets the format of window titles. The following placeholders may be used:

%title - The title supplied by the window ++
%app_id - The wayland app ID (applicable to wayland windows only) ++
%class - The X11 classname (applicable to xwayland windows only) ++
%instance - The X11 instance (applicable to xwayland windows only) ++
%shell - The protocol the window is using (typically xwayland or
xdg_shell)
*%title*
The title supplied by the window

*%app_id*
The wayland app ID (applicable to wayland windows only)

*%class*
The X11 classname (applicable to xwayland windows only)

*%instance*
The X11 instance (applicable to xwayland windows only)

*%shell*
The protocol the window is using (typically xwayland or xdg_shell)

*%sandbox_engine*
The associated sandbox engine

*%sandbox_app_id*
The app ID provided by the associated sandbox engine

*%sandbox_instance_id*
The instance ID provided by the associated sandbox engine

This command is typically used with *for_window* criteria. For example:

Expand Down Expand Up @@ -1058,6 +1075,22 @@ The following attributes may be matched with:
expression. If the value is \_\_focused\_\_, then all the views on the
currently focused workspace matches.

*sandbox_engine*
Compare against the associated sandbox engine. Can be a regular expression.
If the value is \_\_focused\_\_, then the sandbox engine must be the same as
that of the currently focused window.

*sandbox_app_id*
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm kind of wondering whether we should expose this, or whether we should always prefer the sandbox-provided app ID over the one provided by the sandboxed client.

(IIRC GNOME allows org.libreoffice.Writer if the sandbox app ID is org.libreoffice.)

Compare against the app ID provided by the associated sandbox engine. Can be
a regular expression. If the value is \_\_focused\_\_, then the sandbox app
ID must be the same as that of the currently focused window.

*sandbox_instance_id*
Compare against the instance ID provided by the associated sandbox engine.
Can be a regular expression. If the value is \_\_focused\_\_, then the
sandbox instance ID must be the same as that of the currently focused
window.

# SEE ALSO

*sway*(1) *sway-input*(5) *sway-output*(5) *sway-bar*(5) *sway-ipc*(7)
9 changes: 9 additions & 0 deletions sway/tree/container.c
Original file line number Diff line number Diff line change
Expand Up @@ -716,6 +716,15 @@ size_t parse_title_format(struct sway_container *container, char *buffer) {
} else if (has_prefix(next, "%shell")) {
len += append_prop(buffer, view_get_shell(container->view));
format += strlen("%shell");
} else if (has_prefix(next, "%sandbox_engine")) {
len += append_prop(buffer, view_get_sandbox_engine(container->view));
format += strlen("%sandbox_engine");
} else if (has_prefix(next, "%sandbox_app_id")) {
len += append_prop(buffer, view_get_sandbox_app_id(container->view));
format += strlen("%sandbox_app_id");
} else if (has_prefix(next, "%sandbox_instance_id")) {
len += append_prop(buffer, view_get_sandbox_instance_id(container->view));
format += strlen("%sandbox_instance_id");
} else {
lenient_strcat(buffer, "%");
++format;
Expand Down
21 changes: 21 additions & 0 deletions sway/tree/view.c
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,27 @@ uint32_t view_get_window_type(struct sway_view *view) {
return 0;
}

const char *view_get_sandbox_engine(struct sway_view *view) {
if (view->impl->get_string_prop) {
return view->impl->get_string_prop(view, VIEW_PROP_SANDBOX_ENGINE);
}
return NULL;
}

const char *view_get_sandbox_app_id(struct sway_view *view) {
if (view->impl->get_string_prop) {
return view->impl->get_string_prop(view, VIEW_PROP_SANDBOX_APP_ID);
}
return NULL;
}

const char *view_get_sandbox_instance_id(struct sway_view *view) {
if (view->impl->get_string_prop) {
return view->impl->get_string_prop(view, VIEW_PROP_SANDBOX_INSTANCE_ID);
}
return NULL;
}

const char *view_get_shell(struct sway_view *view) {
switch(view->type) {
case SWAY_VIEW_XDG_SHELL:
Expand Down
12 changes: 12 additions & 0 deletions swaymsg/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -330,6 +330,9 @@ static void pretty_print_tree(json_object *obj, int indent) {
const char *instance = json_object_get_string(json_object_object_get(window_props_obj, "instance"));
const char *class = json_object_get_string(json_object_object_get(window_props_obj, "class"));
int x11_id = json_object_get_int(json_object_object_get(obj, "window"));
const char *sandbox_engine = json_object_get_string(json_object_object_get(obj, "sandbox_engine"));
const char *sandbox_app_id = json_object_get_string(json_object_object_get(obj, "sandbox_app_id"));
const char *sandbox_instance_id = json_object_get_string(json_object_object_get(obj, "sandbox_instance_id"));

printf(" (%s, pid: %d", shell, pid);
if (app_id != NULL) {
Expand All @@ -344,6 +347,15 @@ static void pretty_print_tree(json_object *obj, int indent) {
if (x11_id != 0) {
printf(", X11 window: 0x%X", x11_id);
}
if (sandbox_engine != NULL) {
printf(", sandbox_engine: \"%s\"", sandbox_engine);
}
if (sandbox_app_id != NULL) {
printf(", sandbox_app_id: \"%s\"", sandbox_app_id);
}
if (sandbox_instance_id != NULL) {
printf(", sandbox_instance_id: \"%s\"", sandbox_instance_id);
}
printf(")");
}

Expand Down