diff --git a/hw/xwayland/xwayland-cursor.c b/hw/xwayland/xwayland-cursor.c index c4457cc2a..f62839ac1 100644 --- a/hw/xwayland/xwayland-cursor.c +++ b/hw/xwayland/xwayland-cursor.c @@ -190,6 +190,7 @@ xwl_cursor_attach_pixmap(struct xwl_seat *xwl_seat, void xwl_seat_set_cursor(struct xwl_seat *xwl_seat) { + struct xwl_screen *xwl_screen = xwl_seat->xwl_screen; struct xwl_cursor *xwl_cursor = &xwl_seat->cursor; PixmapPtr pixmap; CursorPtr cursor; @@ -220,8 +221,8 @@ xwl_seat_set_cursor(struct xwl_seat *xwl_seat) 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); + xwl_scale_to(xwl_screen, xwl_seat->x_cursor->bits->xhot), + xwl_scale_to(xwl_screen, xwl_seat->x_cursor->bits->yhot)); xwl_cursor_attach_pixmap(xwl_seat, xwl_cursor, pixmap); } @@ -230,6 +231,7 @@ 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; @@ -258,8 +260,8 @@ xwl_tablet_tool_set_cursor(struct xwl_tablet_tool *xwl_tablet_tool) 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); + xwl_scale_to(xwl_screen, xwl_seat->x_cursor->bits->xhot), + xwl_scale_to(xwl_screen, xwl_seat->x_cursor->bits->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 26b3630c7..55cd8d466 100644 --- a/hw/xwayland/xwayland-input.c +++ b/hw/xwayland/xwayland-input.c @@ -412,8 +412,8 @@ pointer_handle_enter(void *data, struct wl_pointer *pointer, 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 = wl_fixed_to_int(sx_w) * xwl_seat->xwl_screen->global_output_scale; + int sy = wl_fixed_to_int(sy_w) * xwl_seat->xwl_screen->global_output_scale; int dx, dy; ScreenPtr pScreen = xwl_seat->xwl_screen->screen; ValuatorMask mask; @@ -592,13 +592,14 @@ pointer_handle_motion(void *data, struct wl_pointer *pointer, uint32_t time, wl_fixed_t sx_w, wl_fixed_t sy_w) { struct xwl_seat *xwl_seat = data; + int32_t scale = xwl_seat->xwl_screen->global_output_scale; if (!xwl_seat->focus_window) return; xwl_seat->pending_pointer_event.has_absolute = TRUE; - xwl_seat->pending_pointer_event.x = sx_w; - xwl_seat->pending_pointer_event.y = sy_w; + xwl_seat->pending_pointer_event.x = sx_w * scale; + xwl_seat->pending_pointer_event.y = sy_w * scale; if (wl_proxy_get_version((struct wl_proxy *) xwl_seat->wl_pointer) < 5) dispatch_pointer_motion_event(xwl_seat); @@ -672,7 +673,8 @@ pointer_handle_axis(void *data, struct wl_pointer *pointer, xorg_list_del(&pending->l); free(pending); } else { - valuator_mask_set_double(&mask, index, wl_fixed_to_double(value) / divisor); + double scaled_value = wl_fixed_to_double(value); + valuator_mask_set_double(&mask, index, scaled_value / divisor); } QueuePointerEvents(get_pointer_device(xwl_seat), @@ -740,12 +742,13 @@ relative_pointer_handle_relative_motion(void *data, wl_fixed_t dy_unaccelf) { struct xwl_seat *xwl_seat = data; + int32_t scale = xwl_seat->xwl_screen->global_output_scale; xwl_seat->pending_pointer_event.has_relative = TRUE; - xwl_seat->pending_pointer_event.dx = wl_fixed_to_double(dxf); - xwl_seat->pending_pointer_event.dy = wl_fixed_to_double(dyf); - xwl_seat->pending_pointer_event.dx_unaccel = wl_fixed_to_double(dx_unaccelf); - xwl_seat->pending_pointer_event.dy_unaccel = wl_fixed_to_double(dy_unaccelf); + xwl_seat->pending_pointer_event.dx = wl_fixed_to_double(dxf) * scale; + xwl_seat->pending_pointer_event.dy = wl_fixed_to_double(dyf) * scale; + xwl_seat->pending_pointer_event.dx_unaccel = wl_fixed_to_double(dx_unaccelf) * scale; + xwl_seat->pending_pointer_event.dy_unaccel = wl_fixed_to_double(dy_unaccelf) * scale; if (!xwl_seat->focus_window) return; @@ -1057,8 +1060,8 @@ touch_handle_down(void *data, struct wl_touch *wl_touch, xwl_touch->window = wl_surface_get_user_data(surface); xwl_touch->id = id; - xwl_touch->x = wl_fixed_to_int(sx_w); - xwl_touch->y = wl_fixed_to_int(sy_w); + xwl_touch->x = wl_fixed_to_int(sx_w) * xwl_seat->xwl_screen->global_output_scale; + xwl_touch->y = wl_fixed_to_int(sy_w) * xwl_seat->xwl_screen->global_output_scale; xorg_list_add(&xwl_touch->link_touch, &xwl_seat->touches); xwl_touch_send_event(xwl_touch, xwl_seat, XI_TouchBegin); @@ -1094,8 +1097,8 @@ touch_handle_motion(void *data, struct wl_touch *wl_touch, if (!xwl_touch) return; - xwl_touch->x = wl_fixed_to_int(sx_w); - xwl_touch->y = wl_fixed_to_int(sy_w); + xwl_touch->x = wl_fixed_to_int(sx_w) * xwl_seat->xwl_screen->global_output_scale;; + xwl_touch->y = wl_fixed_to_int(sy_w) * xwl_seat->xwl_screen->global_output_scale;; xwl_touch_send_event(xwl_touch, xwl_seat, XI_TouchUpdate); } @@ -1726,8 +1729,8 @@ 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; int32_t dx, dy; - double sx = wl_fixed_to_double(x); - double sy = wl_fixed_to_double(y); + double sx = wl_fixed_to_double(x) * xwl_seat->xwl_screen->global_output_scale; + double sy = wl_fixed_to_double(y) * xwl_seat->xwl_screen->global_output_scale; if (!xwl_seat->tablet_focus_window) return; @@ -2714,6 +2717,7 @@ xwl_pointer_warp_emulator_set_fake_pos(struct xwl_pointer_warp_emulator *warp_em int x, int y) { + struct xwl_screen *xwl_screen; struct zwp_locked_pointer_v1 *locked_pointer = warp_emulator->locked_pointer; WindowPtr window; @@ -2725,6 +2729,7 @@ xwl_pointer_warp_emulator_set_fake_pos(struct xwl_pointer_warp_emulator *warp_em if (!warp_emulator->xwl_seat->focus_window) return; + xwl_screen = warp_emulator->xwl_seat->xwl_screen; window = warp_emulator->xwl_seat->focus_window->window; if (x >= window->drawable.x || y >= window->drawable.y || @@ -2733,8 +2738,8 @@ xwl_pointer_warp_emulator_set_fake_pos(struct xwl_pointer_warp_emulator *warp_em sx = x - window->drawable.x; sy = y - window->drawable.y; zwp_locked_pointer_v1_set_cursor_position_hint(locked_pointer, - wl_fixed_from_int(sx), - wl_fixed_from_int(sy)); + wl_fixed_from_int(xwl_scale_to(xwl_screen, sx)), + wl_fixed_from_int(xwl_scale_to(xwl_screen, sy))); wl_surface_commit(warp_emulator->xwl_seat->focus_window->surface); } } diff --git a/hw/xwayland/xwayland-output.c b/hw/xwayland/xwayland-output.c index ef705bc01..b8f6cd51b 100644 --- a/hw/xwayland/xwayland-output.c +++ b/hw/xwayland/xwayland-output.c @@ -191,6 +191,9 @@ update_screen_size(struct xwl_output *xwl_output, int width, int height) { struct xwl_screen *xwl_screen = xwl_output->xwl_screen; + width *= xwl_screen->global_output_scale; + height *= xwl_screen->global_output_scale; + if (xwl_screen->root_clip_mode == ROOT_CLIP_FULL) SetRootClip(xwl_screen->screen, ROOT_CLIP_NONE); @@ -497,14 +500,15 @@ xwl_output_set_emulated_mode(struct xwl_output *xwl_output, ClientPtr client, xwl_output_set_randr_emu_props(xwl_output->xwl_screen, client); } -static void -apply_output_change(struct xwl_output *xwl_output) +void +xwl_output_apply_changes(struct xwl_output *xwl_output) { struct xwl_screen *xwl_screen = xwl_output->xwl_screen; struct xwl_output *it; int mode_width, mode_height, count; int width = 0, height = 0, has_this_output = 0; RRModePtr *randr_modes; + int32_t scale = xwl_screen->global_output_scale; /* Clear out the "done" received flags */ xwl_output->wl_output_done = FALSE; @@ -523,10 +527,10 @@ apply_output_change(struct xwl_output *xwl_output) } /* Build a fresh modes array using the current refresh rate */ - randr_modes = output_get_rr_modes(xwl_output, mode_width, mode_height, &count); + randr_modes = output_get_rr_modes(xwl_output, mode_width * scale, mode_height * scale, &count); RROutputSetModes(xwl_output->randr_output, randr_modes, count, 1); RRCrtcNotify(xwl_output->randr_crtc, randr_modes[0], - xwl_output->x, xwl_output->y, + xwl_output->x * scale, xwl_output->y * scale, xwl_output->rotation, NULL, 1, &xwl_output->randr_output); /* RROutputSetModes takes ownership of the passed in modes, so we only * have to free the pointer array. @@ -567,7 +571,7 @@ output_handle_done(void *data, struct wl_output *wl_output) */ if (xwl_output->xdg_output_done || !xwl_output->xdg_output || zxdg_output_v1_get_version(xwl_output->xdg_output) >= 3) - apply_output_change(xwl_output); + xwl_output_apply_changes(xwl_output); } static void @@ -610,7 +614,7 @@ xdg_output_handle_done(void *data, struct zxdg_output_v1 *xdg_output) xwl_output->xdg_output_done = TRUE; if (xwl_output->wl_output_done && zxdg_output_v1_get_version(xdg_output) < 3) - apply_output_change(xwl_output); + xwl_output_apply_changes(xwl_output); } static void @@ -678,6 +682,8 @@ xwl_output_create(struct xwl_screen *xwl_screen, uint32_t id) RROutputSetConnection(xwl_output->randr_output, RR_Connected); RRTellChanged(xwl_screen->screen); + xwl_output->scale = 1; + /* We want the output to be in the list as soon as created so we can * use it when binding to the xdg-output protocol... */ diff --git a/hw/xwayland/xwayland-output.h b/hw/xwayland/xwayland-output.h index 02b983108..ec089757f 100644 --- a/hw/xwayland/xwayland-output.h +++ b/hw/xwayland/xwayland-output.h @@ -43,7 +43,7 @@ struct xwl_output { struct xwl_screen *xwl_screen; RROutputPtr randr_output; RRCrtcPtr randr_crtc; - int32_t x, y, width, height, refresh; + int32_t x, y, width, height, scale, refresh; Rotation rotation; Bool wl_output_done; Bool xdg_output_done; @@ -77,6 +77,8 @@ void xwl_output_set_emulated_mode(struct xwl_output *xwl_output, void xwl_output_set_window_randr_emu_props(struct xwl_screen *xwl_screen, WindowPtr window); +void xwl_output_apply_changes(struct xwl_output *xwl_output); + void xwl_screen_init_xdg_output(struct xwl_screen *xwl_screen); #endif /* XWAYLAND_OUTPUT_H */ diff --git a/hw/xwayland/xwayland-screen.c b/hw/xwayland/xwayland-screen.c index bb18e5c94..c1fe34de0 100644 --- a/hw/xwayland/xwayland-screen.c +++ b/hw/xwayland/xwayland-screen.c @@ -110,6 +110,12 @@ xwl_screen_has_resolution_change_emulation(struct xwl_screen *xwl_screen) return xwl_screen->rootless && xwl_screen_has_viewport_support(xwl_screen); } +int +xwl_scale_to(struct xwl_screen *xwl_screen, int value) +{ + return value / (double)xwl_screen->global_output_scale + 0.5; +} + /* Return the output @ 0x0, falling back to the first output in the list */ struct xwl_output * xwl_screen_get_first_output(struct xwl_screen *xwl_screen) @@ -521,8 +527,14 @@ void xwl_surface_damage(struct xwl_screen *xwl_screen, { if (wl_surface_get_version(surface) >= WL_SURFACE_DAMAGE_BUFFER_SINCE_VERSION) wl_surface_damage_buffer(surface, x, y, width, height); - else + else { + x = xwl_scale_to(xwl_screen, x); + y = xwl_scale_to(xwl_screen, y); + width = xwl_scale_to(xwl_screen, width); + height = xwl_scale_to(xwl_screen, height); + wl_surface_damage(surface, x, y, width, height); + } } void @@ -538,6 +550,18 @@ xwl_screen_roundtrip(struct xwl_screen *xwl_screen) xwl_give_up("could not connect to wayland server\n"); } +void +xwl_screen_set_global_scale(struct xwl_screen *xwl_screen, int32_t scale) +{ + struct xwl_output *it; + xwl_screen->global_output_scale = scale; + + /* change randr resolutions and positions */ + xorg_list_for_each_entry(it, &xwl_screen->output_list, link) { + xwl_output_apply_changes(it); + } +} + Bool xwl_screen_init(ScreenPtr pScreen, int argc, char **argv) { @@ -573,6 +597,7 @@ xwl_screen_init(ScreenPtr pScreen, int argc, char **argv) #ifdef XWL_HAS_GLAMOR xwl_screen->glamor = 1; #endif + xwl_screen->global_output_scale = 1; for (i = 1; i < argc; i++) { if (strcmp(argv[i], "-rootless") == 0) { diff --git a/hw/xwayland/xwayland-screen.h b/hw/xwayland/xwayland-screen.h index b965dddd7..812387d99 100644 --- a/hw/xwayland/xwayland-screen.h +++ b/hw/xwayland/xwayland-screen.h @@ -72,6 +72,8 @@ struct xwl_screen { struct xorg_list damage_window_list; struct xorg_list window_list; + int32_t global_output_scale; + int wayland_fd; struct wl_display *display; struct wl_registry *registry; @@ -134,5 +136,7 @@ void xwl_screen_roundtrip (struct xwl_screen *xwl_screen); void xwl_surface_damage(struct xwl_screen *xwl_screen, struct wl_surface *surface, int32_t x, int32_t y, int32_t width, int32_t height); +int xwl_scale_to(struct xwl_screen *xwl_screen, int value); +void xwl_screen_set_global_scale(struct xwl_screen *xwl_screen, int32_t scale); #endif /* XWAYLAND_SCREEN_H */ diff --git a/hw/xwayland/xwayland-window.c b/hw/xwayland/xwayland-window.c index 00f161eda..1b2487c07 100644 --- a/hw/xwayland/xwayland-window.c +++ b/hw/xwayland/xwayland-window.c @@ -470,7 +470,8 @@ ensure_surface_for_window(WindowPtr window) } wl_region_add(region, 0, 0, - window->drawable.width, window->drawable.height); + xwl_scale_to(xwl_screen, window->drawable.width), + xwl_scale_to(xwl_screen, window->drawable.height)); wl_surface_set_opaque_region(xwl_window->surface, region); wl_region_destroy(region); } @@ -819,6 +820,7 @@ xwl_window_post_damage(struct xwl_window *xwl_window) } #endif + wl_surface_set_buffer_scale(xwl_window->surface, xwl_screen->global_output_scale); wl_surface_attach(xwl_window->surface, buffer, 0, 0); /* Arbitrary limit to try to avoid flooding the Wayland