aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar Drew DeVault <sir@cmpwn.com>2016-07-30 23:28:02 -0400
committerLibravatar GitHub <noreply@github.com>2016-07-30 23:28:02 -0400
commit44a4905466599155fb7203a585dfca1ce1720b33 (patch)
treea7acb9aab8520040d49be04184d70984a66b95e7
parentMerge pull request #803 from zandrmartin/x11-pids (diff)
parentimplement solid color rendering for swaybg (diff)
downloadsway-44a4905466599155fb7203a585dfca1ce1720b33.tar.gz
sway-44a4905466599155fb7203a585dfca1ce1720b33.tar.zst
sway-44a4905466599155fb7203a585dfca1ce1720b33.zip
Merge pull request #805 from zandrmartin/swaybg-solid-color0.9-rc3
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
12 stringop.c 12 stringop.c
13 ) 13 )
14 14
15target_link_libraries(sway-common m)
16
15if(Backtrace_FOUND) 17if(Backtrace_FOUND)
16 set_target_properties(sway-common 18 set_target_properties(sway-common
17 PROPERTIES 19 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) {
97 97
98 return -1; 98 return -1;
99} 99}
100
101uint32_t parse_color(const char *color) {
102 int len = strlen(color);
103 if (color[0] != '#' || (len != 7 && len != 9)) {
104 sway_log(L_DEBUG, "Invalid color %s, defaulting to color 0xFFFFFFFF", color);
105 return 0xFFFFFFFF;
106 }
107 uint32_t res = (uint32_t)strtol(color + 1, NULL, 16);
108 if (strlen(color) == 7) {
109 res = (res << 8) | 0xFF;
110 }
111 return res;
112}
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 @@
5#include <stdbool.h> 5#include <stdbool.h>
6 6
7#include "list.h" 7#include "list.h"
8#include "util.h"
8 9
9/** 10/**
10 * Colors for a box with background, border and text colors. 11 * Colors for a box with background, border and text colors.
@@ -48,11 +49,6 @@ struct config {
48}; 49};
49 50
50/** 51/**
51 * Parse colors defined as hex string to uint32_t.
52 */
53uint32_t parse_color(const char *color);
54
55/**
56 * Parse position top|bottom|left|right. 52 * Parse position top|bottom|left|right.
57 */ 53 */
58uint32_t parse_position(const char *position); 54uint32_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 {
81 int enabled; 81 int enabled;
82 int width, height; 82 int width, height;
83 int x, y; 83 int x, y;
84 int scale; 84 int scale;
85 char *background; 85 char *background;
86 char *background_option; 86 char *background_option;
87}; 87};
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);
44 */ 44 */
45pid_t get_parent_pid(pid_t pid); 45pid_t get_parent_pid(pid_t pid);
46 46
47/**
48 * Given a string that represents an RGB(A) color, return a uint32_t
49 * version of the color.
50 */
51uint32_t parse_color(const char *color);
52
47#endif 53#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) {
1651 } else if (strcasecmp(command, "background") == 0 || strcasecmp(command, "bg") == 0) { 1651 } else if (strcasecmp(command, "background") == 0 || strcasecmp(command, "bg") == 0) {
1652 wordexp_t p; 1652 wordexp_t p;
1653 if (++i >= argc) { 1653 if (++i >= argc) {
1654 return cmd_results_new(CMD_INVALID, "output", "Missing background file."); 1654 return cmd_results_new(CMD_INVALID, "output", "Missing background file or color specification.");
1655 } 1655 }
1656 if (i + 1 >= argc) { 1656 if (i + 1 >= argc) {
1657 return cmd_results_new(CMD_INVALID, "output", "Missing background scaling mode."); 1657 return cmd_results_new(CMD_INVALID, "output", "Missing background scaling mode or `solid_color`.");
1658 } 1658 }
1659 char *src = join_args(argv + i, argc - i - 1); 1659 if (strcasecmp(argv[argc - 1], "solid_color") == 0) {
1660 char *mode = argv[argc - 1]; 1660 output->background = strdup(argv[argc - 2]);
1661 if (wordexp(src, &p, 0) != 0 || p.we_wordv[0] == NULL) { 1661 output->background_option = strdup("solid_color");
1662 return cmd_results_new(CMD_INVALID, "output", "Invalid syntax (%s)", src); 1662 } else {
1663 } 1663 char *src = join_args(argv + i, argc - i - 1);
1664 free(src); 1664 char *mode = argv[argc - 1];
1665 src = p.we_wordv[0]; 1665 if (wordexp(src, &p, 0) != 0 || p.we_wordv[0] == NULL) {
1666 if (config->reading && *src != '/') { 1666 return cmd_results_new(CMD_INVALID, "output", "Invalid syntax (%s)", src);
1667 char *conf = strdup(config->current_config);
1668 char *conf_path = dirname(conf);
1669 src = malloc(strlen(conf_path) + strlen(src) + 2);
1670 sprintf(src, "%s/%s", conf_path, p.we_wordv[0]);
1671 free(conf);
1672 }
1673 if (access(src, F_OK) == -1) {
1674 return cmd_results_new(CMD_INVALID, "output", "Background file unreadable (%s)", src);
1675 }
1676 for (char *m = mode; *m; ++m) *m = tolower(*m);
1677 // Check mode
1678 bool valid = false;
1679 size_t j;
1680 for (j = 0; j < sizeof(bg_options) / sizeof(char *); ++j) {
1681 if (strcasecmp(mode, bg_options[j]) == 0) {
1682 valid = true;
1683 break;
1684 } 1667 }
1685 }
1686 if (!valid) {
1687 return cmd_results_new(CMD_INVALID, "output", "Invalid background scaling mode.");
1688 }
1689 output->background = strdup(src);
1690 output->background_option = strdup(mode);
1691 if (src != p.we_wordv[0]) {
1692 free(src); 1668 free(src);
1669 src = p.we_wordv[0];
1670 if (config->reading && *src != '/') {
1671 char *conf = strdup(config->current_config);
1672 char *conf_path = dirname(conf);
1673 src = malloc(strlen(conf_path) + strlen(src) + 2);
1674 sprintf(src, "%s/%s", conf_path, p.we_wordv[0]);
1675 free(conf);
1676 }
1677 if (access(src, F_OK) == -1) {
1678 return cmd_results_new(CMD_INVALID, "output", "Background file unreadable (%s)", src);
1679 }
1680 for (char *m = mode; *m; ++m) *m = tolower(*m);
1681 // Check mode
1682 bool valid = false;
1683 size_t j;
1684 for (j = 0; j < sizeof(bg_options) / sizeof(char *); ++j) {
1685 if (strcasecmp(mode, bg_options[j]) == 0) {
1686 valid = true;
1687 break;
1688 }
1689 }
1690 if (!valid) {
1691 return cmd_results_new(CMD_INVALID, "output", "Invalid background scaling mode.");
1692 }
1693 output->background = strdup(src);
1694 output->background_option = strdup(mode);
1695 if (src != p.we_wordv[0]) {
1696 free(src);
1697 }
1698 wordfree(&p);
1693 } 1699 }
1694 wordfree(&p);
1695 } 1700 }
1696 } 1701 }
1697 1702
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:
308 Sets the wallpaper for the given output to the specified file, using the given 308 Sets the wallpaper for the given output to the specified file, using the given
309 scaling mode (one of "stretch", "fill", "fit", "center", "tile"). 309 scaling mode (one of "stretch", "fill", "fit", "center", "tile").
310 310
311**output** <name> <background|bg> <color> solid_color::
312 Sets the background of the given output to the specified color. _color_ should
313 be specified as an _#rrggbb_ (no alpha) color.
314
311**output** <name> disable:: 315**output** <name> disable::
312 Disables the specified output. 316 Disables the specified output.
313 317
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 @@
5#include "log.h" 5#include "log.h"
6#include "bar/config.h" 6#include "bar/config.h"
7 7
8uint32_t parse_color(const char *color) {
9 if (color[0] != '#') {
10 sway_log(L_DEBUG, "Invalid color %s, defaulting to color 0xFFFFFFFF", color);
11 return 0xFFFFFFFF;
12 }
13 char *end;
14 uint32_t res = (uint32_t)strtol(color + 1, &end, 16);
15 if (strlen(color) == 7) {
16 res = (res << 8) | 0xFF;
17 }
18 return res;
19}
20
21uint32_t parse_position(const char *position) { 8uint32_t parse_position(const char *position) {
22 if (strcmp("top", position) == 0) { 9 if (strcmp("top", position) == 0) {
23 return DESKTOP_SHELL_PANEL_POSITION_TOP; 10 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 @@
6#include "log.h" 6#include "log.h"
7#include "bar/config.h" 7#include "bar/config.h"
8#include "bar/status_line.h" 8#include "bar/status_line.h"
9#include "util.h"
9 10
10#define I3JSON_MAXDEPTH 4 11#define I3JSON_MAXDEPTH 4
11#define I3JSON_UNKNOWN 0 12#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 @@
1#include "wayland-desktop-shell-client-protocol.h" 1#include "wayland-desktop-shell-client-protocol.h"
2#include <stdbool.h>
2#include <stdio.h> 3#include <stdio.h>
3#include <stdlib.h> 4#include <stdlib.h>
5#include <ctype.h>
4#include <wayland-client.h> 6#include <wayland-client.h>
5#include <time.h> 7#include <time.h>
6#include <string.h> 8#include <string.h>
@@ -9,6 +11,7 @@
9#include "client/cairo.h" 11#include "client/cairo.h"
10#include "log.h" 12#include "log.h"
11#include "list.h" 13#include "list.h"
14#include "util.h"
12 15
13list_t *surfaces; 16list_t *surfaces;
14struct registry *registry; 17struct registry *registry;
@@ -32,6 +35,23 @@ void sway_terminate(int exit_code) {
32 exit(exit_code); 35 exit(exit_code);
33} 36}
34 37
38bool is_valid_color(const char *color) {
39 int len = strlen(color);
40 if (len != 7 || color[0] != '#') {
41 sway_log(L_ERROR, "%s is not a valid color for swaybg. Color should be specified as #rrggbb (no alpha).", color);
42 return false;
43 }
44
45 int i;
46 for (i = 1; i < len; ++i) {
47 if (!isxdigit(color[i])) {
48 return false;
49 }
50 }
51
52 return true;
53}
54
35int main(int argc, const char **argv) { 55int main(int argc, const char **argv) {
36 init_log(L_INFO); 56 init_log(L_INFO);
37 surfaces = create_list(); 57 surfaces = create_list();
@@ -57,112 +77,118 @@ int main(int argc, const char **argv) {
57 window_make_shell(window); 77 window_make_shell(window);
58 list_add(surfaces, window); 78 list_add(surfaces, window);
59 79
80 if (strcmp(argv[3], "solid_color") == 0 && is_valid_color(argv[2])) {
81 cairo_set_source_u32(window->cairo, parse_color(argv[2]));
82 cairo_paint(window->cairo);
83 window_render(window);
84 } else {
60#ifdef WITH_GDK_PIXBUF 85#ifdef WITH_GDK_PIXBUF
61 GError *err = NULL; 86 GError *err = NULL;
62 GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file(argv[2], &err); 87 GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file(argv[2], &err);
63 if (!pixbuf) { 88 if (!pixbuf) {
64 sway_abort("Failed to load background image."); 89 sway_abort("Failed to load background image.");
65 } 90 }
66 cairo_surface_t *image = gdk_cairo_image_surface_create_from_pixbuf(pixbuf); 91 cairo_surface_t *image = gdk_cairo_image_surface_create_from_pixbuf(pixbuf);
67 g_object_unref(pixbuf); 92 g_object_unref(pixbuf);
68#else 93#else
69 cairo_surface_t *image = cairo_image_surface_create_from_png(argv[2]); 94 cairo_surface_t *image = cairo_image_surface_create_from_png(argv[2]);
70#endif //WITH_GDK_PIXBUF 95#endif //WITH_GDK_PIXBUF
71 if (!image) { 96 if (!image) {
72 sway_abort("Failed to read background image."); 97 sway_abort("Failed to read background image.");
73 } 98 }
74 double width = cairo_image_surface_get_width(image); 99 double width = cairo_image_surface_get_width(image);
75 double height = cairo_image_surface_get_height(image); 100 double height = cairo_image_surface_get_height(image);
76 101
77 const char *scaling_mode_str = argv[3]; 102 const char *scaling_mode_str = argv[3];
78 enum scaling_mode scaling_mode = SCALING_MODE_STRETCH; 103 enum scaling_mode scaling_mode = SCALING_MODE_STRETCH;
79 if (strcmp(scaling_mode_str, "stretch") == 0) { 104 if (strcmp(scaling_mode_str, "stretch") == 0) {
80 scaling_mode = SCALING_MODE_STRETCH; 105 scaling_mode = SCALING_MODE_STRETCH;
81 } else if (strcmp(scaling_mode_str, "fill") == 0) { 106 } else if (strcmp(scaling_mode_str, "fill") == 0) {
82 scaling_mode = SCALING_MODE_FILL; 107 scaling_mode = SCALING_MODE_FILL;
83 } else if (strcmp(scaling_mode_str, "fit") == 0) { 108 } else if (strcmp(scaling_mode_str, "fit") == 0) {
84 scaling_mode = SCALING_MODE_FIT; 109 scaling_mode = SCALING_MODE_FIT;
85 } else if (strcmp(scaling_mode_str, "center") == 0) { 110 } else if (strcmp(scaling_mode_str, "center") == 0) {
86 scaling_mode = SCALING_MODE_CENTER; 111 scaling_mode = SCALING_MODE_CENTER;
87 } else if (strcmp(scaling_mode_str, "tile") == 0) { 112 } else if (strcmp(scaling_mode_str, "tile") == 0) {
88 scaling_mode = SCALING_MODE_TILE; 113 scaling_mode = SCALING_MODE_TILE;
89 } else { 114 } else {
90 sway_abort("Unsupported scaling mode: %s", scaling_mode_str); 115 sway_abort("Unsupported scaling mode: %s", scaling_mode_str);
91 } 116 }
92 117
93 for (i = 0; i < surfaces->length; ++i) { 118 for (i = 0; i < surfaces->length; ++i) {
94 struct window *window = surfaces->items[i]; 119 struct window *window = surfaces->items[i];
95 if (window_prerender(window) && window->cairo) { 120 if (window_prerender(window) && window->cairo) {
96 switch (scaling_mode) { 121 switch (scaling_mode) {
97 case SCALING_MODE_STRETCH: 122 case SCALING_MODE_STRETCH:
98 cairo_scale(window->cairo, 123 cairo_scale(window->cairo,
99 (double) window->width / width, 124 (double) window->width / width,
100 (double) window->height / height); 125 (double) window->height / height);
101 cairo_set_source_surface(window->cairo, image, 0, 0); 126 cairo_set_source_surface(window->cairo, image, 0, 0);
102 break; 127 break;
103 case SCALING_MODE_FILL: 128 case SCALING_MODE_FILL:
104 { 129 {
105 double window_ratio = (double) window->width / window->height; 130 double window_ratio = (double) window->width / window->height;
106 double bg_ratio = width / height; 131 double bg_ratio = width / height;
107 132
108 if (window_ratio > bg_ratio) { 133 if (window_ratio > bg_ratio) {
109 double scale = (double) window->width / width; 134 double scale = (double) window->width / width;
110 cairo_scale(window->cairo, scale, scale); 135 cairo_scale(window->cairo, scale, scale);
111 cairo_set_source_surface(window->cairo, image, 136 cairo_set_source_surface(window->cairo, image,
112 0, 137 0,
113 (double) window->height/2 / scale - height/2); 138 (double) window->height/2 / scale - height/2);
114 } else { 139 } else {
115 double scale = (double) window->height / height; 140 double scale = (double) window->height / height;
116 cairo_scale(window->cairo, scale, scale); 141 cairo_scale(window->cairo, scale, scale);
117 cairo_set_source_surface(window->cairo, image, 142 cairo_set_source_surface(window->cairo, image,
118 (double) window->width/2 / scale - width/2, 143 (double) window->width/2 / scale - width/2,
119 0); 144 0);
145 }
146 break;
120 } 147 }
121 break; 148 case SCALING_MODE_FIT:
122 } 149 {
123 case SCALING_MODE_FIT: 150 double window_ratio = (double) window->width / window->height;
124 { 151 double bg_ratio = width / height;
125 double window_ratio = (double) window->width / window->height; 152
126 double bg_ratio = width / height; 153 if (window_ratio > bg_ratio) {
127 154 double scale = (double) window->height / height;
128 if (window_ratio > bg_ratio) { 155 cairo_scale(window->cairo, scale, scale);
129 double scale = (double) window->height / height; 156 cairo_set_source_surface(window->cairo, image,
130 cairo_scale(window->cairo, scale, scale); 157 (double) window->width/2 / scale - width/2,
131 cairo_set_source_surface(window->cairo, image, 158 0);
132 (double) window->width/2 / scale - width/2, 159 } else {
133 0); 160 double scale = (double) window->width / width;
134 } else { 161 cairo_scale(window->cairo, scale, scale);
135 double scale = (double) window->width / width; 162 cairo_set_source_surface(window->cairo, image,
136 cairo_scale(window->cairo, scale, scale); 163 0,
164 (double) window->height/2 / scale - height/2);
165 }
166 break;
167 }
168 case SCALING_MODE_CENTER:
137 cairo_set_source_surface(window->cairo, image, 169 cairo_set_source_surface(window->cairo, image,
138 0, 170 (double) window->width/2 - width/2,
139 (double) window->height/2 / scale - height/2); 171 (double) window->height/2 - height/2);
172 break;
173 case SCALING_MODE_TILE:
174 {
175 cairo_pattern_t *pattern = cairo_pattern_create_for_surface(image);
176 cairo_pattern_set_extend(pattern, CAIRO_EXTEND_REPEAT);
177 cairo_set_source(window->cairo, pattern);
178 break;
179 }
180 default:
181 sway_abort("Scaling mode '%s' not implemented yet!", scaling_mode_str);
140 } 182 }
141 break;
142 }
143 case SCALING_MODE_CENTER:
144 cairo_set_source_surface(window->cairo, image,
145 (double) window->width/2 - width/2,
146 (double) window->height/2 - height/2);
147 break;
148 case SCALING_MODE_TILE:
149 {
150 cairo_pattern_t *pattern = cairo_pattern_create_for_surface(image);
151 cairo_pattern_set_extend(pattern, CAIRO_EXTEND_REPEAT);
152 cairo_set_source(window->cairo, pattern);
153 break;
154 }
155 default:
156 sway_abort("Scaling mode '%s' not implemented yet!", scaling_mode_str);
157 }
158 183
159 cairo_paint(window->cairo); 184 cairo_paint(window->cairo);
160 185
161 window_render(window); 186 window_render(window);
187 }
162 } 188 }
163 }
164 189
165 cairo_surface_destroy(image); 190 cairo_surface_destroy(image);
191 }
166 192
167 while (wl_display_dispatch(registry->display) != -1); 193 while (wl_display_dispatch(registry->display) != -1);
168 194