diff --git a/src/platforms/wayland/display.cpp b/src/platforms/wayland/display.cpp index 8d6c3d07395..eb70f9bbe3e 100644 --- a/src/platforms/wayland/display.cpp +++ b/src/platforms/wayland/display.cpp @@ -369,7 +369,9 @@ void mir::graphics::wayland::Display::pointer_motion(wl_pointer* pointer, uint32 { { std::lock_guard lock{sink_mutex}; - pointer_pos = geom::PointF{wl_fixed_to_double(x), wl_fixed_to_double(y)} + geom::DisplacementF{pointer_displacement}; + auto const descaled_x = pointer_scale * wl_fixed_to_double(x); + auto const descaled_y = pointer_scale * wl_fixed_to_double(y); + pointer_pos = geom::PointF{descaled_x, descaled_y} + pointer_displacement; pointer_time = std::chrono::milliseconds{time}; } diff --git a/src/platforms/wayland/displayclient.cpp b/src/platforms/wayland/displayclient.cpp index 81da19081e4..cb2e0cc74f7 100644 --- a/src/platforms/wayland/displayclient.cpp +++ b/src/platforms/wayland/displayclient.cpp @@ -58,6 +58,7 @@ class mgw::DisplayClient::Output : DisplayConfigurationOutput dcout; geom::Size output_size; + float host_scale{1.0f}; wl_output* const output; DisplayClient* const owner; @@ -280,7 +281,7 @@ void mgw::DisplayClient::Output::mode(uint32_t flags, int32_t width, int32_t hei void mgw::DisplayClient::Output::scale(int32_t factor) { - dcout.scale = factor; + host_scale = factor; } void mgw::DisplayClient::Output::done() @@ -301,7 +302,7 @@ void mgw::DisplayClient::Output::done() xdg_toplevel_add_listener(shell_toplevel, &shell_toplevel_listener, this); xdg_toplevel_set_fullscreen(shell_toplevel, output); - wl_surface_set_buffer_scale(surface, round(dcout.scale)); + wl_surface_set_buffer_scale(surface, round(host_scale)); wl_surface_commit(surface); // After the next roundtrip the surface should be configured @@ -325,9 +326,9 @@ void mgw::DisplayClient::Output::surface_configure(uint32_t serial) xdg_surface_ack_configure(shell_surface, serial); bool const size_is_changed = pending_toplevel_size && ( !dcout.custom_logical_size || dcout.custom_logical_size.value() != pending_toplevel_size.value()); - dcout.custom_logical_size = pending_toplevel_size.value(); + dcout.custom_logical_size = host_scale*pending_toplevel_size.value(); pending_toplevel_size.reset(); - output_size = dcout.extents().size * dcout.scale; + output_size = dcout.extents().size; if (!has_initialized) { egl_window = wl_egl_window_create(surface, output_size.width.as_int(), output_size.height.as_int()); @@ -718,7 +719,9 @@ void mgw::DisplayClient::pointer_enter( { if (surface == out.second->surface) { - pointer_displacement = out.second->dcout.top_left - geometry::Point{}; + // Pointer events are displaced and scaled according to the surface + pointer_displacement = geom::DisplacementF{out.second->dcout.top_left - geometry::Point{}}; + pointer_scale = out.second->host_scale; break; } } diff --git a/src/platforms/wayland/displayclient.h b/src/platforms/wayland/displayclient.h index f95c955d2f0..ca73bb3dd6b 100644 --- a/src/platforms/wayland/displayclient.h +++ b/src/platforms/wayland/displayclient.h @@ -159,8 +159,9 @@ class DisplayClient xkb_keymap* keyboard_map_ = nullptr; xkb_state* keyboard_state_ = nullptr; bool fake_pointer_frame = false; - geometry::Displacement pointer_displacement; // Position of current output + geometry::DisplacementF pointer_displacement; // Position of current output geometry::Displacement touch_displacement; // Position of current output + float pointer_scale{1.0f}; std::unique_ptr registry;