Skip to content
Draft
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
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -1957,7 +1957,7 @@ and the [FAQ](https://github.com/emersion/xdg-desktop-portal-wlr/wiki/FAQ).
desktop bar.

See `include/ipc.h` for `IPC_GET_SCROLLER`, `IPC_EVENT_SCROLLER`, `IPC_EVENT_LUA`,
`IPG_GET_TRAILS` and `IPC_EVENT_TRAILS`.
`IPC_GET_TRAILS`, `IPC_EVENT_TRAILS` and `IPC_MINT_ACTIVATION_TOKEN`.

You can get data for mode/mode modifiers, overview and scale mode as well as
trails and whether a view has an active trailmark.
Expand Down
1 change: 1 addition & 0 deletions completions/bash/scrollmsg
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ _scrollmsg()
'get_config'
'send_tick'
'subscribe'
'mint_activation_token'
)

short=(
Expand Down
1 change: 1 addition & 0 deletions completions/fish/scrollmsg.fish
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,4 @@ complete -c scrollmsg -s t -l type -fra 'get_config' --description "Gets a JSON-
complete -c scrollmsg -s t -l type -fra 'get_seats' --description "Gets a JSON-encoded list of all seats, its properties and all assigned devices."
complete -c scrollmsg -s t -l type -fra 'send_tick' --description "Sends a tick event to all subscribed clients."
complete -c scrollmsg -s t -l type -fra 'subscribe' --description "Subscribe to a list of event types."
complete -c scrollmsg -s t -l type -fra 'mint_activation_token' --description "Mint a new XDG activation token."
1 change: 1 addition & 0 deletions completions/zsh/_scrollmsg
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ types=(
'get_config'
'send_tick'
'subscribe'
'mint_activation_token'
)

_arguments -s \
Expand Down
27 changes: 14 additions & 13 deletions include/ipc.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ enum ipc_command_type {
// sway-specific command types
IPC_GET_INPUTS = 100,
IPC_GET_SEATS = 101,
IPC_MINT_ACTIVATION_TOKEN = 102,

// scroll-specific command types
IPC_GET_SCROLLER = 120,
Expand All @@ -30,23 +31,23 @@ enum ipc_command_type {
IPC_GET_BINDINGS = 123,

// Events sent from sway to clients. Events have the highest bits set.
IPC_EVENT_WORKSPACE = ((1<<31) | 0),
IPC_EVENT_OUTPUT = ((1<<31) | 1),
IPC_EVENT_MODE = ((1<<31) | 2),
IPC_EVENT_WINDOW = ((1<<31) | 3),
IPC_EVENT_BARCONFIG_UPDATE = ((1<<31) | 4),
IPC_EVENT_BINDING = ((1<<31) | 5),
IPC_EVENT_SHUTDOWN = ((1<<31) | 6),
IPC_EVENT_TICK = ((1<<31) | 7),
IPC_EVENT_WORKSPACE = ((1 << 31) | 0),
IPC_EVENT_OUTPUT = ((1 << 31) | 1),
IPC_EVENT_MODE = ((1 << 31) | 2),
IPC_EVENT_WINDOW = ((1 << 31) | 3),
IPC_EVENT_BARCONFIG_UPDATE = ((1 << 31) | 4),
IPC_EVENT_BINDING = ((1 << 31) | 5),
IPC_EVENT_SHUTDOWN = ((1 << 31) | 6),
IPC_EVENT_TICK = ((1 << 31) | 7),

// sway-specific event types
IPC_EVENT_BAR_STATE_UPDATE = ((1<<31) | 20),
IPC_EVENT_INPUT = ((1<<31) | 21),
IPC_EVENT_BAR_STATE_UPDATE = ((1 << 31) | 20),
IPC_EVENT_INPUT = ((1 << 31) | 21),

// scroll-specific event types
IPC_EVENT_LUA = ((1<<31) | 29),
IPC_EVENT_SCROLLER = ((1<<31) | 30),
IPC_EVENT_TRAILS = ((1<<31) | 31),
IPC_EVENT_LUA = ((1 << 31) | 29),
IPC_EVENT_SCROLLER = ((1 << 31) | 30),
IPC_EVENT_TRAILS = ((1 << 31) | 31),
};

#endif
3 changes: 2 additions & 1 deletion include/sway/commands.h
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ char *cmd_results_to_json(list_t *res_list);
* Handlers shared by exec and exec_always.
*/
sway_cmd cmd_exec_validate;
sway_cmd cmd_exec_process;
struct cmd_results *cmd_exec_process(int argc, char **argv, const char *cmdlist);

sway_cmd cmd_align;
sway_cmd cmd_align_reset_auto;
Expand Down Expand Up @@ -149,6 +149,7 @@ sway_cmd cmd_focus_follows_mouse;
sway_cmd cmd_focus_on_window_activation;
sway_cmd cmd_focus_wrapping;
sway_cmd cmd_font;
sway_cmd cmd_for_exec_window;
sway_cmd cmd_for_window;
sway_cmd cmd_force_display_urgency_hint;
sway_cmd cmd_force_focus_wrapping;
Expand Down
1 change: 1 addition & 0 deletions include/sway/criteria.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ struct criteria {
struct pattern *sandbox_app_id;
struct pattern *sandbox_instance_id;
struct pattern *tag;
char *initial_activation_token;
};

bool criteria_is_empty(struct criteria *criteria);
Expand Down
3 changes: 3 additions & 0 deletions include/sway/desktop/launcher.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,13 @@ struct launcher_ctx {
struct wl_listener node_destroy;

struct wl_list link; // sway_server::pending_launcher_ctxs
char *cmdlist;
};

struct launcher_ctx *launcher_ctx_find_pid(pid_t pid);

struct launcher_ctx *launcher_ctx_find_token(const char *token_name);

struct sway_workspace *launcher_ctx_get_workspace(struct launcher_ctx *ctx);

void launcher_ctx_consume(struct launcher_ctx *ctx);
Expand Down
2 changes: 2 additions & 0 deletions include/sway/tree/view.h
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,8 @@ struct sway_view {

pid_t pid;
struct launcher_ctx *ctx;
char *exec_cmdlist;
char *initial_activation_token;

// The size the view would want to be if it weren't tiled.
// Used when changing a view from tiled to floating.
Expand Down
1 change: 1 addition & 0 deletions protocols/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ protocols = [
wl_protocol_dir / 'stable/xdg-shell/xdg-shell.xml',
wl_protocol_dir / 'staging/cursor-shape/cursor-shape-v1.xml',
wl_protocol_dir / 'unstable/xdg-output/xdg-output-unstable-v1.xml',
wl_protocol_dir / 'staging/xdg-activation/xdg-activation-v1.xml',
'wlr-layer-shell-unstable-v1.xml',
'wlr-output-power-management-unstable-v1.xml',
]
Expand Down
21 changes: 9 additions & 12 deletions sway/commands.c
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ static const struct cmd_handler handlers[] = {
{ "focus_on_window_activation", cmd_focus_on_window_activation },
{ "focus_wrapping", cmd_focus_wrapping },
{ "font", cmd_font },
{ "for_exec_window", cmd_for_exec_window },
{ "for_window", cmd_for_window },
{ "force_display_urgency_hint", cmd_force_display_urgency_hint },
{ "force_focus_wrapping", cmd_force_focus_wrapping },
Expand Down Expand Up @@ -329,9 +330,8 @@ list_t *execute_command(char *_exec, struct sway_seat *seat,
//TODO better handling of argv
int argc;
char **argv = split_args(cmd, &argc);
if (strcmp(argv[0], "exec") != 0 &&
strcmp(argv[0], "exec_always") != 0 &&
strcmp(argv[0], "mode") != 0) {
if (strcmp(argv[0], "exec") != 0 && strcmp(argv[0], "exec_always") != 0 &&
strcmp(argv[0], "for_exec_window") != 0 && strcmp(argv[0], "mode") != 0) {
for (int i = 1; i < argc; ++i) {
if (*argv[i] == '\"' || *argv[i] == '\'') {
strip_quotes(argv[i]);
Expand Down Expand Up @@ -476,15 +476,12 @@ struct cmd_results *config_command(char *exec, char **new_block) {

// Strip quotes and unescape the string
for (int i = handler->handle == cmd_set ? 2 : 1; i < argc; ++i) {
if (handler->handle != cmd_exec && handler->handle != cmd_exec_always
&& handler->handle != cmd_mode
&& handler->handle != cmd_bindsym
&& handler->handle != cmd_bindcode
&& handler->handle != cmd_bindswitch
&& handler->handle != cmd_bindgesture
&& handler->handle != cmd_set
&& handler->handle != cmd_for_window
&& (*argv[i] == '\"' || *argv[i] == '\'')) {
if (handler->handle != cmd_exec && handler->handle != cmd_exec_always &&
handler->handle != cmd_mode && handler->handle != cmd_bindsym &&
handler->handle != cmd_bindcode && handler->handle != cmd_bindswitch &&
handler->handle != cmd_bindgesture && handler->handle != cmd_set &&
handler->handle != cmd_for_window && handler->handle != cmd_for_exec_window &&
(*argv[i] == '\"' || *argv[i] == '\'')) {
strip_quotes(argv[i]);
}
unescape_string(argv[i]);
Expand Down
2 changes: 1 addition & 1 deletion sway/commands/exec.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,5 @@ struct cmd_results *cmd_exec(int argc, char **argv) {
free(args);
return cmd_results_new(CMD_SUCCESS, NULL);
}
return cmd_exec_process(argc, argv);
return cmd_exec_process(argc, argv, NULL);
}
8 changes: 6 additions & 2 deletions sway/commands/exec_always.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ struct cmd_results *cmd_exec_validate(int argc, char **argv) {
return error;
}

struct cmd_results *cmd_exec_process(int argc, char **argv) {
struct cmd_results *cmd_exec_process(int argc, char **argv, const char *cmdlist) {
struct cmd_results *error = NULL;
char *cmd = NULL;
bool no_startup_id = false;
Expand All @@ -47,6 +47,10 @@ struct cmd_results *cmd_exec_process(int argc, char **argv) {
sway_log(SWAY_DEBUG, "Executing %s", cmd);

struct launcher_ctx *ctx = launcher_ctx_create_internal();
if (ctx && cmdlist) {
ctx->cmdlist = strdup(cmdlist);
sway_log(SWAY_DEBUG, "Recorded cmdlist '%s' to ctx %p", ctx->cmdlist, ctx);
}

// Fork process
pid_t child = fork();
Expand Down Expand Up @@ -85,5 +89,5 @@ struct cmd_results *cmd_exec_always(int argc, char **argv) {
if ((error = cmd_exec_validate(argc, argv))) {
return error;
}
return cmd_exec_process(argc, argv);
return cmd_exec_process(argc, argv, NULL);
}
30 changes: 30 additions & 0 deletions sway/commands/for_exec_window.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#include <string.h>
#include "sway/commands.h"
#include "sway/config.h"
#include "log.h"
#include "stringop.h"

struct cmd_results *cmd_for_exec_window(int argc, char **argv) {
struct cmd_results *error = NULL;
if ((error = checkarg(argc, "for_exec_window", EXPECTED_AT_LEAST, 2))) {
return error;
}
if (!config->active || config->validating) {
return cmd_results_new(CMD_DEFER, NULL);
}
if (config->reloading) {
char *args = join_args(argv, argc);
sway_log(SWAY_DEBUG, "Ignoring 'for_exec_window %s' due to reload", args);
free(args);
return cmd_results_new(CMD_SUCCESS, NULL);
}

char *cmdlist = strdup(argv[0]);
strip_quotes(cmdlist);
strip_whitespace(cmdlist);
sway_log(SWAY_DEBUG, "for_exec_window: cmdlist='%s'", cmdlist);

struct cmd_results *res = cmd_exec_process(argc - 1, argv + 1, cmdlist);
free(cmdlist);
return res;
}
29 changes: 29 additions & 0 deletions sway/commands/for_window.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include "list.h"
#include "log.h"
#include "stringop.h"
#include "sway/desktop/launcher.h"

struct cmd_results *cmd_for_window(int argc, char **argv) {
struct cmd_results *error = NULL;
Expand All @@ -22,6 +23,34 @@ struct cmd_results *cmd_for_window(int argc, char **argv) {
criteria->type = CT_COMMAND;
criteria->cmdlist = join_args(argv + 1, argc - 1);

if (criteria->initial_activation_token) {
char *temp_token = criteria->initial_activation_token;
criteria->initial_activation_token = NULL;
bool has_others = !criteria_is_empty(criteria);
criteria->initial_activation_token = temp_token;

if (has_others) {
criteria_destroy(criteria);
return cmd_results_new(CMD_INVALID,
"initial_activation_token criteria cannot be combined with other criteria");
}

struct launcher_ctx *ctx = launcher_ctx_find_token(criteria->initial_activation_token);
if (ctx) {
free(ctx->cmdlist);
ctx->cmdlist = strdup(criteria->cmdlist);
sway_log(SWAY_DEBUG, "Bound commands '%s' to activation token '%s'", ctx->cmdlist,
criteria->initial_activation_token);
} else {
criteria_destroy(criteria);
return cmd_results_new(
CMD_INVALID, "Activation token '%s' not found or expired", temp_token);
}

criteria_destroy(criteria);
return cmd_results_new(CMD_SUCCESS, NULL);
}

// Check if it already exists
if (criteria_already_exists(criteria)) {
sway_log(SWAY_DEBUG, "for_window already exists: '%s' -> '%s'",
Expand Down
44 changes: 24 additions & 20 deletions sway/criteria.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,28 +18,16 @@
#include "config.h"

bool criteria_is_empty(struct criteria *criteria) {
return !criteria->title
&& !criteria->shell
&& !criteria->all
&& !criteria->app_id
&& !criteria->con_mark
&& !criteria->con_id
return !criteria->title && !criteria->shell && !criteria->all && !criteria->app_id &&
!criteria->con_mark && !criteria->con_id
#if WLR_HAS_XWAYLAND
&& !criteria->class
&& !criteria->id
&& !criteria->instance
&& !criteria->window_role
&& criteria->window_type == ATOM_LAST
&& !criteria->class && !criteria->id && !criteria->instance && !criteria->window_role &&
criteria->window_type == ATOM_LAST
#endif
&& !criteria->floating
&& !criteria->tiling
&& !criteria->urgent
&& !criteria->workspace
&& !criteria->pid
&& !criteria->sandbox_engine
&& !criteria->sandbox_app_id
&& !criteria->sandbox_instance_id
&& !criteria->tag;
&& !criteria->floating && !criteria->tiling && !criteria->urgent &&
!criteria->workspace && !criteria->pid && !criteria->sandbox_engine &&
!criteria->sandbox_app_id && !criteria->sandbox_instance_id && !criteria->tag &&
!criteria->initial_activation_token;
}

// The error pointer is used for parsing functions, and saves having to pass it
Expand Down Expand Up @@ -123,6 +111,7 @@ void criteria_destroy(struct criteria *criteria) {
pattern_destroy(criteria->tag);
free(criteria->target);
free(criteria->cmdlist);
free(criteria->initial_activation_token);
free(criteria->raw);
free(criteria);
}
Expand Down Expand Up @@ -355,6 +344,13 @@ bool criteria_matches_view(struct criteria *criteria,
}
}

if (criteria->initial_activation_token) {
const char *token = view->initial_activation_token;
if (!token || strcmp(token, criteria->initial_activation_token) != 0) {
return false;
}
}

if (!criteria_matches_container(criteria, view->container)) {
return false;
}
Expand Down Expand Up @@ -598,6 +594,7 @@ enum criteria_token {
T_SANDBOX_APP_ID,
T_SANDBOX_INSTANCE_ID,
T_TAG,
T_INITIAL_ACTIVATION_TOKEN,

T_INVALID,
};
Expand Down Expand Up @@ -645,6 +642,8 @@ static enum criteria_token token_from_name(char *name) {
return T_SANDBOX_INSTANCE_ID;
} else if (strcmp(name, "tag") == 0) {
return T_TAG;
} else if (strcmp(name, "initial_activation_token") == 0) {
return T_INITIAL_ACTIVATION_TOKEN;
}
return T_INVALID;
}
Expand Down Expand Up @@ -759,6 +758,9 @@ static bool parse_token(struct criteria *criteria, char *name, char *value) {
case T_TAG:
pattern_create(&criteria->tag, value);
break;
case T_INITIAL_ACTIVATION_TOKEN:
criteria->initial_activation_token = strdup(value);
break;
case T_INVALID:
break;
}
Expand Down Expand Up @@ -965,6 +967,8 @@ struct criteria *criteria_duplicate(struct criteria *criteria) {
dup->sandbox_app_id = pattern_duplicate(criteria->sandbox_app_id);
dup->sandbox_instance_id = pattern_duplicate(criteria->sandbox_instance_id);
dup->tag = pattern_duplicate(criteria->tag);
dup->initial_activation_token =
criteria->initial_activation_token ? strdup(criteria->initial_activation_token) : NULL;

return dup;
}
Loading