wayland: support fractional scale for custom cursor
This commit is contained in:
parent
078c4c0c4f
commit
4fe4ce3d77
4 changed files with 41 additions and 13 deletions
|
|
@ -253,3 +253,4 @@ changelog entry.
|
|||
- On macOS, fixed `run_app_on_demand` returning without closing open windows.
|
||||
- On Wayland, fixed a crash when consequently calling `set_cursor_grab` without pointer focus.
|
||||
- On Wayland, ensure that external event loop is woken-up when using pump_events and integrating via `FD`.
|
||||
- On Wayland, apply fractional scaling to custom cursors.
|
||||
|
|
|
|||
|
|
@ -96,8 +96,12 @@ impl SeatHandler for WinitState {
|
|||
},
|
||||
SeatCapability::Pointer if seat_state.pointer.is_none() => {
|
||||
let surface = self.compositor_state.create_surface(queue_handle);
|
||||
let viewport = self
|
||||
.viewporter_state
|
||||
.as_ref()
|
||||
.map(|state| state.get_viewport(&surface, queue_handle));
|
||||
let surface_id = surface.id();
|
||||
let pointer_data = WinitPointerData::new(seat.clone());
|
||||
let pointer_data = WinitPointerData::new(seat.clone(), viewport);
|
||||
let themed_pointer = self
|
||||
.seat_state
|
||||
.get_pointer_with_theme_and_data(
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ use sctk::reexports::protocols::wp::cursor_shape::v1::client::wp_cursor_shape_ma
|
|||
use sctk::reexports::protocols::wp::pointer_constraints::zv1::client::zwp_pointer_constraints_v1::{Lifetime, ZwpPointerConstraintsV1};
|
||||
use sctk::reexports::client::globals::{BindError, GlobalList};
|
||||
use sctk::reexports::csd_frame::FrameClick;
|
||||
use sctk::reexports::protocols::wp::viewporter::client::wp_viewport::WpViewport;
|
||||
|
||||
use sctk::compositor::SurfaceData;
|
||||
use sctk::globals::GlobalData;
|
||||
|
|
@ -246,13 +247,17 @@ pub struct WinitPointerData {
|
|||
|
||||
/// The data required by the sctk.
|
||||
sctk_data: PointerData,
|
||||
|
||||
/// Viewport for fractional cursor.
|
||||
viewport: Option<WpViewport>,
|
||||
}
|
||||
|
||||
impl WinitPointerData {
|
||||
pub fn new(seat: WlSeat) -> Self {
|
||||
pub fn new(seat: WlSeat, viewport: Option<WpViewport>) -> Self {
|
||||
Self {
|
||||
inner: Mutex::new(WinitPointerDataInner::default()),
|
||||
sctk_data: PointerData::new(seat),
|
||||
viewport,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -333,6 +338,18 @@ impl WinitPointerData {
|
|||
locked_pointer.set_cursor_position_hint(surface_x, surface_y);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn viewport(&self) -> Option<&WpViewport> {
|
||||
self.viewport.as_ref()
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for WinitPointerData {
|
||||
fn drop(&mut self) {
|
||||
if let Some(viewport) = self.viewport.take() {
|
||||
viewport.destroy();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl PointerDataExt for WinitPointerData {
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ use tracing::{info, warn};
|
|||
use wayland_protocols_plasma::blur::client::org_kde_kwin_blur::OrgKdeKwinBlur;
|
||||
|
||||
use crate::cursor::CustomCursor as CoreCustomCursor;
|
||||
use crate::dpi::{LogicalPosition, LogicalSize, PhysicalSize, Size};
|
||||
use crate::dpi::{LogicalPosition, LogicalSize, PhysicalPosition, PhysicalSize, Size};
|
||||
use crate::error::{NotSupportedError, RequestError};
|
||||
use crate::platform_impl::wayland::event_loop::OwnedDisplayHandle;
|
||||
use crate::platform_impl::wayland::logical_to_physical_rounded;
|
||||
|
|
@ -725,17 +725,26 @@ impl WindowState {
|
|||
}
|
||||
|
||||
fn apply_custom_cursor(&self, cursor: &CustomCursor) {
|
||||
self.apply_on_pointer(|pointer, _| {
|
||||
self.apply_on_pointer(|pointer, data| {
|
||||
let surface = pointer.surface();
|
||||
|
||||
let scale = surface.data::<SurfaceData>().unwrap().surface_data().scale_factor();
|
||||
let scale = if let Some(viewport) = data.viewport() {
|
||||
let scale = self.scale_factor();
|
||||
let size = PhysicalSize::new(cursor.w, cursor.h).to_logical(scale);
|
||||
viewport.set_destination(size.width, size.height);
|
||||
scale
|
||||
} else {
|
||||
let scale = surface.data::<SurfaceData>().unwrap().surface_data().scale_factor();
|
||||
surface.set_buffer_scale(scale);
|
||||
scale as f64
|
||||
};
|
||||
|
||||
surface.set_buffer_scale(scale);
|
||||
surface.attach(Some(cursor.buffer.wl_buffer()), 0, 0);
|
||||
if surface.version() >= 4 {
|
||||
surface.damage_buffer(0, 0, cursor.w, cursor.h);
|
||||
} else {
|
||||
surface.damage(0, 0, cursor.w / scale, cursor.h / scale);
|
||||
let size = PhysicalSize::new(cursor.w, cursor.h).to_logical(scale);
|
||||
surface.damage(0, 0, size.width, size.height);
|
||||
}
|
||||
surface.commit();
|
||||
|
||||
|
|
@ -745,12 +754,9 @@ impl WindowState {
|
|||
.and_then(|data| data.pointer_data().latest_enter_serial())
|
||||
.unwrap();
|
||||
|
||||
pointer.pointer().set_cursor(
|
||||
serial,
|
||||
Some(surface),
|
||||
cursor.hotspot_x / scale,
|
||||
cursor.hotspot_y / scale,
|
||||
);
|
||||
let hotspot =
|
||||
PhysicalPosition::new(cursor.hotspot_x, cursor.hotspot_y).to_logical(scale);
|
||||
pointer.pointer().set_cursor(serial, Some(surface), hotspot.x, hotspot.y);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue