From 33e939906c53e3b9dd5f98b9fb6e31aa266e4efa Mon Sep 17 00:00:00 2001 From: Christian Meissl Date: Sat, 24 Feb 2024 18:17:51 +0100 Subject: [PATCH] handle role specific buffer offset --- Cargo.lock | 12 ++---------- src/handlers/compositor.rs | 33 +++++++++++++++++++++++++++++++-- src/handlers/mod.rs | 26 ++++++++++++++++++++++---- src/niri.rs | 37 +++++++++++++++++++++++-------------- 4 files changed, 78 insertions(+), 30 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 00bedd34..3377a483 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3346,12 +3346,6 @@ dependencies = [ "winapi-util", ] -[[package]] -name = "scan_fmt" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b53b0a5db882a8e2fdaae0a43f7b39e7e9082389e978398bdf223a55b581248" - [[package]] name = "schemars" version = "0.8.21" @@ -3528,7 +3522,7 @@ checksum = "b7c388c1b5e93756d0c740965c41e8822f866621d41acbdf6336a6a168f8840c" [[package]] name = "smithay" version = "0.3.0" -source = "git+https://github.com/Smithay/smithay.git#f364c73cae953aebfa189075e9f118f9008e100b" +source = "git+https://github.com/Smithay/smithay.git#0cd0895f9b179f79cffc2da518da4dca86c4de1d" dependencies = [ "appendlist", "bitflags 2.6.0", @@ -3545,7 +3539,6 @@ dependencies = [ "gl_generator", "indexmap", "input", - "lazy_static", "libc", "libloading", "libseat", @@ -3555,7 +3548,6 @@ dependencies = [ "profiling", "rand", "rustix 0.38.37", - "scan_fmt", "smallvec", "tempfile", "thiserror", @@ -3602,7 +3594,7 @@ dependencies = [ [[package]] name = "smithay-drm-extras" version = "0.1.0" -source = "git+https://github.com/Smithay/smithay.git#f364c73cae953aebfa189075e9f118f9008e100b" +source = "git+https://github.com/Smithay/smithay.git#0cd0895f9b179f79cffc2da518da4dca86c4de1d" dependencies = [ "drm", "libdisplay-info", diff --git a/src/handlers/compositor.rs b/src/handlers/compositor.rs index 57be5ad3..f20088f3 100644 --- a/src/handlers/compositor.rs +++ b/src/handlers/compositor.rs @@ -1,7 +1,7 @@ use std::collections::hash_map::Entry; use smithay::backend::renderer::utils::{on_commit_buffer_handler, with_renderer_surface_state}; -use smithay::input::pointer::CursorImageStatus; +use smithay::input::pointer::{CursorImageStatus, CursorImageSurfaceData}; use smithay::reexports::calloop::Interest; use smithay::reexports::wayland_server::protocol::wl_buffer; use smithay::reexports::wayland_server::protocol::wl_surface::WlSurface; @@ -297,13 +297,42 @@ impl CompositorHandler for State { &self.niri.cursor_manager.cursor_image(), CursorImageStatus::Surface(s) if s == &root_surface ) { + with_states(surface, |states| { + let cursor_image_attributes = states.data_map.get::(); + + if let Some(mut cursor_image_attributes) = + cursor_image_attributes.map(|attrs| attrs.lock().unwrap()) + { + let buffer_delta = states + .cached_state + .get::() + .current() + .buffer_delta + .take(); + if let Some(buffer_delta) = buffer_delta { + cursor_image_attributes.hotspot -= buffer_delta; + } + } + }); + // FIXME: granular redraws for cursors. self.niri.queue_redraw_all(); return; } // This might be a DnD icon surface. - if self.niri.dnd_icon.as_ref() == Some(&root_surface) { + if matches!(&self.niri.dnd_icon, Some(icon) if icon.surface == root_surface) { + let dnd_icon = self.niri.dnd_icon.as_mut().unwrap(); + with_states(&dnd_icon.surface, |states| { + let buffer_delta = states + .cached_state + .get::() + .current() + .buffer_delta + .take() + .unwrap_or_default(); + dnd_icon.offset += buffer_delta; + }); // FIXME: granular redraws for cursors. self.niri.queue_redraw_all(); return; diff --git a/src/handlers/mod.rs b/src/handlers/mod.rs index 3e0bb18f..63bde132 100644 --- a/src/handlers/mod.rs +++ b/src/handlers/mod.rs @@ -12,7 +12,9 @@ use smithay::backend::allocator::dmabuf::Dmabuf; use smithay::backend::drm::DrmNode; use smithay::backend::input::TabletToolDescriptor; use smithay::desktop::{PopupKind, PopupManager}; -use smithay::input::pointer::{CursorIcon, CursorImageStatus, PointerHandle}; +use smithay::input::pointer::{ + CursorIcon, CursorImageStatus, CursorImageSurfaceData, PointerHandle, +}; use smithay::input::{keyboard, Seat, SeatHandler, SeatState}; use smithay::output::Output; use smithay::reexports::rustix::fs::{fcntl_setfl, OFlags}; @@ -22,7 +24,7 @@ use smithay::reexports::wayland_server::protocol::wl_data_source::WlDataSource; use smithay::reexports::wayland_server::protocol::wl_output::WlOutput; use smithay::reexports::wayland_server::protocol::wl_surface::WlSurface; use smithay::reexports::wayland_server::Resource; -use smithay::utils::{Logical, Rectangle, Size}; +use smithay::utils::{Logical, Point, Rectangle, Size}; use smithay::wayland::compositor::with_states; use smithay::wayland::dmabuf::{DmabufGlobal, DmabufHandler, DmabufState, ImportNotifier}; use smithay::wayland::drm_lease::{ @@ -64,7 +66,7 @@ use smithay::{ }; pub use crate::handlers::xdg_shell::KdeDecorationsModeState; -use crate::niri::{ClientState, State}; +use crate::niri::{ClientState, DndIcon, State}; use crate::protocols::foreign_toplevel::{ self, ForeignToplevelHandler, ForeignToplevelManagerState, }; @@ -225,7 +227,23 @@ impl ClientDndGrabHandler for State { icon: Option, _seat: Seat, ) { - self.niri.dnd_icon = icon; + let offset = if let CursorImageStatus::Surface(ref surface) = + self.niri.cursor_manager.cursor_image() + { + with_states(surface, |states| { + let hotspot = states + .data_map + .get::() + .unwrap() + .lock() + .unwrap() + .hotspot; + Point::from((-hotspot.x, -hotspot.y)) + }) + } else { + (0, 0).into() + }; + self.niri.dnd_icon = icon.map(|surface| DndIcon { surface, offset }); // FIXME: more granular self.niri.queue_redraw_all(); } diff --git a/src/niri.rs b/src/niri.rs index 9e432319..f2e5aa3f 100644 --- a/src/niri.rs +++ b/src/niri.rs @@ -259,7 +259,7 @@ pub struct Niri { pub cursor_manager: CursorManager, pub cursor_texture_cache: CursorTextureCache, pub cursor_shape_manager_state: CursorShapeManagerState, - pub dnd_icon: Option, + pub dnd_icon: Option, pub pointer_focus: PointerFocus, /// Whether the pointer is hidden, for example due to a previous touch input. /// @@ -304,6 +304,12 @@ pub struct Niri { pub mapped_cast_output: HashMap, } +#[derive(Debug)] +pub struct DndIcon { + pub surface: WlSurface, + pub offset: Point, +} + pub struct OutputState { pub global: GlobalId, pub frame_clock: FrameClock, @@ -2589,8 +2595,8 @@ impl Niri { let output_scale = Scale::from(output.current_scale().fractional_scale()); - let (mut pointer_elements, pointer_pos) = match render_cursor { - RenderCursor::Hidden => (vec![], pointer_pos.to_physical_precise_round(output_scale)), + let mut pointer_elements = match render_cursor { + RenderCursor::Hidden => vec![], RenderCursor::Surface { surface, hotspot } => { let pointer_pos = (pointer_pos - hotspot.to_f64()).to_physical_precise_round(output_scale); @@ -2604,7 +2610,7 @@ impl Niri { Kind::Cursor, ); - (pointer_elements, pointer_pos) + pointer_elements } RenderCursor::Named { icon, @@ -2620,7 +2626,7 @@ impl Niri { let mut pointer_elements = vec![]; let pointer_element = match MemoryRenderBufferRenderElement::from_buffer( renderer, - pointer_pos.to_f64(), + pointer_pos, &texture, None, None, @@ -2637,14 +2643,16 @@ impl Niri { pointer_elements.push(OutputRenderElements::NamedPointer(element)); } - (pointer_elements, pointer_pos) + pointer_elements } }; - if let Some(dnd_icon) = &self.dnd_icon { + if let Some(dnd_icon) = self.dnd_icon.as_ref() { + let pointer_pos = + (pointer_pos + dnd_icon.offset.to_f64()).to_physical_precise_round(output_scale); pointer_elements.extend(render_elements_from_surface_tree( renderer, - dnd_icon, + &dnd_icon.surface, pointer_pos, output_scale, 1., @@ -2685,6 +2693,7 @@ impl Niri { let dnd = self .dnd_icon .as_ref() + .map(|icon| &icon.surface) .map(|surface| (surface, bbox_from_surface_tree(surface, surface_pos))); // FIXME we basically need to pick the largest scale factor across the overlapping @@ -2746,7 +2755,7 @@ impl Niri { } cursor_image => { // There's no cursor surface, but there might be a DnD icon. - let Some(surface) = &self.dnd_icon else { + let Some(surface) = self.dnd_icon.as_ref().map(|icon| &icon.surface) else { return; }; @@ -3268,7 +3277,7 @@ impl Niri { ); } - if let Some(surface) = &self.dnd_icon { + if let Some(surface) = self.dnd_icon.as_ref().map(|icon| &icon.surface) { with_surface_tree_downward( surface, (), @@ -3406,7 +3415,7 @@ impl Niri { ); } - if let Some(surface) = &self.dnd_icon { + if let Some(surface) = self.dnd_icon.as_ref().map(|icon| &icon.surface) { send_dmabuf_feedback_surface_tree( surface, output, @@ -3508,7 +3517,7 @@ impl Niri { ); } - if let Some(surface) = &self.dnd_icon { + if let Some(surface) = self.dnd_icon.as_ref().map(|icon| &icon.surface) { send_frames_surface_tree( surface, output, @@ -3576,7 +3585,7 @@ impl Niri { } } - if let Some(surface) = &self.dnd_icon { + if let Some(surface) = &self.dnd_icon.as_ref().map(|icon| &icon.surface) { send_frames_surface_tree( surface, output, @@ -3615,7 +3624,7 @@ impl Niri { ); } - if let Some(surface) = &self.dnd_icon { + if let Some(surface) = self.dnd_icon.as_ref().map(|icon| &icon.surface) { take_presentation_feedback_surface_tree( surface, &mut feedback,