2022-07-04 15:26:26 +02:00
|
|
|
// SPDX-License-Identifier: GPL-3.0-only
|
|
|
|
|
|
2022-07-04 16:00:29 +02:00
|
|
|
use crate::state::State;
|
2022-07-04 15:26:26 +02:00
|
|
|
use smithay::{
|
2022-07-04 16:00:29 +02:00
|
|
|
delegate_data_device,
|
2024-09-13 19:22:57 +02:00
|
|
|
input::{
|
|
|
|
|
pointer::{CursorImageStatus, CursorImageSurfaceData},
|
|
|
|
|
Seat,
|
|
|
|
|
},
|
2022-07-04 16:00:29 +02:00
|
|
|
reexports::wayland_server::protocol::{wl_data_source::WlDataSource, wl_surface::WlSurface},
|
2024-09-13 19:22:57 +02:00
|
|
|
utils::{IsAlive, Logical, Point},
|
|
|
|
|
wayland::{
|
|
|
|
|
compositor::{self, SurfaceAttributes},
|
|
|
|
|
selection::data_device::{
|
|
|
|
|
ClientDndGrabHandler, DataDeviceHandler, DataDeviceState, ServerDndGrabHandler,
|
|
|
|
|
},
|
2022-07-04 15:26:26 +02:00
|
|
|
},
|
|
|
|
|
};
|
2024-06-17 15:13:14 +02:00
|
|
|
use std::sync::Mutex;
|
2022-07-04 15:26:26 +02:00
|
|
|
|
2024-09-13 19:22:57 +02:00
|
|
|
#[derive(Debug, Clone)]
|
2022-07-04 15:26:26 +02:00
|
|
|
pub struct DnDIcon {
|
2024-09-13 19:22:57 +02:00
|
|
|
pub surface: WlSurface,
|
|
|
|
|
pub offset: Point<i32, Logical>,
|
2022-07-04 15:26:26 +02:00
|
|
|
}
|
|
|
|
|
|
2024-09-13 19:22:57 +02:00
|
|
|
pub fn get_dnd_icon(seat: &Seat<State>) -> Option<DnDIcon> {
|
2022-07-04 15:26:26 +02:00
|
|
|
let userdata = seat.user_data();
|
|
|
|
|
userdata
|
2024-09-13 19:22:57 +02:00
|
|
|
.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;
|
|
|
|
|
});
|
|
|
|
|
}
|
2022-07-04 15:26:26 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl ClientDndGrabHandler for State {
|
|
|
|
|
fn started(
|
2022-07-04 16:00:29 +02:00
|
|
|
&mut self,
|
|
|
|
|
_source: Option<WlDataSource>,
|
|
|
|
|
icon: Option<WlSurface>,
|
|
|
|
|
seat: Seat<Self>,
|
2022-07-04 15:26:26 +02:00
|
|
|
) {
|
|
|
|
|
let user_data = seat.user_data();
|
2024-09-13 19:22:57 +02:00
|
|
|
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 })
|
2022-07-04 15:26:26 +02:00
|
|
|
}
|
2024-11-18 19:48:17 +01:00
|
|
|
|
|
|
|
|
fn dropped(&mut self, _target: Option<WlSurface>, _validated: bool, seat: Seat<Self>) {
|
2022-07-04 15:26:26 +02:00
|
|
|
seat.user_data()
|
2024-09-13 19:22:57 +02:00
|
|
|
.get::<Mutex<Option<DnDIcon>>>()
|
2022-07-04 15:26:26 +02:00
|
|
|
.unwrap()
|
2024-06-17 15:13:14 +02:00
|
|
|
.lock()
|
|
|
|
|
.unwrap()
|
2022-07-04 15:26:26 +02:00
|
|
|
.take();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
impl ServerDndGrabHandler for State {}
|
|
|
|
|
impl DataDeviceHandler for State {
|
|
|
|
|
fn data_device_state(&self) -> &DataDeviceState {
|
|
|
|
|
&self.common.data_device_state
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
delegate_data_device!(State);
|