aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar Brian Ashworth <bosrsf04@gmail.com>2019-12-27 23:33:55 -0500
committerLibravatar Simon Ser <contact@emersion.fr>2019-12-28 10:07:25 +0100
commit97f9f0b699316ba60009b395948a712ec0b671d2 (patch)
treeb5916b36f4161c1c4d670295254d0f3fd9e793df
parentlayer-shell: refocus if keyboard interactive lost (diff)
downloadsway-97f9f0b699316ba60009b395948a712ec0b671d2.tar.gz
sway-97f9f0b699316ba60009b395948a712ec0b671d2.tar.zst
sway-97f9f0b699316ba60009b395948a712ec0b671d2.zip
parse_color: return success + drop fallback color
This is the first in a series of commits to refactor the color handling in sway. This changes parse_color to return whether it was success and no longer uses 0xFFFFFFFF as the fallback color. This also verifies that the string actually contains a valid hexadecimal number along with the length checks. In the process of altering the calls to parse_color, I also took the opportunity to heavily refactor swaybar's ipc_parse_colors function. This allowed for several lines of duplicated code to be removed.
-rw-r--r--common/util.c19
-rw-r--r--include/swaybar/i3bar.h3
-rw-r--r--include/util.h7
-rw-r--r--swaybar/i3bar.c20
-rw-r--r--swaybar/ipc.c147
-rw-r--r--swaybar/render.c2
-rw-r--r--swaynag/config.c20
7 files changed, 76 insertions, 142 deletions
diff --git a/common/util.c b/common/util.c
index c0324b2f..84ebab99 100644
--- a/common/util.c
+++ b/common/util.c
@@ -1,4 +1,5 @@
1#define _POSIX_C_SOURCE 200809L 1#define _POSIX_C_SOURCE 200809L
2#include <ctype.h>
2#include <float.h> 3#include <float.h>
3#include <fcntl.h> 4#include <fcntl.h>
4#include <math.h> 5#include <math.h>
@@ -13,21 +14,21 @@ int wrap(int i, int max) {
13 return ((i % max) + max) % max; 14 return ((i % max) + max) % max;
14} 15}
15 16
16uint32_t parse_color(const char *color) { 17bool parse_color(const char *color, uint32_t *result) {
17 if (color[0] == '#') { 18 if (color[0] == '#') {
18 ++color; 19 ++color;
19 } 20 }
20
21 int len = strlen(color); 21 int len = strlen(color);
22 if (len != 6 && len != 8) { 22 if ((len != 6 && len != 8) || !isxdigit(color[0]) || !isxdigit(color[1])) {
23 sway_log(SWAY_DEBUG, "Invalid color %s, defaulting to color 0xFFFFFFFF", color); 23 return false;
24 return 0xFFFFFFFF;
25 } 24 }
26 uint32_t res = (uint32_t)strtoul(color, NULL, 16); 25 char *ptr;
27 if (strlen(color) == 6) { 26 uint32_t parsed = strtoul(color, &ptr, 16);
28 res = (res << 8) | 0xFF; 27 if (*ptr != '\0') {
28 return false;
29 } 29 }
30 return res; 30 *result = len == 6 ? ((parsed << 8) | 0xFF) : parsed;
31 return true;
31} 32}
32 33
33bool parse_boolean(const char *boolean, bool current) { 34bool parse_boolean(const char *boolean, bool current) {
diff --git a/include/swaybar/i3bar.h b/include/swaybar/i3bar.h
index 5b6001ce..0b3bee21 100644
--- a/include/swaybar/i3bar.h
+++ b/include/swaybar/i3bar.h
@@ -9,7 +9,8 @@ struct i3bar_block {
9 int ref_count; 9 int ref_count;
10 char *full_text, *short_text, *align, *min_width_str; 10 char *full_text, *short_text, *align, *min_width_str;
11 bool urgent; 11 bool urgent;
12 uint32_t *color; 12 uint32_t color;
13 bool color_set;
13 int min_width; 14 int min_width;
14 char *name, *instance; 15 char *name, *instance;
15 bool separator; 16 bool separator;
diff --git a/include/util.h b/include/util.h
index 3cba49f0..931ac691 100644
--- a/include/util.h
+++ b/include/util.h
@@ -11,10 +11,11 @@
11int wrap(int i, int max); 11int wrap(int i, int max);
12 12
13/** 13/**
14 * Given a string that represents an RGB(A) color, return a uint32_t 14 * Given a string that represents an RGB(A) color, result will be set to a
15 * version of the color. 15 * uint32_t version of the color, as long as it is valid. If it is invalid,
16 * then false will be returned and result will be untouched.
16 */ 17 */
17uint32_t parse_color(const char *color); 18bool parse_color(const char *color, uint32_t *result);
18 19
19/** 20/**
20 * Given a string that represents a boolean, return the boolean value. This 21 * Given a string that represents a boolean, return the boolean value. This
diff --git a/swaybar/i3bar.c b/swaybar/i3bar.c
index 43e2fe2d..5c8b87a2 100644
--- a/swaybar/i3bar.c
+++ b/swaybar/i3bar.c
@@ -24,7 +24,6 @@ void i3bar_block_unref(struct i3bar_block *block) {
24 free(block->min_width_str); 24 free(block->min_width_str);
25 free(block->name); 25 free(block->name);
26 free(block->instance); 26 free(block->instance);
27 free(block->color);
28 free(block); 27 free(block);
29 } 28 }
30} 29}
@@ -70,8 +69,11 @@ static void i3bar_parse_json(struct status_line *status,
70 block->short_text = short_text ? 69 block->short_text = short_text ?
71 strdup(json_object_get_string(short_text)) : NULL; 70 strdup(json_object_get_string(short_text)) : NULL;
72 if (color) { 71 if (color) {
73 block->color = malloc(sizeof(uint32_t)); 72 const char *hexstring = json_object_get_string(color);
74 *block->color = parse_color(json_object_get_string(color)); 73 block->color_set = parse_color(hexstring, &block->color);
74 if (!block->color_set) {
75 sway_log(SWAY_ERROR, "Invalid block color: %s", hexstring);
76 }
75 } 77 }
76 if (min_width) { 78 if (min_width) {
77 json_type type = json_object_get_type(min_width); 79 json_type type = json_object_get_type(min_width);
@@ -98,10 +100,14 @@ static void i3bar_parse_json(struct status_line *status,
98 block->separator_block_width = separator_block_width ? 100 block->separator_block_width = separator_block_width ?
99 json_object_get_int(separator_block_width) : 9; 101 json_object_get_int(separator_block_width) : 9;
100 // Airblader features 102 // Airblader features
101 block->background = background ? 103 const char *hex = background ? json_object_get_string(background) : NULL;
102 parse_color(json_object_get_string(background)) : 0; 104 if (hex && !parse_color(hex, &block->background)) {
103 block->border = border ? 105 sway_log(SWAY_ERROR, "Ignoring invalid block background: %s", hex);
104 parse_color(json_object_get_string(border)) : 0; 106 }
107 hex = border ? json_object_get_string(border) : NULL;
108 if (hex && !parse_color(hex, &block->border)) {
109 sway_log(SWAY_ERROR, "Ignoring invalid block border: %s", hex);
110 }
105 block->border_top = border_top ? json_object_get_int(border_top) : 1; 111 block->border_top = border_top ? json_object_get_int(border_top) : 1;
106 block->border_bottom = border_bottom ? 112 block->border_bottom = border_bottom ?
107 json_object_get_int(border_bottom) : 1; 113 json_object_get_int(border_bottom) : 1;
diff --git a/swaybar/ipc.c b/swaybar/ipc.c
index afaffb04..cca510c6 100644
--- a/swaybar/ipc.c
+++ b/swaybar/ipc.c
@@ -55,117 +55,42 @@ char *parse_font(const char *font) {
55 55
56static void ipc_parse_colors( 56static void ipc_parse_colors(
57 struct swaybar_config *config, json_object *colors) { 57 struct swaybar_config *config, json_object *colors) {
58 json_object *background, *statusline, *separator; 58 struct {
59 json_object *focused_background, *focused_statusline, *focused_separator; 59 const char *name;
60 json_object *focused_workspace_border, *focused_workspace_bg, *focused_workspace_text; 60 uint32_t *color;
61 json_object *inactive_workspace_border, *inactive_workspace_bg, *inactive_workspace_text; 61 } properties[] = {
62 json_object *active_workspace_border, *active_workspace_bg, *active_workspace_text; 62 { "background", &config->colors.background },
63 json_object *urgent_workspace_border, *urgent_workspace_bg, *urgent_workspace_text; 63 { "statusline", &config->colors.statusline },
64 json_object *binding_mode_border, *binding_mode_bg, *binding_mode_text; 64 { "separator", &config->colors.separator },
65 json_object_object_get_ex(colors, "background", &background); 65 { "focused_background", &config->colors.focused_background },
66 json_object_object_get_ex(colors, "statusline", &statusline); 66 { "focused_statusline", &config->colors.focused_statusline },
67 json_object_object_get_ex(colors, "separator", &separator); 67 { "focused_separator", &config->colors.focused_separator },
68 json_object_object_get_ex(colors, "focused_background", &focused_background); 68 { "focused_workspace_border", &config->colors.focused_workspace.border },
69 json_object_object_get_ex(colors, "focused_statusline", &focused_statusline); 69 { "focused_workspace_bg", &config->colors.focused_workspace.background },
70 json_object_object_get_ex(colors, "focused_separator", &focused_separator); 70 { "focused_workspace_text", &config->colors.focused_workspace.text },
71 json_object_object_get_ex(colors, "focused_workspace_border", &focused_workspace_border); 71 { "active_workspace_border", &config->colors.active_workspace.border },
72 json_object_object_get_ex(colors, "focused_workspace_bg", &focused_workspace_bg); 72 { "active_workspace_bg", &config->colors.active_workspace.background },
73 json_object_object_get_ex(colors, "focused_workspace_text", &focused_workspace_text); 73 { "active_workspace_text", &config->colors.active_workspace.text },
74 json_object_object_get_ex(colors, "active_workspace_border", &active_workspace_border); 74 { "inactive_workspace_border", &config->colors.inactive_workspace.border },
75 json_object_object_get_ex(colors, "active_workspace_bg", &active_workspace_bg); 75 { "inactive_workspace_bg", &config->colors.inactive_workspace.background },
76 json_object_object_get_ex(colors, "active_workspace_text", &active_workspace_text); 76 { "inactive_workspace_text", &config->colors.inactive_workspace.text },
77 json_object_object_get_ex(colors, "inactive_workspace_border", &inactive_workspace_border); 77 { "urgent_workspace_border", &config->colors.urgent_workspace.border },
78 json_object_object_get_ex(colors, "inactive_workspace_bg", &inactive_workspace_bg); 78 { "urgent_workspace_bg", &config->colors.urgent_workspace.background },
79 json_object_object_get_ex(colors, "inactive_workspace_text", &inactive_workspace_text); 79 { "urgent_workspace_text", &config->colors.urgent_workspace.text },
80 json_object_object_get_ex(colors, "urgent_workspace_border", &urgent_workspace_border); 80 { "binding_mode_border", &config->colors.binding_mode.border },
81 json_object_object_get_ex(colors, "urgent_workspace_bg", &urgent_workspace_bg); 81 { "binding_mode_bg", &config->colors.binding_mode.background },
82 json_object_object_get_ex(colors, "urgent_workspace_text", &urgent_workspace_text); 82 { "binding_mode_text", &config->colors.binding_mode.text },
83 json_object_object_get_ex(colors, "binding_mode_border", &binding_mode_border); 83 };
84 json_object_object_get_ex(colors, "binding_mode_bg", &binding_mode_bg); 84
85 json_object_object_get_ex(colors, "binding_mode_text", &binding_mode_text); 85 for (size_t i = 0; i < sizeof(properties) / sizeof(properties[i]); i++) {
86 if (background) { 86 json_object *object;
87 config->colors.background = parse_color( 87 if (json_object_object_get_ex(colors, properties[i].name, &object)) {
88 json_object_get_string(background)); 88 const char *hexstring = json_object_get_string(object);
89 } 89 if (!parse_color(hexstring, properties[i].color)) {
90 if (statusline) { 90 sway_log(SWAY_ERROR, "Ignoring invalid %s: %s",
91 config->colors.statusline = parse_color( 91 properties[i].name, hexstring);
92 json_object_get_string(statusline)); 92 }
93 } 93 }
94 if (separator) {
95 config->colors.separator = parse_color(
96 json_object_get_string(separator));
97 }
98 if (focused_background) {
99 config->colors.focused_background = parse_color(
100 json_object_get_string(focused_background));
101 }
102 if (focused_statusline) {
103 config->colors.focused_statusline = parse_color(
104 json_object_get_string(focused_statusline));
105 }
106 if (focused_separator) {
107 config->colors.focused_separator = parse_color(
108 json_object_get_string(focused_separator));
109 }
110 if (focused_workspace_border) {
111 config->colors.focused_workspace.border = parse_color(
112 json_object_get_string(focused_workspace_border));
113 }
114 if (focused_workspace_bg) {
115 config->colors.focused_workspace.background = parse_color(
116 json_object_get_string(focused_workspace_bg));
117 }
118 if (focused_workspace_text) {
119 config->colors.focused_workspace.text = parse_color(
120 json_object_get_string(focused_workspace_text));
121 }
122 if (active_workspace_border) {
123 config->colors.active_workspace.border = parse_color(
124 json_object_get_string(active_workspace_border));
125 }
126 if (active_workspace_bg) {
127 config->colors.active_workspace.background = parse_color(
128 json_object_get_string(active_workspace_bg));
129 }
130 if (active_workspace_text) {
131 config->colors.active_workspace.text = parse_color(
132 json_object_get_string(active_workspace_text));
133 }
134 if (inactive_workspace_border) {
135 config->colors.inactive_workspace.border = parse_color(
136 json_object_get_string(inactive_workspace_border));
137 }
138 if (inactive_workspace_bg) {
139 config->colors.inactive_workspace.background = parse_color(
140 json_object_get_string(inactive_workspace_bg));
141 }
142 if (inactive_workspace_text) {
143 config->colors.inactive_workspace.text = parse_color(
144 json_object_get_string(inactive_workspace_text));
145 }
146 if (urgent_workspace_border) {
147 config->colors.urgent_workspace.border = parse_color(
148 json_object_get_string(urgent_workspace_border));
149 }
150 if (urgent_workspace_bg) {
151 config->colors.urgent_workspace.background = parse_color(
152 json_object_get_string(urgent_workspace_bg));
153 }
154 if (urgent_workspace_text) {
155 config->colors.urgent_workspace.text = parse_color(
156 json_object_get_string(urgent_workspace_text));
157 }
158 if (binding_mode_border) {
159 config->colors.binding_mode.border = parse_color(
160 json_object_get_string(binding_mode_border));
161 }
162 if (binding_mode_bg) {
163 config->colors.binding_mode.background = parse_color(
164 json_object_get_string(binding_mode_bg));
165 }
166 if (binding_mode_text) {
167 config->colors.binding_mode.text = parse_color(
168 json_object_get_string(binding_mode_text));
169 } 94 }
170} 95}
171 96
diff --git a/swaybar/render.c b/swaybar/render.c
index 0d6bb354..06efb53c 100644
--- a/swaybar/render.c
+++ b/swaybar/render.c
@@ -265,7 +265,7 @@ static uint32_t render_status_block(cairo_t *cairo,
265 } 265 }
266 double text_y = height / 2.0 - text_height / 2.0; 266 double text_y = height / 2.0 - text_height / 2.0;
267 cairo_move_to(cairo, offset, (int)floor(text_y)); 267 cairo_move_to(cairo, offset, (int)floor(text_y));
268 uint32_t color = block->color ? *block->color : config->colors.statusline; 268 uint32_t color = block->color_set ? block->color : config->colors.statusline;
269 color = block->urgent ? config->colors.urgent_workspace.text : color; 269 color = block->urgent ? config->colors.urgent_workspace.text : color;
270 cairo_set_source_u32(cairo, color); 270 cairo_set_source_u32(cairo, color);
271 pango_printf(cairo, config->font, output->scale, 271 pango_printf(cairo, config->font, output->scale,
diff --git a/swaynag/config.c b/swaynag/config.c
index 2fa7cb61..f1161b39 100644
--- a/swaynag/config.c
+++ b/swaynag/config.c
@@ -221,28 +221,28 @@ int swaynag_parse_options(int argc, char **argv, struct swaynag *swaynag,
221 fprintf(stdout, "swaynag version " SWAY_VERSION "\n"); 221 fprintf(stdout, "swaynag version " SWAY_VERSION "\n");
222 return -1; 222 return -1;
223 case TO_COLOR_BACKGROUND: // Background color 223 case TO_COLOR_BACKGROUND: // Background color
224 if (type) { 224 if (type && !parse_color(optarg, &type->background)) {
225 type->background = parse_color(optarg); 225 fprintf(stderr, "Invalid background color: %s", optarg);
226 } 226 }
227 break; 227 break;
228 case TO_COLOR_BORDER: // Border color 228 case TO_COLOR_BORDER: // Border color
229 if (type) { 229 if (type && !parse_color(optarg, &type->border)) {
230 type->border = parse_color(optarg); 230 fprintf(stderr, "Invalid border color: %s", optarg);
231 } 231 }
232 break; 232 break;
233 case TO_COLOR_BORDER_BOTTOM: // Bottom border color 233 case TO_COLOR_BORDER_BOTTOM: // Bottom border color
234 if (type) { 234 if (type && !parse_color(optarg, &type->border_bottom)) {
235 type->border_bottom = parse_color(optarg); 235 fprintf(stderr, "Invalid border bottom color: %s", optarg);
236 } 236 }
237 break; 237 break;
238 case TO_COLOR_BUTTON: // Button background color 238 case TO_COLOR_BUTTON: // Button background color
239 if (type) { 239 if (type && !parse_color(optarg, &type->button_background)) {
240 type->button_background = parse_color(optarg); 240 fprintf(stderr, "Invalid button background color: %s", optarg);
241 } 241 }
242 break; 242 break;
243 case TO_COLOR_TEXT: // Text color 243 case TO_COLOR_TEXT: // Text color
244 if (type) { 244 if (type && !parse_color(optarg, &type->text)) {
245 type->text = parse_color(optarg); 245 fprintf(stderr, "Invalid text color: %s", optarg);
246 } 246 }
247 break; 247 break;
248 case TO_THICK_BAR_BORDER: // Bottom border thickness 248 case TO_THICK_BAR_BORDER: // Bottom border thickness