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)
|
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_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_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;
|
PangoAlignment align;
|
||||||
switch (settings.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);
|
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)
|
static struct dimensions calculate_dimensions(GSList *layouts)
|
||||||
{
|
{
|
||||||
struct dimensions dim = { 0 };
|
struct dimensions dim = { 0 };
|
||||||
|
int scale = output->get_scale();
|
||||||
|
|
||||||
const struct screen_info *scr = output->get_active_screen();
|
const struct screen_info *scr = output->get_active_screen();
|
||||||
if (have_dynamic_width()) {
|
if (have_dynamic_width()) {
|
||||||
@ -221,10 +233,10 @@ static struct dimensions calculate_dimensions(GSList *layouts)
|
|||||||
for (GSList *iter = layouts; iter; iter = iter->next) {
|
for (GSList *iter = layouts; iter; iter = iter->next) {
|
||||||
struct colored_layout *cl = iter->data;
|
struct colored_layout *cl = iter->data;
|
||||||
int w=0,h=0;
|
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) {
|
if (cl->icon) {
|
||||||
h = MAX(cairo_image_surface_get_height(cl->icon), h);
|
h = MAX(get_icon_height(cl->icon, scale), h);
|
||||||
w += cairo_image_surface_get_width(cl->icon) + settings.h_padding;
|
w += get_icon_width(cl->icon, scale) + settings.h_padding;
|
||||||
}
|
}
|
||||||
h = MAX(settings.notification_height, h + settings.padding * 2);
|
h = MAX(settings.notification_height, h + settings.padding * 2);
|
||||||
dim.h += h;
|
dim.h += h;
|
||||||
@ -250,15 +262,15 @@ static struct dimensions calculate_dimensions(GSList *layouts)
|
|||||||
w -= 2 * settings.h_padding;
|
w -= 2 * settings.h_padding;
|
||||||
w -= 2 * settings.frame_width;
|
w -= 2 * settings.frame_width;
|
||||||
if (cl->icon) {
|
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);
|
layout_setup_pango(cl->l, w);
|
||||||
|
|
||||||
/* re-read information */
|
/* re-read information */
|
||||||
pango_layout_get_pixel_size(cl->l, &w, &h);
|
get_text_size(cl->l, &w, &h, scale);
|
||||||
if (cl->icon) {
|
if (cl->icon) {
|
||||||
h = MAX(cairo_image_surface_get_height(cl->icon), h);
|
h = MAX(get_icon_height(cl->icon, scale), h);
|
||||||
w += cairo_image_surface_get_width(cl->icon) + settings.h_padding;
|
w += get_icon_width(cl->icon, scale) + settings.h_padding;
|
||||||
}
|
}
|
||||||
h = MAX(settings.notification_height, h + settings.padding * 2);
|
h = MAX(settings.notification_height, h + settings.padding * 2);
|
||||||
dim.h += h;
|
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));
|
struct colored_layout *cl = g_malloc(sizeof(struct colored_layout));
|
||||||
cl->l = layout_create(c);
|
cl->l = layout_create(c);
|
||||||
|
int scale = output->get_scale();
|
||||||
|
|
||||||
if (!settings.word_wrap) {
|
if (!settings.word_wrap) {
|
||||||
PangoEllipsizeMode ellipsize;
|
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.h_padding;
|
||||||
width -= 2 * settings.frame_width;
|
width -= 2 * settings.frame_width;
|
||||||
if (cl->icon) {
|
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);
|
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);
|
struct colored_layout *cl = layout_init_shared(c, n);
|
||||||
|
int scale = output->get_scale();
|
||||||
|
|
||||||
/* markup */
|
/* markup */
|
||||||
GError *err = NULL;
|
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));
|
get_text_size(cl->l, NULL, &(n->displayed_height), scale);
|
||||||
if (cl->icon) n->displayed_height = MAX(cairo_image_surface_get_height(cl->icon), n->displayed_height);
|
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;
|
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;
|
||||||
int h_icon = 0;
|
int h_icon = 0;
|
||||||
int h_progress_bar = 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)
|
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)){
|
if (have_progress_bar(cl->n)){
|
||||||
h_progress_bar = settings.progress_bar_height + settings.padding;
|
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.
|
* The top corners will get rounded by `corner_radius`, if `first` is set.
|
||||||
* Respectably the same for `last` with the bottom corners.
|
* 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;
|
const float degrees = M_PI / 180.0;
|
||||||
|
|
||||||
cairo_new_sub_path(c);
|
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);
|
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,
|
static cairo_surface_t *render_background(cairo_surface_t *srf,
|
||||||
struct colored_layout *cl,
|
struct colored_layout *cl,
|
||||||
struct colored_layout *cl_next,
|
struct colored_layout *cl_next,
|
||||||
@ -540,7 +567,8 @@ static cairo_surface_t *render_background(cairo_surface_t *srf,
|
|||||||
int corner_radius,
|
int corner_radius,
|
||||||
bool first,
|
bool first,
|
||||||
bool last,
|
bool last,
|
||||||
int *ret_width)
|
int *ret_width,
|
||||||
|
int scale)
|
||||||
{
|
{
|
||||||
int x = 0;
|
int x = 0;
|
||||||
int radius_int = corner_radius;
|
int radius_int = corner_radius;
|
||||||
@ -560,7 +588,7 @@ static cairo_surface_t *render_background(cairo_surface_t *srf,
|
|||||||
else
|
else
|
||||||
height += settings.separator_height;
|
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 */
|
/* adding frame */
|
||||||
x += settings.frame_width;
|
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);
|
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_set_source_rgba(c, cl->frame.r, cl->frame.g, cl->frame.b, cl->frame.a);
|
||||||
cairo_fill(c);
|
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_set_source_rgba(c, cl->bg.r, cl->bg.g, cl->bg.b, cl->bg.a);
|
||||||
cairo_fill(c);
|
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);
|
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_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);
|
cairo_fill(c);
|
||||||
}
|
}
|
||||||
@ -604,18 +632,18 @@ static cairo_surface_t *render_background(cairo_surface_t *srf,
|
|||||||
if (ret_width)
|
if (ret_width)
|
||||||
*ret_width = 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;
|
int h_without_progress_bar = h;
|
||||||
if (have_progress_bar(cl->n)){
|
if (have_progress_bar(cl->n)){
|
||||||
h_without_progress_bar -= settings.progress_bar_height + settings.padding;
|
h_without_progress_bar -= settings.progress_bar_height + settings.padding;
|
||||||
}
|
}
|
||||||
int h_text;
|
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,
|
int text_x = settings.h_padding,
|
||||||
text_y = settings.padding + h_without_progress_bar / 2 - h_text / 2;
|
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
|
// icon position
|
||||||
if (settings.icon_position == ICON_LEFT) {
|
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
|
} // 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);
|
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_update_layout(c, cl->l);
|
||||||
@ -645,8 +673,8 @@ static void render_content(cairo_t *c, struct colored_layout *cl, int width)
|
|||||||
|
|
||||||
// icon positioning
|
// icon positioning
|
||||||
if (cl->icon) {
|
if (cl->icon) {
|
||||||
unsigned int image_width = cairo_image_surface_get_width(cl->icon),
|
unsigned int image_width = get_icon_width(cl->icon, scale),
|
||||||
image_height = cairo_image_surface_get_height(cl->icon),
|
image_height = get_icon_height(cl->icon, scale),
|
||||||
image_x = width - settings.h_padding - image_width,
|
image_x = width - settings.h_padding - image_width,
|
||||||
image_y = settings.padding + h_without_progress_bar/2 - image_height/2;
|
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;
|
image_x = settings.h_padding;
|
||||||
} // else ICON_RIGHT
|
} // else ICON_RIGHT
|
||||||
|
|
||||||
cairo_set_source_surface(c, cl->icon, image_x, image_y);
|
cairo_set_source_surface(c, cl->icon, image_x * scale, image_y * scale);
|
||||||
cairo_rectangle(c, image_x, image_y, image_width, image_height);
|
draw_rect(c, image_x, image_y, image_width, image_height, scale);
|
||||||
cairo_fill(c);
|
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
|
// Note: the bar could be drawn a bit smaller, because the frame is drawn on top
|
||||||
// left side
|
// left side
|
||||||
cairo_set_source_rgba(c, cl->highlight.r, cl->highlight.g, cl->highlight.b, cl->highlight.a);
|
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);
|
cairo_fill(c);
|
||||||
// right side
|
// right side
|
||||||
cairo_set_source_rgba(c, cl->bg.r, cl->bg.g, cl->bg.b, cl->bg.a);
|
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);
|
cairo_fill(c);
|
||||||
// border
|
// border
|
||||||
cairo_set_source_rgba(c, cl->frame.r, cl->frame.g, cl->frame.b, cl->frame.a);
|
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);
|
// TODO draw_rect instead of cairo_rectangle resulted in blurry lines. Why?
|
||||||
cairo_set_line_width(c, frame_width);
|
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);
|
cairo_stroke(c);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -710,18 +739,19 @@ static struct dimensions layout_render(cairo_surface_t *srf,
|
|||||||
bool first,
|
bool first,
|
||||||
bool last)
|
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;
|
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_width = 0;
|
||||||
int bg_height = MAX(settings.notification_height, (2 * settings.padding) + cl_h);
|
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);
|
cairo_t *c = cairo_create(content);
|
||||||
|
|
||||||
render_content(c, cl, bg_width);
|
render_content(c, cl, bg_width, scale);
|
||||||
|
|
||||||
/* adding frame */
|
/* adding frame */
|
||||||
if (first)
|
if (first)
|
||||||
@ -773,8 +803,9 @@ void draw(void)
|
|||||||
GSList *layouts = create_layouts(output->win_get_context(win));
|
GSList *layouts = create_layouts(output->win_get_context(win));
|
||||||
|
|
||||||
struct dimensions dim = calculate_dimensions(layouts);
|
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;
|
bool first = true;
|
||||||
for (GSList *iter = layouts; iter; iter = iter->next) {
|
for (GSList *iter = layouts; iter; iter = iter->next) {
|
||||||
@ -799,4 +830,14 @@ void draw_deinit(void)
|
|||||||
output->win_destroy(win);
|
output->win_destroy(win);
|
||||||
output->deinit();
|
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: */
|
/* vim: set ft=c tabstop=8 shiftwidth=8 expandtab textwidth=0: */
|
||||||
|
@ -12,9 +12,13 @@ void draw_setup(void);
|
|||||||
|
|
||||||
void draw(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);
|
void draw_deinit(void);
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
/* vim: set ft=c tabstop=8 shiftwidth=8 expandtab textwidth=0: */
|
/* 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;
|
GMainLoop *mainloop = NULL;
|
||||||
|
|
||||||
static struct dunst_status status;
|
static struct dunst_status status;
|
||||||
|
static bool setup_done = false;
|
||||||
|
|
||||||
/* see dunst.h */
|
/* see dunst.h */
|
||||||
void dunst_status(const enum dunst_status_field field,
|
void dunst_status(const enum dunst_status_field field,
|
||||||
@ -56,6 +57,14 @@ static gboolean run(void *data);
|
|||||||
|
|
||||||
void wake_up(void)
|
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");
|
LOG_D("Waking up");
|
||||||
run(NULL);
|
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
|
// we do not call wakeup now, wake_up does not work here yet
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setup_done = true;
|
||||||
run(NULL);
|
run(NULL);
|
||||||
g_main_loop_run(mainloop);
|
g_main_loop_run(mainloop);
|
||||||
g_clear_pointer(&mainloop, g_main_loop_unref);
|
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)
|
cairo_surface_t *gdk_pixbuf_to_cairo_surface(GdkPixbuf *pixbuf)
|
||||||
{
|
{
|
||||||
assert(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.
|
* @param pixbuf (nullable) The pixbuf, which may be too big.
|
||||||
* Takes ownership of the reference.
|
* 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
|
* @return the scaled version of the pixbuf. If scaling wasn't
|
||||||
* necessary, it returns the same pixbuf. Transfers full
|
* necessary, it returns the same pixbuf. Transfers full
|
||||||
* ownership of the reference.
|
* 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);
|
ASSERT_OR_RET(pixbuf, NULL);
|
||||||
|
|
||||||
int w = gdk_pixbuf_get_width(pixbuf);
|
int w = gdk_pixbuf_get_width(pixbuf);
|
||||||
int h = gdk_pixbuf_get_height(pixbuf);
|
int h = gdk_pixbuf_get_height(pixbuf);
|
||||||
|
|
||||||
|
|
||||||
|
// TODO immediately rescale icon upon scale changes
|
||||||
if (icon_size_clamp(&w, &h)) {
|
if (icon_size_clamp(&w, &h)) {
|
||||||
GdkPixbuf *scaled = gdk_pixbuf_scale_simple(
|
GdkPixbuf *scaled = gdk_pixbuf_scale_simple(
|
||||||
pixbuf,
|
pixbuf,
|
||||||
w,
|
w * dpi_scale,
|
||||||
h,
|
h * dpi_scale,
|
||||||
GDK_INTERP_BILINEAR);
|
GDK_INTERP_BILINEAR);
|
||||||
g_object_unref(pixbuf);
|
g_object_unref(pixbuf);
|
||||||
pixbuf = scaled;
|
pixbuf = scaled;
|
||||||
@ -168,7 +180,7 @@ static GdkPixbuf *icon_pixbuf_scale(GdkPixbuf *pixbuf)
|
|||||||
return 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));
|
char *path = string_to_path(g_strdup(filename));
|
||||||
GError *error = NULL;
|
GError *error = NULL;
|
||||||
@ -179,10 +191,11 @@ GdkPixbuf *get_pixbuf_from_file(const char *filename)
|
|||||||
g_free(path);
|
g_free(path);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
// TODO immediately rescale icon upon scale changes
|
||||||
icon_size_clamp(&w, &h);
|
icon_size_clamp(&w, &h);
|
||||||
GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file_at_scale(path,
|
GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file_at_scale(path,
|
||||||
w,
|
w * scale,
|
||||||
h,
|
h * scale,
|
||||||
TRUE,
|
TRUE,
|
||||||
&error);
|
&error);
|
||||||
|
|
||||||
@ -250,7 +263,7 @@ char *get_path_from_icon_name(const char *iconname)
|
|||||||
return new_name;
|
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);
|
char *path = get_path_from_icon_name(iconname);
|
||||||
if (!path) {
|
if (!path) {
|
||||||
@ -259,7 +272,7 @@ GdkPixbuf *get_pixbuf_from_icon(const char *iconname)
|
|||||||
|
|
||||||
GdkPixbuf *pixbuf = NULL;
|
GdkPixbuf *pixbuf = NULL;
|
||||||
|
|
||||||
pixbuf = get_pixbuf_from_file(path);
|
pixbuf = get_pixbuf_from_file(path, scale);
|
||||||
g_free(path);
|
g_free(path);
|
||||||
|
|
||||||
if (!pixbuf)
|
if (!pixbuf)
|
||||||
@ -268,18 +281,18 @@ GdkPixbuf *get_pixbuf_from_icon(const char *iconname)
|
|||||||
return pixbuf;
|
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(name, NULL);
|
||||||
ASSERT_OR_RET(id, NULL);
|
ASSERT_OR_RET(id, NULL);
|
||||||
|
|
||||||
GdkPixbuf *pb = get_pixbuf_from_icon(name);
|
GdkPixbuf *pb = get_pixbuf_from_icon(name, scale);
|
||||||
if (pb)
|
if (pb)
|
||||||
*id = g_strdup(name);
|
*id = g_strdup(name);
|
||||||
return pb;
|
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(data, NULL);
|
||||||
ASSERT_OR_RET(id, NULL);
|
ASSERT_OR_RET(id, NULL);
|
||||||
@ -389,7 +402,7 @@ GdkPixbuf *icon_get_for_data(GVariant *data, char **id)
|
|||||||
g_free(data_chk);
|
g_free(data_chk);
|
||||||
g_variant_unref(data_variant);
|
g_variant_unref(data_variant);
|
||||||
|
|
||||||
pixbuf = icon_pixbuf_scale(pixbuf);
|
pixbuf = icon_pixbuf_scale(pixbuf, dpi_scale);
|
||||||
|
|
||||||
return pixbuf;
|
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.
|
/** Retrieve an icon by its full filepath, scaled according to settings.
|
||||||
*
|
*
|
||||||
* @param filename A string representing a readable file path
|
* @param filename A string representing a readable file path
|
||||||
|
* @param scale An integer representing the output dpi scaling.
|
||||||
*
|
*
|
||||||
* @return an instance of `GdkPixbuf`
|
* @return an instance of `GdkPixbuf`
|
||||||
* @retval NULL: file does not exist, not readable, etc..
|
* @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.
|
/** 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
|
* @param iconname A string describing a `file://` URL, an arbitary filename
|
||||||
* or an icon name, which then gets searched for in the
|
* or an icon name, which then gets searched for in the
|
||||||
* settings.icon_path
|
* settings.icon_path
|
||||||
|
* @param scale An integer representing the output dpi scaling.
|
||||||
*
|
*
|
||||||
* @return an instance of `GdkPixbuf`
|
* @return an instance of `GdkPixbuf`
|
||||||
* @retval NULL: file does not exist, not readable, etc..
|
* @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
|
/** 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.
|
* get searched in the folders of the icon_path setting.
|
||||||
* @param id (necessary) A unique identifier of the returned pixbuf. Only filled,
|
* @param id (necessary) A unique identifier of the returned pixbuf. Only filled,
|
||||||
* if the return value is non-NULL.
|
* 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
|
* @return an instance of `GdkPixbuf`, representing the name's image
|
||||||
* @retval NULL: Invalid path given
|
* @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
|
/** 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.
|
* like described in the notification spec.
|
||||||
* @param id (necessary) A unique identifier of the returned pixbuf.
|
* @param id (necessary) A unique identifier of the returned pixbuf.
|
||||||
* Only filled, if the return value is non-NULL.
|
* 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
|
* @return an instance of `GdkPixbuf` derived from the GVariant
|
||||||
* @retval NULL: GVariant parameter nulled, invalid or in wrong format
|
* @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
|
#endif
|
||||||
/* vim: set ft=c tabstop=8 shiftwidth=8 expandtab textwidth=0: */
|
/* vim: set ft=c tabstop=8 shiftwidth=8 expandtab textwidth=0: */
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
#include "rules.h"
|
#include "rules.h"
|
||||||
#include "settings.h"
|
#include "settings.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
#include "draw.h"
|
||||||
|
|
||||||
static void notification_extract_urls(struct notification *n);
|
static void notification_extract_urls(struct notification *n);
|
||||||
static void notification_format_message(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_object(&n->icon);
|
||||||
g_clear_pointer(&n->icon_id, g_free);
|
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)
|
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_object(&n->icon);
|
||||||
g_clear_pointer(&n->icon_id, g_free);
|
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 */
|
/* see notification.h */
|
||||||
|
@ -29,7 +29,9 @@ const struct output output_x11 = {
|
|||||||
get_active_screen,
|
get_active_screen,
|
||||||
|
|
||||||
x_is_idle,
|
x_is_idle,
|
||||||
have_fullscreen_window
|
have_fullscreen_window,
|
||||||
|
|
||||||
|
x_get_scale,
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef ENABLE_WAYLAND
|
#ifdef ENABLE_WAYLAND
|
||||||
@ -49,7 +51,9 @@ const struct output output_wl = {
|
|||||||
wl_get_active_screen,
|
wl_get_active_screen,
|
||||||
|
|
||||||
wl_is_idle,
|
wl_is_idle,
|
||||||
wl_have_fullscreen_window
|
wl_have_fullscreen_window,
|
||||||
|
|
||||||
|
wl_get_scale,
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -44,6 +44,8 @@ struct output {
|
|||||||
|
|
||||||
bool (*is_idle)(void);
|
bool (*is_idle)(void);
|
||||||
bool (*have_fullscreen_window)(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 x, int32_t y, int32_t phy_width, int32_t phy_height,
|
||||||
int32_t subpixel, const char *make, const char *model,
|
int32_t subpixel, const char *make, const char *model,
|
||||||
int32_t transform) {
|
int32_t transform) {
|
||||||
//TODO
|
//TODO do something with the subpixel data
|
||||||
struct dunst_output *output = data;
|
struct dunst_output *output = data;
|
||||||
output->subpixel = subpixel;
|
output->subpixel = subpixel;
|
||||||
}
|
}
|
||||||
@ -116,6 +116,8 @@ static void output_handle_scale(void *data, struct wl_output *wl_output,
|
|||||||
int32_t factor) {
|
int32_t factor) {
|
||||||
struct dunst_output *output = data;
|
struct dunst_output *output = data;
|
||||||
output->scale = factor;
|
output->scale = factor;
|
||||||
|
|
||||||
|
wake_up();
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct wl_output_listener output_listener = {
|
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);
|
LOG_I("New output found - id %i", number);
|
||||||
output->global_name = global_name;
|
output->global_name = global_name;
|
||||||
output->wl_output = wl_output;
|
output->wl_output = wl_output;
|
||||||
// TODO: Fix this
|
|
||||||
output->scale = 1;
|
output->scale = 1;
|
||||||
output->fullscreen = false;
|
output->fullscreen = false;
|
||||||
wl_list_insert(&ctx.outputs, &output->link);
|
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);
|
ctx.pointer.wl_pointer = wl_seat_get_pointer(wl_seat);
|
||||||
wl_pointer_add_listener(ctx.pointer.wl_pointer,
|
wl_pointer_add_listener(ctx.pointer.wl_pointer,
|
||||||
&pointer_listener, ctx.seat);
|
&pointer_listener, ctx.seat);
|
||||||
LOG_I("Adding pointer");
|
|
||||||
}
|
}
|
||||||
if (ctx.touch.wl_touch != NULL) {
|
if (ctx.touch.wl_touch != NULL) {
|
||||||
wl_touch_release(ctx.touch.wl_touch);
|
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
|
// Warning, can return NULL
|
||||||
static struct dunst_output *get_configured_output() {
|
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){
|
switch (settings.f_mode){
|
||||||
case FOLLOW_NONE: ; // this semicolon is neccesary
|
case FOLLOW_NONE: ; // this semicolon is neccesary
|
||||||
int n = 0;
|
if (!configured_output) {
|
||||||
int target_monitor = settings.monitor;
|
LOG_W("Monitor %i doesn't exist, using focused monitor", settings.monitor);
|
||||||
|
|
||||||
struct dunst_output *output;
|
|
||||||
wl_list_for_each(output, &ctx.outputs, link) {
|
|
||||||
if (n == target_monitor)
|
|
||||||
return output;
|
|
||||||
n++;
|
|
||||||
}
|
}
|
||||||
LOG_W("Monitor %i doesn't exist, using focused monitor", settings.monitor);
|
return configured_output;
|
||||||
return NULL;
|
|
||||||
case FOLLOW_MOUSE:
|
case FOLLOW_MOUSE:
|
||||||
// fallthrough
|
// fallthrough
|
||||||
case FOLLOW_KEYBOARD:
|
case FOLLOW_KEYBOARD:
|
||||||
@ -626,7 +635,7 @@ static void schedule_frame_and_commit();
|
|||||||
|
|
||||||
// Draw and commit a new frame.
|
// Draw and commit a new frame.
|
||||||
static void send_frame() {
|
static void send_frame() {
|
||||||
int scale = 1;
|
int scale = wl_get_scale();
|
||||||
|
|
||||||
struct dunst_output *output = get_configured_output();
|
struct dunst_output *output = get_configured_output();
|
||||||
int height = ctx.cur_dim.h;
|
int height = ctx.cur_dim.h;
|
||||||
@ -692,8 +701,6 @@ static void send_frame() {
|
|||||||
if (ctx.height != height || ctx.width != width) {
|
if (ctx.height != height || ctx.width != width) {
|
||||||
struct dimensions dim = ctx.cur_dim;
|
struct dimensions dim = ctx.cur_dim;
|
||||||
// Set window size
|
// 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,
|
zwlr_layer_surface_v1_set_size(ctx.layer_surface,
|
||||||
dim.w, dim.h);
|
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) {
|
void wl_display_surface(cairo_surface_t *srf, window winptr, const struct dimensions* dim) {
|
||||||
/* struct window_wl *win = (struct window_wl*)winptr; */
|
/* 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_t *c = ctx.current_buffer->cairo;
|
||||||
cairo_save(c);
|
cairo_save(c);
|
||||||
cairo_set_source_surface(c, srf, 0, 0);
|
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_fill(c);
|
||||||
cairo_restore(c);
|
cairo_restore(c);
|
||||||
|
|
||||||
@ -851,6 +861,7 @@ const struct screen_info* wl_get_active_screen(void) {
|
|||||||
.id = 0,
|
.id = 0,
|
||||||
.mmh = 500
|
.mmh = 500
|
||||||
};
|
};
|
||||||
|
scr.dpi = wl_get_scale() * 96;
|
||||||
return &scr;
|
return &scr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -886,4 +897,21 @@ bool wl_have_fullscreen_window(void) {
|
|||||||
LOG_D("Fullscreen queried: %i", have_fullscreen);
|
LOG_D("Fullscreen queried: %i", have_fullscreen);
|
||||||
return 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: */
|
/* 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_is_idle(void);
|
||||||
bool wl_have_fullscreen_window(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
|
#endif
|
||||||
/* vim: set ft=c tabstop=8 shiftwidth=8 expandtab textwidth=0: */
|
/* 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,
|
draw_rounded_rect(cr, 0, 0,
|
||||||
width, height,
|
width, height,
|
||||||
rad,
|
rad, 1,
|
||||||
true, true);
|
true, true);
|
||||||
cairo_fill(cr);
|
cairo_fill(cr);
|
||||||
|
|
||||||
@ -942,4 +942,8 @@ static void x_shortcut_init(struct keyboard_shortcut *ks)
|
|||||||
g_free(str_begin);
|
g_free(str_begin);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int x_get_scale(void) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
/* vim: set ft=c tabstop=8 shiftwidth=8 expandtab textwidth=0: */
|
/* 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);
|
struct geometry x_parse_geometry(const char *geom_str);
|
||||||
|
|
||||||
|
int x_get_scale(void);
|
||||||
#endif
|
#endif
|
||||||
/* vim: set ft=c tabstop=8 shiftwidth=8 expandtab textwidth=0: */
|
/* 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;
|
extern const char *base;
|
||||||
|
|
||||||
|
int scale = 1;
|
||||||
|
|
||||||
TEST test_get_path_from_icon_null(void){
|
TEST test_get_path_from_icon_null(void){
|
||||||
char *result = get_path_from_icon_name(NULL);
|
char *result = get_path_from_icon_name(NULL);
|
||||||
ASSERT_EQ(result, 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);
|
gchar *path = g_build_filename(base, iconpath, "valid", "icon1.svg", NULL);
|
||||||
path = string_replace_at(path, 0, strlen(home), "~");
|
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);
|
g_clear_pointer(&path, g_free);
|
||||||
|
|
||||||
ASSERT(pixbuf);
|
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);
|
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);
|
g_clear_pointer(&path, g_free);
|
||||||
|
|
||||||
ASSERT(pixbuf);
|
ASSERT(pixbuf);
|
||||||
@ -113,7 +115,7 @@ TEST test_get_pixbuf_from_file_absolute(void)
|
|||||||
|
|
||||||
TEST test_get_pixbuf_from_icon_invalid(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);
|
ASSERT(pixbuf == NULL);
|
||||||
g_clear_pointer(&pixbuf, g_object_unref);
|
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)
|
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
|
// the first icon found is invalid, so the pixbuf is empty
|
||||||
ASSERT(!pixbuf);
|
ASSERT(!pixbuf);
|
||||||
g_clear_pointer(&pixbuf, g_object_unref);
|
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)
|
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);
|
ASSERT(pixbuf);
|
||||||
ASSERTm("SVG pixbuf isn't loaded", IS_ICON_SVG(pixbuf));
|
ASSERTm("SVG pixbuf isn't loaded", IS_ICON_SVG(pixbuf));
|
||||||
g_clear_pointer(&pixbuf, g_object_unref);
|
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)
|
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);
|
ASSERT(pixbuf);
|
||||||
ASSERTm("PNG pixbuf isn't loaded", IS_ICON_PNG(pixbuf));
|
ASSERTm("PNG pixbuf isn't loaded", IS_ICON_PNG(pixbuf));
|
||||||
g_clear_pointer(&pixbuf, g_object_unref);
|
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)
|
TEST test_get_pixbuf_from_icon_filename(void)
|
||||||
{
|
{
|
||||||
char *icon = g_strconcat(base, "/data/icons/valid.png", NULL);
|
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);
|
ASSERT(pixbuf);
|
||||||
ASSERTm("PNG pixbuf isn't loaded", IS_ICON_PNG(pixbuf));
|
ASSERTm("PNG pixbuf isn't loaded", IS_ICON_PNG(pixbuf));
|
||||||
g_clear_pointer(&pixbuf, g_object_unref);
|
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)
|
TEST test_get_pixbuf_from_icon_fileuri(void)
|
||||||
{
|
{
|
||||||
char *icon = g_strconcat("file://", base, "/data/icons/valid.svg", NULL);
|
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);
|
ASSERT(pixbuf);
|
||||||
ASSERTm("SVG pixbuf isn't loaded", IS_ICON_SVG(pixbuf));
|
ASSERTm("SVG pixbuf isn't loaded", IS_ICON_SVG(pixbuf));
|
||||||
g_clear_pointer(&pixbuf, g_object_unref);
|
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)
|
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(pixbuf);
|
||||||
ASSERT_EQ(gdk_pixbuf_get_width(pixbuf), 16);
|
ASSERT_EQ(gdk_pixbuf_get_width(pixbuf), 16);
|
||||||
ASSERT_EQ(gdk_pixbuf_get_height(pixbuf), 16);
|
ASSERT_EQ(gdk_pixbuf_get_height(pixbuf), 16);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user