mirror of
https://github.com/swaywm/sway.git
synced 2026-04-06 07:15:44 -04:00
Compare commits
52 commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a1b9aa11d1 | ||
|
|
0940a46c11 | ||
|
|
34f5c1e7c4 | ||
|
|
f22aef018b | ||
|
|
eaec82abd2 | ||
|
|
c6b43359e7 | ||
|
|
f120f70f5a | ||
|
|
d2456c3b37 | ||
|
|
19586ab768 | ||
|
|
9ff59b7c6b | ||
|
|
8dbd4b98f7 | ||
|
|
c07d91ca96 | ||
|
|
b02198a0d1 | ||
|
|
1a46da7fcf | ||
|
|
47abc45e86 | ||
|
|
8d708b8e1d | ||
|
|
f0e8c68ca7 | ||
|
|
ee236afb43 | ||
|
|
1d4b995c0f | ||
|
|
ad34837dda | ||
|
|
d126410de1 | ||
|
|
59b3c4d06e | ||
|
|
e50e1fe058 | ||
|
|
06e03ed878 | ||
|
|
e4e579ea36 | ||
|
|
40023d45a1 | ||
|
|
a5a189cc73 | ||
|
|
a4d7ee1923 | ||
|
|
4e27785980 | ||
|
|
062da8eae7 | ||
|
|
95e16bb744 | ||
|
|
243d5a3a43 | ||
|
|
4339ba6424 | ||
|
|
32f790bd15 | ||
|
|
8229814e7a | ||
|
|
a2f661dceb | ||
|
|
6ade4bd7dd | ||
|
|
d2d2fc545a | ||
|
|
48511c3b35 | ||
|
|
d4e49a49eb | ||
|
|
cc5139d52a | ||
|
|
2112f0aa2f | ||
|
|
0c091bed76 | ||
|
|
9346ed1805 | ||
|
|
41e10db0de | ||
|
|
610794d4e3 | ||
|
|
5d770d028a | ||
|
|
66062f53de | ||
|
|
df3ea6a55f | ||
|
|
4272bf1274 | ||
|
|
130626a5db | ||
|
|
743d345383 |
47 changed files with 394 additions and 202 deletions
|
|
@ -258,6 +258,9 @@ int unescape_string(char *string) {
|
|||
}
|
||||
|
||||
char *join_args(char **argv, int argc) {
|
||||
if (!sway_assert(argc > 0, "argc should be positive")) {
|
||||
return NULL;
|
||||
}
|
||||
int len = 0, i;
|
||||
for (i = 0; i < argc; ++i) {
|
||||
len += strlen(argv[i]) + 1;
|
||||
|
|
|
|||
|
|
@ -112,7 +112,6 @@ sway_cmd cmd_client_placeholder;
|
|||
sway_cmd cmd_client_background;
|
||||
sway_cmd cmd_commands;
|
||||
sway_cmd cmd_create_output;
|
||||
sway_cmd cmd_debuglog;
|
||||
sway_cmd cmd_default_border;
|
||||
sway_cmd cmd_default_floating_border;
|
||||
sway_cmd cmd_default_orientation;
|
||||
|
|
|
|||
|
|
@ -586,6 +586,8 @@ struct output_config *store_output_config(struct output_config *oc);
|
|||
|
||||
void apply_output_config_to_outputs(struct output_config *oc);
|
||||
|
||||
void reset_outputs(void);
|
||||
|
||||
void free_output_config(struct output_config *oc);
|
||||
|
||||
int workspace_output_cmp_workspace(const void *a, const void *b);
|
||||
|
|
|
|||
|
|
@ -72,6 +72,7 @@ struct sway_cursor *sway_cursor_create(struct sway_seat *seat);
|
|||
* This chooses a cursor icon and sends a motion event to the surface.
|
||||
*/
|
||||
void cursor_rebase(struct sway_cursor *cursor);
|
||||
void cursor_rebase_all(void);
|
||||
|
||||
void cursor_handle_activity(struct sway_cursor *cursor);
|
||||
void cursor_unhide(struct sway_cursor *cursor);
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ void input_manager_apply_seat_config(struct seat_config *seat_config);
|
|||
|
||||
struct sway_seat *input_manager_get_default_seat(void);
|
||||
|
||||
struct sway_seat *input_manager_get_seat(const char *seat_name);
|
||||
struct sway_seat *input_manager_get_seat(const char *seat_name, bool create);
|
||||
|
||||
/**
|
||||
* If none of the seat configs have a fallback setting (either true or false),
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ struct sway_output {
|
|||
struct sway_node node;
|
||||
struct wlr_output *wlr_output;
|
||||
struct sway_server *server;
|
||||
struct wl_list link;
|
||||
|
||||
struct wl_list layers[4]; // sway_layer_surface::link
|
||||
struct wlr_box usable_area;
|
||||
|
|
@ -36,6 +37,8 @@ struct sway_output {
|
|||
|
||||
struct sway_output_state current;
|
||||
|
||||
struct wl_client *swaybg_client;
|
||||
|
||||
struct wl_listener destroy;
|
||||
struct wl_listener mode;
|
||||
struct wl_listener transform;
|
||||
|
|
@ -43,10 +46,7 @@ struct sway_output {
|
|||
struct wl_listener present;
|
||||
struct wl_listener damage_destroy;
|
||||
struct wl_listener damage_frame;
|
||||
|
||||
struct wl_list link;
|
||||
|
||||
pid_t bg_pid;
|
||||
struct wl_listener swaybg_client_destroy;
|
||||
|
||||
struct {
|
||||
struct wl_signal destroy;
|
||||
|
|
|
|||
|
|
@ -46,6 +46,8 @@ struct swaybar {
|
|||
#if HAVE_TRAY
|
||||
struct swaybar_tray *tray;
|
||||
#endif
|
||||
|
||||
bool running;
|
||||
};
|
||||
|
||||
struct swaybar_output {
|
||||
|
|
|
|||
23
meson.build
23
meson.build
|
|
@ -1,6 +1,7 @@
|
|||
project(
|
||||
'sway',
|
||||
'c',
|
||||
version: '1.0',
|
||||
license: 'MIT',
|
||||
meson_version: '>=0.48.0',
|
||||
default_options: [
|
||||
|
|
@ -59,7 +60,11 @@ rt = cc.find_library('rt')
|
|||
git = find_program('git', required: false)
|
||||
|
||||
# Try first to find wlroots as a subproject, then as a system dependency
|
||||
wlroots_proj = subproject('wlroots', required: false)
|
||||
wlroots_proj = subproject(
|
||||
'wlroots',
|
||||
default_options: ['rootston=false', 'examples=false'],
|
||||
required: false,
|
||||
)
|
||||
if wlroots_proj.found()
|
||||
wlroots = wlroots_proj.get_variable('wlroots')
|
||||
wlroots_conf = wlroots_proj.get_variable('conf_data')
|
||||
|
|
@ -127,17 +132,13 @@ endif
|
|||
|
||||
add_project_arguments('-DSYSCONFDIR="/@0@"'.format(join_paths(prefix, sysconfdir)), language : 'c')
|
||||
|
||||
version = get_option('sway-version')
|
||||
if version != ''
|
||||
version = '"@0@"'.format(version)
|
||||
else
|
||||
if not git.found()
|
||||
error('git is required to make the version string')
|
||||
version = '"@0@"'.format(meson.project_version())
|
||||
if git.found()
|
||||
git_commit_hash = run_command([git.path(), 'describe', '--always', '--tags'])
|
||||
git_branch = run_command([git.path(), 'rev-parse', '--abbrev-ref', 'HEAD'])
|
||||
if git_commit_hash.returncode() == 0 and git_branch.returncode() == 0
|
||||
version = '"@0@ (" __DATE__ ", branch \'@1@\')"'.format(git_commit_hash.stdout().strip(), git_branch.stdout().strip())
|
||||
endif
|
||||
|
||||
git_commit_hash = run_command([git.path(), 'describe', '--always', '--tags']).stdout().strip()
|
||||
git_branch = run_command([git.path(), 'rev-parse', '--abbrev-ref', 'HEAD']).stdout().strip()
|
||||
version = '"@0@ (" __DATE__ ", branch \'@1@\')"'.format(git_commit_hash, git_branch)
|
||||
endif
|
||||
add_project_arguments('-DSWAY_VERSION=@0@'.format(version), language: 'c')
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
option('sway-version', type : 'string', description: 'The version string reported in `sway --version`.')
|
||||
option('default-wallpaper', type: 'boolean', value: true, description: 'Install the default wallpaper.')
|
||||
option('zsh-completions', type: 'boolean', value: true, description: 'Install zsh shell completions.')
|
||||
option('bash-completions', type: 'boolean', value: true, description: 'Install bash shell completions.')
|
||||
|
|
|
|||
|
|
@ -254,7 +254,8 @@ list_t *execute_command(char *_exec, struct sway_seat *seat,
|
|||
//TODO better handling of argv
|
||||
int argc;
|
||||
char **argv = split_args(cmd, &argc);
|
||||
if (strcmp(argv[0], "exec") != 0) {
|
||||
if (strcmp(argv[0], "exec") != 0 &&
|
||||
strcmp(argv[0], "exec_always") != 0) {
|
||||
int i;
|
||||
for (i = 1; i < argc; ++i) {
|
||||
if (*argv[i] == '\"' || *argv[i] == '\'') {
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ static struct cmd_results *bar_set_mode(struct bar_config *bar, const char *mode
|
|||
if (strcasecmp("toggle", mode) == 0 && !config->reading) {
|
||||
if (strcasecmp("dock", bar->mode) == 0) {
|
||||
bar->mode = strdup("hide");
|
||||
} else if (strcasecmp("hide", bar->mode) == 0) {
|
||||
} else{
|
||||
bar->mode = strdup("dock");
|
||||
}
|
||||
} else if (strcasecmp("dock", mode) == 0) {
|
||||
|
|
|
|||
|
|
@ -15,11 +15,17 @@ struct cmd_results *bar_cmd_modifier(int argc, char **argv) {
|
|||
}
|
||||
|
||||
uint32_t mod = 0;
|
||||
if (strcmp(argv[0], "none") != 0) {
|
||||
list_t *split = split_string(argv[0], "+");
|
||||
for (int i = 0; i < split->length; ++i) {
|
||||
uint32_t tmp_mod;
|
||||
if ((tmp_mod = get_modifier_mask_by_name(split->items[i])) > 0) {
|
||||
mod |= tmp_mod;
|
||||
} else if (strcmp(split->items[i], "none") == 0) {
|
||||
error = cmd_results_new(CMD_INVALID,
|
||||
"none cannot be used along with other modifiers");
|
||||
list_free_items_and_destroy(split);
|
||||
return error;
|
||||
} else {
|
||||
error = cmd_results_new(CMD_INVALID,
|
||||
"Unknown modifier '%s'", (char *)split->items[i]);
|
||||
|
|
@ -28,6 +34,7 @@ struct cmd_results *bar_cmd_modifier(int argc, char **argv) {
|
|||
}
|
||||
}
|
||||
list_free_items_and_destroy(split);
|
||||
}
|
||||
config->current_bar->modifier = mod;
|
||||
sway_log(SWAY_DEBUG,
|
||||
"Show/Hide the bar when pressing '%s' in hide mode.", argv[0]);
|
||||
|
|
|
|||
|
|
@ -1,10 +1,11 @@
|
|||
#define _POSIX_C_SOURCE 200809L
|
||||
#include <libevdev/libevdev.h>
|
||||
#include <linux/input-event-codes.h>
|
||||
#include <xkbcommon/xkbcommon.h>
|
||||
#include <xkbcommon/xkbcommon-names.h>
|
||||
#include <string.h>
|
||||
#include <strings.h>
|
||||
#include <xkbcommon/xkbcommon.h>
|
||||
#include <xkbcommon/xkbcommon-names.h>
|
||||
#include <wlr/types/wlr_cursor.h>
|
||||
#include "sway/commands.h"
|
||||
#include "sway/config.h"
|
||||
#include "sway/input/cursor.h"
|
||||
|
|
@ -330,7 +331,20 @@ struct cmd_results *cmd_bindcode(int argc, char **argv) {
|
|||
void seat_execute_command(struct sway_seat *seat, struct sway_binding *binding) {
|
||||
sway_log(SWAY_DEBUG, "running command for binding: %s", binding->command);
|
||||
|
||||
list_t *res_list = execute_command(binding->command, seat, NULL);
|
||||
struct sway_container *con = NULL;
|
||||
if (binding->type == BINDING_MOUSESYM
|
||||
|| binding->type == BINDING_MOUSECODE) {
|
||||
struct wlr_surface *surface = NULL;
|
||||
double sx, sy;
|
||||
struct sway_node *node = node_at_coords(seat,
|
||||
seat->cursor->cursor->x, seat->cursor->cursor->y,
|
||||
&surface, &sx, &sy);
|
||||
if (node && node->type == N_CONTAINER) {
|
||||
con = node->sway_container;
|
||||
}
|
||||
}
|
||||
|
||||
list_t *res_list = execute_command(binding->command, seat, con);
|
||||
bool success = true;
|
||||
for (int i = 0; i < res_list->length; ++i) {
|
||||
struct cmd_results *results = res_list->items[i];
|
||||
|
|
|
|||
|
|
@ -516,7 +516,6 @@ static struct cmd_results *cmd_move_container(int argc, char **argv) {
|
|||
|
||||
// move container
|
||||
if (container->scratchpad) {
|
||||
root_scratchpad_remove_container(container);
|
||||
root_scratchpad_show(container);
|
||||
}
|
||||
switch (destination->type) {
|
||||
|
|
|
|||
|
|
@ -61,6 +61,9 @@ struct cmd_results *output_cmd_background(int argc, char **argv) {
|
|||
return cmd_results_new(CMD_INVALID,
|
||||
"Missing background scaling mode.");
|
||||
}
|
||||
if (j == 0) {
|
||||
return cmd_results_new(CMD_INVALID, "Missing background file");
|
||||
}
|
||||
|
||||
wordexp_t p = {0};
|
||||
char *src = join_args(argv, j);
|
||||
|
|
|
|||
|
|
@ -50,5 +50,5 @@ struct cmd_results *cmd_seat(int argc, char **argv) {
|
|||
}
|
||||
|
||||
config->handler_context.seat_config = NULL;
|
||||
return cmd_results_new(CMD_SUCCESS, NULL);
|
||||
return res ? res : cmd_results_new(CMD_SUCCESS, NULL);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ static struct cmd_results *press_or_release(struct sway_cursor *cursor,
|
|||
|
||||
static const char expected_syntax[] = "Expected 'cursor <move> <x> <y>' or "
|
||||
"'cursor <set> <x> <y>' or "
|
||||
"'curor <press|release> <button[1-9]|event-name-or-code>'";
|
||||
"'cursor <press|release> <button[1-9]|event-name-or-code>'";
|
||||
|
||||
static struct cmd_results *handle_command(struct sway_cursor *cursor,
|
||||
int argc, char **argv) {
|
||||
|
|
@ -61,9 +61,10 @@ struct cmd_results *seat_cmd_cursor(int argc, char **argv) {
|
|||
}
|
||||
|
||||
if (strcmp(sc->name, "*") != 0) {
|
||||
struct sway_seat *seat = input_manager_get_seat(sc->name);
|
||||
struct sway_seat *seat = input_manager_get_seat(sc->name, false);
|
||||
if (!seat) {
|
||||
return cmd_results_new(CMD_FAILURE, "Failed to get seat");
|
||||
return cmd_results_new(CMD_FAILURE,
|
||||
"Seat %s does not exist", sc->name);
|
||||
}
|
||||
error = handle_command(seat->cursor, argc, argv);
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -76,7 +76,6 @@ static struct cmd_results *cmd_workspace_gaps(int argc, char **argv,
|
|||
char *end;
|
||||
int amount = strtol(argv[gaps_location + 2], &end, 10);
|
||||
if (strlen(end)) {
|
||||
free(end);
|
||||
return cmd_results_new(CMD_FAILURE, expected);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -118,7 +118,7 @@ void free_config(struct sway_config *config) {
|
|||
}
|
||||
list_free(config->no_focus);
|
||||
list_free(config->active_bar_modifiers);
|
||||
list_free(config->config_chain);
|
||||
list_free_items_and_destroy(config->config_chain);
|
||||
list_free(config->command_policies);
|
||||
list_free(config->feature_policies);
|
||||
list_free(config->ipc_policies);
|
||||
|
|
@ -141,13 +141,20 @@ static void destroy_removed_seats(struct sway_config *old_config,
|
|||
int i;
|
||||
for (i = 0; i < old_config->seat_configs->length; i++) {
|
||||
seat_config = old_config->seat_configs->items[i];
|
||||
// Skip the wildcard seat config, it won't have a matching real seat.
|
||||
if (strcmp(seat_config->name, "*") == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Also destroy seats that aren't present in new config */
|
||||
if (new_config && list_seq_find(new_config->seat_configs,
|
||||
seat_name_cmp, seat_config->name) < 0) {
|
||||
seat = input_manager_get_seat(seat_config->name);
|
||||
seat = input_manager_get_seat(seat_config->name, false);
|
||||
if (seat) {
|
||||
seat_destroy(seat);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void set_color(float dest[static 4], uint32_t color) {
|
||||
|
|
@ -372,6 +379,13 @@ bool load_main_config(const char *file, bool is_active, bool validating) {
|
|||
path = get_config_path();
|
||||
}
|
||||
|
||||
char *real_path = realpath(path, NULL);
|
||||
if (real_path == NULL) {
|
||||
sway_log(SWAY_DEBUG, "%s not found.", path);
|
||||
free(path);
|
||||
return false;
|
||||
}
|
||||
|
||||
struct sway_config *old_config = config;
|
||||
config = calloc(1, sizeof(struct sway_config));
|
||||
if (!config) {
|
||||
|
|
@ -395,7 +409,7 @@ bool load_main_config(const char *file, bool is_active, bool validating) {
|
|||
}
|
||||
|
||||
config->current_config_path = path;
|
||||
list_add(config->config_chain, path);
|
||||
list_add(config->config_chain, real_path);
|
||||
|
||||
config->reading = true;
|
||||
|
||||
|
|
@ -457,9 +471,8 @@ bool load_main_config(const char *file, bool is_active, bool validating) {
|
|||
}
|
||||
|
||||
if (is_active) {
|
||||
for (int i = 0; i < config->output_configs->length; i++) {
|
||||
apply_output_config_to_outputs(config->output_configs->items[i]);
|
||||
}
|
||||
reset_outputs();
|
||||
|
||||
config->reloading = false;
|
||||
if (config->swaynag_config_errors.pid > 0) {
|
||||
swaynag_show(&config->swaynag_config_errors);
|
||||
|
|
@ -550,7 +563,7 @@ bool load_include_configs(const char *path, struct sway_config *config,
|
|||
|
||||
wordexp_t p;
|
||||
|
||||
if (wordexp(path, &p, 0) < 0) {
|
||||
if (wordexp(path, &p, 0) != 0) {
|
||||
free(parent_path);
|
||||
free(wd);
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@ void free_bar_config(struct bar_config *bar) {
|
|||
free(bar->position);
|
||||
free(bar->hidden_state);
|
||||
free(bar->status_command);
|
||||
free(bar->swaybar_command);
|
||||
free(bar->font);
|
||||
free(bar->separator_symbol);
|
||||
for (int i = 0; i < bar->bindings->length; i++) {
|
||||
|
|
|
|||
|
|
@ -1,16 +1,17 @@
|
|||
#define _POSIX_C_SOURCE 200809L
|
||||
#include <assert.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include <signal.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/wait.h>
|
||||
#include <unistd.h>
|
||||
#include <wlr/types/wlr_output.h>
|
||||
#include <wlr/types/wlr_output_layout.h>
|
||||
#include <wlr/types/wlr_output.h>
|
||||
#include "log.h"
|
||||
#include "sway/config.h"
|
||||
#include "sway/output.h"
|
||||
#include "sway/tree/root.h"
|
||||
#include "log.h"
|
||||
|
||||
int output_name_cmp(const void *item, const void *data) {
|
||||
const struct output_config *output = item;
|
||||
|
|
@ -165,14 +166,71 @@ static bool set_mode(struct wlr_output *output, int width, int height,
|
|||
return wlr_output_set_mode(output, best);
|
||||
}
|
||||
|
||||
void terminate_swaybg(pid_t pid) {
|
||||
int ret = kill(pid, SIGTERM);
|
||||
if (ret != 0) {
|
||||
sway_log(SWAY_ERROR, "Unable to terminate swaybg [pid: %d]", pid);
|
||||
} else {
|
||||
int status;
|
||||
waitpid(pid, &status, 0);
|
||||
static void handle_swaybg_client_destroy(struct wl_listener *listener,
|
||||
void *data) {
|
||||
struct sway_output *output =
|
||||
wl_container_of(listener, output, swaybg_client_destroy);
|
||||
wl_list_remove(&output->swaybg_client_destroy.link);
|
||||
wl_list_init(&output->swaybg_client_destroy.link);
|
||||
output->swaybg_client = NULL;
|
||||
}
|
||||
|
||||
static bool spawn_swaybg(struct sway_output *output, char *const cmd[]) {
|
||||
int sockets[2];
|
||||
if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, sockets) != 0) {
|
||||
sway_log_errno(SWAY_ERROR, "socketpair failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
output->swaybg_client = wl_client_create(server.wl_display, sockets[0]);
|
||||
if (output->swaybg_client == NULL) {
|
||||
sway_log_errno(SWAY_ERROR, "wl_client_create failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
output->swaybg_client_destroy.notify = handle_swaybg_client_destroy;
|
||||
wl_client_add_destroy_listener(output->swaybg_client,
|
||||
&output->swaybg_client_destroy);
|
||||
|
||||
pid_t pid = fork();
|
||||
if (pid < 0) {
|
||||
sway_log_errno(SWAY_ERROR, "fork failed");
|
||||
return false;
|
||||
} else if (pid == 0) {
|
||||
pid = fork();
|
||||
if (pid < 0) {
|
||||
sway_log_errno(SWAY_ERROR, "fork failed");
|
||||
exit(EXIT_FAILURE);
|
||||
} else if (pid == 0) {
|
||||
// Remove the CLOEXEC flag
|
||||
int flags = fcntl(sockets[1], F_GETFD);
|
||||
if (flags == -1) {
|
||||
sway_log_errno(SWAY_ERROR, "fcntl() failed");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
if (fcntl(sockets[1], F_SETFD, flags & ~FD_CLOEXEC) == -1) {
|
||||
sway_log_errno(SWAY_ERROR, "fcntl() failed");
|
||||
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(cmd[0], cmd);
|
||||
sway_log_errno(SWAY_ERROR, "execvp failed");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
if (waitpid(pid, NULL, 0) < 0) {
|
||||
sway_log_errno(SWAY_ERROR, "waitpid failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool apply_output_config(struct output_config *oc, struct sway_output *output) {
|
||||
|
|
@ -199,6 +257,11 @@ bool apply_output_config(struct output_config *oc, struct sway_output *output) {
|
|||
return true;
|
||||
}
|
||||
|
||||
if (oc && oc->dpms_state == DPMS_ON) {
|
||||
sway_log(SWAY_DEBUG, "Turning on screen");
|
||||
wlr_output_enable(wlr_output, true);
|
||||
}
|
||||
|
||||
bool modeset_success;
|
||||
if (oc && oc->width > 0 && oc->height > 0) {
|
||||
sway_log(SWAY_DEBUG, "Set %s mode to %dx%d (%f GHz)", oc->name, oc->width,
|
||||
|
|
@ -238,8 +301,8 @@ bool apply_output_config(struct output_config *oc, struct sway_output *output) {
|
|||
wlr_output_layout_add_auto(root->output_layout, wlr_output);
|
||||
}
|
||||
|
||||
if (output->bg_pid != 0) {
|
||||
terminate_swaybg(output->bg_pid);
|
||||
if (output->swaybg_client != NULL) {
|
||||
wl_client_destroy(output->swaybg_client);
|
||||
}
|
||||
if (oc && oc->background && config->swaybg_command) {
|
||||
sway_log(SWAY_DEBUG, "Setting background for output %s to %s",
|
||||
|
|
@ -253,29 +316,14 @@ bool apply_output_config(struct output_config *oc, struct sway_output *output) {
|
|||
oc->background_fallback ? oc->background_fallback : NULL,
|
||||
NULL,
|
||||
};
|
||||
|
||||
output->bg_pid = fork();
|
||||
if (output->bg_pid < 0) {
|
||||
sway_log_errno(SWAY_ERROR, "fork failed");
|
||||
} else if (output->bg_pid == 0) {
|
||||
execvp(cmd[0], cmd);
|
||||
sway_log_errno(SWAY_ERROR, "Failed to execute swaybg");
|
||||
if (!spawn_swaybg(output, cmd)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (oc) {
|
||||
switch (oc->dpms_state) {
|
||||
case DPMS_ON:
|
||||
sway_log(SWAY_DEBUG, "Turning on screen");
|
||||
wlr_output_enable(wlr_output, true);
|
||||
break;
|
||||
case DPMS_OFF:
|
||||
if (oc && oc->dpms_state == DPMS_OFF) {
|
||||
sway_log(SWAY_DEBUG, "Turning off screen");
|
||||
wlr_output_enable(wlr_output, false);
|
||||
break;
|
||||
case DPMS_IGNORE:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
@ -294,6 +342,7 @@ static void default_output_config(struct output_config *oc,
|
|||
oc->x = oc->y = -1;
|
||||
oc->scale = 1;
|
||||
oc->transform = WL_OUTPUT_TRANSFORM_NORMAL;
|
||||
oc->dpms_state = DPMS_ON;
|
||||
}
|
||||
|
||||
static struct output_config *get_output_config(char *identifier,
|
||||
|
|
@ -395,6 +444,17 @@ void apply_output_config_to_outputs(struct output_config *oc) {
|
|||
}
|
||||
}
|
||||
|
||||
void reset_outputs(void) {
|
||||
struct output_config *oc = NULL;
|
||||
int i = list_seq_find(config->output_configs, output_name_cmp, "*");
|
||||
if (i >= 0) {
|
||||
oc = config->output_configs->items[i];
|
||||
} else {
|
||||
oc = store_output_config(new_output_config("*"));
|
||||
}
|
||||
apply_output_config_to_outputs(oc);
|
||||
}
|
||||
|
||||
void free_output_config(struct output_config *oc) {
|
||||
if (!oc) {
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -6,7 +6,9 @@
|
|||
#include <wlr/types/wlr_layer_shell_v1.h>
|
||||
#include <wlr/types/wlr_output_damage.h>
|
||||
#include <wlr/types/wlr_output.h>
|
||||
#include "log.h"
|
||||
#include "sway/desktop/transaction.h"
|
||||
#include "sway/input/cursor.h"
|
||||
#include "sway/input/input-manager.h"
|
||||
#include "sway/input/seat.h"
|
||||
#include "sway/layers.h"
|
||||
|
|
@ -14,7 +16,6 @@
|
|||
#include "sway/server.h"
|
||||
#include "sway/tree/arrange.h"
|
||||
#include "sway/tree/workspace.h"
|
||||
#include "log.h"
|
||||
|
||||
static void apply_exclusive(struct wlr_box *usable_area,
|
||||
uint32_t anchor, int32_t exclusive,
|
||||
|
|
@ -302,6 +303,8 @@ static void unmap(struct sway_layer_surface *sway_layer) {
|
|||
if (seat->focused_layer == sway_layer->layer_surface) {
|
||||
seat_set_focus_layer(seat, NULL);
|
||||
}
|
||||
|
||||
cursor_rebase_all();
|
||||
}
|
||||
|
||||
static void handle_destroy(struct wl_listener *listener, void *data) {
|
||||
|
|
@ -321,7 +324,6 @@ static void handle_destroy(struct wl_listener *listener, void *data) {
|
|||
struct sway_output *output = sway_layer->layer_surface->output->data;
|
||||
if (output != NULL) {
|
||||
arrange_layers(output);
|
||||
arrange_output(output);
|
||||
transaction_commit_dirty();
|
||||
}
|
||||
wl_list_remove(&sway_layer->output_destroy.link);
|
||||
|
|
@ -339,6 +341,7 @@ static void handle_map(struct wl_listener *listener, void *data) {
|
|||
// TODO: send enter to subsurfaces and popups
|
||||
wlr_surface_send_enter(sway_layer->layer_surface->surface,
|
||||
sway_layer->layer_surface->output);
|
||||
cursor_rebase_all();
|
||||
}
|
||||
|
||||
static void handle_unmap(struct wl_listener *listener, void *data) {
|
||||
|
|
|
|||
|
|
@ -506,6 +506,7 @@ static void handle_destroy(struct wl_listener *listener, void *data) {
|
|||
wl_list_remove(&output->present.link);
|
||||
wl_list_remove(&output->damage_destroy.link);
|
||||
wl_list_remove(&output->damage_frame.link);
|
||||
wl_list_remove(&output->swaybg_client_destroy.link);
|
||||
|
||||
transaction_commit_dirty();
|
||||
}
|
||||
|
|
@ -612,6 +613,7 @@ void handle_new_output(struct wl_listener *listener, void *data) {
|
|||
output->damage_frame.notify = damage_handle_frame;
|
||||
wl_signal_add(&output->damage->events.destroy, &output->damage_destroy);
|
||||
output->damage_destroy.notify = damage_handle_destroy;
|
||||
wl_list_init(&output->swaybg_client_destroy.link);
|
||||
|
||||
struct output_config *oc = output_find_config(output);
|
||||
if (!oc || oc->enabled) {
|
||||
|
|
|
|||
|
|
@ -314,14 +314,7 @@ static void transaction_apply(struct sway_transaction *transaction) {
|
|||
node->instruction = NULL;
|
||||
}
|
||||
|
||||
if (root->outputs->length) {
|
||||
struct sway_seat *seat;
|
||||
wl_list_for_each(seat, &server.input->seats, link) {
|
||||
if (!seat_doing_seatop(seat)) {
|
||||
cursor_rebase(seat->cursor);
|
||||
}
|
||||
}
|
||||
}
|
||||
cursor_rebase_all();
|
||||
}
|
||||
|
||||
static void transaction_commit(struct sway_transaction *transaction);
|
||||
|
|
|
|||
|
|
@ -236,19 +236,11 @@ static void _close(struct sway_view *view) {
|
|||
}
|
||||
}
|
||||
|
||||
static void close_popups_iterator(struct wlr_surface *surface,
|
||||
int sx, int sy, void *data) {
|
||||
struct wlr_xdg_surface *xdg_surface =
|
||||
wlr_xdg_surface_from_wlr_surface(surface);
|
||||
if (xdg_surface->role == WLR_XDG_SURFACE_ROLE_POPUP
|
||||
&& xdg_surface->popup) {
|
||||
wlr_xdg_popup_destroy(xdg_surface);
|
||||
}
|
||||
}
|
||||
|
||||
static void close_popups(struct sway_view *view) {
|
||||
wlr_xdg_surface_for_each_popup(view->wlr_xdg_surface,
|
||||
close_popups_iterator, NULL);
|
||||
struct wlr_xdg_popup *popup, *tmp;
|
||||
wl_list_for_each_safe(popup, tmp, &view->wlr_xdg_surface->popups, link) {
|
||||
wlr_xdg_popup_destroy(popup->base);
|
||||
}
|
||||
}
|
||||
|
||||
static void destroy(struct sway_view *view) {
|
||||
|
|
|
|||
|
|
@ -283,6 +283,19 @@ void cursor_rebase(struct sway_cursor *cursor) {
|
|||
cursor_do_rebase(cursor, time_msec, cursor->previous.node, surface, sx, sy);
|
||||
}
|
||||
|
||||
void cursor_rebase_all(void) {
|
||||
if (!root->outputs->length) {
|
||||
return;
|
||||
}
|
||||
|
||||
struct sway_seat *seat;
|
||||
wl_list_for_each(seat, &server.input->seats, link) {
|
||||
if (!seat_doing_seatop(seat)) {
|
||||
cursor_rebase(seat->cursor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int hide_notify(void *data) {
|
||||
struct sway_cursor *cursor = data;
|
||||
wlr_cursor_set_image(cursor->cursor, NULL, 0, 0, 0, 0, 0, 0);
|
||||
|
|
@ -362,7 +375,7 @@ void cursor_send_pointer_motion(struct sway_cursor *cursor, uint32_t time_msec,
|
|||
struct sway_output *focused_output = node_get_output(focus);
|
||||
struct sway_output *output = node_get_output(node);
|
||||
if (output != focused_output) {
|
||||
seat_set_focus(seat, node);
|
||||
seat_set_focus(seat, seat_get_focus_inactive(seat, node));
|
||||
}
|
||||
} else if (node->type == N_CONTAINER && node->sway_container->view) {
|
||||
// Focus node if the following are true:
|
||||
|
|
@ -408,15 +421,16 @@ static void handle_cursor_motion(struct wl_listener *listener, void *data) {
|
|||
|
||||
wlr_relative_pointer_manager_v1_send_relative_motion(
|
||||
server.relative_pointer_manager,
|
||||
cursor->seat->wlr_seat, event->time_msec, dx, dy,
|
||||
dx_unaccel, dy_unaccel);
|
||||
cursor->seat->wlr_seat, (uint64_t)event->time_msec * 1000,
|
||||
dx, dy, dx_unaccel, dy_unaccel);
|
||||
|
||||
struct wlr_surface *surface = NULL;
|
||||
struct sway_node *node = NULL;
|
||||
double sx, sy;
|
||||
struct sway_node *node = node_at_coords(cursor->seat,
|
||||
if (cursor->active_constraint) {
|
||||
node = node_at_coords(cursor->seat,
|
||||
cursor->cursor->x, cursor->cursor->y, &surface, &sx, &sy);
|
||||
|
||||
if (cursor->active_constraint) {
|
||||
if (cursor->active_constraint->surface != surface) {
|
||||
return;
|
||||
}
|
||||
|
|
@ -432,8 +446,13 @@ static void handle_cursor_motion(struct wl_listener *listener, void *data) {
|
|||
}
|
||||
|
||||
wlr_cursor_move(cursor->cursor, event->device, dx, dy);
|
||||
|
||||
// Recalculate pointer location after layout checks
|
||||
node = node_at_coords(cursor->seat,
|
||||
cursor->cursor->x, cursor->cursor->y, &surface, &sx, &sy);
|
||||
|
||||
cursor_send_pointer_motion(cursor, event->time_msec, node, surface,
|
||||
sx + dx, sy + dy);
|
||||
sx, sy);
|
||||
transaction_commit_dirty();
|
||||
}
|
||||
|
||||
|
|
@ -1459,7 +1478,11 @@ void handle_pointer_constraint(struct wl_listener *listener, void *data) {
|
|||
void sway_cursor_constrain(struct sway_cursor *cursor,
|
||||
struct wlr_pointer_constraint_v1 *constraint) {
|
||||
struct seat_config *config = seat_get_config(cursor->seat);
|
||||
if (config->allow_constrain == CONSTRAIN_DISABLE) {
|
||||
if (!config) {
|
||||
config = seat_get_config_by_name("*");
|
||||
}
|
||||
|
||||
if (!config || config->allow_constrain == CONSTRAIN_DISABLE) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -31,10 +31,10 @@ struct sway_seat *input_manager_current_seat(void) {
|
|||
}
|
||||
|
||||
struct sway_seat *input_manager_get_default_seat(void) {
|
||||
return input_manager_get_seat(DEFAULT_SEAT);
|
||||
return input_manager_get_seat(DEFAULT_SEAT, true);
|
||||
}
|
||||
|
||||
struct sway_seat *input_manager_get_seat(const char *seat_name) {
|
||||
struct sway_seat *input_manager_get_seat(const char *seat_name, bool create) {
|
||||
struct sway_seat *seat = NULL;
|
||||
wl_list_for_each(seat, &server.input->seats, link) {
|
||||
if (strcmp(seat->wlr_seat->name, seat_name) == 0) {
|
||||
|
|
@ -42,7 +42,7 @@ struct sway_seat *input_manager_get_seat(const char *seat_name) {
|
|||
}
|
||||
}
|
||||
|
||||
return seat_create(seat_name);
|
||||
return create ? seat_create(seat_name) : NULL;
|
||||
}
|
||||
|
||||
char *input_device_get_identifier(struct wlr_input_device *device) {
|
||||
|
|
@ -674,7 +674,8 @@ void input_manager_apply_seat_config(struct seat_config *seat_config) {
|
|||
seat_apply_config(seat, sc);
|
||||
}
|
||||
} else {
|
||||
struct sway_seat *seat = input_manager_get_seat(seat_config->name);
|
||||
struct sway_seat *seat =
|
||||
input_manager_get_seat(seat_config->name, true);
|
||||
if (!seat) {
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -425,7 +425,8 @@ static void determine_bar_visibility(uint32_t modifiers) {
|
|||
for (int i = 0; i < config->bars->length; ++i) {
|
||||
struct bar_config *bar = config->bars->items[i];
|
||||
if (strcmp(bar->mode, bar->hidden_state) == 0) { // both are "hide"
|
||||
bool should_be_visible = (~modifiers & bar->modifier) == 0;
|
||||
bool should_be_visible =
|
||||
bar->modifier != 0 && (~modifiers & bar->modifier) == 0;
|
||||
if (bar->visible_by_modifier != should_be_visible) {
|
||||
bar->visible_by_modifier = should_be_visible;
|
||||
ipc_event_bar_state_update(bar);
|
||||
|
|
@ -548,13 +549,17 @@ void sway_keyboard_configure(struct sway_keyboard *keyboard) {
|
|||
wlr_keyboard_led_update(wlr_device->keyboard, leds);
|
||||
}
|
||||
|
||||
if (input_config && input_config->repeat_delay != INT_MIN
|
||||
&& input_config->repeat_rate != INT_MIN) {
|
||||
wlr_keyboard_set_repeat_info(wlr_device->keyboard,
|
||||
input_config->repeat_rate, input_config->repeat_delay);
|
||||
} else {
|
||||
wlr_keyboard_set_repeat_info(wlr_device->keyboard, 25, 600);
|
||||
int repeat_rate = 25;
|
||||
if (input_config && input_config->repeat_rate != INT_MIN) {
|
||||
repeat_rate = input_config->repeat_rate;
|
||||
}
|
||||
int repeat_delay = 600;
|
||||
if (input_config && input_config->repeat_delay != INT_MIN) {
|
||||
repeat_delay = input_config->repeat_delay;
|
||||
}
|
||||
wlr_keyboard_set_repeat_info(wlr_device->keyboard, repeat_rate,
|
||||
repeat_delay);
|
||||
|
||||
xkb_context_unref(context);
|
||||
struct wlr_seat *seat = keyboard->seat_device->sway_seat->wlr_seat;
|
||||
wlr_seat_set_keyboard(seat, wlr_device);
|
||||
|
|
|
|||
|
|
@ -525,6 +525,7 @@ static void seat_configure_touch(struct sway_seat *seat,
|
|||
|
||||
static void seat_configure_tablet_tool(struct sway_seat *seat,
|
||||
struct sway_seat_device *sway_device) {
|
||||
seat_configure_xcursor(seat);
|
||||
wlr_cursor_attach_input_device(seat->cursor->cursor,
|
||||
sway_device->input_device->wlr_device);
|
||||
seat_apply_input_config(seat, sway_device);
|
||||
|
|
@ -724,6 +725,10 @@ void seat_set_raw_focus(struct sway_seat *seat, struct sway_node *node) {
|
|||
|
||||
void seat_set_focus(struct sway_seat *seat, struct sway_node *node) {
|
||||
if (seat->focused_layer) {
|
||||
struct wlr_layer_surface_v1 *layer = seat->focused_layer;
|
||||
seat_set_focus_layer(seat, NULL);
|
||||
seat_set_focus(seat, node);
|
||||
seat_set_focus_layer(seat, layer);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -150,6 +150,9 @@ static void handle_motion_postthreshold(struct sway_seat *seat) {
|
|||
}
|
||||
if (edge) {
|
||||
e->target_node = node_get_parent(&con->node);
|
||||
if (e->target_node == &e->con->node) {
|
||||
e->target_node = node_get_parent(e->target_node);
|
||||
}
|
||||
e->target_edge = edge;
|
||||
node_get_box(e->target_node, &e->drop_box);
|
||||
resize_box(&e->drop_box, edge, DROP_LAYOUT_BORDER);
|
||||
|
|
@ -161,7 +164,8 @@ static void handle_motion_postthreshold(struct sway_seat *seat) {
|
|||
|
||||
// Use the hovered view - but we must be over the actual surface
|
||||
con = node->sway_container;
|
||||
if (!con->view->surface || node == &e->con->node) {
|
||||
if (!con->view->surface || node == &e->con->node
|
||||
|| node_has_ancestor(node, &e->con->node)) {
|
||||
e->target_node = NULL;
|
||||
e->target_edge = WLR_EDGE_NONE;
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -597,7 +597,7 @@ json_object *ipc_json_describe_input(struct sway_input_device *device) {
|
|||
const char *layout =
|
||||
xkb_keymap_layout_get_name(keymap, layout_idx);
|
||||
json_object_object_add(object, "xkb_active_layout_name",
|
||||
json_object_new_string(layout));
|
||||
layout ? json_object_new_string(layout) : NULL);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -264,7 +264,7 @@ int ipc_client_handle_readable(int client_fd, uint32_t mask, void *data) {
|
|||
static bool ipc_has_event_listeners(enum ipc_command_type event) {
|
||||
for (int i = 0; i < ipc_client_list->length; i++) {
|
||||
struct ipc_client *client = ipc_client_list->items[i];
|
||||
if ((client->subscribed_events & event_mask(event)) == 0) {
|
||||
if ((client->subscribed_events & event_mask(event)) != 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -595,6 +595,16 @@ void ipc_client_handle_command(struct ipc_client *client) {
|
|||
switch (client->current_command) {
|
||||
case IPC_COMMAND:
|
||||
{
|
||||
char *line = strtok(buf, "\n");
|
||||
while (line) {
|
||||
size_t line_length = strlen(line);
|
||||
if (line + line_length >= buf + client->payload_length) {
|
||||
break;
|
||||
}
|
||||
line[line_length] = ';';
|
||||
line = strtok(NULL, "\n");
|
||||
}
|
||||
|
||||
list_t *res_list = execute_command(buf, NULL, NULL);
|
||||
transaction_commit_dirty();
|
||||
char *json = cmd_results_to_json(res_list);
|
||||
|
|
|
|||
33
sway/main.c
33
sway/main.c
|
|
@ -299,6 +299,14 @@ int main(int argc, char **argv) {
|
|||
}
|
||||
}
|
||||
|
||||
// Since wayland requires XDG_RUNTIME_DIR to be set, abort with just the
|
||||
// clear error message (when not running as an IPC client).
|
||||
if (!getenv("XDG_RUNTIME_DIR") && optind == argc) {
|
||||
fprintf(stderr,
|
||||
"XDG_RUNTIME_DIR is not set in the environment. Aborting.\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
// As the 'callback' function for wlr_log is equivalent to that for
|
||||
// sway, we do not need to override it.
|
||||
if (debug) {
|
||||
|
|
@ -312,9 +320,21 @@ int main(int argc, char **argv) {
|
|||
wlr_log_init(WLR_ERROR, NULL);
|
||||
}
|
||||
|
||||
log_kernel();
|
||||
log_distro();
|
||||
log_env();
|
||||
detect_proprietary(allow_unsupported_gpu);
|
||||
detect_raspi();
|
||||
|
||||
if (optind < argc) { // Behave as IPC client
|
||||
if (optind != 1) {
|
||||
sway_log(SWAY_ERROR, "Don't use options with the IPC client");
|
||||
sway_log(SWAY_ERROR,
|
||||
"Detected both options and positional arguments. If you "
|
||||
"are trying to use the IPC client, options are not "
|
||||
"supported. Otherwise, check the provided arguments for "
|
||||
"issues. See `man 1 sway` or `sway -h` for usage. If you "
|
||||
"are trying to generate a debug log, use "
|
||||
"`sway -d 2>sway.log`.");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
if (!drop_permissions()) {
|
||||
|
|
@ -334,11 +354,6 @@ int main(int argc, char **argv) {
|
|||
return 1;
|
||||
}
|
||||
|
||||
log_kernel();
|
||||
log_distro();
|
||||
detect_proprietary(allow_unsupported_gpu);
|
||||
detect_raspi();
|
||||
|
||||
if (!drop_permissions()) {
|
||||
server_fini(&server);
|
||||
exit(EXIT_FAILURE);
|
||||
|
|
@ -358,14 +373,14 @@ int main(int argc, char **argv) {
|
|||
return 1;
|
||||
}
|
||||
|
||||
ipc_init(&server);
|
||||
log_env();
|
||||
|
||||
if (validate) {
|
||||
bool valid = load_main_config(config_path, false, true);
|
||||
free(config_path);
|
||||
return valid ? 0 : 1;
|
||||
}
|
||||
|
||||
ipc_init(&server);
|
||||
|
||||
setenv("WAYLAND_DISPLAY", server.socket, true);
|
||||
if (!load_main_config(config_path, false, false)) {
|
||||
sway_terminate(EXIT_FAILURE);
|
||||
|
|
|
|||
|
|
@ -8,6 +8,13 @@ sway-input - input configuration file and commands
|
|||
|
||||
Sway allows for configuration of devices within the sway configuration file.
|
||||
To obtain a list of available device identifiers, run *swaymsg -t get_inputs*.
|
||||
Settings can also be applied to all input devices by using the wildcard, _\*_,
|
||||
in place of _\<identifier\>_ in the commands below.
|
||||
|
||||
Tip: If the configuration settings do not appear to be taking effect, you could
|
||||
try using _\*_ instead of _\<identifier\>_. If it works with the wildcard, try
|
||||
using a different identifier from *swaymsg -t get_inputs* until you find the
|
||||
correct input device.
|
||||
|
||||
# INPUT COMMANDS
|
||||
|
||||
|
|
@ -144,7 +151,13 @@ configured. While sway is running, _-_ (hyphen) can be used as an alias for the
|
|||
current seat. Each seat has an independent keyboard focus and a separate cursor
|
||||
that is controlled by the pointer devices of the seat. This is useful for
|
||||
multiple people using the desktop at the same time with their own devices (each
|
||||
sitting in their own "seat").
|
||||
sitting in their own "seat"). The wildcard character, _\*_, can also be used in
|
||||
place of _\<identifier\>_ to change settings for all seats.
|
||||
|
||||
Tip: If the configuration settings do not appear to be taking effect, you could
|
||||
try using _\*_ instead of _\<identifier\>_. If it works with the wildcard, try
|
||||
using a different identifier from *swaymsg -t get_seats* until you find the
|
||||
correct seat.
|
||||
|
||||
*seat* <name> attach <input_identifier>
|
||||
Attach an input device to this seat by its input identifier. A special
|
||||
|
|
|
|||
|
|
@ -293,12 +293,13 @@ runtime.
|
|||
overwrite a binding, swaynag will give you a warning. To silence this, use
|
||||
the _--no-warn_ flag.
|
||||
|
||||
Mouse buttons can either be specified in the form _button[1-9]_ or by using
|
||||
the name of the event code (ex _BTN\_LEFT_ or _BTN\_RIGHT_). For the former
|
||||
option, the buttons will be mapped to their values in X11 (1=left, 2=middle,
|
||||
3=right, 4=scroll up, 5=scroll down, 6=scroll left, 7=scroll right, 8=back,
|
||||
9=forward). For the latter option, you can find the event names using
|
||||
_libinput debug-events_.
|
||||
Mouse bindings operate on the container under the cursor instead of the
|
||||
container that has focus. Mouse buttons can either be specified in the form
|
||||
_button[1-9]_ or by using the name of the event code (ex _BTN\_LEFT_ or
|
||||
_BTN\_RIGHT_). For the former option, the buttons will be mapped to their
|
||||
values in X11 (1=left, 2=middle, 3=right, 4=scroll up, 5=scroll down,
|
||||
6=scroll left, 7=scroll right, 8=back, 9=forward). For the latter option,
|
||||
you can find the event names using _libinput debug-events_.
|
||||
|
||||
_--whole-window_, _--border_, and _--exclude-titlebar_ are mouse-only options
|
||||
which affect the region in which the mouse bindings can be triggered. By
|
||||
|
|
@ -413,10 +414,6 @@ The default colors are:
|
|||
: #0c0c0c
|
||||
|
||||
|
||||
*debuglog* on|off|toggle
|
||||
Enables, disables or toggles debug logging. _toggle_ cannot be used in the
|
||||
configuration file.
|
||||
|
||||
*default_border* normal|none|pixel [<n>]
|
||||
Set default border style for new tiled windows.
|
||||
|
||||
|
|
|
|||
|
|
@ -251,11 +251,13 @@ static struct sway_container *container_at_stacked(struct sway_node *parent,
|
|||
|
||||
// Title bars
|
||||
int title_height = container_titlebar_height();
|
||||
if (title_height > 0) {
|
||||
int child_index = (ly - box.y) / title_height;
|
||||
if (child_index < children->length) {
|
||||
struct sway_container *child = children->items[child_index];
|
||||
return child;
|
||||
}
|
||||
}
|
||||
|
||||
// Surfaces
|
||||
struct sway_node *current = seat_get_active_tiling_child(seat, parent);
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@
|
|||
#include "sway/layers.h"
|
||||
#include "sway/output.h"
|
||||
#include "sway/tree/arrange.h"
|
||||
#include "sway/tree/output.h"
|
||||
#include "sway/tree/workspace.h"
|
||||
#include "log.h"
|
||||
#include "util.h"
|
||||
|
|
@ -234,9 +233,8 @@ void output_disable(struct sway_output *output) {
|
|||
|
||||
root_for_each_container(untrack_output, output);
|
||||
|
||||
if (output->bg_pid) {
|
||||
terminate_swaybg(output->bg_pid);
|
||||
output->bg_pid = 0;
|
||||
if (output->swaybg_client != NULL) {
|
||||
wl_client_destroy(output->swaybg_client);
|
||||
}
|
||||
|
||||
int index = list_find(root->outputs, output);
|
||||
|
|
|
|||
|
|
@ -664,6 +664,13 @@ void view_unmap(struct sway_view *view) {
|
|||
struct sway_seat *seat;
|
||||
wl_list_for_each(seat, &server.input->seats, link) {
|
||||
seat->cursor->image_surface = NULL;
|
||||
if (seat->cursor->active_constraint) {
|
||||
struct wlr_surface *constrain_surface =
|
||||
seat->cursor->active_constraint->surface;
|
||||
if (view_from_wlr_surface(constrain_surface) == view) {
|
||||
sway_cursor_constrain(seat->cursor, NULL);
|
||||
}
|
||||
}
|
||||
seat_consider_warp_to_focus(seat);
|
||||
}
|
||||
|
||||
|
|
@ -701,6 +708,9 @@ static void subsurface_get_root_coords(struct sway_view_child *child,
|
|||
while (surface && wlr_surface_is_subsurface(surface)) {
|
||||
struct wlr_subsurface *subsurface =
|
||||
wlr_subsurface_from_wlr_surface(surface);
|
||||
if (subsurface == NULL) {
|
||||
break;
|
||||
}
|
||||
*root_sx += subsurface->current.x;
|
||||
*root_sy += subsurface->current.y;
|
||||
surface = subsurface->parent;
|
||||
|
|
|
|||
|
|
@ -42,10 +42,16 @@ struct sway_output *workspace_get_initial_output(const char *name) {
|
|||
}
|
||||
}
|
||||
}
|
||||
// Otherwise put it on the focused output
|
||||
// Otherwise try to put it on the focused output
|
||||
struct sway_seat *seat = input_manager_current_seat();
|
||||
struct sway_workspace *focus = seat_get_focused_workspace(seat);
|
||||
return focus->output;
|
||||
struct sway_node *focus = seat_get_focus_inactive(seat, &root->node);
|
||||
if (focus && focus->type == N_WORKSPACE) {
|
||||
return focus->sway_workspace->output;
|
||||
} else if (focus && focus->type == N_CONTAINER) {
|
||||
return focus->sway_container->workspace->output;
|
||||
}
|
||||
// Fallback to the first output or noop output for headless
|
||||
return root->outputs->length ? root->outputs->items[0] : root->noop_output;
|
||||
}
|
||||
|
||||
static void prevent_invalid_outer_gaps(struct sway_workspace *ws) {
|
||||
|
|
@ -328,16 +334,13 @@ char *workspace_next_name(const char *output_name) {
|
|||
if (target != NULL) {
|
||||
return target;
|
||||
}
|
||||
// As a fall back, get the current number of active workspaces
|
||||
// and return that + 1 for the next workspace's name
|
||||
int ws_num = root->outputs->length;
|
||||
int l = snprintf(NULL, 0, "%d", ws_num);
|
||||
char *name = malloc(l + 1);
|
||||
if (!sway_assert(name, "Could not allocate workspace name")) {
|
||||
return NULL;
|
||||
}
|
||||
sprintf(name, "%d", ws_num++);
|
||||
return name;
|
||||
// As a fall back, use the next available number
|
||||
char name[12] = "";
|
||||
unsigned int ws_num = 1;
|
||||
do {
|
||||
snprintf(name, sizeof(name), "%u", ws_num++);
|
||||
} while (workspace_by_number(name));
|
||||
return strdup(name);
|
||||
}
|
||||
|
||||
static bool _workspace_by_number(struct sway_workspace *ws, void *data) {
|
||||
|
|
@ -445,9 +448,15 @@ struct sway_workspace *workspace_prev(struct sway_workspace *current) {
|
|||
bool workspace_switch(struct sway_workspace *workspace,
|
||||
bool no_auto_back_and_forth) {
|
||||
struct sway_seat *seat = input_manager_current_seat();
|
||||
struct sway_workspace *active_ws = seat_get_focused_workspace(seat);
|
||||
struct sway_workspace *active_ws = NULL;
|
||||
struct sway_node *focus = seat_get_focus_inactive(seat, &root->node);
|
||||
if (focus && focus->type == N_WORKSPACE) {
|
||||
active_ws = focus->sway_workspace;
|
||||
} else if (focus && focus->type == N_CONTAINER) {
|
||||
active_ws = focus->sway_container->workspace;
|
||||
}
|
||||
|
||||
if (!no_auto_back_and_forth && config->auto_back_and_forth
|
||||
if (!no_auto_back_and_forth && config->auto_back_and_forth && active_ws
|
||||
&& active_ws == workspace && seat->prev_workspace_name) {
|
||||
struct sway_workspace *new_ws =
|
||||
workspace_by_name(seat->prev_workspace_name);
|
||||
|
|
@ -456,9 +465,9 @@ bool workspace_switch(struct sway_workspace *workspace,
|
|||
workspace_create(NULL, seat->prev_workspace_name);
|
||||
}
|
||||
|
||||
if (!seat->prev_workspace_name ||
|
||||
if (active_ws && (!seat->prev_workspace_name ||
|
||||
(strcmp(seat->prev_workspace_name, active_ws->name)
|
||||
&& active_ws != workspace)) {
|
||||
&& active_ws != workspace))) {
|
||||
free(seat->prev_workspace_name);
|
||||
seat->prev_workspace_name = malloc(strlen(active_ws->name) + 1);
|
||||
if (!seat->prev_workspace_name) {
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
#include <fcntl.h>
|
||||
#include <poll.h>
|
||||
#include <signal.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/wait.h>
|
||||
|
|
@ -403,8 +404,7 @@ bool bar_setup(struct swaybar *bar, const char *socket_path) {
|
|||
static void display_in(int fd, short mask, void *data) {
|
||||
struct swaybar *bar = data;
|
||||
if (wl_display_dispatch(bar->display) == -1) {
|
||||
bar_teardown(bar);
|
||||
exit(0);
|
||||
bar->running = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -439,7 +439,7 @@ void bar_run(struct swaybar *bar) {
|
|||
loop_add_fd(bar->eventloop, bar->tray->fd, POLLIN, tray_in, bar->tray->bus);
|
||||
}
|
||||
#endif
|
||||
while (1) {
|
||||
while (bar->running) {
|
||||
errno = 0;
|
||||
if (wl_display_flush(bar->display) == -1 && errno != EAGAIN) {
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -11,13 +11,7 @@
|
|||
static struct swaybar swaybar;
|
||||
|
||||
void sig_handler(int signal) {
|
||||
bar_teardown(&swaybar);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
void sway_terminate(int code) {
|
||||
bar_teardown(&swaybar);
|
||||
exit(code);
|
||||
swaybar.running = false;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
|
|
@ -93,8 +87,6 @@ int main(int argc, char **argv) {
|
|||
}
|
||||
}
|
||||
|
||||
signal(SIGTERM, sig_handler);
|
||||
|
||||
if (!bar_setup(&swaybar, socket_path)) {
|
||||
free(socket_path);
|
||||
return 1;
|
||||
|
|
@ -102,6 +94,10 @@ int main(int argc, char **argv) {
|
|||
|
||||
free(socket_path);
|
||||
|
||||
signal(SIGINT, sig_handler);
|
||||
signal(SIGTERM, sig_handler);
|
||||
|
||||
swaybar.running = true;
|
||||
bar_run(&swaybar);
|
||||
bar_teardown(&swaybar);
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -189,9 +189,9 @@ bool init_host(struct swaybar_host *host, char *protocol,
|
|||
goto error;
|
||||
}
|
||||
|
||||
sd_bus_slot_set_floating(reg_slot, 1);
|
||||
sd_bus_slot_set_floating(unreg_slot, 1);
|
||||
sd_bus_slot_set_floating(watcher_slot, 1);
|
||||
sd_bus_slot_set_floating(reg_slot, 0);
|
||||
sd_bus_slot_set_floating(unreg_slot, 0);
|
||||
sd_bus_slot_set_floating(watcher_slot, 0);
|
||||
|
||||
sway_log(SWAY_DEBUG, "Registered %s", host->service);
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -299,6 +299,8 @@ void destroy_sni(struct swaybar_sni *sni) {
|
|||
return;
|
||||
}
|
||||
|
||||
cairo_surface_destroy(sni->icon);
|
||||
|
||||
sd_bus_slot_unref(sni->new_icon_slot);
|
||||
sd_bus_slot_unref(sni->new_attention_icon_slot);
|
||||
sd_bus_slot_unref(sni->new_status_slot);
|
||||
|
|
@ -308,9 +310,11 @@ void destroy_sni(struct swaybar_sni *sni) {
|
|||
free(sni->path);
|
||||
free(sni->status);
|
||||
free(sni->icon_name);
|
||||
free(sni->icon_pixmap);
|
||||
list_free_items_and_destroy(sni->icon_pixmap);
|
||||
free(sni->attention_icon_name);
|
||||
list_free_items_and_destroy(sni->attention_icon_pixmap);
|
||||
free(sni->menu);
|
||||
free(sni->icon_theme_path);
|
||||
free(sni);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -18,10 +18,6 @@ static int cmp_id(const void *item, const void *cmp_to) {
|
|||
return strcmp(item, cmp_to);
|
||||
}
|
||||
|
||||
static int cmp_service(const void *item, const void *cmp_to) {
|
||||
return strncmp(item, cmp_to, strlen(cmp_to));
|
||||
}
|
||||
|
||||
static int handle_lost_service(sd_bus_message *msg,
|
||||
void *data, sd_bus_error *error) {
|
||||
char *service, *old_owner, *new_owner;
|
||||
|
|
@ -33,18 +29,23 @@ static int handle_lost_service(sd_bus_message *msg,
|
|||
|
||||
if (!*new_owner) {
|
||||
struct swaybar_watcher *watcher = data;
|
||||
int idx = list_seq_find(watcher->items,
|
||||
using_standard_protocol(watcher) ? cmp_id : cmp_service, service);
|
||||
if (idx != -1) {
|
||||
for (int idx = 0; idx < watcher->items->length; ++idx) {
|
||||
char *id = watcher->items->items[idx];
|
||||
int cmp_res = using_standard_protocol(watcher) ?
|
||||
cmp_id(id, service) : strncmp(id, service, strlen(service));
|
||||
if (cmp_res == 0) {
|
||||
sway_log(SWAY_DEBUG, "Unregistering Status Notifier Item '%s'", id);
|
||||
list_del(watcher->items, idx);
|
||||
list_del(watcher->items, idx--);
|
||||
sd_bus_emit_signal(watcher->bus, obj_path, watcher->interface,
|
||||
"StatusNotifierItemUnregistered", "s", id);
|
||||
free(id);
|
||||
if (using_standard_protocol(watcher)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
idx = list_seq_find(watcher->hosts, cmp_id, service);
|
||||
int idx = list_seq_find(watcher->hosts, cmp_id, service);
|
||||
if (idx != -1) {
|
||||
sway_log(SWAY_DEBUG, "Unregistering Status Notifier Host '%s'", service);
|
||||
free(watcher->hosts->items[idx]);
|
||||
|
|
@ -185,8 +186,8 @@ struct swaybar_watcher *create_watcher(char *protocol, sd_bus *bus) {
|
|||
goto error;
|
||||
}
|
||||
|
||||
sd_bus_slot_set_floating(signal_slot, 1);
|
||||
sd_bus_slot_set_floating(vtable_slot, 1);
|
||||
sd_bus_slot_set_floating(signal_slot, 0);
|
||||
sd_bus_slot_set_floating(vtable_slot, 0);
|
||||
|
||||
watcher->bus = bus;
|
||||
watcher->hosts = create_list();
|
||||
|
|
|
|||
|
|
@ -135,8 +135,8 @@ static void pretty_print_input(json_object *i) {
|
|||
json_object_get_int(vendor));
|
||||
|
||||
if (json_object_object_get_ex(i, "xkb_active_layout_name", &kbdlayout)) {
|
||||
printf(" Active Keyboard Layout: %s\n",
|
||||
json_object_get_string(kbdlayout));
|
||||
const char *layout = json_object_get_string(kbdlayout);
|
||||
printf(" Active Keyboard Layout: %s\n", layout ? layout : "(unnamed)");
|
||||
}
|
||||
|
||||
if (json_object_object_get_ex(i, "libinput_send_events", &events)) {
|
||||
|
|
|
|||
|
|
@ -348,6 +348,10 @@ int swaynag_load_config(char *path, struct swaynag *swaynag, list_t *types) {
|
|||
continue;
|
||||
}
|
||||
|
||||
if (line[nread - 1] == '\n') {
|
||||
line[nread - 1] = '\0';
|
||||
}
|
||||
|
||||
if (line[0] == '[') {
|
||||
char *close = strchr(line, ']');
|
||||
if (!close) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue