summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOlivier Fourdan <ofourdan@redhat.com>2023-11-02 10:25:46 +0100
committerOlivier Fourdan <ofourdan@redhat.com>2024-03-20 09:05:36 +0100
commit54f8fc409091ea3b3466cbf948a53194aaa26aad (patch)
treee2bed5a1ce4b11c958930e3e660f19d4522377e8
parentb678297c53b081d42cb19fabc65d13202ad5494e (diff)
xwayland: Account for the scale factor
Apply the scale factor to the root window and adjust the coordinates and hotspot location for cursors. Signed-off-by: Olivier Fourdan <ofourdan@redhat.com> Reviewed-By: Kenny Levinsen <kl@kl.wtf> Acked-by: Peter Hutterer <peter.hutterer@who-t.net> Part-of: <https://gitlab.freedesktop.org/xorg/xserver/-/merge_requests/1197>
-rw-r--r--hw/xwayland/xwayland-cursor.c22
-rw-r--r--hw/xwayland/xwayland-input.c50
-rw-r--r--hw/xwayland/xwayland-window.c64
3 files changed, 117 insertions, 19 deletions
diff --git a/hw/xwayland/xwayland-cursor.c b/hw/xwayland/xwayland-cursor.c
index bd94b0cfb..9ee427063 100644
--- a/hw/xwayland/xwayland-cursor.c
+++ b/hw/xwayland/xwayland-cursor.c
@@ -156,6 +156,7 @@ xwl_cursor_attach_pixmap(struct xwl_seat *xwl_seat,
struct xwl_cursor *xwl_cursor, PixmapPtr pixmap)
{
struct wl_buffer *buffer;
+ struct xwl_screen *xwl_screen = xwl_seat->xwl_screen;
buffer = xwl_shm_pixmap_get_wl_buffer(pixmap);
if (!buffer) {
@@ -164,7 +165,8 @@ xwl_cursor_attach_pixmap(struct xwl_seat *xwl_seat,
}
wl_surface_attach(xwl_cursor->surface, buffer, 0, 0);
- xwl_surface_damage(xwl_seat->xwl_screen, xwl_cursor->surface, 0, 0,
+ wl_surface_set_buffer_scale(xwl_cursor->surface, xwl_screen->global_surface_scale);
+ xwl_surface_damage(xwl_screen, xwl_cursor->surface, 0, 0,
xwl_seat->x_cursor->bits->width,
xwl_seat->x_cursor->bits->height);
@@ -196,8 +198,10 @@ void
xwl_seat_set_cursor(struct xwl_seat *xwl_seat)
{
struct xwl_cursor *xwl_cursor = &xwl_seat->cursor;
+ struct xwl_screen *xwl_screen = xwl_seat->xwl_screen;
PixmapPtr pixmap;
CursorPtr cursor;
+ int xhot, yhot;
if (!xwl_seat->wl_pointer)
return;
@@ -222,11 +226,14 @@ xwl_seat_set_cursor(struct xwl_seat *xwl_seat)
xwl_cursor_copy_bits_to_pixmap(cursor, pixmap);
+ xhot = xwl_seat->x_cursor->bits->xhot / xwl_screen->global_surface_scale;
+ yhot = xwl_seat->x_cursor->bits->yhot / xwl_screen->global_surface_scale;
+
wl_pointer_set_cursor(xwl_seat->wl_pointer,
xwl_seat->pointer_enter_serial,
xwl_cursor->surface,
- xwl_seat->x_cursor->bits->xhot,
- xwl_seat->x_cursor->bits->yhot);
+ xhot,
+ yhot);
xwl_cursor_attach_pixmap(xwl_seat, xwl_cursor, pixmap);
}
@@ -235,9 +242,11 @@ void
xwl_tablet_tool_set_cursor(struct xwl_tablet_tool *xwl_tablet_tool)
{
struct xwl_seat *xwl_seat = xwl_tablet_tool->seat;
+ struct xwl_screen *xwl_screen = xwl_seat->xwl_screen;
struct xwl_cursor *xwl_cursor = &xwl_tablet_tool->cursor;
PixmapPtr pixmap;
CursorPtr cursor;
+ int xhot, yhot;
if (!xwl_seat->x_cursor) {
zwp_tablet_tool_v2_set_cursor(xwl_tablet_tool->tool,
@@ -260,11 +269,14 @@ xwl_tablet_tool_set_cursor(struct xwl_tablet_tool *xwl_tablet_tool)
xwl_cursor_copy_bits_to_pixmap(cursor, pixmap);
+ xhot = xwl_seat->x_cursor->bits->xhot / xwl_screen->global_surface_scale;
+ yhot = xwl_seat->x_cursor->bits->yhot / xwl_screen->global_surface_scale;
+
zwp_tablet_tool_v2_set_cursor(xwl_tablet_tool->tool,
xwl_tablet_tool->proximity_in_serial,
xwl_cursor->surface,
- xwl_seat->x_cursor->bits->xhot,
- xwl_seat->x_cursor->bits->yhot);
+ xhot,
+ yhot);
xwl_cursor_attach_pixmap(xwl_seat, xwl_cursor, pixmap);
}
diff --git a/hw/xwayland/xwayland-input.c b/hw/xwayland/xwayland-input.c
index abbf3b0e3..cf0ca87b0 100644
--- a/hw/xwayland/xwayland-input.c
+++ b/hw/xwayland/xwayland-input.c
@@ -515,13 +515,13 @@ pointer_handle_enter(void *data, struct wl_pointer *pointer,
wl_fixed_t sx_w, wl_fixed_t sy_w)
{
struct xwl_seat *xwl_seat = data;
+ struct xwl_screen *xwl_screen = xwl_seat->xwl_screen;
DeviceIntPtr dev = get_pointer_device(xwl_seat);
DeviceIntPtr master;
int i;
- int sx = wl_fixed_to_int(sx_w);
- int sy = wl_fixed_to_int(sy_w);
+ int sx, sy;
int dx, dy;
- ScreenPtr pScreen = xwl_seat->xwl_screen->screen;
+ ScreenPtr pScreen = xwl_screen->screen;
ValuatorMask mask;
/* There's a race here where if we create and then immediately
@@ -536,6 +536,9 @@ pointer_handle_enter(void *data, struct wl_pointer *pointer,
if (!is_surface_from_xwl_window(surface))
return;
+ sx = wl_fixed_to_int(sx_w) * xwl_screen->global_surface_scale;
+ sy = wl_fixed_to_int(sy_w) * xwl_screen->global_surface_scale;
+
xwl_seat->xwl_screen->serial = serial;
xwl_seat->pointer_enter_serial = serial;
@@ -624,6 +627,7 @@ pointer_handle_leave(void *data, struct wl_pointer *pointer,
static void
dispatch_relative_motion_with_warp(struct xwl_seat *xwl_seat)
{
+ struct xwl_screen *xwl_screen = xwl_seat->xwl_screen;
double dx, dx_unaccel;
double dy, dy_unaccel;
@@ -632,6 +636,11 @@ dispatch_relative_motion_with_warp(struct xwl_seat *xwl_seat)
dx_unaccel = xwl_seat->pending_pointer_event.dx_unaccel;
dy_unaccel = xwl_seat->pending_pointer_event.dy_unaccel;
+ dx *= xwl_screen->global_surface_scale;
+ dy *= xwl_screen->global_surface_scale;
+ dx_unaccel *= xwl_screen->global_surface_scale;
+ dy_unaccel *= xwl_screen->global_surface_scale;
+
xwl_pointer_warp_emulator_handle_motion(xwl_seat->pointer_warp_emulator,
dx, dy,
dx_unaccel, dy_unaccel);
@@ -640,6 +649,7 @@ dispatch_relative_motion_with_warp(struct xwl_seat *xwl_seat)
static void
dispatch_absolute_motion(struct xwl_seat *xwl_seat)
{
+ struct xwl_screen *xwl_screen = xwl_seat->xwl_screen;
ValuatorMask mask;
DeviceIntPtr device;
int flags;
@@ -650,6 +660,9 @@ dispatch_absolute_motion(struct xwl_seat *xwl_seat)
int x;
int y;
+ event_x *= xwl_screen->global_surface_scale;
+ event_y *= xwl_screen->global_surface_scale;
+
if (xwl_window_has_viewport_enabled(xwl_seat->focus_window)) {
event_x *= xwl_seat->focus_window->scale_x;
event_y *= xwl_seat->focus_window->scale_y;
@@ -676,12 +689,18 @@ dispatch_absolute_motion(struct xwl_seat *xwl_seat)
static void
dispatch_relative_motion(struct xwl_seat *xwl_seat)
{
+ struct xwl_screen *xwl_screen = xwl_seat->xwl_screen;
ValuatorMask mask;
double event_dx = xwl_seat->pending_pointer_event.dx;
double event_dy = xwl_seat->pending_pointer_event.dy;
double event_dx_unaccel = xwl_seat->pending_pointer_event.dx_unaccel;
double event_dy_unaccel = xwl_seat->pending_pointer_event.dy_unaccel;
+ event_dx *= xwl_screen->global_surface_scale;
+ event_dy *= xwl_screen->global_surface_scale;
+ event_dx_unaccel *= xwl_screen->global_surface_scale;
+ event_dy_unaccel *= xwl_screen->global_surface_scale;
+
valuator_mask_zero(&mask);
valuator_mask_set_unaccelerated(&mask, 0, event_dx, event_dx_unaccel);
valuator_mask_set_unaccelerated(&mask, 1, event_dy, event_dy_unaccel);
@@ -955,9 +974,13 @@ pointer_gesture_swipe_handle_update(void *data,
wl_fixed_t dyf)
{
struct xwl_seat *xwl_seat = data;
+ struct xwl_screen *xwl_screen = xwl_seat->xwl_screen;
double dx = wl_fixed_to_double(dxf);
double dy = wl_fixed_to_double(dyf);
+ dx *= xwl_screen->global_surface_scale;
+ dy *= xwl_screen->global_surface_scale;
+
QueueGestureSwipeEvents(xwl_seat->pointer_gestures,
XI_GestureSwipeUpdate,
xwl_seat->pointer_gesture_swipe_fingers,
@@ -1021,10 +1044,14 @@ pointer_gesture_pinch_handle_update(void *data,
wl_fixed_t rotation)
{
struct xwl_seat *xwl_seat = data;
+ struct xwl_screen *xwl_screen = xwl_seat->xwl_screen;
double dx = wl_fixed_to_double(dxf);
double dy = wl_fixed_to_double(dyf);
double scale = wl_fixed_to_double(scalef);
+ dx *= xwl_screen->global_surface_scale;
+ dy *= xwl_screen->global_surface_scale;
+
xwl_seat->pointer_gesture_pinch_last_scale = scale;
QueueGesturePinchEvents(xwl_seat->pointer_gestures,
XI_GesturePinchUpdate,
@@ -1403,6 +1430,7 @@ touch_handle_down(void *data, struct wl_touch *wl_touch,
int32_t id, wl_fixed_t sx_w, wl_fixed_t sy_w)
{
struct xwl_seat *xwl_seat = data;
+ struct xwl_screen *xwl_screen = xwl_seat->xwl_screen;
struct xwl_touch *xwl_touch;
if (surface == NULL)
@@ -1423,6 +1451,9 @@ touch_handle_down(void *data, struct wl_touch *wl_touch,
xwl_touch->y = wl_fixed_to_int(sy_w);
xorg_list_add(&xwl_touch->link_touch, &xwl_seat->touches);
+ xwl_touch->x *= xwl_screen->global_surface_scale;
+ xwl_touch->y *= xwl_screen->global_surface_scale;
+
xwl_touch_send_event(xwl_touch, xwl_seat, XI_TouchBegin);
}
@@ -1449,6 +1480,7 @@ touch_handle_motion(void *data, struct wl_touch *wl_touch,
wl_fixed_t sx_w, wl_fixed_t sy_w)
{
struct xwl_seat *xwl_seat = data;
+ struct xwl_screen *xwl_screen = xwl_seat->xwl_screen;
struct xwl_touch *xwl_touch;
xwl_touch = xwl_seat_lookup_touch(xwl_seat, id);
@@ -1458,6 +1490,10 @@ touch_handle_motion(void *data, struct wl_touch *wl_touch,
xwl_touch->x = wl_fixed_to_int(sx_w);
xwl_touch->y = wl_fixed_to_int(sy_w);
+
+ xwl_touch->x *= xwl_screen->global_surface_scale;
+ xwl_touch->y *= xwl_screen->global_surface_scale;
+
xwl_touch_send_event(xwl_touch, xwl_seat, XI_TouchUpdate);
}
@@ -2146,6 +2182,7 @@ tablet_tool_motion(void *data, struct zwp_tablet_tool_v2 *tool,
{
struct xwl_tablet_tool *xwl_tablet_tool = data;
struct xwl_seat *xwl_seat = xwl_tablet_tool->seat;
+ struct xwl_screen *xwl_screen = xwl_seat->xwl_screen;
int32_t dx, dy;
double sx = wl_fixed_to_double(x);
double sy = wl_fixed_to_double(y);
@@ -2153,6 +2190,9 @@ tablet_tool_motion(void *data, struct zwp_tablet_tool_v2 *tool,
if (!xwl_seat->tablet_focus_window)
return;
+ sx *= xwl_screen->global_surface_scale;
+ sy *= xwl_screen->global_surface_scale;
+
dx = xwl_seat->tablet_focus_window->window->drawable.x;
dy = xwl_seat->tablet_focus_window->window->drawable.y;
@@ -2186,12 +2226,16 @@ tablet_tool_tilt(void *data, struct zwp_tablet_tool_v2 *tool,
{
struct xwl_tablet_tool *xwl_tablet_tool = data;
struct xwl_seat *xwl_seat = xwl_tablet_tool->seat;
+ struct xwl_screen *xwl_screen = xwl_seat->xwl_screen;
if (!xwl_seat->tablet_focus_window)
return;
xwl_tablet_tool->tilt_x = wl_fixed_to_double(tilt_x);
xwl_tablet_tool->tilt_y = wl_fixed_to_double(tilt_y);
+
+ xwl_tablet_tool->tilt_x *= xwl_screen->global_surface_scale;
+ xwl_tablet_tool->tilt_y *= xwl_screen->global_surface_scale;
}
static void
diff --git a/hw/xwayland/xwayland-window.c b/hw/xwayland/xwayland-window.c
index 325ffdb13..e83ca8a2c 100644
--- a/hw/xwayland/xwayland-window.c
+++ b/hw/xwayland/xwayland-window.c
@@ -27,6 +27,7 @@
#include <dix-config.h>
#endif
+#include <math.h>
#include <sys/mman.h>
#include <X11/X.h>
@@ -266,6 +267,9 @@ xwl_window_enable_viewport(struct xwl_window *xwl_window,
struct xwl_output *xwl_output,
struct xwl_emulated_mode *emulated_mode)
{
+ struct xwl_screen *xwl_screen = xwl_window->xwl_screen;
+ int width, height;
+
if (!xwl_window_has_viewport_enabled(xwl_window)) {
DebugF("XWAYLAND: enabling viewport %dx%d -> %dx%d\n",
emulated_mode->width, emulated_mode->height,
@@ -274,17 +278,20 @@ xwl_window_enable_viewport(struct xwl_window *xwl_window,
xwl_window->surface);
}
+ width = emulated_mode->width / xwl_screen->global_surface_scale;
+ height = emulated_mode->height / xwl_screen->global_surface_scale;
+
wp_viewport_set_source(xwl_window->viewport,
wl_fixed_from_int(0),
wl_fixed_from_int(0),
- wl_fixed_from_int(emulated_mode->width),
- wl_fixed_from_int(emulated_mode->height));
+ wl_fixed_from_int(width),
+ wl_fixed_from_int(height));
wp_viewport_set_destination(xwl_window->viewport,
xwl_output->width,
xwl_output->height);
- xwl_window->scale_x = (float)emulated_mode->width / xwl_output->width;
- xwl_window->scale_y = (float)emulated_mode->height / xwl_output->height;
+ xwl_window->scale_x = (float) width / xwl_output->width;
+ xwl_window->scale_y = (float) height / xwl_output->height;
}
static Bool
@@ -641,12 +648,20 @@ xwl_window_maybe_resize(struct xwl_window *xwl_window, double width, double heig
{
struct xwl_screen *xwl_screen = xwl_window->xwl_screen;
struct xwl_output *xwl_output;
+ double scale;
RRModePtr mode;
/* Clamp the size */
width = min(max(width, MIN_ROOTFUL_WIDTH), MAX_ROOTFUL_WIDTH);
height = min(max(height, MIN_ROOTFUL_HEIGHT), MAX_ROOTFUL_HEIGHT);
+ /* Make sure the size is a multiple of the scale, it's a protocol error otherwise. */
+ scale = xwl_screen->global_surface_scale;
+ if (scale > 1.0) {
+ width = round(width / scale) * scale;
+ height = round(height / scale) * scale;
+ }
+
if (width == xwl_screen->width && height == xwl_screen->height)
return;
@@ -667,10 +682,18 @@ xwl_window_maybe_resize(struct xwl_window *xwl_window, double width, double heig
static void
xwl_window_libdecor_set_size_limits(struct xwl_window *xwl_window)
{
+ struct xwl_screen *xwl_screen = xwl_window->xwl_screen;
+
libdecor_frame_set_min_content_size(xwl_window->libdecor_frame,
- MIN_ROOTFUL_WIDTH, MIN_ROOTFUL_HEIGHT);
+ MIN_ROOTFUL_WIDTH /
+ xwl_screen->global_surface_scale,
+ MIN_ROOTFUL_HEIGHT /
+ xwl_screen->global_surface_scale);
libdecor_frame_set_max_content_size(xwl_window->libdecor_frame,
- MAX_ROOTFUL_WIDTH, MAX_ROOTFUL_HEIGHT);
+ MAX_ROOTFUL_WIDTH /
+ xwl_screen->global_surface_scale,
+ MAX_ROOTFUL_HEIGHT /
+ xwl_screen->global_surface_scale);
}
static void
@@ -701,11 +724,21 @@ handle_libdecor_configure(struct libdecor_frame *frame,
new_width = (double) width;
new_height = (double) height;
}
+ else {
+ new_width = xwl_screen->width / xwl_screen->global_surface_scale;
+ new_height = xwl_screen->height / xwl_screen->global_surface_scale;
+ }
+
+ new_width *= xwl_screen->global_surface_scale;
+ new_height *= xwl_screen->global_surface_scale;
xwl_window_maybe_resize(xwl_window, new_width, new_height);
+
+ new_width = xwl_screen->width / xwl_screen->global_surface_scale;
+ new_height = xwl_screen->height / xwl_screen->global_surface_scale;
+
xwl_window_update_libdecor_size(xwl_window, configuration,
- xwl_screen_get_width(xwl_screen),
- xwl_screen_get_height(xwl_screen));
+ round(new_width), round(new_height));
wl_surface_commit(xwl_window->surface);
}
@@ -802,14 +835,17 @@ xdg_toplevel_handle_configure(void *data,
struct xwl_screen *xwl_screen = xwl_window->xwl_screen;
uint32_t *p;
Bool old_active = xwl_screen->active;
+ int new_width, new_height;
/* Maintain our current size if no dimensions are requested */
if (width == 0 && height == 0)
return;
if (!xwl_screen->fullscreen) {
+ new_width = width * xwl_screen->global_surface_scale;
+ new_height = height * xwl_screen->global_surface_scale;
/* This will be committed by the xdg_surface.configure handler */
- xwl_window_maybe_resize(xwl_window, width, height);
+ xwl_window_maybe_resize(xwl_window, new_width, new_height);
}
xwl_screen->active = FALSE;
@@ -1273,8 +1309,14 @@ xwl_resize_window(WindowPtr window,
if (xwl_window_get(window) || xwl_window_is_toplevel(window))
xwl_window_check_resolution_change_emulation(xwl_window);
#ifdef XWL_HAS_LIBDECOR
- if (window == screen->root)
- xwl_window_update_libdecor_size(xwl_window, NULL, width, height);
+ if (window == screen->root) {
+ unsigned int decor_width, decor_height;
+
+ decor_width = width / xwl_screen->global_surface_scale;
+ decor_height = height / xwl_screen->global_surface_scale;
+ xwl_window_update_libdecor_size(xwl_window, NULL,
+ decor_width, decor_height);
+ }
#endif
}
}