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

Add support for "top" option to icon_position rule and hide_text rule #985

Merged
merged 21 commits into from
Jan 22, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
536adf0
add icon_position rule, add top as possible value
m-bartlett Jan 8, 2022
7f9db5a
support ICON_TOP initial implementation
m-bartlett Jan 9, 2022
39a7d1c
center progress bar
m-bartlett Jan 10, 2022
4357000
remove commented lines
m-bartlett Jan 15, 2022
46c691e
add hide_text notification rule and documentation
m-bartlett Jan 15, 2022
7d5f465
change icon_position to enum in notification struct
m-bartlett Jan 15, 2022
bc91854
implement hide_text compatibily with icon_position
m-bartlett Jan 15, 2022
0e388bb
add test for icon_position & hide_text
m-bartlett Jan 16, 2022
5ef58f6
minor formatting
m-bartlett Jan 16, 2022
cfada42
simplify hide_text boolean checks
m-bartlett Jan 16, 2022
87a8b60
simplify ternary width check
m-bartlett Jan 16, 2022
db460c7
remove unintentional newline
m-bartlett Jan 16, 2022
1c1e89b
remove icon_position global setting
m-bartlett Jan 17, 2022
20d2ffe
use default icons for icon_position & hide_text tests
m-bartlett Jan 17, 2022
4bdf2ab
use text_icon_padding when icon_position == ICON_TOP
m-bartlett Jan 17, 2022
cf3393e
undo enum init leading to incorrect default overriding
m-bartlett Jan 17, 2022
80a7e28
fix config with incorrect enum init default values
m-bartlett Jan 17, 2022
903719c
simplify layout_get_height
m-bartlett Jan 22, 2022
e0189e6
restore text_icon_padding functions with icon-conditionals
m-bartlett Jan 22, 2022
7d56731
default icon_position = left
m-bartlett Jan 22, 2022
b20544a
add padding demonstration to icon_position tests
m-bartlett Jan 22, 2022
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
9 changes: 8 additions & 1 deletion docs/dunst.5.pod
Original file line number Diff line number Diff line change
Expand Up @@ -364,7 +364,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 @@ -884,6 +884,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;
m-bartlett marked this conversation as resolved.
Show resolved Hide resolved
} 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,
fwsmit marked this conversation as resolved.
Show resolved Hide resolved
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 @@ -417,6 +417,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 @@ -36,6 +36,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 @@ -46,6 +48,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