Merge pull request #854 from fwSmit/wayland-hidpi
wayland hidpi support
This commit is contained in:
		
						commit
						b77f76f02e
					
				
							
								
								
									
										121
									
								
								src/draw.c
									
									
									
									
									
								
							
							
						
						
									
										121
									
								
								src/draw.c
									
									
									
									
									
								
							| @ -141,10 +141,11 @@ static struct color layout_get_sepcolor(struct colored_layout *cl, | ||||
| 
 | ||||
| static void layout_setup_pango(PangoLayout *layout, int width) | ||||
| { | ||||
|         int scale = output->get_scale(); | ||||
|         pango_layout_set_wrap(layout, PANGO_WRAP_WORD_CHAR); | ||||
|         pango_layout_set_width(layout, width * PANGO_SCALE); | ||||
|         pango_layout_set_width(layout, width * scale * PANGO_SCALE); | ||||
|         pango_layout_set_font_description(layout, pango_fdesc); | ||||
|         pango_layout_set_spacing(layout, settings.line_height * PANGO_SCALE); | ||||
|         pango_layout_set_spacing(layout, settings.line_height * scale * PANGO_SCALE); | ||||
| 
 | ||||
|         PangoAlignment align; | ||||
|         switch (settings.align) { | ||||
| @ -192,9 +193,20 @@ static bool have_progress_bar(const struct notification *n) | ||||
|         return (n->progress >= 0 && settings.progress_bar == true); | ||||
| } | ||||
| 
 | ||||
| static void get_text_size(PangoLayout *l, int *w, int *h, int scale) { | ||||
|         pango_layout_get_pixel_size(l, w, h); | ||||
|         // scale the size down, because it may be rendered at higher DPI
 | ||||
| 
 | ||||
|         if (w) | ||||
|                 *w /= scale; | ||||
|         if (h) | ||||
|                 *h /= scale; | ||||
| } | ||||
| 
 | ||||
| static struct dimensions calculate_dimensions(GSList *layouts) | ||||
| { | ||||
|         struct dimensions dim = { 0 }; | ||||
|         int scale = output->get_scale(); | ||||
| 
 | ||||
|         const struct screen_info *scr = output->get_active_screen(); | ||||
|         if (have_dynamic_width()) { | ||||
| @ -221,10 +233,10 @@ static struct dimensions calculate_dimensions(GSList *layouts) | ||||
|         for (GSList *iter = layouts; iter; iter = iter->next) { | ||||
|                 struct colored_layout *cl = iter->data; | ||||
|                 int w=0,h=0; | ||||
|                 pango_layout_get_pixel_size(cl->l, &w, &h); | ||||
|                 get_text_size(cl->l, &w, &h, scale); | ||||
|                 if (cl->icon) { | ||||
|                         h = MAX(cairo_image_surface_get_height(cl->icon), h); | ||||
|                         w += cairo_image_surface_get_width(cl->icon) + settings.h_padding; | ||||
|                         h = MAX(get_icon_height(cl->icon, scale), h); | ||||
|                         w += get_icon_width(cl->icon, scale) + settings.h_padding; | ||||
|                 } | ||||
|                 h = MAX(settings.notification_height, h + settings.padding * 2); | ||||
|                 dim.h += h; | ||||
| @ -250,15 +262,15 @@ static struct dimensions calculate_dimensions(GSList *layouts) | ||||
|                         w -= 2 * settings.h_padding; | ||||
|                         w -= 2 * settings.frame_width; | ||||
|                         if (cl->icon) { | ||||
|                                 w -= cairo_image_surface_get_width(cl->icon) + get_text_icon_padding(); | ||||
|                                 w -= get_icon_width(cl->icon, scale) + get_text_icon_padding(); | ||||
|                         } | ||||
|                         layout_setup_pango(cl->l, w); | ||||
| 
 | ||||
|                         /* re-read information */ | ||||
|                         pango_layout_get_pixel_size(cl->l, &w, &h); | ||||
|                         get_text_size(cl->l, &w, &h, scale); | ||||
|                         if (cl->icon) { | ||||
|                                 h = MAX(cairo_image_surface_get_height(cl->icon), h); | ||||
|                                 w += cairo_image_surface_get_width(cl->icon) + settings.h_padding; | ||||
|                                 h = MAX(get_icon_height(cl->icon, scale), h); | ||||
|                                 w += get_icon_width(cl->icon, scale) + settings.h_padding; | ||||
|                         } | ||||
|                         h = MAX(settings.notification_height, h + settings.padding * 2); | ||||
|                         dim.h += h; | ||||
| @ -299,6 +311,7 @@ static struct colored_layout *layout_init_shared(cairo_t *c, const struct notifi | ||||
| { | ||||
|         struct colored_layout *cl = g_malloc(sizeof(struct colored_layout)); | ||||
|         cl->l = layout_create(c); | ||||
|         int scale = output->get_scale(); | ||||
| 
 | ||||
|         if (!settings.word_wrap) { | ||||
|                 PangoEllipsizeMode ellipsize; | ||||
| @ -346,7 +359,7 @@ static struct colored_layout *layout_init_shared(cairo_t *c, const struct notifi | ||||
|                 width -= 2 * settings.h_padding; | ||||
|                 width -= 2 * settings.frame_width; | ||||
|                 if (cl->icon) { | ||||
|                         width -= cairo_image_surface_get_width(cl->icon) + get_text_icon_padding(); | ||||
|                         width -= get_icon_width(cl->icon, scale) + get_text_icon_padding(); | ||||
|                 } | ||||
|                 layout_setup_pango(cl->l, width); | ||||
|         } | ||||
| @ -367,6 +380,7 @@ static struct colored_layout *layout_from_notification(cairo_t *c, struct notifi | ||||
| { | ||||
| 
 | ||||
|         struct colored_layout *cl = layout_init_shared(c, n); | ||||
|         int scale = output->get_scale(); | ||||
| 
 | ||||
|         /* markup */ | ||||
|         GError *err = NULL; | ||||
| @ -388,8 +402,8 @@ static struct colored_layout *layout_from_notification(cairo_t *c, struct notifi | ||||
|         } | ||||
| 
 | ||||
| 
 | ||||
|         pango_layout_get_pixel_size(cl->l, NULL, &(n->displayed_height)); | ||||
|         if (cl->icon) n->displayed_height = MAX(cairo_image_surface_get_height(cl->icon), n->displayed_height); | ||||
|         get_text_size(cl->l, NULL, &(n->displayed_height), scale); | ||||
|         if (cl->icon) n->displayed_height = MAX(get_icon_height(cl->icon, scale), n->displayed_height); | ||||
| 
 | ||||
|         n->displayed_height = n->displayed_height + settings.padding * 2; | ||||
| 
 | ||||
| @ -435,14 +449,14 @@ static GSList *create_layouts(cairo_t *c) | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| static int layout_get_height(struct colored_layout *cl) | ||||
| static int layout_get_height(struct colored_layout *cl, int scale) | ||||
| { | ||||
|         int h; | ||||
|         int h_icon = 0; | ||||
|         int h_progress_bar = 0; | ||||
|         pango_layout_get_pixel_size(cl->l, NULL, &h); | ||||
|         get_text_size(cl->l, NULL, &h, scale); | ||||
|         if (cl->icon) | ||||
|                 h_icon = cairo_image_surface_get_height(cl->icon); | ||||
|                 h_icon = get_icon_height(cl->icon, scale); | ||||
|         if (have_progress_bar(cl->n)){ | ||||
|                 h_progress_bar = settings.progress_bar_height + settings.padding; | ||||
|         } | ||||
| @ -482,8 +496,14 @@ static int frame_internal_radius (int r, int w, int h) | ||||
|  * The top corners will get rounded by `corner_radius`, if `first` is set. | ||||
|  * Respectably the same for `last` with the bottom corners. | ||||
|  */ | ||||
| void draw_rounded_rect(cairo_t *c, int x, int y, int width, int height, int corner_radius, bool first, bool last) | ||||
| void draw_rounded_rect(cairo_t *c, int x, int y, int width, int height, int corner_radius, int scale, bool first, bool last) | ||||
| { | ||||
|         width *= scale; | ||||
|         height *= scale; | ||||
|         x *= scale; | ||||
|         y *= scale; | ||||
|         corner_radius *= scale; | ||||
| 
 | ||||
|         const float degrees = M_PI / 180.0; | ||||
| 
 | ||||
|         cairo_new_sub_path(c); | ||||
| @ -531,6 +551,13 @@ void draw_rounded_rect(cairo_t *c, int x, int y, int width, int height, int corn | ||||
|         cairo_close_path(c); | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  * A small wrapper around cairo_rectange for drawing a scaled rectangle. | ||||
|  */ | ||||
| void draw_rect(cairo_t *c, int x, int y, int width, int height, int scale) { | ||||
|         cairo_rectangle(c, x * scale, y * scale, width * scale, height * scale); | ||||
| } | ||||
| 
 | ||||
| static cairo_surface_t *render_background(cairo_surface_t *srf, | ||||
|                                           struct colored_layout *cl, | ||||
|                                           struct colored_layout *cl_next, | ||||
| @ -540,7 +567,8 @@ static cairo_surface_t *render_background(cairo_surface_t *srf, | ||||
|                                           int corner_radius, | ||||
|                                           bool first, | ||||
|                                           bool last, | ||||
|                                           int *ret_width) | ||||
|                                           int *ret_width, | ||||
|                                           int scale) | ||||
| { | ||||
|         int x = 0; | ||||
|         int radius_int = corner_radius; | ||||
| @ -560,7 +588,7 @@ static cairo_surface_t *render_background(cairo_surface_t *srf, | ||||
|         else | ||||
|                 height += settings.separator_height; | ||||
| 
 | ||||
|         draw_rounded_rect(c, x, y, width, height, corner_radius, first, last); | ||||
|         draw_rounded_rect(c, x, y, width, height, corner_radius, scale, first, last); | ||||
| 
 | ||||
|         /* adding frame */ | ||||
|         x += settings.frame_width; | ||||
| @ -578,11 +606,11 @@ static cairo_surface_t *render_background(cairo_surface_t *srf, | ||||
| 
 | ||||
|         radius_int = frame_internal_radius(corner_radius, settings.frame_width, height); | ||||
| 
 | ||||
|         draw_rounded_rect(c, x, y, width, height, radius_int, first, last); | ||||
|         draw_rounded_rect(c, x, y, width, height, radius_int, scale, first, last); | ||||
|         cairo_set_source_rgba(c, cl->frame.r, cl->frame.g, cl->frame.b, cl->frame.a); | ||||
|         cairo_fill(c); | ||||
| 
 | ||||
|         draw_rounded_rect(c, x, y, width, height, radius_int, first, last); | ||||
|         draw_rounded_rect(c, x, y, width, height, radius_int, scale, first, last); | ||||
|         cairo_set_source_rgba(c, cl->bg.r, cl->bg.g, cl->bg.b, cl->bg.a); | ||||
|         cairo_fill(c); | ||||
| 
 | ||||
| @ -594,7 +622,7 @@ static cairo_surface_t *render_background(cairo_surface_t *srf, | ||||
|                 struct color sep_color = layout_get_sepcolor(cl, cl_next); | ||||
|                 cairo_set_source_rgba(c, sep_color.r, sep_color.g, sep_color.b, sep_color.a); | ||||
| 
 | ||||
|                 cairo_rectangle(c, settings.frame_width, y + height, width, settings.separator_height); | ||||
|                 draw_rect(c, settings.frame_width, y + height, width, settings.separator_height, scale); | ||||
| 
 | ||||
|                 cairo_fill(c); | ||||
|         } | ||||
| @ -604,18 +632,18 @@ static cairo_surface_t *render_background(cairo_surface_t *srf, | ||||
|         if (ret_width) | ||||
|                 *ret_width = width; | ||||
| 
 | ||||
|         return cairo_surface_create_for_rectangle(srf, x, y, width, height); | ||||
|         return cairo_surface_create_for_rectangle(srf, x * scale, y * scale, width * scale, height * scale); | ||||
| } | ||||
| 
 | ||||
| static void render_content(cairo_t *c, struct colored_layout *cl, int width) | ||||
| static void render_content(cairo_t *c, struct colored_layout *cl, int width, int scale) | ||||
| { | ||||
|         const int h = layout_get_height(cl); | ||||
|         const int h = layout_get_height(cl, scale); | ||||
|         int h_without_progress_bar = h; | ||||
|         if (have_progress_bar(cl->n)){ | ||||
|                  h_without_progress_bar -= settings.progress_bar_height + settings.padding; | ||||
|         } | ||||
|         int h_text; | ||||
|         pango_layout_get_pixel_size(cl->l, NULL, &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; | ||||
| @ -633,10 +661,10 @@ static void render_content(cairo_t *c, struct colored_layout *cl, int width) | ||||
| 
 | ||||
|                 // icon position
 | ||||
|                 if (settings.icon_position == ICON_LEFT) { | ||||
|                         text_x = cairo_image_surface_get_width(cl->icon) + settings.h_padding + get_text_icon_padding(); | ||||
|                         text_x = get_icon_width(cl->icon, scale) + settings.h_padding + get_text_icon_padding(); | ||||
|                 } // else ICON_RIGHT
 | ||||
|         } | ||||
|         cairo_move_to(c, text_x, text_y); | ||||
|         cairo_move_to(c, text_x * scale, 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); | ||||
| @ -645,8 +673,8 @@ static void render_content(cairo_t *c, struct colored_layout *cl, int width) | ||||
| 
 | ||||
|         // icon positioning
 | ||||
|         if (cl->icon) { | ||||
|                 unsigned int image_width = cairo_image_surface_get_width(cl->icon), | ||||
|                              image_height = cairo_image_surface_get_height(cl->icon), | ||||
|                 unsigned int image_width = get_icon_width(cl->icon, scale), | ||||
|                              image_height = get_icon_height(cl->icon, scale), | ||||
|                              image_x = width - settings.h_padding - image_width, | ||||
|                              image_y = settings.padding + h_without_progress_bar/2 - image_height/2; | ||||
| 
 | ||||
| @ -664,8 +692,8 @@ static void render_content(cairo_t *c, struct colored_layout *cl, int width) | ||||
|                         image_x = settings.h_padding; | ||||
|                 } // else ICON_RIGHT
 | ||||
| 
 | ||||
|                 cairo_set_source_surface(c, cl->icon, image_x, image_y); | ||||
|                 cairo_rectangle(c, image_x, image_y, image_width, image_height); | ||||
|                 cairo_set_source_surface(c, cl->icon, image_x * scale, image_y * scale); | ||||
|                 draw_rect(c, image_x, image_y, image_width, image_height, scale); | ||||
|                 cairo_fill(c); | ||||
|         } | ||||
| 
 | ||||
| @ -689,16 +717,17 @@ static void render_content(cairo_t *c, struct colored_layout *cl, int width) | ||||
|                 // Note: the bar could be drawn a bit smaller, because the frame is drawn on top
 | ||||
|                 // left side
 | ||||
|                 cairo_set_source_rgba(c, cl->highlight.r, cl->highlight.g, cl->highlight.b, cl->highlight.a); | ||||
|                 cairo_rectangle(c, x_bar_1, frame_y, progress_width_1, progress_height); | ||||
|                 draw_rect(c, x_bar_1, frame_y, progress_width_1, progress_height, scale); | ||||
|                 cairo_fill(c); | ||||
|                 // right side
 | ||||
|                 cairo_set_source_rgba(c, cl->bg.r, cl->bg.g, cl->bg.b, cl->bg.a); | ||||
|                 cairo_rectangle(c, x_bar_2, frame_y, progress_width_2, progress_height); | ||||
|                 draw_rect(c, x_bar_2, frame_y, progress_width_2, progress_height, scale); | ||||
|                 cairo_fill(c); | ||||
|                 // border
 | ||||
|                 cairo_set_source_rgba(c, cl->frame.r, cl->frame.g, cl->frame.b, cl->frame.a); | ||||
|                 cairo_rectangle(c, frame_x + half_frame_width, frame_y + half_frame_width, progress_width - frame_width, progress_height); | ||||
|                 cairo_set_line_width(c, frame_width); | ||||
|                 // TODO draw_rect instead of cairo_rectangle resulted in blurry lines. Why?
 | ||||
|                 cairo_rectangle(c, (frame_x + half_frame_width) * scale, (frame_y + half_frame_width) * scale, (progress_width - frame_width) * scale, progress_height * scale); | ||||
|                 cairo_set_line_width(c, frame_width * scale); | ||||
|                 cairo_stroke(c); | ||||
|         } | ||||
| } | ||||
| @ -710,18 +739,19 @@ static struct dimensions layout_render(cairo_surface_t *srf, | ||||
|                                        bool first, | ||||
|                                        bool last) | ||||
| { | ||||
|         const int cl_h = layout_get_height(cl); | ||||
|         int scale = output->get_scale(); | ||||
|         const int cl_h = layout_get_height(cl, scale); | ||||
| 
 | ||||
|         int h_text = 0; | ||||
|         pango_layout_get_pixel_size(cl->l, NULL, &h_text); | ||||
|         get_text_size(cl->l, NULL, &h_text, scale); | ||||
| 
 | ||||
|         int bg_width = 0; | ||||
|         int bg_height = MAX(settings.notification_height, (2 * settings.padding) + cl_h); | ||||
| 
 | ||||
|         cairo_surface_t *content = render_background(srf, cl, cl_next, dim.y, dim.w, bg_height, dim.corner_radius, first, last, &bg_width); | ||||
|         cairo_surface_t *content = render_background(srf, cl, cl_next, dim.y, dim.w, bg_height, dim.corner_radius, first, last, &bg_width, scale); | ||||
|         cairo_t *c = cairo_create(content); | ||||
| 
 | ||||
|         render_content(c, cl, bg_width); | ||||
|         render_content(c, cl, bg_width, scale); | ||||
| 
 | ||||
|         /* adding frame */ | ||||
|         if (first) | ||||
| @ -773,8 +803,9 @@ void draw(void) | ||||
|         GSList *layouts = create_layouts(output->win_get_context(win)); | ||||
| 
 | ||||
|         struct dimensions dim = calculate_dimensions(layouts); | ||||
|         int scale = output->get_scale(); | ||||
| 
 | ||||
|         cairo_surface_t *image_surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, dim.w, dim.h); | ||||
|         cairo_surface_t *image_surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, dim.w * scale, dim.h * scale); | ||||
| 
 | ||||
|         bool first = true; | ||||
|         for (GSList *iter = layouts; iter; iter = iter->next) { | ||||
| @ -799,4 +830,14 @@ void draw_deinit(void) | ||||
|         output->win_destroy(win); | ||||
|         output->deinit(); | ||||
| } | ||||
| 
 | ||||
| int draw_get_scale(void) | ||||
| { | ||||
|         if (output) { | ||||
|                 return output->get_scale(); | ||||
|         } else { | ||||
|                 LOG_W("Called draw_get_scale before output init"); | ||||
|                 return 1; | ||||
|         } | ||||
| } | ||||
| /* vim: set ft=c tabstop=8 shiftwidth=8 expandtab textwidth=0: */ | ||||
|  | ||||
| @ -12,9 +12,13 @@ void draw_setup(void); | ||||
| 
 | ||||
| void draw(void); | ||||
| 
 | ||||
| void draw_rounded_rect(cairo_t *c, int x, int y, int width, int height, int corner_radius, bool first, bool last); | ||||
| void draw_rounded_rect(cairo_t *c, int x, int y, int width, int height, int corner_radius, int scale, bool first, bool last); | ||||
| 
 | ||||
| // TODO get rid of this function by passing scale to everything that needs it.
 | ||||
| int draw_get_scale(void); | ||||
| 
 | ||||
| void draw_deinit(void); | ||||
| 
 | ||||
| 
 | ||||
| #endif | ||||
| /* vim: set ft=c tabstop=8 shiftwidth=8 expandtab textwidth=0: */ | ||||
|  | ||||
							
								
								
									
										10
									
								
								src/dunst.c
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								src/dunst.c
									
									
									
									
									
								
							| @ -24,6 +24,7 @@ | ||||
| GMainLoop *mainloop = NULL; | ||||
| 
 | ||||
| static struct dunst_status status; | ||||
| static bool setup_done = false; | ||||
| 
 | ||||
| /* see dunst.h */ | ||||
| void dunst_status(const enum dunst_status_field field, | ||||
| @ -56,6 +57,14 @@ static gboolean run(void *data); | ||||
| 
 | ||||
| void wake_up(void) | ||||
| { | ||||
|         // If wake_up is being called before the output has been setup we should
 | ||||
|         // return.
 | ||||
|         if (!setup_done) | ||||
|         { | ||||
|                 LOG_D("Ignoring wake up"); | ||||
|                 return; | ||||
|         } | ||||
| 
 | ||||
|         LOG_D("Waking up"); | ||||
|         run(NULL); | ||||
| } | ||||
| @ -197,6 +206,7 @@ int dunst_main(int argc, char *argv[]) | ||||
|                 // we do not call wakeup now, wake_up does not work here yet
 | ||||
|         } | ||||
| 
 | ||||
|         setup_done = true; | ||||
|         run(NULL); | ||||
|         g_main_loop_run(mainloop); | ||||
|         g_clear_pointer(&mainloop, g_main_loop_unref); | ||||
|  | ||||
							
								
								
									
										37
									
								
								src/icon.c
									
									
									
									
									
								
							
							
						
						
									
										37
									
								
								src/icon.c
									
									
									
									
									
								
							| @ -86,6 +86,14 @@ static void pixbuf_data_to_cairo_data( | ||||
|         } | ||||
| } | ||||
| 
 | ||||
| int get_icon_width(cairo_surface_t *icon, int scale) { | ||||
|         return cairo_image_surface_get_width(icon) / scale; | ||||
| } | ||||
| 
 | ||||
| int get_icon_height(cairo_surface_t *icon, int scale) { | ||||
|         return cairo_image_surface_get_height(icon) / scale; | ||||
| } | ||||
| 
 | ||||
| cairo_surface_t *gdk_pixbuf_to_cairo_surface(GdkPixbuf *pixbuf) | ||||
| { | ||||
|         assert(pixbuf); | ||||
| @ -144,22 +152,26 @@ static bool icon_size_clamp(int *w, int *h) { | ||||
|  * | ||||
|  * @param pixbuf (nullable) The pixbuf, which may be too big. | ||||
|  *                          Takes ownership of the reference. | ||||
|  * @param dpi_scale An integer for the dpi scaling. That doesn't mean the icon | ||||
|  *                  is always scaled by dpi_scale. | ||||
|  * @return the scaled version of the pixbuf. If scaling wasn't | ||||
|  *         necessary, it returns the same pixbuf. Transfers full | ||||
|  *         ownership of the reference. | ||||
|  */ | ||||
| static GdkPixbuf *icon_pixbuf_scale(GdkPixbuf *pixbuf) | ||||
| static GdkPixbuf *icon_pixbuf_scale(GdkPixbuf *pixbuf, int dpi_scale) | ||||
| { | ||||
|         ASSERT_OR_RET(pixbuf, NULL); | ||||
| 
 | ||||
|         int w = gdk_pixbuf_get_width(pixbuf); | ||||
|         int h = gdk_pixbuf_get_height(pixbuf); | ||||
| 
 | ||||
| 
 | ||||
|         // TODO immediately rescale icon upon scale changes
 | ||||
|         if (icon_size_clamp(&w, &h)) { | ||||
|                 GdkPixbuf *scaled = gdk_pixbuf_scale_simple( | ||||
|                                 pixbuf, | ||||
|                                 w, | ||||
|                                 h, | ||||
|                                 w * dpi_scale, | ||||
|                                 h * dpi_scale, | ||||
|                                 GDK_INTERP_BILINEAR); | ||||
|                 g_object_unref(pixbuf); | ||||
|                 pixbuf = scaled; | ||||
| @ -168,7 +180,7 @@ static GdkPixbuf *icon_pixbuf_scale(GdkPixbuf *pixbuf) | ||||
|         return pixbuf; | ||||
| } | ||||
| 
 | ||||
| GdkPixbuf *get_pixbuf_from_file(const char *filename) | ||||
| GdkPixbuf *get_pixbuf_from_file(const char *filename, int scale) | ||||
| { | ||||
|         char *path = string_to_path(g_strdup(filename)); | ||||
|         GError *error = NULL; | ||||
| @ -179,10 +191,11 @@ GdkPixbuf *get_pixbuf_from_file(const char *filename) | ||||
|                 g_free(path); | ||||
|                 return NULL; | ||||
|         } | ||||
|         // TODO immediately rescale icon upon scale changes
 | ||||
|         icon_size_clamp(&w, &h); | ||||
|         GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file_at_scale(path, | ||||
|                                                               w, | ||||
|                                                               h, | ||||
|                                                               w * scale, | ||||
|                                                               h * scale, | ||||
|                                                               TRUE, | ||||
|                                                               &error); | ||||
| 
 | ||||
| @ -250,7 +263,7 @@ char *get_path_from_icon_name(const char *iconname) | ||||
|         return new_name; | ||||
| } | ||||
| 
 | ||||
| GdkPixbuf *get_pixbuf_from_icon(const char *iconname) | ||||
| GdkPixbuf *get_pixbuf_from_icon(const char *iconname, int scale) | ||||
| { | ||||
|         char *path = get_path_from_icon_name(iconname); | ||||
|         if (!path) { | ||||
| @ -259,7 +272,7 @@ GdkPixbuf *get_pixbuf_from_icon(const char *iconname) | ||||
| 
 | ||||
|         GdkPixbuf *pixbuf = NULL; | ||||
| 
 | ||||
|         pixbuf = get_pixbuf_from_file(path); | ||||
|         pixbuf = get_pixbuf_from_file(path, scale); | ||||
|         g_free(path); | ||||
| 
 | ||||
|         if (!pixbuf) | ||||
| @ -268,18 +281,18 @@ GdkPixbuf *get_pixbuf_from_icon(const char *iconname) | ||||
|         return pixbuf; | ||||
| } | ||||
| 
 | ||||
| GdkPixbuf *icon_get_for_name(const char *name, char **id) | ||||
| GdkPixbuf *icon_get_for_name(const char *name, char **id, int scale) | ||||
| { | ||||
|         ASSERT_OR_RET(name, NULL); | ||||
|         ASSERT_OR_RET(id, NULL); | ||||
| 
 | ||||
|         GdkPixbuf *pb = get_pixbuf_from_icon(name); | ||||
|         GdkPixbuf *pb = get_pixbuf_from_icon(name, scale); | ||||
|         if (pb) | ||||
|                 *id = g_strdup(name); | ||||
|         return pb; | ||||
| } | ||||
| 
 | ||||
| GdkPixbuf *icon_get_for_data(GVariant *data, char **id) | ||||
| GdkPixbuf *icon_get_for_data(GVariant *data, char **id, int dpi_scale) | ||||
| { | ||||
|         ASSERT_OR_RET(data, NULL); | ||||
|         ASSERT_OR_RET(id, NULL); | ||||
| @ -389,7 +402,7 @@ GdkPixbuf *icon_get_for_data(GVariant *data, char **id) | ||||
|         g_free(data_chk); | ||||
|         g_variant_unref(data_variant); | ||||
| 
 | ||||
|         pixbuf = icon_pixbuf_scale(pixbuf); | ||||
|         pixbuf = icon_pixbuf_scale(pixbuf, dpi_scale); | ||||
| 
 | ||||
|         return pixbuf; | ||||
| } | ||||
|  | ||||
							
								
								
									
										26
									
								
								src/icon.h
									
									
									
									
									
								
							
							
						
						
									
										26
									
								
								src/icon.h
									
									
									
									
									
								
							| @ -11,11 +11,26 @@ cairo_surface_t *gdk_pixbuf_to_cairo_surface(GdkPixbuf *pixbuf); | ||||
| /** Retrieve an icon by its full filepath, scaled according to settings.
 | ||||
|  * | ||||
|  * @param filename A string representing a readable file path | ||||
|  * @param scale An integer representing the output dpi scaling. | ||||
|  * | ||||
|  * @return an instance of `GdkPixbuf` | ||||
|  * @retval NULL: file does not exist, not readable, etc.. | ||||
|  */ | ||||
| GdkPixbuf *get_pixbuf_from_file(const char *filename); | ||||
| GdkPixbuf *get_pixbuf_from_file(const char *filename, int scale); | ||||
| 
 | ||||
| 
 | ||||
| /**
 | ||||
|  * Get the unscaled icon width. | ||||
|  * | ||||
|  * If scale is 2 for example, the icon will render in twice the size, but | ||||
|  * get_icon_width still returns the same size as when scale is 1. | ||||
|  */ | ||||
| int get_icon_width(cairo_surface_t *icon, int scale); | ||||
| 
 | ||||
| /**
 | ||||
|  * Get the unscaled icon height, see get_icon_width. | ||||
|  */ | ||||
| int get_icon_height(cairo_surface_t *icon, int scale); | ||||
| 
 | ||||
| /** Retrieve a path from an icon name.
 | ||||
|  * | ||||
| @ -33,11 +48,12 @@ char *get_path_from_icon_name(const char *iconname); | ||||
|  * @param iconname A string describing a `file://` URL, an arbitary filename
 | ||||
|  *                 or an icon name, which then gets searched for in the | ||||
|  *                 settings.icon_path | ||||
|  * @param scale An integer representing the output dpi scaling. | ||||
|  * | ||||
|  * @return an instance of `GdkPixbuf` | ||||
|  * @retval NULL: file does not exist, not readable, etc.. | ||||
|  */ | ||||
| GdkPixbuf *get_pixbuf_from_icon(const char *iconname); | ||||
| GdkPixbuf *get_pixbuf_from_icon(const char *iconname, int scale); | ||||
| 
 | ||||
| /** Read an icon from disk and convert it to a GdkPixbuf, scaled according to settings
 | ||||
|  * | ||||
| @ -49,10 +65,11 @@ GdkPixbuf *get_pixbuf_from_icon(const char *iconname); | ||||
|  *             get searched in the folders of the icon_path setting. | ||||
|  * @param id   (necessary) A unique identifier of the returned pixbuf. Only filled, | ||||
|  *             if the return value is non-NULL. | ||||
|  * @param scale An integer representing the output dpi scaling. | ||||
|  * @return an instance of `GdkPixbuf`, representing the name's image | ||||
|  * @retval NULL: Invalid path given | ||||
|  */ | ||||
| GdkPixbuf *icon_get_for_name(const char *name, char **id); | ||||
| GdkPixbuf *icon_get_for_name(const char *name, char **id, int dpi_scale); | ||||
| 
 | ||||
| /** Convert a GVariant like described in GdkPixbuf, scaled according to settings
 | ||||
|  * | ||||
| @ -63,10 +80,11 @@ GdkPixbuf *icon_get_for_name(const char *name, char **id); | ||||
|  *             like described in the notification spec. | ||||
|  * @param id   (necessary) A unique identifier of the returned pixbuf. | ||||
|  *             Only filled, if the return value is non-NULL. | ||||
|  * @param scale An integer representing the output dpi scaling. | ||||
|  * @return an instance of `GdkPixbuf` derived from the GVariant | ||||
|  * @retval NULL: GVariant parameter nulled, invalid or in wrong format | ||||
|  */ | ||||
| GdkPixbuf *icon_get_for_data(GVariant *data, char **id); | ||||
| GdkPixbuf *icon_get_for_data(GVariant *data, char **id, int scale); | ||||
| 
 | ||||
| #endif | ||||
| /* vim: set ft=c tabstop=8 shiftwidth=8 expandtab textwidth=0: */ | ||||
|  | ||||
| @ -23,6 +23,7 @@ | ||||
| #include "rules.h" | ||||
| #include "settings.h" | ||||
| #include "utils.h" | ||||
| #include "draw.h" | ||||
| 
 | ||||
| static void notification_extract_urls(struct notification *n); | ||||
| static void notification_format_message(struct notification *n); | ||||
| @ -313,7 +314,7 @@ void notification_icon_replace_path(struct notification *n, const char *new_icon | ||||
|         g_clear_object(&n->icon); | ||||
|         g_clear_pointer(&n->icon_id, g_free); | ||||
| 
 | ||||
|         n->icon = icon_get_for_name(new_icon, &n->icon_id); | ||||
|         n->icon = icon_get_for_name(new_icon, &n->icon_id, draw_get_scale()); | ||||
| } | ||||
| 
 | ||||
| void notification_icon_replace_data(struct notification *n, GVariant *new_icon) | ||||
| @ -324,7 +325,7 @@ void notification_icon_replace_data(struct notification *n, GVariant *new_icon) | ||||
|         g_clear_object(&n->icon); | ||||
|         g_clear_pointer(&n->icon_id, g_free); | ||||
| 
 | ||||
|         n->icon = icon_get_for_data(new_icon, &n->icon_id); | ||||
|         n->icon = icon_get_for_data(new_icon, &n->icon_id, draw_get_scale()); | ||||
| } | ||||
| 
 | ||||
| /* see notification.h */ | ||||
|  | ||||
| @ -29,7 +29,9 @@ const struct output output_x11 = { | ||||
|         get_active_screen, | ||||
| 
 | ||||
|         x_is_idle, | ||||
|         have_fullscreen_window | ||||
|         have_fullscreen_window, | ||||
| 
 | ||||
|         x_get_scale, | ||||
| }; | ||||
| 
 | ||||
| #ifdef ENABLE_WAYLAND | ||||
| @ -49,7 +51,9 @@ const struct output output_wl = { | ||||
|         wl_get_active_screen, | ||||
| 
 | ||||
|         wl_is_idle, | ||||
|         wl_have_fullscreen_window | ||||
|         wl_have_fullscreen_window, | ||||
| 
 | ||||
|         wl_get_scale, | ||||
| }; | ||||
| #endif | ||||
| 
 | ||||
|  | ||||
| @ -44,6 +44,8 @@ struct output { | ||||
| 
 | ||||
|         bool (*is_idle)(void); | ||||
|         bool (*have_fullscreen_window)(void); | ||||
| 
 | ||||
|         int (*get_scale)(void); | ||||
| }; | ||||
| 
 | ||||
| /**
 | ||||
|  | ||||
| @ -107,7 +107,7 @@ static void output_handle_geometry(void *data, struct wl_output *wl_output, | ||||
|                 int32_t x, int32_t y, int32_t phy_width, int32_t phy_height, | ||||
|                 int32_t subpixel, const char *make, const char *model, | ||||
|                 int32_t transform) { | ||||
|         //TODO
 | ||||
|         //TODO do something with the subpixel data
 | ||||
|         struct dunst_output *output = data; | ||||
|         output->subpixel = subpixel; | ||||
| } | ||||
| @ -116,6 +116,8 @@ static void output_handle_scale(void *data, struct wl_output *wl_output, | ||||
|                 int32_t factor) { | ||||
|         struct dunst_output *output = data; | ||||
|         output->scale = factor; | ||||
| 
 | ||||
|         wake_up(); | ||||
| } | ||||
| 
 | ||||
| static const struct wl_output_listener output_listener = { | ||||
| @ -135,7 +137,6 @@ static void create_output( struct wl_output *wl_output, uint32_t global_name) { | ||||
|         LOG_I("New output found - id %i", number); | ||||
|         output->global_name = global_name; | ||||
|         output->wl_output = wl_output; | ||||
|         // TODO: Fix this
 | ||||
|         output->scale = 1; | ||||
|         output->fullscreen = false; | ||||
|         wl_list_insert(&ctx.outputs, &output->link); | ||||
| @ -227,7 +228,6 @@ static void seat_handle_capabilities(void *data, struct wl_seat *wl_seat, | ||||
|                 ctx.pointer.wl_pointer = wl_seat_get_pointer(wl_seat); | ||||
|                 wl_pointer_add_listener(ctx.pointer.wl_pointer, | ||||
|                         &pointer_listener, ctx.seat); | ||||
|                 LOG_I("Adding pointer"); | ||||
|         } | ||||
|         if (ctx.touch.wl_touch != NULL) { | ||||
|                 wl_touch_release(ctx.touch.wl_touch); | ||||
| @ -343,20 +343,29 @@ static void add_seat_to_idle_handler(struct wl_seat *seat) { | ||||
| 
 | ||||
| // Warning, can return NULL
 | ||||
| static struct dunst_output *get_configured_output() { | ||||
|         int n = 0; | ||||
|         int target_monitor = settings.monitor; | ||||
| 
 | ||||
|         struct dunst_output *first_output = NULL, *configured_output = NULL, | ||||
|                             *tmp_output = NULL; | ||||
|         wl_list_for_each(tmp_output, &ctx.outputs, link) { | ||||
|                 if (n == 0) | ||||
|                         first_output = tmp_output; | ||||
|                 if (n == target_monitor) | ||||
|                         configured_output = tmp_output; | ||||
|                 n++; | ||||
|         } | ||||
| 
 | ||||
|         // There's only 1 output, so return that
 | ||||
|         if (n == 1) | ||||
|                 return first_output; | ||||
| 
 | ||||
|         switch (settings.f_mode){ | ||||
|                 case FOLLOW_NONE: ; // this semicolon is neccesary
 | ||||
|                         int n = 0; | ||||
|                         int target_monitor = settings.monitor; | ||||
| 
 | ||||
|                         struct dunst_output *output; | ||||
|                         wl_list_for_each(output, &ctx.outputs, link) { | ||||
|                                 if (n == target_monitor) | ||||
|                                         return output; | ||||
|                                 n++; | ||||
|                         if (!configured_output) { | ||||
|                                 LOG_W("Monitor %i doesn't exist, using focused monitor", settings.monitor); | ||||
|                         } | ||||
|                         LOG_W("Monitor %i doesn't exist, using focused monitor", settings.monitor); | ||||
|                         return NULL; | ||||
|                         return configured_output; | ||||
|                 case FOLLOW_MOUSE: | ||||
|                         // fallthrough
 | ||||
|                 case FOLLOW_KEYBOARD: | ||||
| @ -626,7 +635,7 @@ static void schedule_frame_and_commit(); | ||||
| 
 | ||||
| // Draw and commit a new frame.
 | ||||
| static void send_frame() { | ||||
|         int scale = 1; | ||||
|         int scale = wl_get_scale(); | ||||
| 
 | ||||
|         struct dunst_output *output = get_configured_output(); | ||||
|         int height = ctx.cur_dim.h; | ||||
| @ -692,8 +701,6 @@ static void send_frame() { | ||||
|         if (ctx.height != height || ctx.width != width) { | ||||
|                 struct dimensions dim = ctx.cur_dim; | ||||
|                 // Set window size
 | ||||
|                 LOG_D("Window dimensions %ix%i", dim.w, dim.h); | ||||
|                 LOG_D("Window position %ix%i", dim.x, dim.y); | ||||
|                 zwlr_layer_surface_v1_set_size(ctx.layer_surface, | ||||
|                                 dim.w, dim.h); | ||||
| 
 | ||||
| @ -818,12 +825,15 @@ void wl_win_hide(window win) { | ||||
| 
 | ||||
| void wl_display_surface(cairo_surface_t *srf, window winptr, const struct dimensions* dim) { | ||||
|         /* struct window_wl *win = (struct window_wl*)winptr; */ | ||||
|         ctx.current_buffer = get_next_buffer(ctx.shm, ctx.buffers, dim->w, dim->h); | ||||
|         int scale = wl_get_scale(); | ||||
|         LOG_D("Buffer size (scaled) %ix%i", dim->w * scale, dim->h * scale); | ||||
|         ctx.current_buffer = get_next_buffer(ctx.shm, ctx.buffers, | ||||
|                         dim->w * scale, dim->h * scale); | ||||
| 
 | ||||
|         cairo_t *c = ctx.current_buffer->cairo; | ||||
|         cairo_save(c); | ||||
|         cairo_set_source_surface(c, srf, 0, 0); | ||||
|         cairo_rectangle(c, 0, 0, dim->w, dim->h); | ||||
|         cairo_rectangle(c, 0, 0, dim->w * scale, dim->h * scale); | ||||
|         cairo_fill(c); | ||||
|         cairo_restore(c); | ||||
| 
 | ||||
| @ -851,6 +861,7 @@ const struct screen_info* wl_get_active_screen(void) { | ||||
|                 .id = 0, | ||||
|                 .mmh = 500 | ||||
|         }; | ||||
|         scr.dpi = wl_get_scale() * 96; | ||||
|         return &scr; | ||||
| } | ||||
| 
 | ||||
| @ -886,4 +897,21 @@ bool wl_have_fullscreen_window(void) { | ||||
|         LOG_D("Fullscreen queried: %i", have_fullscreen); | ||||
|         return have_fullscreen; | ||||
| } | ||||
| 
 | ||||
| int wl_get_scale(void) { | ||||
|         int scale = 0; | ||||
|         struct dunst_output *output = get_configured_output(); | ||||
|         if (output) { | ||||
|                 scale = output->scale; | ||||
|         } else { | ||||
|                 // return the largest scale
 | ||||
|                 struct dunst_output *output; | ||||
|                 wl_list_for_each(output, &ctx.outputs, link) { | ||||
|                         scale = MAX(output->scale, scale); | ||||
|                 } | ||||
|         } | ||||
|         if (scale <= 0) | ||||
|                 scale = 1; | ||||
|         return scale; | ||||
| } | ||||
| /* vim: set ft=c tabstop=8 shiftwidth=8 expandtab textwidth=0: */ | ||||
|  | ||||
| @ -23,5 +23,10 @@ const struct screen_info* wl_get_active_screen(void); | ||||
| 
 | ||||
| bool wl_is_idle(void); | ||||
| bool wl_have_fullscreen_window(void); | ||||
| 
 | ||||
| // Return the dpi scaling of the current output. Everything that's rendered
 | ||||
| // should be multiplied by this value, but don't use it to multiply other
 | ||||
| // values. All sizes should be in unscaled units.
 | ||||
| int wl_get_scale(void); | ||||
| #endif | ||||
| /* vim: set ft=c tabstop=8 shiftwidth=8 expandtab textwidth=0: */ | ||||
|  | ||||
| @ -113,7 +113,7 @@ static void x_win_corners_shape(struct window_x11 *win, const int rad) | ||||
| 
 | ||||
|         draw_rounded_rect(cr, 0, 0, | ||||
|                           width, height, | ||||
|                           rad, | ||||
|                           rad, 1, | ||||
|                           true, true); | ||||
|         cairo_fill(cr); | ||||
| 
 | ||||
| @ -942,4 +942,8 @@ static void x_shortcut_init(struct keyboard_shortcut *ks) | ||||
|         g_free(str_begin); | ||||
| } | ||||
| 
 | ||||
| int x_get_scale(void) { | ||||
|         return 1; | ||||
| } | ||||
| 
 | ||||
| /* vim: set ft=c tabstop=8 shiftwidth=8 expandtab textwidth=0: */ | ||||
|  | ||||
| @ -51,5 +51,6 @@ void x_free(void); | ||||
| 
 | ||||
| struct geometry x_parse_geometry(const char *geom_str); | ||||
| 
 | ||||
| int x_get_scale(void); | ||||
| #endif | ||||
| /* vim: set ft=c tabstop=8 shiftwidth=8 expandtab textwidth=0: */ | ||||
|  | ||||
							
								
								
									
										20
									
								
								test/icon.c
									
									
									
									
									
								
							
							
						
						
									
										20
									
								
								test/icon.c
									
									
									
									
									
								
							| @ -12,6 +12,8 @@ | ||||
| 
 | ||||
| extern const char *base; | ||||
| 
 | ||||
| int scale = 1; | ||||
| 
 | ||||
| TEST test_get_path_from_icon_null(void){ | ||||
|     char *result = get_path_from_icon_name(NULL); | ||||
|     ASSERT_EQ(result, NULL); | ||||
| @ -86,7 +88,7 @@ TEST test_get_pixbuf_from_file_tilde(void) | ||||
|         gchar *path = g_build_filename(base, iconpath, "valid", "icon1.svg", NULL); | ||||
|         path = string_replace_at(path, 0, strlen(home), "~"); | ||||
| 
 | ||||
|         GdkPixbuf *pixbuf = get_pixbuf_from_file(path); | ||||
|         GdkPixbuf *pixbuf = get_pixbuf_from_file(path, scale); | ||||
|         g_clear_pointer(&path, g_free); | ||||
| 
 | ||||
|         ASSERT(pixbuf); | ||||
| @ -101,7 +103,7 @@ TEST test_get_pixbuf_from_file_absolute(void) | ||||
| 
 | ||||
|         gchar *path = g_build_filename(base, iconpath, "valid", "icon1.svg", NULL); | ||||
| 
 | ||||
|         GdkPixbuf *pixbuf = get_pixbuf_from_file(path); | ||||
|         GdkPixbuf *pixbuf = get_pixbuf_from_file(path, scale); | ||||
|         g_clear_pointer(&path, g_free); | ||||
| 
 | ||||
|         ASSERT(pixbuf); | ||||
| @ -113,7 +115,7 @@ TEST test_get_pixbuf_from_file_absolute(void) | ||||
| 
 | ||||
| TEST test_get_pixbuf_from_icon_invalid(void) | ||||
| { | ||||
|         GdkPixbuf *pixbuf = get_pixbuf_from_icon("invalid"); | ||||
|         GdkPixbuf *pixbuf = get_pixbuf_from_icon("invalid", scale); | ||||
|         ASSERT(pixbuf == NULL); | ||||
|         g_clear_pointer(&pixbuf, g_object_unref); | ||||
| 
 | ||||
| @ -122,7 +124,7 @@ TEST test_get_pixbuf_from_icon_invalid(void) | ||||
| 
 | ||||
| TEST test_get_pixbuf_from_icon_both(void) | ||||
| { | ||||
|         GdkPixbuf *pixbuf = get_pixbuf_from_icon("icon1"); | ||||
|         GdkPixbuf *pixbuf = get_pixbuf_from_icon("icon1", scale); | ||||
|         // the first icon  found is invalid, so the pixbuf is empty
 | ||||
|         ASSERT(!pixbuf); | ||||
|         g_clear_pointer(&pixbuf, g_object_unref); | ||||
| @ -132,7 +134,7 @@ TEST test_get_pixbuf_from_icon_both(void) | ||||
| 
 | ||||
| TEST test_get_pixbuf_from_icon_onlysvg(void) | ||||
| { | ||||
|         GdkPixbuf *pixbuf = get_pixbuf_from_icon("onlysvg"); | ||||
|         GdkPixbuf *pixbuf = get_pixbuf_from_icon("onlysvg", scale); | ||||
|         ASSERT(pixbuf); | ||||
|         ASSERTm("SVG pixbuf isn't loaded", IS_ICON_SVG(pixbuf)); | ||||
|         g_clear_pointer(&pixbuf, g_object_unref); | ||||
| @ -142,7 +144,7 @@ TEST test_get_pixbuf_from_icon_onlysvg(void) | ||||
| 
 | ||||
| TEST test_get_pixbuf_from_icon_onlypng(void) | ||||
| { | ||||
|         GdkPixbuf *pixbuf = get_pixbuf_from_icon("onlypng"); | ||||
|         GdkPixbuf *pixbuf = get_pixbuf_from_icon("onlypng", scale); | ||||
|         ASSERT(pixbuf); | ||||
|         ASSERTm("PNG pixbuf isn't loaded", IS_ICON_PNG(pixbuf)); | ||||
|         g_clear_pointer(&pixbuf, g_object_unref); | ||||
| @ -153,7 +155,7 @@ TEST test_get_pixbuf_from_icon_onlypng(void) | ||||
| TEST test_get_pixbuf_from_icon_filename(void) | ||||
| { | ||||
|         char *icon = g_strconcat(base, "/data/icons/valid.png", NULL); | ||||
|         GdkPixbuf *pixbuf = get_pixbuf_from_icon(icon); | ||||
|         GdkPixbuf *pixbuf = get_pixbuf_from_icon(icon, scale); | ||||
|         ASSERT(pixbuf); | ||||
|         ASSERTm("PNG pixbuf isn't loaded", IS_ICON_PNG(pixbuf)); | ||||
|         g_clear_pointer(&pixbuf, g_object_unref); | ||||
| @ -165,7 +167,7 @@ TEST test_get_pixbuf_from_icon_filename(void) | ||||
| TEST test_get_pixbuf_from_icon_fileuri(void) | ||||
| { | ||||
|         char *icon = g_strconcat("file://", base, "/data/icons/valid.svg", NULL); | ||||
|         GdkPixbuf *pixbuf = get_pixbuf_from_icon(icon); | ||||
|         GdkPixbuf *pixbuf = get_pixbuf_from_icon(icon, scale); | ||||
|         ASSERT(pixbuf); | ||||
|         ASSERTm("SVG pixbuf isn't loaded", IS_ICON_SVG(pixbuf)); | ||||
|         g_clear_pointer(&pixbuf, g_object_unref); | ||||
| @ -220,7 +222,7 @@ TEST test_icon_size_clamp_too_small_then_too_big(void) | ||||
| 
 | ||||
| TEST test_get_pixbuf_from_icon_both_is_scaled(void) | ||||
| { | ||||
|         GdkPixbuf *pixbuf = get_pixbuf_from_icon("onlypng"); | ||||
|         GdkPixbuf *pixbuf = get_pixbuf_from_icon("onlypng", scale); | ||||
|         ASSERT(pixbuf); | ||||
|         ASSERT_EQ(gdk_pixbuf_get_width(pixbuf), 16); | ||||
|         ASSERT_EQ(gdk_pixbuf_get_height(pixbuf), 16); | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Nikos Tsipinakis
						Nikos Tsipinakis