Merge branch 'master' into document-headless-output-manpage

This commit is contained in:
Sooraj S 2023-05-01 19:33:44 +05:30 committed by GitHub
commit da862448f9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
52 changed files with 327 additions and 314 deletions

1
.mailmap Normal file
View file

@ -0,0 +1 @@
Ronan Pigott <ronan@rjp.ie> <rpigott@berkeley.edu>

View file

@ -12,23 +12,6 @@
const uint8_t GESTURE_FINGERS_ANY = 0; const uint8_t GESTURE_FINGERS_ANY = 0;
// Helper to easily allocate and format string
static char *strformat(const char *format, ...) {
va_list args;
va_start(args, format);
int length = vsnprintf(NULL, 0, format, args) + 1;
va_end(args);
char *result = malloc(length);
if (result) {
va_start(args, format);
vsnprintf(result, length, format, args);
va_end(args);
}
return result;
}
char *gesture_parse(const char *input, struct gesture *output) { char *gesture_parse(const char *input, struct gesture *output) {
// Clear output in case of failure // Clear output in case of failure
output->type = GESTURE_TYPE_NONE; output->type = GESTURE_TYPE_NONE;
@ -38,7 +21,7 @@ char *gesture_parse(const char *input, struct gesture *output) {
// Split input type, fingers and directions // Split input type, fingers and directions
list_t *split = split_string(input, ":"); list_t *split = split_string(input, ":");
if (split->length < 1 || split->length > 3) { if (split->length < 1 || split->length > 3) {
return strformat( return format_str(
"expected <gesture>[:<fingers>][:direction], got %s", "expected <gesture>[:<fingers>][:direction], got %s",
input); input);
} }
@ -51,8 +34,8 @@ char *gesture_parse(const char *input, struct gesture *output) {
} else if (strcmp(split->items[0], "swipe") == 0) { } else if (strcmp(split->items[0], "swipe") == 0) {
output->type = GESTURE_TYPE_SWIPE; output->type = GESTURE_TYPE_SWIPE;
} else { } else {
return strformat("expected hold|pinch|swipe, got %s", return format_str("expected hold|pinch|swipe, got %s",
split->items[0]); (const char *)split->items[0]);
} }
// Parse optional arguments // Parse optional arguments
@ -67,7 +50,7 @@ char *gesture_parse(const char *input, struct gesture *output) {
next = split->length == 3 ? split->items[2] : NULL; next = split->length == 3 ? split->items[2] : NULL;
} else if (split->length == 3) { } else if (split->length == 3) {
// Fail here if argument can only be finger count // Fail here if argument can only be finger count
return strformat("expected 1-9, got %s", next); return format_str("expected 1-9, got %s", next);
} }
// If there is an argument left, try to parse as direction // If there is an argument left, try to parse as direction
@ -95,7 +78,7 @@ char *gesture_parse(const char *input, struct gesture *output) {
} else if (strcmp(item, "counterclockwise") == 0) { } else if (strcmp(item, "counterclockwise") == 0) {
output->directions |= GESTURE_DIRECTION_COUNTERCLOCKWISE; output->directions |= GESTURE_DIRECTION_COUNTERCLOCKWISE;
} else { } else {
return strformat("expected direction, got %s", item); return format_str("expected direction, got %s", item);
} }
} }
list_free_items_and_destroy(directions); list_free_items_and_destroy(directions);
@ -163,7 +146,7 @@ static char *gesture_directions_to_string(uint32_t directions) {
if (!result) { if (!result) {
result = strdup(name); result = strdup(name);
} else { } else {
char *new = strformat("%s+%s", result, name); char *new = format_str("%s+%s", result, name);
free(result); free(result);
result = new; result = new;
} }
@ -179,7 +162,7 @@ static char *gesture_directions_to_string(uint32_t directions) {
char *gesture_to_string(struct gesture *gesture) { char *gesture_to_string(struct gesture *gesture) {
char *directions = gesture_directions_to_string(gesture->directions); char *directions = gesture_directions_to_string(gesture->directions);
char *result = strformat("%s:%u:%s", char *result = format_str("%s:%u:%s",
gesture_type_string(gesture->type), gesture_type_string(gesture->type),
gesture->fingers, directions); gesture->fingers, directions);
free(directions); free(directions);

View file

@ -84,18 +84,11 @@ void get_text_size(cairo_t *cairo, const PangoFontDescription *desc, int *width,
int *baseline, double scale, bool markup, const char *fmt, ...) { int *baseline, double scale, bool markup, const char *fmt, ...) {
va_list args; va_list args;
va_start(args, fmt); va_start(args, fmt);
// Add one since vsnprintf excludes null terminator. char *buf = vformat_str(fmt, args);
int length = vsnprintf(NULL, 0, fmt, args) + 1;
va_end(args); va_end(args);
char *buf = malloc(length);
if (buf == NULL) { if (buf == NULL) {
sway_log(SWAY_ERROR, "Failed to allocate memory");
return; return;
} }
va_start(args, fmt);
vsnprintf(buf, length, fmt, args);
va_end(args);
PangoLayout *layout = get_pango_layout(cairo, desc, buf, scale, markup); PangoLayout *layout = get_pango_layout(cairo, desc, buf, scale, markup);
pango_cairo_update_layout(cairo, layout); pango_cairo_update_layout(cairo, layout);
@ -104,6 +97,7 @@ void get_text_size(cairo_t *cairo, const PangoFontDescription *desc, int *width,
*baseline = pango_layout_get_baseline(layout) / PANGO_SCALE; *baseline = pango_layout_get_baseline(layout) / PANGO_SCALE;
} }
g_object_unref(layout); g_object_unref(layout);
free(buf); free(buf);
} }
@ -125,18 +119,11 @@ void render_text(cairo_t *cairo, const PangoFontDescription *desc,
double scale, bool markup, const char *fmt, ...) { double scale, bool markup, const char *fmt, ...) {
va_list args; va_list args;
va_start(args, fmt); va_start(args, fmt);
// Add one since vsnprintf excludes null terminator. char *buf = vformat_str(fmt, args);
int length = vsnprintf(NULL, 0, fmt, args) + 1;
va_end(args); va_end(args);
char *buf = malloc(length);
if (buf == NULL) { if (buf == NULL) {
sway_log(SWAY_ERROR, "Failed to allocate memory");
return; return;
} }
va_start(args, fmt);
vsnprintf(buf, length, fmt, args);
va_end(args);
PangoLayout *layout = get_pango_layout(cairo, desc, buf, scale, markup); PangoLayout *layout = get_pango_layout(cairo, desc, buf, scale, markup);
cairo_font_options_t *fo = cairo_font_options_create(); cairo_font_options_t *fo = cairo_font_options_create();
@ -146,5 +133,6 @@ void render_text(cairo_t *cairo, const PangoFontDescription *desc,
pango_cairo_update_layout(cairo, layout); pango_cairo_update_layout(cairo, layout);
pango_cairo_show_layout(cairo, layout); pango_cairo_show_layout(cairo, layout);
g_object_unref(layout); g_object_unref(layout);
free(buf); free(buf);
} }

View file

@ -1,5 +1,6 @@
#define _POSIX_C_SOURCE 200809L #define _POSIX_C_SOURCE 200809L
#include <ctype.h> #include <ctype.h>
#include <stdarg.h>
#include <stdbool.h> #include <stdbool.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
@ -328,3 +329,35 @@ bool expand_path(char **path) {
wordfree(&p); wordfree(&p);
return true; return true;
} }
char *vformat_str(const char *fmt, va_list args) {
char *str = NULL;
va_list args_copy;
va_copy(args_copy, args);
int len = vsnprintf(NULL, 0, fmt, args);
if (len < 0) {
sway_log_errno(SWAY_ERROR, "vsnprintf(\"%s\") failed", fmt);
goto out;
}
str = malloc(len + 1);
if (str == NULL) {
sway_log_errno(SWAY_ERROR, "malloc() failed");
goto out;
}
vsnprintf(str, len + 1, fmt, args_copy);
out:
va_end(args_copy);
return str;
}
char *format_str(const char *fmt, ...) {
va_list args;
va_start(args, fmt);
char *str = vformat_str(fmt, args);
va_end(args);
return str;
}

View file

@ -5,6 +5,7 @@
#include <stdint.h> #include <stdint.h>
#include <cairo.h> #include <cairo.h>
#include <pango/pangocairo.h> #include <pango/pangocairo.h>
#include "stringop.h"
/** /**
* Utility function which escape characters a & < > ' ". * Utility function which escape characters a & < > ' ".
@ -16,9 +17,9 @@ size_t escape_markup_text(const char *src, char *dest);
PangoLayout *get_pango_layout(cairo_t *cairo, const PangoFontDescription *desc, PangoLayout *get_pango_layout(cairo_t *cairo, const PangoFontDescription *desc,
const char *text, double scale, bool markup); const char *text, double scale, bool markup);
void get_text_size(cairo_t *cairo, const PangoFontDescription *desc, int *width, int *height, void get_text_size(cairo_t *cairo, const PangoFontDescription *desc, int *width, int *height,
int *baseline, double scale, bool markup, const char *fmt, ...); int *baseline, double scale, bool markup, const char *fmt, ...) _SWAY_ATTRIB_PRINTF(8, 9);
void get_text_metrics(const PangoFontDescription *desc, int *height, int *baseline); void get_text_metrics(const PangoFontDescription *desc, int *height, int *baseline);
void render_text(cairo_t *cairo, PangoFontDescription *desc, void render_text(cairo_t *cairo, PangoFontDescription *desc,
double scale, bool markup, const char *fmt, ...); double scale, bool markup, const char *fmt, ...) _SWAY_ATTRIB_PRINTF(5, 6);
#endif #endif

View file

@ -5,6 +5,12 @@
#include <stddef.h> #include <stddef.h>
#include "list.h" #include "list.h"
#ifdef __GNUC__
#define _SWAY_ATTRIB_PRINTF(start, end) __attribute__((format(printf, start, end)))
#else
#define _SWAY_ATTRIB_PRINTF(start, end)
#endif
void strip_whitespace(char *str); void strip_whitespace(char *str);
void strip_quotes(char *str); void strip_quotes(char *str);
@ -31,4 +37,7 @@ char *argsep(char **stringp, const char *delim, char *matched_delim);
// Expand a path using shell replacements such as $HOME and ~ // Expand a path using shell replacements such as $HOME and ~
bool expand_path(char **path); bool expand_path(char **path);
char *vformat_str(const char *fmt, va_list args) _SWAY_ATTRIB_PRINTF(1, 0);
char *format_str(const char *fmt, ...) _SWAY_ATTRIB_PRINTF(1, 2);
#endif #endif

View file

@ -3,6 +3,7 @@
#include <wlr/util/edges.h> #include <wlr/util/edges.h>
#include "config.h" #include "config.h"
#include "stringop.h"
struct sway_container; struct sway_container;
@ -76,7 +77,7 @@ struct cmd_results *config_commands_command(char *exec);
/** /**
* Allocates a cmd_results object. * Allocates a cmd_results object.
*/ */
struct cmd_results *cmd_results_new(enum cmd_status status, const char *error, ...); struct cmd_results *cmd_results_new(enum cmd_status status, const char *error, ...) _SWAY_ATTRIB_PRINTF(2, 3);
/** /**
* Frees a cmd_results object. * Frees a cmd_results object.
*/ */

View file

@ -12,6 +12,7 @@
#include "../include/config.h" #include "../include/config.h"
#include "gesture.h" #include "gesture.h"
#include "list.h" #include "list.h"
#include "stringop.h"
#include "swaynag.h" #include "swaynag.h"
#include "tree/container.h" #include "tree/container.h"
#include "sway/input/tablet.h" #include "sway/input/tablet.h"
@ -625,7 +626,7 @@ void run_deferred_bindings(void);
/** /**
* Adds a warning entry to the swaynag instance used for errors. * Adds a warning entry to the swaynag instance used for errors.
*/ */
void config_add_swaynag_warning(char *fmt, ...); void config_add_swaynag_warning(char *fmt, ...) _SWAY_ATTRIB_PRINTF(1, 2);
/** /**
* Free config struct * Free config struct

View file

@ -96,6 +96,9 @@ void output_damage_box(struct sway_output *output, struct wlr_box *box);
void output_damage_whole_container(struct sway_output *output, void output_damage_whole_container(struct sway_output *output,
struct sway_container *con); struct sway_container *con);
bool output_match_name_or_id(struct sway_output *output,
const char *name_or_id);
// this ONLY includes the enabled outputs // this ONLY includes the enabled outputs
struct sway_output *output_by_name_or_id(const char *name_or_id); struct sway_output *output_by_name_or_id(const char *name_or_id);

View file

@ -1,6 +1,7 @@
#ifndef _SWAY_SWAYNAG_H #ifndef _SWAY_SWAYNAG_H
#define _SWAY_SWAYNAG_H #define _SWAY_SWAYNAG_H
#include <wayland-server-core.h> #include <wayland-server-core.h>
#include "stringop.h"
struct swaynag_instance { struct swaynag_instance {
struct wl_client *client; struct wl_client *client;
@ -21,7 +22,7 @@ bool swaynag_spawn(const char *swaynag_command,
// Write a log message to swaynag->fd[1]. This will fail when swaynag->detailed // Write a log message to swaynag->fd[1]. This will fail when swaynag->detailed
// is false. // is false.
void swaynag_log(const char *swaynag_command, struct swaynag_instance *swaynag, void swaynag_log(const char *swaynag_command, struct swaynag_instance *swaynag,
const char *fmt, ...); const char *fmt, ...) _SWAY_ATTRIB_PRINTF(3, 4);
// If swaynag->detailed, close swaynag->fd[1] so swaynag displays // If swaynag->detailed, close swaynag->fd[1] so swaynag displays
void swaynag_show(struct swaynag_instance *swaynag); void swaynag_show(struct swaynag_instance *swaynag);

View file

@ -113,6 +113,11 @@ struct sway_container {
// Hidden scratchpad containers have a NULL parent. // Hidden scratchpad containers have a NULL parent.
bool scratchpad; bool scratchpad;
// Stores last output size and position for adjusting coordinates of
// scratchpad windows.
// Unused for non-scratchpad windows.
struct wlr_box transform;
float alpha; float alpha;
struct wlr_texture *title_focused; struct wlr_texture *title_focused;
@ -196,6 +201,9 @@ size_t container_titlebar_height(void);
void floating_calculate_constraints(int *min_width, int *max_width, void floating_calculate_constraints(int *min_width, int *max_width,
int *min_height, int *max_height); int *min_height, int *max_height);
void floating_fix_coordinates(struct sway_container *con,
struct wlr_box *old, struct wlr_box *new);
void container_floating_resize_and_center(struct sway_container *con); void container_floating_resize_and_center(struct sway_container *con);
void container_floating_set_default_size(struct sway_container *con); void container_floating_set_default_size(struct sway_container *con);

View file

@ -18,6 +18,7 @@ add_project_arguments(
'-Wno-unused-parameter', '-Wno-unused-parameter',
'-Wno-unused-result', '-Wno-unused-result',
'-Wno-missing-braces', '-Wno-missing-braces',
'-Wno-format-zero-length',
'-Wundef', '-Wundef',
'-Wvla', '-Wvla',
], ],
@ -117,6 +118,11 @@ conf_data.set10('HAVE_LIBSYSTEMD', sdbus.found() and sdbus.name() == 'libsystemd
conf_data.set10('HAVE_LIBELOGIND', sdbus.found() and sdbus.name() == 'libelogind') conf_data.set10('HAVE_LIBELOGIND', sdbus.found() and sdbus.name() == 'libelogind')
conf_data.set10('HAVE_BASU', sdbus.found() and sdbus.name() == 'basu') conf_data.set10('HAVE_BASU', sdbus.found() and sdbus.name() == 'basu')
conf_data.set10('HAVE_TRAY', have_tray) conf_data.set10('HAVE_TRAY', have_tray)
conf_data.set10('HAVE_LIBINPUT_CONFIG_ACCEL_PROFILE_CUSTOM', cc.has_header_symbol(
'libinput.h',
'LIBINPUT_CONFIG_ACCEL_PROFILE_CUSTOM',
dependencies: libinput,
))
scdoc = dependency('scdoc', version: '>=1.9.2', native: true, required: get_option('man-pages')) scdoc = dependency('scdoc', version: '>=1.9.2', native: true, required: get_option('man-pages'))
if scdoc.found() if scdoc.found()

View file

@ -381,10 +381,13 @@ struct cmd_results *config_command(char *exec, char **new_block) {
sway_log(SWAY_INFO, "Config command: %s", exec); sway_log(SWAY_INFO, "Config command: %s", exec);
const struct cmd_handler *handler = find_core_handler(argv[0]); const struct cmd_handler *handler = find_core_handler(argv[0]);
if (!handler || !handler->handle) { if (!handler || !handler->handle) {
const char *error = handler if (handler) {
? "Command '%s' is shimmed, but unimplemented" results = cmd_results_new(CMD_INVALID,
: "Unknown/invalid command '%s'"; "Command '%s' is shimmed, but unimplemented", argv[0]);
results = cmd_results_new(CMD_INVALID, error, argv[0]); } else {
results = cmd_results_new(CMD_INVALID,
"Unknown/invalid command '%s'", argv[0]);
}
goto cleanup; goto cleanup;
} }
@ -486,20 +489,10 @@ struct cmd_results *cmd_results_new(enum cmd_status status,
} }
results->status = status; results->status = status;
if (format) { if (format) {
char *error = NULL;
va_list args; va_list args;
va_start(args, format); va_start(args, format);
int slen = vsnprintf(NULL, 0, format, args); results->error = vformat_str(format, args);
va_end(args); va_end(args);
if (slen > 0) {
error = malloc(slen + 1);
if (error != NULL) {
va_start(args, format);
vsnprintf(error, slen + 1, format, args);
va_end(args);
}
}
results->error = error;
} else { } else {
results->error = NULL; results->error = NULL;
} }

View file

@ -17,7 +17,7 @@ struct cmd_results *cmd_assign(int argc, char **argv) {
char *err_str = NULL; char *err_str = NULL;
struct criteria *criteria = criteria_parse(argv[0], &err_str); struct criteria *criteria = criteria_parse(argv[0], &err_str);
if (!criteria) { if (!criteria) {
error = cmd_results_new(CMD_INVALID, err_str); error = cmd_results_new(CMD_INVALID, "%s", err_str);
free(err_str); free(err_str);
return error; return error;
} }

View file

@ -73,12 +73,10 @@ struct cmd_results *cmd_bar(int argc, char **argv) {
} }
++argv; --argc; ++argv; --argc;
} else if (config->reading && !config->current_bar) { } else if (config->reading && !config->current_bar) {
int len = snprintf(NULL, 0, "bar-%d", config->bars->length) + 1; id = format_str("bar-%d", config->bars->length);
id = malloc(len * sizeof(char));
if (!id) { if (!id) {
return cmd_results_new(CMD_FAILURE, "Unable to allocate bar id"); return cmd_results_new(CMD_FAILURE, "Unable to allocate bar id");
} }
snprintf(id, len, "bar-%d", config->bars->length);
} else if (!config->reading && strcmp(argv[0], "mode") != 0 && } else if (!config->reading && strcmp(argv[0], "mode") != 0 &&
strcmp(argv[0], "hidden_state") != 0) { strcmp(argv[0], "hidden_state") != 0) {
if (is_subcommand(argv[0])) { if (is_subcommand(argv[0])) {

View file

@ -96,7 +96,7 @@ static struct cmd_results *bar_cmd_bind(int argc, char **argv, bool code,
} }
if (message) { if (message) {
free_bar_binding(binding); free_bar_binding(binding);
error = cmd_results_new(CMD_INVALID, message); error = cmd_results_new(CMD_INVALID, "%s", message);
free(message); free(message);
return error; return error;
} else if (!binding->button) { } else if (!binding->button) {

View file

@ -26,7 +26,7 @@ static struct cmd_results *tray_bind(int argc, char **argv, bool code) {
} }
if (message) { if (message) {
free(binding); free(binding);
error = cmd_results_new(CMD_INVALID, message); error = cmd_results_new(CMD_INVALID, "%s", message);
free(message); free(message);
return error; return error;
} else if (!binding->button) { } else if (!binding->button) {

View file

@ -127,7 +127,7 @@ static struct cmd_results *identify_key(const char* name, bool first_key,
if (!button) { if (!button) {
if (message) { if (message) {
struct cmd_results *error = struct cmd_results *error =
cmd_results_new(CMD_INVALID, message); cmd_results_new(CMD_INVALID, "%s", message);
free(message); free(message);
return error; return error;
} else { } else {
@ -143,7 +143,7 @@ static struct cmd_results *identify_key(const char* name, bool first_key,
if (!button) { if (!button) {
if (message) { if (message) {
struct cmd_results *error = struct cmd_results *error =
cmd_results_new(CMD_INVALID, message); cmd_results_new(CMD_INVALID, "%s", message);
free(message); free(message);
return error; return error;
} else { } else {
@ -182,7 +182,7 @@ static struct cmd_results *identify_key(const char* name, bool first_key,
uint32_t button = get_mouse_bindsym(name, &message); uint32_t button = get_mouse_bindsym(name, &message);
if (message) { if (message) {
struct cmd_results *error = struct cmd_results *error =
cmd_results_new(CMD_INVALID, message); cmd_results_new(CMD_INVALID, "%s", message);
free(message); free(message);
return error; return error;
} else if (button) { } else if (button) {
@ -539,7 +539,7 @@ struct cmd_results *cmd_bind_or_unbind_switch(int argc, char **argv,
free_switch_binding(binding); free_switch_binding(binding);
return cmd_results_new(CMD_FAILURE, return cmd_results_new(CMD_FAILURE,
"Invalid %s command (expected binding with the form " "Invalid %s command (expected binding with the form "
"<switch>:<state>)", bindtype, argc); "<switch>:<state>)", bindtype);
} }
if (strcmp(split->items[0], "tablet") == 0) { if (strcmp(split->items[0], "tablet") == 0) {
binding->type = WLR_SWITCH_TYPE_TABLET_MODE; binding->type = WLR_SWITCH_TYPE_TABLET_MODE;
@ -549,7 +549,8 @@ struct cmd_results *cmd_bind_or_unbind_switch(int argc, char **argv,
free_switch_binding(binding); free_switch_binding(binding);
return cmd_results_new(CMD_FAILURE, return cmd_results_new(CMD_FAILURE,
"Invalid %s command (expected switch binding: " "Invalid %s command (expected switch binding: "
"unknown switch %s)", bindtype, split->items[0]); "unknown switch %s)", bindtype,
(const char *)split->items[0]);
} }
if (strcmp(split->items[1], "on") == 0) { if (strcmp(split->items[1], "on") == 0) {
binding->trigger = SWAY_SWITCH_TRIGGER_ON; binding->trigger = SWAY_SWITCH_TRIGGER_ON;
@ -562,7 +563,7 @@ struct cmd_results *cmd_bind_or_unbind_switch(int argc, char **argv,
return cmd_results_new(CMD_FAILURE, return cmd_results_new(CMD_FAILURE,
"Invalid %s command " "Invalid %s command "
"(expected switch state: unknown state %s)", "(expected switch state: unknown state %s)",
bindtype, split->items[1]); bindtype, (const char *)split->items[1]);
} }
list_free_items_and_destroy(split); list_free_items_and_destroy(split);

View file

@ -23,16 +23,16 @@ static struct cmd_results *handle_command(int argc, char **argv, char *cmd_name,
char *err; char *err;
int width = (int)strtol(argv[0], &err, 10); int width = (int)strtol(argv[0], &err, 10);
if (*err) { if (*err) {
return cmd_results_new(CMD_INVALID, cmd_name, usage); return cmd_results_new(CMD_INVALID, "%s", usage);
} }
if (strcmp(argv[1], "x") != 0) { if (strcmp(argv[1], "x") != 0) {
return cmd_results_new(CMD_INVALID, cmd_name, usage); return cmd_results_new(CMD_INVALID, "%s", usage);
} }
int height = (int)strtol(argv[2], &err, 10); int height = (int)strtol(argv[2], &err, 10);
if (*err) { if (*err) {
return cmd_results_new(CMD_INVALID, cmd_name, usage); return cmd_results_new(CMD_INVALID, "%s", usage);
} }
*config_width = width; *config_width = width;

View file

@ -14,7 +14,7 @@ struct cmd_results *cmd_for_window(int argc, char **argv) {
char *err_str = NULL; char *err_str = NULL;
struct criteria *criteria = criteria_parse(argv[0], &err_str); struct criteria *criteria = criteria_parse(argv[0], &err_str);
if (!criteria) { if (!criteria) {
error = cmd_results_new(CMD_INVALID, err_str); error = cmd_results_new(CMD_INVALID, "%s", err_str);
free(err_str); free(err_str);
return error; return error;
} }

View file

@ -20,7 +20,7 @@ struct cmd_results *cmd_hide_edge_borders(int argc, char **argv) {
} }
if (!argc) { if (!argc) {
return cmd_results_new(CMD_INVALID, expected_syntax); return cmd_results_new(CMD_INVALID, "%s", expected_syntax);
} }
if (strcmp(argv[0], "none") == 0) { if (strcmp(argv[0], "none") == 0) {
@ -38,7 +38,7 @@ struct cmd_results *cmd_hide_edge_borders(int argc, char **argv) {
config->hide_edge_borders = E_NONE; config->hide_edge_borders = E_NONE;
config->hide_edge_borders_smart = ESMART_NO_GAPS; config->hide_edge_borders_smart = ESMART_NO_GAPS;
} else { } else {
return cmd_results_new(CMD_INVALID, expected_syntax); return cmd_results_new(CMD_INVALID, "%s", expected_syntax);
} }
config->hide_lone_tab = hide_lone_tab; config->hide_lone_tab = hide_lone_tab;

View file

@ -49,5 +49,5 @@ struct cmd_results *input_cmd_map_to_region(int argc, char **argv) {
error: error:
free(ic->mapped_to_region); free(ic->mapped_to_region);
ic->mapped_to_region = NULL; ic->mapped_to_region = NULL;
return cmd_results_new(CMD_FAILURE, errstr); return cmd_results_new(CMD_FAILURE, "%s", errstr);
} }

View file

@ -21,7 +21,7 @@ struct cmd_results *input_cmd_scroll_button(int argc, char **argv) {
char *message = NULL; char *message = NULL;
uint32_t button = get_mouse_button(*argv, &message); uint32_t button = get_mouse_button(*argv, &message);
if (message) { if (message) {
error = cmd_results_new(CMD_INVALID, message); error = cmd_results_new(CMD_INVALID, "%s", message);
free(message); free(message);
return error; return error;
} else if (button == SWAY_SCROLL_UP || button == SWAY_SCROLL_DOWN } else if (button == SWAY_SCROLL_UP || button == SWAY_SCROLL_DOWN

View file

@ -153,7 +153,7 @@ struct cmd_results *cmd_layout(int argc, char **argv) {
workspace->output); workspace->output);
} }
if (new_layout == L_NONE) { if (new_layout == L_NONE) {
return cmd_results_new(CMD_INVALID, expected_syntax); return cmd_results_new(CMD_INVALID, "%s", expected_syntax);
} }
if (new_layout != old_layout) { if (new_layout != old_layout) {
if (container) { if (container) {

View file

@ -206,9 +206,17 @@ static void container_move_to_workspace(struct sway_container *container,
container_detach(container); container_detach(container);
workspace_add_floating(workspace, container); workspace_add_floating(workspace, container);
container_handle_fullscreen_reparent(container); container_handle_fullscreen_reparent(container);
// If changing output, center it within the workspace // If changing output, adjust the coordinates of the window.
if (old_output != workspace->output && !container->pending.fullscreen_mode) { if (old_output != workspace->output && !container->pending.fullscreen_mode) {
container_floating_move_to_center(container); struct wlr_box workspace_box, old_workspace_box;
workspace_get_box(workspace, &workspace_box);
workspace_get_box(old_workspace, &old_workspace_box);
floating_fix_coordinates(container, &old_workspace_box, &workspace_box);
if (container->scratchpad && workspace->output) {
struct wlr_box output_box;
output_get_box(workspace->output, &output_box);
container->transform = workspace_box;
}
} }
} else { } else {
container_detach(container); container_detach(container);
@ -462,7 +470,7 @@ static struct cmd_results *cmd_move_container(bool no_auto_back_and_forth,
if (strcasecmp(argv[1], "number") == 0) { if (strcasecmp(argv[1], "number") == 0) {
// move [window|container] [to] "workspace number x" // move [window|container] [to] "workspace number x"
if (argc < 3) { if (argc < 3) {
return cmd_results_new(CMD_INVALID, expected_syntax); return cmd_results_new(CMD_INVALID, "%s", expected_syntax);
} }
if (!isdigit(argv[2][0])) { if (!isdigit(argv[2][0])) {
return cmd_results_new(CMD_INVALID, return cmd_results_new(CMD_INVALID,
@ -522,7 +530,7 @@ static struct cmd_results *cmd_move_container(bool no_auto_back_and_forth,
} }
destination = &dest_con->node; destination = &dest_con->node;
} else { } else {
return cmd_results_new(CMD_INVALID, expected_syntax); return cmd_results_new(CMD_INVALID, "%s", expected_syntax);
} }
if (destination->type == N_CONTAINER && if (destination->type == N_CONTAINER &&
@ -821,7 +829,7 @@ static struct cmd_results *cmd_move_to_position(int argc, char **argv) {
} }
if (!argc) { if (!argc) {
return cmd_results_new(CMD_INVALID, expected_position_syntax); return cmd_results_new(CMD_INVALID, "%s", expected_position_syntax);
} }
bool absolute = false; bool absolute = false;
@ -831,19 +839,19 @@ static struct cmd_results *cmd_move_to_position(int argc, char **argv) {
++argv; ++argv;
} }
if (!argc) { if (!argc) {
return cmd_results_new(CMD_INVALID, expected_position_syntax); return cmd_results_new(CMD_INVALID, "%s", expected_position_syntax);
} }
if (strcmp(argv[0], "position") == 0) { if (strcmp(argv[0], "position") == 0) {
--argc; --argc;
++argv; ++argv;
} }
if (!argc) { if (!argc) {
return cmd_results_new(CMD_INVALID, expected_position_syntax); return cmd_results_new(CMD_INVALID, "%s", expected_position_syntax);
} }
if (strcmp(argv[0], "cursor") == 0 || strcmp(argv[0], "mouse") == 0 || if (strcmp(argv[0], "cursor") == 0 || strcmp(argv[0], "mouse") == 0 ||
strcmp(argv[0], "pointer") == 0) { strcmp(argv[0], "pointer") == 0) {
if (absolute) { if (absolute) {
return cmd_results_new(CMD_INVALID, expected_position_syntax); return cmd_results_new(CMD_INVALID, "%s", expected_position_syntax);
} }
return cmd_move_to_position_pointer(container); return cmd_move_to_position_pointer(container);
} else if (strcmp(argv[0], "center") == 0) { } else if (strcmp(argv[0], "center") == 0) {
@ -865,7 +873,7 @@ static struct cmd_results *cmd_move_to_position(int argc, char **argv) {
} }
if (argc < 2) { if (argc < 2) {
return cmd_results_new(CMD_FAILURE, expected_position_syntax); return cmd_results_new(CMD_FAILURE, "%s", expected_position_syntax);
} }
struct movement_amount lx = { .amount = 0, .unit = MOVEMENT_UNIT_INVALID }; struct movement_amount lx = { .amount = 0, .unit = MOVEMENT_UNIT_INVALID };
@ -878,7 +886,7 @@ static struct cmd_results *cmd_move_to_position(int argc, char **argv) {
} }
if (argc < 1) { if (argc < 1) {
return cmd_results_new(CMD_FAILURE, expected_position_syntax); return cmd_results_new(CMD_FAILURE, "%s", expected_position_syntax);
} }
struct movement_amount ly = { .amount = 0, .unit = MOVEMENT_UNIT_INVALID }; struct movement_amount ly = { .amount = 0, .unit = MOVEMENT_UNIT_INVALID };
@ -887,7 +895,7 @@ static struct cmd_results *cmd_move_to_position(int argc, char **argv) {
argc -= num_consumed_args; argc -= num_consumed_args;
argv += num_consumed_args; argv += num_consumed_args;
if (argc > 0) { if (argc > 0) {
return cmd_results_new(CMD_INVALID, expected_position_syntax); return cmd_results_new(CMD_INVALID, "%s", expected_position_syntax);
} }
if (ly.unit == MOVEMENT_UNIT_INVALID) { if (ly.unit == MOVEMENT_UNIT_INVALID) {
return cmd_results_new(CMD_INVALID, "Invalid y position specified"); return cmd_results_new(CMD_INVALID, "Invalid y position specified");
@ -1033,13 +1041,13 @@ struct cmd_results *cmd_move(int argc, char **argv) {
} }
if (!argc) { if (!argc) {
return cmd_results_new(CMD_INVALID, expected_full_syntax); return cmd_results_new(CMD_INVALID, "%s", expected_full_syntax);
} }
// Only `move [window|container] [to] workspace` supports // Only `move [window|container] [to] workspace` supports
// `--no-auto-back-and-forth` so treat others as invalid syntax // `--no-auto-back-and-forth` so treat others as invalid syntax
if (no_auto_back_and_forth && strcasecmp(argv[0], "workspace") != 0) { if (no_auto_back_and_forth && strcasecmp(argv[0], "workspace") != 0) {
return cmd_results_new(CMD_INVALID, expected_full_syntax); return cmd_results_new(CMD_INVALID, "%s", expected_full_syntax);
} }
if (strcasecmp(argv[0], "workspace") == 0 || if (strcasecmp(argv[0], "workspace") == 0 ||
@ -1053,5 +1061,5 @@ struct cmd_results *cmd_move(int argc, char **argv) {
strcasecmp(argv[1], "position") == 0)) { strcasecmp(argv[1], "position") == 0)) {
return cmd_move_to_position(argc, argv); return cmd_move_to_position(argc, argv);
} }
return cmd_results_new(CMD_INVALID, expected_full_syntax); return cmd_results_new(CMD_INVALID, "%s", expected_full_syntax);
} }

View file

@ -13,7 +13,7 @@ struct cmd_results *cmd_no_focus(int argc, char **argv) {
char *err_str = NULL; char *err_str = NULL;
struct criteria *criteria = criteria_parse(argv[0], &err_str); struct criteria *criteria = criteria_parse(argv[0], &err_str);
if (!criteria) { if (!criteria) {
error = cmd_results_new(CMD_INVALID, err_str); error = cmd_results_new(CMD_INVALID, "%s", err_str);
free(err_str); free(err_str);
return error; return error;
} }

View file

@ -26,7 +26,7 @@ struct cmd_results *cmd_rename(int argc, char **argv) {
"Can't run this command while there's no outputs connected."); "Can't run this command while there's no outputs connected.");
} }
if (strcasecmp(argv[0], "workspace") != 0) { if (strcasecmp(argv[0], "workspace") != 0) {
return cmd_results_new(CMD_INVALID, expected_syntax); return cmd_results_new(CMD_INVALID, "%s", expected_syntax);
} }
int argn = 1; int argn = 1;
@ -65,7 +65,7 @@ struct cmd_results *cmd_rename(int argc, char **argv) {
++argn; // move past "to" ++argn; // move past "to"
if (argn >= argc) { if (argn >= argc) {
return cmd_results_new(CMD_INVALID, expected_syntax); return cmd_results_new(CMD_INVALID, "%s", expected_syntax);
} }
char *new_name = join_args(argv + argn, argc - argn); char *new_name = join_args(argv + argn, argc - argn);

View file

@ -415,7 +415,7 @@ static struct cmd_results *cmd_resize_set(int argc, char **argv) {
argc -= num_consumed_args; argc -= num_consumed_args;
argv += num_consumed_args; argv += num_consumed_args;
if (width.unit == MOVEMENT_UNIT_INVALID) { if (width.unit == MOVEMENT_UNIT_INVALID) {
return cmd_results_new(CMD_INVALID, usage); return cmd_results_new(CMD_INVALID, "%s", usage);
} }
} }
@ -427,10 +427,10 @@ static struct cmd_results *cmd_resize_set(int argc, char **argv) {
} }
int num_consumed_args = parse_movement_amount(argc, argv, &height); int num_consumed_args = parse_movement_amount(argc, argv, &height);
if (argc > num_consumed_args) { if (argc > num_consumed_args) {
return cmd_results_new(CMD_INVALID, usage); return cmd_results_new(CMD_INVALID, "%s", usage);
} }
if (width.unit == MOVEMENT_UNIT_INVALID) { if (width.unit == MOVEMENT_UNIT_INVALID) {
return cmd_results_new(CMD_INVALID, usage); return cmd_results_new(CMD_INVALID, "%s", usage);
} }
} }
@ -462,7 +462,7 @@ static struct cmd_results *cmd_resize_adjust(int argc, char **argv,
"[<amount> px|ppt [or <amount> px|ppt]]'"; "[<amount> px|ppt [or <amount> px|ppt]]'";
uint32_t axis = parse_resize_axis(*argv); uint32_t axis = parse_resize_axis(*argv);
if (axis == WLR_EDGE_NONE) { if (axis == WLR_EDGE_NONE) {
return cmd_results_new(CMD_INVALID, usage); return cmd_results_new(CMD_INVALID, "%s", usage);
} }
--argc; ++argv; --argc; ++argv;
@ -473,7 +473,7 @@ static struct cmd_results *cmd_resize_adjust(int argc, char **argv,
argc -= num_consumed_args; argc -= num_consumed_args;
argv += num_consumed_args; argv += num_consumed_args;
if (first_amount.unit == MOVEMENT_UNIT_INVALID) { if (first_amount.unit == MOVEMENT_UNIT_INVALID) {
return cmd_results_new(CMD_INVALID, usage); return cmd_results_new(CMD_INVALID, "%s", usage);
} }
} else { } else {
first_amount.amount = 10; first_amount.amount = 10;
@ -483,7 +483,7 @@ static struct cmd_results *cmd_resize_adjust(int argc, char **argv,
// "or" // "or"
if (argc) { if (argc) {
if (strcmp(*argv, "or") != 0) { if (strcmp(*argv, "or") != 0) {
return cmd_results_new(CMD_INVALID, usage); return cmd_results_new(CMD_INVALID, "%s", usage);
} }
--argc; ++argv; --argc; ++argv;
} }
@ -493,10 +493,10 @@ static struct cmd_results *cmd_resize_adjust(int argc, char **argv,
if (argc) { if (argc) {
int num_consumed_args = parse_movement_amount(argc, argv, &second_amount); int num_consumed_args = parse_movement_amount(argc, argv, &second_amount);
if (argc > num_consumed_args) { if (argc > num_consumed_args) {
return cmd_results_new(CMD_INVALID, usage); return cmd_results_new(CMD_INVALID, "%s", usage);
} }
if (second_amount.unit == MOVEMENT_UNIT_INVALID) { if (second_amount.unit == MOVEMENT_UNIT_INVALID) {
return cmd_results_new(CMD_INVALID, usage); return cmd_results_new(CMD_INVALID, "%s", usage);
} }
} else { } else {
second_amount.amount = 0; second_amount.amount = 0;
@ -566,5 +566,5 @@ struct cmd_results *cmd_resize(int argc, char **argv) {
const char usage[] = "Expected 'resize <shrink|grow> " const char usage[] = "Expected 'resize <shrink|grow> "
"<width|height|up|down|left|right> [<amount>] [px|ppt]'"; "<width|height|up|down|left|right> [<amount>] [px|ppt]'";
return cmd_results_new(CMD_INVALID, usage); return cmd_results_new(CMD_INVALID, "%s", usage);
} }

View file

@ -18,7 +18,7 @@ static struct cmd_results *handle_command(struct sway_cursor *cursor,
int argc, char **argv) { int argc, char **argv) {
if (strcasecmp(argv[0], "move") == 0) { if (strcasecmp(argv[0], "move") == 0) {
if (argc < 3) { if (argc < 3) {
return cmd_results_new(CMD_INVALID, expected_syntax); return cmd_results_new(CMD_INVALID, "%s", expected_syntax);
} }
int delta_x = strtol(argv[1], NULL, 10); int delta_x = strtol(argv[1], NULL, 10);
int delta_y = strtol(argv[2], NULL, 10); int delta_y = strtol(argv[2], NULL, 10);
@ -27,7 +27,7 @@ static struct cmd_results *handle_command(struct sway_cursor *cursor,
wlr_seat_pointer_notify_frame(cursor->seat->wlr_seat); wlr_seat_pointer_notify_frame(cursor->seat->wlr_seat);
} else if (strcasecmp(argv[0], "set") == 0) { } else if (strcasecmp(argv[0], "set") == 0) {
if (argc < 3) { if (argc < 3) {
return cmd_results_new(CMD_INVALID, expected_syntax); return cmd_results_new(CMD_INVALID, "%s", expected_syntax);
} }
// map absolute coords (0..1,0..1) to root container coords // map absolute coords (0..1,0..1) to root container coords
float x = strtof(argv[1], NULL) / root->width; float x = strtof(argv[1], NULL) / root->width;
@ -37,7 +37,7 @@ static struct cmd_results *handle_command(struct sway_cursor *cursor,
wlr_seat_pointer_notify_frame(cursor->seat->wlr_seat); wlr_seat_pointer_notify_frame(cursor->seat->wlr_seat);
} else { } else {
if (argc < 2) { if (argc < 2) {
return cmd_results_new(CMD_INVALID, expected_syntax); return cmd_results_new(CMD_INVALID, "%s", expected_syntax);
} }
struct cmd_results *error = NULL; struct cmd_results *error = NULL;
if ((error = press_or_release(cursor, argv[0], argv[1]))) { if ((error = press_or_release(cursor, argv[0], argv[1]))) {
@ -92,14 +92,14 @@ static struct cmd_results *press_or_release(struct sway_cursor *cursor,
} else if (strcasecmp(action, "release") == 0) { } else if (strcasecmp(action, "release") == 0) {
state = WLR_BUTTON_RELEASED; state = WLR_BUTTON_RELEASED;
} else { } else {
return cmd_results_new(CMD_INVALID, expected_syntax); return cmd_results_new(CMD_INVALID, "%s", expected_syntax);
} }
char *message = NULL; char *message = NULL;
button = get_mouse_button(button_str, &message); button = get_mouse_button(button_str, &message);
if (message) { if (message) {
struct cmd_results *error = struct cmd_results *error =
cmd_results_new(CMD_INVALID, message); cmd_results_new(CMD_INVALID, "%s", message);
free(message); free(message);
return error; return error;
} else if (button == SWAY_SCROLL_UP || button == SWAY_SCROLL_DOWN } else if (button == SWAY_SCROLL_UP || button == SWAY_SCROLL_DOWN

View file

@ -32,7 +32,7 @@ static struct cmd_results *do_split(int layout) {
return cmd_results_new(CMD_SUCCESS, NULL); return cmd_results_new(CMD_SUCCESS, NULL);
} }
static struct cmd_results *do_unsplit() { static struct cmd_results *do_unsplit(void) {
struct sway_container *con = config->handler_context.container; struct sway_container *con = config->handler_context.container;
struct sway_workspace *ws = config->handler_context.workspace; struct sway_workspace *ws = config->handler_context.workspace;

View file

@ -46,7 +46,7 @@ struct cmd_results *cmd_swap(int argc, char **argv) {
} }
if (strcasecmp(argv[0], "container") || strcasecmp(argv[1], "with")) { if (strcasecmp(argv[0], "container") || strcasecmp(argv[1], "with")) {
return cmd_results_new(CMD_INVALID, expected_syntax); return cmd_results_new(CMD_INVALID, "%s", expected_syntax);
} }
struct sway_container *current = config->handler_context.container; struct sway_container *current = config->handler_context.container;
@ -65,7 +65,7 @@ struct cmd_results *cmd_swap(int argc, char **argv) {
other = root_find_container(test_mark, value); other = root_find_container(test_mark, value);
} else { } else {
free(value); free(value);
return cmd_results_new(CMD_INVALID, expected_syntax); return cmd_results_new(CMD_INVALID, "%s", expected_syntax);
} }
if (!other) { if (!other) {

View file

@ -61,7 +61,7 @@ static struct cmd_results *cmd_workspace_gaps(int argc, char **argv,
const char expected[] = "Expected 'workspace <name> gaps " const char expected[] = "Expected 'workspace <name> gaps "
"inner|outer|horizontal|vertical|top|right|bottom|left <px>'"; "inner|outer|horizontal|vertical|top|right|bottom|left <px>'";
if (gaps_location == 0) { if (gaps_location == 0) {
return cmd_results_new(CMD_INVALID, expected); return cmd_results_new(CMD_INVALID, "%s", expected);
} }
struct cmd_results *error = NULL; struct cmd_results *error = NULL;
if ((error = checkarg(argc, "workspace", EXPECTED_EQUAL_TO, if ((error = checkarg(argc, "workspace", EXPECTED_EQUAL_TO,
@ -79,7 +79,7 @@ static struct cmd_results *cmd_workspace_gaps(int argc, char **argv,
char *end; char *end;
int amount = strtol(argv[gaps_location + 2], &end, 10); int amount = strtol(argv[gaps_location + 2], &end, 10);
if (strlen(end)) { if (strlen(end)) {
return cmd_results_new(CMD_FAILURE, expected); return cmd_results_new(CMD_FAILURE, "%s", expected);
} }
bool valid = false; bool valid = false;
@ -110,7 +110,7 @@ static struct cmd_results *cmd_workspace_gaps(int argc, char **argv,
} }
} }
if (!valid) { if (!valid) {
return cmd_results_new(CMD_INVALID, expected); return cmd_results_new(CMD_INVALID, "%s", expected);
} }
// Prevent invalid gaps configurations. // Prevent invalid gaps configurations.
@ -174,7 +174,7 @@ struct cmd_results *cmd_workspace(int argc, char **argv) {
} }
if (root->fullscreen_global) { if (root->fullscreen_global) {
return cmd_results_new(CMD_FAILURE, "workspace", return cmd_results_new(CMD_FAILURE,
"Can't switch workspaces while fullscreen global"); "Can't switch workspaces while fullscreen global");
} }

View file

@ -924,23 +924,18 @@ void config_add_swaynag_warning(char *fmt, ...) {
if (config->reading && !config->validating) { if (config->reading && !config->validating) {
va_list args; va_list args;
va_start(args, fmt); va_start(args, fmt);
size_t length = vsnprintf(NULL, 0, fmt, args) + 1; char *str = vformat_str(fmt, args);
va_end(args); va_end(args);
if (str == NULL) {
char *temp = malloc(length + 1);
if (!temp) {
sway_log(SWAY_ERROR, "Failed to allocate buffer for warning.");
return; return;
} }
va_start(args, fmt);
vsnprintf(temp, length, fmt, args);
va_end(args);
swaynag_log(config->swaynag_command, &config->swaynag_config_errors, swaynag_log(config->swaynag_command, &config->swaynag_config_errors,
"Warning on line %i (%s) '%s': %s", "Warning on line %i (%s) '%s': %s",
config->current_config_line_number, config->current_config_path, config->current_config_line_number, config->current_config_path,
config->current_config_line, temp); config->current_config_line, str);
free(str);
} }
} }

View file

@ -153,25 +153,16 @@ static void merge_wildcard_on_all(struct output_config *wildcard) {
} }
static void merge_id_on_name(struct output_config *oc) { static void merge_id_on_name(struct output_config *oc) {
char *id_on_name = NULL; struct sway_output *output = all_output_by_name_or_id(oc->name);
char id[128]; if (output == NULL) {
char *name = NULL; return;
struct sway_output *output;
wl_list_for_each(output, &root->all_outputs, link) {
name = output->wlr_output->name;
output_get_identifier(id, sizeof(id), output);
if (strcmp(name, oc->name) == 0 || strcmp(id, oc->name) == 0) {
size_t length = snprintf(NULL, 0, "%s on %s", id, name) + 1;
id_on_name = malloc(length);
if (!id_on_name) {
sway_log(SWAY_ERROR, "Failed to allocate id on name string");
return;
}
snprintf(id_on_name, length, "%s on %s", id, name);
break;
}
} }
const char *name = output->wlr_output->name;
char id[128];
output_get_identifier(id, sizeof(id), output);
char *id_on_name = format_str("%s on %s", id, name);
if (!id_on_name) { if (!id_on_name) {
return; return;
} }
@ -639,9 +630,7 @@ static struct output_config *get_output_config(char *identifier,
struct output_config *oc_name = NULL; struct output_config *oc_name = NULL;
struct output_config *oc_id = NULL; struct output_config *oc_id = NULL;
size_t length = snprintf(NULL, 0, "%s on %s", identifier, name) + 1; char *id_on_name = format_str("%s on %s", identifier, name);
char *id_on_name = malloc(length);
snprintf(id_on_name, length, "%s on %s", identifier, name);
int i = list_seq_find(config->output_configs, output_name_cmp, id_on_name); int i = list_seq_find(config->output_configs, output_name_cmp, id_on_name);
if (i >= 0) { if (i >= 0) {
oc_id_on_name = config->output_configs->items[i]; oc_id_on_name = config->output_configs->items[i];
@ -728,12 +717,11 @@ void apply_output_config_to_outputs(struct output_config *oc) {
// this is during startup then there will be no container and config // this is during startup then there will be no container and config
// will be applied during normal "new output" event from wlroots. // will be applied during normal "new output" event from wlroots.
bool wildcard = strcmp(oc->name, "*") == 0; bool wildcard = strcmp(oc->name, "*") == 0;
char id[128];
struct sway_output *sway_output, *tmp; struct sway_output *sway_output, *tmp;
wl_list_for_each_safe(sway_output, tmp, &root->all_outputs, link) { wl_list_for_each_safe(sway_output, tmp, &root->all_outputs, link) {
char *name = sway_output->wlr_output->name; if (output_match_name_or_id(sway_output, oc->name)) {
output_get_identifier(id, sizeof(id), sway_output); char id[128];
if (wildcard || !strcmp(name, oc->name) || !strcmp(id, oc->name)) { output_get_identifier(id, sizeof(id), sway_output);
struct output_config *current = get_output_config(id, sway_output); struct output_config *current = get_output_config(id, sway_output);
if (!current) { if (!current) {
// No stored output config matched, apply oc directly // No stored output config matched, apply oc directly

View file

@ -228,7 +228,7 @@ struct launcher_ctx *launcher_ctx_create(struct wlr_xdg_activation_token_v1 *tok
} }
// Creates a context with a new token for the internal launcher // Creates a context with a new token for the internal launcher
struct launcher_ctx *launcher_ctx_create_internal() { struct launcher_ctx *launcher_ctx_create_internal(void) {
struct sway_seat *seat = input_manager_current_seat(); struct sway_seat *seat = input_manager_current_seat();
struct sway_workspace *ws = seat_get_focused_workspace(seat); struct sway_workspace *ws = seat_get_focused_workspace(seat);
if (!ws) { if (!ws) {

View file

@ -36,13 +36,22 @@
#include <wlr/types/wlr_drm_lease_v1.h> #include <wlr/types/wlr_drm_lease_v1.h>
#endif #endif
bool output_match_name_or_id(struct sway_output *output,
const char *name_or_id) {
if (strcmp(name_or_id, "*") == 0) {
return true;
}
char identifier[128];
output_get_identifier(identifier, sizeof(identifier), output);
return strcasecmp(identifier, name_or_id) == 0
|| strcasecmp(output->wlr_output->name, name_or_id) == 0;
}
struct sway_output *output_by_name_or_id(const char *name_or_id) { struct sway_output *output_by_name_or_id(const char *name_or_id) {
for (int i = 0; i < root->outputs->length; ++i) { for (int i = 0; i < root->outputs->length; ++i) {
struct sway_output *output = root->outputs->items[i]; struct sway_output *output = root->outputs->items[i];
char identifier[128]; if (output_match_name_or_id(output, name_or_id)) {
output_get_identifier(identifier, sizeof(identifier), output);
if (strcasecmp(identifier, name_or_id) == 0
|| strcasecmp(output->wlr_output->name, name_or_id) == 0) {
return output; return output;
} }
} }
@ -52,10 +61,7 @@ struct sway_output *output_by_name_or_id(const char *name_or_id) {
struct sway_output *all_output_by_name_or_id(const char *name_or_id) { struct sway_output *all_output_by_name_or_id(const char *name_or_id) {
struct sway_output *output; struct sway_output *output;
wl_list_for_each(output, &root->all_outputs, link) { wl_list_for_each(output, &root->all_outputs, link) {
char identifier[128]; if (output_match_name_or_id(output, name_or_id)) {
output_get_identifier(identifier, sizeof(identifier), output);
if (strcasecmp(identifier, name_or_id) == 0
|| strcasecmp(output->wlr_output->name, name_or_id) == 0) {
return output; return output;
} }
} }
@ -512,6 +518,10 @@ static bool scan_out_fullscreen_view(struct sway_output *output,
return false; return false;
} }
if (!wlr_output_is_direct_scanout_allowed(wlr_output)) {
return false;
}
wlr_output_attach_buffer(wlr_output, &surface->buffer->base); wlr_output_attach_buffer(wlr_output, &surface->buffer->base);
if (!wlr_output_test(wlr_output)) { if (!wlr_output_test(wlr_output)) {
return false; return false;
@ -552,6 +562,11 @@ static int output_repaint_timer_handler(void *data) {
wlr_output->frame_pending = false; wlr_output->frame_pending = false;
if (!wlr_output->needs_frame &&
!pixman_region32_not_empty(&output->damage_ring.current)) {
return 0;
}
struct sway_workspace *workspace = output->current.active_workspace; struct sway_workspace *workspace = output->current.active_workspace;
if (workspace == NULL) { if (workspace == NULL) {
return 0; return 0;
@ -562,6 +577,11 @@ static int output_repaint_timer_handler(void *data) {
fullscreen_con = workspace->current.fullscreen; fullscreen_con = workspace->current.fullscreen;
} }
pixman_region32_t frame_damage;
get_frame_damage(output, &frame_damage);
wlr_output_set_damage(wlr_output, &frame_damage);
pixman_region32_fini(&frame_damage);
if (fullscreen_con && fullscreen_con->view && !debug.noscanout) { if (fullscreen_con && fullscreen_con->view && !debug.noscanout) {
// Try to scan-out the fullscreen view // Try to scan-out the fullscreen view
static bool last_scanned_out = false; static bool last_scanned_out = false;
@ -584,11 +604,6 @@ static int output_repaint_timer_handler(void *data) {
} }
} }
if (!output->wlr_output->needs_frame &&
!pixman_region32_not_empty(&output->damage_ring.current)) {
return 0;
}
int buffer_age; int buffer_age;
if (!wlr_output_attach_render(output->wlr_output, &buffer_age)) { if (!wlr_output_attach_render(output->wlr_output, &buffer_age)) {
return 0; return 0;
@ -605,11 +620,6 @@ static int output_repaint_timer_handler(void *data) {
pixman_region32_fini(&damage); pixman_region32_fini(&damage);
pixman_region32_t frame_damage;
get_frame_damage(output, &frame_damage);
wlr_output_set_damage(wlr_output, &frame_damage);
pixman_region32_fini(&frame_damage);
if (!wlr_output_commit(wlr_output)) { if (!wlr_output_commit(wlr_output)) {
return 0; return 0;
} }
@ -884,11 +894,6 @@ static void handle_mode(struct sway_output *output) {
arrange_output(output); arrange_output(output);
transaction_commit_dirty(); transaction_commit_dirty();
int width, height;
wlr_output_transformed_resolution(output->wlr_output, &width, &height);
wlr_damage_ring_set_bounds(&output->damage_ring, width, height);
wlr_output_schedule_frame(output->wlr_output);
update_output_manager_config(output->server); update_output_manager_config(output->server);
} }
@ -1024,6 +1029,9 @@ void handle_new_output(struct wl_listener *listener, void *data) {
transaction_commit_dirty(); transaction_commit_dirty();
int width, height;
wlr_output_transformed_resolution(output->wlr_output, &width, &height);
wlr_damage_ring_set_bounds(&output->damage_ring, width, height);
update_output_manager_config(server); update_output_manager_config(server);
} }

View file

@ -67,7 +67,13 @@ static void popup_unconstrain(struct sway_xdg_popup *popup) {
struct sway_view *view = popup->child.view; struct sway_view *view = popup->child.view;
struct wlr_xdg_popup *wlr_popup = popup->wlr_xdg_popup; struct wlr_xdg_popup *wlr_popup = popup->wlr_xdg_popup;
struct sway_output *output = view->container->pending.workspace->output; struct sway_workspace *workspace = view->container->pending.workspace;
if (!workspace) {
// is null if in the scratchpad
return;
}
struct sway_output *output = workspace->output;
// the output box expressed in the coordinate system of the toplevel parent // the output box expressed in the coordinate system of the toplevel parent
// of the popup // of the popup

View file

@ -1273,11 +1273,7 @@ uint32_t get_mouse_bindsym(const char *name, char **error) {
// Get event code from name // Get event code from name
int code = libevdev_event_code_from_name(EV_KEY, name); int code = libevdev_event_code_from_name(EV_KEY, name);
if (code == -1) { if (code == -1) {
size_t len = snprintf(NULL, 0, "Unknown event %s", name) + 1; *error = format_str("Unknown event %s", name);
*error = malloc(len);
if (*error) {
snprintf(*error, len, "Unknown event %s", name);
}
return 0; return 0;
} }
return code; return code;
@ -1299,13 +1295,8 @@ uint32_t get_mouse_bindcode(const char *name, char **error) {
} }
const char *event = libevdev_event_code_get_name(EV_KEY, code); const char *event = libevdev_event_code_get_name(EV_KEY, code);
if (!event || strncmp(event, "BTN_", strlen("BTN_")) != 0) { if (!event || strncmp(event, "BTN_", strlen("BTN_")) != 0) {
size_t len = snprintf(NULL, 0, "Event code %d (%s) is not a button", *error = format_str("Event code %d (%s) is not a button",
code, event ? event : "(null)") + 1; code, event ? event : "(null)");
*error = malloc(len);
if (*error) {
snprintf(*error, len, "Event code %d (%s) is not a button",
code, event ? event : "(null)");
}
return 0; return 0;
} }
return code; return code;

View file

@ -80,15 +80,7 @@ char *input_device_get_identifier(struct wlr_input_device *device) {
} }
} }
const char *fmt = "%d:%d:%s"; char *identifier = format_str("%d:%d:%s", vendor, product, name);
int len = snprintf(NULL, 0, fmt, vendor, product, name) + 1;
char *identifier = malloc(len);
if (!identifier) {
sway_log(SWAY_ERROR, "Unable to allocate unique input device name");
return NULL;
}
snprintf(identifier, len, fmt, vendor, product, name);
free(name); free(name);
return identifier; return identifier;
} }

View file

@ -717,23 +717,11 @@ struct sway_keyboard *sway_keyboard_create(struct sway_seat *seat,
static void handle_xkb_context_log(struct xkb_context *context, static void handle_xkb_context_log(struct xkb_context *context,
enum xkb_log_level level, const char *format, va_list args) { enum xkb_log_level level, const char *format, va_list args) {
va_list args_copy; char *error = vformat_str(format, args);
va_copy(args_copy, args);
size_t length = vsnprintf(NULL, 0, format, args_copy) + 1;
va_end(args_copy);
char *error = malloc(length); size_t len = strlen(error);
if (!error) { if (error[len - 1] == '\n') {
sway_log(SWAY_ERROR, "Failed to allocate libxkbcommon log message"); error[len - 1] = '\0';
return;
}
va_copy(args_copy, args);
vsnprintf(error, length, format, args_copy);
va_end(args_copy);
if (error[length - 2] == '\n') {
error[length - 2] = '\0';
} }
sway_log_importance_t importance = SWAY_DEBUG; sway_log_importance_t importance = SWAY_DEBUG;
@ -768,13 +756,8 @@ struct xkb_keymap *sway_keyboard_compile_keymap(struct input_config *ic,
if (!keymap_file) { if (!keymap_file) {
sway_log_errno(SWAY_ERROR, "cannot read xkb file %s", ic->xkb_file); sway_log_errno(SWAY_ERROR, "cannot read xkb file %s", ic->xkb_file);
if (error) { if (error) {
size_t len = snprintf(NULL, 0, "cannot read xkb file %s: %s", *error = format_str("cannot read xkb file %s: %s",
ic->xkb_file, strerror(errno)) + 1; ic->xkb_file, strerror(errno));
*error = malloc(len);
if (*error) {
snprintf(*error, len, "cannot read xkb_file %s: %s",
ic->xkb_file, strerror(errno));
}
} }
goto cleanup; goto cleanup;
} }

View file

@ -935,6 +935,11 @@ static json_object *describe_libinput_device(struct libinput_device *device) {
case LIBINPUT_CONFIG_ACCEL_PROFILE_ADAPTIVE: case LIBINPUT_CONFIG_ACCEL_PROFILE_ADAPTIVE:
accel_profile = "adaptive"; accel_profile = "adaptive";
break; break;
#if HAVE_LIBINPUT_CONFIG_ACCEL_PROFILE_CUSTOM
case LIBINPUT_CONFIG_ACCEL_PROFILE_CUSTOM:
accel_profile = "custom";
break;
#endif
} }
json_object_object_add(object, "accel_profile", json_object_object_add(object, "accel_profile",
json_object_new_string(accel_profile)); json_object_new_string(accel_profile));

View file

@ -103,7 +103,7 @@ bool server_init(struct sway_server *server) {
return false; return false;
} }
server->compositor = wlr_compositor_create(server->wl_display, server->compositor = wlr_compositor_create(server->wl_display, 5,
server->renderer); server->renderer);
server->compositor_new_surface.notify = handle_compositor_new_surface; server->compositor_new_surface.notify = handle_compositor_new_surface;
wl_signal_add(&server->compositor->events.new_surface, wl_signal_add(&server->compositor->events.new_surface,

View file

@ -228,6 +228,8 @@ correct seat.
absolute coordinates (with respect to the global coordinate space). absolute coordinates (with respect to the global coordinate space).
Specifying either value as 0 will not update that coordinate. Specifying either value as 0 will not update that coordinate.
Deprecated: use the virtual-pointer Wayland protocol instead.
*seat* <seat> cursor press|release button[1-9]|<event-name-or-code> *seat* <seat> cursor press|release button[1-9]|<event-name-or-code>
Simulate pressing (or releasing) the specified mouse button on the Simulate pressing (or releasing) the specified mouse button on the
specified seat. The button can either be provided as a button event name or specified seat. The button can either be provided as a button event name or
@ -236,6 +238,8 @@ correct seat.
event will be simulated, however _press_ and _release_ will be ignored and event will be simulated, however _press_ and _release_ will be ignored and
both will occur. both will occur.
Deprecated: use the virtual-pointer Wayland protocol instead.
*seat* <name> fallback true|false *seat* <name> fallback true|false
Set this seat as the fallback seat. A fallback seat will attach any device Set this seat as the fallback seat. A fallback seat will attach any device
not explicitly attached to another seat (similar to a "default" seat). not explicitly attached to another seat (similar to a "default" seat).
@ -251,6 +255,10 @@ correct seat.
If _when-typing_ is enabled, then the cursor will be hidden whenever a key If _when-typing_ is enabled, then the cursor will be hidden whenever a key
is pressed. is pressed.
Be aware that this setting can interfere with input handling in games and
certain types of software (Gimp, Blender etc) that rely on simultaneous
input from mouse and keyboard.
*seat* <name> idle_inhibit <sources...> *seat* <name> idle_inhibit <sources...>
Sets the set of input event sources which can prevent the seat from Sets the set of input event sources which can prevent the seat from
becoming idle, as a space separated list of source names. Valid names are becoming idle, as a space separated list of source names. Valid names are

View file

@ -145,22 +145,16 @@ void swaynag_log(const char *swaynag_command, struct swaynag_instance *swaynag,
va_list args; va_list args;
va_start(args, fmt); va_start(args, fmt);
size_t length = vsnprintf(NULL, 0, fmt, args) + 1; char *str = vformat_str(fmt, args);
va_end(args); va_end(args);
if (!str) {
char *temp = malloc(length + 1);
if (!temp) {
sway_log(SWAY_ERROR, "Failed to allocate buffer for swaynag log entry."); sway_log(SWAY_ERROR, "Failed to allocate buffer for swaynag log entry.");
return; return;
} }
va_start(args, fmt); write(swaynag->fd[1], str, strlen(str));
vsnprintf(temp, length, fmt, args);
va_end(args);
write(swaynag->fd[1], temp, length); free(str);
free(temp);
} }
void swaynag_show(struct swaynag_instance *swaynag) { void swaynag_show(struct swaynag_instance *swaynag) {

View file

@ -264,6 +264,9 @@ void arrange_workspace(struct sway_workspace *workspace) {
area->width, area->height, area->x, area->y); area->width, area->height, area->x, area->y);
bool first_arrange = workspace->width == 0 && workspace->height == 0; bool first_arrange = workspace->width == 0 && workspace->height == 0;
struct wlr_box prev_box;
workspace_get_box(workspace, &prev_box);
double prev_x = workspace->x - workspace->current_gaps.left; double prev_x = workspace->x - workspace->current_gaps.left;
double prev_y = workspace->y - workspace->current_gaps.top; double prev_y = workspace->y - workspace->current_gaps.top;
workspace->width = area->width; workspace->width = area->width;
@ -277,13 +280,14 @@ void arrange_workspace(struct sway_workspace *workspace) {
if (!first_arrange && (diff_x != 0 || diff_y != 0)) { if (!first_arrange && (diff_x != 0 || diff_y != 0)) {
for (int i = 0; i < workspace->floating->length; ++i) { for (int i = 0; i < workspace->floating->length; ++i) {
struct sway_container *floater = workspace->floating->items[i]; struct sway_container *floater = workspace->floating->items[i];
container_floating_translate(floater, diff_x, diff_y);
double center_x = floater->pending.x + floater->pending.width / 2;
double center_y = floater->pending.y + floater->pending.height / 2;
struct wlr_box workspace_box; struct wlr_box workspace_box;
workspace_get_box(workspace, &workspace_box); workspace_get_box(workspace, &workspace_box);
if (!wlr_box_contains_point(&workspace_box, center_x, center_y)) { floating_fix_coordinates(floater, &prev_box, &workspace_box);
container_floating_move_to_center(floater); // Set transformation for scratchpad windows.
if (floater->scratchpad) {
struct wlr_box output_box;
output_get_box(output, &output_box);
floater->transform = output_box;
} }
} }
} }

View file

@ -712,6 +712,21 @@ void floating_calculate_constraints(int *min_width, int *max_width,
} }
void floating_fix_coordinates(struct sway_container *con, struct wlr_box *old, struct wlr_box *new) {
if (!old->width || !old->height) {
// Fall back to centering on the workspace.
container_floating_move_to_center(con);
} else {
int rel_x = con->pending.x - old->x + (con->pending.width / 2);
int rel_y = con->pending.y - old->y + (con->pending.height / 2);
con->pending.x = new->x + (double)(rel_x * new->width) / old->width - (con->pending.width / 2);
con->pending.y = new->y + (double)(rel_y * new->height) / old->height - (con->pending.height / 2);
sway_log(SWAY_DEBUG, "Transformed container %p to coords (%f, %f)", con, con->pending.x, con->pending.y);
}
}
static void floating_natural_resize(struct sway_container *con) { static void floating_natural_resize(struct sway_container *con) {
int min_width, max_width, min_height, max_height; int min_width, max_width, min_height, max_height;
floating_calculate_constraints(&min_width, &max_width, floating_calculate_constraints(&min_width, &max_width,
@ -1025,6 +1040,13 @@ void container_floating_move_to(struct sway_container *con,
workspace_add_floating(new_workspace, con); workspace_add_floating(new_workspace, con);
arrange_workspace(old_workspace); arrange_workspace(old_workspace);
arrange_workspace(new_workspace); arrange_workspace(new_workspace);
// If the moved container was a visible scratchpad container, then
// update its transform.
if (con->scratchpad) {
struct wlr_box output_box;
output_get_box(new_output, &output_box);
con->transform = output_box;
}
workspace_detect_urgent(old_workspace); workspace_detect_urgent(old_workspace);
workspace_detect_urgent(new_workspace); workspace_detect_urgent(new_workspace);
} }

View file

@ -56,6 +56,16 @@ void root_destroy(struct sway_root *root) {
free(root); free(root);
} }
static void set_container_transform(struct sway_workspace *ws,
struct sway_container *con) {
struct sway_output *output = ws->output;
struct wlr_box box = {0};
if (output) {
output_get_box(output, &box);
}
con->transform = box;
}
void root_scratchpad_add_container(struct sway_container *con, struct sway_workspace *ws) { void root_scratchpad_add_container(struct sway_container *con, struct sway_workspace *ws) {
if (!sway_assert(!con->scratchpad, "Container is already in scratchpad")) { if (!sway_assert(!con->scratchpad, "Container is already in scratchpad")) {
return; return;
@ -64,6 +74,8 @@ void root_scratchpad_add_container(struct sway_container *con, struct sway_works
struct sway_container *parent = con->pending.parent; struct sway_container *parent = con->pending.parent;
struct sway_workspace *workspace = con->pending.workspace; struct sway_workspace *workspace = con->pending.workspace;
set_container_transform(workspace, con);
// Clear the fullscreen mode when sending to the scratchpad // Clear the fullscreen mode when sending to the scratchpad
if (con->pending.fullscreen_mode != FULLSCREEN_NONE) { if (con->pending.fullscreen_mode != FULLSCREEN_NONE) {
container_fullscreen_disable(con); container_fullscreen_disable(con);
@ -133,7 +145,10 @@ void root_scratchpad_show(struct sway_container *con) {
// Show the container // Show the container
if (old_ws) { if (old_ws) {
container_detach(con); container_detach(con);
workspace_consider_destroy(old_ws); // Make sure the last inactive container on the old workspace is above
// the workspace itself in the focus stack.
struct sway_node *node = seat_get_focus_inactive(seat, &old_ws->node);
seat_set_raw_focus(seat, node);
} else { } else {
// Act on the ancestor of scratchpad hidden split containers // Act on the ancestor of scratchpad hidden split containers
while (con->pending.parent) { while (con->pending.parent) {
@ -142,18 +157,18 @@ void root_scratchpad_show(struct sway_container *con) {
} }
workspace_add_floating(new_ws, con); workspace_add_floating(new_ws, con);
// Make sure the container's center point overlaps this workspace if (new_ws->output) {
double center_lx = con->pending.x + con->pending.width / 2; struct wlr_box output_box;
double center_ly = con->pending.y + con->pending.height / 2; output_get_box(new_ws->output, &output_box);
floating_fix_coordinates(con, &con->transform, &output_box);
struct wlr_box workspace_box;
workspace_get_box(new_ws, &workspace_box);
if (!wlr_box_contains_point(&workspace_box, center_lx, center_ly)) {
container_floating_resize_and_center(con);
} }
set_container_transform(new_ws, con);
arrange_workspace(new_ws); arrange_workspace(new_ws);
seat_set_focus(seat, seat_get_focus_inactive(seat, &con->node)); seat_set_focus(seat, seat_get_focus_inactive(seat, &con->node));
if (old_ws) {
workspace_consider_destroy(old_ws);
}
} }
static void disable_fullscreen(struct sway_container *con, void *data) { static void disable_fullscreen(struct sway_container *con, void *data) {
@ -173,6 +188,8 @@ void root_scratchpad_hide(struct sway_container *con) {
return; return;
} }
set_container_transform(con->pending.workspace, con);
disable_fullscreen(con, NULL); disable_fullscreen(con, NULL);
container_for_each_child(con, disable_fullscreen, NULL); container_for_each_child(con, disable_fullscreen, NULL);
container_detach(con); container_detach(con);

View file

@ -176,22 +176,16 @@ void workspace_consider_destroy(struct sway_workspace *ws) {
static bool workspace_valid_on_output(const char *output_name, static bool workspace_valid_on_output(const char *output_name,
const char *ws_name) { const char *ws_name) {
struct workspace_config *wsc = workspace_find_config(ws_name); struct workspace_config *wsc = workspace_find_config(ws_name);
char identifier[128];
struct sway_output *output = output_by_name_or_id(output_name); struct sway_output *output = output_by_name_or_id(output_name);
if (!output) { if (!output) {
return false; return false;
} }
output_name = output->wlr_output->name;
output_get_identifier(identifier, sizeof(identifier), output);
if (!wsc) { if (!wsc) {
return true; return true;
} }
for (int i = 0; i < wsc->outputs->length; i++) { for (int i = 0; i < wsc->outputs->length; i++) {
if (strcmp(wsc->outputs->items[i], "*") == 0 || if (output_match_name_or_id(output, wsc->outputs->items[i])) {
strcmp(wsc->outputs->items[i], output_name) == 0 ||
strcmp(wsc->outputs->items[i], identifier) == 0) {
return true; return true;
} }
} }
@ -286,13 +280,10 @@ char *workspace_next_name(const char *output_name) {
// assignments primarily, falling back to bindings and numbers. // assignments primarily, falling back to bindings and numbers.
struct sway_mode *mode = config->current_mode; struct sway_mode *mode = config->current_mode;
char identifier[128];
struct sway_output *output = output_by_name_or_id(output_name); struct sway_output *output = output_by_name_or_id(output_name);
if (!output) { if (!output) {
return NULL; return NULL;
} }
output_name = output->wlr_output->name;
output_get_identifier(identifier, sizeof(identifier), output);
int order = INT_MAX; int order = INT_MAX;
char *target = NULL; char *target = NULL;
@ -312,9 +303,7 @@ char *workspace_next_name(const char *output_name) {
} }
bool found = false; bool found = false;
for (int j = 0; j < wsc->outputs->length; ++j) { for (int j = 0; j < wsc->outputs->length; ++j) {
if (strcmp(wsc->outputs->items[j], "*") == 0 || if (output_match_name_or_id(output, wsc->outputs->items[j])) {
strcmp(wsc->outputs->items[j], output_name) == 0 ||
strcmp(wsc->outputs->items[j], identifier) == 0) {
found = true; found = true;
free(target); free(target);
target = strdup(wsc->workspace); target = strdup(wsc->workspace);
@ -654,15 +643,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, struct sway_output *exclude) {
char exclude_id[128] = {'\0'};
if (exclude) {
output_get_identifier(exclude_id, sizeof(exclude_id), exclude);
}
for (int i = 0; i < ws->output_priority->length; i++) { for (int i = 0; i < ws->output_priority->length; i++) {
char *name = ws->output_priority->items[i]; const char *name = ws->output_priority->items[i];
if (exclude && (strcmp(name, exclude->wlr_output->name) == 0 if (exclude && output_match_name_or_id(exclude, name)) {
|| strcmp(name, exclude_id) == 0)) {
continue; continue;
} }

View file

@ -693,15 +693,6 @@ static uint32_t render_to_cairo(struct render_context *ctx) {
struct swaybar_output *output = ctx->output; struct swaybar_output *output = ctx->output;
struct swaybar *bar = output->bar; struct swaybar *bar = output->bar;
struct swaybar_config *config = bar->config; struct swaybar_config *config = bar->config;
cairo_set_operator(cairo, CAIRO_OPERATOR_SOURCE);
if (output->focused) {
ctx->background_color = config->colors.focused_background;
} else {
ctx->background_color = config->colors.background;
}
cairo_set_source_u32(cairo, ctx->background_color);
cairo_paint(cairo);
int th; int th;
get_text_size(cairo, config->font_description, NULL, &th, NULL, 1, false, ""); get_text_size(cairo, config->font_description, NULL, &th, NULL, 1, false, "");
@ -763,8 +754,17 @@ void render_frame(struct swaybar_output *output) {
free_hotspots(&output->hotspots); free_hotspots(&output->hotspots);
uint32_t background_color;
if (output->focused) {
background_color = output->bar->config->colors.focused_background;
} else {
background_color = output->bar->config->colors.background;
}
struct render_context ctx = { 0 }; struct render_context ctx = { 0 };
ctx.output = output; ctx.output = output;
// initial background color used for deciding the best way to antialias text
ctx.background_color = background_color;
cairo_surface_t *recorder = cairo_recording_surface_create( cairo_surface_t *recorder = cairo_recording_surface_create(
CAIRO_CONTENT_COLOR_ALPHA, NULL); CAIRO_CONTENT_COLOR_ALPHA, NULL);
@ -786,10 +786,11 @@ void render_frame(struct swaybar_output *output) {
ctx.textaa_sharp = fo; ctx.textaa_sharp = fo;
} }
cairo_save(cairo);
cairo_set_operator(cairo, CAIRO_OPERATOR_CLEAR); cairo_set_operator(cairo, CAIRO_OPERATOR_SOURCE);
cairo_set_source_u32(cairo, background_color);
cairo_paint(cairo); cairo_paint(cairo);
cairo_restore(cairo);
uint32_t height = render_to_cairo(&ctx); uint32_t height = render_to_cairo(&ctx);
int config_height = output->bar->config->height; int config_height = output->bar->config->height;
if (config_height > 0) { if (config_height > 0) {
@ -834,13 +835,15 @@ void render_frame(struct swaybar_output *output) {
wl_surface_damage(output->surface, 0, 0, wl_surface_damage(output->surface, 0, 0,
output->width, output->height); output->width, output->height);
uint32_t bg_alpha = ctx.background_color & 0xFF; uint32_t bg_alpha = background_color & 0xFF;
if (bg_alpha == 0xFF) { if (bg_alpha == 0xFF) {
struct wl_region *region = struct wl_region *region =
wl_compositor_create_region(output->bar->compositor); wl_compositor_create_region(output->bar->compositor);
wl_region_add(region, 0, 0, INT32_MAX, INT32_MAX); wl_region_add(region, 0, 0, INT32_MAX, INT32_MAX);
wl_surface_set_opaque_region(output->surface, region); wl_surface_set_opaque_region(output->surface, region);
wl_region_destroy(region); wl_region_destroy(region);
} else {
wl_surface_set_opaque_region(output->surface, NULL);
} }
struct wl_callback *frame_callback = wl_surface_frame(output->surface); struct wl_callback *frame_callback = wl_surface_frame(output->surface);

View file

@ -10,6 +10,7 @@
#include "swaybar/tray/tray.h" #include "swaybar/tray/tray.h"
#include "list.h" #include "list.h"
#include "log.h" #include "log.h"
#include "stringop.h"
static const char *watcher_path = "/StatusNotifierWatcher"; static const char *watcher_path = "/StatusNotifierWatcher";
@ -138,12 +139,10 @@ static int handle_new_watcher(sd_bus_message *msg,
bool init_host(struct swaybar_host *host, char *protocol, bool init_host(struct swaybar_host *host, char *protocol,
struct swaybar_tray *tray) { struct swaybar_tray *tray) {
size_t len = snprintf(NULL, 0, "org.%s.StatusNotifierWatcher", protocol) + 1; host->watcher_interface = format_str("org.%s.StatusNotifierWatcher", protocol);
host->watcher_interface = malloc(len);
if (!host->watcher_interface) { if (!host->watcher_interface) {
return false; return false;
} }
snprintf(host->watcher_interface, len, "org.%s.StatusNotifierWatcher", protocol);
sd_bus_slot *reg_slot = NULL, *unreg_slot = NULL, *watcher_slot = NULL; sd_bus_slot *reg_slot = NULL, *unreg_slot = NULL, *watcher_slot = NULL;
int ret = sd_bus_match_signal(tray->bus, &reg_slot, host->watcher_interface, int ret = sd_bus_match_signal(tray->bus, &reg_slot, host->watcher_interface,
@ -173,13 +172,10 @@ bool init_host(struct swaybar_host *host, char *protocol,
} }
pid_t pid = getpid(); pid_t pid = getpid();
size_t service_len = snprintf(NULL, 0, "org.%s.StatusNotifierHost-%d", host->service = format_str("org.%s.StatusNotifierHost-%d", protocol, pid);
protocol, pid) + 1;
host->service = malloc(service_len);
if (!host->service) { if (!host->service) {
goto error; goto error;
} }
snprintf(host->service, service_len, "org.%s.StatusNotifierHost-%d", protocol, pid);
ret = sd_bus_request_name(tray->bus, host->service, 0); ret = sd_bus_request_name(tray->bus, host->service, 0);
if (ret < 0) { if (ret < 0) {
sway_log(SWAY_DEBUG, "Failed to acquire service name: %s", strerror(-ret)); sway_log(SWAY_DEBUG, "Failed to acquire service name: %s", strerror(-ret));

View file

@ -40,9 +40,7 @@ static list_t *get_basedirs(void) {
data_dirs = strdup(data_dirs); data_dirs = strdup(data_dirs);
char *dir = strtok(data_dirs, ":"); char *dir = strtok(data_dirs, ":");
do { do {
size_t path_len = snprintf(NULL, 0, "%s/icons", dir) + 1; char *path = format_str("%s/icons", dir);
char *path = malloc(path_len);
snprintf(path, path_len, "%s/icons", dir);
list_add(basedirs, path); list_add(basedirs, path);
} while ((dir = strtok(NULL, ":"))); } while ((dir = strtok(NULL, ":")));
free(data_dirs); free(data_dirs);
@ -206,13 +204,7 @@ static const char *entry_handler(char *group, char *key, char *value,
*/ */
static struct icon_theme *read_theme_file(char *basedir, char *theme_name) { static struct icon_theme *read_theme_file(char *basedir, char *theme_name) {
// look for index.theme file // look for index.theme file
size_t path_len = snprintf(NULL, 0, "%s/%s/index.theme", basedir, char *path = format_str("%s/%s/index.theme", basedir, theme_name);
theme_name) + 1;
char *path = malloc(path_len);
if (!path) {
return NULL;
}
snprintf(path, path_len, "%s/%s/index.theme", basedir, theme_name);
FILE *theme_file = fopen(path, "r"); FILE *theme_file = fopen(path, "r");
free(path); free(path);
if (!theme_file) { if (!theme_file) {
@ -416,26 +408,20 @@ static char *find_icon_in_subdir(char *name, char *basedir, char *theme,
#endif #endif
}; };
size_t path_len = snprintf(NULL, 0, "%s/%s/%s/%s.EXT", basedir, theme,
subdir, name) + 1;
char *path = malloc(path_len);
for (size_t i = 0; i < sizeof(extensions) / sizeof(*extensions); ++i) { for (size_t i = 0; i < sizeof(extensions) / sizeof(*extensions); ++i) {
snprintf(path, path_len, "%s/%s/%s/%s.%s", basedir, theme, subdir, char *path = format_str("%s/%s/%s/%s.%s",
name, extensions[i]); basedir, theme, subdir, name, extensions[i]);
if (access(path, R_OK) == 0) { if (access(path, R_OK) == 0) {
return path; return path;
} }
free(path);
} }
free(path);
return NULL; return NULL;
} }
static bool theme_exists_in_basedir(char *theme, char *basedir) { static bool theme_exists_in_basedir(char *theme, char *basedir) {
size_t path_len = snprintf(NULL, 0, "%s/%s", basedir, theme) + 1; char *path = format_str("%s/%s", basedir, theme);
char *path = malloc(path_len);
snprintf(path, path_len, "%s/%s", basedir, theme);
bool ret = dir_exists(path); bool ret = dir_exists(path);
free(path); free(path);
return ret; return ret;

View file

@ -6,6 +6,7 @@
#include <string.h> #include <string.h>
#include "list.h" #include "list.h"
#include "log.h" #include "log.h"
#include "stringop.h"
#include "swaybar/tray/watcher.h" #include "swaybar/tray/watcher.h"
static const char *obj_path = "/StatusNotifierWatcher"; static const char *obj_path = "/StatusNotifierWatcher";
@ -76,9 +77,7 @@ static int register_sni(sd_bus_message *msg, void *data, sd_bus_error *error) {
service = service_or_path; service = service_or_path;
path = "/StatusNotifierItem"; path = "/StatusNotifierItem";
} }
size_t id_len = snprintf(NULL, 0, "%s%s", service, path) + 1; id = format_str("%s%s", service, path);
id = malloc(id_len);
snprintf(id, id_len, "%s%s", service, path);
} }
if (list_seq_find(watcher->items, cmp_id, id) == -1) { if (list_seq_find(watcher->items, cmp_id, id) == -1) {
@ -159,9 +158,7 @@ struct swaybar_watcher *create_watcher(char *protocol, sd_bus *bus) {
return NULL; return NULL;
} }
size_t len = snprintf(NULL, 0, "org.%s.StatusNotifierWatcher", protocol) + 1; watcher->interface = format_str("org.%s.StatusNotifierWatcher", protocol);
watcher->interface = malloc(len);
snprintf(watcher->interface, len, "org.%s.StatusNotifierWatcher", protocol);
sd_bus_slot *signal_slot = NULL, *vtable_slot = NULL; sd_bus_slot *signal_slot = NULL, *vtable_slot = NULL;
int ret = sd_bus_add_object_vtable(bus, &vtable_slot, obj_path, int ret = sd_bus_add_object_vtable(bus, &vtable_slot, obj_path,