History

wayland: fix vertical resizing

Resizing in strictly the vertical direction has been broken forever on wayland. It's because of how the keepaspect calculation always resized with respect to the width. So if you moved the mouse strictly vertically with no change left/right, the mpv window would never change size since it just calculates with respect to the width that doesn't change. Fixing this is kind of weird and maybe someone should think of a better algorithm for preserving aspect ratio (we just multiply by the gcd basically), but whatever. You might naively try something like "resize with respect to what direction changes the most" at first, but this leads to very cludgy resizing since during a typical mouse dragging motion, it will flip constantly from "resize w/ respect to the width" and "resize w/ respect to the height". It "works" but it's really ugly and not worth it. The trick is to realize that we need to consider the resizing state as one continuous motion, choose a direction initially, stick to it throughout the entirety of the resize, and reset the relevant parameters after we finish the resize. This ensures the direction never unintuitively flips during a motion, but also allows for the strictly vertical case to still work. Might as well note it here in the commit, but mpv's resizing behavior technically violates xdg-shell. For the resizing event, "[t]he window geometry specified in the configure event is a maximum; the client cannot resize beyond it." Well, we do obviously go beyond the maximum in certain cases. For example consider resizing strictly horizontally. The width value increases from the compositor but not the height. Since mpv preserves aspect ratio by default, the height obviously must increase which will go over the prescribed bounds by the compositor. This happens before and after this commit, and I think everyone agrees is the desired behavior. With this commit, now vertical resizing works which violates xdg-shell in the same way. Before, it incidentally obeyed the protocol since it did not resize at all, but let's presume users expect the window to actually get bigger when they do a drag resize. *: https://wayland.app/protocols/xdg-shell#xdg_toplevel:enum:state:entry:resizing

Dudemanguy committed 2 years ago

Commit e6c536a1 parent 5edc8972 files · +43 −0Browse files

Unified · Split

2 files
  1. video/out/wayland_common.c +41 −0
  2. video/out/wayland_common.h +2 −0
video/out/wayland_common.c+41−0
@@ -66,6 +66,11 @@ · 65 unmodified lines
6666 #define WAYLAND_SCALE_FACTOR 120.0
6767
6868
69+enum resizing_constraint {
70+ MP_WIDTH_CONSTRAINT = 1,
71+ MP_HEIGHT_CONSTRAINT = 2,
72+};
73+
6974 static const struct mp_keymap keymap[] = {
7075 /* Special keys */
7176 {XKB_KEY_Pause, MP_KEY_PAUSE}, {XKB_KEY_Escape, MP_KEY_ESC},
@@ -1038,6 +1043,7 @@ static void handle_toplevel_config(void *data, struct xdg_toplevel *toplevel, · 966 unmodified lines
10381043 bool is_maximized = false;
10391044 bool is_fullscreen = false;
10401045 bool is_activated = false;
1046+ bool is_resizing = false;
10411047 bool is_suspended = false;
10421048 bool is_tiled = false;
10431049 enum xdg_toplevel_state *state;
@@ -1047,6 +1053,7 @@ static void handle_toplevel_config(void *data, struct xdg_toplevel *toplevel, · 3 unmodified lines
10471053 is_fullscreen = true;
10481054 break;
10491055 case XDG_TOPLEVEL_STATE_RESIZING:
1056+ is_resizing = true;
10501057 break;
10511058 case XDG_TOPLEVEL_STATE_ACTIVATED:
10521059 is_activated = true;
@@ -1077,6 +1084,11 @@ static void handle_toplevel_config(void *data, struct xdg_toplevel *toplevel, · 24 unmodified lines
10771084 if (wl->hidden != is_suspended)
10781085 wl->hidden = is_suspended;
10791086
1087+ if (wl->resizing != is_resizing) {
1088+ wl->resizing = is_resizing;
1089+ wl->resizing_constraint = 0;
1090+ }
1091+
10801092 if (opts->fullscreen != is_fullscreen) {
10811093 wl->state_change = wl->reconfigured;
10821094 opts->fullscreen = is_fullscreen;
@@ -1553,10 +1565,39 @@ static void apply_keepaspect(struct vo_wayland_state *wl, int *width, int *heigh · 470 unmodified lines
15531565 if (!wl->opts->keepaspect)
15541566 return;
15551567
1568+ int phys_width = handle_round(wl->scaling, *width);
1569+ int phys_height = handle_round(wl->scaling, *height);
1570+
1571+ // Ensure that the size actually changes before we start trying to actually
1572+ // calculate anything so the wrong constraint for the rezie isn't choosen.
1573+ if (wl->resizing && !wl->resizing_constraint &&
1574+ phys_width == mp_rect_w(wl->geometry) && phys_height == mp_rect_h(wl->geometry))
1575+ return;
1576+
1577+ // We are doing a continuous resize (e.g. dragging with mouse), constrain the
1578+ // aspect ratio against the height if the change is only in the height
1579+ // coordinate.
1580+ if (wl->resizing && !wl->resizing_constraint && phys_width == mp_rect_w(wl->geometry) &&
1581+ phys_height != mp_rect_h(wl->geometry)) {
1582+ wl->resizing_constraint = MP_HEIGHT_CONSTRAINT;
1583+ } else if (!wl->resizing_constraint) {
1584+ wl->resizing_constraint = MP_WIDTH_CONSTRAINT;
1585+ }
1586+
1587+ if (wl->resizing_constraint == MP_HEIGHT_CONSTRAINT) {
1588+ MPSWAP(int, *width, *height);
1589+ MPSWAP(int, wl->reduced_width, wl->reduced_height);
1590+ }
1591+
15561592 double scale_factor = (double)*width / wl->reduced_width;
15571593 *width = ceil(wl->reduced_width * scale_factor);
15581594 if (wl->opts->keepaspect_window)
15591595 *height = ceil(wl->reduced_height * scale_factor);
1596+
1597+ if (wl->resizing_constraint == MP_HEIGHT_CONSTRAINT) {
1598+ MPSWAP(int, *width, *height);
1599+ MPSWAP(int, wl->reduced_width, wl->reduced_height);
1600+ }
15601601 }
15611602
15621603 static void free_dnd_data(struct vo_wayland_state *wl)
video/out/wayland_common.h+2−0
@@ -68,6 +68,7 @@ struct vo_wayland_state { · 67 unmodified lines
6868 bool locked_size;
6969 bool need_rescale;
7070 bool reconfigured;
71+ bool resizing;
7172 bool scale_configured;
7273 bool state_change;
7374 bool tiled;
@@ -79,6 +80,7 @@ struct vo_wayland_state { · 5 unmodified lines
7980 int pending_scaling; // base 120
8081 int scaling; // base 120
8182 double scaling_factor; // wl->scaling divided by 120
83+ int resizing_constraint;
8284 int timeout_count;
8385 int wakeup_pipe[2];
8486

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t