Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor draw code to use cairo_surface_set_device_scale #1337

Draft
wants to merge 4 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
169 changes: 70 additions & 99 deletions src/draw.c

Large diffs are not rendered by default.

5 changes: 1 addition & 4 deletions src/draw.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,10 +57,7 @@ void draw_setup(void);

void draw(void);

void draw_rounded_rect(cairo_t *c, float x, float y, int width, int height, int corner_radius, double scale, enum corner_pos corners);

// TODO get rid of this function by passing scale to everything that needs it.
double draw_get_scale(void);
void draw_rounded_rect(cairo_t *c, int x, int y, int width, int height, int corner_radius, enum corner_pos corners);

void draw_deinit(void);

Expand Down
25 changes: 12 additions & 13 deletions src/icon.c
Original file line number Diff line number Diff line change
Expand Up @@ -83,12 +83,12 @@ static void pixbuf_data_to_cairo_data(
}
}

int get_icon_width(cairo_surface_t *icon, double scale) {
return round(cairo_image_surface_get_width(icon) / scale);
int get_icon_width(cairo_surface_t *icon) {
return cairo_image_surface_get_width(icon);
}

int get_icon_height(cairo_surface_t *icon, double scale) {
return round(cairo_image_surface_get_height(icon) / scale);
int get_icon_height(cairo_surface_t *icon) {
return cairo_image_surface_get_height(icon);
}

cairo_surface_t *gdk_pixbuf_to_cairo_surface(GdkPixbuf *pixbuf)
Expand Down Expand Up @@ -154,14 +154,13 @@ static bool icon_size_clamp(int *w, int *h, int min_size, int max_size) {
*
* @param pixbuf (nullable) The pixbuf, which may be too big.
* Takes ownership of the reference.
* @param dpi_scale A double for the dpi scaling.
* @param min_size The minimum allowed icon size.
* @param max_size The maximum allowed icon size.
* @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_to_size(GdkPixbuf *pixbuf, double dpi_scale, int min_size, int max_size)
static GdkPixbuf *icon_pixbuf_scale_to_size(GdkPixbuf *pixbuf, int min_size, int max_size)
{
ASSERT_OR_RET(pixbuf, NULL);

Expand All @@ -170,8 +169,8 @@ static GdkPixbuf *icon_pixbuf_scale_to_size(GdkPixbuf *pixbuf, double dpi_scale,

// TODO immediately rescale icon upon scale changes
if(icon_size_clamp(&w, &h, min_size, max_size)) {
w = round(w * dpi_scale);
h = round(h * dpi_scale);
//w = round(w * dpi_scale);
//h = round(h * dpi_scale);
}
GdkPixbuf *scaled = gdk_pixbuf_scale_simple(
pixbuf,
Expand All @@ -183,7 +182,7 @@ static GdkPixbuf *icon_pixbuf_scale_to_size(GdkPixbuf *pixbuf, double dpi_scale,
return pixbuf;
}

GdkPixbuf *get_pixbuf_from_file(const char *filename, int min_size, int max_size, double scale)
GdkPixbuf *get_pixbuf_from_file(const char *filename, int min_size, int max_size)
{
GError *error = NULL;
gint w, h;
Expand All @@ -196,8 +195,8 @@ GdkPixbuf *get_pixbuf_from_file(const char *filename, int min_size, int max_size
// TODO immediately rescale icon upon scale changes
icon_size_clamp(&w, &h, min_size, max_size);
pixbuf = gdk_pixbuf_new_from_file_at_scale(filename,
round(w * scale),
round(h * scale),
w,
h,
TRUE,
&error);

Expand Down Expand Up @@ -270,7 +269,7 @@ char *get_path_from_icon_name(const char *iconname, int size)
return new_name;
}

GdkPixbuf *icon_get_for_data(GVariant *data, char **id, double dpi_scale, int min_size, int max_size)
GdkPixbuf *icon_get_for_data(GVariant *data, char **id, int min_size, int max_size)
{
ASSERT_OR_RET(data, NULL);
ASSERT_OR_RET(id, NULL);
Expand Down Expand Up @@ -380,7 +379,7 @@ GdkPixbuf *icon_get_for_data(GVariant *data, char **id, double dpi_scale, int mi
g_free(data_chk);
g_variant_unref(data_variant);

pixbuf = icon_pixbuf_scale_to_size(pixbuf, dpi_scale, min_size, max_size);
pixbuf = icon_pixbuf_scale_to_size(pixbuf, min_size, max_size);

return pixbuf;
}
Expand Down
10 changes: 4 additions & 6 deletions src/icon.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,11 @@ cairo_surface_t *gdk_pixbuf_to_cairo_surface(GdkPixbuf *pixbuf);
* @param filename A string representing a readable file path
* @param min_size An iteger representing the desired minimum unscaled icon size.
* @param max_size An iteger representing the desired maximum unscaled icon size.
* @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, int min_size, int max_size, double scale);
GdkPixbuf *get_pixbuf_from_file(const char *filename, int min_size, int max_size);


/**
Expand All @@ -27,12 +26,12 @@ GdkPixbuf *get_pixbuf_from_file(const char *filename, int min_size, int max_size
* 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, double scale);
int get_icon_width(cairo_surface_t *icon);

/**
* Get the unscaled icon height, see get_icon_width.
*/
int get_icon_height(cairo_surface_t *icon, double scale);
int get_icon_height(cairo_surface_t *icon);

/** Retrieve a path from an icon name.
*
Expand All @@ -56,13 +55,12 @@ char *get_path_from_icon_name(const char *iconname, int size);
* 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 dpi_scale An integer representing the output dpi scaling.
* @param min_size An integer representing the desired minimum unscaled icon size.
* @param max_size An integer representing the desired maximum unscaled icon size.
* @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, double dpi_scale, int min_size, int max_size);
GdkPixbuf *icon_get_for_data(GVariant *data, char **id, int min_size, int max_size);

#endif
/* vim: set ft=c tabstop=8 shiftwidth=8 expandtab textwidth=0: */
7 changes: 2 additions & 5 deletions src/notification.c
Original file line number Diff line number Diff line change
Expand Up @@ -356,9 +356,7 @@ void notification_icon_replace_path(struct notification *n, const char *new_icon
g_free(n->icon_path);
n->icon_path = get_path_from_icon_name(new_icon, n->min_icon_size);
if (n->icon_path) {
GdkPixbuf *pixbuf = get_pixbuf_from_file(n->icon_path,
n->min_icon_size, n->max_icon_size,
draw_get_scale());
GdkPixbuf *pixbuf = get_pixbuf_from_file(n->icon_path, n->min_icon_size, n->max_icon_size);
if (pixbuf) {
n->icon = gdk_pixbuf_to_cairo_surface(pixbuf);
g_object_unref(pixbuf);
Expand All @@ -377,8 +375,7 @@ void notification_icon_replace_data(struct notification *n, GVariant *new_icon)
n->icon = NULL;
g_clear_pointer(&n->icon_id, g_free);

GdkPixbuf *icon = icon_get_for_data(new_icon, &n->icon_id,
draw_get_scale(), n->min_icon_size, n->max_icon_size);
GdkPixbuf *icon = icon_get_for_data(new_icon, &n->icon_id, n->min_icon_size, n->max_icon_size);
n->icon = gdk_pixbuf_to_cairo_surface(icon);
if (icon)
g_object_unref(icon);
Expand Down
2 changes: 2 additions & 0 deletions src/output.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ const struct output output_x11 = {

x_display_surface,
x_win_get_context,
x_win_get_surface,

get_active_screen,

Expand All @@ -51,6 +52,7 @@ const struct output output_wl = {

wl_display_surface,
wl_win_get_context,
wl_win_get_surface,

wl_get_active_screen,

Expand Down
2 changes: 2 additions & 0 deletions src/output.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ struct screen_info {
int dpi;
};

// NOTE: Refactor the output struct
struct output {
bool (*init)(void);
void (*deinit)(void);
Expand All @@ -42,6 +43,7 @@ struct output {
void (*display_surface)(cairo_surface_t *srf, window win, const struct dimensions*);

cairo_t* (*win_get_context)(window);
cairo_surface_t* (*win_get_surface)(window);

const struct screen_info* (*get_active_screen)(void);

Expand Down
25 changes: 20 additions & 5 deletions src/wayland/wl.c
Original file line number Diff line number Diff line change
Expand Up @@ -583,10 +583,10 @@ 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; */
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);
double scale = wl_get_scale();
int w = round(dim->w * scale), h = round(dim->h * scale);
LOG_D("Buffer size (scaled) %ix%i", w, h);
ctx.current_buffer = get_next_buffer(ctx.shm, ctx.buffers, w, h);

if(ctx.current_buffer == NULL) {
return;
Expand All @@ -595,7 +595,7 @@ void wl_display_surface(cairo_surface_t *srf, window winptr, const struct dimens
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 * scale, dim->h * scale);
cairo_rectangle(c, 0, 0, w, h);
cairo_fill(c);
cairo_restore(c);

Expand All @@ -618,6 +618,18 @@ cairo_t* wl_win_get_context(window winptr) {
return win->c_ctx;
}

cairo_surface_t* wl_win_get_surface(window winptr) {
struct window_wl *win = (struct window_wl*)winptr;
ctx.current_buffer = get_next_buffer(ctx.shm, ctx.buffers, 500, 500);

if(ctx.current_buffer == NULL) {
return NULL;
}

win->c_surface = ctx.current_buffer->surface;
return win->c_surface;
}

const struct screen_info* wl_get_active_screen(void) {
static struct screen_info scr = {
.w = 3840,
Expand Down Expand Up @@ -685,6 +697,9 @@ bool wl_have_fullscreen_window(void) {
}

double wl_get_scale(void) {
if (settings.scale > 0)
return settings.scale;

int scale = 0;
struct dunst_output *output = get_configured_output();
if (output) {
Expand Down
1 change: 1 addition & 0 deletions src/wayland/wl.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ void wl_win_hide(window);

void wl_display_surface(cairo_surface_t *srf, window win, const struct dimensions*);
cairo_t* wl_win_get_context(window);
cairo_surface_t* wl_win_get_surface(window);

const struct screen_info* wl_get_active_screen(void);

Expand Down
8 changes: 6 additions & 2 deletions src/wayland/wl_seat.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include "../log.h"
#include "../settings.h"
#include "wl_ctx.h"
#include "wl.h"

static void touch_handle_motion(void *data, struct wl_touch *wl_touch,
uint32_t time, int32_t id,
Expand Down Expand Up @@ -50,8 +51,10 @@ static void touch_handle_up(void *data, struct wl_touch *wl_touch,
if (id >= MAX_TOUCHPOINTS) {
return;
}

double scale = wl_get_scale();
input_handle_click(BTN_TOUCH, false,
seat->touch.pts[id].x, seat->touch.pts[id].y);
seat->touch.pts[id].x/scale, seat->touch.pts[id].y/scale);

}

Expand Down Expand Up @@ -100,7 +103,8 @@ static void pointer_handle_button(void *data, struct wl_pointer *wl_pointer,
uint32_t button_state) {
struct dunst_seat *seat = data;

input_handle_click(button, button_state, seat->pointer.x, seat->pointer.y);
double scale = wl_get_scale();
input_handle_click(button, button_state, seat->pointer.x/scale, seat->pointer.y/scale);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

before wayland didn't scale the user input

}

static void pointer_handle_leave(void *data, struct wl_pointer *wl_pointer,
Expand Down
10 changes: 6 additions & 4 deletions src/x11/x.c
Original file line number Diff line number Diff line change
Expand Up @@ -118,10 +118,7 @@ static void x_win_corners_shape(struct window_x11 *win, const int rad)
cairo_paint(cr);
cairo_set_source_rgba(cr, 1, 1, 1, 1);

draw_rounded_rect(cr, 0, 0,
width, height,
rad, 1,
settings.corners);
draw_rounded_rect(cr, 0, 0, width, height, rad, settings.corners);
cairo_fill(cr);

cairo_show_page(cr);
Expand Down Expand Up @@ -197,6 +194,11 @@ cairo_t* x_win_get_context(window winptr)
return ((struct window_x11*)win)->c_ctx;
}

cairo_surface_t* x_win_get_surface(window win)
{
return ((struct window_x11*)win)->root_surface;
}

static void setopacity(Window win, unsigned long opacity)
{
Atom _NET_WM_WINDOW_OPACITY =
Expand Down
1 change: 1 addition & 0 deletions src/x11/x.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ void x_win_hide(window);
void x_display_surface(cairo_surface_t *srf, window, const struct dimensions *dim);

cairo_t* x_win_get_context(window);
cairo_surface_t* x_win_get_surface(window);

/* X misc */
bool x_is_idle(void);
Expand Down
2 changes: 2 additions & 0 deletions test/draw.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ const struct output dummy_output = {

wl_display_surface,
wl_win_get_context,
wl_win_get_surface,

noop_screen,

Expand All @@ -48,6 +49,7 @@ const struct output dummy_output = {

x_display_surface,
x_win_get_context,
x_win_get_surface,

noop_screen,

Expand Down
16 changes: 8 additions & 8 deletions test/notification.c
Original file line number Diff line number Diff line change
Expand Up @@ -168,8 +168,8 @@ TEST test_notification_icon_scaling_toosmall(void)
struct notification *n = notification_load_icon_with_scaling(20, 100);

ASSERT(n->icon);
ASSERT_EQ(get_icon_width(n->icon, 1), 20);
ASSERT_EQ(get_icon_height(n->icon, 1), 20);
ASSERT_EQ(get_icon_width(n->icon), 20);
ASSERT_EQ(get_icon_height(n->icon), 20);

notification_unref(n);

Expand All @@ -182,8 +182,8 @@ TEST test_notification_icon_scaling_toolarge(void)
struct notification *n = notification_load_icon_with_scaling(5, 10);

ASSERT(n->icon);
ASSERT_EQ(get_icon_width(n->icon, 1), 10);
ASSERT_EQ(get_icon_height(n->icon, 1), 10);
ASSERT_EQ(get_icon_width(n->icon), 10);
ASSERT_EQ(get_icon_height(n->icon), 10);

notification_unref(n);

Expand All @@ -195,8 +195,8 @@ TEST test_notification_icon_scaling_notconfigured(void)
struct notification *n = notification_load_icon_with_scaling(0, 0);

ASSERT(n->icon);
ASSERT_EQ(get_icon_width(n->icon, 1), 16);
ASSERT_EQ(get_icon_height(n->icon, 1), 16);
ASSERT_EQ(get_icon_width(n->icon), 16);
ASSERT_EQ(get_icon_height(n->icon), 16);

notification_unref(n);

Expand All @@ -208,8 +208,8 @@ TEST test_notification_icon_scaling_notneeded(void)
struct notification *n = notification_load_icon_with_scaling(10, 20);

ASSERT(n->icon);
ASSERT_EQ(get_icon_width(n->icon, 1), 16);
ASSERT_EQ(get_icon_height(n->icon, 1), 16);
ASSERT_EQ(get_icon_width(n->icon), 16);
ASSERT_EQ(get_icon_height(n->icon), 16);

notification_unref(n);

Expand Down
Loading