aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZandr Martin <zandrmartin@gmail.com>2016-07-30 18:50:13 -0500
committerZandr Martin <zandrmartin@gmail.com>2016-07-30 18:50:13 -0500
commit98aa59fdda5fcc9a589e93f7c6ef40d3eaee3972 (patch)
treea7acb9aab8520040d49be04184d70984a66b95e7
parent2e4ece65da7e2afe5da1d3347c88bda48b1efa90 (diff)
implement solid color rendering for swaybg
-rw-r--r--common/CMakeLists.txt2
-rw-r--r--common/util.c13
-rw-r--r--include/bar/config.h6
-rw-r--r--include/config.h2
-rw-r--r--include/util.h6
-rw-r--r--sway/commands.c75
-rw-r--r--sway/sway.5.txt4
-rw-r--r--swaybar/config.c13
-rw-r--r--swaybar/status_line.c1
-rw-r--r--swaybg/main.c216
10 files changed, 189 insertions, 149 deletions
diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt
index 9c2c0a99..3d6e0fb9 100644
--- a/common/CMakeLists.txt
+++ b/common/CMakeLists.txt
@@ -12,6 +12,8 @@ add_library(sway-common STATIC
stringop.c
)
+target_link_libraries(sway-common m)
+
if(Backtrace_FOUND)
set_target_properties(sway-common
PROPERTIES
diff --git a/common/util.c b/common/util.c
index 31a75a9b..86120769 100644
--- a/common/util.c
+++ b/common/util.c
@@ -97,3 +97,16 @@ pid_t get_parent_pid(pid_t child) {
return -1;
}
+
+uint32_t parse_color(const char *color) {
+ int len = strlen(color);
+ if (color[0] != '#' || (len != 7 && len != 9)) {
+ sway_log(L_DEBUG, "Invalid color %s, defaulting to color 0xFFFFFFFF", color);
+ return 0xFFFFFFFF;
+ }
+ uint32_t res = (uint32_t)strtol(color + 1, NULL, 16);
+ if (strlen(color) == 7) {
+ res = (res << 8) | 0xFF;
+ }
+ return res;
+}
diff --git a/include/bar/config.h b/include/bar/config.h
index c957caa7..934116ca 100644
--- a/include/bar/config.h
+++ b/include/bar/config.h
@@ -5,6 +5,7 @@
#include <stdbool.h>
#include "list.h"
+#include "util.h"
/**
* Colors for a box with background, border and text colors.
@@ -48,11 +49,6 @@ struct config {
};
/**
- * Parse colors defined as hex string to uint32_t.
- */
-uint32_t parse_color(const char *color);
-
-/**
* Parse position top|bottom|left|right.
*/
uint32_t parse_position(const char *position);
diff --git a/include/config.h b/include/config.h
index 5e1c123e..56deaf01 100644
--- a/include/config.h
+++ b/include/config.h
@@ -81,7 +81,7 @@ struct output_config {
int enabled;
int width, height;
int x, y;
- int scale;
+ int scale;
char *background;
char *background_option;
};
diff --git a/include/util.h b/include/util.h
index 6f21bff0..e33a08f7 100644
--- a/include/util.h
+++ b/include/util.h
@@ -44,4 +44,10 @@ int get_modifier_names(const char **names, uint32_t modifier_masks);
*/
pid_t get_parent_pid(pid_t pid);
+/**
+ * Given a string that represents an RGB(A) color, return a uint32_t
+ * version of the color.
+ */
+uint32_t parse_color(const char *color);
+
#endif
diff --git a/sway/commands.c b/sway/commands.c
index 053b5792..7247a407 100644
--- a/sway/commands.c
+++ b/sway/commands.c
@@ -1651,47 +1651,52 @@ static struct cmd_results *cmd_output(int argc, char **argv) {
} else if (strcasecmp(command, "background") == 0 || strcasecmp(command, "bg") == 0) {
wordexp_t p;
if (++i >= argc) {
- return cmd_results_new(CMD_INVALID, "output", "Missing background file.");
+ return cmd_results_new(CMD_INVALID, "output", "Missing background file or color specification.");
}
if (i + 1 >= argc) {
- return cmd_results_new(CMD_INVALID, "output", "Missing background scaling mode.");
+ return cmd_results_new(CMD_INVALID, "output", "Missing background scaling mode or `solid_color`.");
}
- char *src = join_args(argv + i, argc - i - 1);
- char *mode = argv[argc - 1];
- if (wordexp(src, &p, 0) != 0 || p.we_wordv[0] == NULL) {
- return cmd_results_new(CMD_INVALID, "output", "Invalid syntax (%s)", src);
- }
- free(src);
- src = p.we_wordv[0];
- if (config->reading && *src != '/') {
- char *conf = strdup(config->current_config);
- char *conf_path = dirname(conf);
- src = malloc(strlen(conf_path) + strlen(src) + 2);
- sprintf(src, "%s/%s", conf_path, p.we_wordv[0]);
- free(conf);
- }
- if (access(src, F_OK) == -1) {
- return cmd_results_new(CMD_INVALID, "output", "Background file unreadable (%s)", src);
- }
- for (char *m = mode; *m; ++m) *m = tolower(*m);
- // Check mode
- bool valid = false;
- size_t j;
- for (j = 0; j < sizeof(bg_options) / sizeof(char *); ++j) {
- if (strcasecmp(mode, bg_options[j]) == 0) {
- valid = true;
- break;
+ if (strcasecmp(argv[argc - 1], "solid_color") == 0) {
+ output->background = strdup(argv[argc - 2]);
+ output->background_option = strdup("solid_color");
+ } else {
+ char *src = join_args(argv + i, argc - i - 1);
+ char *mode = argv[argc - 1];
+ if (wordexp(src, &p, 0) != 0 || p.we_wordv[0] == NULL) {
+ return cmd_results_new(CMD_INVALID, "output", "Invalid syntax (%s)", src);
}
- }
- if (!valid) {
- return cmd_results_new(CMD_INVALID, "output", "Invalid background scaling mode.");
- }
- output->background = strdup(src);
- output->background_option = strdup(mode);
- if (src != p.we_wordv[0]) {
free(src);
+ src = p.we_wordv[0];
+ if (config->reading && *src != '/') {
+ char *conf = strdup(config->current_config);
+ char *conf_path = dirname(conf);
+ src = malloc(strlen(conf_path) + strlen(src) + 2);
+ sprintf(src, "%s/%s", conf_path, p.we_wordv[0]);
+ free(conf);
+ }
+ if (access(src, F_OK) == -1) {
+ return cmd_results_new(CMD_INVALID, "output", "Background file unreadable (%s)", src);
+ }
+ for (char *m = mode; *m; ++m) *m = tolower(*m);
+ // Check mode
+ bool valid = false;
+ size_t j;
+ for (j = 0; j < sizeof(bg_options) / sizeof(char *); ++j) {
+ if (strcasecmp(mode, bg_options[j]) == 0) {
+ valid = true;
+ break;
+ }
+ }
+ if (!valid) {
+ return cmd_results_new(CMD_INVALID, "output", "Invalid background scaling mode.");
+ }
+ output->background = strdup(src);
+ output->background_option = strdup(mode);
+ if (src != p.we_wordv[0]) {
+ free(src);
+ }
+ wordfree(&p);
}
- wordfree(&p);
}
}
diff --git a/sway/sway.5.txt b/sway/sway.5.txt
index 446995d5..787253a0 100644
--- a/sway/sway.5.txt
+++ b/sway/sway.5.txt
@@ -308,6 +308,10 @@ The default colors are:
Sets the wallpaper for the given output to the specified file, using the given
scaling mode (one of "stretch", "fill", "fit", "center", "tile").
+**output** <name> <background|bg> <color> solid_color::
+ Sets the background of the given output to the specified color. _color_ should
+ be specified as an _#rrggbb_ (no alpha) color.
+
**output** <name> disable::
Disables the specified output.
diff --git a/swaybar/config.c b/swaybar/config.c
index f3a3e716..b5dca668 100644
--- a/swaybar/config.c
+++ b/swaybar/config.c
@@ -5,19 +5,6 @@
#include "log.h"
#include "bar/config.h"
-uint32_t parse_color(const char *color) {
- if (color[0] != '#') {
- sway_log(L_DEBUG, "Invalid color %s, defaulting to color 0xFFFFFFFF", color);
- return 0xFFFFFFFF;
- }
- char *end;
- uint32_t res = (uint32_t)strtol(color + 1, &end, 16);
- if (strlen(color) == 7) {
- res = (res << 8) | 0xFF;
- }
- return res;
-}
-
uint32_t parse_position(const char *position) {
if (strcmp("top", position) == 0) {
return DESKTOP_SHELL_PANEL_POSITION_TOP;
diff --git a/swaybar/status_line.c b/swaybar/status_line.c
index 49a8363a..33a8908f 100644
--- a/swaybar/status_line.c
+++ b/swaybar/status_line.c
@@ -6,6 +6,7 @@
#include "log.h"
#include "bar/config.h"
#include "bar/status_line.h"
+#include "util.h"
#define I3JSON_MAXDEPTH 4
#define I3JSON_UNKNOWN 0
diff --git a/swaybg/main.c b/swaybg/main.c
index 4e0cc4b3..b23b8027 100644
--- a/swaybg/main.c
+++ b/swaybg/main.c
@@ -1,6 +1,8 @@
#include "wayland-desktop-shell-client-protocol.h"
+#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
+#include <ctype.h>
#include <wayland-client.h>
#include <time.h>
#include <string.h>
@@ -9,6 +11,7 @@
#include "client/cairo.h"
#include "log.h"
#include "list.h"
+#include "util.h"
list_t *surfaces;
struct registry *registry;
@@ -32,6 +35,23 @@ void sway_terminate(int exit_code) {
exit(exit_code);
}
+bool is_valid_color(const char *color) {
+ int len = strlen(color);
+ if (len != 7 || color[0] != '#') {
+ sway_log(L_ERROR, "%s is not a valid color for swaybg. Color should be specified as #rrggbb (no alpha).", color);
+ return false;
+ }
+
+ int i;
+ for (i = 1; i < len; ++i) {
+ if (!isxdigit(color[i])) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
int main(int argc, const char **argv) {
init_log(L_INFO);
surfaces = create_list();
@@ -57,112 +77,118 @@ int main(int argc, const char **argv) {
window_make_shell(window);
list_add(surfaces, window);
+ if (strcmp(argv[3], "solid_color") == 0 && is_valid_color(argv[2])) {
+ cairo_set_source_u32(window->cairo, parse_color(argv[2]));
+ cairo_paint(window->cairo);
+ window_render(window);
+ } else {
#ifdef WITH_GDK_PIXBUF
- GError *err = NULL;
- GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file(argv[2], &err);
- if (!pixbuf) {
- sway_abort("Failed to load background image.");
- }
- cairo_surface_t *image = gdk_cairo_image_surface_create_from_pixbuf(pixbuf);
- g_object_unref(pixbuf);
+ GError *err = NULL;
+ GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file(argv[2], &err);
+ if (!pixbuf) {
+ sway_abort("Failed to load background image.");
+ }
+ cairo_surface_t *image = gdk_cairo_image_surface_create_from_pixbuf(pixbuf);
+ g_object_unref(pixbuf);
#else
- cairo_surface_t *image = cairo_image_surface_create_from_png(argv[2]);
+ cairo_surface_t *image = cairo_image_surface_create_from_png(argv[2]);
#endif //WITH_GDK_PIXBUF
- if (!image) {
- sway_abort("Failed to read background image.");
- }
- double width = cairo_image_surface_get_width(image);
- double height = cairo_image_surface_get_height(image);
-
- const char *scaling_mode_str = argv[3];
- enum scaling_mode scaling_mode = SCALING_MODE_STRETCH;
- if (strcmp(scaling_mode_str, "stretch") == 0) {
- scaling_mode = SCALING_MODE_STRETCH;
- } else if (strcmp(scaling_mode_str, "fill") == 0) {
- scaling_mode = SCALING_MODE_FILL;
- } else if (strcmp(scaling_mode_str, "fit") == 0) {
- scaling_mode = SCALING_MODE_FIT;
- } else if (strcmp(scaling_mode_str, "center") == 0) {
- scaling_mode = SCALING_MODE_CENTER;
- } else if (strcmp(scaling_mode_str, "tile") == 0) {
- scaling_mode = SCALING_MODE_TILE;
- } else {
- sway_abort("Unsupported scaling mode: %s", scaling_mode_str);
- }
+ if (!image) {
+ sway_abort("Failed to read background image.");
+ }
+ double width = cairo_image_surface_get_width(image);
+ double height = cairo_image_surface_get_height(image);
+
+ const char *scaling_mode_str = argv[3];
+ enum scaling_mode scaling_mode = SCALING_MODE_STRETCH;
+ if (strcmp(scaling_mode_str, "stretch") == 0) {
+ scaling_mode = SCALING_MODE_STRETCH;
+ } else if (strcmp(scaling_mode_str, "fill") == 0) {
+ scaling_mode = SCALING_MODE_FILL;
+ } else if (strcmp(scaling_mode_str, "fit") == 0) {
+ scaling_mode = SCALING_MODE_FIT;
+ } else if (strcmp(scaling_mode_str, "center") == 0) {
+ scaling_mode = SCALING_MODE_CENTER;
+ } else if (strcmp(scaling_mode_str, "tile") == 0) {
+ scaling_mode = SCALING_MODE_TILE;
+ } else {
+ sway_abort("Unsupported scaling mode: %s", scaling_mode_str);
+ }
- for (i = 0; i < surfaces->length; ++i) {
- struct window *window = surfaces->items[i];
- if (window_prerender(window) && window->cairo) {
- switch (scaling_mode) {
- case SCALING_MODE_STRETCH:
- cairo_scale(window->cairo,
- (double) window->width / width,
- (double) window->height / height);
- cairo_set_source_surface(window->cairo, image, 0, 0);
- break;
- case SCALING_MODE_FILL:
- {
- double window_ratio = (double) window->width / window->height;
- double bg_ratio = width / height;
-
- if (window_ratio > bg_ratio) {
- double scale = (double) window->width / width;
- cairo_scale(window->cairo, scale, scale);
- cairo_set_source_surface(window->cairo, image,
- 0,
- (double) window->height/2 / scale - height/2);
- } else {
- double scale = (double) window->height / height;
- cairo_scale(window->cairo, scale, scale);
- cairo_set_source_surface(window->cairo, image,
- (double) window->width/2 / scale - width/2,
- 0);
+ for (i = 0; i < surfaces->length; ++i) {
+ struct window *window = surfaces->items[i];
+ if (window_prerender(window) && window->cairo) {
+ switch (scaling_mode) {
+ case SCALING_MODE_STRETCH:
+ cairo_scale(window->cairo,
+ (double) window->width / width,
+ (double) window->height / height);
+ cairo_set_source_surface(window->cairo, image, 0, 0);
+ break;
+ case SCALING_MODE_FILL:
+ {
+ double window_ratio = (double) window->width / window->height;
+ double bg_ratio = width / height;
+
+ if (window_ratio > bg_ratio) {
+ double scale = (double) window->width / width;
+ cairo_scale(window->cairo, scale, scale);
+ cairo_set_source_surface(window->cairo, image,
+ 0,
+ (double) window->height/2 / scale - height/2);
+ } else {
+ double scale = (double) window->height / height;
+ cairo_scale(window->cairo, scale, scale);
+ cairo_set_source_surface(window->cairo, image,
+ (double) window->width/2 / scale - width/2,
+ 0);
+ }
+ break;
}
- break;
- }
- case SCALING_MODE_FIT:
- {
- double window_ratio = (double) window->width / window->height;
- double bg_ratio = width / height;
-
- if (window_ratio > bg_ratio) {
- double scale = (double) window->height / height;
- cairo_scale(window->cairo, scale, scale);
- cairo_set_source_surface(window->cairo, image,
- (double) window->width/2 / scale - width/2,
- 0);
- } else {
- double scale = (double) window->width / width;
- cairo_scale(window->cairo, scale, scale);
+ case SCALING_MODE_FIT:
+ {
+ double window_ratio = (double) window->width / window->height;
+ double bg_ratio = width / height;
+
+ if (window_ratio > bg_ratio) {
+ double scale = (double) window->height / height;
+ cairo_scale(window->cairo, scale, scale);
+ cairo_set_source_surface(window->cairo, image,
+ (double) window->width/2 / scale - width/2,
+ 0);
+ } else {
+ double scale = (double) window->width / width;
+ cairo_scale(window->cairo, scale, scale);
+ cairo_set_source_surface(window->cairo, image,
+ 0,
+ (double) window->height/2 / scale - height/2);
+ }
+ break;
+ }
+ case SCALING_MODE_CENTER:
cairo_set_source_surface(window->cairo, image,
- 0,
- (double) window->height/2 / scale - height/2);
+ (double) window->width/2 - width/2,
+ (double) window->height/2 - height/2);
+ break;
+ case SCALING_MODE_TILE:
+ {
+ cairo_pattern_t *pattern = cairo_pattern_create_for_surface(image);
+ cairo_pattern_set_extend(pattern, CAIRO_EXTEND_REPEAT);
+ cairo_set_source(window->cairo, pattern);
+ break;
+ }
+ default:
+ sway_abort("Scaling mode '%s' not implemented yet!", scaling_mode_str);
}
- break;
- }
- case SCALING_MODE_CENTER:
- cairo_set_source_surface(window->cairo, image,
- (double) window->width/2 - width/2,
- (double) window->height/2 - height/2);
- break;
- case SCALING_MODE_TILE:
- {
- cairo_pattern_t *pattern = cairo_pattern_create_for_surface(image);
- cairo_pattern_set_extend(pattern, CAIRO_EXTEND_REPEAT);
- cairo_set_source(window->cairo, pattern);
- break;
- }
- default:
- sway_abort("Scaling mode '%s' not implemented yet!", scaling_mode_str);
- }
- cairo_paint(window->cairo);
+ cairo_paint(window->cairo);
- window_render(window);
+ window_render(window);
+ }
}
- }
- cairo_surface_destroy(image);
+ cairo_surface_destroy(image);
+ }
while (wl_display_dispatch(registry->display) != -1);