diff options
author | Olivier Fourdan <ofourdan@redhat.com> | 2023-11-02 10:25:46 +0100 |
---|---|---|
committer | Olivier Fourdan <ofourdan@redhat.com> | 2024-03-20 09:05:36 +0100 |
commit | 54f8fc409091ea3b3466cbf948a53194aaa26aad (patch) | |
tree | e2bed5a1ce4b11c958930e3e660f19d4522377e8 /hw/xwayland | |
parent | b678297c53b081d42cb19fabc65d13202ad5494e (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>
Diffstat (limited to 'hw/xwayland')
-rw-r--r-- | hw/xwayland/xwayland-cursor.c | 22 | ||||
-rw-r--r-- | hw/xwayland/xwayland-input.c | 50 | ||||
-rw-r--r-- | hw/xwayland/xwayland-window.c | 64 |
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 } } |