Skip to content

Commit 0d58450

Browse files
committed
Implement built-in clickable menu rendering
Add menu button drawing function. Update layout calculations for menu height. Integrate menu rendering into notification display. Signed-off-by: LI Qingwu <[email protected]>
1 parent fef0ab4 commit 0d58450

File tree

1 file changed

+91
-8
lines changed

1 file changed

+91
-8
lines changed

src/draw.c

Lines changed: 91 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include "settings.h"
2222
#include "utils.h"
2323
#include "icon-lookup.h"
24+
#include "menu.h"
2425

2526
struct colored_layout {
2627
PangoLayout *l;
@@ -233,6 +234,13 @@ static bool have_progress_bar(const struct colored_layout *cl)
233234
!cl->is_xmore);
234235
}
235236

237+
static bool have_built_in_menu(const struct colored_layout *cl)
238+
{
239+
return (g_hash_table_size(cl->n->actions)>0 &&
240+
settings.built_in_menu == true &&
241+
!cl->is_xmore);
242+
}
243+
236244
static void get_text_size(PangoLayout *l, int *w, int *h, double scale) {
237245
pango_layout_get_pixel_size(l, w, h);
238246
// scale the size down, because it may be rendered at higher DPI
@@ -298,6 +306,7 @@ static struct dimensions calculate_notification_dimensions(struct colored_layout
298306
int icon_width = cl->icon? get_icon_width(cl->icon, scale) + horizontal_padding : 0;
299307
int icon_height = cl->icon? get_icon_height(cl->icon, scale) : 0;
300308
int progress_bar_height = have_progress_bar(cl) ? settings.progress_bar_height + settings.padding : 0;
309+
int menu_height = have_built_in_menu(cl) ? settings.menu_height + settings.padding : 0;
301310

302311
int vertical_padding;
303312
if (cl->n->hide_text) {
@@ -318,6 +327,8 @@ static struct dimensions calculate_notification_dimensions(struct colored_layout
318327
dim.h += progress_bar_height + settings.padding * 2;
319328
dim.w = dim.text_width + icon_width + 2 * settings.h_padding;
320329

330+
dim.h += menu_height + settings.padding * 2;
331+
321332
if (have_progress_bar(cl))
322333
dim.w = MAX(settings.progress_bar_min_width, dim.w);
323334

@@ -442,6 +453,10 @@ static struct colored_layout *layout_from_notification(cairo_t *c, struct notifi
442453
g_error_free(err);
443454
}
444455

456+
if(have_built_in_menu(cl)) {
457+
menu_init(n);
458+
}
459+
445460
n->first_render = false;
446461
return cl;
447462
}
@@ -484,6 +499,7 @@ static int layout_get_height(struct colored_layout *cl, double scale)
484499
int h_text = 0;
485500
int h_icon = 0;
486501
int h_progress_bar = 0;
502+
int h_action_menu = 0;
487503

488504
int vertical_padding;
489505
if (cl->n->hide_text) {
@@ -500,9 +516,13 @@ static int layout_get_height(struct colored_layout *cl, double scale)
500516
h_progress_bar = settings.progress_bar_height + settings.padding;
501517
}
502518

519+
if(have_built_in_menu(cl)){
520+
h_action_menu += settings.menu_height + settings.padding;
521+
}
522+
503523
return (cl->n->icon_position == ICON_TOP && cl->n->icon)
504524
? h_icon + h_text + h_progress_bar + vertical_padding
505-
: MAX(h_text, h_icon) + h_progress_bar;
525+
: MAX(h_text, h_icon) + h_progress_bar + h_action_menu;
506526
}
507527

508528
/* Attempt to make internal radius more organic.
@@ -699,6 +719,58 @@ void draw_rounded_rect(cairo_t *c, float x, float y, int width, int height, int
699719
cairo_close_path(c);
700720
}
701721

722+
static void draw_built_in_menu(cairo_t *c,
723+
struct colored_layout *cl,
724+
int area_x,
725+
int area_y,
726+
int area_width,
727+
int area_height,
728+
double scale)
729+
{
730+
if(!have_built_in_menu(cl))
731+
return;
732+
733+
int buttons = menu_get_count(cl->n);
734+
if (buttons == 0) {
735+
return;
736+
}
737+
738+
int total_gap = settings.padding * (buttons + 1);
739+
740+
int button_width = (area_width - total_gap) / buttons;
741+
if (button_width < settings.menu_min_width) {
742+
button_width = settings.menu_min_width;
743+
}
744+
745+
for (int i = 0; i < buttons; i++) {
746+
char *label = menu_get_label(cl->n, i);
747+
if (label == NULL)
748+
continue;
749+
int x = area_x + settings.padding + i * (button_width + settings.padding);
750+
int y = area_y;
751+
752+
double r = settings.menu_frame_color.r;
753+
double g = settings.menu_frame_color.g;
754+
double b = settings.menu_frame_color.b;
755+
756+
cairo_set_source_rgb(c, r,g,b);
757+
draw_rect(c, x, y, button_width, settings.menu_height, scale);
758+
cairo_fill(c);
759+
760+
cairo_set_source_rgba(c, COLOR(cl, fg.r), COLOR(cl, fg.g), COLOR(cl, fg.b), COLOR(cl, fg.a));
761+
762+
cairo_text_extents_t extents;
763+
cairo_text_extents(c, label, &extents);
764+
765+
double text_x = x + (button_width - extents.width) / 2;
766+
double text_y = y + (settings.menu_height + extents.height) / 2;
767+
768+
cairo_move_to(c, round(text_x * scale), round(text_y * scale));
769+
cairo_show_text(c, label);
770+
menu_set_position(cl->n, i, x, y, button_width, settings.menu_height);
771+
}
772+
}
773+
702774
static cairo_surface_t *render_background(cairo_surface_t *srf,
703775
struct colored_layout *cl,
704776
struct colored_layout *cl_next,
@@ -784,10 +856,12 @@ static void render_content(cairo_t *c, struct colored_layout *cl, int width, int
784856
layout_setup(cl, width, height, scale);
785857

786858
// NOTE: Includes paddings!
787-
int h_without_progress_bar = height;
788-
if (have_progress_bar(cl)) {
789-
h_without_progress_bar -= settings.progress_bar_height + settings.padding;
790-
}
859+
int h_text_and_icon = height;
860+
if (have_progress_bar(cl))
861+
h_text_and_icon -= settings.progress_bar_height + settings.padding;
862+
863+
if (have_built_in_menu(cl))
864+
h_text_and_icon -= settings.menu_height + settings.padding;
791865

792866
int text_h = 0;
793867
if (!cl->n->hide_text) {
@@ -799,9 +873,9 @@ static void render_content(cairo_t *c, struct colored_layout *cl, int width, int
799873
text_y = settings.padding;
800874

801875
if (settings.vertical_alignment == VERTICAL_CENTER) {
802-
text_y = h_without_progress_bar / 2 - text_h / 2;
876+
text_y = h_text_and_icon / 2 - text_h / 2;
803877
} else if (settings.vertical_alignment == VERTICAL_BOTTOM) {
804-
text_y = h_without_progress_bar - settings.padding - text_h;
878+
text_y = h_text_and_icon - settings.padding - text_h;
805879
if (text_y < 0) text_y = settings.padding;
806880
} // else VERTICAL_TOP
807881

@@ -867,7 +941,7 @@ static void render_content(cairo_t *c, struct colored_layout *cl, int width, int
867941
unsigned int frame_width = settings.progress_bar_frame_width,
868942
progress_width = MIN(width - 2 * settings.h_padding, settings.progress_bar_max_width),
869943
progress_height = settings.progress_bar_height - frame_width,
870-
frame_y = h_without_progress_bar,
944+
frame_y = h_text_and_icon,
871945
progress_width_without_frame = progress_width - 2 * frame_width,
872946
progress_width_1 = progress_width_without_frame * progress / 100,
873947
progress_width_2 = progress_width_without_frame - 1;
@@ -922,6 +996,15 @@ static void render_content(cairo_t *c, struct colored_layout *cl, int width, int
922996
scale, settings.progress_bar_corners);
923997
cairo_stroke(c);
924998
}
999+
1000+
if (have_built_in_menu(cl)) {
1001+
int y = h_text_and_icon;
1002+
if (have_progress_bar(cl)) {
1003+
y += settings.progress_bar_height + settings.padding;
1004+
}
1005+
draw_built_in_menu(c, cl, 0, y, width, height, scale);
1006+
}
1007+
9251008
}
9261009

9271010
static struct dimensions layout_render(cairo_surface_t *srf,

0 commit comments

Comments
 (0)