From c8fc55b5dc5e4b3f3431e0c5786be94213f698a2 Mon Sep 17 00:00:00 2001 From: lilydjwg Date: Tue, 23 Nov 2021 14:30:32 +0800 Subject: [PATCH 1/5] scale cursor too so the mouse pointer doesn't change above notification --- include/mako.h | 1 + wayland.c | 33 +++++++++++++++++++++++++++------ 2 files changed, 28 insertions(+), 6 deletions(-) diff --git a/include/mako.h b/include/mako.h index 9117011..b35bc74 100644 --- a/include/mako.h +++ b/include/mako.h @@ -63,6 +63,7 @@ struct mako_state { struct wl_cursor_theme *cursor_theme; const struct wl_cursor_image *cursor_image; struct wl_surface *cursor_surface; + int32_t cursor_scale; struct wl_list surfaces; // mako_surface::link diff --git a/wayland.c b/wayland.c index eacdc50..81e5b10 100644 --- a/wayland.c +++ b/wayland.c @@ -176,7 +176,8 @@ static void pointer_handle_enter(void *data, struct wl_pointer *wl_pointer, // Change the mouse cursor to "left_ptr" if (state->cursor_theme != NULL) { wl_pointer_set_cursor(wl_pointer, serial, state->cursor_surface, - state->cursor_image->hotspot_x, state->cursor_image->hotspot_y); + state->cursor_image->hotspot_x / state->cursor_scale, + state->cursor_image->hotspot_y / state->cursor_scale); } } @@ -307,6 +308,7 @@ static const struct wl_surface_listener surface_listener = { static void schedule_frame_and_commit(struct mako_surface *state); static void send_frame(struct mako_surface *surface); +void setup_cursor(struct mako_state *state, int scale); static void layer_surface_handle_configure(void *data, struct zwlr_layer_surface_v1 *surface, @@ -452,6 +454,10 @@ bool init_wayland(struct mako_state *state) { } } + return true; +} + +void setup_cursor(struct mako_state *state, int scale) { // Set up the cursor. It needs a wl_surface with the cursor loaded into it. // If one of these fail, mako will work fine without the cursor being able to change. const char *cursor_size_env = getenv("XCURSOR_SIZE"); @@ -467,10 +473,13 @@ bool init_wayland(struct mako_state *state) { fprintf(stderr, "Error: XCURSOR_SIZE is invalid\n"); } } - state->cursor_theme = wl_cursor_theme_load(NULL, cursor_size, state->shm); + if (state->cursor_theme) { + wl_cursor_theme_destroy(state->cursor_theme); + } + state->cursor_theme = wl_cursor_theme_load(NULL, cursor_size * scale, state->shm); if (state->cursor_theme == NULL) { fprintf(stderr, "couldn't find a cursor theme\n"); - return true; + return; } struct wl_cursor *cursor = wl_cursor_theme_get_cursor(state->cursor_theme, "left_ptr"); if (cursor == NULL) { @@ -478,15 +487,15 @@ bool init_wayland(struct mako_state *state) { wl_cursor_theme_destroy(state->cursor_theme); // Set to NULL so it doesn't get free'd again state->cursor_theme = NULL; - return true; + return; } state->cursor_image = cursor->images[0]; struct wl_buffer *cursor_buffer = wl_cursor_image_get_buffer(cursor->images[0]); state->cursor_surface = wl_compositor_create_surface(state->compositor); wl_surface_attach(state->cursor_surface, cursor_buffer, 0, 0); + wl_surface_set_buffer_scale(state->cursor_surface, scale); wl_surface_commit(state->cursor_surface); - - return true; + state->cursor_scale = scale; } void finish_wayland(struct mako_state *state) { @@ -645,6 +654,9 @@ static void send_frame(struct mako_surface *surface) { zwlr_layer_surface_v1_set_anchor(surface->layer_surface, surface->anchor); wl_surface_commit(surface->surface); + if (state->cursor_scale != scale) { + setup_cursor(state, scale); + } // Now we're going to bail without drawing anything. This gives the // compositor a chance to create the surface and tell us what size we @@ -708,6 +720,15 @@ static void schedule_frame_and_commit(struct mako_surface *surface) { surface->frame_callback = wl_surface_frame(surface->surface); wl_callback_add_listener(surface->frame_callback, &frame_listener, surface); wl_surface_commit(surface->surface); + + struct mako_state *state = surface->state; + if (surface->surface_output != NULL) { + int scale = surface->surface_output->scale; + if (state->cursor_scale != scale) { + // output or output scale changed, update cursor + setup_cursor(state, scale); + } + } } void set_dirty(struct mako_surface *surface) { From 47ac373d567a834fa92dc0e4d02be1b637a8ce0a Mon Sep 17 00:00:00 2001 From: lilydjwg Date: Tue, 23 Nov 2021 14:12:08 +0800 Subject: [PATCH 2/5] make_surface.scale is unused --- include/mako.h | 1 - 1 file changed, 1 deletion(-) diff --git a/include/mako.h b/include/mako.h index b35bc74..9a08bc1 100644 --- a/include/mako.h +++ b/include/mako.h @@ -33,7 +33,6 @@ struct mako_surface { struct wl_callback *frame_callback; bool configured; bool dirty; // Do we need to redraw? - int32_t scale; char *configured_output; enum zwlr_layer_shell_v1_layer layer; From 80f98d2a8693ef02f8cecbe9316c6291e7109962 Mon Sep 17 00:00:00 2001 From: lilydjwg Date: Tue, 23 Nov 2021 18:22:46 +0800 Subject: [PATCH 3/5] use last_scale initially to avoid many redraws (which cause flickering) --- include/mako.h | 1 + main.c | 1 + wayland.c | 3 ++- 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/include/mako.h b/include/mako.h index 9a08bc1..ece4ea0 100644 --- a/include/mako.h +++ b/include/mako.h @@ -70,6 +70,7 @@ struct mako_state { struct wl_list notifications; // mako_notification::link struct wl_list history; // mako_notification::link char *current_mode; + uint32_t last_scale; int argc; char **argv; diff --git a/main.c b/main.c index 44f2094..b93c5e5 100644 --- a/main.c +++ b/main.c @@ -70,6 +70,7 @@ static bool init(struct mako_state *state) { wl_list_init(&state->notifications); wl_list_init(&state->history); state->current_mode = strdup("default"); + state->last_scale = 1; return true; } diff --git a/wayland.c b/wayland.c index 81e5b10..7620c21 100644 --- a/wayland.c +++ b/wayland.c @@ -571,9 +571,10 @@ static void schedule_frame_and_commit(struct mako_surface *surface); static void send_frame(struct mako_surface *surface) { struct mako_state *state = surface->state; - int scale = 1; + int scale = state->last_scale; if (surface->surface_output != NULL) { scale = surface->surface_output->scale; + state->last_scale = scale; } surface->current_buffer = From a9f17443a43b33fcea99155c227cd8b0ce4c548a Mon Sep 17 00:00:00 2001 From: lilydjwg Date: Tue, 23 Nov 2021 19:10:24 +0800 Subject: [PATCH 4/5] don't redraw if the surface size isn't changed --- wayland.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/wayland.c b/wayland.c index 7620c21..e5e6534 100644 --- a/wayland.c +++ b/wayland.c @@ -315,11 +315,17 @@ static void layer_surface_handle_configure(void *data, uint32_t serial, uint32_t width, uint32_t height) { struct mako_surface *msurface = data; + zwlr_layer_surface_v1_ack_configure(surface, serial); + + if (msurface->configured && msurface->width == (int)width + && msurface->height == (int)height) { + return; + } + msurface->configured = true; msurface->width = width; msurface->height = height; - zwlr_layer_surface_v1_ack_configure(surface, serial); send_frame(msurface); } From fe7f49463e29e3275f7183b5f8d44e080d9203a8 Mon Sep 17 00:00:00 2001 From: lilydjwg Date: Tue, 23 Nov 2021 19:21:34 +0800 Subject: [PATCH 5/5] fix schedule_frame_and_commit declaration --- wayland.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/wayland.c b/wayland.c index e5e6534..228a1fe 100644 --- a/wayland.c +++ b/wayland.c @@ -306,7 +306,7 @@ static const struct wl_surface_listener surface_listener = { }; -static void schedule_frame_and_commit(struct mako_surface *state); +static void schedule_frame_and_commit(struct mako_surface *surface); static void send_frame(struct mako_surface *surface); void setup_cursor(struct mako_state *state, int scale); @@ -571,8 +571,6 @@ static struct mako_output *get_configured_output(struct mako_surface *surface) { return NULL; } -static void schedule_frame_and_commit(struct mako_surface *surface); - // Draw and commit a new frame. static void send_frame(struct mako_surface *surface) { struct mako_state *state = surface->state;