Update smithay for DnD updates

This commit is contained in:
Victoria Brekenfeld 2025-11-10 18:32:34 +01:00 committed by Victoria Brekenfeld
parent 3ddc9421e4
commit 77d3605fb9
12 changed files with 340 additions and 99 deletions

2
Cargo.lock generated
View file

@ -4952,7 +4952,7 @@ checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03"
[[package]] [[package]]
name = "smithay" name = "smithay"
version = "0.7.0" version = "0.7.0"
source = "git+https://github.com/smithay/smithay.git?rev=d40ada5#d40ada55eceac04fb1c752f0f17b0c32cf24fbb1" source = "git+https://github.com/smithay/smithay.git?rev=593b2d5#593b2d5fb32a24652d8cde12b53d6871d1bd2275"
dependencies = [ dependencies = [
"aliasable", "aliasable",
"appendlist", "appendlist",

View file

@ -146,4 +146,4 @@ cosmic-protocols = { git = "https://github.com/pop-os//cosmic-protocols", branch
cosmic-client-toolkit = { git = "https://github.com/pop-os//cosmic-protocols", branch = "main" } cosmic-client-toolkit = { git = "https://github.com/pop-os//cosmic-protocols", branch = "main" }
[patch.crates-io] [patch.crates-io]
smithay = { git = "https://github.com/smithay/smithay.git", rev = "d40ada5" } smithay = { git = "https://github.com/smithay/smithay.git", rev = "593b2d5" }

View file

@ -287,6 +287,12 @@ fn format_pointer_focus(focus: Option<PointerFocusTarget>) -> String {
} }
_ => format!("Surface {}", surface.id().protocol_id()), _ => format!("Surface {}", surface.id().protocol_id()),
}, },
Some(X11Surface { surface, toplevel }) => match toplevel {
Some(window) => {
format!("Window {} ({})", surface.window_id(), window.title())
}
_ => format!("X11Surface {}", surface.window_id()),
},
Some(StackUI(stack)) => format!( Some(StackUI(stack)) => format!(
"Stack SSD {} ({})", "Stack SSD {} ({})",
match stack.active().0.underlying_surface() { match stack.active().0.underlying_surface() {

View file

@ -502,18 +502,34 @@ impl State {
ptr.frame(self); ptr.frame(self);
return; return;
} }
if let PointerFocusTarget::WlSurface { surface, .. } = surface { match surface {
if under_from_surface_tree( PointerFocusTarget::WlSurface { surface, .. } => {
surface, if under_from_surface_tree(
position.as_logical() - surface_loc.to_f64(), surface,
(0, 0), position.as_logical() - surface_loc.to_f64(),
WindowSurfaceType::ALL, (0, 0),
) WindowSurfaceType::ALL,
.is_none() )
{ .is_none()
ptr.frame(self); {
return; ptr.frame(self);
return;
}
} }
PointerFocusTarget::X11Surface { surface, .. } => {
if surface
.surface_under(
position.as_logical() - surface_loc.to_f64(),
(0, 0),
WindowSurfaceType::ALL,
)
.is_none()
{
ptr.frame(self);
return;
}
}
_ => {}
} }
if let Some(region) = confine_region { if let Some(region) = confine_region {
if !region if !region
@ -2243,21 +2259,18 @@ impl State {
} }
} }
Stage::OverrideRedirect { surface, location } => { Stage::OverrideRedirect { surface, location } => {
if let Some(surface) = surface.wl_surface() { if let Some((_, surface_loc)) = surface.surface_under(
if let Some((surface, surface_loc)) = under_from_surface_tree( global_pos.as_logical(),
&surface, location.as_logical(),
global_pos.as_logical(), WindowSurfaceType::ALL,
location.as_logical(), ) {
WindowSurfaceType::ALL, return ControlFlow::Break(Ok(Some((
) { PointerFocusTarget::X11Surface {
return ControlFlow::Break(Ok(Some(( surface: surface.clone(),
PointerFocusTarget::WlSurface { toplevel: None,
surface, },
toplevel: None, surface_loc.as_global().to_f64(),
}, ))));
surface_loc.as_global().to_f64(),
))));
}
} }
} }
Stage::StickyPopups(floating_layer) => { Stage::StickyPopups(floating_layer) => {

View file

@ -523,18 +523,14 @@ impl CosmicStack {
let active_window = &p.windows.lock().unwrap()[p.active.load(Ordering::SeqCst)]; let active_window = &p.windows.lock().unwrap()[p.active.load(Ordering::SeqCst)];
stack_ui.or_else(|| { stack_ui.or_else(|| {
active_window active_window.focus_under(relative_pos, surface_type).map(
.0 |(target, surface_offset)| {
.surface_under(relative_pos, surface_type)
.map(|(surface, surface_offset)| {
( (
PointerFocusTarget::WlSurface { target,
surface,
toplevel: Some(active_window.clone().into()),
},
surface_offset.to_f64() + Point::from((0., TAB_HEIGHT as f64)), surface_offset.to_f64() + Point::from((0., TAB_HEIGHT as f64)),
) )
}) },
)
}) })
}) })
} }

View file

@ -1,4 +1,6 @@
use crate::wayland::protocols::corner_radius::CacheableCorners; use crate::{
shell::focus::target::PointerFocusTarget, wayland::protocols::corner_radius::CacheableCorners,
};
use std::{ use std::{
borrow::Cow, borrow::Cow,
sync::{ sync::{
@ -618,6 +620,38 @@ impl CosmicSurface {
} }
} }
pub fn focus_under(
&self,
relative_pos: Point<f64, Logical>,
surface_type: WindowSurfaceType,
) -> Option<(PointerFocusTarget, Point<f64, Logical>)> {
if let Some(xsurface) = self.x11_surface() {
xsurface
.surface_under(relative_pos, Point::default(), surface_type)
.map(|(_surface, surface_offset)| {
(
PointerFocusTarget::X11Surface {
surface: xsurface.clone(),
toplevel: Some(self.clone()),
},
surface_offset.to_f64(),
)
})
} else {
self.0
.surface_under(relative_pos, surface_type)
.map(|(surface, surface_offset)| {
(
PointerFocusTarget::WlSurface {
surface,
toplevel: Some(self.clone().into()),
},
surface_offset.to_f64(),
)
})
}
}
pub fn on_commit(&self) { pub fn on_commit(&self) {
self.0.on_commit(); self.0.on_commit();
} }

View file

@ -281,17 +281,9 @@ impl CosmicWindow {
} }
window_ui.or_else(|| { window_ui.or_else(|| {
p.window.0.surface_under(relative_pos, surface_type).map( p.window
|(surface, surface_offset)| { .focus_under(relative_pos, surface_type)
( .map(|(target, surface_offset)| (target, offset + surface_offset))
PointerFocusTarget::WlSurface {
surface,
toplevel: Some(p.window.clone().into()),
},
(offset + surface_offset.to_f64()),
)
},
)
}) })
}) })
} }

View file

@ -1,4 +1,8 @@
use std::{borrow::Cow, sync::Weak, time::Duration}; use std::{
borrow::Cow,
sync::{Arc, Weak},
time::Duration,
};
use crate::{ use crate::{
shell::{ shell::{
@ -16,6 +20,7 @@ use smithay::{
desktop::{LayerSurface, PopupKind, WindowSurface, WindowSurfaceType, space::SpaceElement}, desktop::{LayerSurface, PopupKind, WindowSurface, WindowSurfaceType, space::SpaceElement},
input::{ input::{
Seat, Seat,
dnd::{DndFocus, OfferData, Source},
keyboard::{KeyboardTarget, KeysymHandle, ModifiersState}, keyboard::{KeyboardTarget, KeysymHandle, ModifiersState},
pointer::{ pointer::{
AxisFrame, ButtonEvent, GestureHoldBeginEvent, GestureHoldEndEvent, AxisFrame, ButtonEvent, GestureHoldBeginEvent, GestureHoldEndEvent,
@ -29,11 +34,14 @@ use smithay::{
}, },
}, },
reexports::wayland_server::{ reexports::wayland_server::{
Client, Resource, backend::ObjectId, protocol::wl_surface::WlSurface, Client, DisplayHandle, Resource, backend::ObjectId, protocol::wl_surface::WlSurface,
}, },
utils::{IsAlive, Logical, Point, Serial, Transform}, utils::{IsAlive, Logical, Point, Serial, Transform},
wayland::{seat::WaylandFocus, session_lock::LockSurface}, wayland::{seat::WaylandFocus, selection::data_device::WlOfferData, session_lock::LockSurface},
xwayland::{X11Surface, xwm::XwmId}, xwayland::{
X11Surface,
xwm::{XwmId, XwmOfferData},
},
}; };
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq)]
@ -42,6 +50,10 @@ pub enum PointerFocusTarget {
surface: WlSurface, surface: WlSurface,
toplevel: Option<PointerFocusToplevel>, toplevel: Option<PointerFocusToplevel>,
}, },
X11Surface {
surface: X11Surface,
toplevel: Option<CosmicSurface>,
},
StackUI(CosmicStack), StackUI(CosmicStack),
WindowUI(CosmicWindow), WindowUI(CosmicWindow),
ResizeFork(ResizeForkTarget), ResizeFork(ResizeForkTarget),
@ -82,16 +94,32 @@ impl From<KeyboardFocusTarget> for PointerFocusTarget {
match target { match target {
KeyboardFocusTarget::Element(elem) => { KeyboardFocusTarget::Element(elem) => {
let window = elem.active_window(); let window = elem.active_window();
let surface = window.wl_surface().unwrap();
PointerFocusTarget::WlSurface { if let Some(xsurface) = window.x11_surface() {
surface: surface.into_owned(), PointerFocusTarget::X11Surface {
toplevel: Some(window.into()), surface: xsurface.clone(),
toplevel: Some(window),
}
} else {
PointerFocusTarget::WlSurface {
surface: window.wl_surface().unwrap().into_owned(),
toplevel: Some(window.into()),
}
}
}
KeyboardFocusTarget::Fullscreen(elem) => {
if let Some(xsurface) = elem.x11_surface() {
PointerFocusTarget::X11Surface {
surface: xsurface.clone(),
toplevel: Some(elem),
}
} else {
PointerFocusTarget::WlSurface {
surface: elem.wl_surface().unwrap().into_owned(),
toplevel: Some(elem.into()),
}
} }
} }
KeyboardFocusTarget::Fullscreen(elem) => PointerFocusTarget::WlSurface {
surface: elem.wl_surface().unwrap().into_owned(),
toplevel: Some(elem.into()),
},
KeyboardFocusTarget::LayerSurface(layer) => PointerFocusTarget::WlSurface { KeyboardFocusTarget::LayerSurface(layer) => PointerFocusTarget::WlSurface {
surface: layer.wl_surface().clone(), surface: layer.wl_surface().clone(),
toplevel: None, toplevel: None,
@ -113,6 +141,7 @@ impl PointerFocusTarget {
fn inner_pointer_target(&self) -> &dyn PointerTarget<State> { fn inner_pointer_target(&self) -> &dyn PointerTarget<State> {
match self { match self {
PointerFocusTarget::WlSurface { surface, .. } => surface, PointerFocusTarget::WlSurface { surface, .. } => surface,
PointerFocusTarget::X11Surface { surface, .. } => surface,
PointerFocusTarget::StackUI(u) => u, PointerFocusTarget::StackUI(u) => u,
PointerFocusTarget::WindowUI(u) => u, PointerFocusTarget::WindowUI(u) => u,
PointerFocusTarget::ResizeFork(f) => f, PointerFocusTarget::ResizeFork(f) => f,
@ -123,6 +152,7 @@ impl PointerFocusTarget {
fn inner_touch_target(&self) -> &dyn TouchTarget<State> { fn inner_touch_target(&self) -> &dyn TouchTarget<State> {
match self { match self {
PointerFocusTarget::WlSurface { surface, .. } => surface, PointerFocusTarget::WlSurface { surface, .. } => surface,
PointerFocusTarget::X11Surface { surface, .. } => surface,
PointerFocusTarget::StackUI(u) => u, PointerFocusTarget::StackUI(u) => u,
PointerFocusTarget::WindowUI(u) => u, PointerFocusTarget::WindowUI(u) => u,
PointerFocusTarget::ResizeFork(f) => f, PointerFocusTarget::ResizeFork(f) => f,
@ -148,9 +178,9 @@ impl PointerFocusTarget {
) )
}), }),
WindowSurface::X11(x11_surface) => Some(( WindowSurface::X11(x11_surface) => Some((
Self::WlSurface { Self::X11Surface {
surface: x11_surface.wl_surface()?, surface: x11_surface.clone(),
toplevel: Some(surface.clone().into()), toplevel: Some(surface.clone()),
}, },
Point::default(), Point::default(),
)), )),
@ -173,6 +203,10 @@ impl PointerFocusTarget {
.find(|(w, _)| w.wl_surface().map(|s2| s == *s2).unwrap_or(false)) .find(|(w, _)| w.wl_surface().map(|s2| s == *s2).unwrap_or(false))
.map(|(s, _)| s) .map(|(s, _)| s)
}), }),
PointerFocusTarget::X11Surface {
toplevel: Some(surface),
..
} => Some(surface.clone()),
PointerFocusTarget::StackUI(stack) => Some(stack.active()), PointerFocusTarget::StackUI(stack) => Some(stack.active()),
PointerFocusTarget::WindowUI(window) => Some(window.surface()), PointerFocusTarget::WindowUI(window) => Some(window.surface()),
_ => None, _ => None,
@ -184,6 +218,9 @@ impl PointerFocusTarget {
PointerFocusTarget::WlSurface { surface, .. } => { PointerFocusTarget::WlSurface { surface, .. } => {
surface.client().is_some_and(|c| c == *client) surface.client().is_some_and(|c| c == *client)
} }
PointerFocusTarget::X11Surface { surface, .. } => surface
.wl_surface()
.is_some_and(|s| s.client().is_some_and(|c| c == *client)),
_ => false, _ => false,
} }
} }
@ -263,6 +300,7 @@ impl IsAlive for PointerFocusTarget {
match self { match self {
// XXX? does this change anything // XXX? does this change anything
PointerFocusTarget::WlSurface { surface, .. } => surface.alive(), PointerFocusTarget::WlSurface { surface, .. } => surface.alive(),
PointerFocusTarget::X11Surface { surface, .. } => surface.alive(),
PointerFocusTarget::StackUI(e) => e.alive(), PointerFocusTarget::StackUI(e) => e.alive(),
PointerFocusTarget::WindowUI(e) => e.alive(), PointerFocusTarget::WindowUI(e) => e.alive(),
PointerFocusTarget::ResizeFork(f) => f.alive(), PointerFocusTarget::ResizeFork(f) => f.alive(),
@ -459,6 +497,146 @@ impl TouchTarget<State> for PointerFocusTarget {
} }
} }
pub enum CosmicOfferData<S: Source> {
Wl(WlOfferData<S>),
X11(XwmOfferData<S>),
}
impl<S: Source> OfferData for CosmicOfferData<S> {
fn disable(&self) {
match self {
CosmicOfferData::Wl(data) => data.disable(),
CosmicOfferData::X11(data) => data.disable(),
}
}
fn drop(&self) {
match self {
CosmicOfferData::Wl(data) => data.drop(),
CosmicOfferData::X11(data) => data.drop(),
}
}
fn validated(&self) -> bool {
match self {
CosmicOfferData::Wl(data) => data.validated(),
CosmicOfferData::X11(data) => data.validated(),
}
}
}
impl DndFocus<State> for PointerFocusTarget {
type OfferData<S>
= CosmicOfferData<S>
where
S: Source;
fn enter<S: Source>(
&self,
data: &mut State,
dh: &DisplayHandle,
source: Arc<S>,
seat: &Seat<State>,
location: Point<f64, Logical>,
serial: &Serial,
) -> Option<CosmicOfferData<S>> {
match self {
PointerFocusTarget::WlSurface { surface, .. } => {
DndFocus::enter(surface, data, dh, source, seat, location, serial)
.map(CosmicOfferData::Wl)
}
PointerFocusTarget::X11Surface { surface, .. } => {
DndFocus::enter(surface, data, dh, source, seat, location, serial)
.map(CosmicOfferData::X11)
}
_ => None,
}
}
fn motion<S: Source>(
&self,
data: &mut State,
offer: Option<&mut CosmicOfferData<S>>,
seat: &Seat<State>,
location: Point<f64, Logical>,
time: u32,
) {
match self {
PointerFocusTarget::WlSurface { surface, .. } => {
let offer = match offer {
Some(CosmicOfferData::Wl(offer)) => Some(offer),
None => None,
_ => return,
};
DndFocus::motion(surface, data, offer, seat, location, time)
}
PointerFocusTarget::X11Surface { surface, .. } => {
let offer = match offer {
Some(CosmicOfferData::X11(offer)) => Some(offer),
None => None,
_ => return,
};
DndFocus::motion(surface, data, offer, seat, location, time)
}
_ => {}
}
}
fn leave<S: Source>(
&self,
data: &mut State,
offer: Option<&mut CosmicOfferData<S>>,
seat: &Seat<State>,
) {
match self {
PointerFocusTarget::WlSurface { surface, .. } => {
let offer = match offer {
Some(CosmicOfferData::Wl(offer)) => Some(offer),
None => None,
_ => return,
};
DndFocus::leave(surface, data, offer, seat)
}
PointerFocusTarget::X11Surface { surface, .. } => {
let offer = match offer {
Some(CosmicOfferData::X11(offer)) => Some(offer),
None => None,
_ => return,
};
DndFocus::leave(surface, data, offer, seat)
}
_ => {}
}
}
fn drop<S: Source>(
&self,
data: &mut State,
offer: Option<&mut CosmicOfferData<S>>,
seat: &Seat<State>,
) {
match self {
PointerFocusTarget::WlSurface { surface, .. } => {
let offer = match offer {
Some(CosmicOfferData::Wl(offer)) => Some(offer),
None => None,
_ => return,
};
DndFocus::drop(surface, data, offer, seat)
}
PointerFocusTarget::X11Surface { surface, .. } => {
let offer = match offer {
Some(CosmicOfferData::X11(offer)) => Some(offer),
None => None,
_ => return,
};
DndFocus::drop(surface, data, offer, seat)
}
_ => {}
}
}
}
impl KeyboardTarget<State> for KeyboardFocusTarget { impl KeyboardTarget<State> for KeyboardFocusTarget {
fn enter( fn enter(
&self, &self,
@ -550,6 +728,7 @@ impl WaylandFocus for PointerFocusTarget {
fn wl_surface(&self) -> Option<Cow<'_, WlSurface>> { fn wl_surface(&self) -> Option<Cow<'_, WlSurface>> {
Some(match self { Some(match self {
PointerFocusTarget::WlSurface { surface, .. } => Cow::Borrowed(surface), PointerFocusTarget::WlSurface { surface, .. } => Cow::Borrowed(surface),
PointerFocusTarget::X11Surface { surface, .. } => Cow::Owned(surface.wl_surface()?),
PointerFocusTarget::ResizeFork(_) PointerFocusTarget::ResizeFork(_)
| PointerFocusTarget::StackUI(_) | PointerFocusTarget::StackUI(_)
| PointerFocusTarget::WindowUI(_) | PointerFocusTarget::WindowUI(_)
@ -561,15 +740,16 @@ impl WaylandFocus for PointerFocusTarget {
fn same_client_as(&self, object_id: &ObjectId) -> bool { fn same_client_as(&self, object_id: &ObjectId) -> bool {
match self { match self {
PointerFocusTarget::WlSurface { surface, .. } => surface.id().same_client_as(object_id), PointerFocusTarget::WlSurface { surface, .. } => surface.id().same_client_as(object_id),
PointerFocusTarget::X11Surface { surface, .. } => surface
.wl_surface()
.is_some_and(|s| s.id().same_client_as(object_id)),
PointerFocusTarget::StackUI(stack) => stack PointerFocusTarget::StackUI(stack) => stack
.active() .active()
.wl_surface() .wl_surface()
.map(|s| s.id().same_client_as(object_id)) .is_some_and(|s| s.id().same_client_as(object_id)),
.unwrap_or(false),
PointerFocusTarget::WindowUI(window) => window PointerFocusTarget::WindowUI(window) => window
.wl_surface() .wl_surface()
.map(|s| s.id().same_client_as(object_id)) .is_some_and(|s| s.id().same_client_as(object_id)),
.unwrap_or(false),
PointerFocusTarget::ResizeFork(_) | PointerFocusTarget::ZoomUI(_) => false, PointerFocusTarget::ResizeFork(_) | PointerFocusTarget::ZoomUI(_) => false,
} }
} }

View file

@ -908,19 +908,12 @@ impl Workspace {
let geometry = self.fullscreen_geometry().unwrap(); let geometry = self.fullscreen_geometry().unwrap();
return fullscreen return fullscreen
.surface .surface
.0 .focus_under(
.surface_under(
(location - geometry.loc.to_f64()).as_logical(), (location - geometry.loc.to_f64()).as_logical(),
WindowSurfaceType::TOPLEVEL | WindowSurfaceType::SUBSURFACE, WindowSurfaceType::TOPLEVEL | WindowSurfaceType::SUBSURFACE,
) )
.map(|(surface, surface_offset)| { .map(|(target, surface_offset)| {
( (target, (geometry.loc.to_f64() + surface_offset.as_local()))
PointerFocusTarget::WlSurface {
surface,
toplevel: Some(fullscreen.surface.clone().into()),
},
(geometry.loc + surface_offset.as_local()).to_f64(),
)
}); });
} }

View file

@ -5,15 +5,14 @@ use smithay::{
delegate_data_device, delegate_data_device,
input::{ input::{
Seat, Seat,
pointer::{CursorImageStatus, CursorImageSurfaceData}, dnd::{DnDGrab, DndGrabHandler, DndTarget, GrabType},
pointer::{CursorImageStatus, CursorImageSurfaceData, Focus},
}, },
reexports::wayland_server::protocol::{wl_data_source::WlDataSource, wl_surface::WlSurface}, reexports::wayland_server::protocol::wl_surface::WlSurface,
utils::{IsAlive, Logical, Point}, utils::{IsAlive, Logical, Point},
wayland::{ wayland::{
compositor::{self, SurfaceAttributes}, compositor::{self, SurfaceAttributes},
selection::data_device::{ selection::data_device::{DataDeviceHandler, DataDeviceState, WaylandDndGrabHandler},
ClientDndGrabHandler, DataDeviceHandler, DataDeviceState, ServerDndGrabHandler,
},
}, },
}; };
use std::sync::Mutex; use std::sync::Mutex;
@ -60,12 +59,14 @@ pub fn on_commit(surface: &WlSurface, seat: &Seat<State>) {
} }
} }
impl ClientDndGrabHandler for State { impl WaylandDndGrabHandler for State {
fn started( fn dnd_requested<S: smithay::input::dnd::Source>(
&mut self, &mut self,
_source: Option<WlDataSource>, source: S,
icon: Option<WlSurface>, icon: Option<WlSurface>,
seat: Seat<Self>, seat: Seat<Self>,
serial: smithay::utils::Serial,
type_: GrabType,
) { ) {
let user_data = seat.user_data(); let user_data = seat.user_data();
user_data.insert_if_missing_threadsafe::<Mutex<Option<DnDIcon>>, _>(Default::default); user_data.insert_if_missing_threadsafe::<Mutex<Option<DnDIcon>>, _>(Default::default);
@ -89,19 +90,46 @@ impl ClientDndGrabHandler for State {
.get::<Mutex<Option<DnDIcon>>>() .get::<Mutex<Option<DnDIcon>>>()
.unwrap() .unwrap()
.lock() .lock()
.unwrap() = icon.map(|surface| DnDIcon { surface, offset }) .unwrap() = icon.map(|surface| DnDIcon { surface, offset });
}
fn dropped(&mut self, _target: Option<WlSurface>, _validated: bool, seat: Seat<Self>) { match type_ {
seat.user_data() GrabType::Pointer => {
.get::<Mutex<Option<DnDIcon>>>() let pointer = seat.get_pointer().unwrap();
.unwrap() let start_data = pointer.grab_start_data().unwrap();
.lock() pointer.set_grab(
.unwrap() self,
.take(); DnDGrab::new_pointer(&self.common.display_handle, start_data, source, seat),
serial,
Focus::Keep,
);
}
GrabType::Touch => {
let touch = seat.get_touch().unwrap();
let start_data = touch.grab_start_data().unwrap();
touch.set_grab(
self,
DnDGrab::new_touch(&self.common.display_handle, start_data, source, seat),
serial,
);
}
}
} }
} }
impl ServerDndGrabHandler for State {}
impl DndGrabHandler for State {
fn dropped(
&mut self,
_target: Option<DndTarget<'_, Self>>,
_validated: bool,
seat: Seat<Self>,
_location: Point<f64, Logical>,
) {
if let Some(icon) = seat.user_data().get::<Mutex<Option<DnDIcon>>>() {
icon.lock().unwrap().take();
}
}
}
impl DataDeviceHandler for State { impl DataDeviceHandler for State {
fn data_device_state(&mut self) -> &mut DataDeviceState { fn data_device_state(&mut self) -> &mut DataDeviceState {
&mut self.common.data_device_state &mut self.common.data_device_state

View file

@ -71,9 +71,7 @@ impl SelectionHandler for State {
.as_mut() .as_mut()
.and_then(|xstate| xstate.xwm.as_mut()) .and_then(|xstate| xstate.xwm.as_mut())
{ {
if let Err(err) = if let Err(err) = xwm.send_selection(target, mime_type, fd) {
xwm.send_selection(target, mime_type, fd, self.common.event_loop_handle.clone())
{
warn!(?err, "Failed to send selection (X11 -> Wayland)."); warn!(?err, "Failed to send selection (X11 -> Wayland).");
} }
} }

View file

@ -114,6 +114,7 @@ impl State {
let wm = match X11Wm::start_wm( let wm = match X11Wm::start_wm(
data.common.event_loop_handle.clone(), data.common.event_loop_handle.clone(),
&data.common.display_handle,
x11_socket, x11_socket,
client.clone(), client.clone(),
) { ) {