mirror of
https://github.com/labwc/labwc.git
synced 2026-02-24 01:40:15 -05:00
magnifier: refactor magnifier_draw()
This commit is contained in:
parent
a40c779e59
commit
c9eaecb3ee
1 changed files with 62 additions and 88 deletions
150
src/magnifier.c
150
src/magnifier.c
|
|
@ -3,6 +3,7 @@
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <wlr/render/swapchain.h>
|
#include <wlr/render/swapchain.h>
|
||||||
#include <wlr/types/wlr_output.h>
|
#include <wlr/types/wlr_output.h>
|
||||||
|
#include "common/box.h"
|
||||||
#include "common/macros.h"
|
#include "common/macros.h"
|
||||||
#include "labwc.h"
|
#include "labwc.h"
|
||||||
#include "magnifier.h"
|
#include "magnifier.h"
|
||||||
|
|
@ -15,73 +16,51 @@ static double mag_scale = 0.0;
|
||||||
static struct wlr_buffer *tmp_buffer = NULL;
|
static struct wlr_buffer *tmp_buffer = NULL;
|
||||||
static struct wlr_texture *tmp_texture = NULL;
|
static struct wlr_texture *tmp_texture = NULL;
|
||||||
|
|
||||||
#define CLAMP(in, lower, upper) MAX(MIN((in), (upper)), (lower))
|
|
||||||
|
|
||||||
void
|
void
|
||||||
magnifier_draw(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;
|
|
||||||
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 server *server = output->server;
|
||||||
struct theme *theme = server->theme;
|
struct theme *theme = server->theme;
|
||||||
struct wlr_cursor *cursor = server->seat.cursor;
|
bool fullscreen = (rc.mag_width == -1 || rc.mag_height == -1);
|
||||||
double ox = cursor->x;
|
|
||||||
double oy = cursor->y;
|
struct wlr_box output_box = {
|
||||||
wlr_output_layout_output_coords(server->output_layout, output->wlr_output, &ox, &oy);
|
.width = output_buffer->width,
|
||||||
ox *= output->wlr_output->scale;
|
.height = output_buffer->height,
|
||||||
oy *= output->wlr_output->scale;
|
};
|
||||||
if (rc.mag_width == -1 || rc.mag_height == -1) {
|
|
||||||
fullscreen = true;
|
/* Cursor position in physical output coordinate */
|
||||||
}
|
double cursor_x = server->seat.cursor->x;
|
||||||
if ((ox < 0 || oy < 0 || ox >= output_buffer->width || oy >= output_buffer->height)
|
double cursor_y = server->seat.cursor->y;
|
||||||
&& fullscreen) {
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mag_scale == 0.0) {
|
if (mag_scale == 0.0) {
|
||||||
mag_scale = rc.mag_scale;
|
mag_scale = rc.mag_scale;
|
||||||
}
|
}
|
||||||
if (mag_scale == 0.0) {
|
assert(mag_scale >= 1.0);
|
||||||
mag_scale = 1.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
/* Magnifier geometry in physical output coordinate */
|
||||||
|
struct wlr_box mag_box;
|
||||||
if (fullscreen) {
|
if (fullscreen) {
|
||||||
width = output_buffer->width;
|
mag_box = output_box;
|
||||||
height = output_buffer->height;
|
|
||||||
x = 0;
|
|
||||||
y = 0;
|
|
||||||
} else {
|
} else {
|
||||||
width = rc.mag_width + 1;
|
mag_box.x = cursor_x - (rc.mag_width / 2.0);
|
||||||
height = rc.mag_height + 1;
|
mag_box.y = cursor_y - (rc.mag_height / 2.0);
|
||||||
x = ox - (rc.mag_width / 2.0);
|
mag_box.width = rc.mag_width;
|
||||||
y = oy - (rc.mag_height / 2.0);
|
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 */
|
/* (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");
|
wlr_log(WLR_DEBUG, "tmp magnifier buffer size changed, dropping");
|
||||||
assert(tmp_texture);
|
assert(tmp_texture);
|
||||||
wlr_texture_destroy(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) {
|
if (!tmp_buffer) {
|
||||||
tmp_buffer = wlr_allocator_create_buffer(
|
tmp_buffer = wlr_allocator_create_buffer(
|
||||||
server->allocator, width, height,
|
server->allocator, mag_box.width, mag_box.height,
|
||||||
&output->wlr_output->swapchain->format);
|
&output->wlr_output->swapchain->format);
|
||||||
}
|
}
|
||||||
if (!tmp_buffer) {
|
if (!tmp_buffer) {
|
||||||
|
|
@ -124,13 +103,17 @@ magnifier_draw(struct output *output, struct wlr_buffer *output_buffer, struct w
|
||||||
goto cleanup;
|
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 = {
|
struct wlr_render_texture_options opts = {
|
||||||
.texture = output_texture,
|
.texture = output_texture,
|
||||||
.src_box = (struct wlr_fbox) {
|
.src_box = box_to_fbox(&src_box_for_copy),
|
||||||
x, y, cropped_width, cropped_height },
|
.dst_box = dst_box_for_copy,
|
||||||
.dst_box = (struct wlr_box) {
|
|
||||||
dst_x, dst_y, cropped_width, cropped_height },
|
|
||||||
.alpha = NULL,
|
|
||||||
};
|
};
|
||||||
wlr_render_pass_add_texture(tmp_render_pass, &opts);
|
wlr_render_pass_add_texture(tmp_render_pass, &opts);
|
||||||
if (!wlr_render_pass_submit(tmp_render_pass)) {
|
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;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Borders */
|
struct wlr_box damage_box;
|
||||||
if (fullscreen) {
|
if (fullscreen) {
|
||||||
border_box.x = 0;
|
damage_box = output_box;
|
||||||
border_box.y = 0;
|
|
||||||
border_box.width = width;
|
|
||||||
border_box.height = height;
|
|
||||||
} else {
|
} else {
|
||||||
border_box.x = ox - (width / 2 + theme->mag_border_width);
|
/* Draw borders */
|
||||||
border_box.y = oy - (height / 2 + theme->mag_border_width);
|
struct wlr_box border_box = {
|
||||||
border_box.width = (width + theme->mag_border_width * 2);
|
.x = mag_box.x - theme->mag_border_width,
|
||||||
border_box.height = (height + theme->mag_border_width * 2);
|
.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 = {
|
struct wlr_render_rect_options bg_opts = {
|
||||||
.box = border_box,
|
.box = border_box,
|
||||||
.color = (struct wlr_render_color) {
|
.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],
|
.b = theme->mag_border_color[2],
|
||||||
.a = theme->mag_border_color[3]
|
.a = theme->mag_border_color[3]
|
||||||
},
|
},
|
||||||
.clip = NULL,
|
|
||||||
};
|
};
|
||||||
wlr_render_pass_add_rect(tmp_render_pass, &bg_opts);
|
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;
|
struct wlr_fbox src_box_for_paste = {
|
||||||
src_box.height = height / mag_scale;
|
.width = mag_box.width / mag_scale,
|
||||||
dst_box.width = width;
|
.height = mag_box.height / mag_scale,
|
||||||
dst_box.height = height;
|
};
|
||||||
|
|
||||||
if (fullscreen) {
|
if (fullscreen) {
|
||||||
src_box.x = CLAMP(ox - (ox / mag_scale), 0.0,
|
src_box_for_paste.x = cursor_x - (cursor_x / mag_scale);
|
||||||
width * (mag_scale - 1.0) / mag_scale);
|
src_box_for_paste.y = cursor_y - (cursor_y / 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;
|
|
||||||
} else {
|
} else {
|
||||||
src_box.x = width * (mag_scale - 1.0) / (2.0 * mag_scale);
|
src_box_for_paste.x =
|
||||||
src_box.y = height * (mag_scale - 1.0) / (2.0 * mag_scale);
|
mag_box.width * (mag_scale - 1.0) / (2.0 * mag_scale);
|
||||||
dst_box.x = ox - (width / 2);
|
src_box_for_paste.y =
|
||||||
dst_box.y = oy - (height / 2);
|
mag_box.height * (mag_scale - 1.0) / (2.0 * mag_scale);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Paste the magnified result back into the output buffer */
|
/* Paste the magnified result back into the output buffer */
|
||||||
opts = (struct wlr_render_texture_options) {
|
opts = (struct wlr_render_texture_options) {
|
||||||
.texture = tmp_texture,
|
.texture = tmp_texture,
|
||||||
.src_box = src_box,
|
.src_box = src_box_for_paste,
|
||||||
.dst_box = dst_box,
|
.dst_box = mag_box,
|
||||||
.alpha = NULL,
|
|
||||||
.clip = NULL,
|
|
||||||
.filter_mode = rc.mag_filter ? WLR_SCALE_FILTER_BILINEAR
|
.filter_mode = rc.mag_filter ? WLR_SCALE_FILTER_BILINEAR
|
||||||
: WLR_SCALE_FILTER_NEAREST,
|
: 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 */
|
/* And finally mark the extra damage */
|
||||||
*damage = border_box;
|
*damage = damage_box;
|
||||||
damage->width += 1;
|
|
||||||
damage->height += 1;
|
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
wlr_buffer_unlock(output_buffer);
|
wlr_buffer_unlock(output_buffer);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue