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 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, 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, 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() => {
|
SeatCapability::Pointer if seat_state.pointer.is_none() => {
|
||||||
let surface = self.compositor_state.create_surface(queue_handle);
|
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 surface_id = surface.id();
|
||||||
let pointer_data = WinitPointerData::new(seat.clone());
|
let pointer_data = WinitPointerData::new(seat.clone(), viewport);
|
||||||
let themed_pointer = self
|
let themed_pointer = self
|
||||||
.seat_state
|
.seat_state
|
||||||
.get_pointer_with_theme_and_data(
|
.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::protocols::wp::pointer_constraints::zv1::client::zwp_pointer_constraints_v1::{Lifetime, ZwpPointerConstraintsV1};
|
||||||
use sctk::reexports::client::globals::{BindError, GlobalList};
|
use sctk::reexports::client::globals::{BindError, GlobalList};
|
||||||
use sctk::reexports::csd_frame::FrameClick;
|
use sctk::reexports::csd_frame::FrameClick;
|
||||||
|
use sctk::reexports::protocols::wp::viewporter::client::wp_viewport::WpViewport;
|
||||||
|
|
||||||
use sctk::compositor::SurfaceData;
|
use sctk::compositor::SurfaceData;
|
||||||
use sctk::globals::GlobalData;
|
use sctk::globals::GlobalData;
|
||||||
|
|
@ -246,13 +247,17 @@ pub struct WinitPointerData {
|
||||||
|
|
||||||
/// The data required by the sctk.
|
/// The data required by the sctk.
|
||||||
sctk_data: PointerData,
|
sctk_data: PointerData,
|
||||||
|
|
||||||
|
/// Viewport for fractional cursor.
|
||||||
|
viewport: Option<WpViewport>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WinitPointerData {
|
impl WinitPointerData {
|
||||||
pub fn new(seat: WlSeat) -> Self {
|
pub fn new(seat: WlSeat, viewport: Option<WpViewport>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
inner: Mutex::new(WinitPointerDataInner::default()),
|
inner: Mutex::new(WinitPointerDataInner::default()),
|
||||||
sctk_data: PointerData::new(seat),
|
sctk_data: PointerData::new(seat),
|
||||||
|
viewport,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -333,6 +338,18 @@ impl WinitPointerData {
|
||||||
locked_pointer.set_cursor_position_hint(surface_x, surface_y);
|
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 {
|
impl PointerDataExt for WinitPointerData {
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,7 @@ use tracing::{info, warn};
|
||||||
use wayland_protocols_plasma::blur::client::org_kde_kwin_blur::OrgKdeKwinBlur;
|
use wayland_protocols_plasma::blur::client::org_kde_kwin_blur::OrgKdeKwinBlur;
|
||||||
|
|
||||||
use crate::cursor::CustomCursor as CoreCustomCursor;
|
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::error::{NotSupportedError, RequestError};
|
||||||
use crate::platform_impl::wayland::event_loop::OwnedDisplayHandle;
|
use crate::platform_impl::wayland::event_loop::OwnedDisplayHandle;
|
||||||
use crate::platform_impl::wayland::logical_to_physical_rounded;
|
use crate::platform_impl::wayland::logical_to_physical_rounded;
|
||||||
|
|
@ -725,17 +725,26 @@ impl WindowState {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn apply_custom_cursor(&self, cursor: &CustomCursor) {
|
fn apply_custom_cursor(&self, cursor: &CustomCursor) {
|
||||||
self.apply_on_pointer(|pointer, _| {
|
self.apply_on_pointer(|pointer, data| {
|
||||||
let surface = pointer.surface();
|
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);
|
surface.attach(Some(cursor.buffer.wl_buffer()), 0, 0);
|
||||||
if surface.version() >= 4 {
|
if surface.version() >= 4 {
|
||||||
surface.damage_buffer(0, 0, cursor.w, cursor.h);
|
surface.damage_buffer(0, 0, cursor.w, cursor.h);
|
||||||
} else {
|
} 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();
|
surface.commit();
|
||||||
|
|
||||||
|
|
@ -745,12 +754,9 @@ impl WindowState {
|
||||||
.and_then(|data| data.pointer_data().latest_enter_serial())
|
.and_then(|data| data.pointer_data().latest_enter_serial())
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
pointer.pointer().set_cursor(
|
let hotspot =
|
||||||
serial,
|
PhysicalPosition::new(cursor.hotspot_x, cursor.hotspot_y).to_logical(scale);
|
||||||
Some(surface),
|
pointer.pointer().set_cursor(serial, Some(surface), hotspot.x, hotspot.y);
|
||||||
cursor.hotspot_x / scale,
|
|
||||||
cursor.hotspot_y / scale,
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue