mirror of
https://github.com/swaywm/sway.git
synced 2025-10-08 13:16:05 +00:00
Merge branch 'swaywm:master' into remove_stuff
This commit is contained in:
commit
fd11eff12b
46 changed files with 748 additions and 408 deletions
|
@ -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);
|
||||
|
|
|
@ -13,6 +13,7 @@ enum sway_idle_inhibit_mode {
|
|||
struct sway_idle_inhibit_manager_v1 {
|
||||
struct wlr_idle_inhibit_manager_v1 *wlr_manager;
|
||||
struct wl_listener new_idle_inhibitor_v1;
|
||||
struct wl_listener manager_destroy;
|
||||
struct wl_list inhibitors;
|
||||
};
|
||||
|
||||
|
|
|
@ -39,6 +39,8 @@ struct sway_input_manager {
|
|||
|
||||
struct sway_input_manager *input_manager_create(struct sway_server *server);
|
||||
|
||||
void input_manager_finish(struct sway_input_manager *input);
|
||||
|
||||
bool input_manager_has_focus(struct sway_node *node);
|
||||
|
||||
void input_manager_set_focus(struct sway_node *node);
|
||||
|
|
|
@ -25,8 +25,10 @@ struct sway_input_method_relay {
|
|||
struct wlr_input_method_v2 *input_method; // doesn't have to be present
|
||||
|
||||
struct wl_listener text_input_new;
|
||||
struct wl_listener text_input_manager_destroy;
|
||||
|
||||
struct wl_listener input_method_new;
|
||||
struct wl_listener input_method_manager_destroy;
|
||||
struct wl_listener input_method_commit;
|
||||
struct wl_listener input_method_new_popup_surface;
|
||||
struct wl_listener input_method_grab_keyboard;
|
||||
|
|
|
@ -91,6 +91,9 @@ struct sway_output *output_from_wlr_output(struct wlr_output *output);
|
|||
struct sway_output *output_get_in_direction(struct sway_output *reference,
|
||||
enum wlr_direction direction);
|
||||
|
||||
void output_configure_scene(struct sway_output *output,
|
||||
struct wlr_scene_node *node, float opacity);
|
||||
|
||||
void output_add_workspace(struct sway_output *output,
|
||||
struct sway_workspace *workspace);
|
||||
|
||||
|
|
|
@ -46,6 +46,7 @@ struct sway_server {
|
|||
|
||||
struct wl_listener new_output;
|
||||
struct wl_listener renderer_lost;
|
||||
struct wl_event_source *recreating_renderer;
|
||||
|
||||
struct wlr_idle_notifier_v1 *idle_notifier_v1;
|
||||
struct sway_idle_inhibit_manager_v1 idle_inhibit_manager_v1;
|
||||
|
@ -104,8 +105,10 @@ struct sway_server {
|
|||
struct wlr_ext_foreign_toplevel_list_v1 *foreign_toplevel_list;
|
||||
struct wlr_foreign_toplevel_manager_v1 *foreign_toplevel_manager;
|
||||
struct wlr_content_type_manager_v1 *content_type_manager_v1;
|
||||
struct wlr_data_control_manager_v1 *data_control_manager_v1;
|
||||
struct wlr_data_control_manager_v1 *wlr_data_control_manager_v1;
|
||||
struct wlr_ext_data_control_manager_v1 *ext_data_control_manager_v1;
|
||||
struct wlr_screencopy_manager_v1 *screencopy_manager_v1;
|
||||
struct wlr_ext_image_copy_capture_manager_v1 *ext_image_copy_capture_manager_v1;
|
||||
struct wlr_export_dmabuf_manager_v1 *export_dmabuf_manager_v1;
|
||||
struct wlr_security_context_manager_v1 *security_context_manager_v1;
|
||||
|
||||
|
@ -148,20 +151,19 @@ struct sway_debug {
|
|||
bool noatomic; // Ignore atomic layout updates
|
||||
bool txn_timings; // Log verbose messages about transactions
|
||||
bool txn_wait; // Always wait for the timeout before applying
|
||||
bool legacy_wl_drm; // Enable the legacy wl_drm interface
|
||||
};
|
||||
|
||||
extern struct sway_debug debug;
|
||||
|
||||
extern bool allow_unsupported_gpu;
|
||||
|
||||
void sway_terminate(int exit_code);
|
||||
|
||||
bool server_init(struct sway_server *server);
|
||||
void server_fini(struct sway_server *server);
|
||||
bool server_start(struct sway_server *server);
|
||||
void server_run(struct sway_server *server);
|
||||
|
||||
void restore_nofile_limit(void);
|
||||
|
||||
void handle_new_output(struct wl_listener *listener, void *data);
|
||||
|
||||
void handle_idle_inhibitor_v1(struct wl_listener *listener, void *data);
|
||||
|
|
|
@ -95,6 +95,7 @@ struct sway_container {
|
|||
|
||||
struct wl_listener output_enter;
|
||||
struct wl_listener output_leave;
|
||||
struct wl_listener output_handler_destroy;
|
||||
|
||||
struct sway_container_state current;
|
||||
struct sway_container_state pending;
|
||||
|
|
|
@ -221,6 +221,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,
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
project(
|
||||
'sway',
|
||||
'c',
|
||||
version: '1.10-dev',
|
||||
version: '1.11-rc2',
|
||||
license: 'MIT',
|
||||
meson_version: '>=1.3',
|
||||
default_options: [
|
||||
|
@ -79,7 +79,7 @@ libudev = wlroots_features['libinput_backend'] ? dependency('libudev') : null_de
|
|||
math = cc.find_library('m')
|
||||
rt = cc.find_library('rt')
|
||||
xcb_icccm = wlroots_features['xwayland'] ? dependency('xcb-icccm') : null_dep
|
||||
threads = dependency('threads') # for pthread_setschedparam
|
||||
threads = dependency('threads') # for pthread_setschedparam and pthread_atfork
|
||||
|
||||
if get_option('sd-bus-provider') == 'auto'
|
||||
if not get_option('tray').disabled()
|
||||
|
|
|
@ -9,12 +9,15 @@ wayland_scanner = find_program(
|
|||
protocols = [
|
||||
wl_protocol_dir / 'stable/tablet/tablet-v2.xml',
|
||||
wl_protocol_dir / 'stable/xdg-shell/xdg-shell.xml',
|
||||
wl_protocol_dir / 'unstable/xdg-output/xdg-output-unstable-v1.xml',
|
||||
wl_protocol_dir / 'unstable/pointer-constraints/pointer-constraints-unstable-v1.xml',
|
||||
wl_protocol_dir / 'unstable/linux-dmabuf/linux-dmabuf-unstable-v1.xml',
|
||||
wl_protocol_dir / 'staging/content-type/content-type-v1.xml',
|
||||
wl_protocol_dir / 'staging/cursor-shape/cursor-shape-v1.xml',
|
||||
wl_protocol_dir / 'staging/ext-foreign-toplevel-list/ext-foreign-toplevel-list-v1.xml',
|
||||
wl_protocol_dir / 'staging/ext-image-capture-source/ext-image-capture-source-v1.xml',
|
||||
wl_protocol_dir / 'staging/ext-image-copy-capture/ext-image-copy-capture-v1.xml',
|
||||
wl_protocol_dir / 'staging/tearing-control/tearing-control-v1.xml',
|
||||
wl_protocol_dir / 'unstable/linux-dmabuf/linux-dmabuf-unstable-v1.xml',
|
||||
wl_protocol_dir / 'unstable/pointer-constraints/pointer-constraints-unstable-v1.xml',
|
||||
wl_protocol_dir / 'unstable/xdg-output/xdg-output-unstable-v1.xml',
|
||||
'wlr-layer-shell-unstable-v1.xml',
|
||||
'idle.xml',
|
||||
'wlr-output-power-management-unstable-v1.xml',
|
||||
|
|
|
@ -3,3 +3,4 @@ Name=Sway
|
|||
Comment=An i3-compatible Wayland compositor
|
||||
Exec=sway
|
||||
Type=Application
|
||||
DesktopNames=sway;wlroots
|
||||
|
|
|
@ -367,7 +367,7 @@ static struct cmd_results *cmd_bindsym_or_bindcode(int argc, char **argv,
|
|||
}
|
||||
} else if (strcmp("--exclude-titlebar", argv[0]) == 0) {
|
||||
exclude_titlebar = true;
|
||||
} else if (has_prefix("--input-device=", argv[0])) {
|
||||
} else if (has_prefix(argv[0], "--input-device=")) {
|
||||
free(binding->input);
|
||||
binding->input = strdup(argv[0] + strlen("--input-device="));
|
||||
strip_quotes(binding->input);
|
||||
|
|
|
@ -25,16 +25,6 @@ struct cmd_results *cmd_exec_validate(int argc, char **argv) {
|
|||
return error;
|
||||
}
|
||||
|
||||
static void export_xdga_token(struct launcher_ctx *ctx) {
|
||||
const char *token = launcher_ctx_get_token_name(ctx);
|
||||
setenv("XDG_ACTIVATION_TOKEN", token, 1);
|
||||
}
|
||||
|
||||
static void export_startup_id(struct launcher_ctx *ctx) {
|
||||
const char *token = launcher_ctx_get_token_name(ctx);
|
||||
setenv("DESKTOP_STARTUP_ID", token, 1);
|
||||
}
|
||||
|
||||
struct cmd_results *cmd_exec_process(int argc, char **argv) {
|
||||
struct cmd_results *error = NULL;
|
||||
char *cmd = NULL;
|
||||
|
@ -56,67 +46,37 @@ struct cmd_results *cmd_exec_process(int argc, char **argv) {
|
|||
|
||||
sway_log(SWAY_DEBUG, "Executing %s", cmd);
|
||||
|
||||
int fd[2];
|
||||
if (pipe(fd) != 0) {
|
||||
sway_log(SWAY_ERROR, "Unable to create pipe for fork");
|
||||
}
|
||||
|
||||
pid_t pid, child;
|
||||
struct launcher_ctx *ctx = launcher_ctx_create_internal();
|
||||
|
||||
// Fork process
|
||||
if ((pid = fork()) == 0) {
|
||||
// Fork child process again
|
||||
restore_nofile_limit();
|
||||
pid_t child = fork();
|
||||
if (child == 0) {
|
||||
setsid();
|
||||
sigset_t set;
|
||||
sigemptyset(&set);
|
||||
sigprocmask(SIG_SETMASK, &set, NULL);
|
||||
signal(SIGPIPE, SIG_DFL);
|
||||
close(fd[0]);
|
||||
if ((child = fork()) == 0) {
|
||||
close(fd[1]);
|
||||
if (ctx) {
|
||||
export_xdga_token(ctx);
|
||||
|
||||
if (ctx) {
|
||||
const char *token = launcher_ctx_get_token_name(ctx);
|
||||
setenv("XDG_ACTIVATION_TOKEN", token, 1);
|
||||
if (!no_startup_id) {
|
||||
setenv("DESKTOP_STARTUP_ID", token, 1);
|
||||
}
|
||||
if (ctx && !no_startup_id) {
|
||||
export_startup_id(ctx);
|
||||
}
|
||||
execlp("sh", "sh", "-c", cmd, (void *)NULL);
|
||||
sway_log_errno(SWAY_ERROR, "execlp failed");
|
||||
_exit(1);
|
||||
}
|
||||
ssize_t s = 0;
|
||||
while ((size_t)s < sizeof(pid_t)) {
|
||||
s += write(fd[1], ((uint8_t *)&child) + s, sizeof(pid_t) - s);
|
||||
}
|
||||
close(fd[1]);
|
||||
|
||||
execlp("sh", "sh", "-c", cmd, (void*)NULL);
|
||||
sway_log_errno(SWAY_ERROR, "execve failed");
|
||||
_exit(0); // Close child process
|
||||
} else if (pid < 0) {
|
||||
} else if (child < 0) {
|
||||
launcher_ctx_destroy(ctx);
|
||||
free(cmd);
|
||||
close(fd[0]);
|
||||
close(fd[1]);
|
||||
return cmd_results_new(CMD_FAILURE, "fork() failed");
|
||||
}
|
||||
free(cmd);
|
||||
close(fd[1]); // close write
|
||||
ssize_t s = 0;
|
||||
while ((size_t)s < sizeof(pid_t)) {
|
||||
s += read(fd[0], ((uint8_t *)&child) + s, sizeof(pid_t) - s);
|
||||
}
|
||||
close(fd[0]);
|
||||
// cleanup child process
|
||||
waitpid(pid, NULL, 0);
|
||||
if (child > 0) {
|
||||
sway_log(SWAY_DEBUG, "Child process created with pid %d", child);
|
||||
if (ctx != NULL) {
|
||||
sway_log(SWAY_DEBUG, "Recording workspace for process %d", child);
|
||||
ctx->pid = child;
|
||||
}
|
||||
} else {
|
||||
launcher_ctx_destroy(ctx);
|
||||
return cmd_results_new(CMD_FAILURE, "Second fork() failed");
|
||||
|
||||
sway_log(SWAY_DEBUG, "Child process created with pid %d", child);
|
||||
if (ctx != NULL) {
|
||||
sway_log(SWAY_DEBUG, "Recording workspace for process %d", child);
|
||||
ctx->pid = child;
|
||||
}
|
||||
|
||||
free(cmd);
|
||||
return cmd_results_new(CMD_SUCCESS, NULL);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
#include <stddef.h>
|
||||
#include "sway/commands.h"
|
||||
#include "sway/config.h"
|
||||
|
||||
void sway_terminate(int exit_code);
|
||||
#include "sway/server.h"
|
||||
|
||||
struct cmd_results *cmd_exit(int argc, char **argv) {
|
||||
struct cmd_results *error = NULL;
|
||||
|
|
|
@ -121,7 +121,7 @@ static struct cmd_results *cmd_bind_or_unbind_gesture(int argc, char **argv, boo
|
|||
binding->flags |= BINDING_EXACT;
|
||||
} else if (strcmp("--no-warn", argv[0]) == 0) {
|
||||
warn = false;
|
||||
} else if (has_prefix("--input-device=", argv[0])) {
|
||||
} else if (has_prefix(argv[0], "--input-device=")) {
|
||||
free(binding->input);
|
||||
binding->input = strdup(argv[0] + strlen("--input-device="));
|
||||
} else {
|
||||
|
|
|
@ -2,7 +2,8 @@
|
|||
#include <stdlib.h>
|
||||
#include <strings.h>
|
||||
#include "sway/commands.h"
|
||||
#include "sway/tree/view.h"
|
||||
#include "sway/tree/container.h"
|
||||
#include "sway/output.h"
|
||||
#include "log.h"
|
||||
|
||||
struct cmd_results *cmd_opacity(int argc, char **argv) {
|
||||
|
@ -37,6 +38,7 @@ struct cmd_results *cmd_opacity(int argc, char **argv) {
|
|||
}
|
||||
|
||||
con->alpha = val;
|
||||
output_configure_scene(NULL, &con->scene_tree->node, 1);
|
||||
container_update(con);
|
||||
|
||||
return cmd_results_new(CMD_SUCCESS, NULL);
|
||||
|
|
|
@ -3,10 +3,8 @@
|
|||
#include <string.h>
|
||||
#include <strings.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include "sway/commands.h"
|
||||
#include "sway/config.h"
|
||||
#include "sway/swaynag.h"
|
||||
#include "log.h"
|
||||
#include "stringop.h"
|
||||
|
||||
|
@ -42,14 +40,14 @@ struct cmd_results *output_cmd_background(int argc, char **argv) {
|
|||
}
|
||||
|
||||
struct output_config *output = config->handler_context.output_config;
|
||||
|
||||
char *src = NULL;
|
||||
if (strcasecmp(argv[1], "solid_color") == 0) {
|
||||
if (!validate_color(argv[0])) {
|
||||
return cmd_results_new(CMD_INVALID,
|
||||
"Colors should be of the form #RRGGBB");
|
||||
}
|
||||
output->background = strdup(argv[0]);
|
||||
output->background_option = strdup("solid_color");
|
||||
if (!(output->background = strdup(argv[0]))) goto cleanup;
|
||||
if (!(output->background_option = strdup("solid_color"))) goto cleanup;
|
||||
output->background_fallback = NULL;
|
||||
argc -= 2; argv += 2;
|
||||
} else {
|
||||
|
@ -77,37 +75,25 @@ struct cmd_results *output_cmd_background(int argc, char **argv) {
|
|||
return cmd_results_new(CMD_INVALID, "Missing background file");
|
||||
}
|
||||
|
||||
char *src = join_args(argv, j);
|
||||
if (!(src = join_args(argv, j))) goto cleanup;
|
||||
if (!expand_path(&src)) {
|
||||
struct cmd_results *cmd_res = cmd_results_new(CMD_INVALID,
|
||||
"Invalid syntax (%s)", src);
|
||||
free(src);
|
||||
return cmd_res;
|
||||
}
|
||||
if (!src) {
|
||||
sway_log(SWAY_ERROR, "Failed to allocate expanded path");
|
||||
return cmd_results_new(CMD_FAILURE, "Unable to allocate resource");
|
||||
}
|
||||
|
||||
if (config->reading && *src != '/') {
|
||||
// src file is inside configuration dir
|
||||
|
||||
char *conf = strdup(config->current_config_path);
|
||||
if (!conf) {
|
||||
sway_log(SWAY_ERROR, "Failed to duplicate string");
|
||||
free(src);
|
||||
return cmd_results_new(CMD_FAILURE,
|
||||
"Unable to allocate resources");
|
||||
}
|
||||
if (!conf) goto cleanup;
|
||||
|
||||
char *conf_path = dirname(conf);
|
||||
char *real_src = malloc(strlen(conf_path) + strlen(src) + 2);
|
||||
if (!real_src) {
|
||||
free(src);
|
||||
free(conf);
|
||||
sway_log(SWAY_ERROR, "Unable to allocate memory");
|
||||
return cmd_results_new(CMD_FAILURE,
|
||||
"Unable to allocate resources");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
snprintf(real_src, strlen(conf_path) + strlen(src) + 2, "%s/%s", conf_path, src);
|
||||
|
@ -117,40 +103,48 @@ struct cmd_results *output_cmd_background(int argc, char **argv) {
|
|||
}
|
||||
|
||||
bool can_access = access(src, F_OK) != -1;
|
||||
argc -= j + 1; argv += j + 1;
|
||||
free(output->background_option);
|
||||
free(output->background_fallback);
|
||||
free(output->background);
|
||||
output->background = output->background_option = output->background_fallback = NULL;
|
||||
char *fallback = NULL;
|
||||
|
||||
if (argc && *argv[0] == '#') {
|
||||
if (validate_color(argv[0])) {
|
||||
if (!(fallback = strdup(argv[0]))) goto cleanup;
|
||||
output->background_fallback = fallback;
|
||||
} else {
|
||||
sway_log(SWAY_ERROR, "fallback '%s' should be of the form #RRGGBB", argv[0]);
|
||||
config_add_swaynag_warning("fallback '%s' should be of the form #RRGGBB\n", argv[0]);
|
||||
}
|
||||
argc--; argv++;
|
||||
}
|
||||
|
||||
if (!can_access) {
|
||||
sway_log_errno(SWAY_ERROR, "Unable to access background file '%s'",
|
||||
src);
|
||||
config_add_swaynag_warning("Unable to access background file '%s'",
|
||||
src);
|
||||
struct cmd_results *result = cmd_results_new(CMD_FAILURE,
|
||||
"unable to access background file '%s'", src);
|
||||
free(src);
|
||||
return result;
|
||||
if (!fallback) {
|
||||
sway_log(SWAY_ERROR, "Unable to access background file '%s' "
|
||||
"and no valid fallback provided", src);
|
||||
struct cmd_results *res = cmd_results_new(CMD_FAILURE, "Unable to access "
|
||||
"background file '%s' and no valid fallback provided", src);
|
||||
free(src);
|
||||
return res;
|
||||
}
|
||||
sway_log(SWAY_DEBUG, "Cannot access file '%s', using fallback '%s'", src, fallback);
|
||||
output->background = fallback;
|
||||
if (!(output->background_option = strdup("solid_color"))) goto cleanup;
|
||||
output->background_fallback = NULL;
|
||||
} else {
|
||||
output->background = src;
|
||||
output->background_option = strdup(mode);
|
||||
}
|
||||
argc -= j + 1; argv += j + 1;
|
||||
|
||||
output->background_fallback = NULL;
|
||||
if (argc && *argv[0] == '#') {
|
||||
if (!validate_color(argv[0])) {
|
||||
return cmd_results_new(CMD_INVALID,
|
||||
"fallback color should be of the form #RRGGBB");
|
||||
}
|
||||
|
||||
output->background_fallback = strdup(argv[0]);
|
||||
argc--; argv++;
|
||||
|
||||
if (!can_access) {
|
||||
output->background = output->background_fallback;
|
||||
output->background_option = strdup("solid_color");
|
||||
output->background_fallback = NULL;
|
||||
}
|
||||
if (!(output->background_option = strdup(mode))) goto cleanup;
|
||||
}
|
||||
}
|
||||
|
||||
config->handler_context.leftovers.argc = argc;
|
||||
config->handler_context.leftovers.argv = argv;
|
||||
return NULL;
|
||||
|
||||
cleanup:
|
||||
free(src);
|
||||
sway_log(SWAY_ERROR, "Failed to allocate resources");
|
||||
return cmd_results_new(CMD_FAILURE, "Unable to allocate resources");
|
||||
}
|
||||
|
|
|
@ -457,7 +457,7 @@ static struct cmd_results *cmd_resize_set(int argc, char **argv) {
|
|||
if (argc > num_consumed_args) {
|
||||
return cmd_results_new(CMD_INVALID, "%s", usage);
|
||||
}
|
||||
if (width.unit == MOVEMENT_UNIT_INVALID) {
|
||||
if (height.unit == MOVEMENT_UNIT_INVALID) {
|
||||
return cmd_results_new(CMD_INVALID, "%s", usage);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -118,10 +118,10 @@ struct cmd_results *cmd_scratchpad(int argc, char **argv) {
|
|||
|
||||
// If using criteria, this command is executed for every container which
|
||||
// matches the criteria. If this container isn't in the scratchpad,
|
||||
// we'll just silently return a success. The same is true if the
|
||||
// we'll return an error. The same is true if the
|
||||
// overridden node is not a container.
|
||||
if (!con || !con->scratchpad) {
|
||||
return cmd_results_new(CMD_SUCCESS, NULL);
|
||||
return cmd_results_new(CMD_INVALID, "Container is not in scratchpad.");
|
||||
}
|
||||
scratchpad_toggle_container(con);
|
||||
} else {
|
||||
|
|
|
@ -552,28 +552,12 @@ bool load_main_config(const char *file, bool is_active, bool validating) {
|
|||
return success;
|
||||
}
|
||||
|
||||
static bool load_include_config(const char *path, const char *parent_dir,
|
||||
struct sway_config *config, struct swaynag_instance *swaynag) {
|
||||
static bool load_include_config(const char *path, struct sway_config *config,
|
||||
struct swaynag_instance *swaynag) {
|
||||
// save parent config
|
||||
const char *parent_config = config->current_config_path;
|
||||
|
||||
char *full_path;
|
||||
int len = strlen(path);
|
||||
if (len >= 1 && path[0] != '/') {
|
||||
len = len + strlen(parent_dir) + 2;
|
||||
full_path = malloc(len * sizeof(char));
|
||||
if (!full_path) {
|
||||
sway_log(SWAY_ERROR,
|
||||
"Unable to allocate full path to included config");
|
||||
return false;
|
||||
}
|
||||
snprintf(full_path, len, "%s/%s", parent_dir, path);
|
||||
} else {
|
||||
full_path = strdup(path);
|
||||
}
|
||||
|
||||
char *real_path = realpath(full_path, NULL);
|
||||
free(full_path);
|
||||
char *real_path = realpath(path, NULL);
|
||||
|
||||
if (real_path == NULL) {
|
||||
sway_log(SWAY_DEBUG, "%s not found.", path);
|
||||
|
@ -625,7 +609,7 @@ void load_include_configs(const char *path, struct sway_config *config,
|
|||
char **w = p.we_wordv;
|
||||
size_t i;
|
||||
for (i = 0; i < p.we_wordc; ++i) {
|
||||
load_include_config(w[i], parent_dir, config, swaynag);
|
||||
load_include_config(w[i], config, swaynag);
|
||||
}
|
||||
wordfree(&p);
|
||||
}
|
||||
|
|
|
@ -213,36 +213,21 @@ static void invoke_swaybar(struct bar_config *bar) {
|
|||
sway_log(SWAY_ERROR, "Failed to create fork for swaybar");
|
||||
return;
|
||||
} else if (pid == 0) {
|
||||
// Remove the SIGUSR1 handler that wlroots adds for xwayland
|
||||
sigset_t set;
|
||||
sigemptyset(&set);
|
||||
sigprocmask(SIG_SETMASK, &set, NULL);
|
||||
signal(SIGPIPE, SIG_DFL);
|
||||
|
||||
restore_nofile_limit();
|
||||
|
||||
pid = fork();
|
||||
if (pid < 0) {
|
||||
sway_log_errno(SWAY_ERROR, "fork failed");
|
||||
_exit(EXIT_FAILURE);
|
||||
} else if (pid == 0) {
|
||||
if (!sway_set_cloexec(sockets[1], false)) {
|
||||
_exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
char wayland_socket_str[16];
|
||||
snprintf(wayland_socket_str, sizeof(wayland_socket_str),
|
||||
"%d", sockets[1]);
|
||||
setenv("WAYLAND_SOCKET", wayland_socket_str, true);
|
||||
|
||||
// run custom swaybar
|
||||
char *const cmd[] = {
|
||||
bar->swaybar_command ? bar->swaybar_command : "swaybar",
|
||||
"-b", bar->id, NULL};
|
||||
execvp(cmd[0], cmd);
|
||||
if (!sway_set_cloexec(sockets[1], false)) {
|
||||
_exit(EXIT_FAILURE);
|
||||
}
|
||||
_exit(EXIT_SUCCESS);
|
||||
|
||||
char wayland_socket_str[16];
|
||||
snprintf(wayland_socket_str, sizeof(wayland_socket_str),
|
||||
"%d", sockets[1]);
|
||||
setenv("WAYLAND_SOCKET", wayland_socket_str, true);
|
||||
|
||||
// run custom swaybar
|
||||
char *const cmd[] = {
|
||||
bar->swaybar_command ? bar->swaybar_command : "swaybar",
|
||||
"-b", bar->id, NULL};
|
||||
execvp(cmd[0], cmd);
|
||||
_exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (close(sockets[1]) != 0) {
|
||||
|
@ -250,11 +235,6 @@ static void invoke_swaybar(struct bar_config *bar) {
|
|||
return;
|
||||
}
|
||||
|
||||
if (waitpid(pid, NULL, 0) < 0) {
|
||||
sway_log_errno(SWAY_ERROR, "waitpid failed");
|
||||
return;
|
||||
}
|
||||
|
||||
sway_log(SWAY_DEBUG, "Spawned swaybar %s", bar->id);
|
||||
}
|
||||
|
||||
|
|
|
@ -67,7 +67,7 @@ struct output_config *new_output_config(const char *name) {
|
|||
oc->refresh_rate = -1;
|
||||
oc->custom_mode = -1;
|
||||
oc->drm_mode.type = -1;
|
||||
oc->x = oc->y = -1;
|
||||
oc->x = oc->y = INT_MAX;
|
||||
oc->scale = -1;
|
||||
oc->scale_filter = SCALE_FILTER_DEFAULT;
|
||||
oc->transform = -1;
|
||||
|
@ -93,11 +93,11 @@ static void supersede_output_config(struct output_config *dst, struct output_con
|
|||
if (src->height != -1) {
|
||||
dst->height = -1;
|
||||
}
|
||||
if (src->x != -1) {
|
||||
dst->x = -1;
|
||||
if (src->x != INT_MAX) {
|
||||
dst->x = INT_MAX;
|
||||
}
|
||||
if (src->y != -1) {
|
||||
dst->y = -1;
|
||||
if (src->y != INT_MAX) {
|
||||
dst->y = INT_MAX;
|
||||
}
|
||||
if (src->scale != -1) {
|
||||
dst->scale = -1;
|
||||
|
@ -129,6 +129,13 @@ static void supersede_output_config(struct output_config *dst, struct output_con
|
|||
if (src->render_bit_depth != RENDER_BIT_DEPTH_DEFAULT) {
|
||||
dst->render_bit_depth = RENDER_BIT_DEPTH_DEFAULT;
|
||||
}
|
||||
if (src->set_color_transform) {
|
||||
if (dst->color_transform) {
|
||||
wlr_color_transform_unref(dst->color_transform);
|
||||
dst->color_transform = NULL;
|
||||
}
|
||||
dst->set_color_transform = false;
|
||||
}
|
||||
if (src->background) {
|
||||
free(dst->background);
|
||||
dst->background = NULL;
|
||||
|
@ -144,6 +151,9 @@ static void supersede_output_config(struct output_config *dst, struct output_con
|
|||
if (src->power != -1) {
|
||||
dst->power = -1;
|
||||
}
|
||||
if (src->allow_tearing != -1) {
|
||||
dst->allow_tearing = -1;
|
||||
}
|
||||
}
|
||||
|
||||
// merge_output_config sets all fields in dst that were set in src
|
||||
|
@ -157,10 +167,10 @@ static void merge_output_config(struct output_config *dst, struct output_config
|
|||
if (src->height != -1) {
|
||||
dst->height = src->height;
|
||||
}
|
||||
if (src->x != -1) {
|
||||
if (src->x != INT_MAX) {
|
||||
dst->x = src->x;
|
||||
}
|
||||
if (src->y != -1) {
|
||||
if (src->y != INT_MAX) {
|
||||
dst->y = src->y;
|
||||
}
|
||||
if (src->scale != -1) {
|
||||
|
@ -527,7 +537,7 @@ static bool finalize_output_config(struct output_config *oc, struct sway_output
|
|||
}
|
||||
|
||||
// Find position for it
|
||||
if (oc && (oc->x != -1 || oc->y != -1)) {
|
||||
if (oc && oc->x != INT_MAX && oc->y != INT_MAX) {
|
||||
sway_log(SWAY_DEBUG, "Set %s position to %d, %d", oc->name, oc->x, oc->y);
|
||||
wlr_output_layout_add(root->output_layout, wlr_output, oc->x, oc->y);
|
||||
} else {
|
||||
|
@ -1018,6 +1028,7 @@ void free_output_config(struct output_config *oc) {
|
|||
free(oc->name);
|
||||
free(oc->background);
|
||||
free(oc->background_option);
|
||||
free(oc->background_fallback);
|
||||
wlr_color_transform_unref(oc->color_transform);
|
||||
free(oc);
|
||||
}
|
||||
|
@ -1059,42 +1070,27 @@ static bool _spawn_swaybg(char **command) {
|
|||
sway_log_errno(SWAY_ERROR, "fork failed");
|
||||
return false;
|
||||
} else if (pid == 0) {
|
||||
restore_nofile_limit();
|
||||
|
||||
pid = fork();
|
||||
if (pid < 0) {
|
||||
sway_log_errno(SWAY_ERROR, "fork failed");
|
||||
_exit(EXIT_FAILURE);
|
||||
} else if (pid == 0) {
|
||||
if (!sway_set_cloexec(sockets[1], false)) {
|
||||
_exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
char wayland_socket_str[16];
|
||||
snprintf(wayland_socket_str, sizeof(wayland_socket_str),
|
||||
"%d", sockets[1]);
|
||||
setenv("WAYLAND_SOCKET", wayland_socket_str, true);
|
||||
|
||||
execvp(command[0], command);
|
||||
sway_log_errno(SWAY_ERROR, "failed to execute '%s' "
|
||||
"(background configuration probably not applied)",
|
||||
command[0]);
|
||||
if (!sway_set_cloexec(sockets[1], false)) {
|
||||
_exit(EXIT_FAILURE);
|
||||
}
|
||||
_exit(EXIT_SUCCESS);
|
||||
|
||||
char wayland_socket_str[16];
|
||||
snprintf(wayland_socket_str, sizeof(wayland_socket_str),
|
||||
"%d", sockets[1]);
|
||||
setenv("WAYLAND_SOCKET", wayland_socket_str, true);
|
||||
|
||||
execvp(command[0], command);
|
||||
sway_log_errno(SWAY_ERROR, "failed to execute '%s' "
|
||||
"(background configuration probably not applied)",
|
||||
command[0]);
|
||||
_exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (close(sockets[1]) != 0) {
|
||||
sway_log_errno(SWAY_ERROR, "close failed");
|
||||
return false;
|
||||
}
|
||||
int fork_status = 0;
|
||||
if (waitpid(pid, &fork_status, 0) < 0) {
|
||||
sway_log_errno(SWAY_ERROR, "waitpid failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
return WIFEXITED(fork_status) && WEXITSTATUS(fork_status) == EXIT_SUCCESS;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool spawn_swaybg(void) {
|
||||
|
|
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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,
|
||||
};
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -555,8 +630,7 @@ static bool parse_token(struct criteria *criteria, char *name, char *value) {
|
|||
if (strcmp(value, "__focused__") == 0) {
|
||||
struct sway_seat *seat = input_manager_current_seat();
|
||||
struct sway_container *focus = seat_get_focused_container(seat);
|
||||
struct sway_view *view = focus ? focus->view : NULL;
|
||||
criteria->con_id = view ? view->container->node.id : 0;
|
||||
criteria->con_id = focus ? focus->node.id : 0;
|
||||
} else {
|
||||
criteria->con_id = strtoul(value, &endptr, 10);
|
||||
if (*endptr != 0) {
|
||||
|
@ -617,6 +691,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;
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#include <stdlib.h>
|
||||
#include <wlr/types/wlr_idle_notify_v1.h>
|
||||
#include <wlr/types/wlr_session_lock_v1.h>
|
||||
#include "log.h"
|
||||
#include "sway/desktop/idle_inhibit_v1.h"
|
||||
#include "sway/input/seat.h"
|
||||
|
@ -44,6 +45,14 @@ void handle_idle_inhibitor_v1(struct wl_listener *listener, void *data) {
|
|||
sway_idle_inhibit_v1_check_active();
|
||||
}
|
||||
|
||||
void handle_manager_destroy(struct wl_listener *listener, void *data) {
|
||||
struct sway_idle_inhibit_manager_v1 *manager =
|
||||
wl_container_of(listener, manager, manager_destroy);
|
||||
|
||||
wl_list_remove(&manager->manager_destroy.link);
|
||||
wl_list_remove(&manager->new_idle_inhibitor_v1.link);
|
||||
}
|
||||
|
||||
void sway_idle_inhibit_v1_user_inhibitor_register(struct sway_view *view,
|
||||
enum sway_idle_inhibit_mode mode) {
|
||||
struct sway_idle_inhibit_manager_v1 *manager = &server.idle_inhibit_manager_v1;
|
||||
|
@ -103,11 +112,34 @@ void sway_idle_inhibit_v1_user_inhibitor_destroy(
|
|||
}
|
||||
|
||||
bool sway_idle_inhibit_v1_is_active(struct sway_idle_inhibitor_v1 *inhibitor) {
|
||||
if (server.session_lock.lock) {
|
||||
// A session lock is active. In this case, only application inhibitors
|
||||
// on the session lock surface can have any effect.
|
||||
if (inhibitor->mode != INHIBIT_IDLE_APPLICATION) {
|
||||
return false;
|
||||
}
|
||||
struct wlr_surface *wlr_surface = inhibitor->wlr_inhibitor->surface;
|
||||
if (!wlr_session_lock_surface_v1_try_from_wlr_surface(wlr_surface)) {
|
||||
return false;
|
||||
}
|
||||
return wlr_surface->mapped;
|
||||
}
|
||||
|
||||
switch (inhibitor->mode) {
|
||||
case INHIBIT_IDLE_APPLICATION:;
|
||||
// If there is no view associated with the inhibitor, assume visible
|
||||
struct sway_view *view = view_from_wlr_surface(inhibitor->wlr_inhibitor->surface);
|
||||
return !view || !view->container || view_is_visible(view);
|
||||
struct wlr_surface *wlr_surface = inhibitor->wlr_inhibitor->surface;
|
||||
struct wlr_layer_surface_v1 *layer_surface =
|
||||
wlr_layer_surface_v1_try_from_wlr_surface(wlr_surface);
|
||||
if (layer_surface) {
|
||||
// Layer surfaces can be occluded but are always on screen after
|
||||
// they have been mapped.
|
||||
return layer_surface->output && layer_surface->output->enabled &&
|
||||
wlr_surface->mapped;
|
||||
}
|
||||
|
||||
// If there is no view associated with the inhibitor, assume invisible
|
||||
struct sway_view *view = view_from_wlr_surface(wlr_surface);
|
||||
return view && view->container && view_is_visible(view);
|
||||
case INHIBIT_IDLE_FOCUS:;
|
||||
struct sway_seat *seat = NULL;
|
||||
wl_list_for_each(seat, &server.input->seats, link) {
|
||||
|
@ -153,6 +185,9 @@ bool sway_idle_inhibit_manager_v1_init(void) {
|
|||
wl_signal_add(&manager->wlr_manager->events.new_inhibitor,
|
||||
&manager->new_idle_inhibitor_v1);
|
||||
manager->new_idle_inhibitor_v1.notify = handle_idle_inhibitor_v1;
|
||||
wl_signal_add(&manager->wlr_manager->events.destroy,
|
||||
&manager->manager_destroy);
|
||||
manager->manager_destroy.notify = handle_manager_destroy;
|
||||
wl_list_init(&manager->inhibitors);
|
||||
|
||||
return true;
|
||||
|
|
|
@ -221,7 +221,7 @@ static void handle_output_destroy(struct wl_listener *listener, void *data) {
|
|||
wl_container_of(listener, layer, output_destroy);
|
||||
|
||||
layer->output = NULL;
|
||||
wlr_scene_node_destroy(&layer->scene->tree->node);
|
||||
wlr_layer_surface_v1_destroy(layer->layer_surface);
|
||||
}
|
||||
|
||||
static void handle_node_destroy(struct wl_listener *listener, void *data) {
|
||||
|
@ -256,6 +256,7 @@ static void handle_node_destroy(struct wl_listener *listener, void *data) {
|
|||
wl_list_remove(&layer->unmap.link);
|
||||
wl_list_remove(&layer->surface_commit.link);
|
||||
wl_list_remove(&layer->node_destroy.link);
|
||||
wl_list_remove(&layer->new_popup.link);
|
||||
wl_list_remove(&layer->output_destroy.link);
|
||||
|
||||
layer->layer_surface->data = NULL;
|
||||
|
|
|
@ -10,7 +10,6 @@
|
|||
#include <wlr/types/wlr_buffer.h>
|
||||
#include <wlr/types/wlr_alpha_modifier_v1.h>
|
||||
#include <wlr/types/wlr_gamma_control_v1.h>
|
||||
#include <wlr/types/wlr_matrix.h>
|
||||
#include <wlr/types/wlr_output_layout.h>
|
||||
#include <wlr/types/wlr_output_management_v1.h>
|
||||
#include <wlr/types/wlr_output_power_management_v1.h>
|
||||
|
@ -203,7 +202,7 @@ static enum wlr_scale_filter_mode get_scale_filter(struct sway_output *output,
|
|||
}
|
||||
}
|
||||
|
||||
static void output_configure_scene(struct sway_output *output,
|
||||
void output_configure_scene(struct sway_output *output,
|
||||
struct wlr_scene_node *node, float opacity) {
|
||||
if (!node->enabled) {
|
||||
return;
|
||||
|
@ -230,7 +229,9 @@ static void output_configure_scene(struct sway_output *output,
|
|||
// hack: don't call the scene setter because that will damage all outputs
|
||||
// We don't want to damage outputs that aren't our current output that
|
||||
// we're configuring
|
||||
buffer->filter_mode = get_scale_filter(output, buffer);
|
||||
if (output) {
|
||||
buffer->filter_mode = get_scale_filter(output, buffer);
|
||||
}
|
||||
|
||||
wlr_scene_buffer_set_opacity(buffer, opacity);
|
||||
} else if (node->type == WLR_SCENE_NODE_TREE) {
|
||||
|
@ -263,7 +264,7 @@ static int output_repaint_timer_handler(void *data) {
|
|||
struct sway_output *output = data;
|
||||
|
||||
output->wlr_output->frame_pending = false;
|
||||
if (!output->enabled) {
|
||||
if (!output->wlr_output->enabled) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -312,9 +312,9 @@ static void arrange_children(enum sway_container_layout layout, list_t *children
|
|||
wlr_scene_node_set_position(&child->scene_tree->node, 0, title_bar_height);
|
||||
wlr_scene_node_reparent(&child->scene_tree->node, content);
|
||||
|
||||
if (activated) {
|
||||
arrange_container(child, width, height - title_bar_height,
|
||||
title_bar_height == 0, 0);
|
||||
int net_height = height - title_bar_height;
|
||||
if (activated && width > 0 && net_height > 0) {
|
||||
arrange_container(child, width, net_height, title_bar_height == 0, 0);
|
||||
} else {
|
||||
disable_container(child);
|
||||
}
|
||||
|
@ -341,9 +341,9 @@ static void arrange_children(enum sway_container_layout layout, list_t *children
|
|||
wlr_scene_node_set_position(&child->scene_tree->node, 0, title_height);
|
||||
wlr_scene_node_reparent(&child->scene_tree->node, content);
|
||||
|
||||
if (activated) {
|
||||
arrange_container(child, width, height - title_height,
|
||||
title_bar_height == 0, 0);
|
||||
int net_height = height - title_bar_height;
|
||||
if (activated && width > 0 && net_height > 0) {
|
||||
arrange_container(child, width, net_height, title_bar_height == 0, 0);
|
||||
} else {
|
||||
disable_container(child);
|
||||
}
|
||||
|
@ -359,8 +359,12 @@ static void arrange_children(enum sway_container_layout layout, list_t *children
|
|||
wlr_scene_node_set_enabled(&child->border.tree->node, true);
|
||||
wlr_scene_node_set_position(&child->scene_tree->node, 0, off);
|
||||
wlr_scene_node_reparent(&child->scene_tree->node, content);
|
||||
arrange_container(child, width, cheight, true, gaps);
|
||||
off += cheight + gaps;
|
||||
if (width > 0 && cheight > 0) {
|
||||
arrange_container(child, width, cheight, true, gaps);
|
||||
off += cheight + gaps;
|
||||
} else {
|
||||
disable_container(child);
|
||||
}
|
||||
}
|
||||
} else if (layout == L_HORIZ) {
|
||||
int off = 0;
|
||||
|
@ -371,8 +375,12 @@ static void arrange_children(enum sway_container_layout layout, list_t *children
|
|||
wlr_scene_node_set_enabled(&child->border.tree->node, true);
|
||||
wlr_scene_node_set_position(&child->scene_tree->node, off, 0);
|
||||
wlr_scene_node_reparent(&child->scene_tree->node, content);
|
||||
arrange_container(child, cwidth, height, true, gaps);
|
||||
off += cwidth + gaps;
|
||||
if (cwidth > 0 && height > 0) {
|
||||
arrange_container(child, cwidth, height, true, gaps);
|
||||
off += cwidth + gaps;
|
||||
} else {
|
||||
disable_container(child);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
sway_assert(false, "unreachable");
|
||||
|
@ -652,6 +660,8 @@ static void arrange_root(struct sway_root *root) {
|
|||
struct sway_output *output = root->outputs->items[i];
|
||||
struct sway_workspace *ws = output->current.active_workspace;
|
||||
|
||||
wlr_scene_output_set_position(output->scene_output, output->lx, output->ly);
|
||||
|
||||
if (ws) {
|
||||
arrange_workspace_floating(ws);
|
||||
}
|
||||
|
|
|
@ -1029,6 +1029,7 @@ void sway_cursor_destroy(struct sway_cursor *cursor) {
|
|||
wl_list_remove(&cursor->touch_frame.link);
|
||||
wl_list_remove(&cursor->tool_axis.link);
|
||||
wl_list_remove(&cursor->tool_tip.link);
|
||||
wl_list_remove(&cursor->tool_proximity.link);
|
||||
wl_list_remove(&cursor->tool_button.link);
|
||||
wl_list_remove(&cursor->request_set_cursor.link);
|
||||
|
||||
|
|
|
@ -494,6 +494,14 @@ struct sway_input_manager *input_manager_create(struct sway_server *server) {
|
|||
return input;
|
||||
}
|
||||
|
||||
void input_manager_finish(struct sway_input_manager *input) {
|
||||
wl_list_remove(&input->new_input.link);
|
||||
wl_list_remove(&input->virtual_keyboard_new.link);
|
||||
wl_list_remove(&input->virtual_pointer_new.link);
|
||||
wl_list_remove(&input->keyboard_shortcuts_inhibit_new_inhibitor.link);
|
||||
wl_list_remove(&input->transient_seat_create.link);
|
||||
}
|
||||
|
||||
bool input_manager_has_focus(struct sway_node *node) {
|
||||
struct sway_seat *seat = NULL;
|
||||
wl_list_for_each(seat, &server.input->seats, link) {
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include "sway/input/text_input_popup.h"
|
||||
#include "sway/layers.h"
|
||||
#include "sway/server.h"
|
||||
#include <wlr/types/wlr_session_lock_v1.h>
|
||||
|
||||
static struct sway_text_input *relay_get_focusable_text_input(
|
||||
struct sway_input_method_relay *relay) {
|
||||
|
@ -385,6 +386,8 @@ static void input_popup_set_focus(struct sway_input_popup *popup,
|
|||
|
||||
struct wlr_layer_surface_v1 *layer_surface =
|
||||
wlr_layer_surface_v1_try_from_wlr_surface(surface);
|
||||
struct wlr_session_lock_surface_v1 *lock_surface =
|
||||
wlr_session_lock_surface_v1_try_from_wlr_surface(surface);
|
||||
|
||||
struct wlr_scene_tree *relative_parent;
|
||||
if (layer_surface) {
|
||||
|
@ -404,8 +407,30 @@ static void input_popup_set_focus(struct sway_input_popup *popup,
|
|||
// surface. Layer surfaces get destroyed as part of the output being
|
||||
// destroyed, thus also trickling down to popups.
|
||||
popup->fixed_output = layer->layer_surface->output;
|
||||
} else if (lock_surface) {
|
||||
wl_signal_add(&lock_surface->surface->events.unmap,
|
||||
&popup->focused_surface_unmap);
|
||||
|
||||
struct sway_layer_surface *lock = lock_surface->data;
|
||||
if (lock == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
relative_parent = lock->scene->tree;
|
||||
popup->desc.view = NULL;
|
||||
|
||||
// we don't need to add an event here to NULL out this field because
|
||||
// this field will only be initialized if the popup is part of a layer
|
||||
// surface. Layer surfaces get destroyed as part of the output being
|
||||
// destroyed, thus also trickling down to popups.
|
||||
popup->fixed_output = lock->layer_surface->output;
|
||||
} else {
|
||||
struct sway_view *view = view_from_wlr_surface(surface);
|
||||
// In the future there may be other shells been added, so we also need to check here.
|
||||
if (view == NULL) {
|
||||
sway_log(SWAY_DEBUG, "Unsupported IME focus surface");
|
||||
return;
|
||||
}
|
||||
wl_signal_add(&view->events.unmap, &popup->focused_surface_unmap);
|
||||
relative_parent = view->scene_tree;
|
||||
popup->desc.view = view;
|
||||
|
@ -572,6 +597,34 @@ static void relay_handle_input_method(struct wl_listener *listener,
|
|||
}
|
||||
}
|
||||
|
||||
static void sway_input_method_relay_finish_text_input(struct sway_input_method_relay *relay) {
|
||||
wl_list_remove(&relay->text_input_new.link);
|
||||
wl_list_remove(&relay->text_input_manager_destroy.link);
|
||||
wl_list_init(&relay->text_input_new.link);
|
||||
wl_list_init(&relay->text_input_manager_destroy.link);
|
||||
}
|
||||
|
||||
static void relay_handle_text_input_manager_destroy(struct wl_listener *listener, void *data) {
|
||||
struct sway_input_method_relay *relay = wl_container_of(listener, relay,
|
||||
text_input_manager_destroy);
|
||||
|
||||
sway_input_method_relay_finish_text_input(relay);
|
||||
}
|
||||
|
||||
static void sway_input_method_relay_finish_input_method(struct sway_input_method_relay *relay) {
|
||||
wl_list_remove(&relay->input_method_new.link);
|
||||
wl_list_remove(&relay->input_method_manager_destroy.link);
|
||||
wl_list_init(&relay->input_method_new.link);
|
||||
wl_list_init(&relay->input_method_manager_destroy.link);
|
||||
}
|
||||
|
||||
static void relay_handle_input_method_manager_destroy(struct wl_listener *listener, void *data) {
|
||||
struct sway_input_method_relay *relay = wl_container_of(listener, relay,
|
||||
input_method_manager_destroy);
|
||||
|
||||
sway_input_method_relay_finish_input_method(relay);
|
||||
}
|
||||
|
||||
void sway_input_method_relay_init(struct sway_seat *seat,
|
||||
struct sway_input_method_relay *relay) {
|
||||
relay->seat = seat;
|
||||
|
@ -581,16 +634,22 @@ void sway_input_method_relay_init(struct sway_seat *seat,
|
|||
relay->text_input_new.notify = relay_handle_text_input;
|
||||
wl_signal_add(&server.text_input->events.text_input,
|
||||
&relay->text_input_new);
|
||||
relay->text_input_manager_destroy.notify = relay_handle_text_input_manager_destroy;
|
||||
wl_signal_add(&server.text_input->events.destroy,
|
||||
&relay->text_input_manager_destroy);
|
||||
|
||||
relay->input_method_new.notify = relay_handle_input_method;
|
||||
wl_signal_add(
|
||||
&server.input_method->events.input_method,
|
||||
&relay->input_method_new);
|
||||
relay->input_method_manager_destroy.notify = relay_handle_input_method_manager_destroy;
|
||||
wl_signal_add(&server.input_method->events.destroy,
|
||||
&relay->input_method_manager_destroy);
|
||||
}
|
||||
|
||||
void sway_input_method_relay_finish(struct sway_input_method_relay *relay) {
|
||||
wl_list_remove(&relay->input_method_new.link);
|
||||
wl_list_remove(&relay->text_input_new.link);
|
||||
sway_input_method_relay_finish_text_input(relay);
|
||||
sway_input_method_relay_finish_input_method(relay);
|
||||
}
|
||||
|
||||
void sway_input_method_relay_set_focus(struct sway_input_method_relay *relay,
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#include <wlr/config.h>
|
||||
#include <wlr/types/wlr_content_type_v1.h>
|
||||
#include <wlr/types/wlr_output.h>
|
||||
#include <wlr/types/wlr_ext_foreign_toplevel_list_v1.h>
|
||||
#include <xkbcommon/xkbcommon.h>
|
||||
#include "config.h"
|
||||
#include "log.h"
|
||||
|
@ -577,6 +578,10 @@ static void ipc_json_describe_view(struct sway_container *c, json_object *object
|
|||
json_object_object_add(object, "app_id",
|
||||
app_id ? json_object_new_string(app_id) : NULL);
|
||||
|
||||
json_object_object_add(object, "foreign_toplevel_identifier",
|
||||
c->view->ext_foreign_toplevel ?
|
||||
json_object_new_string(c->view->ext_foreign_toplevel->identifier) : NULL);
|
||||
|
||||
bool visible = view_is_visible(c->view);
|
||||
json_object_object_add(object, "visible", json_object_new_boolean(visible));
|
||||
|
||||
|
@ -602,6 +607,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",
|
||||
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 =
|
||||
|
|
|
@ -234,6 +234,9 @@ static void handle_unlock(struct wl_listener *listener, void *data) {
|
|||
struct sway_output *output = root->outputs->items[i];
|
||||
arrange_layers(output);
|
||||
}
|
||||
|
||||
// Views are now visible, so check if we need to activate inhibition again.
|
||||
sway_idle_inhibit_v1_check_active();
|
||||
}
|
||||
|
||||
static void handle_abandon(struct wl_listener *listener, void *data) {
|
||||
|
@ -297,6 +300,10 @@ static void handle_session_lock(struct wl_listener *listener, void *data) {
|
|||
|
||||
wlr_session_lock_v1_send_locked(lock);
|
||||
server.session_lock.lock = sway_lock;
|
||||
|
||||
// The lock screen covers everything, so check if any active inhibition got
|
||||
// deactivated due to lost visibility.
|
||||
sway_idle_inhibit_v1_check_active();
|
||||
}
|
||||
|
||||
static void handle_session_lock_destroy(struct wl_listener *listener, void *data) {
|
||||
|
|
65
sway/main.c
65
sway/main.c
|
@ -1,5 +1,6 @@
|
|||
#include <getopt.h>
|
||||
#include <pango/pangocairo.h>
|
||||
#include <pthread.h>
|
||||
#include <signal.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
|
@ -44,10 +45,6 @@ void sway_terminate(int exit_code) {
|
|||
}
|
||||
}
|
||||
|
||||
void sig_handler(int signal) {
|
||||
sway_terminate(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
void run_as_ipc_client(char *command, char *socket_path) {
|
||||
int socketfd = ipc_open_socket(socket_path);
|
||||
uint32_t len = strlen(command);
|
||||
|
@ -125,6 +122,16 @@ static bool detect_suid(void) {
|
|||
return true;
|
||||
}
|
||||
|
||||
static void restore_nofile_limit(void) {
|
||||
if (original_nofile_rlimit.rlim_cur == 0) {
|
||||
return;
|
||||
}
|
||||
if (setrlimit(RLIMIT_NOFILE, &original_nofile_rlimit) != 0) {
|
||||
sway_log_errno(SWAY_ERROR, "Failed to restore max open files limit: "
|
||||
"setrlimit(NOFILE) failed");
|
||||
}
|
||||
}
|
||||
|
||||
static void increase_nofile_limit(void) {
|
||||
if (getrlimit(RLIMIT_NOFILE, &original_nofile_rlimit) != 0) {
|
||||
sway_log_errno(SWAY_ERROR, "Failed to bump max open files limit: "
|
||||
|
@ -139,17 +146,38 @@ static void increase_nofile_limit(void) {
|
|||
"setrlimit(NOFILE) failed");
|
||||
sway_log(SWAY_INFO, "Running with %d max open files",
|
||||
(int)original_nofile_rlimit.rlim_cur);
|
||||
}
|
||||
}
|
||||
|
||||
void restore_nofile_limit(void) {
|
||||
if (original_nofile_rlimit.rlim_cur == 0) {
|
||||
return;
|
||||
}
|
||||
if (setrlimit(RLIMIT_NOFILE, &original_nofile_rlimit) != 0) {
|
||||
sway_log_errno(SWAY_ERROR, "Failed to restore max open files limit: "
|
||||
"setrlimit(NOFILE) failed");
|
||||
}
|
||||
|
||||
pthread_atfork(NULL, NULL, restore_nofile_limit);
|
||||
}
|
||||
|
||||
static int term_signal(int signal, void *data) {
|
||||
sway_terminate(EXIT_SUCCESS);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void restore_signals(void) {
|
||||
sigset_t set;
|
||||
sigemptyset(&set);
|
||||
sigprocmask(SIG_SETMASK, &set, NULL);
|
||||
|
||||
struct sigaction sa_dfl = { .sa_handler = SIG_DFL };
|
||||
sigaction(SIGCHLD, &sa_dfl, NULL);
|
||||
sigaction(SIGPIPE, &sa_dfl, NULL);
|
||||
}
|
||||
|
||||
static void init_signals(void) {
|
||||
wl_event_loop_add_signal(server.wl_event_loop, SIGTERM, term_signal, NULL);
|
||||
wl_event_loop_add_signal(server.wl_event_loop, SIGINT, term_signal, NULL);
|
||||
|
||||
struct sigaction sa_ign = { .sa_handler = SIG_IGN };
|
||||
// avoid need to reap children
|
||||
sigaction(SIGCHLD, &sa_ign, NULL);
|
||||
// prevent ipc write errors from crashing sway
|
||||
sigaction(SIGPIPE, &sa_ign, NULL);
|
||||
|
||||
pthread_atfork(NULL, NULL, restore_signals);
|
||||
}
|
||||
|
||||
void enable_debug_flag(const char *flag) {
|
||||
|
@ -161,8 +189,6 @@ void enable_debug_flag(const char *flag) {
|
|||
debug.txn_timings = true;
|
||||
} else if (has_prefix(flag, "txn-timeout=")) {
|
||||
server.txn_timeout_ms = atoi(&flag[strlen("txn-timeout=")]);
|
||||
} else if (strcmp(flag, "legacy-wl-drm") == 0) {
|
||||
debug.legacy_wl_drm = true;
|
||||
} else {
|
||||
sway_log(SWAY_ERROR, "Unknown debug flag: %s", flag);
|
||||
}
|
||||
|
@ -322,19 +348,14 @@ int main(int argc, char **argv) {
|
|||
|
||||
increase_nofile_limit();
|
||||
|
||||
// handle SIGTERM signals
|
||||
signal(SIGTERM, sig_handler);
|
||||
signal(SIGINT, sig_handler);
|
||||
|
||||
// prevent ipc from crashing sway
|
||||
signal(SIGPIPE, SIG_IGN);
|
||||
|
||||
sway_log(SWAY_INFO, "Starting sway version " SWAY_VERSION);
|
||||
|
||||
if (!server_init(&server)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
init_signals();
|
||||
|
||||
if (server.linux_dmabuf_v1) {
|
||||
wlr_scene_set_linux_dmabuf_v1(root->root_scene, server.linux_dmabuf_v1);
|
||||
}
|
||||
|
|
|
@ -14,11 +14,13 @@
|
|||
#include <wlr/types/wlr_content_type_v1.h>
|
||||
#include <wlr/types/wlr_cursor_shape_v1.h>
|
||||
#include <wlr/types/wlr_data_control_v1.h>
|
||||
#include <wlr/types/wlr_ext_data_control_v1.h>
|
||||
#include <wlr/types/wlr_data_device.h>
|
||||
#include <wlr/types/wlr_drm.h>
|
||||
#include <wlr/types/wlr_export_dmabuf_v1.h>
|
||||
#include <wlr/types/wlr_ext_foreign_toplevel_list_v1.h>
|
||||
#include <wlr/types/wlr_foreign_toplevel_management_v1.h>
|
||||
#include <wlr/types/wlr_ext_image_capture_source_v1.h>
|
||||
#include <wlr/types/wlr_ext_image_copy_capture_v1.h>
|
||||
#include <wlr/types/wlr_fractional_scale_v1.h>
|
||||
#include <wlr/types/wlr_gamma_control_v1.h>
|
||||
#include <wlr/types/wlr_idle_notify_v1.h>
|
||||
|
@ -106,8 +108,10 @@ static bool is_privileged(const struct wl_global *global) {
|
|||
global == server.input_method->global ||
|
||||
global == server.foreign_toplevel_list->global ||
|
||||
global == server.foreign_toplevel_manager->global ||
|
||||
global == server.data_control_manager_v1->global ||
|
||||
global == server.wlr_data_control_manager_v1->global ||
|
||||
global == server.ext_data_control_manager_v1->global ||
|
||||
global == server.screencopy_manager_v1->global ||
|
||||
global == server.ext_image_copy_capture_manager_v1->global ||
|
||||
global == server.export_dmabuf_manager_v1->global ||
|
||||
global == server.security_context_manager_v1->global ||
|
||||
global == server.gamma_control_manager_v1->global ||
|
||||
|
@ -177,11 +181,11 @@ static void detect_proprietary(struct wlr_backend *backend, void *data) {
|
|||
drmFreeVersion(version);
|
||||
}
|
||||
|
||||
static void handle_renderer_lost(struct wl_listener *listener, void *data) {
|
||||
struct sway_server *server = wl_container_of(listener, server, renderer_lost);
|
||||
static void do_renderer_recreate(void *data) {
|
||||
struct sway_server *server = data;
|
||||
server->recreating_renderer = NULL;
|
||||
|
||||
sway_log(SWAY_INFO, "Re-creating renderer after GPU reset");
|
||||
|
||||
struct wlr_renderer *renderer = wlr_renderer_autocreate(server->backend);
|
||||
if (renderer == NULL) {
|
||||
sway_log(SWAY_ERROR, "Unable to create renderer");
|
||||
|
@ -216,12 +220,25 @@ static void handle_renderer_lost(struct wl_listener *listener, void *data) {
|
|||
wlr_renderer_destroy(old_renderer);
|
||||
}
|
||||
|
||||
static void handle_renderer_lost(struct wl_listener *listener, void *data) {
|
||||
struct sway_server *server = wl_container_of(listener, server, renderer_lost);
|
||||
|
||||
if (server->recreating_renderer != NULL) {
|
||||
sway_log(SWAY_DEBUG, "Re-creation of renderer already scheduled");
|
||||
return;
|
||||
}
|
||||
|
||||
sway_log(SWAY_INFO, "Scheduling re-creation of renderer after GPU reset");
|
||||
server->recreating_renderer = wl_event_loop_add_idle(server->wl_event_loop, do_renderer_recreate, server);
|
||||
}
|
||||
|
||||
bool server_init(struct sway_server *server) {
|
||||
sway_log(SWAY_DEBUG, "Initializing Wayland server");
|
||||
server->wl_display = wl_display_create();
|
||||
server->wl_event_loop = wl_display_get_event_loop(server->wl_display);
|
||||
|
||||
wl_display_set_global_filter(server->wl_display, filter_global, NULL);
|
||||
wl_display_set_default_max_buffer_size(server->wl_display, 1024 * 1024);
|
||||
|
||||
root = root_create(server->wl_display);
|
||||
|
||||
|
@ -247,9 +264,6 @@ bool server_init(struct sway_server *server) {
|
|||
if (wlr_renderer_get_texture_formats(server->renderer, WLR_BUFFER_CAP_DMABUF) != NULL) {
|
||||
server->linux_dmabuf_v1 = wlr_linux_dmabuf_v1_create_with_renderer(
|
||||
server->wl_display, 4, server->renderer);
|
||||
if (debug.legacy_wl_drm) {
|
||||
wlr_drm_create(server->wl_display, server->renderer);
|
||||
}
|
||||
}
|
||||
if (wlr_renderer_get_drm_fd(server->renderer) >= 0 &&
|
||||
server->renderer->features.timeline &&
|
||||
|
@ -370,7 +384,10 @@ bool server_init(struct sway_server *server) {
|
|||
|
||||
server->export_dmabuf_manager_v1 = wlr_export_dmabuf_manager_v1_create(server->wl_display);
|
||||
server->screencopy_manager_v1 = wlr_screencopy_manager_v1_create(server->wl_display);
|
||||
server->data_control_manager_v1 = wlr_data_control_manager_v1_create(server->wl_display);
|
||||
server->ext_image_copy_capture_manager_v1 = wlr_ext_image_copy_capture_manager_v1_create(server->wl_display, 1);
|
||||
wlr_ext_output_image_capture_source_manager_v1_create(server->wl_display, 1);
|
||||
server->wlr_data_control_manager_v1 = wlr_data_control_manager_v1_create(server->wl_display);
|
||||
server->ext_data_control_manager_v1 = wlr_ext_data_control_manager_v1_create(server->wl_display, 1);
|
||||
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);
|
||||
|
@ -451,9 +468,35 @@ bool server_init(struct sway_server *server) {
|
|||
}
|
||||
|
||||
void server_fini(struct sway_server *server) {
|
||||
// remove listeners
|
||||
wl_list_remove(&server->renderer_lost.link);
|
||||
wl_list_remove(&server->new_output.link);
|
||||
wl_list_remove(&server->layer_shell_surface.link);
|
||||
wl_list_remove(&server->xdg_shell_toplevel.link);
|
||||
wl_list_remove(&server->server_decoration.link);
|
||||
wl_list_remove(&server->xdg_decoration.link);
|
||||
wl_list_remove(&server->pointer_constraint.link);
|
||||
wl_list_remove(&server->output_manager_apply.link);
|
||||
wl_list_remove(&server->output_manager_test.link);
|
||||
wl_list_remove(&server->output_power_manager_set_mode.link);
|
||||
#if WLR_HAS_DRM_BACKEND
|
||||
if (server->drm_lease_manager) {
|
||||
wl_list_remove(&server->drm_lease_request.link);
|
||||
}
|
||||
#endif
|
||||
wl_list_remove(&server->tearing_control_new_object.link);
|
||||
wl_list_remove(&server->xdg_activation_v1_request_activate.link);
|
||||
wl_list_remove(&server->xdg_activation_v1_new_token.link);
|
||||
wl_list_remove(&server->request_set_cursor_shape.link);
|
||||
input_manager_finish(server->input);
|
||||
|
||||
// TODO: free sway-specific resources
|
||||
#if WLR_HAS_XWAYLAND
|
||||
wlr_xwayland_destroy(server->xwayland.wlr_xwayland);
|
||||
if (server->xwayland.wlr_xwayland != NULL) {
|
||||
wl_list_remove(&server->xwayland_surface.link);
|
||||
wl_list_remove(&server->xwayland_ready.link);
|
||||
wlr_xwayland_destroy(server->xwayland.wlr_xwayland);
|
||||
}
|
||||
#endif
|
||||
wl_display_destroy_clients(server->wl_display);
|
||||
wlr_backend_destroy(server->backend);
|
||||
|
|
|
@ -143,6 +143,12 @@ runtime.
|
|||
|
||||
This setting also applies to the current binding mode indicator.
|
||||
|
||||
The following commands may only be used at runtime.
|
||||
|
||||
*mode* toggle [<bar_id>]
|
||||
Toggles the current mode between _hide_ and _dock_. Any other mode
|
||||
is treated as _hide_.
|
||||
|
||||
## TRAY
|
||||
|
||||
Swaybar provides a system tray where third-party applications may place icons.
|
||||
|
|
|
@ -138,7 +138,7 @@ has the following properties:
|
|||
: Whether the workspace is currently focused by the default seat (_seat0_)
|
||||
|- urgent
|
||||
: boolean
|
||||
: Whether a view on the workspace has the urgent flag set
|
||||
: Whether a window on the workspace has the urgent flag set
|
||||
|- rect
|
||||
: object
|
||||
: The bounds of the workspace. It consists of _x_, _y_, _width_, and _height_
|
||||
|
@ -374,7 +374,7 @@ node and will have the following properties:
|
|||
that can be used as an aid in submitting reproduction steps for bug reports
|
||||
|- fullscreen_mode
|
||||
: integer
|
||||
: (Only containers and views) The fullscreen mode of the node. 0 means none, 1 means
|
||||
: (Only containers and windows) The fullscreen mode of the node. 0 means none, 1 means
|
||||
full workspace, and 2 means global fullscreen
|
||||
|- floating
|
||||
: string
|
||||
|
@ -384,32 +384,45 @@ node and will have the following properties:
|
|||
: Whether the window is in the scratchpad. Can be either "none" or "fresh"
|
||||
|- app_id
|
||||
: string
|
||||
: (Only views) For an xdg-shell view, the name of the application, if set.
|
||||
: (Only windows) For an xdg-shell window, the name of the application, if set.
|
||||
Otherwise, _null_
|
||||
|- pid
|
||||
: integer
|
||||
: (Only views) The PID of the application that owns the view
|
||||
: (Only windows) The PID of the application that owns the window
|
||||
|- foreign_toplevel_identifier
|
||||
: string
|
||||
: (Only windows) The ext-foreign-toplevel-list-v1 toplevel identifier of this node.
|
||||
|- visible
|
||||
: boolean
|
||||
: (Only views) Whether the node is visible
|
||||
: (Only windows) Whether the node is visible
|
||||
|- shell
|
||||
: string
|
||||
: (Only views) The shell of the view, such as _xdg\_shell_ or _xwayland_
|
||||
: (Only windows) The shell of the window, such as _xdg\_shell_ or _xwayland_
|
||||
|- inhibit_idle
|
||||
: boolean
|
||||
: (Only views) Whether the view is inhibiting the idle state
|
||||
: (Only windows) Whether the window is inhibiting the idle state
|
||||
|- idle_inhibitors
|
||||
: object
|
||||
: (Only views) An object containing the state of the _application_ and _user_ idle inhibitors.
|
||||
: (Only windows) 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 windows) The associated sandbox engine (or _null_)
|
||||
|- sandbox_app_id
|
||||
: string
|
||||
: (Only windows) The app ID provided by the associated sandbox engine (or _null_)
|
||||
|- sandbox_instance_id
|
||||
: string
|
||||
: (Only windows) The instance ID provided by the associated sandbox engine (or
|
||||
_null_)
|
||||
|- window
|
||||
: integer
|
||||
: (Only xwayland views) The X11 window ID for the xwayland view
|
||||
: (Only xwayland windows) The X11 window ID for the xwayland window
|
||||
|- window_properties
|
||||
: object
|
||||
: (Only xwayland views) An object containing the _title_, _class_, _instance_,
|
||||
_window\_role_, _window\_type_, and _transient\_for_ for the view
|
||||
: (Only xwayland windows) An object containing the _title_, _class_, _instance_,
|
||||
_window\_role_, _window\_type_, and _transient\_for_ for the window
|
||||
|
||||
|
||||
*Example Reply:*
|
||||
|
@ -914,13 +927,13 @@ containing the _#RRGGBBAA_ representation of the color:
|
|||
that are not visible
|
||||
|- urgent_workspace_text
|
||||
: The color to use for the text of the workspace buttons for workspaces that
|
||||
contain an urgent view
|
||||
contain an urgent window
|
||||
|- urgent_workspace_bg
|
||||
: The color to use for the background of the workspace buttons for workspaces
|
||||
that contain an urgent view
|
||||
that contain an urgent window
|
||||
|- urgent_workspace_border
|
||||
: The color to use for the border of the workspace buttons for workspaces that
|
||||
contain an urgent view
|
||||
contain an urgent window
|
||||
|- binding_mode_text
|
||||
: The color to use for the text of the binding mode indicator
|
||||
|- binding_mode_bg
|
||||
|
@ -1467,7 +1480,7 @@ available:
|
|||
: Sent whenever the binding mode changes
|
||||
|- 0x80000003
|
||||
: window
|
||||
: Sent whenever an event involving a view occurs such as being reparented,
|
||||
: Sent whenever an event involving a window occurs such as being reparented,
|
||||
focused, or closed
|
||||
|- 0x80000004
|
||||
: barconfig_update
|
||||
|
@ -1523,8 +1536,8 @@ The following change types are currently available:
|
|||
|- rename
|
||||
: The workspace was renamed
|
||||
|- urgent
|
||||
: A view on the workspace has had their urgency hint set or all urgency hints
|
||||
for views on the workspace have been cleared
|
||||
: A window on the workspace has had their urgency hint set or all urgency hints
|
||||
for windows on the workspace have been cleared
|
||||
|- reload
|
||||
: The configuration file has been reloaded
|
||||
|
||||
|
@ -1622,7 +1635,7 @@ with the following properties:
|
|||
|
||||
## 0x80000003. WINDOW
|
||||
|
||||
Sent whenever a change involving a view occurs. The event consists of a single
|
||||
Sent whenever a change involving a window occurs. The event consists of a single
|
||||
object with the following properties:
|
||||
|
||||
[- *PROPERTY*
|
||||
|
@ -1633,30 +1646,30 @@ object with the following properties:
|
|||
:[ The type of change that occurred. See below for more information
|
||||
|- container
|
||||
: object
|
||||
: An object representing the view effected
|
||||
: An object representing the window effected
|
||||
|
||||
|
||||
The following change types are currently available:
|
||||
[- *TYPE*
|
||||
:- *DESCRIPTION*
|
||||
|- new
|
||||
:[ The view was created
|
||||
:[ The window was created
|
||||
|- close
|
||||
: The view was closed
|
||||
: The window was closed
|
||||
|- focus
|
||||
: The view was focused
|
||||
: The window was focused
|
||||
|- title
|
||||
: The view's title has changed
|
||||
: The window's title has changed
|
||||
|- fullscreen_mode
|
||||
: The view's fullscreen mode has changed
|
||||
: The window's fullscreen mode has changed
|
||||
|- move
|
||||
: The view has been reparented in the tree
|
||||
: The window has been reparented in the tree
|
||||
|- floating
|
||||
: The view has become floating or is no longer floating
|
||||
: The window has become floating or is no longer floating
|
||||
|- urgent
|
||||
: The view's urgency hint has changed status
|
||||
: The window's urgency hint has changed status
|
||||
|- mark
|
||||
: A mark has been added or removed from the view
|
||||
: A mark has been added or removed from the window
|
||||
|
||||
|
||||
*Example Event:*
|
||||
|
|
127
sway/sway.5.scd
127
sway/sway.5.scd
|
@ -117,7 +117,7 @@ They are expected to be used with *bindsym* or at runtime through *swaymsg*(1).
|
|||
Exit sway and end your Wayland session.
|
||||
|
||||
*floating* enable|disable|toggle
|
||||
Make focused view floating, non-floating, or the opposite of what it is now.
|
||||
Make focused window floating, non-floating, or the opposite of what it is now.
|
||||
|
||||
<criteria> *focus*
|
||||
Moves focus to the container that matches the specified criteria.
|
||||
|
@ -152,9 +152,9 @@ They are expected to be used with *bindsym* or at runtime through *swaymsg*(1).
|
|||
Moves focus between the floating and tiled layers.
|
||||
|
||||
*fullscreen* [enable|disable|toggle] [global]
|
||||
Makes focused view fullscreen, non-fullscreen, or the opposite of what it
|
||||
Makes focused window fullscreen, non-fullscreen, or the opposite of what it
|
||||
is now. If no argument is given, it does the same as _toggle_. If _global_
|
||||
is specified, the view will be fullscreen across all outputs.
|
||||
is specified, the window will be fullscreen across all outputs.
|
||||
|
||||
*gaps* inner|outer|horizontal|vertical|top|right|bottom|left all|current
|
||||
set|plus|minus|toggle <amount>
|
||||
|
@ -164,16 +164,16 @@ set|plus|minus|toggle <amount>
|
|||
_vertical_.
|
||||
|
||||
*inhibit_idle* focus|fullscreen|open|none|visible
|
||||
Set/unset an idle inhibitor for the view. _focus_ will inhibit idle when
|
||||
the view is focused by any seat. _fullscreen_ will inhibit idle when the
|
||||
Set/unset an idle inhibitor for the window. _focus_ will inhibit idle when
|
||||
the window is focused by any seat. _fullscreen_ will inhibit idle when the
|
||||
view is fullscreen (or a descendant of a fullscreen container) and is
|
||||
visible. _open_ will inhibit idle until the view is closed (or the
|
||||
inhibitor is unset/changed). _visible_ will inhibit idle when the view is
|
||||
visible. _open_ will inhibit idle until the window is closed (or the
|
||||
inhibitor is unset/changed). _visible_ will inhibit idle when the window is
|
||||
visible on any output. _none_ will remove any existing idle inhibitor for
|
||||
the view.
|
||||
the window.
|
||||
|
||||
This can also be used with criteria to set an idle inhibitor for any
|
||||
existing view or with _for_window_ to set idle inhibitors for future views.
|
||||
existing window or with _for_window_ to set idle inhibitors for future windows.
|
||||
|
||||
*layout* default|splith|splitv|stacking|tabbed
|
||||
Sets the layout mode of the focused container.
|
||||
|
@ -331,12 +331,12 @@ set|plus|minus|toggle <amount>
|
|||
|
||||
*shortcuts_inhibitor* enable|disable
|
||||
Enables or disables the ability of clients to inhibit keyboard
|
||||
shortcuts for a view. This is primarily useful for virtualization and
|
||||
remote desktop software. It affects either the currently focused view
|
||||
or a set of views selected by criteria. Subcommand _disable_
|
||||
additionally deactivates any active inhibitors for the given view(s).
|
||||
shortcuts for a window. This is primarily useful for virtualization and
|
||||
remote desktop software. It affects either the currently focused window
|
||||
or a set of windows selected by criteria. Subcommand _disable_
|
||||
additionally deactivates any active inhibitors for the given window(s).
|
||||
Criteria are particularly useful with the *for_window* command to
|
||||
configure a class of views differently from the per-seat defaults
|
||||
configure a class of windows differently from the per-seat defaults
|
||||
established by the *seat* subcommand of the same name. See
|
||||
*sway-input*(5) for more ways to affect inhibitors.
|
||||
|
||||
|
@ -364,7 +364,7 @@ set|plus|minus|toggle <amount>
|
|||
Swaps the position, geometry, and fullscreen status of two containers. The
|
||||
first container can be selected either by criteria or focus. The second
|
||||
container can be selected by _id_, _con_id_, or _mark_. _id_ can only be
|
||||
used with xwayland views. If the first container has focus, it will retain
|
||||
used with xwayland windows. If the first container has focus, it will retain
|
||||
focus unless it is moved to a different workspace or the second container
|
||||
becomes fullscreen on the same workspace as the first container. In either
|
||||
of those cases, the second container will gain focus.
|
||||
|
@ -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:
|
||||
|
||||
|
@ -392,14 +409,14 @@ The following commands may be used either in the configuration file or at
|
|||
runtime.
|
||||
|
||||
*assign* <criteria> [→] [workspace] [number] <workspace>
|
||||
Assigns views matching _criteria_ (see *CRITERIA* for details) to
|
||||
Assigns windows matching _criteria_ (see *CRITERIA* for details) to
|
||||
_workspace_. The → (U+2192) is optional and cosmetic. This command is
|
||||
equivalent to:
|
||||
|
||||
for_window <criteria> move container to workspace <workspace>
|
||||
|
||||
*assign* <criteria> [→] output left|right|up|down|<name>
|
||||
Assigns views matching _criteria_ (see *CRITERIA* for details) to the
|
||||
Assigns windows matching _criteria_ (see *CRITERIA* for details) to the
|
||||
specified output. The → (U+2192) is optional and cosmetic. This command is
|
||||
equivalent to:
|
||||
|
||||
|
@ -582,10 +599,10 @@ runtime.
|
|||
The window that has focus.
|
||||
|
||||
*client.focused_inactive*
|
||||
The most recently focused view within a container which is not focused.
|
||||
The most recently focused window within a container which is not focused.
|
||||
|
||||
*client.focused_tab_title*
|
||||
A view that has focused descendant container.
|
||||
A window that has focused descendant container.
|
||||
Tab or stack container title that is the parent of the focused container
|
||||
but is not directly focused. Defaults to focused_inactive if not
|
||||
specified and does not use the indicator and child_border colors.
|
||||
|
@ -594,10 +611,10 @@ runtime.
|
|||
Ignored (present for i3 compatibility).
|
||||
|
||||
*client.unfocused*
|
||||
A view that does not have focus.
|
||||
A window that does not have focus.
|
||||
|
||||
*client.urgent*
|
||||
A view with an urgency hint. *Note*: Native Wayland windows do not
|
||||
A window with an urgency hint. *Note*: Native Wayland windows do not
|
||||
support urgency. Urgency only works for Xwayland windows.
|
||||
|
||||
The meaning of each color is:
|
||||
|
@ -612,12 +629,12 @@ runtime.
|
|||
The text color of the title bar.
|
||||
|
||||
_indicator_
|
||||
The color used to indicate where a new view will open. In a tiled
|
||||
container, this would paint the right border of the current view if a
|
||||
new view would be opened to the right.
|
||||
The color used to indicate where a new window will open. In a tiled
|
||||
container, this would paint the right border of the current window if a
|
||||
new window would be opened to the right.
|
||||
|
||||
_child_border_
|
||||
The border around the view itself.
|
||||
The border around the window itself.
|
||||
|
||||
The default colors are:
|
||||
|
||||
|
@ -755,7 +772,7 @@ The default colors are:
|
|||
|
||||
*gaps* inner|outer|horizontal|vertical|top|right|bottom|left <amount>
|
||||
Sets default _amount_ pixels of _inner_ or _outer_ gap, where the inner
|
||||
affects spacing around each view and outer affects the spacing around each
|
||||
affects spacing around each window and outer affects the spacing around each
|
||||
workspace. Outer gaps are in addition to inner gaps. To reduce or remove
|
||||
outer gaps, outer gaps can be set to a negative value. _outer_ gaps can
|
||||
also be specified per side with _top_, _right_, _bottom_, and _left_ or
|
||||
|
@ -827,9 +844,9 @@ The default colors are:
|
|||
A list of output names may be obtained via *swaymsg -t get_outputs*.
|
||||
|
||||
*popup_during_fullscreen* smart|ignore|leave_fullscreen
|
||||
Determines what to do when a fullscreen view opens a dialog.
|
||||
Determines what to do when a fullscreen window opens a dialog.
|
||||
If _smart_ (the default), the dialog will be displayed. If _ignore_, the
|
||||
dialog will not be rendered. If _leave_fullscreen_, the view will exit
|
||||
dialog will not be rendered. If _leave_fullscreen_, the window will exit
|
||||
fullscreen mode and the dialog will be rendered.
|
||||
|
||||
*primary_selection* enabled|disabled
|
||||
|
@ -955,18 +972,18 @@ The default colors are:
|
|||
A criteria is a string in the form of, for example:
|
||||
|
||||
```
|
||||
[class="[Rr]egex.*" title="some title"]
|
||||
[app_id="some-application" title="[Rr]egex.*"]
|
||||
```
|
||||
|
||||
The string contains one or more (space separated) attribute/value pairs. They
|
||||
are used by some commands to choose which views to execute actions on. All
|
||||
are used by some commands to choose which windows to execute actions on. All
|
||||
attributes must match for the criteria to match. Criteria is retained across
|
||||
commands separated by a *,*, but will be reset (and allow for new criteria, if
|
||||
desired) for commands separated by a *;*.
|
||||
|
||||
Criteria may be used with either the *for_window* or *assign* commands to
|
||||
specify operations to perform on new views. A criteria may also be used to
|
||||
perform specific commands (ones that normally act upon one window) on all views
|
||||
specify operations to perform on new windows. A criteria may also be used to
|
||||
perform specific commands (ones that normally act upon one window) on all windows
|
||||
that match that criteria. For example:
|
||||
|
||||
Focus on a window with the mark "IRC":
|
||||
|
@ -975,10 +992,19 @@ Focus on a window with the mark "IRC":
|
|||
[con_mark="IRC"] focus
|
||||
```
|
||||
|
||||
Kill all windows with the title "Emacs":
|
||||
Kill all windows where the title contains "Emacs":
|
||||
|
||||
```
|
||||
[class="Emacs"] kill
|
||||
[title="Emacs"] kill
|
||||
```
|
||||
|
||||
Several attributes allow regular expressions. These use Perl-compatible regular
|
||||
expressions (PCRE2), which are documented in *pcre2pattern*(3) and summarized in
|
||||
*pcre2syntax*(3). For example, this moves all windows with titles ending in
|
||||
"sway" or "Sway" to workspace 1:
|
||||
|
||||
```
|
||||
[title="[Ss]way$"] move workspace 1
|
||||
```
|
||||
|
||||
You may like to use swaymsg -t get_tree for finding the values of these
|
||||
|
@ -1054,10 +1080,27 @@ The following attributes may be matched with:
|
|||
applications and requires XWayland.
|
||||
|
||||
*workspace*
|
||||
Compare against the workspace name for this view. Can be a regular
|
||||
expression. If the value is \_\_focused\_\_, then all the views on the
|
||||
Compare against the workspace name for this window. Can be a regular
|
||||
expression. If the value is \_\_focused\_\_, then all the windows 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*
|
||||
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)
|
||||
*pcre2pattern*(3) *pcre2syntax*(3)
|
||||
|
|
|
@ -64,18 +64,6 @@ static int get_text_width(struct sway_text_node *props) {
|
|||
return MAX(width, 0);
|
||||
}
|
||||
|
||||
static void update_source_box(struct text_buffer *buffer) {
|
||||
struct sway_text_node *props = &buffer->props;
|
||||
struct wlr_fbox source_box = {
|
||||
.x = 0,
|
||||
.y = 0,
|
||||
.width = ceil(get_text_width(props) * buffer->scale),
|
||||
.height = ceil(props->height * buffer->scale),
|
||||
};
|
||||
|
||||
wlr_scene_buffer_set_source_box(buffer->buffer_node, &source_box);
|
||||
}
|
||||
|
||||
static void render_backing_buffer(struct text_buffer *buffer) {
|
||||
if (!buffer->visible) {
|
||||
return;
|
||||
|
@ -87,7 +75,7 @@ static void render_backing_buffer(struct text_buffer *buffer) {
|
|||
}
|
||||
|
||||
float scale = buffer->scale;
|
||||
int width = ceil(buffer->props.width * scale);
|
||||
int width = ceil(get_text_width(&buffer->props) * scale);
|
||||
int height = ceil(buffer->props.height * scale);
|
||||
float *color = (float *)&buffer->props.color;
|
||||
float *background = (float *)&buffer->props.background;
|
||||
|
@ -147,13 +135,12 @@ static void render_backing_buffer(struct text_buffer *buffer) {
|
|||
|
||||
wlr_scene_buffer_set_buffer(buffer->buffer_node, &cairo_buffer->base);
|
||||
wlr_buffer_drop(&cairo_buffer->base);
|
||||
update_source_box(buffer);
|
||||
|
||||
pixman_region32_t opaque;
|
||||
pixman_region32_init(&opaque);
|
||||
if (background[3] == 1) {
|
||||
pixman_region32_union_rect(&opaque, &opaque, 0, 0,
|
||||
buffer->props.width, buffer->props.height);
|
||||
get_text_width(&buffer->props), buffer->props.height);
|
||||
}
|
||||
wlr_scene_buffer_set_opaque_region(buffer->buffer_node, &opaque);
|
||||
pixman_region32_fini(&opaque);
|
||||
|
@ -300,7 +287,6 @@ void sway_text_node_set_max_width(struct sway_text_node *node, int max_width) {
|
|||
buffer->props.max_width = max_width;
|
||||
wlr_scene_buffer_set_dest_size(buffer->buffer_node,
|
||||
get_text_width(&buffer->props), buffer->props.height);
|
||||
update_source_box(buffer);
|
||||
render_backing_buffer(buffer);
|
||||
}
|
||||
|
||||
|
|
|
@ -63,36 +63,27 @@ bool swaynag_spawn(const char *swaynag_command,
|
|||
sway_log(SWAY_ERROR, "Failed to create fork for swaynag");
|
||||
goto failed;
|
||||
} else if (pid == 0) {
|
||||
restore_nofile_limit();
|
||||
|
||||
pid = fork();
|
||||
if (pid < 0) {
|
||||
sway_log_errno(SWAY_ERROR, "fork failed");
|
||||
_exit(EXIT_FAILURE);
|
||||
} else if (pid == 0) {
|
||||
if (!sway_set_cloexec(sockets[1], false)) {
|
||||
_exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (swaynag->detailed) {
|
||||
close(swaynag->fd[1]);
|
||||
dup2(swaynag->fd[0], STDIN_FILENO);
|
||||
close(swaynag->fd[0]);
|
||||
}
|
||||
|
||||
char wayland_socket_str[16];
|
||||
snprintf(wayland_socket_str, sizeof(wayland_socket_str),
|
||||
"%d", sockets[1]);
|
||||
setenv("WAYLAND_SOCKET", wayland_socket_str, true);
|
||||
|
||||
size_t length = strlen(swaynag_command) + strlen(swaynag->args) + 2;
|
||||
char *cmd = malloc(length);
|
||||
snprintf(cmd, length, "%s %s", swaynag_command, swaynag->args);
|
||||
execlp("sh", "sh", "-c", cmd, NULL);
|
||||
sway_log_errno(SWAY_ERROR, "execlp failed");
|
||||
if (!sway_set_cloexec(sockets[1], false)) {
|
||||
_exit(EXIT_FAILURE);
|
||||
}
|
||||
_exit(EXIT_SUCCESS);
|
||||
|
||||
if (swaynag->detailed) {
|
||||
close(swaynag->fd[1]);
|
||||
dup2(swaynag->fd[0], STDIN_FILENO);
|
||||
close(swaynag->fd[0]);
|
||||
}
|
||||
|
||||
char wayland_socket_str[16];
|
||||
snprintf(wayland_socket_str, sizeof(wayland_socket_str),
|
||||
"%d", sockets[1]);
|
||||
setenv("WAYLAND_SOCKET", wayland_socket_str, true);
|
||||
|
||||
size_t length = strlen(swaynag_command) + strlen(swaynag->args) + 2;
|
||||
char *cmd = malloc(length);
|
||||
snprintf(cmd, length, "%s %s", swaynag_command, swaynag->args);
|
||||
execlp("sh", "sh", "-c", cmd, NULL);
|
||||
sway_log_errno(SWAY_ERROR, "execlp failed");
|
||||
_exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (swaynag->detailed) {
|
||||
|
@ -107,11 +98,6 @@ bool swaynag_spawn(const char *swaynag_command,
|
|||
return false;
|
||||
}
|
||||
|
||||
if (waitpid(pid, NULL, 0) < 0) {
|
||||
sway_log_errno(SWAY_ERROR, "waitpid failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
failed:
|
||||
|
@ -161,4 +147,3 @@ void swaynag_show(struct swaynag_instance *swaynag) {
|
|||
close(swaynag->fd[1]);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -29,7 +29,7 @@ static void apply_horiz_layout(list_t *children, struct wlr_box *parent) {
|
|||
}
|
||||
}
|
||||
|
||||
// Calculate each height fraction
|
||||
// Calculate each width fraction
|
||||
double total_width_fraction = 0;
|
||||
for (int i = 0; i < children->length; ++i) {
|
||||
struct sway_container *child = children->items[i];
|
||||
|
@ -82,12 +82,18 @@ static void apply_horiz_layout(list_t *children, struct wlr_box *parent) {
|
|||
child->pending.y = parent->y;
|
||||
child->pending.width = round(child->width_fraction * child_total_width);
|
||||
child->pending.height = parent->height;
|
||||
child_x += child->pending.width + inner_gap;
|
||||
|
||||
// Make last child use remaining width of parent
|
||||
if (i == children->length - 1) {
|
||||
child->pending.width = parent->x + parent->width - child->pending.x;
|
||||
}
|
||||
|
||||
// Arbitrary lower bound for window size
|
||||
if (child->pending.width < 10 || child->pending.height < 10) {
|
||||
child->pending.width = 0;
|
||||
child->pending.height = 0;
|
||||
}
|
||||
child_x += child->pending.width + inner_gap;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -161,12 +167,18 @@ static void apply_vert_layout(list_t *children, struct wlr_box *parent) {
|
|||
child->pending.y = child_y;
|
||||
child->pending.width = parent->width;
|
||||
child->pending.height = round(child->height_fraction * child_total_height);
|
||||
child_y += child->pending.height + inner_gap;
|
||||
|
||||
// Make last child use remaining height of parent
|
||||
if (i == children->length - 1) {
|
||||
child->pending.height = parent->y + parent->height - child->pending.y;
|
||||
}
|
||||
|
||||
// Arbitrary lower bound for window size
|
||||
if (child->pending.width < 10 || child->pending.height < 10) {
|
||||
child->pending.width = 0;
|
||||
child->pending.height = 0;
|
||||
}
|
||||
child_y += child->pending.height + inner_gap;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -50,6 +50,14 @@ static void handle_output_leave(
|
|||
}
|
||||
}
|
||||
|
||||
static void handle_destroy(
|
||||
struct wl_listener *listener, void *data) {
|
||||
struct sway_container *con = wl_container_of(
|
||||
listener, con, output_handler_destroy);
|
||||
|
||||
container_begin_destroy(con);
|
||||
}
|
||||
|
||||
static bool handle_point_accepts_input(
|
||||
struct wlr_scene_buffer *buffer, double *x, double *y) {
|
||||
return false;
|
||||
|
@ -135,6 +143,9 @@ struct sway_container *container_create(struct sway_view *view) {
|
|||
c->output_leave.notify = handle_output_leave;
|
||||
wl_signal_add(&c->output_handler->events.output_leave,
|
||||
&c->output_leave);
|
||||
c->output_handler_destroy.notify = handle_destroy;
|
||||
wl_signal_add(&c->output_handler->node.events.destroy,
|
||||
&c->output_handler_destroy);
|
||||
c->output_handler->point_accepts_input = handle_point_accepts_input;
|
||||
}
|
||||
}
|
||||
|
@ -508,8 +519,6 @@ void container_destroy(struct sway_container *con) {
|
|||
|
||||
if (con->view && con->view->container == con) {
|
||||
con->view->container = NULL;
|
||||
wl_list_remove(&con->output_enter.link);
|
||||
wl_list_remove(&con->output_leave.link);
|
||||
wlr_scene_node_destroy(&con->output_handler->node);
|
||||
if (con->view->destroying) {
|
||||
view_destroy(con->view);
|
||||
|
@ -552,6 +561,12 @@ void container_begin_destroy(struct sway_container *con) {
|
|||
if (con->pending.parent || con->pending.workspace) {
|
||||
container_detach(con);
|
||||
}
|
||||
|
||||
if (con->view && con->view->container == con) {
|
||||
wl_list_remove(&con->output_enter.link);
|
||||
wl_list_remove(&con->output_leave.link);
|
||||
wl_list_remove(&con->output_handler_destroy.link);
|
||||
}
|
||||
}
|
||||
|
||||
void container_reap_empty(struct sway_container *con) {
|
||||
|
@ -716,6 +731,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;
|
||||
|
|
|
@ -8,9 +8,11 @@
|
|||
#include <wlr/types/wlr_foreign_toplevel_management_v1.h>
|
||||
#include <wlr/types/wlr_fractional_scale_v1.h>
|
||||
#include <wlr/types/wlr_output_layout.h>
|
||||
#include <wlr/types/wlr_security_context_v1.h>
|
||||
#include <wlr/types/wlr_server_decoration.h>
|
||||
#include <wlr/types/wlr_subcompositor.h>
|
||||
#include <wlr/types/wlr_xdg_decoration_v1.h>
|
||||
#include <wlr/types/wlr_session_lock_v1.h>
|
||||
#if WLR_HAS_XWAYLAND
|
||||
#include <wlr/xwayland.h>
|
||||
#endif
|
||||
|
@ -154,6 +156,34 @@ uint32_t view_get_window_type(struct sway_view *view) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
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);
|
||||
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;
|
||||
}
|
||||
|
||||
const char *view_get_sandbox_engine(struct sway_view *view) {
|
||||
const struct wlr_security_context_v1_state *security_context =
|
||||
security_context_from_view(view);
|
||||
return security_context ? security_context->sandbox_engine : NULL;
|
||||
}
|
||||
|
||||
const char *view_get_sandbox_app_id(struct sway_view *view) {
|
||||
const struct wlr_security_context_v1_state *security_context =
|
||||
security_context_from_view(view);
|
||||
return security_context ? security_context->app_id : NULL;
|
||||
}
|
||||
|
||||
const char *view_get_sandbox_instance_id(struct sway_view *view) {
|
||||
const struct wlr_security_context_v1_state *security_context =
|
||||
security_context_from_view(view);
|
||||
return security_context ? security_context->instance_id : NULL;
|
||||
}
|
||||
|
||||
const char *view_get_shell(struct sway_view *view) {
|
||||
switch(view->type) {
|
||||
case SWAY_VIEW_XDG_SHELL:
|
||||
|
@ -188,6 +218,10 @@ uint32_t view_configure(struct sway_view *view, double lx, double ly, int width,
|
|||
}
|
||||
|
||||
bool view_inhibit_idle(struct sway_view *view) {
|
||||
if (server.session_lock.lock) {
|
||||
return false;
|
||||
}
|
||||
|
||||
struct sway_idle_inhibitor_v1 *user_inhibitor =
|
||||
sway_idle_inhibit_v1_user_inhibitor_for_view(view);
|
||||
|
||||
|
@ -981,6 +1015,9 @@ struct sway_view *view_from_wlr_surface(struct wlr_surface *wlr_surface) {
|
|||
if (wlr_layer_surface_v1_try_from_wlr_surface(wlr_surface) != NULL) {
|
||||
return NULL;
|
||||
}
|
||||
if (wlr_session_lock_surface_v1_try_from_wlr_surface(wlr_surface) != NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char *role = wlr_surface->role ? wlr_surface->role->name : NULL;
|
||||
sway_log(SWAY_DEBUG, "Surface of unknown type (role %s): %p",
|
||||
|
|
|
@ -46,7 +46,7 @@ void ipc_send_workspace_command(struct swaybar *bar, const char *ws) {
|
|||
|
||||
char *parse_font(const char *font) {
|
||||
char *new_font = NULL;
|
||||
if (has_prefix("pango:", font)) {
|
||||
if (has_prefix(font, "pango:")) {
|
||||
font += strlen("pango:");
|
||||
}
|
||||
new_font = strdup(font);
|
||||
|
|
|
@ -93,8 +93,9 @@ int main(int argc, char **argv) {
|
|||
|
||||
free(socket_path);
|
||||
|
||||
signal(SIGINT, sig_handler);
|
||||
signal(SIGTERM, sig_handler);
|
||||
struct sigaction sa = { .sa_handler = sig_handler };
|
||||
sigaction(SIGINT, &sa, NULL);
|
||||
sigaction(SIGTERM, &sa, NULL);
|
||||
|
||||
swaybar.running = true;
|
||||
bar_run(&swaybar);
|
||||
|
|
|
@ -16,10 +16,6 @@
|
|||
#include "ipc-client.h"
|
||||
#include "log.h"
|
||||
|
||||
void sway_terminate(int exit_code) {
|
||||
exit(exit_code);
|
||||
}
|
||||
|
||||
static bool success_object(json_object *result) {
|
||||
json_object *success;
|
||||
|
||||
|
@ -99,7 +95,7 @@ static const char *pretty_type_name(const char *name) {
|
|||
const char *b;
|
||||
} type_names[] = {
|
||||
{ "keyboard", "Keyboard" },
|
||||
{ "pointer", "Mouse" },
|
||||
{ "pointer", "Pointer" },
|
||||
{ "touchpad", "Touchpad" },
|
||||
{ "tablet_pad", "Tablet pad" },
|
||||
{ "tablet_tool", "Tablet tool" },
|
||||
|
@ -330,6 +326,10 @@ 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 *foreign_toplevel_id = json_object_get_string(json_object_object_get(obj, "foreign_toplevel_identifier"));
|
||||
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) {
|
||||
|
@ -344,6 +344,18 @@ static void pretty_print_tree(json_object *obj, int indent) {
|
|||
if (x11_id != 0) {
|
||||
printf(", X11 window: 0x%X", x11_id);
|
||||
}
|
||||
if (foreign_toplevel_id != NULL) {
|
||||
printf(", foreign_toplevel_id: \"%s\"", foreign_toplevel_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(")");
|
||||
}
|
||||
|
||||
|
|
|
@ -13,11 +13,6 @@ void sig_handler(int signal) {
|
|||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
void sway_terminate(int code) {
|
||||
swaynag_destroy(&swaynag);
|
||||
exit(code);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
int status = EXIT_SUCCESS;
|
||||
|
||||
|
@ -107,7 +102,8 @@ int main(int argc, char **argv) {
|
|||
sway_log(SWAY_DEBUG, "\t[%s] `%s`", button->text, button->action);
|
||||
}
|
||||
|
||||
signal(SIGTERM, sig_handler);
|
||||
struct sigaction sa = { .sa_handler = sig_handler };
|
||||
sigaction(SIGTERM, &sa, NULL);
|
||||
|
||||
swaynag_setup(&swaynag);
|
||||
swaynag_run(&swaynag);
|
||||
|
|
Loading…
Add table
Reference in a new issue