From a4f7bf23b21d0d838a8a19261d5fd69719003a03 Mon Sep 17 00:00:00 2001 From: Brian Ashworth Date: Fri, 27 Jul 2018 11:19:42 -0400 Subject: Address first round review for swaynag --- swaynag/swaynag.1.scd | 52 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 swaynag/swaynag.1.scd (limited to 'swaynag/swaynag.1.scd') diff --git a/swaynag/swaynag.1.scd b/swaynag/swaynag.1.scd new file mode 100644 index 00000000..879aaf2e --- /dev/null +++ b/swaynag/swaynag.1.scd @@ -0,0 +1,52 @@ +swaynagbar(1) + +# NAME + +swaynag - Show a warning or error message with buttons + +# SYNOPSIS + +_swaynag_ [options...] + +# OPTIONS +*-b, --button* + Create a button with the text _text_ that executes _action_ when pressed. + Multiple buttons can be defined by providing the flag multiple times. + +*-d, --debug* + Enable debugging. + +*-e, --edge top|bottom* + Set the edge to use. + +*-f, --font * + Set the font to use. + +*-h, --help* + Show help message and quit. + +*-l, --detailed-message* + Read a detailed message from stdin. A button to toggle details will be + added. Details are shown in a scrollable multi-line text area. + +*-L, --detailed-button * + Set the text for the button that toggles details. This has no effect if + there is not a detailed message. The default is _Toggle Details_. + +*-m, --message * + Set the message text. + +*-o, --output * + Set the output to use. This should be the name of a _xdg\_output_. If + _xdg\_output\_manager_ is not supported, then the first detected output + will be used + +*-s, --dismiss-button * + Sets the text for the dismiss nagbar button. The default is _X_. + +*-t, --type error|warning* + Set the message type. + +*-v, --version + Show the version number and quit. + -- cgit v1.2.3 From 8463a2896a932cd99f3dc93608b03cb4aba93293 Mon Sep 17 00:00:00 2001 From: Brian Ashworth Date: Sat, 28 Jul 2018 09:34:25 -0400 Subject: swaynag: implement config file support --- include/swaynag/nagbar.h | 20 +-- include/swaynag/types.h | 25 ++++ meson.build | 1 + swaynag/main.c | 357 +++++++++++++++++++++++++++++++++-------------- swaynag/meson.build | 1 + swaynag/nagbar.c | 5 + swaynag/render.c | 23 +-- swaynag/swaynag.1.scd | 33 +++-- swaynag/swaynag.5.scd | 57 ++++++++ swaynag/types.c | 116 +++++++++++++++ 10 files changed, 500 insertions(+), 138 deletions(-) create mode 100644 include/swaynag/types.h create mode 100644 swaynag/swaynag.5.scd create mode 100644 swaynag/types.c (limited to 'swaynag/swaynag.1.scd') diff --git a/include/swaynag/nagbar.h b/include/swaynag/nagbar.h index 8b55e4fa..b5d9b2cb 100644 --- a/include/swaynag/nagbar.h +++ b/include/swaynag/nagbar.h @@ -1,8 +1,9 @@ #ifndef _SWAY_NAGBAR_NAGBAR_H -#define _SWAY_NAGBAR_NAGNAR_H +#define _SWAY_NAGBAR_NAGBAR_H #include #include "list.h" #include "pool-buffer.h" +#include "swaynag/types.h" #include "xdg-output-unstable-v1-client-protocol.h" #define NAGBAR_BAR_BORDER_THICKNESS 2 @@ -16,25 +17,12 @@ #define NAGBAR_MAX_HEIGHT 500 -enum sway_nagbar_type { - NAGBAR_ERROR, - NAGBAR_WARNING, -}; - enum sway_nagbar_action_type { NAGBAR_ACTION_DISMISS, NAGBAR_ACTION_EXPAND, NAGBAR_ACTION_COMMAND, }; -struct sway_nagbar_colors { - uint32_t button_background; - uint32_t background; - uint32_t text; - uint32_t border; - uint32_t border_bottom; -}; - struct sway_nagbar_pointer { struct wl_pointer *pointer; struct wl_cursor_theme *cursor_theme; @@ -72,6 +60,7 @@ struct sway_nagbar_details { int offset; int visible_lines; int total_lines; + struct sway_nagbar_button button_details; struct sway_nagbar_button button_up; struct sway_nagbar_button button_down; }; @@ -97,8 +86,7 @@ struct sway_nagbar { struct pool_buffer buffers[2]; struct pool_buffer *current_buffer; - enum sway_nagbar_type type; - struct sway_nagbar_colors colors; + struct sway_nagbar_type *type; uint32_t anchors; char *message; char *font; diff --git a/include/swaynag/types.h b/include/swaynag/types.h new file mode 100644 index 00000000..32056514 --- /dev/null +++ b/include/swaynag/types.h @@ -0,0 +1,25 @@ +#ifndef _SWAY_NAGBAR_TYPES_H +#define _SWAY_NAGBAR_TYPES_H + +struct sway_nagbar_type { + char *name; + uint32_t button_background; + uint32_t background; + uint32_t text; + uint32_t border; + uint32_t border_bottom; +}; + +void nagbar_types_add_default(list_t *types); + +struct sway_nagbar_type *nagbar_type_get(list_t *types, char *name); + +struct sway_nagbar_type *nagbar_type_clone(struct sway_nagbar_type *type); + +void nagbar_type_free(struct sway_nagbar_type *type); + +void nagbar_types_free(list_t *types); + +int nagbar_parse_type(int argc, char **argv, struct sway_nagbar_type *type); + +#endif diff --git a/meson.build b/meson.build index c6501c39..57ed70cb 100644 --- a/meson.build +++ b/meson.build @@ -83,6 +83,7 @@ if scdoc.found() 'swaymsg/swaymsg.1.scd', 'swayidle/swayidle.1.scd', 'swaynag/swaynag.1.scd', + 'swaynag/swaynag.5.scd', ] foreach filename : man_files topic = filename.split('.')[-3].split('/')[-1] 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 @@ -#define _XOPEN_SOURCE 500 +#define _XOPEN_SOURCE 700 +#define _POSIX_C_SOURCE 200112L #include #include +#include +#include #include "log.h" #include "list.h" #include "readline.h" #include "swaynag/nagbar.h" +#include "swaynag/types.h" #include "wlr-layer-shell-unstable-v1-client-protocol.h" static struct sway_nagbar nagbar; @@ -19,22 +23,6 @@ void sway_terminate(int code) { exit(code); } -static void set_nagbar_colors() { - if (nagbar.type == NAGBAR_ERROR) { - nagbar.colors.button_background = 0x680A0AFF; - nagbar.colors.background = 0x900000FF; - nagbar.colors.text = 0xFFFFFFFF; - nagbar.colors.border = 0xD92424FF; - nagbar.colors.border_bottom = 0x470909FF; - } else if (nagbar.type == NAGBAR_WARNING) { - nagbar.colors.button_background = 0xFFC100FF; - nagbar.colors.background = 0xFFA800FF; - nagbar.colors.text = 0x000000FF; - nagbar.colors.border = 0xAB7100FF; - nagbar.colors.border_bottom = 0xAB7100FF; - } -} - static char *read_from_stdin() { char *buffer = NULL; while (!feof(stdin)) { @@ -61,32 +49,11 @@ static char *read_from_stdin() { return buffer; } -int main(int argc, char **argv) { - int exit_code = EXIT_SUCCESS; - bool debug = false; - - memset(&nagbar, 0, sizeof(nagbar)); - nagbar.anchors = ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP - | ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT - | ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT; - nagbar.type = NAGBAR_ERROR; - set_nagbar_colors(); - nagbar.font = strdup("pango:monospace 10"); - nagbar.buttons = create_list(); - - struct sway_nagbar_button *button_close = - calloc(sizeof(struct sway_nagbar_button), 1); - button_close->text = strdup("X"); - button_close->type = NAGBAR_ACTION_DISMISS; - list_add(nagbar.buttons, button_close); - - struct sway_nagbar_button *button_details = - calloc(sizeof(struct sway_nagbar_button), 1); - button_details->text = strdup("Toggle Details"); - button_details->type = NAGBAR_ACTION_EXPAND; - +static int parse_options(int argc, char **argv, struct sway_nagbar *nagbar, + list_t *types, char **config, bool *debug) { static struct option opts[] = { {"button", required_argument, NULL, 'b'}, + {"config", required_argument, NULL, 'c'}, {"debug", no_argument, NULL, 'd'}, {"edge", required_argument, NULL, 'e'}, {"font", required_argument, NULL, 'f'}, @@ -106,6 +73,7 @@ int main(int argc, char **argv) { "\n" " -b, --button Create a button with text that " "executes action when pressed. Multiple buttons can be defined.\n" + " -c, --config Path to config file.\n" " -d, --debug Enable debugging.\n" " -e, --edge top|bottom Set the edge to use.\n" " -f, --font Set the font to use.\n" @@ -115,114 +83,301 @@ int main(int argc, char **argv) { " -m, --message Set the message text.\n" " -o, --output Set the output to use.\n" " -s, --dismiss-button Set the dismiss button text.\n" - " -t, --type error|warning Set the message type.\n" + " -t, --type Set the message type.\n" " -v, --version Show the version number and quit.\n"; + optind = 1; while (1) { - int c = getopt_long(argc, argv, "b:de:f:hlL:m:o:s:t:v", opts, NULL); + int c = getopt_long(argc, argv, "b:c:de:f:hlL:m:o:s:t:v", opts, NULL); if (c == -1) { break; } switch (c) { case 'b': // Button - if (optind >= argc) { - fprintf(stderr, "Missing action for button %s\n", optarg); - exit_code = EXIT_FAILURE; - goto cleanup; - } - struct sway_nagbar_button *button; - button = calloc(sizeof(struct sway_nagbar_button), 1); - button->text = strdup(optarg); - button->type = NAGBAR_ACTION_COMMAND; - button->action = strdup(argv[optind]); - optind++; - list_add(nagbar.buttons, button); + if (nagbar) { + if (optind >= argc) { + fprintf(stderr, "Missing action for button %s\n", optarg); + return EXIT_FAILURE; + } + struct sway_nagbar_button *button; + button = calloc(sizeof(struct sway_nagbar_button), 1); + button->text = strdup(optarg); + button->type = NAGBAR_ACTION_COMMAND; + button->action = strdup(argv[optind]); + optind++; + list_add(nagbar->buttons, button); + } + break; + case 'c': // Config + if (config) { + *config = strdup(optarg); + } break; case 'd': // Debug - debug = true; + if (debug) { + *debug = true; + } break; case 'e': // Edge - if (strcmp(optarg, "top") == 0) { - nagbar.anchors = ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP - | ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT - | ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT; - } else if (strcmp(optarg, "bottom") == 0) { - nagbar.anchors = ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM - | ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT - | ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT; - } else { - fprintf(stderr, "Invalid edge: %s\n", optarg); - exit_code = EXIT_FAILURE; - goto cleanup; + if (nagbar) { + if (strcmp(optarg, "top") == 0) { + nagbar->anchors = ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP + | ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT + | ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT; + } else if (strcmp(optarg, "bottom") == 0) { + nagbar->anchors = ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM + | ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT + | ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT; + } else { + fprintf(stderr, "Invalid edge: %s\n", optarg); + return EXIT_FAILURE; + } } break; case 'f': // Font - free(nagbar.font); - nagbar.font = strdup(optarg); + if (nagbar) { + free(nagbar->font); + nagbar->font = strdup(optarg); + } break; case 'l': // Detailed Message - free(nagbar.details.message); - nagbar.details.message = read_from_stdin(); - nagbar.details.button_up.text = strdup("▲"); - nagbar.details.button_down.text = strdup("▼"); + if (nagbar) { + free(nagbar->details.message); + nagbar->details.message = read_from_stdin(); + nagbar->details.button_up.text = strdup("▲"); + nagbar->details.button_down.text = strdup("▼"); + } break; case 'L': // Detailed Button Text - free(button_details->text); - button_details->text = strdup(optarg); + if (nagbar) { + free(nagbar->details.button_details.text); + nagbar->details.button_details.text = strdup(optarg); + } break; case 'm': // Message - free(nagbar.message); - nagbar.message = strdup(optarg); + if (nagbar) { + free(nagbar->message); + nagbar->message = strdup(optarg); + } break; case 'o': // Output - free(nagbar.output.name); - nagbar.output.name = strdup(optarg); + if (nagbar) { + free(nagbar->output.name); + nagbar->output.name = strdup(optarg); + } break; case 's': // Dismiss Button Text - free(button_close->text); - button_close->text = strdup(optarg); + if (nagbar) { + struct sway_nagbar_button *button_close; + button_close = nagbar->buttons->items[0]; + free(button_close->text); + button_close->text = strdup(optarg); + } break; case 't': // Type - if (strcmp(optarg, "error") == 0) { - nagbar.type = NAGBAR_ERROR; - } else if (strcmp(optarg, "warning") == 0) { - nagbar.type = NAGBAR_WARNING; - } else { - fprintf(stderr, "Type must be either 'error' or 'warning'\n"); - exit_code = EXIT_FAILURE; - goto cleanup; + if (nagbar) { + nagbar->type = nagbar_type_get(types, optarg); + if (!nagbar->type) { + fprintf(stderr, "Unknown type %s\n", optarg); + return EXIT_FAILURE; + } } - set_nagbar_colors(); break; case 'v': // Version fprintf(stdout, "swaynag version " SWAY_VERSION "\n"); - exit_code = EXIT_SUCCESS; - goto cleanup; + return -1; default: // Help or unknown flag fprintf(c == 'h' ? stdout : stderr, "%s", usage); - exit_code = c == 'h' ? EXIT_SUCCESS : EXIT_FAILURE; - goto cleanup; + return -1; + } + } + + return 0; +} + +static bool file_exists(const char *path) { + return path && access(path, R_OK) != -1; +} + +static char *get_config_path(void) { + static const char *config_paths[] = { + "$HOME/.swaynag/config", + "$XDG_CONFIG_HOME/swaynag/config", + SYSCONFDIR "/swaynag/config", + }; + + if (!getenv("XDG_CONFIG_HOME")) { + char *home = getenv("HOME"); + char *config_home = malloc(strlen(home) + strlen("/.config") + 1); + if (!config_home) { + wlr_log(WLR_ERROR, "Unable to allocate $HOME/.config"); + } else { + strcpy(config_home, home); + strcat(config_home, "/.config"); + setenv("XDG_CONFIG_HOME", config_home, 1); + wlr_log(WLR_DEBUG, "Set XDG_CONFIG_HOME to %s", config_home); + free(config_home); + } + } + + wordexp_t p; + char *path; + for (size_t i = 0; i < sizeof(config_paths) / sizeof(char *); ++i) { + if (wordexp(config_paths[i], &p, 0) == 0) { + path = strdup(p.we_wordv[0]); + wordfree(&p); + if (file_exists(path)) { + return path; + } + free(path); + } + } + + return NULL; +} + +static int load_config(char *path, struct sway_nagbar *nagbar, list_t *types) { + FILE *config = fopen(path, "r"); + if (!config) { + fprintf(stderr, "Failed to read config. Running without it.\n"); + return 0; + } + struct sway_nagbar_type *type = NULL; + char *line; + int line_number = 0; + while (!feof(config)) { + line = read_line(config); + if (!line) { + continue; + } + + line_number++; + if (line[0] == '#') { + free(line); + continue; } + if (strlen(line) == 0) { + free(line); + continue; + } + + if (line[0] == '[') { + char *close = strchr(line, ']'); + if (!close) { + free(line); + fclose(config); + fprintf(stderr, "Closing bracket not found on line %d\n", + line_number); + return 1; + } + char *name = calloc(1, close - line); + strncat(name, line + 1, close - line - 1); + type = nagbar_type_get(types, name); + if (!type) { + type = calloc(1, sizeof(struct sway_nagbar_type)); + type->name = strdup(name); + list_add(types, type); + } + free(name); + } else { + char flag[strlen(line) + 3]; + sprintf(flag, "--%s", line); + char *argv[] = {"swaynag", flag}; + int result; + if (type) { + result = nagbar_parse_type(2, argv, type); + } else { + result = parse_options(2, argv, nagbar, types, NULL, NULL); + } + if (result != 0) { + free(line); + fclose(config); + return result; + } + } + + free(line); } + fclose(config); + return 0; +} + +int main(int argc, char **argv) { + int exit_code = EXIT_SUCCESS; + + list_t *types = create_list(); + nagbar_types_add_default(types); + + memset(&nagbar, 0, sizeof(nagbar)); + nagbar.anchors = ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP + | ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT + | ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT; + nagbar.font = strdup("pango:monospace 10"); + nagbar.buttons = create_list(); + + struct sway_nagbar_button *button_close = + calloc(sizeof(struct sway_nagbar_button), 1); + button_close->text = strdup("X"); + button_close->type = NAGBAR_ACTION_DISMISS; + list_add(nagbar.buttons, button_close); + + nagbar.details.button_details.text = strdup("Toggle Details"); + nagbar.details.button_details.type = NAGBAR_ACTION_EXPAND; + + char *config_path = NULL; + bool debug = false; + int launch_status = parse_options(argc, argv, NULL, NULL, + &config_path, &debug); + if (launch_status != 0) { + exit_code = launch_status; + goto cleanup; + } wlr_log_init(debug ? WLR_DEBUG : WLR_ERROR, NULL); + if (!config_path) { + config_path = get_config_path(); + } + if (config_path) { + wlr_log(WLR_DEBUG, "Loading config file: %s", config_path); + int config_status = load_config(config_path, &nagbar, types); + free(config_path); + if (config_status != 0) { + exit_code = config_status; + goto cleanup; + } + } + + if (argc > 1) { + int result = parse_options(argc, argv, &nagbar, types, NULL, NULL); + if (result != 0) { + exit_code = result; + goto cleanup; + } + } + if (!nagbar.message) { wlr_log(WLR_ERROR, "No message passed. Please provide --message/-m"); exit_code = EXIT_FAILURE; goto cleanup; } + if (!nagbar.type) { + nagbar.type = nagbar_type_get(types, "error"); + } + + nagbar.type = nagbar_type_clone(nagbar.type); + nagbar_types_free(types); + if (nagbar.details.message) { - list_add(nagbar.buttons, button_details); + list_add(nagbar.buttons, &nagbar.details.button_details); } else { - free(button_details->text); - free(button_details); + free(nagbar.details.button_details.text); } wlr_log(WLR_DEBUG, "Output: %s", nagbar.output.name); wlr_log(WLR_DEBUG, "Anchors: %d", nagbar.anchors); - wlr_log(WLR_DEBUG, "Type: %d", nagbar.type); + wlr_log(WLR_DEBUG, "Type: %s", nagbar.type->name); wlr_log(WLR_DEBUG, "Message: %s", nagbar.message); wlr_log(WLR_DEBUG, "Font: %s", nagbar.font); wlr_log(WLR_DEBUG, "Buttons"); @@ -238,8 +393,8 @@ int main(int argc, char **argv) { return exit_code; cleanup: - free(button_details->text); - free(button_details); + nagbar_types_free(types); + free(nagbar.details.button_details.text); nagbar_destroy(&nagbar); return exit_code; } 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( 'main.c', 'nagbar.c', 'render.c', + 'types.c', ], include_directories: [sway_inc], 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 @@ #include "list.h" #include "swaynag/nagbar.h" #include "swaynag/render.h" +#include "swaynag/types.h" #include "wlr-layer-shell-unstable-v1-client-protocol.h" static void nop() { @@ -386,6 +387,10 @@ void nagbar_destroy(struct sway_nagbar *nagbar) { free(nagbar->details.button_up.text); free(nagbar->details.button_down.text); + if (nagbar->type) { + nagbar_type_free(nagbar->type); + } + if (nagbar->layer_surface) { zwlr_layer_surface_v1_destroy(nagbar->layer_surface); } 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 @@ #include "pango.h" #include "pool-buffer.h" #include "swaynag/nagbar.h" +#include "swaynag/types.h" #include "wlr-layer-shell-unstable-v1-client-protocol.h" static 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) { return ideal_surface_height; } - cairo_set_source_u32(cairo, nagbar->colors.text); + cairo_set_source_u32(cairo, nagbar->type->text); cairo_move_to(cairo, padding, (int)(ideal_height - text_height) / 2); pango_printf(cairo, nagbar->font, nagbar->scale, true, "%s", nagbar->message); @@ -39,17 +40,17 @@ static void render_details_scroll_button(cairo_t *cairo, int border = NAGBAR_BUTTON_BORDER_THICKNESS * nagbar->scale; int padding = NAGBAR_BUTTON_PADDING * nagbar->scale; - cairo_set_source_u32(cairo, nagbar->colors.border); + cairo_set_source_u32(cairo, nagbar->type->border); cairo_rectangle(cairo, button->x, button->y, button->width, button->height); cairo_fill(cairo); - cairo_set_source_u32(cairo, nagbar->colors.button_background); + cairo_set_source_u32(cairo, nagbar->type->button_background); cairo_rectangle(cairo, button->x + border, button->y + border, button->width - (border * 2), button->height - (border * 2)); cairo_fill(cairo); - cairo_set_source_u32(cairo, nagbar->colors.text); + cairo_set_source_u32(cairo, nagbar->type->text); cairo_move_to(cairo, button->x + border + padding, button->y + border + (button->height - text_height) / 2); 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, &nagbar->details.button_down); } - cairo_set_source_u32(cairo, nagbar->colors.border); + cairo_set_source_u32(cairo, nagbar->type->border); cairo_rectangle(cairo, nagbar->details.x, nagbar->details.y, nagbar->details.width, nagbar->details.height); cairo_fill(cairo); cairo_move_to(cairo, nagbar->details.x + padding, nagbar->details.y + padding); - cairo_set_source_u32(cairo, nagbar->colors.text); + cairo_set_source_u32(cairo, nagbar->type->text); pango_cairo_show_layout(cairo, layout); g_object_unref(layout); @@ -192,17 +193,17 @@ static uint32_t render_button(cairo_t *cairo, struct sway_nagbar *nagbar, button->width = text_width + padding * 2; button->height = text_height + padding * 2; - cairo_set_source_u32(cairo, nagbar->colors.border); + cairo_set_source_u32(cairo, nagbar->type->border); cairo_rectangle(cairo, button->x - border, button->y - border, button->width + border * 2, button->height + border * 2); cairo_fill(cairo); - cairo_set_source_u32(cairo, nagbar->colors.button_background); + cairo_set_source_u32(cairo, nagbar->type->button_background); cairo_rectangle(cairo, button->x, button->y, button->width, button->height); cairo_fill(cairo); - cairo_set_source_u32(cairo, nagbar->colors.text); + cairo_set_source_u32(cairo, nagbar->type->text); cairo_move_to(cairo, button->x + padding, button->y + padding); pango_printf(cairo, nagbar->font, nagbar->scale, true, "%s", button->text); @@ -215,7 +216,7 @@ static uint32_t render_to_cairo(cairo_t *cairo, struct sway_nagbar *nagbar) { uint32_t max_height = 0; cairo_set_operator(cairo, CAIRO_OPERATOR_SOURCE); - cairo_set_source_u32(cairo, nagbar->colors.background); + cairo_set_source_u32(cairo, nagbar->type->background); cairo_paint(cairo); uint32_t h = render_message(cairo, nagbar); @@ -240,7 +241,7 @@ static uint32_t render_to_cairo(cairo_t *cairo, struct sway_nagbar *nagbar) { if (max_height > nagbar->height) { max_height += border; } - cairo_set_source_u32(cairo, nagbar->colors.border_bottom); + cairo_set_source_u32(cairo, nagbar->type->border_bottom); cairo_rectangle(cairo, 0, nagbar->height * nagbar->scale - border, nagbar->width * nagbar->scale, border); 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 @@ -swaynagbar(1) +swaynag(1) # NAME @@ -13,13 +13,21 @@ _swaynag_ [options...] Create a button with the text _text_ that executes _action_ when pressed. Multiple buttons can be defined by providing the flag multiple times. +*-c, --config* + The config file to use. By default, the following paths are checked: + _$HOME/.swaynag/config_, _$XDG\_CONFIG\_HOME/swaynag/config_, and + _SYSCONFDIR/swaynag/config_. All flags aside from this one and _debug_ are + valid options in the configuration file using the format + _long-option=value_. All leading dashes should be omitted and the equals + sign is required. See swaynag(5) for more information. + *-d, --debug* Enable debugging. -*-e, --edge top|bottom* +*-e, --edge* top|bottom Set the edge to use. -*-f, --font * +*-f, --font* Set the font to use. *-h, --help* @@ -29,24 +37,29 @@ _swaynag_ [options...] Read a detailed message from stdin. A button to toggle details will be added. Details are shown in a scrollable multi-line text area. -*-L, --detailed-button * +*-L, --detailed-button* Set the text for the button that toggles details. This has no effect if there is not a detailed message. The default is _Toggle Details_. -*-m, --message * +*-m, --message* Set the message text. -*-o, --output * +*-o, --output* Set the output to use. This should be the name of a _xdg\_output_. If _xdg\_output\_manager_ is not supported, then the first detected output will be used -*-s, --dismiss-button * +*-s, --dismiss-button* Sets the text for the dismiss nagbar button. The default is _X_. -*-t, --type error|warning* - Set the message type. +*-t, --type* + Set the message type. Two types are created by default _error_ and + _warning_. Custom types can be defined in the config file. See + _--config_ and swaynag(5) for details. Both of the default types can be + overridden in the config file as well. -*-v, --version +*-v, --version* Show the version number and quit. +# SEE +swaynag(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 @@ +swaynag(5) + +# NAME + +swaynag - swaynag configuration file + +# SYNOPSIS + +$HOME/.swaynag/config, $XDG\_CONFIG\_HOME/swaynag/config, +SYSCONFDIR/swaynag/config + +# CONFIG FILE +At the top of the config file, _swaynag_ options can be set using the format +_long-option=value_. These will be used as default values if _swaynag_ is not +given the option. This can be useful for setting a preferred font, output, and +edge. + +Below the options, custom types may be defined. To define a type, use the +following format: + +``` +[name-of-type] +color=RRGGBB[AA] +``` + +All colors may be given in the form _RRGGBB_ or _RRGGBBAA_. The following +colors can be set: + +*background* + The background color for _swaynag_. + +*border* + The color to use for borders of buttons. + +*border-bottom* + The color of the border line at the bottom of _swaynag_. + +*button-background* + The background color for the buttons. + +*text* + The color of the text. + +# EXAMPLE +``` +font=Monospace 12 + +[green] +background=00AA00 +border=006600 +border-bottom=004400 +text=FFFFFF +button-background=00CC00 +``` + +# SEE +swaynag(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 @@ +#define _XOPEN_SOURCE 500 +#include +#include +#include +#include +#include +#include +#include "list.h" +#include "swaynag/types.h" +#include "util.h" + +void nagbar_types_add_default(list_t *types) { + struct sway_nagbar_type *type_error; + type_error = calloc(1, sizeof(struct sway_nagbar_type)); + type_error->name = strdup("error"); + type_error->button_background = 0x680A0AFF; + type_error->background = 0x900000FF; + type_error->text = 0xFFFFFFFF; + type_error->border = 0xD92424FF; + type_error->border_bottom = 0x470909FF; + list_add(types, type_error); + + struct sway_nagbar_type *type_warning; + type_warning = calloc(1, sizeof(struct sway_nagbar_type)); + type_warning->name = strdup("warning"); + type_warning->button_background = 0xFFC100FF; + type_warning->background = 0xFFA800FF; + type_warning->text = 0x000000FF; + type_warning->border = 0xAB7100FF; + type_warning->border_bottom = 0xAB7100FF; + list_add(types, type_warning); +} + +struct sway_nagbar_type *nagbar_type_get(list_t *types, char *name) { + for (int i = 0; i < types->length; i++) { + struct sway_nagbar_type *type = types->items[i]; + if (strcasecmp(type->name, name) == 0) { + return type; + } + } + return NULL; +} + +struct sway_nagbar_type *nagbar_type_clone(struct sway_nagbar_type *type) { + struct sway_nagbar_type *clone; + clone = calloc(1, sizeof(struct sway_nagbar_type)); + clone->name = strdup(type->name); + clone->button_background = type->button_background; + clone->background = type->background; + clone->text = type->text; + clone->border = type->border; + clone->border_bottom = type->border_bottom; + return clone; +} + +void nagbar_type_free(struct sway_nagbar_type *type) { + free(type->name); + free(type); +} + +void nagbar_types_free(list_t *types) { + while (types->length) { + struct sway_nagbar_type *type = types->items[0]; + nagbar_type_free(type); + list_del(types, 0); + } + list_free(types); +} + +int nagbar_parse_type(int argc, char **argv, struct sway_nagbar_type *type) { + enum color_option { + COLOR_BACKGROUND, + COLOR_BORDER, + COLOR_BORDER_BOTTOM, + COLOR_BUTTON, + COLOR_TEXT, + }; + + static struct option opts[] = { + {"background", required_argument, NULL, COLOR_BACKGROUND}, + {"border", required_argument, NULL, COLOR_BORDER}, + {"border-bottom", required_argument, NULL, COLOR_BORDER_BOTTOM}, + {"button-background", required_argument, NULL, COLOR_BUTTON}, + {"text", required_argument, NULL, COLOR_TEXT}, + {0, 0, 0, 0} + }; + + optind = 1; + while (1) { + int c = getopt_long(argc, argv, "", opts, NULL); + if (c == -1) { + break; + } + switch (c) { + case COLOR_BACKGROUND: + type->background = parse_color(optarg); + break; + case COLOR_BORDER: + type->border = parse_color(optarg); + break; + case COLOR_BORDER_BOTTOM: + type->border_bottom = parse_color(optarg); + break; + case COLOR_BUTTON: + type->button_background = parse_color(optarg); + break; + case COLOR_TEXT: + type->text = parse_color(optarg); + break; + default: + break; + } + } + return 0; +} + -- cgit v1.2.3 From e01acb6097b583fcf2f6d0e0afe1bd878dd9b683 Mon Sep 17 00:00:00 2001 From: Brian Ashworth Date: Sun, 29 Jul 2018 22:42:03 -0400 Subject: swaynag: allow more config options --- include/swaynag/config.h | 2 +- include/swaynag/swaynag.h | 11 ---- include/swaynag/types.h | 18 +++++- swaynag/config.c | 149 +++++++++++++++++++++++++++++++++++++++------ swaynag/main.c | 33 ++++++---- swaynag/render.c | 51 ++++++++-------- swaynag/swaynag.1.scd | 46 ++++++++++++-- swaynag/swaynag.5.scd | 52 ++++++++++++++-- swaynag/swaynag.c | 4 +- swaynag/types.c | 150 ++++++++++++++++++++++++++++------------------ 10 files changed, 379 insertions(+), 137 deletions(-) (limited to 'swaynag/swaynag.1.scd') diff --git a/include/swaynag/config.h b/include/swaynag/config.h index 3fd5b3ce..0d8889de 100644 --- a/include/swaynag/config.h +++ b/include/swaynag/config.h @@ -4,7 +4,7 @@ #include "list.h" int swaynag_parse_options(int argc, char **argv, struct swaynag *swaynag, - list_t *types, char **config, bool *debug); + list_t *types, struct swaynag_type *type, char **config, bool *debug); char *swaynag_get_config_path(void); diff --git a/include/swaynag/swaynag.h b/include/swaynag/swaynag.h index 6a56f14f..dd6fe0cd 100644 --- a/include/swaynag/swaynag.h +++ b/include/swaynag/swaynag.h @@ -7,15 +7,6 @@ #include "swaynag/types.h" #include "xdg-output-unstable-v1-client-protocol.h" -#define SWAYNAG_BAR_BORDER_THICKNESS 2 -#define SWAYNAG_MESSAGE_PADDING 8 -#define SWAYNAG_DETAILS_BORDER_THICKNESS 3 -#define SWAYNAG_BUTTON_BORDER_THICKNESS 3 -#define SWAYNAG_BUTTON_GAP 20 -#define SWAYNAG_BUTTON_GAP_CLOSE 15 -#define SWAYNAG_BUTTON_MARGIN_RIGHT 2 -#define SWAYNAG_BUTTON_PADDING 3 - #define SWAYNAG_MAX_HEIGHT 500 enum swaynag_action_type { @@ -88,9 +79,7 @@ struct swaynag { struct pool_buffer *current_buffer; struct swaynag_type *type; - uint32_t anchors; char *message; - char *font; list_t *buttons; struct swaynag_details details; }; diff --git a/include/swaynag/types.h b/include/swaynag/types.h index af83bd83..2183ce22 100644 --- a/include/swaynag/types.h +++ b/include/swaynag/types.h @@ -3,11 +3,25 @@ struct swaynag_type { char *name; + + char *font; + char *output; + uint32_t anchors; + uint32_t button_background; uint32_t background; uint32_t text; uint32_t border; uint32_t border_bottom; + + uint32_t bar_border_thickness; + uint32_t message_padding; + uint32_t details_border_thickness; + uint32_t button_border_thickness; + uint32_t button_gap; + uint32_t button_gap_close; + uint32_t button_margin_right; + uint32_t button_padding; }; void swaynag_types_add_default(list_t *types); @@ -16,10 +30,10 @@ struct swaynag_type *swaynag_type_get(list_t *types, char *name); struct swaynag_type *swaynag_type_clone(struct swaynag_type *type); +void swaynag_type_merge(struct swaynag_type *dest, struct swaynag_type *src); + void swaynag_type_free(struct swaynag_type *type); void swaynag_types_free(list_t *types); -int swaynag_parse_type(int argc, char **argv, struct swaynag_type *type); - #endif diff --git a/swaynag/config.c b/swaynag/config.c index 289fc82a..80c5ad88 100644 --- a/swaynag/config.c +++ b/swaynag/config.c @@ -8,6 +8,7 @@ #include "readline.h" #include "swaynag/swaynag.h" #include "swaynag/types.h" +#include "util.h" #include "wlr-layer-shell-unstable-v1-client-protocol.h" static char *read_from_stdin() { @@ -37,7 +38,23 @@ static char *read_from_stdin() { } int swaynag_parse_options(int argc, char **argv, struct swaynag *swaynag, - list_t *types, char **config, bool *debug) { + list_t *types, struct swaynag_type *type, char **config, bool *debug) { + enum type_options { + TO_COLOR_BACKGROUND = 256, + TO_COLOR_BORDER, + TO_COLOR_BORDER_BOTTOM, + TO_COLOR_BUTTON, + TO_COLOR_TEXT, + TO_THICK_BAR_BORDER, + TO_PADDING_MESSAGE, + TO_THICK_DET_BORDER, + TO_THICK_BTN_BORDER, + TO_GAP_BTN, + TO_GAP_BTN_DISMISS, + TO_MARGIN_BTN_RIGHT, + TO_PADDING_BTN, + }; + static struct option opts[] = { {"button", required_argument, NULL, 'b'}, {"config", required_argument, NULL, 'c'}, @@ -52,6 +69,21 @@ int swaynag_parse_options(int argc, char **argv, struct swaynag *swaynag, {"dismiss-button", required_argument, NULL, 's'}, {"type", required_argument, NULL, 't'}, {"version", no_argument, NULL, 'v'}, + + {"background", required_argument, NULL, TO_COLOR_BACKGROUND}, + {"border", required_argument, NULL, TO_COLOR_BORDER}, + {"border-bottom", required_argument, NULL, TO_COLOR_BORDER_BOTTOM}, + {"button-background", required_argument, NULL, TO_COLOR_BUTTON}, + {"text", required_argument, NULL, TO_COLOR_TEXT}, + {"border-bottom-size", required_argument, NULL, TO_THICK_BAR_BORDER}, + {"message-padding", required_argument, NULL, TO_PADDING_MESSAGE}, + {"details-border-size", required_argument, NULL, TO_THICK_DET_BORDER}, + {"button-border-size", required_argument, NULL, TO_THICK_BTN_BORDER}, + {"button-gap", required_argument, NULL, TO_GAP_BTN}, + {"button-dismiss-gap", required_argument, NULL, TO_GAP_BTN_DISMISS}, + {"button-margin-right", required_argument, NULL, TO_MARGIN_BTN_RIGHT}, + {"button-padding", required_argument, NULL, TO_PADDING_BTN}, + {0, 0, 0, 0} }; @@ -71,7 +103,22 @@ int swaynag_parse_options(int argc, char **argv, struct swaynag *swaynag, " -o, --output Set the output to use.\n" " -s, --dismiss-button Set the dismiss button text.\n" " -t, --type Set the message type.\n" - " -v, --version Show the version number and quit.\n"; + " -v, --version Show the version number and quit.\n" + "\n" + "The following appearance options can also be given:\n" + " --background RRGGBB[AA] Background color.\n" + " --border RRGGBB[AA] Border color.\n" + " --border-bottom RRGGBB[AA] Bottom border color.\n" + " --button-background RRGGBB[AA] Button background color.\n" + " --text RRGGBB[AA] Text color.\n" + " --border-bottom-size size Thickness of the bar border.\n" + " --message-padding padding Padding for the message.\n" + " --details-border-size size Thickness for the details border.\n" + " --button-border-size size Thickness for the button border.\n" + " --button-gap gap Size of the gap between buttons\n" + " --button-dismiss-gap gap Size of the gap for dismiss button.\n" + " --button-margin-right margin Margin from dismiss button to edge.\n" + " --button-padding padding Padding for the button text.\n"; optind = 1; while (1) { @@ -106,13 +153,13 @@ int swaynag_parse_options(int argc, char **argv, struct swaynag *swaynag, } break; case 'e': // Edge - if (swaynag) { + if (type) { if (strcmp(optarg, "top") == 0) { - swaynag->anchors = ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP + type->anchors = ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP | ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT | ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT; } else if (strcmp(optarg, "bottom") == 0) { - swaynag->anchors = ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM + type->anchors = ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM | ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT | ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT; } else { @@ -122,9 +169,9 @@ int swaynag_parse_options(int argc, char **argv, struct swaynag *swaynag, } break; case 'f': // Font - if (swaynag) { - free(swaynag->font); - swaynag->font = strdup(optarg); + if (type) { + free(type->font); + type->font = strdup(optarg); } break; case 'l': // Detailed Message @@ -148,9 +195,9 @@ int swaynag_parse_options(int argc, char **argv, struct swaynag *swaynag, } break; case 'o': // Output - if (swaynag) { - free(swaynag->output.name); - swaynag->output.name = strdup(optarg); + if (type) { + free(type->output); + type->output = strdup(optarg); } break; case 's': // Dismiss Button Text @@ -173,6 +220,71 @@ int swaynag_parse_options(int argc, char **argv, struct swaynag *swaynag, case 'v': // Version fprintf(stdout, "swaynag version " SWAY_VERSION "\n"); return -1; + case TO_COLOR_BACKGROUND: // Background color + if (type) { + type->background = parse_color(optarg); + } + break; + case TO_COLOR_BORDER: // Border color + if (type) { + type->border = parse_color(optarg); + } + break; + case TO_COLOR_BORDER_BOTTOM: // Bottom border color + if (type) { + type->border_bottom = parse_color(optarg); + } + break; + case TO_COLOR_BUTTON: // Button background color + if (type) { + type->button_background = parse_color(optarg); + } + break; + case TO_COLOR_TEXT: // Text color + if (type) { + type->text = parse_color(optarg); + } + break; + case TO_THICK_BAR_BORDER: // Bottom border thickness + if (type) { + type->bar_border_thickness = strtol(optarg, NULL, 0); + } + break; + case TO_PADDING_MESSAGE: // Message padding + if (type) { + type->message_padding = strtol(optarg, NULL, 0); + } + break; + case TO_THICK_DET_BORDER: // Details border thickness + if (type) { + type->details_border_thickness = strtol(optarg, NULL, 0); + } + break; + case TO_THICK_BTN_BORDER: // Button border thickness + if (type) { + type->button_border_thickness = strtol(optarg, NULL, 0); + } + break; + case TO_GAP_BTN: // Gap between buttons + if (type) { + type->button_gap = strtol(optarg, NULL, 0); + } + break; + case TO_GAP_BTN_DISMISS: // Gap between dismiss button + if (type) { + type->button_gap_close = strtol(optarg, NULL, 0); + } + break; + case TO_MARGIN_BTN_RIGHT: // Margin on the right side of button area + if (type) { + type->button_margin_right = strtol(optarg, NULL, 0); + } + break; + case TO_PADDING_BTN: // Padding for the button text + if (type) { + type->button_padding = strtol(optarg, NULL, 0); + } + break; default: // Help or unknown flag fprintf(c == 'h' ? stdout : stderr, "%s", usage); return -1; @@ -229,7 +341,12 @@ int swaynag_load_config(char *path, struct swaynag *swaynag, list_t *types) { fprintf(stderr, "Failed to read config. Running without it.\n"); return 0; } - struct swaynag_type *type = NULL; + + struct swaynag_type *type; + type = calloc(1, sizeof(struct swaynag_type)); + type->name = strdup(""); + list_add(types, type); + char *line; int line_number = 0; while (!feof(config)) { @@ -271,12 +388,8 @@ int swaynag_load_config(char *path, struct swaynag *swaynag, list_t *types) { sprintf(flag, "--%s", line); char *argv[] = {"swaynag", flag}; int result; - if (type) { - result = swaynag_parse_type(2, argv, type); - } else { - result = swaynag_parse_options(2, argv, swaynag, types, - NULL, NULL); - } + result = swaynag_parse_options(2, argv, swaynag, types, type, + NULL, NULL); if (result != 0) { free(line); fclose(config); diff --git a/swaynag/main.c b/swaynag/main.c index 0493c1f0..20d03c31 100644 --- a/swaynag/main.c +++ b/swaynag/main.c @@ -5,7 +5,6 @@ #include "swaynag/config.h" #include "swaynag/swaynag.h" #include "swaynag/types.h" -#include "wlr-layer-shell-unstable-v1-client-protocol.h" static struct swaynag swaynag; @@ -26,10 +25,6 @@ int main(int argc, char **argv) { swaynag_types_add_default(types); memset(&swaynag, 0, sizeof(swaynag)); - swaynag.anchors = ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP - | ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT - | ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT; - swaynag.font = strdup("pango:monospace 10"); swaynag.buttons = create_list(); struct swaynag_button *button_close = @@ -44,7 +39,7 @@ int main(int argc, char **argv) { char *config_path = NULL; bool debug = false; - int launch_status = swaynag_parse_options(argc, argv, NULL, NULL, + int launch_status = swaynag_parse_options(argc, argv, NULL, NULL, NULL, &config_path, &debug); if (launch_status != 0) { exit_code = launch_status; @@ -66,8 +61,13 @@ int main(int argc, char **argv) { } if (argc > 1) { + struct swaynag_type *type_args; + type_args = calloc(1, sizeof(struct swaynag_type)); + type_args->name = strdup(""); + list_add(types, type_args); + int result = swaynag_parse_options(argc, argv, &swaynag, types, - NULL, NULL); + type_args, NULL, NULL); if (result != 0) { exit_code = result; goto cleanup; @@ -84,7 +84,20 @@ int main(int argc, char **argv) { swaynag.type = swaynag_type_get(types, "error"); } - swaynag.type = swaynag_type_clone(swaynag.type); + // Construct a new type using the config defaults as base, then merging + // config type defaults on top, then merging arguments on top of that, and + // finally merging defaults on top. + struct swaynag_type *type = calloc(1, sizeof(struct swaynag_type)); + type->name = strdup(swaynag.type->name); + swaynag_type_merge(type, swaynag_type_get(types, "")); + swaynag_type_merge(type, swaynag.type); + swaynag_type_merge(type, swaynag_type_get(types, "")); + swaynag_type_merge(type, swaynag_type_get(types, "")); + swaynag.type = type; + if (swaynag.type->output) { + swaynag.output.name = strdup(swaynag.type->output); + } + swaynag_types_free(types); if (swaynag.details.message) { @@ -94,10 +107,10 @@ int main(int argc, char **argv) { } wlr_log(WLR_DEBUG, "Output: %s", swaynag.output.name); - wlr_log(WLR_DEBUG, "Anchors: %d", swaynag.anchors); + wlr_log(WLR_DEBUG, "Anchors: %d", swaynag.type->anchors); wlr_log(WLR_DEBUG, "Type: %s", swaynag.type->name); wlr_log(WLR_DEBUG, "Message: %s", swaynag.message); - wlr_log(WLR_DEBUG, "Font: %s", swaynag.font); + wlr_log(WLR_DEBUG, "Font: %s", swaynag.type->font); wlr_log(WLR_DEBUG, "Buttons"); for (int i = 0; i < swaynag.buttons->length; i++) { struct swaynag_button *button = swaynag.buttons->items[i]; diff --git a/swaynag/render.c b/swaynag/render.c index 67e26eaf..bc3e520e 100644 --- a/swaynag/render.c +++ b/swaynag/render.c @@ -9,13 +9,13 @@ static uint32_t render_message(cairo_t *cairo, struct swaynag *swaynag) { uint32_t height = swaynag->height * swaynag->scale; - height -= SWAYNAG_BAR_BORDER_THICKNESS * swaynag->scale; + height -= swaynag->type->bar_border_thickness * swaynag->scale; int text_width, text_height; - get_text_size(cairo, swaynag->font, &text_width, &text_height, + get_text_size(cairo, swaynag->type->font, &text_width, &text_height, swaynag->scale, true, "%s", swaynag->message); - int padding = SWAYNAG_MESSAGE_PADDING * swaynag->scale; + int padding = swaynag->type->message_padding * swaynag->scale; uint32_t ideal_height = text_height + padding * 2; uint32_t ideal_surface_height = ideal_height / swaynag->scale; @@ -25,7 +25,7 @@ static uint32_t render_message(cairo_t *cairo, struct swaynag *swaynag) { cairo_set_source_u32(cairo, swaynag->type->text); cairo_move_to(cairo, padding, (int)(ideal_height - text_height) / 2); - pango_printf(cairo, swaynag->font, swaynag->scale, false, "%s", + pango_printf(cairo, swaynag->type->font, swaynag->scale, false, "%s", swaynag->message); return ideal_height; @@ -34,11 +34,11 @@ static uint32_t render_message(cairo_t *cairo, struct swaynag *swaynag) { static void render_details_scroll_button(cairo_t *cairo, struct swaynag *swaynag, struct swaynag_button *button) { int text_width, text_height; - get_text_size(cairo, swaynag->font, &text_width, &text_height, + get_text_size(cairo, swaynag->type->font, &text_width, &text_height, swaynag->scale, true, "%s", button->text); - int border = SWAYNAG_BUTTON_BORDER_THICKNESS * swaynag->scale; - int padding = SWAYNAG_BUTTON_PADDING * swaynag->scale; + int border = swaynag->type->button_border_thickness * swaynag->scale; + int padding = swaynag->type->button_padding * swaynag->scale; cairo_set_source_u32(cairo, swaynag->type->border); cairo_rectangle(cairo, button->x, button->y, @@ -53,21 +53,21 @@ static void render_details_scroll_button(cairo_t *cairo, cairo_set_source_u32(cairo, swaynag->type->text); cairo_move_to(cairo, button->x + border + padding, button->y + border + (button->height - text_height) / 2); - pango_printf(cairo, swaynag->font, swaynag->scale, true, + pango_printf(cairo, swaynag->type->font, swaynag->scale, true, "%s", button->text); } static int get_detailed_scroll_button_width(cairo_t *cairo, struct swaynag *swaynag) { int up_width, down_width, temp_height; - get_text_size(cairo, swaynag->font, &up_width, &temp_height, + get_text_size(cairo, swaynag->type->font, &up_width, &temp_height, swaynag->scale, true, "%s", swaynag->details.button_up.text); - get_text_size(cairo, swaynag->font, &down_width, &temp_height, + get_text_size(cairo, swaynag->type->font, &down_width, &temp_height, swaynag->scale, true, "%s", swaynag->details.button_down.text); int text_width = up_width > down_width ? up_width : down_width; - int border = SWAYNAG_BUTTON_BORDER_THICKNESS * swaynag->scale; - int padding = SWAYNAG_BUTTON_PADDING * swaynag->scale; + int border = swaynag->type->button_border_thickness * swaynag->scale; + int padding = swaynag->type->button_padding * swaynag->scale; return text_width + border * 2 + padding * 2; } @@ -76,17 +76,17 @@ static uint32_t render_detailed(cairo_t *cairo, struct swaynag *swaynag, uint32_t y) { uint32_t width = swaynag->width * swaynag->scale; uint32_t height = swaynag->height * swaynag->scale; - height -= SWAYNAG_BAR_BORDER_THICKNESS * swaynag->scale; + height -= swaynag->type->bar_border_thickness * swaynag->scale; - int border = SWAYNAG_DETAILS_BORDER_THICKNESS * swaynag->scale; - int padding = SWAYNAG_MESSAGE_PADDING * swaynag->scale; + int border = swaynag->type->details_border_thickness * swaynag->scale; + int padding = swaynag->type->message_padding * swaynag->scale; int decor = padding + border; swaynag->details.x = decor; swaynag->details.y = y + decor; swaynag->details.width = width - decor * 2; - PangoLayout *layout = get_pango_layout(cairo, swaynag->font, + PangoLayout *layout = get_pango_layout(cairo, swaynag->type->font, swaynag->details.message, swaynag->scale, false); pango_layout_set_width(layout, (swaynag->details.width - padding * 2) * PANGO_SCALE); @@ -173,15 +173,15 @@ static uint32_t render_detailed(cairo_t *cairo, struct swaynag *swaynag, static uint32_t render_button(cairo_t *cairo, struct swaynag *swaynag, int button_index, int *x) { uint32_t height = swaynag->height * swaynag->scale; - height -= SWAYNAG_BAR_BORDER_THICKNESS * swaynag->scale; + height -= swaynag->type->bar_border_thickness * swaynag->scale; struct swaynag_button *button = swaynag->buttons->items[button_index]; int text_width, text_height; - get_text_size(cairo, swaynag->font, &text_width, &text_height, + get_text_size(cairo, swaynag->type->font, &text_width, &text_height, swaynag->scale, true, "%s", button->text); - int border = SWAYNAG_BUTTON_BORDER_THICKNESS * swaynag->scale; - int padding = SWAYNAG_BUTTON_PADDING * swaynag->scale; + int border = swaynag->type->button_border_thickness * swaynag->scale; + int padding = swaynag->type->button_padding * swaynag->scale; uint32_t ideal_height = text_height + padding * 2 + border * 2; uint32_t ideal_surface_height = ideal_height / swaynag->scale; @@ -206,7 +206,7 @@ static uint32_t render_button(cairo_t *cairo, struct swaynag *swaynag, cairo_set_source_u32(cairo, swaynag->type->text); cairo_move_to(cairo, button->x + padding, button->y + padding); - pango_printf(cairo, swaynag->font, swaynag->scale, true, + pango_printf(cairo, swaynag->type->font, swaynag->scale, true, "%s", button->text); *x = button->x - border; @@ -224,13 +224,14 @@ static uint32_t render_to_cairo(cairo_t *cairo, struct swaynag *swaynag) { uint32_t h = render_message(cairo, swaynag); max_height = h > max_height ? h : max_height; - int x = (swaynag->width - SWAYNAG_BUTTON_MARGIN_RIGHT) * swaynag->scale; + int x = swaynag->width - swaynag->type->button_margin_right; + x *= swaynag->scale; for (int i = 0; i < swaynag->buttons->length; i++) { h = render_button(cairo, swaynag, i, &x); max_height = h > max_height ? h : max_height; - x -= SWAYNAG_BUTTON_GAP * swaynag->scale; + x -= swaynag->type->button_gap * swaynag->scale; if (i == 0) { - x -= SWAYNAG_BUTTON_GAP_CLOSE * swaynag->scale; + x -= swaynag->type->button_gap_close * swaynag->scale; } } @@ -239,7 +240,7 @@ static uint32_t render_to_cairo(cairo_t *cairo, struct swaynag *swaynag) { max_height = h > max_height ? h : max_height; } - int border = SWAYNAG_BAR_BORDER_THICKNESS * swaynag->scale; + int border = swaynag->type->bar_border_thickness * swaynag->scale; if (max_height > swaynag->height) { max_height += border; } diff --git a/swaynag/swaynag.1.scd b/swaynag/swaynag.1.scd index 7d250a45..12787c3c 100644 --- a/swaynag/swaynag.1.scd +++ b/swaynag/swaynag.1.scd @@ -45,14 +45,12 @@ _swaynag_ [options...] Set the message text. *-o, --output* - Set the output to use. This should be the name of a _xdg\_output_. If - _xdg\_output\_manager_ is not supported, then the first detected output - will be used + Set the output to use. This should be the name of a _xdg\_output_. *-s, --dismiss-button* Sets the text for the dismiss nagbar button. The default is _X_. -*-t, --type* +*-t, --type* Set the message type. Two types are created by default _error_ and _warning_. Custom types can be defined in the config file. See _--config_ and swaynag(5) for details. Both of the default types can be @@ -61,5 +59,45 @@ _swaynag_ [options...] *-v, --version* Show the version number and quit. +# APPEARANCE OPTIONS +*--background* + Set the color of the background. + +*--border* + Set the color of the border. + +*--border-bottom* + Set the color of the bottom border. + +*--button-background* + Set the color for the background for buttons. + +*--text* + Set the text color. + +*--border-bottom-size* + Set the thickness of the bottom border. + +*--message-padding* + Set the padding for the message. + +*--details-border-size* + Set the thickness for the details border. + +*--button-border-size* + Set the thickness for the button border. + +*--button-gap* + Set the size of the gap between buttons. + +*--button-dismiss-gap* + Set the size of the gap between the dismiss button and another button. + +*--button-margin-right* + Set the margin from the right of the dismiss button to edge. + +*--button-padding* + Set the padding for the button text. + # SEE swaynag(5) diff --git a/swaynag/swaynag.5.scd b/swaynag/swaynag.5.scd index a4e05e3a..e2348d8b 100644 --- a/swaynag/swaynag.5.scd +++ b/swaynag/swaynag.5.scd @@ -20,37 +20,77 @@ following format: ``` [name-of-type] -color=RRGGBB[AA] +option=value ``` All colors may be given in the form _RRGGBB_ or _RRGGBBAA_. The following colors can be set: -*background* +*background=* The background color for _swaynag_. -*border* +*border=* The color to use for borders of buttons. -*border-bottom* +*border-bottom=* The color of the border line at the bottom of _swaynag_. -*button-background* +*button-background=* The background color for the buttons. -*text* +*text=* The color of the text. +The following sizing options can also be set: + +*border-bottom-size=* + Set the thickness of the bottom border. + +*message-padding=* + Set the padding for the message. + +*details-border-size=* + Set the thickness for the details border. + +*button-border-size=* + Set the thickness for the button border. + +*button-gap=* + Set the size of the gap between buttons. + +*button-dismiss-gap=* + Set the size of the gap between the dismiss button and another button. + +*button-margin-right=* + Set the margin from the right of the dismiss button to edge. + +*button-padding=* + Set the padding for the button text. + +Additionally, the following options can be assigned a default per-type: + +*edge=top|bottom* + Set the edge to use. + +*font=* + Set the font to use. + +*output=* + Set the output to use. This should be the name of a _xdg\_output_. + # EXAMPLE ``` font=Monospace 12 +edge=bottom [green] +edge=top background=00AA00 border=006600 border-bottom=004400 text=FFFFFF button-background=00CC00 +message-padding=10 ``` # SEE diff --git a/swaynag/swaynag.c b/swaynag/swaynag.c index e5d2e216..e79cd879 100644 --- a/swaynag/swaynag.c +++ b/swaynag/swaynag.c @@ -345,7 +345,8 @@ void swaynag_setup(struct swaynag *swaynag) { assert(swaynag->layer_surface); zwlr_layer_surface_v1_add_listener(swaynag->layer_surface, &layer_surface_listener, swaynag); - zwlr_layer_surface_v1_set_anchor(swaynag->layer_surface, swaynag->anchors); + zwlr_layer_surface_v1_set_anchor(swaynag->layer_surface, + swaynag->type->anchors); wl_registry_destroy(registry); } @@ -363,7 +364,6 @@ void swaynag_destroy(struct swaynag *swaynag) { swaynag->run_display = false; free(swaynag->message); - free(swaynag->font); while (swaynag->buttons->length) { struct swaynag_button *button = swaynag->buttons->items[0]; list_del(swaynag->buttons, 0); diff --git a/swaynag/types.c b/swaynag/types.c index c92d0e89..f429baf0 100644 --- a/swaynag/types.c +++ b/swaynag/types.c @@ -9,8 +9,26 @@ #include "swaynag/config.h" #include "swaynag/types.h" #include "util.h" +#include "wlr-layer-shell-unstable-v1-client-protocol.h" void swaynag_types_add_default(list_t *types) { + struct swaynag_type *type_defaults; + type_defaults = calloc(1, sizeof(struct swaynag_type)); + type_defaults->name = strdup(""); + type_defaults->font = strdup("pango:Monospace 10"); + type_defaults->anchors = ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP + | ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT + | ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT; + type_defaults->bar_border_thickness = 2; + type_defaults->message_padding = 8; + type_defaults->details_border_thickness = 3; + type_defaults->button_border_thickness = 3; + type_defaults->button_gap = 20; + type_defaults->button_gap_close = 15; + type_defaults->button_margin_right = 2; + type_defaults->button_padding = 3; + list_add(types, type_defaults); + struct swaynag_type *type_error; type_error = calloc(1, sizeof(struct swaynag_type)); type_error->name = strdup("error"); @@ -42,20 +60,84 @@ struct swaynag_type *swaynag_type_get(list_t *types, char *name) { return NULL; } -struct swaynag_type *swaynag_type_clone(struct swaynag_type *type) { - struct swaynag_type *clone; - clone = calloc(1, sizeof(struct swaynag_type)); - clone->name = strdup(type->name); - clone->button_background = type->button_background; - clone->background = type->background; - clone->text = type->text; - clone->border = type->border; - clone->border_bottom = type->border_bottom; - return clone; +void swaynag_type_merge(struct swaynag_type *dest, struct swaynag_type *src) { + if (!dest || !src) { + return; + } + + if (!dest->font && src->font) { + dest->font = strdup(src->font); + } + + if (!dest->output && src->output) { + dest->output = strdup(src->output); + } + + if (dest->anchors == 0 && src->anchors > 0) { + dest->anchors = src->anchors; + } + + // Colors + if (dest->button_background == 0 && src->button_background > 0) { + dest->button_background = src->button_background; + } + + if (dest->background == 0 && src->background > 0) { + dest->background = src->background; + } + + if (dest->text == 0 && src->text > 0) { + dest->text = src->text; + } + + if (dest->border == 0 && src->border > 0) { + dest->border = src->border; + } + + if (dest->border_bottom == 0 && src->border_bottom > 0) { + dest->border_bottom = src->border_bottom; + } + + // Sizing + if (dest->bar_border_thickness == 0 && src->bar_border_thickness > 0) { + dest->bar_border_thickness = src->bar_border_thickness; + } + + if (dest->message_padding == 0 && src->message_padding > 0) { + dest->message_padding = src->message_padding; + } + + if (dest->details_border_thickness == 0 + && src->details_border_thickness > 0) { + dest->details_border_thickness = src->details_border_thickness; + } + + if (dest->button_border_thickness == 0 + && src->button_border_thickness > 0) { + dest->button_border_thickness = src->button_border_thickness; + } + + if (dest->button_gap == 0 && src->button_gap > 0) { + dest->button_gap = src->button_gap; + } + + if (dest->button_gap_close == 0 && src->button_gap_close > 0) { + dest->button_gap_close = src->button_gap_close; + } + + if (dest->button_margin_right == 0 && src->button_margin_right > 0) { + dest->button_margin_right = src->button_margin_right; + } + + if (dest->button_padding == 0 && src->button_padding > 0) { + dest->button_padding = src->button_padding; + } } void swaynag_type_free(struct swaynag_type *type) { free(type->name); + free(type->font); + free(type->output); free(type); } @@ -67,51 +149,3 @@ void swaynag_types_free(list_t *types) { } list_free(types); } - -int swaynag_parse_type(int argc, char **argv, struct swaynag_type *type) { - enum color_option { - COLOR_BACKGROUND, - COLOR_BORDER, - COLOR_BORDER_BOTTOM, - COLOR_BUTTON, - COLOR_TEXT, - }; - - static struct option opts[] = { - {"background", required_argument, NULL, COLOR_BACKGROUND}, - {"border", required_argument, NULL, COLOR_BORDER}, - {"border-bottom", required_argument, NULL, COLOR_BORDER_BOTTOM}, - {"button-background", required_argument, NULL, COLOR_BUTTON}, - {"text", required_argument, NULL, COLOR_TEXT}, - {0, 0, 0, 0} - }; - - optind = 1; - while (1) { - int c = getopt_long(argc, argv, "", opts, NULL); - if (c == -1) { - break; - } - switch (c) { - case COLOR_BACKGROUND: - type->background = parse_color(optarg); - break; - case COLOR_BORDER: - type->border = parse_color(optarg); - break; - case COLOR_BORDER_BOTTOM: - type->border_bottom = parse_color(optarg); - break; - case COLOR_BUTTON: - type->button_background = parse_color(optarg); - break; - case COLOR_TEXT: - type->text = parse_color(optarg); - break; - default: - break; - } - } - return 0; -} - -- cgit v1.2.3 From 41d858b4397f1c89a13900f078854e28ea0ac45a Mon Sep 17 00:00:00 2001 From: Brian Ashworth Date: Mon, 30 Jul 2018 15:17:51 -0400 Subject: swaynag: add blank lines after headings in scdocs --- swaynag/swaynag.1.scd | 3 +++ swaynag/swaynag.5.scd | 3 +++ 2 files changed, 6 insertions(+) (limited to 'swaynag/swaynag.1.scd') diff --git a/swaynag/swaynag.1.scd b/swaynag/swaynag.1.scd index 12787c3c..1c395aee 100644 --- a/swaynag/swaynag.1.scd +++ b/swaynag/swaynag.1.scd @@ -9,6 +9,7 @@ swaynag - Show a warning or error message with buttons _swaynag_ [options...] # OPTIONS + *-b, --button* Create a button with the text _text_ that executes _action_ when pressed. Multiple buttons can be defined by providing the flag multiple times. @@ -60,6 +61,7 @@ _swaynag_ [options...] Show the version number and quit. # APPEARANCE OPTIONS + *--background* Set the color of the background. @@ -100,4 +102,5 @@ _swaynag_ [options...] Set the padding for the button text. # SEE + swaynag(5) diff --git a/swaynag/swaynag.5.scd b/swaynag/swaynag.5.scd index e2348d8b..d3daadf7 100644 --- a/swaynag/swaynag.5.scd +++ b/swaynag/swaynag.5.scd @@ -10,6 +10,7 @@ $HOME/.swaynag/config, $XDG\_CONFIG\_HOME/swaynag/config, SYSCONFDIR/swaynag/config # CONFIG FILE + At the top of the config file, _swaynag_ options can be set using the format _long-option=value_. These will be used as default values if _swaynag_ is not given the option. This can be useful for setting a preferred font, output, and @@ -79,6 +80,7 @@ Additionally, the following options can be assigned a default per-type: Set the output to use. This should be the name of a _xdg\_output_. # EXAMPLE + ``` font=Monospace 12 edge=bottom @@ -94,4 +96,5 @@ message-padding=10 ``` # SEE + swaynag(1) -- cgit v1.2.3