Skip to content

Commit 0d57d1d

Browse files
committed
input/dnd: Special case xwayland instead of working around it for all clients
1 parent 0224640 commit 0d57d1d

File tree

4 files changed

+139
-40
lines changed

4 files changed

+139
-40
lines changed

src/desktop/space/wayland/x11.rs

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,3 @@
1-
use std::borrow::Cow;
2-
3-
use wayland_server::protocol::wl_surface::WlSurface;
4-
51
use crate::{
62
backend::renderer::{
73
element::{
@@ -12,19 +8,11 @@ use crate::{
128
},
139
desktop::{space::SpaceElement, WindowSurfaceType},
1410
utils::{Logical, Physical, Point, Rectangle, Scale},
15-
wayland::seat::WaylandFocus,
1611
xwayland::X11Surface,
1712
};
1813

1914
use super::{output_update, WindowOutputUserData};
2015

21-
impl WaylandFocus for X11Surface {
22-
#[inline]
23-
fn wl_surface(&self) -> Option<Cow<'_, WlSurface>> {
24-
X11Surface::wl_surface(self).map(Cow::Owned)
25-
}
26-
}
27-
2816
impl SpaceElement for X11Surface {
2917
fn bbox(&self) -> Rectangle<i32, Logical> {
3018
let geo = X11Surface::geometry(self);

src/input/dnd/grab.rs

Lines changed: 85 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,11 @@ use std::{fmt, sync::Arc};
33
#[cfg(feature = "wayland_frontend")]
44
use wayland_server::DisplayHandle;
55

6+
#[cfg(feature = "xwayland")]
7+
use crate::{wayland::seat::WaylandFocus, xwayland::XWaylandClientData};
8+
#[cfg(feature = "xwayland")]
9+
use wayland_server::Resource;
10+
611
use crate::{
712
input::{
813
dnd::OfferData,
@@ -323,12 +328,7 @@ where
323328
focus: Option<(<D as SeatHandler>::PointerFocus, Point<f64, Logical>)>,
324329
event: &PointerMotionEvent,
325330
) {
326-
// While the grab is active, we still honor the implicit grab target
327-
handle.motion(
328-
data,
329-
self.pointer_start_data.as_ref().unwrap().focus.clone(),
330-
event,
331-
);
331+
handle.motion(data, self.ptr_focus(), event);
332332

333333
self.last_position = event.location;
334334

@@ -342,26 +342,13 @@ where
342342
_focus: Option<(<D as SeatHandler>::PointerFocus, Point<f64, Logical>)>,
343343
event: &RelativeMotionEvent,
344344
) {
345-
handle.relative_motion(
346-
data,
347-
self.pointer_start_data.as_ref().unwrap().focus.clone(),
348-
event,
349-
);
345+
handle.relative_motion(data, self.ptr_focus(), event);
350346
}
351347

352348
fn button(&mut self, data: &mut D, handle: &mut PointerInnerHandle<'_, D>, event: &ButtonEvent) {
353349
handle.button(data, event);
354350

355351
if handle.current_pressed().is_empty() {
356-
handle.motion(
357-
data,
358-
None,
359-
&PointerMotionEvent {
360-
location: self.last_position,
361-
serial: event.serial,
362-
time: event.time,
363-
},
364-
);
365352
// the user dropped, proceed to the drop
366353
handle.unset_grab(self, data, event.serial, event.time, true);
367354
}
@@ -496,6 +483,8 @@ where
496483
return;
497484
}
498485

486+
handle.motion(data, self.touch_focus(), event, seq);
487+
499488
self.last_position = event.location;
500489

501490
self.update_focus(
@@ -505,13 +494,6 @@ where
505494
SERIAL_COUNTER.next_serial(),
506495
event.time,
507496
);
508-
509-
handle.motion(
510-
data,
511-
self.touch_start_data.as_ref().unwrap().focus.clone(),
512-
event,
513-
seq,
514-
);
515497
}
516498

517499
fn frame(&mut self, data: &mut D, handle: &mut TouchInnerHandle<'_, D>, seq: Serial) {
@@ -549,3 +531,79 @@ where
549531
self.drop(data, DndTarget::Touch);
550532
}
551533
}
534+
535+
#[cfg(not(feature = "xwayland"))]
536+
impl<D, S> DnDGrab<D, S, D::PointerFocus>
537+
where
538+
D: DndGrabHandler,
539+
D: SeatHandler,
540+
<D as SeatHandler>::PointerFocus: DndFocus<D> + 'static,
541+
D: 'static,
542+
S: Source,
543+
{
544+
fn ptr_focus(&self) -> Option<(<D as SeatHandler>::PointerFocus, Point<f64, Logical>)> {
545+
None
546+
}
547+
}
548+
549+
#[cfg(not(feature = "xwayland"))]
550+
impl<D, S> DnDGrab<D, S, D::TouchFocus>
551+
where
552+
D: DndGrabHandler,
553+
D: SeatHandler,
554+
<D as SeatHandler>::TouchFocus: DndFocus<D> + 'static,
555+
D: 'static,
556+
S: Source,
557+
{
558+
fn touch_focus(&self) -> Option<(<D as SeatHandler>::TouchFocus, Point<f64, Logical>)> {
559+
None
560+
}
561+
}
562+
563+
#[cfg(feature = "xwayland")]
564+
impl<D, S> DnDGrab<D, S, D::PointerFocus>
565+
where
566+
D: DndGrabHandler,
567+
D: SeatHandler,
568+
<D as SeatHandler>::PointerFocus: DndFocus<D> + 'static,
569+
D: 'static,
570+
S: Source,
571+
{
572+
fn ptr_focus(&self) -> Option<(<D as SeatHandler>::PointerFocus, Point<f64, Logical>)> {
573+
// While the grab is active, we don't want any focus except for xwayland
574+
self.pointer_start_data
575+
.as_ref()?
576+
.focus
577+
.clone()
578+
.filter(|(focus, _)| {
579+
focus.wl_surface().is_some_and(|s| {
580+
s.client()
581+
.is_some_and(|c| c.get_data::<XWaylandClientData>().is_some())
582+
})
583+
})
584+
}
585+
}
586+
587+
#[cfg(feature = "xwayland")]
588+
impl<D, S> DnDGrab<D, S, D::TouchFocus>
589+
where
590+
D: DndGrabHandler,
591+
D: SeatHandler,
592+
<D as SeatHandler>::TouchFocus: DndFocus<D> + 'static,
593+
D: 'static,
594+
S: Source,
595+
{
596+
fn touch_focus(&self) -> Option<(<D as SeatHandler>::TouchFocus, Point<f64, Logical>)> {
597+
// While the grab is active, we don't want any focus except for xwayland
598+
self.touch_start_data
599+
.as_ref()?
600+
.focus
601+
.clone()
602+
.filter(|(focus, _)| {
603+
focus.wl_surface().is_some_and(|s| {
604+
s.client()
605+
.is_some_and(|c| c.get_data::<XWaylandClientData>().is_some())
606+
})
607+
})
608+
}
609+
}

src/input/dnd/mod.rs

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ use smallvec::SmallVec;
88
#[cfg(feature = "wayland_frontend")]
99
use wayland_server::DisplayHandle;
1010

11+
#[cfg(feature = "xwayland")]
12+
use crate::wayland::seat::WaylandFocus;
1113
use crate::{
1214
input::{Seat, SeatHandler},
1315
utils::{IsAlive, Logical, Point, Serial},
@@ -83,6 +85,47 @@ pub trait OfferData: Send + 'static {
8385
fn validated(&self) -> bool;
8486
}
8587

88+
// We sadly have to duplicate this whole trait for code in `DnDGrab`,
89+
// because conditional trait bounds are not a thing (yet? rust-lang/rust#115590)
90+
#[cfg(feature = "xwayland")]
91+
/// A potential Drag'n'Drop target
92+
pub trait DndFocus<D: SeatHandler>: WaylandFocus + IsAlive + PartialEq {
93+
/// OfferData implementation returned by this target
94+
type OfferData<S>: OfferData
95+
where
96+
S: Source;
97+
98+
/// An active Drag'n'Drop operation has entered the client
99+
fn enter<S: Source>(
100+
&self,
101+
data: &mut D,
102+
#[cfg(feature = "wayland_frontend")] dh: &DisplayHandle,
103+
source: Arc<S>,
104+
seat: &Seat<D>,
105+
location: Point<f64, Logical>,
106+
serial: &Serial,
107+
) -> Option<Self::OfferData<S>>;
108+
109+
/// An active Drag'n'Drop operation, which has previously
110+
/// entered the client, has been moved
111+
fn motion<S: Source>(
112+
&self,
113+
data: &mut D,
114+
offer: Option<&mut Self::OfferData<S>>,
115+
seat: &Seat<D>,
116+
location: Point<f64, Logical>,
117+
time: u32,
118+
);
119+
120+
/// An active Drag'n'Drop operation, which has previously
121+
/// entered the client, left again.
122+
fn leave<S: Source>(&self, data: &mut D, offer: Option<&mut Self::OfferData<S>>, seat: &Seat<D>);
123+
124+
/// An active Drag'n'Drop operation, which has previously
125+
/// entered the client, has been dropped.
126+
fn drop<S: Source>(&self, data: &mut D, offer: Option<&mut Self::OfferData<S>>, seat: &Seat<D>);
127+
}
128+
#[cfg(not(feature = "xwayland"))]
86129
/// A potential Drag'n'Drop target
87130
pub trait DndFocus<D: SeatHandler>: IsAlive + PartialEq {
88131
/// OfferData implementation returned by this target

src/xwayland/xwm/surface.rs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,10 @@ use crate::{
1111
Seat, SeatHandler,
1212
},
1313
utils::{user_data::UserDataMap, Client, IsAlive, Logical, Rectangle, Serial, Size},
14-
wayland::{compositor, seat::keyboard::enter_internal},
14+
wayland::{
15+
compositor,
16+
seat::{keyboard::enter_internal, WaylandFocus},
17+
},
1518
};
1619
#[cfg(feature = "desktop")]
1720
use crate::{
@@ -22,6 +25,7 @@ use crate::{
2225
use atomic_float::AtomicF64;
2326
use encoding_rs::WINDOWS_1252;
2427
use std::{
28+
borrow::Cow,
2529
collections::HashSet,
2630
sync::{
2731
atomic::{AtomicBool, Ordering},
@@ -1342,3 +1346,9 @@ impl<D: SeatHandler + 'static> TouchTarget<D> for X11Surface {
13421346
}
13431347
}
13441348
}
1349+
1350+
impl WaylandFocus for X11Surface {
1351+
fn wl_surface(&self) -> Option<Cow<'_, WlSurface>> {
1352+
X11Surface::wl_surface(self).map(Cow::Owned)
1353+
}
1354+
}

0 commit comments

Comments
 (0)