2121#include "settings.h"
2222#include "utils.h"
2323#include "icon-lookup.h"
24+ #include "menu.h"
2425
2526struct 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+
236244static 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+
702774static 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
9271010static struct dimensions layout_render (cairo_surface_t * srf ,
0 commit comments