aboutsummaryrefslogtreecommitdiffstats
path: root/swaynag
diff options
context:
space:
mode:
authorLibravatar Brian Ashworth <bosrsf04@gmail.com>2018-07-28 09:34:25 -0400
committerLibravatar Brian Ashworth <bosrsf04@gmail.com>2018-08-01 22:47:54 -0400
commit8463a2896a932cd99f3dc93608b03cb4aba93293 (patch)
treeb8c4ba994cf4d9ca7510d0f80a1864cce144092a /swaynag
parentAddress first round review for swaynag (diff)
downloadsway-8463a2896a932cd99f3dc93608b03cb4aba93293.tar.gz
sway-8463a2896a932cd99f3dc93608b03cb4aba93293.tar.zst
sway-8463a2896a932cd99f3dc93608b03cb4aba93293.zip
swaynag: implement config file support
Diffstat (limited to 'swaynag')
-rw-r--r--swaynag/main.c357
-rw-r--r--swaynag/meson.build1
-rw-r--r--swaynag/nagbar.c5
-rw-r--r--swaynag/render.c23
-rw-r--r--swaynag/swaynag.1.scd33
-rw-r--r--swaynag/swaynag.5.scd57
-rw-r--r--swaynag/types.c116
7 files changed, 470 insertions, 122 deletions
diff --git a/swaynag/main.c b/swaynag/main.c
index 60560c72..b199fac4 100644
--- a/swaynag/main.c
+++ b/swaynag/main.c
@@ -1,10 +1,14 @@
1#define _XOPEN_SOURCE 500 1#define _XOPEN_SOURCE 700
2#define _POSIX_C_SOURCE 200112L
2#include <getopt.h> 3#include <getopt.h>
3#include <signal.h> 4#include <signal.h>
5#include <stdlib.h>
6#include <wordexp.h>
4#include "log.h" 7#include "log.h"
5#include "list.h" 8#include "list.h"
6#include "readline.h" 9#include "readline.h"
7#include "swaynag/nagbar.h" 10#include "swaynag/nagbar.h"
11#include "swaynag/types.h"
8#include "wlr-layer-shell-unstable-v1-client-protocol.h" 12#include "wlr-layer-shell-unstable-v1-client-protocol.h"
9 13
10static struct sway_nagbar nagbar; 14static struct sway_nagbar nagbar;
@@ -19,22 +23,6 @@ void sway_terminate(int code) {
19 exit(code); 23 exit(code);
20} 24}
21 25
22static void set_nagbar_colors() {
23 if (nagbar.type == NAGBAR_ERROR) {
24 nagbar.colors.button_background = 0x680A0AFF;
25 nagbar.colors.background = 0x900000FF;
26 nagbar.colors.text = 0xFFFFFFFF;
27 nagbar.colors.border = 0xD92424FF;
28 nagbar.colors.border_bottom = 0x470909FF;
29 } else if (nagbar.type == NAGBAR_WARNING) {
30 nagbar.colors.button_background = 0xFFC100FF;
31 nagbar.colors.background = 0xFFA800FF;
32 nagbar.colors.text = 0x000000FF;
33 nagbar.colors.border = 0xAB7100FF;
34 nagbar.colors.border_bottom = 0xAB7100FF;
35 }
36}
37
38static char *read_from_stdin() { 26static char *read_from_stdin() {
39 char *buffer = NULL; 27 char *buffer = NULL;
40 while (!feof(stdin)) { 28 while (!feof(stdin)) {
@@ -61,32 +49,11 @@ static char *read_from_stdin() {
61 return buffer; 49 return buffer;
62} 50}
63 51
64int main(int argc, char **argv) { 52static int parse_options(int argc, char **argv, struct sway_nagbar *nagbar,
65 int exit_code = EXIT_SUCCESS; 53 list_t *types, char **config, bool *debug) {
66 bool debug = false;
67
68 memset(&nagbar, 0, sizeof(nagbar));
69 nagbar.anchors = ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP
70 | ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT
71 | ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT;
72 nagbar.type = NAGBAR_ERROR;
73 set_nagbar_colors();
74 nagbar.font = strdup("pango:monospace 10");
75 nagbar.buttons = create_list();
76
77 struct sway_nagbar_button *button_close =
78 calloc(sizeof(struct sway_nagbar_button), 1);
79 button_close->text = strdup("X");
80 button_close->type = NAGBAR_ACTION_DISMISS;
81 list_add(nagbar.buttons, button_close);
82
83 struct sway_nagbar_button *button_details =
84 calloc(sizeof(struct sway_nagbar_button), 1);
85 button_details->text = strdup("Toggle Details");
86 button_details->type = NAGBAR_ACTION_EXPAND;
87
88 static struct option opts[] = { 54 static struct option opts[] = {
89 {"button", required_argument, NULL, 'b'}, 55 {"button", required_argument, NULL, 'b'},
56 {"config", required_argument, NULL, 'c'},
90 {"debug", no_argument, NULL, 'd'}, 57 {"debug", no_argument, NULL, 'd'},
91 {"edge", required_argument, NULL, 'e'}, 58 {"edge", required_argument, NULL, 'e'},
92 {"font", required_argument, NULL, 'f'}, 59 {"font", required_argument, NULL, 'f'},
@@ -106,6 +73,7 @@ int main(int argc, char **argv) {
106 "\n" 73 "\n"
107 " -b, --button <text> <action> Create a button with text that " 74 " -b, --button <text> <action> Create a button with text that "
108 "executes action when pressed. Multiple buttons can be defined.\n" 75 "executes action when pressed. Multiple buttons can be defined.\n"
76 " -c, --config <path> Path to config file.\n"
109 " -d, --debug Enable debugging.\n" 77 " -d, --debug Enable debugging.\n"
110 " -e, --edge top|bottom Set the edge to use.\n" 78 " -e, --edge top|bottom Set the edge to use.\n"
111 " -f, --font <font> Set the font to use.\n" 79 " -f, --font <font> Set the font to use.\n"
@@ -115,114 +83,301 @@ int main(int argc, char **argv) {
115 " -m, --message <msg> Set the message text.\n" 83 " -m, --message <msg> Set the message text.\n"
116 " -o, --output <output> Set the output to use.\n" 84 " -o, --output <output> Set the output to use.\n"
117 " -s, --dismiss-button <text> Set the dismiss button text.\n" 85 " -s, --dismiss-button <text> Set the dismiss button text.\n"
118 " -t, --type error|warning Set the message type.\n" 86 " -t, --type <type> Set the message type.\n"
119 " -v, --version Show the version number and quit.\n"; 87 " -v, --version Show the version number and quit.\n";
120 88
89 optind = 1;
121 while (1) { 90 while (1) {
122 int c = getopt_long(argc, argv, "b:de:f:hlL:m:o:s:t:v", opts, NULL); 91 int c = getopt_long(argc, argv, "b:c:de:f:hlL:m:o:s:t:v", opts, NULL);
123 if (c == -1) { 92 if (c == -1) {
124 break; 93 break;
125 } 94 }
126 switch (c) { 95 switch (c) {
127 case 'b': // Button 96 case 'b': // Button
128 if (optind >= argc) { 97 if (nagbar) {
129 fprintf(stderr, "Missing action for button %s\n", optarg); 98 if (optind >= argc) {
130 exit_code = EXIT_FAILURE; 99 fprintf(stderr, "Missing action for button %s\n", optarg);
131 goto cleanup; 100 return EXIT_FAILURE;
132 } 101 }
133 struct sway_nagbar_button *button; 102 struct sway_nagbar_button *button;
134 button = calloc(sizeof(struct sway_nagbar_button), 1); 103 button = calloc(sizeof(struct sway_nagbar_button), 1);
135 button->text = strdup(optarg); 104 button->text = strdup(optarg);
136 button->type = NAGBAR_ACTION_COMMAND; 105 button->type = NAGBAR_ACTION_COMMAND;
137 button->action = strdup(argv[optind]); 106 button->action = strdup(argv[optind]);
138 optind++; 107 optind++;
139 list_add(nagbar.buttons, button); 108 list_add(nagbar->buttons, button);
109 }
110 break;
111 case 'c': // Config
112 if (config) {
113 *config = strdup(optarg);
114 }
140 break; 115 break;
141 case 'd': // Debug 116 case 'd': // Debug
142 debug = true; 117 if (debug) {
118 *debug = true;
119 }
143 break; 120 break;
144 case 'e': // Edge 121 case 'e': // Edge
145 if (strcmp(optarg, "top") == 0) { 122 if (nagbar) {
146 nagbar.anchors = ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP 123 if (strcmp(optarg, "top") == 0) {
147 | ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT 124 nagbar->anchors = ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP
148 | ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT; 125 | ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT
149 } else if (strcmp(optarg, "bottom") == 0) { 126 | ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT;
150 nagbar.anchors = ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM 127 } else if (strcmp(optarg, "bottom") == 0) {
151 | ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT 128 nagbar->anchors = ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM
152 | ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT; 129 | ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT
153 } else { 130 | ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT;
154 fprintf(stderr, "Invalid edge: %s\n", optarg); 131 } else {
155 exit_code = EXIT_FAILURE; 132 fprintf(stderr, "Invalid edge: %s\n", optarg);
156 goto cleanup; 133 return EXIT_FAILURE;
134 }
157 } 135 }
158 break; 136 break;
159 case 'f': // Font 137 case 'f': // Font
160 free(nagbar.font); 138 if (nagbar) {
161 nagbar.font = strdup(optarg); 139 free(nagbar->font);
140 nagbar->font = strdup(optarg);
141 }
162 break; 142 break;
163 case 'l': // Detailed Message 143 case 'l': // Detailed Message
164 free(nagbar.details.message); 144 if (nagbar) {
165 nagbar.details.message = read_from_stdin(); 145 free(nagbar->details.message);
166 nagbar.details.button_up.text = strdup("▲"); 146 nagbar->details.message = read_from_stdin();
167 nagbar.details.button_down.text = strdup("▼"); 147 nagbar->details.button_up.text = strdup("▲");
148 nagbar->details.button_down.text = strdup("▼");
149 }
168 break; 150 break;
169 case 'L': // Detailed Button Text 151 case 'L': // Detailed Button Text
170 free(button_details->text); 152 if (nagbar) {
171 button_details->text = strdup(optarg); 153 free(nagbar->details.button_details.text);
154 nagbar->details.button_details.text = strdup(optarg);
155 }
172 break; 156 break;
173 case 'm': // Message 157 case 'm': // Message
174 free(nagbar.message); 158 if (nagbar) {
175 nagbar.message = strdup(optarg); 159 free(nagbar->message);
160 nagbar->message = strdup(optarg);
161 }
176 break; 162 break;
177 case 'o': // Output 163 case 'o': // Output
178 free(nagbar.output.name); 164 if (nagbar) {
179 nagbar.output.name = strdup(optarg); 165 free(nagbar->output.name);
166 nagbar->output.name = strdup(optarg);
167 }
180 break; 168 break;
181 case 's': // Dismiss Button Text 169 case 's': // Dismiss Button Text
182 free(button_close->text); 170 if (nagbar) {
183 button_close->text = strdup(optarg); 171 struct sway_nagbar_button *button_close;
172 button_close = nagbar->buttons->items[0];
173 free(button_close->text);
174 button_close->text = strdup(optarg);
175 }
184 break; 176 break;
185 case 't': // Type 177 case 't': // Type
186 if (strcmp(optarg, "error") == 0) { 178 if (nagbar) {
187 nagbar.type = NAGBAR_ERROR; 179 nagbar->type = nagbar_type_get(types, optarg);
188 } else if (strcmp(optarg, "warning") == 0) { 180 if (!nagbar->type) {
189 nagbar.type = NAGBAR_WARNING; 181 fprintf(stderr, "Unknown type %s\n", optarg);
190 } else { 182 return EXIT_FAILURE;
191 fprintf(stderr, "Type must be either 'error' or 'warning'\n"); 183 }
192 exit_code = EXIT_FAILURE;
193 goto cleanup;
194 } 184 }
195 set_nagbar_colors();
196 break; 185 break;
197 case 'v': // Version 186 case 'v': // Version
198 fprintf(stdout, "swaynag version " SWAY_VERSION "\n"); 187 fprintf(stdout, "swaynag version " SWAY_VERSION "\n");
199 exit_code = EXIT_SUCCESS; 188 return -1;
200 goto cleanup;
201 default: // Help or unknown flag 189 default: // Help or unknown flag
202 fprintf(c == 'h' ? stdout : stderr, "%s", usage); 190 fprintf(c == 'h' ? stdout : stderr, "%s", usage);
203 exit_code = c == 'h' ? EXIT_SUCCESS : EXIT_FAILURE; 191 return -1;
204 goto cleanup; 192 }
193 }
194
195 return 0;
196}
197
198static bool file_exists(const char *path) {
199 return path && access(path, R_OK) != -1;
200}
201
202static char *get_config_path(void) {
203 static const char *config_paths[] = {
204 "$HOME/.swaynag/config",
205 "$XDG_CONFIG_HOME/swaynag/config",
206 SYSCONFDIR "/swaynag/config",
207 };
208
209 if (!getenv("XDG_CONFIG_HOME")) {
210 char *home = getenv("HOME");
211 char *config_home = malloc(strlen(home) + strlen("/.config") + 1);
212 if (!config_home) {
213 wlr_log(WLR_ERROR, "Unable to allocate $HOME/.config");
214 } else {
215 strcpy(config_home, home);
216 strcat(config_home, "/.config");
217 setenv("XDG_CONFIG_HOME", config_home, 1);
218 wlr_log(WLR_DEBUG, "Set XDG_CONFIG_HOME to %s", config_home);
219 free(config_home);
220 }
221 }
222
223 wordexp_t p;
224 char *path;
225 for (size_t i = 0; i < sizeof(config_paths) / sizeof(char *); ++i) {
226 if (wordexp(config_paths[i], &p, 0) == 0) {
227 path = strdup(p.we_wordv[0]);
228 wordfree(&p);
229 if (file_exists(path)) {
230 return path;
231 }
232 free(path);
233 }
234 }
235
236 return NULL;
237}
238
239static int load_config(char *path, struct sway_nagbar *nagbar, list_t *types) {
240 FILE *config = fopen(path, "r");
241 if (!config) {
242 fprintf(stderr, "Failed to read config. Running without it.\n");
243 return 0;
244 }
245 struct sway_nagbar_type *type = NULL;
246 char *line;
247 int line_number = 0;
248 while (!feof(config)) {
249 line = read_line(config);
250 if (!line) {
251 continue;
252 }
253
254 line_number++;
255 if (line[0] == '#') {
256 free(line);
257 continue;
205 } 258 }
259 if (strlen(line) == 0) {
260 free(line);
261 continue;
262 }
263
264 if (line[0] == '[') {
265 char *close = strchr(line, ']');
266 if (!close) {
267 free(line);
268 fclose(config);
269 fprintf(stderr, "Closing bracket not found on line %d\n",
270 line_number);
271 return 1;
272 }
273 char *name = calloc(1, close - line);
274 strncat(name, line + 1, close - line - 1);
275 type = nagbar_type_get(types, name);
276 if (!type) {
277 type = calloc(1, sizeof(struct sway_nagbar_type));
278 type->name = strdup(name);
279 list_add(types, type);
280 }
281 free(name);
282 } else {
283 char flag[strlen(line) + 3];
284 sprintf(flag, "--%s", line);
285 char *argv[] = {"swaynag", flag};
286 int result;
287 if (type) {
288 result = nagbar_parse_type(2, argv, type);
289 } else {
290 result = parse_options(2, argv, nagbar, types, NULL, NULL);
291 }
292 if (result != 0) {
293 free(line);
294 fclose(config);
295 return result;
296 }
297 }
298
299 free(line);
206 } 300 }
301 fclose(config);
302 return 0;
303}
304
305int main(int argc, char **argv) {
306 int exit_code = EXIT_SUCCESS;
307
308 list_t *types = create_list();
309 nagbar_types_add_default(types);
310
311 memset(&nagbar, 0, sizeof(nagbar));
312 nagbar.anchors = ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP
313 | ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT
314 | ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT;
315 nagbar.font = strdup("pango:monospace 10");
316 nagbar.buttons = create_list();
317
318 struct sway_nagbar_button *button_close =
319 calloc(sizeof(struct sway_nagbar_button), 1);
320 button_close->text = strdup("X");
321 button_close->type = NAGBAR_ACTION_DISMISS;
322 list_add(nagbar.buttons, button_close);
323
324 nagbar.details.button_details.text = strdup("Toggle Details");
325 nagbar.details.button_details.type = NAGBAR_ACTION_EXPAND;
207 326
327
328 char *config_path = NULL;
329 bool debug = false;
330 int launch_status = parse_options(argc, argv, NULL, NULL,
331 &config_path, &debug);
332 if (launch_status != 0) {
333 exit_code = launch_status;
334 goto cleanup;
335 }
208 wlr_log_init(debug ? WLR_DEBUG : WLR_ERROR, NULL); 336 wlr_log_init(debug ? WLR_DEBUG : WLR_ERROR, NULL);
209 337
338 if (!config_path) {
339 config_path = get_config_path();
340 }
341 if (config_path) {
342 wlr_log(WLR_DEBUG, "Loading config file: %s", config_path);
343 int config_status = load_config(config_path, &nagbar, types);
344 free(config_path);
345 if (config_status != 0) {
346 exit_code = config_status;
347 goto cleanup;
348 }
349 }
350
351 if (argc > 1) {
352 int result = parse_options(argc, argv, &nagbar, types, NULL, NULL);
353 if (result != 0) {
354 exit_code = result;
355 goto cleanup;
356 }
357 }
358
210 if (!nagbar.message) { 359 if (!nagbar.message) {
211 wlr_log(WLR_ERROR, "No message passed. Please provide --message/-m"); 360 wlr_log(WLR_ERROR, "No message passed. Please provide --message/-m");
212 exit_code = EXIT_FAILURE; 361 exit_code = EXIT_FAILURE;
213 goto cleanup; 362 goto cleanup;
214 } 363 }
215 364
365 if (!nagbar.type) {
366 nagbar.type = nagbar_type_get(types, "error");
367 }
368
369 nagbar.type = nagbar_type_clone(nagbar.type);
370 nagbar_types_free(types);
371
216 if (nagbar.details.message) { 372 if (nagbar.details.message) {
217 list_add(nagbar.buttons, button_details); 373 list_add(nagbar.buttons, &nagbar.details.button_details);
218 } else { 374 } else {
219 free(button_details->text); 375 free(nagbar.details.button_details.text);
220 free(button_details);
221 } 376 }
222 377
223 wlr_log(WLR_DEBUG, "Output: %s", nagbar.output.name); 378 wlr_log(WLR_DEBUG, "Output: %s", nagbar.output.name);
224 wlr_log(WLR_DEBUG, "Anchors: %d", nagbar.anchors); 379 wlr_log(WLR_DEBUG, "Anchors: %d", nagbar.anchors);
225 wlr_log(WLR_DEBUG, "Type: %d", nagbar.type); 380 wlr_log(WLR_DEBUG, "Type: %s", nagbar.type->name);
226 wlr_log(WLR_DEBUG, "Message: %s", nagbar.message); 381 wlr_log(WLR_DEBUG, "Message: %s", nagbar.message);
227 wlr_log(WLR_DEBUG, "Font: %s", nagbar.font); 382 wlr_log(WLR_DEBUG, "Font: %s", nagbar.font);
228 wlr_log(WLR_DEBUG, "Buttons"); 383 wlr_log(WLR_DEBUG, "Buttons");
@@ -238,8 +393,8 @@ int main(int argc, char **argv) {
238 return exit_code; 393 return exit_code;
239 394
240cleanup: 395cleanup:
241 free(button_details->text); 396 nagbar_types_free(types);
242 free(button_details); 397 free(nagbar.details.button_details.text);
243 nagbar_destroy(&nagbar); 398 nagbar_destroy(&nagbar);
244 return exit_code; 399 return exit_code;
245} 400}
diff --git a/swaynag/meson.build b/swaynag/meson.build
index 6492e4dc..6a9df984 100644
--- a/swaynag/meson.build
+++ b/swaynag/meson.build
@@ -3,6 +3,7 @@ executable(
3 'main.c', 3 'main.c',
4 'nagbar.c', 4 'nagbar.c',
5 'render.c', 5 'render.c',
6 'types.c',
6 ], 7 ],
7 include_directories: [sway_inc], 8 include_directories: [sway_inc],
8 dependencies: [ 9 dependencies: [
diff --git a/swaynag/nagbar.c b/swaynag/nagbar.c
index 6647e8c2..a20a9095 100644
--- a/swaynag/nagbar.c
+++ b/swaynag/nagbar.c
@@ -8,6 +8,7 @@
8#include "list.h" 8#include "list.h"
9#include "swaynag/nagbar.h" 9#include "swaynag/nagbar.h"
10#include "swaynag/render.h" 10#include "swaynag/render.h"
11#include "swaynag/types.h"
11#include "wlr-layer-shell-unstable-v1-client-protocol.h" 12#include "wlr-layer-shell-unstable-v1-client-protocol.h"
12 13
13static void nop() { 14static void nop() {
@@ -386,6 +387,10 @@ void nagbar_destroy(struct sway_nagbar *nagbar) {
386 free(nagbar->details.button_up.text); 387 free(nagbar->details.button_up.text);
387 free(nagbar->details.button_down.text); 388 free(nagbar->details.button_down.text);
388 389
390 if (nagbar->type) {
391 nagbar_type_free(nagbar->type);
392 }
393
389 if (nagbar->layer_surface) { 394 if (nagbar->layer_surface) {
390 zwlr_layer_surface_v1_destroy(nagbar->layer_surface); 395 zwlr_layer_surface_v1_destroy(nagbar->layer_surface);
391 } 396 }
diff --git a/swaynag/render.c b/swaynag/render.c
index 150ae3f2..134c247e 100644
--- a/swaynag/render.c
+++ b/swaynag/render.c
@@ -4,6 +4,7 @@
4#include "pango.h" 4#include "pango.h"
5#include "pool-buffer.h" 5#include "pool-buffer.h"
6#include "swaynag/nagbar.h" 6#include "swaynag/nagbar.h"
7#include "swaynag/types.h"
7#include "wlr-layer-shell-unstable-v1-client-protocol.h" 8#include "wlr-layer-shell-unstable-v1-client-protocol.h"
8 9
9static uint32_t render_message(cairo_t *cairo, struct sway_nagbar *nagbar) { 10static uint32_t render_message(cairo_t *cairo, struct sway_nagbar *nagbar) {
@@ -22,7 +23,7 @@ static uint32_t render_message(cairo_t *cairo, struct sway_nagbar *nagbar) {
22 return ideal_surface_height; 23 return ideal_surface_height;
23 } 24 }
24 25
25 cairo_set_source_u32(cairo, nagbar->colors.text); 26 cairo_set_source_u32(cairo, nagbar->type->text);
26 cairo_move_to(cairo, padding, (int)(ideal_height - text_height) / 2); 27 cairo_move_to(cairo, padding, (int)(ideal_height - text_height) / 2);
27 pango_printf(cairo, nagbar->font, nagbar->scale, true, "%s", 28 pango_printf(cairo, nagbar->font, nagbar->scale, true, "%s",
28 nagbar->message); 29 nagbar->message);
@@ -39,17 +40,17 @@ static void render_details_scroll_button(cairo_t *cairo,
39 int border = NAGBAR_BUTTON_BORDER_THICKNESS * nagbar->scale; 40 int border = NAGBAR_BUTTON_BORDER_THICKNESS * nagbar->scale;
40 int padding = NAGBAR_BUTTON_PADDING * nagbar->scale; 41 int padding = NAGBAR_BUTTON_PADDING * nagbar->scale;
41 42
42 cairo_set_source_u32(cairo, nagbar->colors.border); 43 cairo_set_source_u32(cairo, nagbar->type->border);
43 cairo_rectangle(cairo, button->x, button->y, 44 cairo_rectangle(cairo, button->x, button->y,
44 button->width, button->height); 45 button->width, button->height);
45 cairo_fill(cairo); 46 cairo_fill(cairo);
46 47
47 cairo_set_source_u32(cairo, nagbar->colors.button_background); 48 cairo_set_source_u32(cairo, nagbar->type->button_background);
48 cairo_rectangle(cairo, button->x + border, button->y + border, 49 cairo_rectangle(cairo, button->x + border, button->y + border,
49 button->width - (border * 2), button->height - (border * 2)); 50 button->width - (border * 2), button->height - (border * 2));
50 cairo_fill(cairo); 51 cairo_fill(cairo);
51 52
52 cairo_set_source_u32(cairo, nagbar->colors.text); 53 cairo_set_source_u32(cairo, nagbar->type->text);
53 cairo_move_to(cairo, button->x + border + padding, 54 cairo_move_to(cairo, button->x + border + padding,
54 button->y + border + (button->height - text_height) / 2); 55 button->y + border + (button->height - text_height) / 2);
55 pango_printf(cairo, nagbar->font, nagbar->scale, true, "%s", button->text); 56 pango_printf(cairo, nagbar->font, nagbar->scale, true, "%s", button->text);
@@ -154,14 +155,14 @@ static uint32_t render_detailed(cairo_t *cairo, struct sway_nagbar *nagbar,
154 &nagbar->details.button_down); 155 &nagbar->details.button_down);
155 } 156 }
156 157
157 cairo_set_source_u32(cairo, nagbar->colors.border); 158 cairo_set_source_u32(cairo, nagbar->type->border);
158 cairo_rectangle(cairo, nagbar->details.x, nagbar->details.y, 159 cairo_rectangle(cairo, nagbar->details.x, nagbar->details.y,
159 nagbar->details.width, nagbar->details.height); 160 nagbar->details.width, nagbar->details.height);
160 cairo_fill(cairo); 161 cairo_fill(cairo);
161 162
162 cairo_move_to(cairo, nagbar->details.x + padding, 163 cairo_move_to(cairo, nagbar->details.x + padding,
163 nagbar->details.y + padding); 164 nagbar->details.y + padding);
164 cairo_set_source_u32(cairo, nagbar->colors.text); 165 cairo_set_source_u32(cairo, nagbar->type->text);
165 pango_cairo_show_layout(cairo, layout); 166 pango_cairo_show_layout(cairo, layout);
166 g_object_unref(layout); 167 g_object_unref(layout);
167 168
@@ -192,17 +193,17 @@ static uint32_t render_button(cairo_t *cairo, struct sway_nagbar *nagbar,
192 button->width = text_width + padding * 2; 193 button->width = text_width + padding * 2;
193 button->height = text_height + padding * 2; 194 button->height = text_height + padding * 2;
194 195
195 cairo_set_source_u32(cairo, nagbar->colors.border); 196 cairo_set_source_u32(cairo, nagbar->type->border);
196 cairo_rectangle(cairo, button->x - border, button->y - border, 197 cairo_rectangle(cairo, button->x - border, button->y - border,
197 button->width + border * 2, button->height + border * 2); 198 button->width + border * 2, button->height + border * 2);
198 cairo_fill(cairo); 199 cairo_fill(cairo);
199 200
200 cairo_set_source_u32(cairo, nagbar->colors.button_background); 201 cairo_set_source_u32(cairo, nagbar->type->button_background);
201 cairo_rectangle(cairo, button->x, button->y, 202 cairo_rectangle(cairo, button->x, button->y,
202 button->width, button->height); 203 button->width, button->height);
203 cairo_fill(cairo); 204 cairo_fill(cairo);
204 205
205 cairo_set_source_u32(cairo, nagbar->colors.text); 206 cairo_set_source_u32(cairo, nagbar->type->text);
206 cairo_move_to(cairo, button->x + padding, button->y + padding); 207 cairo_move_to(cairo, button->x + padding, button->y + padding);
207 pango_printf(cairo, nagbar->font, nagbar->scale, true, "%s", button->text); 208 pango_printf(cairo, nagbar->font, nagbar->scale, true, "%s", button->text);
208 209
@@ -215,7 +216,7 @@ static uint32_t render_to_cairo(cairo_t *cairo, struct sway_nagbar *nagbar) {
215 uint32_t max_height = 0; 216 uint32_t max_height = 0;
216 217
217 cairo_set_operator(cairo, CAIRO_OPERATOR_SOURCE); 218 cairo_set_operator(cairo, CAIRO_OPERATOR_SOURCE);
218 cairo_set_source_u32(cairo, nagbar->colors.background); 219 cairo_set_source_u32(cairo, nagbar->type->background);
219 cairo_paint(cairo); 220 cairo_paint(cairo);
220 221
221 uint32_t h = render_message(cairo, nagbar); 222 uint32_t h = render_message(cairo, nagbar);
@@ -240,7 +241,7 @@ static uint32_t render_to_cairo(cairo_t *cairo, struct sway_nagbar *nagbar) {
240 if (max_height > nagbar->height) { 241 if (max_height > nagbar->height) {
241 max_height += border; 242 max_height += border;
242 } 243 }
243 cairo_set_source_u32(cairo, nagbar->colors.border_bottom); 244 cairo_set_source_u32(cairo, nagbar->type->border_bottom);
244 cairo_rectangle(cairo, 0, nagbar->height * nagbar->scale - border, 245 cairo_rectangle(cairo, 0, nagbar->height * nagbar->scale - border,
245 nagbar->width * nagbar->scale, border); 246 nagbar->width * nagbar->scale, border);
246 cairo_fill(cairo); 247 cairo_fill(cairo);
diff --git a/swaynag/swaynag.1.scd b/swaynag/swaynag.1.scd
index 879aaf2e..7d250a45 100644
--- a/swaynag/swaynag.1.scd
+++ b/swaynag/swaynag.1.scd
@@ -1,4 +1,4 @@
1swaynagbar(1) 1swaynag(1)
2 2
3# NAME 3# NAME
4 4
@@ -13,13 +13,21 @@ _swaynag_ [options...]
13 Create a button with the text _text_ that executes _action_ when pressed. 13 Create a button with the text _text_ that executes _action_ when pressed.
14 Multiple buttons can be defined by providing the flag multiple times. 14 Multiple buttons can be defined by providing the flag multiple times.
15 15
16*-c, --config* <path>
17 The config file to use. By default, the following paths are checked:
18 _$HOME/.swaynag/config_, _$XDG\_CONFIG\_HOME/swaynag/config_, and
19 _SYSCONFDIR/swaynag/config_. All flags aside from this one and _debug_ are
20 valid options in the configuration file using the format
21 _long-option=value_. All leading dashes should be omitted and the equals
22 sign is required. See swaynag(5) for more information.
23
16*-d, --debug* 24*-d, --debug*
17 Enable debugging. 25 Enable debugging.
18 26
19*-e, --edge top|bottom* 27*-e, --edge* top|bottom
20 Set the edge to use. 28 Set the edge to use.
21 29
22*-f, --font <font>* 30*-f, --font* <font>
23 Set the font to use. 31 Set the font to use.
24 32
25*-h, --help* 33*-h, --help*
@@ -29,24 +37,29 @@ _swaynag_ [options...]
29 Read a detailed message from stdin. A button to toggle details will be 37 Read a detailed message from stdin. A button to toggle details will be
30 added. Details are shown in a scrollable multi-line text area. 38 added. Details are shown in a scrollable multi-line text area.
31 39
32*-L, --detailed-button <text>* 40*-L, --detailed-button* <text>
33 Set the text for the button that toggles details. This has no effect if 41 Set the text for the button that toggles details. This has no effect if
34 there is not a detailed message. The default is _Toggle Details_. 42 there is not a detailed message. The default is _Toggle Details_.
35 43
36*-m, --message <msg>* 44*-m, --message* <msg>
37 Set the message text. 45 Set the message text.
38 46
39*-o, --output <output>* 47*-o, --output* <output>
40 Set the output to use. This should be the name of a _xdg\_output_. If 48 Set the output to use. This should be the name of a _xdg\_output_. If
41 _xdg\_output\_manager_ is not supported, then the first detected output 49 _xdg\_output\_manager_ is not supported, then the first detected output
42 will be used 50 will be used
43 51
44*-s, --dismiss-button <text>* 52*-s, --dismiss-button* <text>
45 Sets the text for the dismiss nagbar button. The default is _X_. 53 Sets the text for the dismiss nagbar button. The default is _X_.
46 54
47*-t, --type error|warning* 55*-t, --type*
48 Set the message type. 56 Set the message type. Two types are created by default _error_ and
57 _warning_. Custom types can be defined in the config file. See
58 _--config_ and swaynag(5) for details. Both of the default types can be
59 overridden in the config file as well.
49 60
50*-v, --version 61*-v, --version*
51 Show the version number and quit. 62 Show the version number and quit.
52 63
64# SEE
65swaynag(5)
diff --git a/swaynag/swaynag.5.scd b/swaynag/swaynag.5.scd
new file mode 100644
index 00000000..a4e05e3a
--- /dev/null
+++ b/swaynag/swaynag.5.scd
@@ -0,0 +1,57 @@
1swaynag(5)
2
3# NAME
4
5swaynag - swaynag configuration file
6
7# SYNOPSIS
8
9$HOME/.swaynag/config, $XDG\_CONFIG\_HOME/swaynag/config,
10SYSCONFDIR/swaynag/config
11
12# CONFIG FILE
13At the top of the config file, _swaynag_ options can be set using the format
14_long-option=value_. These will be used as default values if _swaynag_ is not
15given the option. This can be useful for setting a preferred font, output, and
16edge.
17
18Below the options, custom types may be defined. To define a type, use the
19following format:
20
21```
22[name-of-type]
23color=RRGGBB[AA]
24```
25
26All colors may be given in the form _RRGGBB_ or _RRGGBBAA_. The following
27colors can be set:
28
29*background*
30 The background color for _swaynag_.
31
32*border*
33 The color to use for borders of buttons.
34
35*border-bottom*
36 The color of the border line at the bottom of _swaynag_.
37
38*button-background*
39 The background color for the buttons.
40
41*text*
42 The color of the text.
43
44# EXAMPLE
45```
46font=Monospace 12
47
48[green]
49background=00AA00
50border=006600
51border-bottom=004400
52text=FFFFFF
53button-background=00CC00
54```
55
56# SEE
57swaynag(1)
diff --git a/swaynag/types.c b/swaynag/types.c
new file mode 100644
index 00000000..8dd99d2a
--- /dev/null
+++ b/swaynag/types.c
@@ -0,0 +1,116 @@
1#define _XOPEN_SOURCE 500
2#include <getopt.h>
3#include <stdbool.h>
4#include <stdlib.h>
5#include <stdint.h>
6#include <string.h>
7#include <strings.h>
8#include "list.h"
9#include "swaynag/types.h"
10#include "util.h"
11
12void nagbar_types_add_default(list_t *types) {
13 struct sway_nagbar_type *type_error;
14 type_error = calloc(1, sizeof(struct sway_nagbar_type));
15 type_error->name = strdup("error");
16 type_error->button_background = 0x680A0AFF;
17 type_error->background = 0x900000FF;
18 type_error->text = 0xFFFFFFFF;
19 type_error->border = 0xD92424FF;
20 type_error->border_bottom = 0x470909FF;
21 list_add(types, type_error);
22
23 struct sway_nagbar_type *type_warning;
24 type_warning = calloc(1, sizeof(struct sway_nagbar_type));
25 type_warning->name = strdup("warning");
26 type_warning->button_background = 0xFFC100FF;
27 type_warning->background = 0xFFA800FF;
28 type_warning->text = 0x000000FF;
29 type_warning->border = 0xAB7100FF;
30 type_warning->border_bottom = 0xAB7100FF;
31 list_add(types, type_warning);
32}
33
34struct sway_nagbar_type *nagbar_type_get(list_t *types, char *name) {
35 for (int i = 0; i < types->length; i++) {
36 struct sway_nagbar_type *type = types->items[i];
37 if (strcasecmp(type->name, name) == 0) {
38 return type;
39 }
40 }
41 return NULL;
42}
43
44struct sway_nagbar_type *nagbar_type_clone(struct sway_nagbar_type *type) {
45 struct sway_nagbar_type *clone;
46 clone = calloc(1, sizeof(struct sway_nagbar_type));
47 clone->name = strdup(type->name);
48 clone->button_background = type->button_background;
49 clone->background = type->background;
50 clone->text = type->text;
51 clone->border = type->border;
52 clone->border_bottom = type->border_bottom;
53 return clone;
54}
55
56void nagbar_type_free(struct sway_nagbar_type *type) {
57 free(type->name);
58 free(type);
59}
60
61void nagbar_types_free(list_t *types) {
62 while (types->length) {
63 struct sway_nagbar_type *type = types->items[0];
64 nagbar_type_free(type);
65 list_del(types, 0);
66 }
67 list_free(types);
68}
69
70int nagbar_parse_type(int argc, char **argv, struct sway_nagbar_type *type) {
71 enum color_option {
72 COLOR_BACKGROUND,
73 COLOR_BORDER,
74 COLOR_BORDER_BOTTOM,
75 COLOR_BUTTON,
76 COLOR_TEXT,
77 };
78
79 static struct option opts[] = {
80 {"background", required_argument, NULL, COLOR_BACKGROUND},
81 {"border", required_argument, NULL, COLOR_BORDER},
82 {"border-bottom", required_argument, NULL, COLOR_BORDER_BOTTOM},
83 {"button-background", required_argument, NULL, COLOR_BUTTON},
84 {"text", required_argument, NULL, COLOR_TEXT},
85 {0, 0, 0, 0}
86 };
87
88 optind = 1;
89 while (1) {
90 int c = getopt_long(argc, argv, "", opts, NULL);
91 if (c == -1) {
92 break;
93 }
94 switch (c) {
95 case COLOR_BACKGROUND:
96 type->background = parse_color(optarg);
97 break;
98 case COLOR_BORDER:
99 type->border = parse_color(optarg);
100 break;
101 case COLOR_BORDER_BOTTOM:
102 type->border_bottom = parse_color(optarg);
103 break;
104 case COLOR_BUTTON:
105 type->button_background = parse_color(optarg);
106 break;
107 case COLOR_TEXT:
108 type->text = parse_color(optarg);
109 break;
110 default:
111 break;
112 }
113 }
114 return 0;
115}
116