mirror of
https://github.com/swaywm/sway.git
synced 2026-04-17 06:46:32 -04:00
Merge branch 'master' into master
This commit is contained in:
commit
6894fe6fd6
43 changed files with 453 additions and 271 deletions
|
|
@ -46,14 +46,18 @@ output * bg @datadir@/backgrounds/sway/Sway_Wallpaper_Blue_1920x1080.png fill
|
||||||
#
|
#
|
||||||
# Example configuration:
|
# Example configuration:
|
||||||
#
|
#
|
||||||
# input "2:14:SynPS/2_Synaptics_TouchPad" {
|
# input type:touchpad {
|
||||||
# dwt enabled
|
# dwt enabled
|
||||||
# tap enabled
|
# tap enabled
|
||||||
# natural_scroll enabled
|
# natural_scroll enabled
|
||||||
# middle_emulation enabled
|
# middle_emulation enabled
|
||||||
# }
|
# }
|
||||||
#
|
#
|
||||||
# You can get the names of your inputs by running: swaymsg -t get_inputs
|
# input type:keyboard {
|
||||||
|
# xkb_layout "eu"
|
||||||
|
# }
|
||||||
|
#
|
||||||
|
# You can also configure each device individually.
|
||||||
# Read `man 5 sway-input` for more information about this section.
|
# Read `man 5 sway-input` for more information about this section.
|
||||||
|
|
||||||
### Key bindings
|
### Key bindings
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@ enum sway_idle_inhibit_mode {
|
||||||
struct sway_idle_inhibit_manager_v1 {
|
struct sway_idle_inhibit_manager_v1 {
|
||||||
struct wlr_idle_inhibit_manager_v1 *wlr_manager;
|
struct wlr_idle_inhibit_manager_v1 *wlr_manager;
|
||||||
struct wl_listener new_idle_inhibitor_v1;
|
struct wl_listener new_idle_inhibitor_v1;
|
||||||
|
struct wl_listener manager_destroy;
|
||||||
struct wl_list inhibitors;
|
struct wl_list inhibitors;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -39,6 +39,8 @@ struct sway_input_manager {
|
||||||
|
|
||||||
struct sway_input_manager *input_manager_create(struct sway_server *server);
|
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);
|
bool input_manager_has_focus(struct sway_node *node);
|
||||||
|
|
||||||
void input_manager_set_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 wlr_input_method_v2 *input_method; // doesn't have to be present
|
||||||
|
|
||||||
struct wl_listener text_input_new;
|
struct wl_listener text_input_new;
|
||||||
|
struct wl_listener text_input_manager_destroy;
|
||||||
|
|
||||||
struct wl_listener input_method_new;
|
struct wl_listener input_method_new;
|
||||||
|
struct wl_listener input_method_manager_destroy;
|
||||||
struct wl_listener input_method_commit;
|
struct wl_listener input_method_commit;
|
||||||
struct wl_listener input_method_new_popup_surface;
|
struct wl_listener input_method_new_popup_surface;
|
||||||
struct wl_listener input_method_grab_keyboard;
|
struct wl_listener input_method_grab_keyboard;
|
||||||
|
|
|
||||||
|
|
@ -46,6 +46,7 @@ struct sway_server {
|
||||||
|
|
||||||
struct wl_listener new_output;
|
struct wl_listener new_output;
|
||||||
struct wl_listener renderer_lost;
|
struct wl_listener renderer_lost;
|
||||||
|
struct wl_event_source *recreating_renderer;
|
||||||
|
|
||||||
struct wlr_idle_notifier_v1 *idle_notifier_v1;
|
struct wlr_idle_notifier_v1 *idle_notifier_v1;
|
||||||
struct sway_idle_inhibit_manager_v1 idle_inhibit_manager_v1;
|
struct sway_idle_inhibit_manager_v1 idle_inhibit_manager_v1;
|
||||||
|
|
@ -150,21 +151,19 @@ struct sway_debug {
|
||||||
bool noatomic; // Ignore atomic layout updates
|
bool noatomic; // Ignore atomic layout updates
|
||||||
bool txn_timings; // Log verbose messages about transactions
|
bool txn_timings; // Log verbose messages about transactions
|
||||||
bool txn_wait; // Always wait for the timeout before applying
|
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 struct sway_debug debug;
|
||||||
|
|
||||||
extern bool allow_unsupported_gpu;
|
extern bool allow_unsupported_gpu;
|
||||||
|
|
||||||
|
void sway_terminate(int exit_code);
|
||||||
|
|
||||||
bool server_init(struct sway_server *server);
|
bool server_init(struct sway_server *server);
|
||||||
void server_fini(struct sway_server *server);
|
void server_fini(struct sway_server *server);
|
||||||
bool server_start(struct sway_server *server);
|
bool server_start(struct sway_server *server);
|
||||||
void server_run(struct sway_server *server);
|
void server_run(struct sway_server *server);
|
||||||
|
|
||||||
void restore_nofile_limit(void);
|
|
||||||
void restore_signals(void);
|
|
||||||
|
|
||||||
void handle_new_output(struct wl_listener *listener, void *data);
|
void handle_new_output(struct wl_listener *listener, void *data);
|
||||||
|
|
||||||
void handle_idle_inhibitor_v1(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_enter;
|
||||||
struct wl_listener output_leave;
|
struct wl_listener output_leave;
|
||||||
|
struct wl_listener output_handler_destroy;
|
||||||
|
|
||||||
struct sway_container_state current;
|
struct sway_container_state current;
|
||||||
struct sway_container_state pending;
|
struct sway_container_state pending;
|
||||||
|
|
|
||||||
|
|
@ -96,7 +96,7 @@ void workspace_output_add_priority(struct sway_workspace *workspace,
|
||||||
struct sway_output *output);
|
struct sway_output *output);
|
||||||
|
|
||||||
struct sway_output *workspace_output_get_highest_available(
|
struct sway_output *workspace_output_get_highest_available(
|
||||||
struct sway_workspace *ws, struct sway_output *exclude);
|
struct sway_workspace *ws);
|
||||||
|
|
||||||
void workspace_detect_urgent(struct sway_workspace *workspace);
|
void workspace_detect_urgent(struct sway_workspace *workspace);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,11 @@ struct box_colors {
|
||||||
uint32_t text;
|
uint32_t text;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct box_size {
|
||||||
|
uint32_t width;
|
||||||
|
uint32_t height;
|
||||||
|
};
|
||||||
|
|
||||||
struct config_output {
|
struct config_output {
|
||||||
struct wl_list link; // swaybar_config::outputs
|
struct wl_list link; // swaybar_config::outputs
|
||||||
char *name;
|
char *name;
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
project(
|
project(
|
||||||
'sway',
|
'sway',
|
||||||
'c',
|
'c',
|
||||||
version: '1.10-dev',
|
version: '1.11-rc2',
|
||||||
license: 'MIT',
|
license: 'MIT',
|
||||||
meson_version: '>=1.3',
|
meson_version: '>=1.3',
|
||||||
default_options: [
|
default_options: [
|
||||||
|
|
@ -38,14 +38,14 @@ if is_freebsd
|
||||||
endif
|
endif
|
||||||
|
|
||||||
# Execute the wlroots subproject, if any
|
# Execute the wlroots subproject, if any
|
||||||
wlroots_version = ['>=0.19.0', '<0.20.0']
|
wlroots_version = ['>=0.20.0', '<0.21.0']
|
||||||
subproject(
|
subproject(
|
||||||
'wlroots',
|
'wlroots',
|
||||||
default_options: ['examples=false'],
|
default_options: ['examples=false'],
|
||||||
required: false,
|
required: false,
|
||||||
version: wlroots_version,
|
version: wlroots_version,
|
||||||
)
|
)
|
||||||
wlroots = dependency('wlroots-0.19', version: wlroots_version, fallback: 'wlroots')
|
wlroots = dependency('wlroots-0.20', version: wlroots_version, fallback: 'wlroots')
|
||||||
wlroots_features = {
|
wlroots_features = {
|
||||||
'xwayland': false,
|
'xwayland': false,
|
||||||
'libinput_backend': false,
|
'libinput_backend': false,
|
||||||
|
|
@ -79,7 +79,7 @@ libudev = wlroots_features['libinput_backend'] ? dependency('libudev') : null_de
|
||||||
math = cc.find_library('m')
|
math = cc.find_library('m')
|
||||||
rt = cc.find_library('rt')
|
rt = cc.find_library('rt')
|
||||||
xcb_icccm = wlroots_features['xwayland'] ? dependency('xcb-icccm') : null_dep
|
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 get_option('sd-bus-provider') == 'auto'
|
||||||
if not get_option('tray').disabled()
|
if not get_option('tray').disabled()
|
||||||
|
|
|
||||||
|
|
@ -367,7 +367,7 @@ static struct cmd_results *cmd_bindsym_or_bindcode(int argc, char **argv,
|
||||||
}
|
}
|
||||||
} else if (strcmp("--exclude-titlebar", argv[0]) == 0) {
|
} else if (strcmp("--exclude-titlebar", argv[0]) == 0) {
|
||||||
exclude_titlebar = true;
|
exclude_titlebar = true;
|
||||||
} else if (has_prefix("--input-device=", argv[0])) {
|
} else if (has_prefix(argv[0], "--input-device=")) {
|
||||||
free(binding->input);
|
free(binding->input);
|
||||||
binding->input = strdup(argv[0] + strlen("--input-device="));
|
binding->input = strdup(argv[0] + strlen("--input-device="));
|
||||||
strip_quotes(binding->input);
|
strip_quotes(binding->input);
|
||||||
|
|
|
||||||
|
|
@ -51,8 +51,6 @@ struct cmd_results *cmd_exec_process(int argc, char **argv) {
|
||||||
// Fork process
|
// Fork process
|
||||||
pid_t child = fork();
|
pid_t child = fork();
|
||||||
if (child == 0) {
|
if (child == 0) {
|
||||||
restore_nofile_limit();
|
|
||||||
restore_signals();
|
|
||||||
setsid();
|
setsid();
|
||||||
|
|
||||||
if (ctx) {
|
if (ctx) {
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,7 @@
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include "sway/commands.h"
|
#include "sway/commands.h"
|
||||||
#include "sway/config.h"
|
#include "sway/config.h"
|
||||||
|
#include "sway/server.h"
|
||||||
void sway_terminate(int exit_code);
|
|
||||||
|
|
||||||
struct cmd_results *cmd_exit(int argc, char **argv) {
|
struct cmd_results *cmd_exit(int argc, char **argv) {
|
||||||
struct cmd_results *error = NULL;
|
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;
|
binding->flags |= BINDING_EXACT;
|
||||||
} else if (strcmp("--no-warn", argv[0]) == 0) {
|
} else if (strcmp("--no-warn", argv[0]) == 0) {
|
||||||
warn = false;
|
warn = false;
|
||||||
} else if (has_prefix("--input-device=", argv[0])) {
|
} else if (has_prefix(argv[0], "--input-device=")) {
|
||||||
free(binding->input);
|
free(binding->input);
|
||||||
binding->input = strdup(argv[0] + strlen("--input-device="));
|
binding->input = strdup(argv[0] + strlen("--input-device="));
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -222,6 +222,7 @@ static void container_move_to_workspace(struct sway_container *container,
|
||||||
container_detach(container);
|
container_detach(container);
|
||||||
if (workspace_is_empty(workspace) && container->pending.children) {
|
if (workspace_is_empty(workspace) && container->pending.children) {
|
||||||
workspace_unwrap_children(workspace, container);
|
workspace_unwrap_children(workspace, container);
|
||||||
|
container_reap_empty(container);
|
||||||
} else {
|
} else {
|
||||||
container->pending.width = container->pending.height = 0;
|
container->pending.width = container->pending.height = 0;
|
||||||
container->width_fraction = container->height_fraction = 0;
|
container->width_fraction = container->height_fraction = 0;
|
||||||
|
|
|
||||||
|
|
@ -457,7 +457,7 @@ static struct cmd_results *cmd_resize_set(int argc, char **argv) {
|
||||||
if (argc > num_consumed_args) {
|
if (argc > num_consumed_args) {
|
||||||
return cmd_results_new(CMD_INVALID, "%s", usage);
|
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);
|
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
|
// If using criteria, this command is executed for every container which
|
||||||
// matches the criteria. If this container isn't in the scratchpad,
|
// 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.
|
// overridden node is not a container.
|
||||||
if (!con || !con->scratchpad) {
|
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);
|
scratchpad_toggle_container(con);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -552,28 +552,12 @@ bool load_main_config(const char *file, bool is_active, bool validating) {
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool load_include_config(const char *path, const char *parent_dir,
|
static bool load_include_config(const char *path, struct sway_config *config,
|
||||||
struct sway_config *config, struct swaynag_instance *swaynag) {
|
struct swaynag_instance *swaynag) {
|
||||||
// save parent config
|
// save parent config
|
||||||
const char *parent_config = config->current_config_path;
|
const char *parent_config = config->current_config_path;
|
||||||
|
|
||||||
char *full_path;
|
char *real_path = realpath(path, NULL);
|
||||||
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);
|
|
||||||
|
|
||||||
if (real_path == NULL) {
|
if (real_path == NULL) {
|
||||||
sway_log(SWAY_DEBUG, "%s not found.", path);
|
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;
|
char **w = p.we_wordv;
|
||||||
size_t i;
|
size_t i;
|
||||||
for (i = 0; i < p.we_wordc; ++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);
|
wordfree(&p);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -213,8 +213,6 @@ static void invoke_swaybar(struct bar_config *bar) {
|
||||||
sway_log(SWAY_ERROR, "Failed to create fork for swaybar");
|
sway_log(SWAY_ERROR, "Failed to create fork for swaybar");
|
||||||
return;
|
return;
|
||||||
} else if (pid == 0) {
|
} else if (pid == 0) {
|
||||||
restore_nofile_limit();
|
|
||||||
restore_signals();
|
|
||||||
if (!sway_set_cloexec(sockets[1], false)) {
|
if (!sway_set_cloexec(sockets[1], false)) {
|
||||||
_exit(EXIT_FAILURE);
|
_exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -67,7 +67,7 @@ struct output_config *new_output_config(const char *name) {
|
||||||
oc->refresh_rate = -1;
|
oc->refresh_rate = -1;
|
||||||
oc->custom_mode = -1;
|
oc->custom_mode = -1;
|
||||||
oc->drm_mode.type = -1;
|
oc->drm_mode.type = -1;
|
||||||
oc->x = oc->y = -1;
|
oc->x = oc->y = INT_MAX;
|
||||||
oc->scale = -1;
|
oc->scale = -1;
|
||||||
oc->scale_filter = SCALE_FILTER_DEFAULT;
|
oc->scale_filter = SCALE_FILTER_DEFAULT;
|
||||||
oc->transform = -1;
|
oc->transform = -1;
|
||||||
|
|
@ -93,11 +93,11 @@ static void supersede_output_config(struct output_config *dst, struct output_con
|
||||||
if (src->height != -1) {
|
if (src->height != -1) {
|
||||||
dst->height = -1;
|
dst->height = -1;
|
||||||
}
|
}
|
||||||
if (src->x != -1) {
|
if (src->x != INT_MAX) {
|
||||||
dst->x = -1;
|
dst->x = INT_MAX;
|
||||||
}
|
}
|
||||||
if (src->y != -1) {
|
if (src->y != INT_MAX) {
|
||||||
dst->y = -1;
|
dst->y = INT_MAX;
|
||||||
}
|
}
|
||||||
if (src->scale != -1) {
|
if (src->scale != -1) {
|
||||||
dst->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) {
|
if (src->render_bit_depth != RENDER_BIT_DEPTH_DEFAULT) {
|
||||||
dst->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) {
|
if (src->background) {
|
||||||
free(dst->background);
|
free(dst->background);
|
||||||
dst->background = NULL;
|
dst->background = NULL;
|
||||||
|
|
@ -144,6 +151,9 @@ static void supersede_output_config(struct output_config *dst, struct output_con
|
||||||
if (src->power != -1) {
|
if (src->power != -1) {
|
||||||
dst->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
|
// 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) {
|
if (src->height != -1) {
|
||||||
dst->height = src->height;
|
dst->height = src->height;
|
||||||
}
|
}
|
||||||
if (src->x != -1) {
|
if (src->x != INT_MAX) {
|
||||||
dst->x = src->x;
|
dst->x = src->x;
|
||||||
}
|
}
|
||||||
if (src->y != -1) {
|
if (src->y != INT_MAX) {
|
||||||
dst->y = src->y;
|
dst->y = src->y;
|
||||||
}
|
}
|
||||||
if (src->scale != -1) {
|
if (src->scale != -1) {
|
||||||
|
|
@ -527,7 +537,7 @@ static bool finalize_output_config(struct output_config *oc, struct sway_output
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find position for it
|
// 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);
|
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);
|
wlr_output_layout_add(root->output_layout, wlr_output, oc->x, oc->y);
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -1060,8 +1070,6 @@ static bool _spawn_swaybg(char **command) {
|
||||||
sway_log_errno(SWAY_ERROR, "fork failed");
|
sway_log_errno(SWAY_ERROR, "fork failed");
|
||||||
return false;
|
return false;
|
||||||
} else if (pid == 0) {
|
} else if (pid == 0) {
|
||||||
restore_nofile_limit();
|
|
||||||
restore_signals();
|
|
||||||
if (!sway_set_cloexec(sockets[1], false)) {
|
if (!sway_set_cloexec(sockets[1], false)) {
|
||||||
_exit(EXIT_FAILURE);
|
_exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <wlr/types/wlr_idle_notify_v1.h>
|
#include <wlr/types/wlr_idle_notify_v1.h>
|
||||||
|
#include <wlr/types/wlr_session_lock_v1.h>
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "sway/desktop/idle_inhibit_v1.h"
|
#include "sway/desktop/idle_inhibit_v1.h"
|
||||||
#include "sway/input/seat.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();
|
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,
|
void sway_idle_inhibit_v1_user_inhibitor_register(struct sway_view *view,
|
||||||
enum sway_idle_inhibit_mode mode) {
|
enum sway_idle_inhibit_mode mode) {
|
||||||
struct sway_idle_inhibit_manager_v1 *manager = &server.idle_inhibit_manager_v1;
|
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) {
|
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) {
|
switch (inhibitor->mode) {
|
||||||
case INHIBIT_IDLE_APPLICATION:;
|
case INHIBIT_IDLE_APPLICATION:;
|
||||||
// If there is no view associated with the inhibitor, assume visible
|
struct wlr_surface *wlr_surface = inhibitor->wlr_inhibitor->surface;
|
||||||
struct sway_view *view = view_from_wlr_surface(inhibitor->wlr_inhibitor->surface);
|
struct wlr_layer_surface_v1 *layer_surface =
|
||||||
return !view || !view->container || view_is_visible(view);
|
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:;
|
case INHIBIT_IDLE_FOCUS:;
|
||||||
struct sway_seat *seat = NULL;
|
struct sway_seat *seat = NULL;
|
||||||
wl_list_for_each(seat, &server.input->seats, link) {
|
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,
|
wl_signal_add(&manager->wlr_manager->events.new_inhibitor,
|
||||||
&manager->new_idle_inhibitor_v1);
|
&manager->new_idle_inhibitor_v1);
|
||||||
manager->new_idle_inhibitor_v1.notify = handle_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);
|
wl_list_init(&manager->inhibitors);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
|
||||||
|
|
@ -221,7 +221,7 @@ static void handle_output_destroy(struct wl_listener *listener, void *data) {
|
||||||
wl_container_of(listener, layer, output_destroy);
|
wl_container_of(listener, layer, output_destroy);
|
||||||
|
|
||||||
layer->output = NULL;
|
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) {
|
static void handle_node_destroy(struct wl_listener *listener, void *data) {
|
||||||
|
|
@ -269,12 +269,8 @@ static void handle_surface_commit(struct wl_listener *listener, void *data) {
|
||||||
wl_container_of(listener, surface, surface_commit);
|
wl_container_of(listener, surface, surface_commit);
|
||||||
|
|
||||||
struct wlr_layer_surface_v1 *layer_surface = surface->layer_surface;
|
struct wlr_layer_surface_v1 *layer_surface = surface->layer_surface;
|
||||||
if (!layer_surface->initialized) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t committed = layer_surface->current.committed;
|
uint32_t committed = layer_surface->current.committed;
|
||||||
if (committed & WLR_LAYER_SURFACE_V1_STATE_LAYER) {
|
if (layer_surface->initialized && committed & WLR_LAYER_SURFACE_V1_STATE_LAYER) {
|
||||||
enum zwlr_layer_shell_v1_layer layer_type = layer_surface->current.layer;
|
enum zwlr_layer_shell_v1_layer layer_type = layer_surface->current.layer;
|
||||||
struct wlr_scene_tree *output_layer = sway_layer_get_scene(
|
struct wlr_scene_tree *output_layer = sway_layer_get_scene(
|
||||||
surface->output, layer_type);
|
surface->output, layer_type);
|
||||||
|
|
|
||||||
|
|
@ -264,7 +264,7 @@ static int output_repaint_timer_handler(void *data) {
|
||||||
struct sway_output *output = data;
|
struct sway_output *output = data;
|
||||||
|
|
||||||
output->wlr_output->frame_pending = false;
|
output->wlr_output->frame_pending = false;
|
||||||
if (!output->enabled) {
|
if (!output->wlr_output->enabled) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -422,13 +422,6 @@ void force_modeset(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static void begin_destroy(struct sway_output *output) {
|
static void begin_destroy(struct sway_output *output) {
|
||||||
if (output->enabled) {
|
|
||||||
output_disable(output);
|
|
||||||
}
|
|
||||||
|
|
||||||
output_begin_destroy(output);
|
|
||||||
|
|
||||||
wl_list_remove(&output->link);
|
|
||||||
|
|
||||||
wl_list_remove(&output->layout_destroy.link);
|
wl_list_remove(&output->layout_destroy.link);
|
||||||
wl_list_remove(&output->destroy.link);
|
wl_list_remove(&output->destroy.link);
|
||||||
|
|
@ -436,8 +429,17 @@ static void begin_destroy(struct sway_output *output) {
|
||||||
wl_list_remove(&output->frame.link);
|
wl_list_remove(&output->frame.link);
|
||||||
wl_list_remove(&output->request_state.link);
|
wl_list_remove(&output->request_state.link);
|
||||||
|
|
||||||
|
// Remove the scene_output first to ensure that the scene does not emit
|
||||||
|
// events for this output.
|
||||||
wlr_scene_output_destroy(output->scene_output);
|
wlr_scene_output_destroy(output->scene_output);
|
||||||
output->scene_output = NULL;
|
output->scene_output = NULL;
|
||||||
|
|
||||||
|
if (output->enabled) {
|
||||||
|
output_disable(output);
|
||||||
|
}
|
||||||
|
output_begin_destroy(output);
|
||||||
|
wl_list_remove(&output->link);
|
||||||
|
|
||||||
output->wlr_output->data = NULL;
|
output->wlr_output->data = NULL;
|
||||||
output->wlr_output = NULL;
|
output->wlr_output = NULL;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -309,12 +309,13 @@ static void arrange_children(enum sway_container_layout layout, list_t *children
|
||||||
arrange_title_bar(child, title_offset, -title_bar_height,
|
arrange_title_bar(child, title_offset, -title_bar_height,
|
||||||
next_title_offset - title_offset, title_bar_height);
|
next_title_offset - title_offset, title_bar_height);
|
||||||
wlr_scene_node_set_enabled(&child->border.tree->node, activated);
|
wlr_scene_node_set_enabled(&child->border.tree->node, activated);
|
||||||
|
wlr_scene_node_set_enabled(&child->scene_tree->node, true);
|
||||||
wlr_scene_node_set_position(&child->scene_tree->node, 0, title_bar_height);
|
wlr_scene_node_set_position(&child->scene_tree->node, 0, title_bar_height);
|
||||||
wlr_scene_node_reparent(&child->scene_tree->node, content);
|
wlr_scene_node_reparent(&child->scene_tree->node, content);
|
||||||
|
|
||||||
if (activated) {
|
int net_height = height - title_bar_height;
|
||||||
arrange_container(child, width, height - title_bar_height,
|
if (activated && width > 0 && net_height > 0) {
|
||||||
title_bar_height == 0, 0);
|
arrange_container(child, width, net_height, title_bar_height == 0, 0);
|
||||||
} else {
|
} else {
|
||||||
disable_container(child);
|
disable_container(child);
|
||||||
}
|
}
|
||||||
|
|
@ -338,12 +339,13 @@ static void arrange_children(enum sway_container_layout layout, list_t *children
|
||||||
|
|
||||||
arrange_title_bar(child, 0, y - title_height, width, title_bar_height);
|
arrange_title_bar(child, 0, y - title_height, width, title_bar_height);
|
||||||
wlr_scene_node_set_enabled(&child->border.tree->node, activated);
|
wlr_scene_node_set_enabled(&child->border.tree->node, activated);
|
||||||
|
wlr_scene_node_set_enabled(&child->scene_tree->node, true);
|
||||||
wlr_scene_node_set_position(&child->scene_tree->node, 0, title_height);
|
wlr_scene_node_set_position(&child->scene_tree->node, 0, title_height);
|
||||||
wlr_scene_node_reparent(&child->scene_tree->node, content);
|
wlr_scene_node_reparent(&child->scene_tree->node, content);
|
||||||
|
|
||||||
if (activated) {
|
int net_height = height - title_height;
|
||||||
arrange_container(child, width, height - title_height,
|
if (activated && width > 0 && net_height > 0) {
|
||||||
title_bar_height == 0, 0);
|
arrange_container(child, width, net_height, title_bar_height == 0, 0);
|
||||||
} else {
|
} else {
|
||||||
disable_container(child);
|
disable_container(child);
|
||||||
}
|
}
|
||||||
|
|
@ -359,8 +361,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_enabled(&child->border.tree->node, true);
|
||||||
wlr_scene_node_set_position(&child->scene_tree->node, 0, off);
|
wlr_scene_node_set_position(&child->scene_tree->node, 0, off);
|
||||||
wlr_scene_node_reparent(&child->scene_tree->node, content);
|
wlr_scene_node_reparent(&child->scene_tree->node, content);
|
||||||
arrange_container(child, width, cheight, true, gaps);
|
if (width > 0 && cheight > 0) {
|
||||||
off += cheight + gaps;
|
arrange_container(child, width, cheight, true, gaps);
|
||||||
|
off += cheight + gaps;
|
||||||
|
} else {
|
||||||
|
disable_container(child);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else if (layout == L_HORIZ) {
|
} else if (layout == L_HORIZ) {
|
||||||
int off = 0;
|
int off = 0;
|
||||||
|
|
@ -371,8 +377,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_enabled(&child->border.tree->node, true);
|
||||||
wlr_scene_node_set_position(&child->scene_tree->node, off, 0);
|
wlr_scene_node_set_position(&child->scene_tree->node, off, 0);
|
||||||
wlr_scene_node_reparent(&child->scene_tree->node, content);
|
wlr_scene_node_reparent(&child->scene_tree->node, content);
|
||||||
arrange_container(child, cwidth, height, true, gaps);
|
if (cwidth > 0 && height > 0) {
|
||||||
off += cwidth + gaps;
|
arrange_container(child, cwidth, height, true, gaps);
|
||||||
|
off += cwidth + gaps;
|
||||||
|
} else {
|
||||||
|
disable_container(child);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
sway_assert(false, "unreachable");
|
sway_assert(false, "unreachable");
|
||||||
|
|
@ -524,6 +534,7 @@ static void arrange_workspace_floating(struct sway_workspace *ws) {
|
||||||
wlr_scene_node_set_position(&floater->scene_tree->node,
|
wlr_scene_node_set_position(&floater->scene_tree->node,
|
||||||
floater->current.x, floater->current.y);
|
floater->current.x, floater->current.y);
|
||||||
wlr_scene_node_set_enabled(&floater->scene_tree->node, true);
|
wlr_scene_node_set_enabled(&floater->scene_tree->node, true);
|
||||||
|
wlr_scene_node_set_enabled(&floater->border.tree->node, true);
|
||||||
|
|
||||||
arrange_container(floater, floater->current.width, floater->current.height,
|
arrange_container(floater, floater->current.width, floater->current.height,
|
||||||
true, ws->gaps_inner);
|
true, ws->gaps_inner);
|
||||||
|
|
@ -576,15 +587,16 @@ static void arrange_output(struct sway_output *output, int width, int height) {
|
||||||
wlr_scene_node_set_enabled(&child->layers.tiling->node, !fs);
|
wlr_scene_node_set_enabled(&child->layers.tiling->node, !fs);
|
||||||
wlr_scene_node_set_enabled(&child->layers.fullscreen->node, fs);
|
wlr_scene_node_set_enabled(&child->layers.fullscreen->node, fs);
|
||||||
|
|
||||||
arrange_workspace_floating(child);
|
|
||||||
|
|
||||||
wlr_scene_node_set_enabled(&output->layers.shell_background->node, !fs);
|
wlr_scene_node_set_enabled(&output->layers.shell_background->node, !fs);
|
||||||
wlr_scene_node_set_enabled(&output->layers.shell_bottom->node, !fs);
|
wlr_scene_node_set_enabled(&output->layers.shell_bottom->node, !fs);
|
||||||
wlr_scene_node_set_enabled(&output->layers.fullscreen->node, fs);
|
wlr_scene_node_set_enabled(&output->layers.fullscreen->node, fs);
|
||||||
|
|
||||||
if (fs) {
|
if (fs) {
|
||||||
|
disable_workspace(child);
|
||||||
|
|
||||||
wlr_scene_rect_set_size(output->fullscreen_background, width, height);
|
wlr_scene_rect_set_size(output->fullscreen_background, width, height);
|
||||||
|
|
||||||
|
arrange_workspace_floating(child);
|
||||||
arrange_fullscreen(child->layers.fullscreen, fs, child,
|
arrange_fullscreen(child->layers.fullscreen, fs, child,
|
||||||
width, height);
|
width, height);
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -597,6 +609,7 @@ static void arrange_output(struct sway_output *output, int width, int height) {
|
||||||
arrange_workspace_tiling(child,
|
arrange_workspace_tiling(child,
|
||||||
area->width - gaps->left - gaps->right,
|
area->width - gaps->left - gaps->right,
|
||||||
area->height - gaps->top - gaps->bottom);
|
area->height - gaps->top - gaps->bottom);
|
||||||
|
arrange_workspace_floating(child);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
wlr_scene_node_set_enabled(&child->layers.tiling->node, false);
|
wlr_scene_node_set_enabled(&child->layers.tiling->node, false);
|
||||||
|
|
@ -654,6 +667,13 @@ static void arrange_root(struct sway_root *root) {
|
||||||
|
|
||||||
wlr_scene_output_set_position(output->scene_output, output->lx, output->ly);
|
wlr_scene_output_set_position(output->scene_output, output->lx, output->ly);
|
||||||
|
|
||||||
|
// disable all workspaces to get to a known state
|
||||||
|
for (int j = 0; j < output->current.workspaces->length; j++) {
|
||||||
|
struct sway_workspace *workspace = output->current.workspaces->items[j];
|
||||||
|
disable_workspace(workspace);
|
||||||
|
}
|
||||||
|
|
||||||
|
// arrange the active workspace
|
||||||
if (ws) {
|
if (ws) {
|
||||||
arrange_workspace_floating(ws);
|
arrange_workspace_floating(ws);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -493,6 +493,14 @@ struct sway_input_manager *input_manager_create(struct sway_server *server) {
|
||||||
return input;
|
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) {
|
bool input_manager_has_focus(struct sway_node *node) {
|
||||||
struct sway_seat *seat = NULL;
|
struct sway_seat *seat = NULL;
|
||||||
wl_list_for_each(seat, &server.input->seats, link) {
|
wl_list_for_each(seat, &server.input->seats, link) {
|
||||||
|
|
|
||||||
|
|
@ -399,6 +399,19 @@ void sway_input_reset_libinput_device(struct sway_input_device *input_device) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool sway_udev_device_is_builtin(struct udev_device *udev_device) {
|
||||||
|
const char *id_path = udev_device_get_property_value(udev_device, "ID_PATH");
|
||||||
|
if (!id_path) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (has_prefix(id_path, "platform-")) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return has_prefix(id_path, "pci-") && strstr(id_path, "-platform-");
|
||||||
|
}
|
||||||
|
|
||||||
bool sway_libinput_device_is_builtin(struct sway_input_device *sway_device) {
|
bool sway_libinput_device_is_builtin(struct sway_input_device *sway_device) {
|
||||||
if (!wlr_input_device_is_libinput(sway_device->wlr_device)) {
|
if (!wlr_input_device_is_libinput(sway_device->wlr_device)) {
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -412,14 +425,7 @@ bool sway_libinput_device_is_builtin(struct sway_input_device *sway_device) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *id_path = udev_device_get_property_value(udev_device, "ID_PATH");
|
bool is_builtin = sway_udev_device_is_builtin(udev_device);
|
||||||
if (!id_path) {
|
udev_device_unref(udev_device);
|
||||||
return false;
|
return is_builtin;
|
||||||
}
|
|
||||||
|
|
||||||
if (has_prefix(id_path, "platform-")) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return has_prefix(id_path, "pci-") && strstr(id_path, "-platform-");
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -100,6 +100,7 @@ static void handle_touch_down(struct sway_seat *seat,
|
||||||
|
|
||||||
if (focused_node) {
|
if (focused_node) {
|
||||||
seat_set_focus(seat, focused_node);
|
seat_set_focus(seat, focused_node);
|
||||||
|
transaction_commit_dirty();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@
|
||||||
#include "sway/input/text_input_popup.h"
|
#include "sway/input/text_input_popup.h"
|
||||||
#include "sway/layers.h"
|
#include "sway/layers.h"
|
||||||
#include "sway/server.h"
|
#include "sway/server.h"
|
||||||
|
#include <wlr/types/wlr_session_lock_v1.h>
|
||||||
|
|
||||||
static struct sway_text_input *relay_get_focusable_text_input(
|
static struct sway_text_input *relay_get_focusable_text_input(
|
||||||
struct sway_input_method_relay *relay) {
|
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 =
|
struct wlr_layer_surface_v1 *layer_surface =
|
||||||
wlr_layer_surface_v1_try_from_wlr_surface(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;
|
struct wlr_scene_tree *relative_parent;
|
||||||
if (layer_surface) {
|
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
|
// surface. Layer surfaces get destroyed as part of the output being
|
||||||
// destroyed, thus also trickling down to popups.
|
// destroyed, thus also trickling down to popups.
|
||||||
popup->fixed_output = layer->layer_surface->output;
|
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 {
|
} else {
|
||||||
struct sway_view *view = view_from_wlr_surface(surface);
|
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);
|
wl_signal_add(&view->events.unmap, &popup->focused_surface_unmap);
|
||||||
relative_parent = view->scene_tree;
|
relative_parent = view->scene_tree;
|
||||||
popup->desc.view = view;
|
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,
|
void sway_input_method_relay_init(struct sway_seat *seat,
|
||||||
struct sway_input_method_relay *relay) {
|
struct sway_input_method_relay *relay) {
|
||||||
relay->seat = seat;
|
relay->seat = seat;
|
||||||
|
|
@ -579,18 +632,24 @@ void sway_input_method_relay_init(struct sway_seat *seat,
|
||||||
wl_list_init(&relay->input_popups);
|
wl_list_init(&relay->input_popups);
|
||||||
|
|
||||||
relay->text_input_new.notify = relay_handle_text_input;
|
relay->text_input_new.notify = relay_handle_text_input;
|
||||||
wl_signal_add(&server.text_input->events.text_input,
|
wl_signal_add(&server.text_input->events.new_text_input,
|
||||||
&relay->text_input_new);
|
&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;
|
relay->input_method_new.notify = relay_handle_input_method;
|
||||||
wl_signal_add(
|
wl_signal_add(
|
||||||
&server.input_method->events.input_method,
|
&server.input_method->events.input_method,
|
||||||
&relay->input_method_new);
|
&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) {
|
void sway_input_method_relay_finish(struct sway_input_method_relay *relay) {
|
||||||
wl_list_remove(&relay->input_method_new.link);
|
sway_input_method_relay_finish_text_input(relay);
|
||||||
wl_list_remove(&relay->text_input_new.link);
|
sway_input_method_relay_finish_input_method(relay);
|
||||||
}
|
}
|
||||||
|
|
||||||
void sway_input_method_relay_set_focus(struct sway_input_method_relay *relay,
|
void sway_input_method_relay_set_focus(struct sway_input_method_relay *relay,
|
||||||
|
|
|
||||||
|
|
@ -234,6 +234,9 @@ static void handle_unlock(struct wl_listener *listener, void *data) {
|
||||||
struct sway_output *output = root->outputs->items[i];
|
struct sway_output *output = root->outputs->items[i];
|
||||||
arrange_layers(output);
|
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) {
|
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);
|
wlr_session_lock_v1_send_locked(lock);
|
||||||
server.session_lock.lock = sway_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) {
|
static void handle_session_lock_destroy(struct wl_listener *listener, void *data) {
|
||||||
|
|
|
||||||
66
sway/main.c
66
sway/main.c
|
|
@ -1,5 +1,6 @@
|
||||||
#include <getopt.h>
|
#include <getopt.h>
|
||||||
#include <pango/pangocairo.h>
|
#include <pango/pangocairo.h>
|
||||||
|
#include <pthread.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdio.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) {
|
void run_as_ipc_client(char *command, char *socket_path) {
|
||||||
int socketfd = ipc_open_socket(socket_path);
|
int socketfd = ipc_open_socket(socket_path);
|
||||||
uint32_t len = strlen(command);
|
uint32_t len = strlen(command);
|
||||||
|
|
@ -125,6 +122,16 @@ static bool detect_suid(void) {
|
||||||
return true;
|
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) {
|
static void increase_nofile_limit(void) {
|
||||||
if (getrlimit(RLIMIT_NOFILE, &original_nofile_rlimit) != 0) {
|
if (getrlimit(RLIMIT_NOFILE, &original_nofile_rlimit) != 0) {
|
||||||
sway_log_errno(SWAY_ERROR, "Failed to bump max open files limit: "
|
sway_log_errno(SWAY_ERROR, "Failed to bump max open files limit: "
|
||||||
|
|
@ -139,25 +146,38 @@ static void increase_nofile_limit(void) {
|
||||||
"setrlimit(NOFILE) failed");
|
"setrlimit(NOFILE) failed");
|
||||||
sway_log(SWAY_INFO, "Running with %d max open files",
|
sway_log(SWAY_INFO, "Running with %d max open files",
|
||||||
(int)original_nofile_rlimit.rlim_cur);
|
(int)original_nofile_rlimit.rlim_cur);
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void restore_nofile_limit(void) {
|
|
||||||
if (original_nofile_rlimit.rlim_cur == 0) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (setrlimit(RLIMIT_NOFILE, &original_nofile_rlimit) != 0) {
|
|
||||||
sway_log_errno(SWAY_ERROR, "Failed to restore max open files limit: "
|
pthread_atfork(NULL, NULL, restore_nofile_limit);
|
||||||
"setrlimit(NOFILE) failed");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void restore_signals(void) {
|
static int term_signal(int signal, void *data) {
|
||||||
|
sway_terminate(EXIT_SUCCESS);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void restore_signals(void) {
|
||||||
sigset_t set;
|
sigset_t set;
|
||||||
sigemptyset(&set);
|
sigemptyset(&set);
|
||||||
sigprocmask(SIG_SETMASK, &set, NULL);
|
sigprocmask(SIG_SETMASK, &set, NULL);
|
||||||
signal(SIGCHLD, SIG_DFL);
|
|
||||||
signal(SIGPIPE, SIG_DFL);
|
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) {
|
void enable_debug_flag(const char *flag) {
|
||||||
|
|
@ -169,8 +189,6 @@ void enable_debug_flag(const char *flag) {
|
||||||
debug.txn_timings = true;
|
debug.txn_timings = true;
|
||||||
} else if (has_prefix(flag, "txn-timeout=")) {
|
} else if (has_prefix(flag, "txn-timeout=")) {
|
||||||
server.txn_timeout_ms = atoi(&flag[strlen("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 {
|
} else {
|
||||||
sway_log(SWAY_ERROR, "Unknown debug flag: %s", flag);
|
sway_log(SWAY_ERROR, "Unknown debug flag: %s", flag);
|
||||||
}
|
}
|
||||||
|
|
@ -330,22 +348,14 @@ int main(int argc, char **argv) {
|
||||||
|
|
||||||
increase_nofile_limit();
|
increase_nofile_limit();
|
||||||
|
|
||||||
// handle SIGTERM signals
|
|
||||||
signal(SIGTERM, sig_handler);
|
|
||||||
signal(SIGINT, sig_handler);
|
|
||||||
|
|
||||||
// avoid need to reap children
|
|
||||||
signal(SIGCHLD, SIG_IGN);
|
|
||||||
|
|
||||||
// prevent ipc from crashing sway
|
|
||||||
signal(SIGPIPE, SIG_IGN);
|
|
||||||
|
|
||||||
sway_log(SWAY_INFO, "Starting sway version " SWAY_VERSION);
|
sway_log(SWAY_INFO, "Starting sway version " SWAY_VERSION);
|
||||||
|
|
||||||
if (!server_init(&server)) {
|
if (!server_init(&server)) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
init_signals();
|
||||||
|
|
||||||
if (server.linux_dmabuf_v1) {
|
if (server.linux_dmabuf_v1) {
|
||||||
wlr_scene_set_linux_dmabuf_v1(root->root_scene, server.linux_dmabuf_v1);
|
wlr_scene_set_linux_dmabuf_v1(root->root_scene, server.linux_dmabuf_v1);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,6 @@
|
||||||
#include <wlr/types/wlr_data_control_v1.h>
|
#include <wlr/types/wlr_data_control_v1.h>
|
||||||
#include <wlr/types/wlr_ext_data_control_v1.h>
|
#include <wlr/types/wlr_ext_data_control_v1.h>
|
||||||
#include <wlr/types/wlr_data_device.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_export_dmabuf_v1.h>
|
||||||
#include <wlr/types/wlr_ext_foreign_toplevel_list_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_foreign_toplevel_management_v1.h>
|
||||||
|
|
@ -182,11 +181,11 @@ static void detect_proprietary(struct wlr_backend *backend, void *data) {
|
||||||
drmFreeVersion(version);
|
drmFreeVersion(version);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void handle_renderer_lost(struct wl_listener *listener, void *data) {
|
static void do_renderer_recreate(void *data) {
|
||||||
struct sway_server *server = wl_container_of(listener, server, renderer_lost);
|
struct sway_server *server = data;
|
||||||
|
server->recreating_renderer = NULL;
|
||||||
|
|
||||||
sway_log(SWAY_INFO, "Re-creating renderer after GPU reset");
|
sway_log(SWAY_INFO, "Re-creating renderer after GPU reset");
|
||||||
|
|
||||||
struct wlr_renderer *renderer = wlr_renderer_autocreate(server->backend);
|
struct wlr_renderer *renderer = wlr_renderer_autocreate(server->backend);
|
||||||
if (renderer == NULL) {
|
if (renderer == NULL) {
|
||||||
sway_log(SWAY_ERROR, "Unable to create renderer");
|
sway_log(SWAY_ERROR, "Unable to create renderer");
|
||||||
|
|
@ -221,6 +220,18 @@ static void handle_renderer_lost(struct wl_listener *listener, void *data) {
|
||||||
wlr_renderer_destroy(old_renderer);
|
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) {
|
bool server_init(struct sway_server *server) {
|
||||||
sway_log(SWAY_DEBUG, "Initializing Wayland server");
|
sway_log(SWAY_DEBUG, "Initializing Wayland server");
|
||||||
server->wl_display = wl_display_create();
|
server->wl_display = wl_display_create();
|
||||||
|
|
@ -253,9 +264,6 @@ bool server_init(struct sway_server *server) {
|
||||||
if (wlr_renderer_get_texture_formats(server->renderer, WLR_BUFFER_CAP_DMABUF) != NULL) {
|
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->linux_dmabuf_v1 = wlr_linux_dmabuf_v1_create_with_renderer(
|
||||||
server->wl_display, 4, server->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 &&
|
if (wlr_renderer_get_drm_fd(server->renderer) >= 0 &&
|
||||||
server->renderer->features.timeline &&
|
server->renderer->features.timeline &&
|
||||||
|
|
@ -460,9 +468,35 @@ bool server_init(struct sway_server *server) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void server_fini(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
|
// TODO: free sway-specific resources
|
||||||
#if WLR_HAS_XWAYLAND
|
#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
|
#endif
|
||||||
wl_display_destroy_clients(server->wl_display);
|
wl_display_destroy_clients(server->wl_display);
|
||||||
wlr_backend_destroy(server->backend);
|
wlr_backend_destroy(server->backend);
|
||||||
|
|
|
||||||
|
|
@ -973,7 +973,7 @@ The default colors are:
|
||||||
A criteria is a string in the form of, for example:
|
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
|
The string contains one or more (space separated) attribute/value pairs. They
|
||||||
|
|
@ -993,10 +993,19 @@ Focus on a window with the mark "IRC":
|
||||||
[con_mark="IRC"] focus
|
[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
|
You may like to use swaymsg -t get_tree for finding the values of these
|
||||||
|
|
@ -1095,3 +1104,4 @@ The following attributes may be matched with:
|
||||||
# SEE ALSO
|
# SEE ALSO
|
||||||
|
|
||||||
*sway*(1) *sway-input*(5) *sway-output*(5) *sway-bar*(5) *sway-ipc*(7)
|
*sway*(1) *sway-input*(5) *sway-output*(5) *sway-bar*(5) *sway-ipc*(7)
|
||||||
|
*pcre2pattern*(3) *pcre2syntax*(3)
|
||||||
|
|
|
||||||
|
|
@ -63,7 +63,6 @@ bool swaynag_spawn(const char *swaynag_command,
|
||||||
sway_log(SWAY_ERROR, "Failed to create fork for swaynag");
|
sway_log(SWAY_ERROR, "Failed to create fork for swaynag");
|
||||||
goto failed;
|
goto failed;
|
||||||
} else if (pid == 0) {
|
} else if (pid == 0) {
|
||||||
restore_nofile_limit();
|
|
||||||
if (!sway_set_cloexec(sockets[1], false)) {
|
if (!sway_set_cloexec(sockets[1], false)) {
|
||||||
_exit(EXIT_FAILURE);
|
_exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
@ -148,4 +147,3 @@ void swaynag_show(struct swaynag_instance *swaynag) {
|
||||||
close(swaynag->fd[1]);
|
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;
|
double total_width_fraction = 0;
|
||||||
for (int i = 0; i < children->length; ++i) {
|
for (int i = 0; i < children->length; ++i) {
|
||||||
struct sway_container *child = children->items[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.y = parent->y;
|
||||||
child->pending.width = round(child->width_fraction * child_total_width);
|
child->pending.width = round(child->width_fraction * child_total_width);
|
||||||
child->pending.height = parent->height;
|
child->pending.height = parent->height;
|
||||||
child_x += child->pending.width + inner_gap;
|
|
||||||
|
|
||||||
// Make last child use remaining width of parent
|
// Make last child use remaining width of parent
|
||||||
if (i == children->length - 1) {
|
if (i == children->length - 1) {
|
||||||
child->pending.width = parent->x + parent->width - child->pending.x;
|
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.y = child_y;
|
||||||
child->pending.width = parent->width;
|
child->pending.width = parent->width;
|
||||||
child->pending.height = round(child->height_fraction * child_total_height);
|
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
|
// Make last child use remaining height of parent
|
||||||
if (i == children->length - 1) {
|
if (i == children->length - 1) {
|
||||||
child->pending.height = parent->y + parent->height - child->pending.y;
|
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(
|
static bool handle_point_accepts_input(
|
||||||
struct wlr_scene_buffer *buffer, double *x, double *y) {
|
struct wlr_scene_buffer *buffer, double *x, double *y) {
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -135,6 +143,9 @@ struct sway_container *container_create(struct sway_view *view) {
|
||||||
c->output_leave.notify = handle_output_leave;
|
c->output_leave.notify = handle_output_leave;
|
||||||
wl_signal_add(&c->output_handler->events.output_leave,
|
wl_signal_add(&c->output_handler->events.output_leave,
|
||||||
&c->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;
|
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) {
|
if (con->view && con->view->container == con) {
|
||||||
con->view->container = NULL;
|
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);
|
wlr_scene_node_destroy(&con->output_handler->node);
|
||||||
if (con->view->destroying) {
|
if (con->view->destroying) {
|
||||||
view_destroy(con->view);
|
view_destroy(con->view);
|
||||||
|
|
@ -552,6 +561,12 @@ void container_begin_destroy(struct sway_container *con) {
|
||||||
if (con->pending.parent || con->pending.workspace) {
|
if (con->pending.parent || con->pending.workspace) {
|
||||||
container_detach(con);
|
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) {
|
void container_reap_empty(struct sway_container *con) {
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,7 @@ static void restore_workspaces(struct sway_output *output) {
|
||||||
for (int j = 0; j < other->workspaces->length; j++) {
|
for (int j = 0; j < other->workspaces->length; j++) {
|
||||||
struct sway_workspace *ws = other->workspaces->items[j];
|
struct sway_workspace *ws = other->workspaces->items[j];
|
||||||
struct sway_output *highest =
|
struct sway_output *highest =
|
||||||
workspace_output_get_highest_available(ws, NULL);
|
workspace_output_get_highest_available(ws);
|
||||||
if (highest == output) {
|
if (highest == output) {
|
||||||
workspace_detach(ws);
|
workspace_detach(ws);
|
||||||
output_add_workspace(output, ws);
|
output_add_workspace(output, ws);
|
||||||
|
|
@ -205,11 +205,8 @@ static void output_evacuate(struct sway_output *output) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
struct sway_output *fallback_output = NULL;
|
struct sway_output *fallback_output = NULL;
|
||||||
if (root->outputs->length > 1) {
|
if (root->outputs->length > 0) {
|
||||||
fallback_output = root->outputs->items[0];
|
fallback_output = root->outputs->items[0];
|
||||||
if (fallback_output == output) {
|
|
||||||
fallback_output = root->outputs->items[1];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
while (output->workspaces->length) {
|
while (output->workspaces->length) {
|
||||||
|
|
@ -218,7 +215,7 @@ static void output_evacuate(struct sway_output *output) {
|
||||||
workspace_detach(workspace);
|
workspace_detach(workspace);
|
||||||
|
|
||||||
struct sway_output *new_output =
|
struct sway_output *new_output =
|
||||||
workspace_output_get_highest_available(workspace, output);
|
workspace_output_get_highest_available(workspace);
|
||||||
if (!new_output) {
|
if (!new_output) {
|
||||||
new_output = fallback_output;
|
new_output = fallback_output;
|
||||||
}
|
}
|
||||||
|
|
@ -289,11 +286,13 @@ void output_disable(struct sway_output *output) {
|
||||||
sway_log(SWAY_DEBUG, "Disabling output '%s'", output->wlr_output->name);
|
sway_log(SWAY_DEBUG, "Disabling output '%s'", output->wlr_output->name);
|
||||||
wl_signal_emit_mutable(&output->events.disable, output);
|
wl_signal_emit_mutable(&output->events.disable, output);
|
||||||
|
|
||||||
output_evacuate(output);
|
// Remove the output now to avoid interacting with it during e.g.,
|
||||||
|
// transactions, as the output might be physically removed with the scene
|
||||||
|
// output destroyed.
|
||||||
list_del(root->outputs, index);
|
list_del(root->outputs, index);
|
||||||
|
|
||||||
output->enabled = false;
|
output->enabled = false;
|
||||||
|
|
||||||
|
output_evacuate(output);
|
||||||
}
|
}
|
||||||
|
|
||||||
void output_begin_destroy(struct sway_output *output) {
|
void output_begin_destroy(struct sway_output *output) {
|
||||||
|
|
|
||||||
|
|
@ -199,6 +199,8 @@ void root_scratchpad_show(struct sway_container *con) {
|
||||||
if (old_ws) {
|
if (old_ws) {
|
||||||
workspace_consider_destroy(old_ws);
|
workspace_consider_destroy(old_ws);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
container_raise_floating(con);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void disable_fullscreen(struct sway_container *con, void *data) {
|
static void disable_fullscreen(struct sway_container *con, void *data) {
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@
|
||||||
#include <wlr/types/wlr_server_decoration.h>
|
#include <wlr/types/wlr_server_decoration.h>
|
||||||
#include <wlr/types/wlr_subcompositor.h>
|
#include <wlr/types/wlr_subcompositor.h>
|
||||||
#include <wlr/types/wlr_xdg_decoration_v1.h>
|
#include <wlr/types/wlr_xdg_decoration_v1.h>
|
||||||
|
#include <wlr/types/wlr_session_lock_v1.h>
|
||||||
#if WLR_HAS_XWAYLAND
|
#if WLR_HAS_XWAYLAND
|
||||||
#include <wlr/xwayland.h>
|
#include <wlr/xwayland.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -217,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) {
|
bool view_inhibit_idle(struct sway_view *view) {
|
||||||
|
if (server.session_lock.lock) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
struct sway_idle_inhibitor_v1 *user_inhibitor =
|
struct sway_idle_inhibitor_v1 *user_inhibitor =
|
||||||
sway_idle_inhibit_v1_user_inhibitor_for_view(view);
|
sway_idle_inhibit_v1_user_inhibitor_for_view(view);
|
||||||
|
|
||||||
|
|
@ -512,10 +517,12 @@ void view_execute_criteria(struct sway_view *view) {
|
||||||
sway_log(SWAY_DEBUG, "for_window '%s' matches view %p, cmd: '%s'",
|
sway_log(SWAY_DEBUG, "for_window '%s' matches view %p, cmd: '%s'",
|
||||||
criteria->raw, view, criteria->cmdlist);
|
criteria->raw, view, criteria->cmdlist);
|
||||||
list_add(view->executed_criteria, criteria);
|
list_add(view->executed_criteria, criteria);
|
||||||
list_t *res_list = execute_command(
|
list_t *res_list = execute_command(criteria->cmdlist, NULL, view->container);
|
||||||
criteria->cmdlist, NULL, view->container);
|
|
||||||
while (res_list->length) {
|
while (res_list->length) {
|
||||||
struct cmd_results *res = res_list->items[0];
|
struct cmd_results *res = res_list->items[0];
|
||||||
|
if (res->status != CMD_SUCCESS) {
|
||||||
|
sway_log(SWAY_ERROR, "for_window '%s' failed: %s", criteria->raw, res->error);
|
||||||
|
}
|
||||||
free_cmd_results(res);
|
free_cmd_results(res);
|
||||||
list_del(res_list, 0);
|
list_del(res_list, 0);
|
||||||
}
|
}
|
||||||
|
|
@ -1010,6 +1017,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) {
|
if (wlr_layer_surface_v1_try_from_wlr_surface(wlr_surface) != NULL) {
|
||||||
return 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;
|
const char *role = wlr_surface->role ? wlr_surface->role->name : NULL;
|
||||||
sway_log(SWAY_DEBUG, "Surface of unknown type (role %s): %p",
|
sway_log(SWAY_DEBUG, "Surface of unknown type (role %s): %p",
|
||||||
|
|
|
||||||
|
|
@ -659,13 +659,9 @@ void workspace_output_add_priority(struct sway_workspace *workspace,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct sway_output *workspace_output_get_highest_available(
|
struct sway_output *workspace_output_get_highest_available(
|
||||||
struct sway_workspace *ws, struct sway_output *exclude) {
|
struct sway_workspace *ws) {
|
||||||
for (int i = 0; i < ws->output_priority->length; i++) {
|
for (int i = 0; i < ws->output_priority->length; i++) {
|
||||||
const char *name = ws->output_priority->items[i];
|
const char *name = ws->output_priority->items[i];
|
||||||
if (exclude && output_match_name_or_id(exclude, name)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct sway_output *output = output_by_name_or_id(name);
|
struct sway_output *output = output_by_name_or_id(name);
|
||||||
if (output) {
|
if (output) {
|
||||||
return output;
|
return output;
|
||||||
|
|
|
||||||
|
|
@ -46,7 +46,7 @@ void ipc_send_workspace_command(struct swaybar *bar, const char *ws) {
|
||||||
|
|
||||||
char *parse_font(const char *font) {
|
char *parse_font(const char *font) {
|
||||||
char *new_font = NULL;
|
char *new_font = NULL;
|
||||||
if (has_prefix("pango:", font)) {
|
if (has_prefix(font, "pango:")) {
|
||||||
font += strlen("pango:");
|
font += strlen("pango:");
|
||||||
}
|
}
|
||||||
new_font = strdup(font);
|
new_font = strdup(font);
|
||||||
|
|
|
||||||
|
|
@ -93,8 +93,9 @@ int main(int argc, char **argv) {
|
||||||
|
|
||||||
free(socket_path);
|
free(socket_path);
|
||||||
|
|
||||||
signal(SIGINT, sig_handler);
|
struct sigaction sa = { .sa_handler = sig_handler };
|
||||||
signal(SIGTERM, sig_handler);
|
sigaction(SIGINT, &sa, NULL);
|
||||||
|
sigaction(SIGTERM, &sa, NULL);
|
||||||
|
|
||||||
swaybar.running = true;
|
swaybar.running = true;
|
||||||
bar_run(&swaybar);
|
bar_run(&swaybar);
|
||||||
|
|
|
||||||
169
swaybar/render.c
169
swaybar/render.c
|
|
@ -13,7 +13,6 @@
|
||||||
#include "swaybar/ipc.h"
|
#include "swaybar/ipc.h"
|
||||||
#include "swaybar/render.h"
|
#include "swaybar/render.h"
|
||||||
#include "swaybar/status_line.h"
|
#include "swaybar/status_line.h"
|
||||||
#include "log.h"
|
|
||||||
#if HAVE_TRAY
|
#if HAVE_TRAY
|
||||||
#include "swaybar/tray/tray.h"
|
#include "swaybar/tray/tray.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -21,7 +20,7 @@
|
||||||
|
|
||||||
static const int WS_HORIZONTAL_PADDING = 5;
|
static const int WS_HORIZONTAL_PADDING = 5;
|
||||||
static const double WS_VERTICAL_PADDING = 1.5;
|
static const double WS_VERTICAL_PADDING = 1.5;
|
||||||
static const double BORDER_WIDTH = 1;
|
static const int BORDER_WIDTH = 1;
|
||||||
|
|
||||||
struct render_context {
|
struct render_context {
|
||||||
cairo_t *cairo;
|
cairo_t *cairo;
|
||||||
|
|
@ -541,6 +540,63 @@ static uint32_t render_status_line(struct render_context *ctx, double *x) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct box_size render_box(struct render_context *ctx, double x,
|
||||||
|
struct box_colors colors, const char *label, bool pango_markup) {
|
||||||
|
struct swaybar_output *output = ctx->output;
|
||||||
|
struct swaybar_config *config = output->bar->config;
|
||||||
|
cairo_t *cairo = ctx->cairo;
|
||||||
|
|
||||||
|
int text_width, text_height;
|
||||||
|
get_text_size(cairo, config->font_description, &text_width, &text_height, NULL,
|
||||||
|
1, pango_markup, "%s", label);
|
||||||
|
|
||||||
|
uint32_t width = text_width + WS_HORIZONTAL_PADDING * 2 + BORDER_WIDTH * 2;
|
||||||
|
if (width < config->workspace_min_width) {
|
||||||
|
width = config->workspace_min_width;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t ideal_height = text_height + WS_VERTICAL_PADDING * 2
|
||||||
|
+ BORDER_WIDTH * 2;
|
||||||
|
uint32_t ideal_surface_height = ideal_height;
|
||||||
|
if (!output->bar->config->height &&
|
||||||
|
output->height < ideal_surface_height) {
|
||||||
|
return (struct box_size) {
|
||||||
|
.width = width,
|
||||||
|
.height = ideal_surface_height,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t height = output->height;
|
||||||
|
cairo_set_operator(cairo, CAIRO_OPERATOR_SOURCE);
|
||||||
|
cairo_set_source_u32(cairo, colors.background);
|
||||||
|
ctx->background_color = colors.background;
|
||||||
|
ctx->has_transparency |= (colors.background & 0xFF) != 0xFF;
|
||||||
|
cairo_rectangle(cairo, x, 0, width, height);
|
||||||
|
cairo_fill(cairo);
|
||||||
|
|
||||||
|
cairo_set_source_u32(cairo, colors.border);
|
||||||
|
cairo_rectangle(cairo, x, 0, width, BORDER_WIDTH);
|
||||||
|
cairo_fill(cairo);
|
||||||
|
cairo_rectangle(cairo, x, 0, BORDER_WIDTH, height);
|
||||||
|
cairo_fill(cairo);
|
||||||
|
cairo_rectangle(cairo, x + width - BORDER_WIDTH, 0, BORDER_WIDTH, height);
|
||||||
|
cairo_fill(cairo);
|
||||||
|
cairo_rectangle(cairo, x, height - BORDER_WIDTH, width, BORDER_WIDTH);
|
||||||
|
cairo_fill(cairo);
|
||||||
|
|
||||||
|
double text_y = height / 2.0 - text_height / 2.0;
|
||||||
|
cairo_set_source_u32(cairo, colors.text);
|
||||||
|
cairo_move_to(cairo, x + width / 2 - text_width / 2, (int)floor(text_y));
|
||||||
|
choose_text_aa_mode(ctx, colors.text);
|
||||||
|
render_text(cairo, config->font_description, 1, pango_markup,
|
||||||
|
"%s", label);
|
||||||
|
|
||||||
|
return (struct box_size) {
|
||||||
|
.width = width,
|
||||||
|
.height = output->height,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
static uint32_t render_binding_mode_indicator(struct render_context *ctx,
|
static uint32_t render_binding_mode_indicator(struct render_context *ctx,
|
||||||
double x) {
|
double x) {
|
||||||
struct swaybar_output *output = ctx->output;
|
struct swaybar_output *output = ctx->output;
|
||||||
|
|
@ -549,54 +605,9 @@ static uint32_t render_binding_mode_indicator(struct render_context *ctx,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
cairo_t *cairo = ctx->cairo;
|
struct box_size size = render_box(ctx, x, output->bar->config->colors.binding_mode,
|
||||||
struct swaybar_config *config = output->bar->config;
|
mode, output->bar->mode_pango_markup);
|
||||||
int text_width, text_height;
|
return size.height;
|
||||||
get_text_size(cairo, config->font_description, &text_width, &text_height, NULL,
|
|
||||||
1, output->bar->mode_pango_markup,
|
|
||||||
"%s", mode);
|
|
||||||
|
|
||||||
int ws_vertical_padding = WS_VERTICAL_PADDING;
|
|
||||||
int ws_horizontal_padding = WS_HORIZONTAL_PADDING;
|
|
||||||
int border_width = BORDER_WIDTH;
|
|
||||||
|
|
||||||
uint32_t ideal_height = text_height + ws_vertical_padding * 2
|
|
||||||
+ border_width * 2;
|
|
||||||
uint32_t ideal_surface_height = ideal_height;
|
|
||||||
if (!output->bar->config->height &&
|
|
||||||
output->height < ideal_surface_height) {
|
|
||||||
return ideal_surface_height;
|
|
||||||
}
|
|
||||||
uint32_t width = text_width + ws_horizontal_padding * 2 + border_width * 2;
|
|
||||||
if (width < config->workspace_min_width) {
|
|
||||||
width = config->workspace_min_width;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t height = output->height;
|
|
||||||
cairo_set_operator(cairo, CAIRO_OPERATOR_SOURCE);
|
|
||||||
cairo_set_source_u32(cairo, config->colors.binding_mode.background);
|
|
||||||
ctx->background_color = config->colors.binding_mode.background;
|
|
||||||
ctx->has_transparency |= (config->colors.binding_mode.background & 0xFF) != 0xFF;
|
|
||||||
cairo_rectangle(cairo, x, 0, width, height);
|
|
||||||
cairo_fill(cairo);
|
|
||||||
|
|
||||||
cairo_set_source_u32(cairo, config->colors.binding_mode.border);
|
|
||||||
cairo_rectangle(cairo, x, 0, width, border_width);
|
|
||||||
cairo_fill(cairo);
|
|
||||||
cairo_rectangle(cairo, x, 0, border_width, height);
|
|
||||||
cairo_fill(cairo);
|
|
||||||
cairo_rectangle(cairo, x + width - border_width, 0, border_width, height);
|
|
||||||
cairo_fill(cairo);
|
|
||||||
cairo_rectangle(cairo, x, height - border_width, width, border_width);
|
|
||||||
cairo_fill(cairo);
|
|
||||||
|
|
||||||
double text_y = height / 2.0 - text_height / 2.0;
|
|
||||||
cairo_set_source_u32(cairo, config->colors.binding_mode.text);
|
|
||||||
cairo_move_to(cairo, x + width / 2 - text_width / 2, (int)floor(text_y));
|
|
||||||
choose_text_aa_mode(ctx, config->colors.binding_mode.text);
|
|
||||||
render_text(cairo, config->font_description, 1, output->bar->mode_pango_markup,
|
|
||||||
"%s", mode);
|
|
||||||
return output->height;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static enum hotspot_event_handling workspace_hotspot_callback(
|
static enum hotspot_event_handling workspace_hotspot_callback(
|
||||||
|
|
@ -618,6 +629,7 @@ static uint32_t render_workspace_button(struct render_context *ctx,
|
||||||
struct swaybar_workspace *ws, double *x) {
|
struct swaybar_workspace *ws, double *x) {
|
||||||
struct swaybar_output *output = ctx->output;
|
struct swaybar_output *output = ctx->output;
|
||||||
struct swaybar_config *config = output->bar->config;
|
struct swaybar_config *config = output->bar->config;
|
||||||
|
|
||||||
struct box_colors box_colors;
|
struct box_colors box_colors;
|
||||||
if (ws->urgent) {
|
if (ws->urgent) {
|
||||||
box_colors = config->colors.urgent_workspace;
|
box_colors = config->colors.urgent_workspace;
|
||||||
|
|
@ -629,66 +641,21 @@ static uint32_t render_workspace_button(struct render_context *ctx,
|
||||||
box_colors = config->colors.inactive_workspace;
|
box_colors = config->colors.inactive_workspace;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t height = output->height;
|
struct box_size size = render_box(ctx, *x, box_colors,
|
||||||
|
ws->label, config->pango_markup);
|
||||||
cairo_t *cairo = ctx->cairo;
|
|
||||||
int text_width, text_height;
|
|
||||||
get_text_size(cairo, config->font_description, &text_width, &text_height, NULL,
|
|
||||||
1, config->pango_markup, "%s", ws->label);
|
|
||||||
|
|
||||||
int ws_vertical_padding = WS_VERTICAL_PADDING;
|
|
||||||
int ws_horizontal_padding = WS_HORIZONTAL_PADDING;
|
|
||||||
int border_width = BORDER_WIDTH;
|
|
||||||
|
|
||||||
uint32_t ideal_height = ws_vertical_padding * 2 + text_height
|
|
||||||
+ border_width * 2;
|
|
||||||
uint32_t ideal_surface_height = ideal_height;
|
|
||||||
if (!output->bar->config->height &&
|
|
||||||
output->height < ideal_surface_height) {
|
|
||||||
return ideal_surface_height;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t width = text_width + ws_horizontal_padding * 2 + border_width * 2;
|
|
||||||
if (width < config->workspace_min_width) {
|
|
||||||
width = config->workspace_min_width;
|
|
||||||
}
|
|
||||||
|
|
||||||
cairo_set_operator(cairo, CAIRO_OPERATOR_SOURCE);
|
|
||||||
cairo_set_source_u32(cairo, box_colors.background);
|
|
||||||
ctx->background_color = box_colors.background;
|
|
||||||
ctx->has_transparency |= (box_colors.background & 0xFF) != 0xFF;
|
|
||||||
cairo_rectangle(cairo, *x, 0, width, height);
|
|
||||||
cairo_fill(cairo);
|
|
||||||
|
|
||||||
cairo_set_source_u32(cairo, box_colors.border);
|
|
||||||
cairo_rectangle(cairo, *x, 0, width, border_width);
|
|
||||||
cairo_fill(cairo);
|
|
||||||
cairo_rectangle(cairo, *x, 0, border_width, height);
|
|
||||||
cairo_fill(cairo);
|
|
||||||
cairo_rectangle(cairo, *x + width - border_width, 0, border_width, height);
|
|
||||||
cairo_fill(cairo);
|
|
||||||
cairo_rectangle(cairo, *x, height - border_width, width, border_width);
|
|
||||||
cairo_fill(cairo);
|
|
||||||
|
|
||||||
double text_y = height / 2.0 - text_height / 2.0;
|
|
||||||
cairo_set_source_u32(cairo, box_colors.text);
|
|
||||||
cairo_move_to(cairo, *x + width / 2 - text_width / 2, (int)floor(text_y));
|
|
||||||
choose_text_aa_mode(ctx, box_colors.text);
|
|
||||||
render_text(cairo, config->font_description, 1, config->pango_markup,
|
|
||||||
"%s", ws->label);
|
|
||||||
|
|
||||||
struct swaybar_hotspot *hotspot = calloc(1, sizeof(struct swaybar_hotspot));
|
struct swaybar_hotspot *hotspot = calloc(1, sizeof(struct swaybar_hotspot));
|
||||||
hotspot->x = *x;
|
hotspot->x = *x;
|
||||||
hotspot->y = 0;
|
hotspot->y = 0;
|
||||||
hotspot->width = width;
|
hotspot->width = size.width;
|
||||||
hotspot->height = height;
|
hotspot->height = size.height;
|
||||||
hotspot->callback = workspace_hotspot_callback;
|
hotspot->callback = workspace_hotspot_callback;
|
||||||
hotspot->destroy = free;
|
hotspot->destroy = free;
|
||||||
hotspot->data = strdup(ws->name);
|
hotspot->data = strdup(ws->name);
|
||||||
wl_list_insert(&output->hotspots, &hotspot->link);
|
wl_list_insert(&output->hotspots, &hotspot->link);
|
||||||
|
|
||||||
*x += width;
|
*x += size.width;
|
||||||
return output->height;
|
return size.height;
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint32_t render_to_cairo(struct render_context *ctx) {
|
static uint32_t render_to_cairo(struct render_context *ctx) {
|
||||||
|
|
|
||||||
|
|
@ -16,10 +16,6 @@
|
||||||
#include "ipc-client.h"
|
#include "ipc-client.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
|
|
||||||
void sway_terminate(int exit_code) {
|
|
||||||
exit(exit_code);
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool success_object(json_object *result) {
|
static bool success_object(json_object *result) {
|
||||||
json_object *success;
|
json_object *success;
|
||||||
|
|
||||||
|
|
@ -99,7 +95,7 @@ static const char *pretty_type_name(const char *name) {
|
||||||
const char *b;
|
const char *b;
|
||||||
} type_names[] = {
|
} type_names[] = {
|
||||||
{ "keyboard", "Keyboard" },
|
{ "keyboard", "Keyboard" },
|
||||||
{ "pointer", "Mouse" },
|
{ "pointer", "Pointer" },
|
||||||
{ "touchpad", "Touchpad" },
|
{ "touchpad", "Touchpad" },
|
||||||
{ "tablet_pad", "Tablet pad" },
|
{ "tablet_pad", "Tablet pad" },
|
||||||
{ "tablet_tool", "Tablet tool" },
|
{ "tablet_tool", "Tablet tool" },
|
||||||
|
|
|
||||||
|
|
@ -13,11 +13,6 @@ void sig_handler(int signal) {
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
void sway_terminate(int code) {
|
|
||||||
swaynag_destroy(&swaynag);
|
|
||||||
exit(code);
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(int argc, char **argv) {
|
int main(int argc, char **argv) {
|
||||||
int status = EXIT_SUCCESS;
|
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);
|
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_setup(&swaynag);
|
||||||
swaynag_run(&swaynag);
|
swaynag_run(&swaynag);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue