Skip to content

Commit

Permalink
Merge pull request #985 from m-bartlett/master
Browse files Browse the repository at this point in the history
Add support for "top" option to icon_position rule and hide_text rule
  • Loading branch information
fwsmit authored Jan 22, 2022
2 parents aebf99f + b20544a commit 1c3876b
Show file tree
Hide file tree
Showing 14 changed files with 309 additions and 62 deletions.
9 changes: 8 additions & 1 deletion docs/dunst.5.pod
Original file line number Diff line number Diff line change
Expand Up @@ -380,7 +380,7 @@ Hide the count of stacked duplicate notifications.
Show an indicator if a notification contains actions and/or open-able URLs. See
ACTIONS below for further details.

=item B<icon_position> (values: [left/right/off], default: off)
=item B<icon_position> (values: [left/right/top/off], default: left)

Defines the position of the icon in the notification window. Setting it to off
disables icons.
Expand Down Expand Up @@ -908,6 +908,13 @@ Specifies where truncated lines should be ellipsized.

Defines how the text should be aligned within the notification.

=item B<hide_text> (values: [true/false], default: false)

Setting this to true will skip displaying any text related to the notification.
The notification icon and progress bar will still be displayed. This option may
be useful for notifications where an icon or progress bar may be sufficient
information for the notification, such as audio volume or brightness level.

=item B<markup> (values: [full/strip/no], default: no)

Defines how markup in notifications is handled.
Expand Down
4 changes: 3 additions & 1 deletion dunstrc
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@

### Icons ###

# Align icons left/right/off
# Align icons left/right/top/off
icon_position = left

# Scale small icons up to this size, set to 0 to disable. Helpful
Expand Down Expand Up @@ -339,12 +339,14 @@
# set_category
# timeout
# urgency
# icon_position
# skip_display
# history_ignore
# action_name
# word_wrap
# ellipsize
# alignment
# hide_text
#
# Shell-like globbing will get expanded.
#
Expand Down
127 changes: 88 additions & 39 deletions src/draw.c
Original file line number Diff line number Diff line change
Expand Up @@ -167,15 +167,28 @@ static struct color layout_get_sepcolor(struct colored_layout *cl,
}
}

static int get_text_icon_padding()
static int get_horizontal_text_icon_padding(struct notification *n)
{
if (settings.text_icon_padding) {
bool horizontal_icon = (
n->icon && (n->icon_position == ICON_LEFT || n->icon_position == ICON_RIGHT)
);
if (settings.text_icon_padding && horizontal_icon) {
return settings.text_icon_padding;
} else {
return settings.h_padding;
}
}

static int get_vertical_text_icon_padding(struct notification *n)
{
bool vertical_icon = n->icon && (n->icon_position == ICON_TOP);
if (settings.text_icon_padding && vertical_icon) {
return settings.text_icon_padding;
} else {
return settings.padding;
}
}

static bool have_progress_bar(const struct colored_layout *cl)
{
return (cl->n->progress >= 0 && settings.progress_bar == true &&
Expand Down Expand Up @@ -220,8 +233,9 @@ static void layout_setup_pango(PangoLayout *layout, int width, int height,
// @param height Height of the layout
static void layout_setup(struct colored_layout *cl, int width, int height, double scale)
{
int icon_width = cl->icon? get_icon_width(cl->icon, scale) + get_text_icon_padding() : 0;
int text_width = width - icon_width - 2 * settings.h_padding;
int horizontal_padding = get_horizontal_text_icon_padding(cl->n);
int icon_width = cl->icon ? get_icon_width(cl->icon, scale) + horizontal_padding : 0;
int text_width = width - 2 * settings.h_padding - (cl->n->icon_position == ICON_TOP ? 0 : icon_width);
int progress_bar_height = have_progress_bar(cl) ? settings.progress_bar_height + settings.padding : 0;
int max_text_height = MAX(0, settings.height - progress_bar_height - 2 * settings.padding);
layout_setup_pango(cl->l, text_width, max_text_height, cl->n->word_wrap, cl->n->ellipsize, cl->n->alignment);
Expand All @@ -242,12 +256,27 @@ static struct dimensions calculate_notification_dimensions(struct colored_layout
struct dimensions dim = { 0 };
layout_setup(cl, settings.width.max, settings.height, scale);

int icon_width = cl->icon? get_icon_width(cl->icon, scale) + get_text_icon_padding() : 0;
int horizontal_padding = get_horizontal_text_icon_padding(cl->n);
int icon_width = cl->icon? get_icon_width(cl->icon, scale) + horizontal_padding : 0;
int icon_height = cl->icon? get_icon_height(cl->icon, scale) : 0;
int progress_bar_height = have_progress_bar(cl) ? settings.progress_bar_height + settings.padding : 0;
get_text_size(cl->l, &dim.text_width, &dim.text_height, scale);

dim.h = MAX(icon_height, dim.text_height);
int vertical_padding;
if (cl->n->hide_text) {
vertical_padding = 0;
dim.text_width = 0;
dim.text_height = 0;
} else {
get_text_size(cl->l, &dim.text_width, &dim.text_height, scale);
vertical_padding = get_vertical_text_icon_padding(cl->n);
}

if (cl->n->icon_position == ICON_TOP && cl->n->icon) {
dim.h = icon_height + dim.text_height + vertical_padding;
} else {
dim.h = MAX(icon_height, dim.text_height);
}

dim.h += progress_bar_height;
dim.w = dim.text_width + icon_width + 2 * settings.h_padding;

Expand Down Expand Up @@ -335,7 +364,7 @@ static struct colored_layout *layout_from_notification(cairo_t *c, struct notifi

struct colored_layout *cl = layout_init_shared(c, n);

if (settings.icon_position != ICON_OFF && n->icon) {
if (n->icon_position != ICON_OFF && n->icon) {
cl->icon = n->icon;
} else {
cl->icon = NULL;
Expand Down Expand Up @@ -399,18 +428,31 @@ static GSList *create_layouts(cairo_t *c)

static int layout_get_height(struct colored_layout *cl, double scale)
{
int h;
int h_text = 0;
int h_icon = 0;
int h_progress_bar = 0;
get_text_size(cl->l, NULL, &h, scale);

int vertical_padding;
if (cl->n->hide_text) {
vertical_padding = 0;
} else {
get_text_size(cl->l, NULL, &h_text, scale);
vertical_padding = get_vertical_text_icon_padding(cl->n);
}

if (cl->icon)
h_icon = get_icon_height(cl->icon, scale);
if (have_progress_bar(cl)){

if (have_progress_bar(cl)) {
h_progress_bar = settings.progress_bar_height + settings.padding;
}

int res = MAX(h, h_icon) + h_progress_bar;
return res;

if (cl->n->icon_position == ICON_TOP && cl->n->icon) {
return h_icon + h_text + h_progress_bar + vertical_padding;
} else {
return MAX(h_text, h_icon) + h_progress_bar;
}
}

/* Attempt to make internal radius more organic.
Expand Down Expand Up @@ -594,37 +636,41 @@ static void render_content(cairo_t *c, struct colored_layout *cl, int width, dou
const int h = layout_get_height(cl, scale);
LOG_D("Layout height %i", h);
int h_without_progress_bar = h;
if (have_progress_bar(cl)){
if (have_progress_bar(cl)) {
h_without_progress_bar -= settings.progress_bar_height + settings.padding;
}
int h_text;
get_text_size(cl->l, NULL, &h_text, scale);

int text_x = settings.h_padding,
text_y = settings.padding + h_without_progress_bar / 2 - h_text / 2;
if (!cl->n->hide_text) {
int h_text = 0;
get_text_size(cl->l, NULL, &h_text, scale);

// text positioning
if (cl->icon) {
// vertical alignment
if (settings.vertical_alignment == VERTICAL_TOP) {
text_y = settings.padding;
} else if (settings.vertical_alignment == VERTICAL_BOTTOM) {
text_y = h_without_progress_bar + settings.padding - h_text;
if (text_y < 0)
int text_x = settings.h_padding,
text_y = settings.padding + h_without_progress_bar / 2 - h_text / 2;

// text positioning
if (cl->icon) {
// vertical alignment
if (settings.vertical_alignment == VERTICAL_TOP) {
text_y = settings.padding;
} // else VERTICAL_CENTER
} else if (settings.vertical_alignment == VERTICAL_BOTTOM) {
text_y = h_without_progress_bar + settings.padding - h_text;
if (text_y < 0)
text_y = settings.padding;
} // else VERTICAL_CENTER

// icon position
if (cl->n->icon_position == ICON_LEFT) {
text_x = get_icon_width(cl->icon, scale) + settings.h_padding + get_horizontal_text_icon_padding(cl->n);
} else if (cl->n->icon_position == ICON_TOP) {
text_y = get_icon_height(cl->icon, scale) + settings.padding + get_vertical_text_icon_padding(cl->n);
} // else ICON_RIGHT
}
cairo_move_to(c, round(text_x * scale), round(text_y * scale));

// icon position
if (settings.icon_position == ICON_LEFT) {
text_x = get_icon_width(cl->icon, scale) + settings.h_padding + get_text_icon_padding();
} // else ICON_RIGHT
cairo_set_source_rgba(c, cl->fg.r, cl->fg.g, cl->fg.b, cl->fg.a);
pango_cairo_update_layout(c, cl->l);
pango_cairo_show_layout(c, cl->l);
}
cairo_move_to(c, round(text_x * scale), round(text_y * scale));

cairo_set_source_rgba(c, cl->fg.r, cl->fg.g, cl->fg.b, cl->fg.a);
pango_cairo_update_layout(c, cl->l);
pango_cairo_show_layout(c, cl->l);


// icon positioning
if (cl->icon) {
Expand All @@ -643,8 +689,11 @@ static void render_content(cairo_t *c, struct colored_layout *cl, int width, dou
} // else VERTICAL_CENTER

// icon position
if (settings.icon_position == ICON_LEFT) {
if (cl->n->icon_position == ICON_LEFT) {
image_x = settings.h_padding;
} else if (cl->n->icon_position == ICON_TOP) {
image_y = settings.padding;
image_x = width/2 - image_width/2;
} // else ICON_RIGHT

cairo_set_source_surface(c, cl->icon, round(image_x * scale), round(image_y * scale));
Expand All @@ -658,7 +707,7 @@ static void render_content(cairo_t *c, struct colored_layout *cl, int width, dou
unsigned int frame_width = settings.progress_bar_frame_width,
progress_width = MIN(width - 2 * settings.h_padding, settings.progress_bar_max_width),
progress_height = settings.progress_bar_height - frame_width,
frame_x = settings.h_padding,
frame_x = width/2 - progress_width/2,
frame_y = settings.padding + h - settings.progress_bar_height,
progress_width_without_frame = progress_width - 2 * frame_width,
progress_width_1 = progress_width_without_frame * progress / 100,
Expand Down
4 changes: 3 additions & 1 deletion src/notification.c
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,7 @@ bool notification_is_duplicate(const struct notification *a, const struct notifi
return STR_EQ(a->appname, b->appname)
&& STR_EQ(a->summary, b->summary)
&& STR_EQ(a->body, b->body)
&& (settings.icon_position != ICON_OFF ? STR_EQ(a->icon_id, b->icon_id) : 1)
&& (a->icon_position != ICON_OFF ? STR_EQ(a->icon_id, b->icon_id) : 1)
&& a->urgency == b->urgency;
}

Expand Down Expand Up @@ -419,6 +419,8 @@ struct notification *notification_create(void)
n->word_wrap = true;
n->ellipsize = PANGO_ELLIPSIZE_MIDDLE;
n->alignment = PANGO_ALIGN_LEFT;
n->hide_text = false;
n->icon_position = ICON_LEFT;
n->icon_size = 32;

n->script_run = false;
Expand Down
9 changes: 9 additions & 0 deletions src/notification.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,13 @@

#define DUNST_NOTIF_MAX_CHARS 50000

enum icon_position {
ICON_LEFT,
ICON_RIGHT,
ICON_TOP,
ICON_OFF
};

enum behavior_fullscreen {
FS_NULL, //!< Invalid value
FS_DELAY, //!< Delay the notification until leaving fullscreen mode
Expand Down Expand Up @@ -58,6 +65,7 @@ struct notification {
char *icon_path; /**< Full path to the notification's icon. */
char *default_icon_name; /**< The icon that is used when no other icon is available. */
int icon_size; /**< Size of the icon used for searching the right icon. */
enum icon_position icon_position; /**< Icon position (enum left,right,top,off). */

gint64 start; /**< begin of current display (in milliseconds) */
gint64 timestamp; /**< arrival time (in milliseconds) */
Expand Down Expand Up @@ -92,6 +100,7 @@ struct notification {
bool word_wrap;
PangoEllipsizeMode ellipsize;
PangoAlignment alignment;
bool hide_text;

/* derived fields */
char *msg; /**< formatted message */
Expand Down
4 changes: 4 additions & 0 deletions src/rules.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ void rule_apply(struct rule *r, struct notification *n)
n->ellipsize = r->ellipsize;
if (r->alignment != -1)
n->alignment = r->alignment;
if (r->hide_text != -1)
n->hide_text = r->hide_text;
if (r->action_name) {
g_free(n->default_action_name);
n->default_action_name = g_strdup(r->action_name);
Expand All @@ -47,6 +49,8 @@ void rule_apply(struct rule *r, struct notification *n)
}
if (r->markup != MARKUP_NULL)
n->markup = r->markup;
if (r->icon_position != -1)
n->icon_position = r->icon_position;
if (r->set_icon_size > 0)
n->icon_size = r->set_icon_size;
if (r->fg) {
Expand Down
2 changes: 2 additions & 0 deletions src/rules.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ struct rule {
int word_wrap;
int ellipsize;
int alignment;
int hide_text;
int icon_position;
int set_icon_size;
char *new_icon;
char *fg;
Expand Down
2 changes: 0 additions & 2 deletions src/settings.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
#define LIST_END (-1)

enum alignment { ALIGN_LEFT, ALIGN_CENTER, ALIGN_RIGHT };
enum icon_position { ICON_LEFT, ICON_RIGHT, ICON_OFF };
enum vertical_alignment { VERTICAL_TOP, VERTICAL_CENTER, VERTICAL_BOTTOM };
enum separator_color { SEP_FOREGROUND, SEP_AUTO, SEP_FRAME, SEP_CUSTOM };
enum follow_mode { FOLLOW_NONE, FOLLOW_MOUSE, FOLLOW_KEYBOARD };
Expand Down Expand Up @@ -127,7 +126,6 @@ struct settings {
char **dmenu_cmd;
char *browser;
char **browser_cmd;
enum icon_position icon_position;
enum vertical_alignment vertical_alignment;
int min_icon_size;
int max_icon_size;
Expand Down
Loading

0 comments on commit 1c3876b

Please sign in to comment.