diff --git a/include/sway/commands.h b/include/sway/commands.h index bbbdfc80e9..1c60d10a0c 100644 --- a/include/sway/commands.h +++ b/include/sway/commands.h @@ -290,6 +290,11 @@ sway_cmd seat_cmd_keyboard_grouping; sway_cmd seat_cmd_pointer_constraint; sway_cmd seat_cmd_xcursor_theme; +sway_cmd xwayland_cmd_enable; +sway_cmd xwayland_cmd_disable; +sway_cmd xwayland_cmd_force; +sway_cmd xwayland_cmd_scale; + sway_cmd cmd_ipc_cmd; sway_cmd cmd_ipc_events; sway_cmd cmd_ipc_event_cmd; diff --git a/include/sway/config.h b/include/sway/config.h index 0a2661dd81..95528d5708 100644 --- a/include/sway/config.h +++ b/include/sway/config.h @@ -513,6 +513,7 @@ struct sway_config { enum sway_fowa focus_on_window_activation; enum sway_popup_during_fullscreen popup_during_fullscreen; enum xwayland_mode xwayland; + int32_t xwayland_scale; // swaybg char *swaybg_command; diff --git a/sway/commands.c b/sway/commands.c index 6a56ff5a9d..c00be6eb82 100644 --- a/sway/commands.c +++ b/sway/commands.c @@ -97,6 +97,7 @@ static struct cmd_handler handlers[] = { { "unbindsym", cmd_unbindsym }, { "workspace", cmd_workspace }, { "workspace_auto_back_and_forth", cmd_ws_auto_back_and_forth }, + { "xwayland", cmd_xwayland }, }; /* Config-time only commands. Keep alphabetized */ @@ -105,7 +106,6 @@ static struct cmd_handler config_handlers[] = { { "swaybg_command", cmd_swaybg_command }, { "swaynag_command", cmd_swaynag_command }, { "workspace_layout", cmd_workspace_layout }, - { "xwayland", cmd_xwayland }, }; /* Runtime-only commands. Keep alphabetized */ diff --git a/sway/commands/xwayland.c b/sway/commands/xwayland.c index 6ca2692317..1c4218c444 100644 --- a/sway/commands/xwayland.c +++ b/sway/commands/xwayland.c @@ -4,27 +4,39 @@ #include "sway/server.h" #include "util.h" -struct cmd_results *cmd_xwayland(int argc, char **argv) { - struct cmd_results *error = NULL; - if ((error = checkarg(argc, "xwayland", EXPECTED_EQUAL_TO, 1))) { - return error; - } +// must be in order for the bsearch +static struct cmd_handler xwayland_handlers[] = { + { "enable", xwayland_cmd_enable }, + { "disable", xwayland_cmd_disable }, + { "force", xwayland_cmd_force }, + { "scale", xwayland_cmd_scale }, +}; +struct cmd_results *cmd_xwayland(int argc, char **argv) { #ifdef HAVE_XWAYLAND - enum xwayland_mode xwayland; - if (strcmp(argv[0], "force") == 0) { - xwayland = XWAYLAND_MODE_IMMEDIATE; - } else if (parse_boolean(argv[0], true)) { - xwayland = XWAYLAND_MODE_LAZY; - } else { - xwayland = XWAYLAND_MODE_DISABLED; - } + struct cmd_results *error; + while (argc > 0) { + config->handler_context.leftovers.argc = 0; + config->handler_context.leftovers.argv = NULL; - if (config->reloading && config->xwayland != xwayland) { - return cmd_results_new(CMD_FAILURE, - "xwayland can only be enabled/disabled at launch"); + if (find_handler(*argv, xwayland_handlers, sizeof(xwayland_handlers))) { + error = config_subcommand(argv, argc, xwayland_handlers, + sizeof(xwayland_handlers)); + } else { + error = cmd_results_new(CMD_INVALID, + "Invalid output subcommand: %s.", *argv); + } + + if (error != NULL) { + return error; + } + + argc = config->handler_context.leftovers.argc; + argv = config->handler_context.leftovers.argv; } - config->xwayland = xwayland; + + config->handler_context.leftovers.argc = 0; + config->handler_context.leftovers.argv = NULL; #else sway_log(SWAY_INFO, "Ignoring `xwayland` command, " "sway hasn't been built with Xwayland support"); diff --git a/sway/commands/xwayland/disable.c b/sway/commands/xwayland/disable.c new file mode 100644 index 0000000000..e6efe3edd3 --- /dev/null +++ b/sway/commands/xwayland/disable.c @@ -0,0 +1,15 @@ +#include "sway/commands.h" +#include "sway/config.h" + +struct cmd_results *xwayland_cmd_disable(int argc, char **argv) { + if (config->reloading && config->xwayland != XWAYLAND_MODE_DISABLED) { + return cmd_results_new(CMD_FAILURE, + "xwayland can only be enabled/disabled at launch"); + } + + config->xwayland = XWAYLAND_MODE_DISABLED; + + config->handler_context.leftovers.argc = argc; + config->handler_context.leftovers.argv = argv; + return NULL; +} diff --git a/sway/commands/xwayland/enable.c b/sway/commands/xwayland/enable.c new file mode 100644 index 0000000000..8dc47434a2 --- /dev/null +++ b/sway/commands/xwayland/enable.c @@ -0,0 +1,15 @@ +#include "sway/commands.h" +#include "sway/config.h" + +struct cmd_results *xwayland_cmd_enable(int argc, char **argv) { + if (config->reloading && config->xwayland != XWAYLAND_MODE_LAZY) { + return cmd_results_new(CMD_FAILURE, + "xwayland can only be enabled/disabled at launch"); + } + config->xwayland = XWAYLAND_MODE_LAZY; + + config->handler_context.leftovers.argc = argc; + config->handler_context.leftovers.argv = argv; + return NULL; +} + diff --git a/sway/commands/xwayland/force.c b/sway/commands/xwayland/force.c new file mode 100644 index 0000000000..a9374a8025 --- /dev/null +++ b/sway/commands/xwayland/force.c @@ -0,0 +1,15 @@ +#include "sway/commands.h" +#include "sway/config.h" + +struct cmd_results *xwayland_cmd_force(int argc, char **argv) { + if (config->reloading && config->xwayland != XWAYLAND_MODE_IMMEDIATE) { + return cmd_results_new(CMD_FAILURE, + "xwayland can only be enabled/disabled at launch"); + } + config->xwayland = XWAYLAND_MODE_IMMEDIATE; + + config->handler_context.leftovers.argc = argc; + config->handler_context.leftovers.argv = argv; + return NULL; +} + diff --git a/sway/commands/xwayland/scale.c b/sway/commands/xwayland/scale.c new file mode 100644 index 0000000000..f1b82a040b --- /dev/null +++ b/sway/commands/xwayland/scale.c @@ -0,0 +1,31 @@ +#include +#include "sway/commands.h" +#include "sway/config.h" +#include "sway/server.h" +#include "log.h" + +struct cmd_results *xwayland_cmd_scale(int argc, char **argv) { + if (!argc) { + return cmd_results_new(CMD_INVALID, "Missing scale argument."); + } + + char *end; + int32_t scale = strtol(*argv, &end, 10); + if (*end) { + return cmd_results_new(CMD_INVALID, "Invalid scale."); + } + if(scale < 1) { + return cmd_results_new(CMD_INVALID, "Invalid scale: must be 1 or higher"); + } + + config->xwayland_scale = scale; + + if(server.xwayland.wlr_xwayland != NULL) { + wlr_xwayland_set_scale(server.xwayland.wlr_xwayland, scale); + } + + config->handler_context.leftovers.argc = argc - 1; + config->handler_context.leftovers.argv = argv + 1; + + return NULL; +} diff --git a/sway/config.c b/sway/config.c index c20625cfc3..4392c6059c 100644 --- a/sway/config.c +++ b/sway/config.c @@ -243,6 +243,7 @@ static void config_defaults(struct sway_config *config) { config->urgent_timeout = 500; config->popup_during_fullscreen = POPUP_SMART; config->xwayland = XWAYLAND_MODE_LAZY; + config->xwayland_scale = 1; config->titlebar_border_thickness = 1; config->titlebar_h_padding = 5; diff --git a/sway/desktop/xwayland.c b/sway/desktop/xwayland.c index 2554d0e468..10954413af 100644 --- a/sway/desktop/xwayland.c +++ b/sway/desktop/xwayland.c @@ -680,6 +680,8 @@ void handle_xwayland_ready(struct wl_listener *listener, void *data) { wl_container_of(listener, server, xwayland_ready); struct sway_xwayland *xwayland = &server->xwayland; + wlr_xwayland_set_scale(xwayland->wlr_xwayland, config->xwayland_scale); + xcb_connection_t *xcb_conn = xcb_connect(NULL, NULL); int err = xcb_connection_has_error(xcb_conn); if (err) { diff --git a/sway/meson.build b/sway/meson.build index 6fdc4a7d54..8f21ec555b 100644 --- a/sway/meson.build +++ b/sway/meson.build @@ -189,6 +189,11 @@ sway_sources = files( 'commands/output/toggle.c', 'commands/output/transform.c', + 'commands/xwayland/enable.c', + 'commands/xwayland/disable.c', + 'commands/xwayland/force.c', + 'commands/xwayland/scale.c', + 'tree/arrange.c', 'tree/container.c', 'tree/node.c',