dnd: correct handling of cursor buffer offset
This commit is contained in:
parent
bd04d68106
commit
afdb656778
4 changed files with 130 additions and 27 deletions
|
|
@ -3,25 +3,61 @@
|
|||
use crate::state::State;
|
||||
use smithay::{
|
||||
delegate_data_device,
|
||||
input::Seat,
|
||||
input::{
|
||||
pointer::{CursorImageStatus, CursorImageSurfaceData},
|
||||
Seat,
|
||||
},
|
||||
reexports::wayland_server::protocol::{wl_data_source::WlDataSource, wl_surface::WlSurface},
|
||||
utils::IsAlive,
|
||||
wayland::selection::data_device::{
|
||||
ClientDndGrabHandler, DataDeviceHandler, DataDeviceState, ServerDndGrabHandler,
|
||||
utils::{IsAlive, Logical, Point},
|
||||
wayland::{
|
||||
compositor::{self, SurfaceAttributes},
|
||||
selection::data_device::{
|
||||
ClientDndGrabHandler, DataDeviceHandler, DataDeviceState, ServerDndGrabHandler,
|
||||
},
|
||||
},
|
||||
};
|
||||
use std::sync::Mutex;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct DnDIcon {
|
||||
surface: Mutex<Option<WlSurface>>,
|
||||
pub surface: WlSurface,
|
||||
pub offset: Point<i32, Logical>,
|
||||
}
|
||||
|
||||
pub fn get_dnd_icon(seat: &Seat<State>) -> Option<WlSurface> {
|
||||
pub fn get_dnd_icon(seat: &Seat<State>) -> Option<DnDIcon> {
|
||||
let userdata = seat.user_data();
|
||||
userdata
|
||||
.get::<DnDIcon>()
|
||||
.and_then(|x| x.surface.lock().unwrap().clone())
|
||||
.filter(IsAlive::alive)
|
||||
.get::<Mutex<Option<DnDIcon>>>()
|
||||
.and_then(|x| x.lock().unwrap().clone())
|
||||
.filter(|icon| icon.surface.alive())
|
||||
}
|
||||
|
||||
pub fn on_commit(surface: &WlSurface, seat: &Seat<State>) {
|
||||
let userdata = seat.user_data();
|
||||
|
||||
let Some(mut guard) = userdata
|
||||
.get::<Mutex<Option<DnDIcon>>>()
|
||||
.map(|guard| guard.lock().unwrap())
|
||||
else {
|
||||
return;
|
||||
};
|
||||
|
||||
let Some(icon) = guard.as_mut() else {
|
||||
return;
|
||||
};
|
||||
|
||||
if &icon.surface == surface {
|
||||
compositor::with_states(surface, |states| {
|
||||
let buffer_delta = states
|
||||
.cached_state
|
||||
.get::<SurfaceAttributes>()
|
||||
.current()
|
||||
.buffer_delta
|
||||
.take()
|
||||
.unwrap_or_default();
|
||||
icon.offset += buffer_delta;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
impl ClientDndGrabHandler for State {
|
||||
|
|
@ -32,16 +68,39 @@ impl ClientDndGrabHandler for State {
|
|||
seat: Seat<Self>,
|
||||
) {
|
||||
let user_data = seat.user_data();
|
||||
user_data.insert_if_missing_threadsafe(|| DnDIcon {
|
||||
surface: Mutex::new(None),
|
||||
});
|
||||
*user_data.get::<DnDIcon>().unwrap().surface.lock().unwrap() = icon;
|
||||
user_data.insert_if_missing_threadsafe::<Mutex<Option<DnDIcon>>, _>(|| Default::default());
|
||||
|
||||
let offset = seat
|
||||
.user_data()
|
||||
.get::<Mutex<CursorImageStatus>>()
|
||||
.map(|guard| {
|
||||
if let CursorImageStatus::Surface(ref surface) = *guard.lock().unwrap() {
|
||||
compositor::with_states(surface, |states| {
|
||||
let hotspot = states
|
||||
.data_map
|
||||
.get::<CursorImageSurfaceData>()
|
||||
.unwrap()
|
||||
.lock()
|
||||
.unwrap()
|
||||
.hotspot;
|
||||
Point::from((-hotspot.x, -hotspot.y))
|
||||
})
|
||||
} else {
|
||||
(0, 0).into()
|
||||
}
|
||||
})
|
||||
.unwrap_or_default();
|
||||
|
||||
*user_data
|
||||
.get::<Mutex<Option<DnDIcon>>>()
|
||||
.unwrap()
|
||||
.lock()
|
||||
.unwrap() = icon.map(|surface| DnDIcon { surface, offset })
|
||||
}
|
||||
fn dropped(&mut self, seat: Seat<Self>) {
|
||||
seat.user_data()
|
||||
.get::<DnDIcon>()
|
||||
.get::<Mutex<Option<DnDIcon>>>()
|
||||
.unwrap()
|
||||
.surface
|
||||
.lock()
|
||||
.unwrap()
|
||||
.take();
|
||||
|
|
|
|||
|
|
@ -540,11 +540,16 @@ pub fn render_window_to_buffer(
|
|||
);
|
||||
}
|
||||
|
||||
if let Some(wl_surface) = get_dnd_icon(&seat) {
|
||||
if let Some(dnd_icon) = get_dnd_icon(&seat) {
|
||||
elements.extend(
|
||||
cursor::draw_dnd_icon(renderer, &wl_surface, location.to_i32_round(), 1.0)
|
||||
.into_iter()
|
||||
.map(WindowCaptureElement::from),
|
||||
cursor::draw_dnd_icon(
|
||||
renderer,
|
||||
&dnd_icon.surface,
|
||||
(location + dnd_icon.offset.to_f64()).to_i32_round(),
|
||||
1.0,
|
||||
)
|
||||
.into_iter()
|
||||
.map(WindowCaptureElement::from),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue