From cfbe54e67a04094a3c42b6658d41c264dcb9e266 Mon Sep 17 00:00:00 2001 From: tokyo4j Date: Sat, 22 Feb 2025 15:20:53 +0900 Subject: [PATCH 1/5] box: add box_to_fbox() --- include/common/box.h | 2 ++ src/common/box.c | 11 +++++++++++ 2 files changed, 13 insertions(+) diff --git a/include/common/box.h b/include/common/box.h index 3d8e917f..6dc2fe3e 100644 --- a/include/common/box.h +++ b/include/common/box.h @@ -22,4 +22,6 @@ void box_union(struct wlr_box *box_dest, struct wlr_box *box_a, */ struct wlr_box box_fit_within(int width, int height, struct wlr_box *bounding_box); +struct wlr_fbox box_to_fbox(struct wlr_box *box); + #endif /* LABWC_BOX_H */ diff --git a/src/common/box.c b/src/common/box.c index 978108fd..a6316d16 100644 --- a/src/common/box.c +++ b/src/common/box.c @@ -73,3 +73,14 @@ box_fit_within(int width, int height, struct wlr_box *bound) return box; } + +struct wlr_fbox +box_to_fbox(struct wlr_box *box) +{ + return (struct wlr_fbox){ + .x = box->x, + .y = box->y, + .width = box->width, + .height = box->height, + }; +} From b66c0d87972c1333f75cb924e4e349c63bd1e8c2 Mon Sep 17 00:00:00 2001 From: tokyo4j Date: Sat, 22 Feb 2025 15:21:32 +0900 Subject: [PATCH 2/5] magnifier: rename some functions --- include/magnifier.h | 10 +++++----- src/action.c | 6 +++--- src/common/scene-helpers.c | 4 ++-- src/magnifier.c | 10 +++++----- src/server.c | 2 +- 5 files changed, 16 insertions(+), 16 deletions(-) diff --git a/include/magnifier.h b/include/magnifier.h index daa6d7a3..afe79e22 100644 --- a/include/magnifier.h +++ b/include/magnifier.h @@ -14,12 +14,12 @@ enum magnify_dir { MAGNIFY_DECREASE }; -void magnify_toggle(struct server *server); -void magnify_set_scale(struct server *server, enum magnify_dir dir); +void magnifier_toggle(struct server *server); +void magnifier_set_scale(struct server *server, enum magnify_dir dir); bool output_wants_magnification(struct output *output); -void magnify(struct output *output, struct wlr_buffer *output_buffer, +void magnifier_draw(struct output *output, struct wlr_buffer *output_buffer, struct wlr_box *damage); -bool is_magnify_on(void); -void magnify_reset(void); +bool magnifier_is_enabled(void); +void magnifier_reset(void); #endif /* LABWC_MAGNIFIER_H */ diff --git a/src/action.c b/src/action.c index 3b03558c..a9fa40b7 100644 --- a/src/action.c +++ b/src/action.c @@ -1319,13 +1319,13 @@ actions_run(struct view *activator, struct server *server, rc.tablet.force_mouse_emulation = !rc.tablet.force_mouse_emulation; break; case ACTION_TYPE_TOGGLE_MAGNIFY: - magnify_toggle(server); + magnifier_toggle(server); break; case ACTION_TYPE_ZOOM_IN: - magnify_set_scale(server, MAGNIFY_INCREASE); + magnifier_set_scale(server, MAGNIFY_INCREASE); break; case ACTION_TYPE_ZOOM_OUT: - magnify_set_scale(server, MAGNIFY_DECREASE); + magnifier_set_scale(server, MAGNIFY_DECREASE); break; case ACTION_TYPE_WARP_CURSOR: { diff --git a/src/common/scene-helpers.c b/src/common/scene-helpers.c index cc9e4db6..a8558ab1 100644 --- a/src/common/scene-helpers.c +++ b/src/common/scene-helpers.c @@ -114,8 +114,8 @@ lab_wlr_scene_output_commit(struct wlr_scene_output *scene_output, } struct wlr_box additional_damage = {0}; - if (state->buffer && is_magnify_on()) { - magnify(output, state->buffer, &additional_damage); + if (state->buffer && magnifier_is_enabled()) { + magnifier_draw(output, state->buffer, &additional_damage); } bool committed = wlr_output_commit_state(wlr_output, state); diff --git a/src/magnifier.c b/src/magnifier.c index fded35fd..d9f316c1 100644 --- a/src/magnifier.c +++ b/src/magnifier.c @@ -17,7 +17,7 @@ static struct wlr_texture *tmp_texture = NULL; #define CLAMP(in, lower, upper) MAX(MIN((in), (upper)), (lower)) void -magnify(struct output *output, struct wlr_buffer *output_buffer, struct wlr_box *damage) +magnifier_draw(struct output *output, struct wlr_buffer *output_buffer, struct wlr_box *damage) { int width, height; double x, y; @@ -258,7 +258,7 @@ enable_magnifier(struct server *server, bool enable) /* Toggles magnification on and off */ void -magnify_toggle(struct server *server) +magnifier_toggle(struct server *server) { enable_magnifier(server, !magnify_on); @@ -270,7 +270,7 @@ magnify_toggle(struct server *server) /* Increases and decreases magnification scale */ void -magnify_set_scale(struct server *server, enum magnify_dir dir) +magnifier_set_scale(struct server *server, enum magnify_dir dir) { struct output *output = output_nearest_to_cursor(server); @@ -296,7 +296,7 @@ magnify_set_scale(struct server *server, enum magnify_dir dir) /* Reset any buffers held by the magnifier */ void -magnify_reset(void) +magnifier_reset(void) { if (tmp_texture && tmp_buffer) { wlr_texture_destroy(tmp_texture); @@ -308,7 +308,7 @@ magnify_reset(void) /* Report whether magnification is enabled */ bool -is_magnify_on(void) +magnifier_is_enabled(void) { return magnify_on; } diff --git a/src/server.c b/src/server.c index 03fd5cd0..2c546309 100644 --- a/src/server.c +++ b/src/server.c @@ -413,7 +413,7 @@ handle_renderer_lost(struct wl_listener *listener, void *data) reload_config_and_theme(server); - magnify_reset(); + magnifier_reset(); wlr_allocator_destroy(old_allocator); wlr_renderer_destroy(old_renderer); From f9d6fcb1e4dda693884bc22f62ed05487788b3b5 Mon Sep 17 00:00:00 2001 From: tokyo4j Date: Sat, 22 Feb 2025 17:33:48 +0900 Subject: [PATCH 3/5] magnifier: use wlr_output.swapchain.format --- src/magnifier.c | 19 +++---------------- 1 file changed, 3 insertions(+), 16 deletions(-) diff --git a/src/magnifier.c b/src/magnifier.c index d9f316c1..d6700415 100644 --- a/src/magnifier.c +++ b/src/magnifier.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only #include +#include #include #include "common/macros.h" #include "labwc.h" @@ -25,21 +26,6 @@ magnifier_draw(struct output *output, struct wlr_buffer *output_buffer, struct w struct wlr_fbox src_box; bool fullscreen = false; - /* TODO: This looks way too complicated to just get the used format */ - struct wlr_drm_format wlr_drm_format = {0}; - struct wlr_shm_attributes shm_attribs = {0}; - struct wlr_dmabuf_attributes dma_attribs = {0}; - if (wlr_buffer_get_dmabuf(output_buffer, &dma_attribs)) { - wlr_drm_format.format = dma_attribs.format; - wlr_drm_format.len = 1; - wlr_drm_format.modifiers = &dma_attribs.modifier; - } else if (wlr_buffer_get_shm(output_buffer, &shm_attribs)) { - wlr_drm_format.format = shm_attribs.format; - } else { - wlr_log(WLR_ERROR, "Failed to read buffer format"); - return; - } - /* Fetch scale-adjusted cursor coordinates */ struct server *server = output->server; struct theme *theme = server->theme; @@ -105,7 +91,8 @@ magnifier_draw(struct output *output, struct wlr_buffer *output_buffer, struct w } if (!tmp_buffer) { tmp_buffer = wlr_allocator_create_buffer( - server->allocator, width, height, &wlr_drm_format); + server->allocator, width, height, + &output->wlr_output->swapchain->format); } if (!tmp_buffer) { wlr_log(WLR_ERROR, "Failed to allocate temporary magnifier buffer"); From a40c779e59e795953d0cce42bf0f6088d6ff9ba6 Mon Sep 17 00:00:00 2001 From: tokyo4j Date: Sun, 23 Feb 2025 14:05:45 +0900 Subject: [PATCH 4/5] magnifier: make sure magnifier scale is bigger than 1.0 --- src/config/rcxml.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/config/rcxml.c b/src/config/rcxml.c index a3b3ee3a..d24c538d 100644 --- a/src/config/rcxml.c +++ b/src/config/rcxml.c @@ -1267,8 +1267,10 @@ entry(xmlNode *node, char *nodename, char *content, struct parser_state *state) rc.mag_height = atoi(content); } else if (!strcasecmp(nodename, "initScale.magnifier")) { set_float(content, &rc.mag_scale); + rc.mag_scale = MAX(1.0, rc.mag_scale); } else if (!strcasecmp(nodename, "increment.magnifier")) { set_float(content, &rc.mag_increment); + rc.mag_increment = MAX(0, rc.mag_increment); } else if (!strcasecmp(nodename, "useFilter.magnifier")) { set_bool(content, &rc.mag_filter); } @@ -1775,10 +1777,6 @@ post_processing(void) wlr_log(WLR_INFO, "load default window switcher fields"); load_default_window_switcher_fields(); } - - if (rc.mag_scale <= 0.0) { - rc.mag_scale = 1.0; - } } static void From c9eaecb3ee1f010924271e45b74cc8f3fcb48b89 Mon Sep 17 00:00:00 2001 From: tokyo4j Date: Sat, 22 Feb 2025 18:13:11 +0900 Subject: [PATCH 5/5] magnifier: refactor magnifier_draw() --- src/magnifier.c | 150 ++++++++++++++++++++---------------------------- 1 file changed, 62 insertions(+), 88 deletions(-) diff --git a/src/magnifier.c b/src/magnifier.c index d6700415..b026d671 100644 --- a/src/magnifier.c +++ b/src/magnifier.c @@ -3,6 +3,7 @@ #include #include #include +#include "common/box.h" #include "common/macros.h" #include "labwc.h" #include "magnifier.h" @@ -15,73 +16,51 @@ static double mag_scale = 0.0; static struct wlr_buffer *tmp_buffer = NULL; static struct wlr_texture *tmp_texture = NULL; -#define CLAMP(in, lower, upper) MAX(MIN((in), (upper)), (lower)) - void magnifier_draw(struct output *output, struct wlr_buffer *output_buffer, struct wlr_box *damage) { - int width, height; - double x, y; - struct wlr_box border_box, dst_box; - struct wlr_fbox src_box; - bool fullscreen = false; - - /* Fetch scale-adjusted cursor coordinates */ struct server *server = output->server; struct theme *theme = server->theme; - struct wlr_cursor *cursor = server->seat.cursor; - double ox = cursor->x; - double oy = cursor->y; - wlr_output_layout_output_coords(server->output_layout, output->wlr_output, &ox, &oy); - ox *= output->wlr_output->scale; - oy *= output->wlr_output->scale; - if (rc.mag_width == -1 || rc.mag_height == -1) { - fullscreen = true; - } - if ((ox < 0 || oy < 0 || ox >= output_buffer->width || oy >= output_buffer->height) - && fullscreen) { + bool fullscreen = (rc.mag_width == -1 || rc.mag_height == -1); + + struct wlr_box output_box = { + .width = output_buffer->width, + .height = output_buffer->height, + }; + + /* Cursor position in physical output coordinate */ + double cursor_x = server->seat.cursor->x; + double cursor_y = server->seat.cursor->y; + wlr_output_layout_output_coords(server->output_layout, + output->wlr_output, &cursor_x, &cursor_y); + cursor_x *= output->wlr_output->scale; + cursor_y *= output->wlr_output->scale; + + bool cursor_in_output = wlr_box_contains_point(&output_box, + cursor_x, cursor_y); + if (fullscreen && !cursor_in_output) { return; } if (mag_scale == 0.0) { mag_scale = rc.mag_scale; } - if (mag_scale == 0.0) { - mag_scale = 1.0; - } + assert(mag_scale >= 1.0); + /* Magnifier geometry in physical output coordinate */ + struct wlr_box mag_box; if (fullscreen) { - width = output_buffer->width; - height = output_buffer->height; - x = 0; - y = 0; + mag_box = output_box; } else { - width = rc.mag_width + 1; - height = rc.mag_height + 1; - x = ox - (rc.mag_width / 2.0); - y = oy - (rc.mag_height / 2.0); + mag_box.x = cursor_x - (rc.mag_width / 2.0); + mag_box.y = cursor_y - (rc.mag_height / 2.0); + mag_box.width = rc.mag_width; + mag_box.height = rc.mag_height; } - double cropped_width = width; - double cropped_height = height; - double dst_x = 0; - double dst_y = 0; - - /* Ensure everything is kept within output boundaries */ - if (x < 0) { - cropped_width += x; - dst_x = x * -1; - x = 0; - } - if (y < 0) { - cropped_height += y; - dst_y = y * -1; - y = 0; - } - cropped_width = MIN(cropped_width, (double)output_buffer->width - x); - cropped_height = MIN(cropped_height, (double)output_buffer->height - y); /* (Re)create the temporary buffer if required */ - if (tmp_buffer && (tmp_buffer->width != width || tmp_buffer->height != height)) { + if (tmp_buffer && (tmp_buffer->width != mag_box.width + || tmp_buffer->height != mag_box.height)) { wlr_log(WLR_DEBUG, "tmp magnifier buffer size changed, dropping"); assert(tmp_texture); wlr_texture_destroy(tmp_texture); @@ -91,7 +70,7 @@ magnifier_draw(struct output *output, struct wlr_buffer *output_buffer, struct w } if (!tmp_buffer) { tmp_buffer = wlr_allocator_create_buffer( - server->allocator, width, height, + server->allocator, mag_box.width, mag_box.height, &output->wlr_output->swapchain->format); } if (!tmp_buffer) { @@ -124,13 +103,17 @@ magnifier_draw(struct output *output, struct wlr_buffer *output_buffer, struct w goto cleanup; } + struct wlr_box src_box_for_copy; + wlr_box_intersection(&src_box_for_copy, &mag_box, &output_box); + + struct wlr_box dst_box_for_copy = src_box_for_copy; + dst_box_for_copy.x -= mag_box.x; + dst_box_for_copy.y -= mag_box.y; + struct wlr_render_texture_options opts = { .texture = output_texture, - .src_box = (struct wlr_fbox) { - x, y, cropped_width, cropped_height }, - .dst_box = (struct wlr_box) { - dst_x, dst_y, cropped_width, cropped_height }, - .alpha = NULL, + .src_box = box_to_fbox(&src_box_for_copy), + .dst_box = dst_box_for_copy, }; wlr_render_pass_add_texture(tmp_render_pass, &opts); if (!wlr_render_pass_submit(tmp_render_pass)) { @@ -148,17 +131,17 @@ magnifier_draw(struct output *output, struct wlr_buffer *output_buffer, struct w goto cleanup; } - /* Borders */ + struct wlr_box damage_box; if (fullscreen) { - border_box.x = 0; - border_box.y = 0; - border_box.width = width; - border_box.height = height; + damage_box = output_box; } else { - border_box.x = ox - (width / 2 + theme->mag_border_width); - border_box.y = oy - (height / 2 + theme->mag_border_width); - border_box.width = (width + theme->mag_border_width * 2); - border_box.height = (height + theme->mag_border_width * 2); + /* Draw borders */ + struct wlr_box border_box = { + .x = mag_box.x - theme->mag_border_width, + .y = mag_box.y - theme->mag_border_width, + .width = mag_box.width + theme->mag_border_width * 2, + .height = mag_box.height + theme->mag_border_width * 2, + }; struct wlr_render_rect_options bg_opts = { .box = border_box, .color = (struct wlr_render_color) { @@ -167,37 +150,31 @@ magnifier_draw(struct output *output, struct wlr_buffer *output_buffer, struct w .b = theme->mag_border_color[2], .a = theme->mag_border_color[3] }, - .clip = NULL, }; wlr_render_pass_add_rect(tmp_render_pass, &bg_opts); + wlr_box_intersection(&damage_box, &border_box, &output_box); } - src_box.width = width / mag_scale; - src_box.height = height / mag_scale; - dst_box.width = width; - dst_box.height = height; + struct wlr_fbox src_box_for_paste = { + .width = mag_box.width / mag_scale, + .height = mag_box.height / mag_scale, + }; if (fullscreen) { - src_box.x = CLAMP(ox - (ox / mag_scale), 0.0, - width * (mag_scale - 1.0) / mag_scale); - src_box.y = CLAMP(oy - (oy / mag_scale), 0.0, - height * (mag_scale - 1.0) / mag_scale); - dst_box.x = 0; - dst_box.y = 0; + src_box_for_paste.x = cursor_x - (cursor_x / mag_scale); + src_box_for_paste.y = cursor_y - (cursor_y / mag_scale); } else { - src_box.x = width * (mag_scale - 1.0) / (2.0 * mag_scale); - src_box.y = height * (mag_scale - 1.0) / (2.0 * mag_scale); - dst_box.x = ox - (width / 2); - dst_box.y = oy - (height / 2); + src_box_for_paste.x = + mag_box.width * (mag_scale - 1.0) / (2.0 * mag_scale); + src_box_for_paste.y = + mag_box.height * (mag_scale - 1.0) / (2.0 * mag_scale); } /* Paste the magnified result back into the output buffer */ opts = (struct wlr_render_texture_options) { .texture = tmp_texture, - .src_box = src_box, - .dst_box = dst_box, - .alpha = NULL, - .clip = NULL, + .src_box = src_box_for_paste, + .dst_box = mag_box, .filter_mode = rc.mag_filter ? WLR_SCALE_FILTER_BILINEAR : WLR_SCALE_FILTER_NEAREST, }; @@ -208,10 +185,7 @@ magnifier_draw(struct output *output, struct wlr_buffer *output_buffer, struct w } /* And finally mark the extra damage */ - *damage = border_box; - damage->width += 1; - damage->height += 1; - + *damage = damage_box; cleanup: wlr_buffer_unlock(output_buffer); }