summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDudemanguy <random342@airmail.cc>2021-06-28 11:03:51 -0500
committerDudemanguy <random342@airmail.cc>2021-06-30 16:37:36 +0000
commitf2afae55e95b4b1eec1aeb828ba6ff1f0695d993 (patch)
treecb8bb2abd59d938077544c1732173dae2c4fef4f
parent0c1544e66cb980bd8a1dedb13ac07904380da608 (diff)
downloadmpv-f2afae55e95b4b1eec1aeb828ba6ff1f0695d993.tar.bz2
mpv-f2afae55e95b4b1eec1aeb828ba6ff1f0695d993.tar.xz
wayland: refactor surface scaling
Another day, another wayland refactor. Way back when, dcc3c2e added support for the hidpi-window-scale option (something you probably should never set to no but whatever) to wayland. Well technically, it never had any runtime toggling support (don't remember if detecting when vo_opts changed was possible or not then; maybe not). Anyways in the process of fixing that, I went ahead and refactored how this is all handled. The key difference is that when hidpi-window-scale is disabled, wl->scaling is directly set to 1 instead of forcibly setting wl->current_output->scale to 1. Note that scaling operations don't always require a geometry reset/resize so set_surface_scaling needs to be separate from set_geometry. The logic here is kind of complicated but it (should) be correct.
-rw-r--r--video/out/wayland_common.c88
-rw-r--r--video/out/wayland_common.h1
2 files changed, 56 insertions, 33 deletions
diff --git a/video/out/wayland_common.c b/video/out/wayland_common.c
index 13cdf5f2f8..4157782c0c 100644
--- a/video/out/wayland_common.c
+++ b/video/out/wayland_common.c
@@ -153,8 +153,8 @@ static int spawn_cursor(struct vo_wayland_state *wl);
static void greatest_common_divisor(struct vo_wayland_state *wl, int a, int b);
static void queue_new_sync(struct vo_wayland_state *wl);
static void remove_output(struct vo_wayland_output *out);
-static void rescale_geometry_dimensions(struct vo_wayland_state *wl, double factor);
static void set_geometry(struct vo_wayland_state *wl);
+static void set_surface_scaling(struct vo_wayland_state *wl);
static void sync_shift(struct vo_wayland_state *wl);
static void window_move(struct vo_wayland_state *wl, uint32_t serial);
@@ -652,8 +652,12 @@ static void output_handle_done(void* data, struct wl_output *wl_output)
* output must have changed (resolution, scale, etc). All window
* geometry and scaling should be recalculated. */
if (wl->current_output && wl->current_output->output == wl_output) {
- wl->scaling = wl->current_output->scale;
- wl_surface_set_buffer_scale(wl->surface, wl->scaling);
+ set_surface_scaling(wl);
+ if (!wl->vo_opts->fullscreen && !wl->vo_opts->window_maximized) {
+ wl_surface_set_buffer_scale(wl->surface, wl->scaling);
+ } else {
+ wl->scale_change = true;
+ }
spawn_cursor(wl);
set_geometry(wl);
wl->window_size = wl->vdparams;
@@ -703,21 +707,23 @@ static void surface_handle_enter(void *data, struct wl_surface *wl_surface,
wl->current_output->has_surface = true;
bool force_resize = false;
+ if (wl->scaling != wl->current_output->scale) {
+ set_surface_scaling(wl);
+ if (!wl->vo_opts->fullscreen && !wl->vo_opts->window_maximized) {
+ wl->scale_change = true;
+ } else {
+ wl_surface_set_buffer_scale(wl->surface, wl->scaling);
+ }
+ spawn_cursor(wl);
+ wl->pending_vo_events |= VO_EVENT_DPI;
+ }
+
if (!mp_rect_equals(&old_output_geometry, &wl->current_output->geometry)) {
set_geometry(wl);
wl->window_size = wl->vdparams;
force_resize = true;
}
- if (wl->scaling != wl->current_output->scale && wl->vo_opts->hidpi_window_scale) {
- double factor = (double)wl->scaling / wl->current_output->scale;
- wl->scaling = wl->current_output->scale;
- wl_surface_set_buffer_scale(wl->surface, wl->scaling);
- spawn_cursor(wl);
- rescale_geometry_dimensions(wl, factor);
- wl->pending_vo_events |= VO_EVENT_DPI;
- }
-
if (!wl->vo_opts->fullscreen && !wl->vo_opts->window_maximized)
wl->geometry = wl->window_size;
@@ -849,6 +855,11 @@ static void handle_toplevel_config(void *data, struct xdg_toplevel *toplevel,
wl->toplevel_width = width;
wl->toplevel_height = height;
+ if (wl->scale_change) {
+ wl_surface_set_buffer_scale(wl->surface, wl->scaling);
+ wl->scale_change = false;
+ }
+
if (wl->state_change) {
if (!is_fullscreen && !is_maximized) {
wl->geometry = wl->window_size;
@@ -1315,18 +1326,6 @@ static void remove_output(struct vo_wayland_output *out)
return;
}
-static void rescale_geometry_dimensions(struct vo_wayland_state *wl, double factor)
-{
- wl->vdparams.x1 *= factor;
- wl->vdparams.y1 *= factor;
- wl->window_size.x1 *= factor;
- wl->window_size.y1 *= factor;
- if (!wl->vo_opts->fullscreen && !wl->vo_opts->window_maximized) {
- wl->geometry.x1 *= factor;
- wl->geometry.y1 *= factor;
- }
-}
-
static void set_border_decorations(struct vo_wayland_state *wl, int state)
{
if (!wl->xdg_toplevel_decoration) {
@@ -1406,6 +1405,22 @@ static int set_screensaver_inhibitor(struct vo_wayland_state *wl, int state)
return VO_TRUE;
}
+static void set_surface_scaling(struct vo_wayland_state *wl)
+{
+ int old_scale = wl->scaling;
+ if (wl->vo_opts->hidpi_window_scale) {
+ wl->scaling = wl->current_output->scale;
+ } else {
+ wl->scaling = 1;
+ }
+
+ double factor = (double)old_scale / wl->scaling;
+ wl->vdparams.x1 *= factor;
+ wl->vdparams.y1 *= factor;
+ wl->window_size.x1 *= factor;
+ wl->window_size.y1 *= factor;
+}
+
static int spawn_cursor(struct vo_wayland_state *wl)
{
/* Reuse if size is identical */
@@ -1546,16 +1561,25 @@ int vo_wayland_control(struct vo *vo, int *events, int request, void *arg)
case VOCTRL_VO_OPTS_CHANGED: {
void *opt;
while (m_config_cache_get_next_changed(wl->vo_opts_cache, &opt)) {
+ if (opt == &opts->appid)
+ update_app_id(wl);
+ if (opt == &opts->border)
+ set_border_decorations(wl, opts->border);
if (opt == &opts->fullscreen)
toggle_fullscreen(wl);
- if (opt == &opts->window_minimized)
- do_minimize(wl);
+ if (opt == &opts->hidpi_window_scale)
+ {
+ set_surface_scaling(wl);
+ if (!wl->vo_opts->fullscreen && !wl->vo_opts->window_maximized) {
+ wl_surface_set_buffer_scale(wl->surface, wl->scaling);
+ } else {
+ wl->scale_change = true;
+ }
+ }
if (opt == &opts->window_maximized)
toggle_maximized(wl);
- if (opt == &opts->border)
- set_border_decorations(wl, opts->border);
- if (opt == &opts->appid)
- update_app_id(wl);
+ if (opt == &opts->window_minimized)
+ do_minimize(wl);
if (opt == &opts->geometry || opt == &opts->autofit ||
opt == &opts->autofit_smaller || opt == &opts->autofit_larger)
{
@@ -1734,9 +1758,7 @@ int vo_wayland_reconfig(struct vo *vo)
wl->current_output = find_output(wl);
if (!wl->current_output)
return false;
- if (!wl->vo_opts->hidpi_window_scale)
- wl->current_output->scale = 1;
- wl->scaling = wl->current_output->scale;
+ set_surface_scaling(wl);
wl_surface_set_buffer_scale(wl->surface, wl->scaling);
wl_surface_commit(wl->surface);
configure = true;
diff --git a/video/out/wayland_common.h b/video/out/wayland_common.h
index 9d8c514d47..b77bab462b 100644
--- a/video/out/wayland_common.h
+++ b/video/out/wayland_common.h
@@ -59,6 +59,7 @@ struct vo_wayland_state {
bool focused;
bool frame_wait;
bool hidden;
+ bool scale_change;
bool state_change;
bool toplevel_configured;
int display_fd;