Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Gradients #1286

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions docs/dunst.5.pod
Original file line number Diff line number Diff line change
Expand Up @@ -847,6 +847,9 @@ The foreground color of the notification. See COLORS for possible values.
The highlight color of the notification. This color is used for coloring the
progress bar. See COLORS for possible values.

Furthermore, you can set additional color values (as a comma-separated list)
to define a linear gradient spanning all the length of the progress bar.

=item C<format>

Equivalent to the C<format> setting.
Expand Down
11 changes: 9 additions & 2 deletions src/dbus.c
Original file line number Diff line number Diff line change
Expand Up @@ -686,8 +686,15 @@ static struct notification *dbus_message_to_notification(const gchar *sender, GV
g_variant_unref(dict_value);
}

if ((dict_value = g_variant_lookup_value(hints, "hlcolor", G_VARIANT_TYPE_STRING))) {
n->colors.highlight = g_variant_dup_string(dict_value, NULL);
if ((dict_value = g_variant_lookup_value(hints, "hlcolor", G_VARIANT_TYPE_STRING_ARRAY))) {
n->colors.highlight = g_variant_dup_strv(dict_value, NULL);
g_variant_unref(dict_value);
} else if ((dict_value = g_variant_lookup_value(hints, "hlcolor", G_VARIANT_TYPE_STRING))) {
char *str = g_variant_dup_string(dict_value, NULL);
if (str != NULL) {
n->colors.highlight = g_malloc0(sizeof(gchar **) * 2);
n->colors.highlight[0] = str;
}
g_variant_unref(dict_value);
}

Expand Down
61 changes: 58 additions & 3 deletions src/draw.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,16 @@ struct color {
double a;
};

struct gradient {
struct color *cs;
zappolowski marked this conversation as resolved.
Show resolved Hide resolved
gsize length;
};

struct colored_layout {
PangoLayout *l;
struct color fg;
struct color bg;
struct color highlight;
struct gradient highlight;
struct color frame;
char *text;
PangoAttrList *attr;
Expand Down Expand Up @@ -120,6 +125,40 @@ static struct color string_to_color(const char *str)
return hex_to_color(0xF, 1);
}

static struct gradient string_to_gradient(char **strv)
{
struct gradient g;
g.length = 0;

if (strv == NULL) {
LOG_W("Invalid empty color gradient string");
g.cs = g_malloc(sizeof(struct color));
g.cs[g.length++] = hex_to_color(0xF, 1);
/* return black (only one color) on error */
} else {
g.cs = g_malloc0(g_strv_length(strv) * sizeof(struct color));
for (int i = 0; strv[i] != NULL; i++) {
char *end, *str = strv[i];
if (STR_EMPTY(str)) continue;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just for understanding: this would mean an empty element would be allowed and yield a opaque black?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am following the previous behavior


uint_fast32_t val = strtoul(str+1, &end, 16);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why uint_fast32_t ... shouldn't it be unsigned long?

Are you using str+1 here to skip the initial #? This should be done, iff it is actually a #.

How about handling of named colors like Yellow? Maybe I'm missing something here, but I couldn't find, where this is handled.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again, i am following the previous behavior (but I don't like it either)

if (end[0] != '\0' && end[1] != '\0') {
LOG_W("Invalid color string: '%s'", str);
continue;
}

switch (end - (str+1)) {
case 3: g.cs[g.length++] = hex_to_color((val << 4) | 0xF, 1); break;
case 6: g.cs[g.length++] = hex_to_color((val << 8) | 0xFF, 2); break;
case 4: g.cs[g.length++] = hex_to_color(val, 1); break;
case 8: g.cs[g.length++] = hex_to_color(val, 2); break;
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There should be a warning, when an incorrectly formatted color was found here.

}
}

return g;
}

static inline double color_apply_delta(double base, double delta)
{
base += delta;
Expand Down Expand Up @@ -248,6 +287,7 @@ static void free_colored_layout(void *data)
struct colored_layout *cl = data;
g_object_unref(cl->l);
pango_attr_list_unref(cl->attr);
g_free(cl->highlight.cs);
g_free(cl->text);
g_free(cl);
}
Expand Down Expand Up @@ -353,7 +393,7 @@ static struct colored_layout *layout_init_shared(cairo_t *c, struct notification

cl->fg = string_to_color(n->colors.fg);
cl->bg = string_to_color(n->colors.bg);
cl->highlight = string_to_color(n->colors.highlight);
cl->highlight = string_to_gradient(n->colors.highlight);
cl->frame = string_to_color(n->colors.frame);
cl->is_xmore = false;

Expand Down Expand Up @@ -857,10 +897,25 @@ static void render_content(cairo_t *c, struct colored_layout *cl, int width, dou
cairo_fill(c);

// top layer (fill)
cairo_set_source_rgba(c, cl->highlight.r, cl->highlight.g, cl->highlight.b, cl->highlight.a);
cairo_pattern_t *pattern;
if (cl->highlight.length == 1) {
pattern = cairo_pattern_create_rgba(cl->highlight.cs[0].r, cl->highlight.cs[0].g,
cl->highlight.cs[0].b, cl->highlight.cs[0].a);
} else {
pattern = cairo_pattern_create_linear(x_bar_1, 0, progress_width_without_frame, 0);
const double step = 1.0 / (cl->highlight.length - 1);

for (int i = 0; i < cl->highlight.length; i++)
cairo_pattern_add_color_stop_rgba(pattern, i * step,
cl->highlight.cs[i].r, cl->highlight.cs[i].g,
cl->highlight.cs[i].b, cl->highlight.cs[i].a);
}

cairo_set_source(c, pattern);
draw_rounded_rect(c, x_bar_1, frame_y, progress_width_1, progress_height,
settings.progress_bar_corner_radius, scale, C_ALL);
cairo_fill(c);
cairo_pattern_destroy(pattern);

// border
cairo_set_source_rgba(c, cl->frame.r, cl->frame.g, cl->frame.b, cl->frame.a);
Expand Down
9 changes: 5 additions & 4 deletions src/notification.c
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,9 @@ void notification_print(const struct notification *n)
printf("\tformatted: '%s'\n", n->msg);
printf("\tfg: %s\n", n->colors.fg);
printf("\tbg: %s\n", n->colors.bg);
printf("\thighlight: %s\n", n->colors.highlight);
printf("\tframe: %s\n", n->colors.frame);
printf("\thighlight: ");
for (int i = 0; n->colors.highlight[i]; i++) printf("%s ", n->colors.highlight[i]);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit pick: this would leave a trailing white space and moving the line break to the following entry seems a bit fragile (when lines are moved around). How about something like

gchar *highlight = g_strjoinv(" ", n->colors.highlight);
printf("\thighlight: %s\n", highlight);
g_free(highlight);

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fair enough, I wasn't satisfied with that in the first place

printf("\n\tframe: %s\n", n->colors.frame);
printf("\tfullscreen: %s\n", enum_to_string_fullscreen(n->fullscreen));
printf("\tformat: %s\n", n->format);
printf("\tprogress: %d\n", n->progress);
Expand Down Expand Up @@ -305,7 +306,7 @@ void notification_unref(struct notification *n)
g_free(n->urls);
g_free(n->colors.fg);
g_free(n->colors.bg);
g_free(n->colors.highlight);
g_strfreev(n->colors.highlight);
g_free(n->colors.frame);
g_free(n->stack_tag);
g_free(n->desktop_entry);
Expand Down Expand Up @@ -500,7 +501,7 @@ void notification_init(struct notification *n)
if (!n->colors.bg)
n->colors.bg = g_strdup(defcolors.bg);
if (!n->colors.highlight)
n->colors.highlight = g_strdup(defcolors.highlight);
n->colors.highlight = g_strdupv(defcolors.highlight);
if (!n->colors.frame)
n->colors.frame = g_strdup(defcolors.frame);

Expand Down
2 changes: 1 addition & 1 deletion src/notification.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ struct notification_colors {
char *frame;
char *bg;
char *fg;
char *highlight;
char **highlight;
};

struct notification {
Expand Down
4 changes: 2 additions & 2 deletions src/rules.c
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,8 @@ void rule_apply(struct rule *r, struct notification *n)
n->colors.bg = g_strdup(r->bg);
}
if (r->highlight) {
g_free(n->colors.highlight);
n->colors.highlight = g_strdup(r->highlight);
g_strfreev(n->colors.highlight);
n->colors.highlight = g_strdupv(r->highlight);
}
if (r->fc) {
g_free(n->colors.frame);
Expand Down
2 changes: 1 addition & 1 deletion src/rules.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ struct rule {
char *new_icon;
char *fg;
char *bg;
char *highlight;
char **highlight;
char *default_icon;
char *fc;
char *set_category;
Expand Down
16 changes: 8 additions & 8 deletions src/settings_data.h
Original file line number Diff line number Diff line change
Expand Up @@ -538,11 +538,11 @@ static const struct setting allowed_settings[] = {
.name = "highlight",
.section = "*",
.description = "The highlight color of the notification.",
.type = TYPE_STRING,
.type = TYPE_LIST,
.default_value = "*",
.value = NULL,
.parser = NULL,
.parser_data = NULL,
.parser_data = GINT_TO_POINTER(STRING_LIST),
.rule_offset = offsetof(struct rule, highlight),
},
{
Expand Down Expand Up @@ -1332,11 +1332,11 @@ static const struct setting allowed_settings[] = {
.name = "highlight",
.section = "urgency_low",
.description = "Highlight color for notifications with low urgency",
.type = TYPE_STRING,
.type = TYPE_LIST,
.default_value = "#7f7fff",
.value = &settings.colors_low.highlight,
.parser = NULL,
.parser_data = NULL,
.parser_data = GINT_TO_POINTER(STRING_LIST),
},
{
.name = "frame_color",
Expand Down Expand Up @@ -1382,11 +1382,11 @@ static const struct setting allowed_settings[] = {
.name = "highlight",
.section = "urgency_normal",
.description = "Highlight color for notifications with normal urgency",
.type = TYPE_STRING,
.type = TYPE_LIST,
.default_value = "#1745d1",
.value = &settings.colors_norm.highlight,
.parser = NULL,
.parser_data = NULL,
.parser_data = GINT_TO_POINTER(STRING_LIST),
},
{
.name = "frame_color",
Expand Down Expand Up @@ -1432,11 +1432,11 @@ static const struct setting allowed_settings[] = {
.name = "highlight",
.section = "urgency_critical",
.description = "Highlight color for notifications with ciritical urgency",
.type = TYPE_STRING,
.type = TYPE_LIST,
.default_value = "#ff6666",
.value = &settings.colors_crit.highlight,
.parser = NULL,
.parser_data = NULL,
.parser_data = GINT_TO_POINTER(STRING_LIST),
},
{
.name = "frame_color",
Expand Down
Loading