Skip to content

Commit

Permalink
fix: internal DnD event handlers need position and surface
Browse files Browse the repository at this point in the history
no data offer is included for internal DnD operations, so event handlers have no way of accessing the position and surface
  • Loading branch information
wash2 committed Jan 22, 2024
1 parent da3e5c5 commit 096ce4f
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 27 deletions.
59 changes: 39 additions & 20 deletions examples/data_device.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,9 @@ use wayland_protocols::wp::primary_selection::zv1::client::{

fn main() {
println!(
"Press c to set the selection, p to set primary selection, or click and drag on\
the window to drag and drop. Selection contents are printed automatically."
"Press c to set the selection, p to set primary selection, or click and drag on \
the window to drag and drop. Selection contents are printed automatically. Ctrl \
+ click and drag to start an internal drag."
);
env_logger::init();

Expand Down Expand Up @@ -135,6 +136,7 @@ fn main() {
width: 256,
keyboard: None,
keyboard_focus: false,
modifiers: Modifiers::default(),
pointer: None,
seat_objects: Vec::new(),
copy_paste_sources: Vec::new(),
Expand Down Expand Up @@ -177,6 +179,7 @@ struct DataDeviceWindow {
window: Window,
keyboard: Option<wl_keyboard::WlKeyboard>,
keyboard_focus: bool,
modifiers: Modifiers,
pointer: Option<wl_pointer::WlPointer>,
dnd_offers: Vec<(DragOffer, Vec<u8>, Option<RegistrationToken>)>,
selection_offers: Vec<(SelectionOffer, Vec<u8>, Option<RegistrationToken>)>,
Expand Down Expand Up @@ -437,9 +440,10 @@ impl KeyboardHandler for DataDeviceWindow {
_: &QueueHandle<Self>,
_: &wl_keyboard::WlKeyboard,
_serial: u32,
_modifiers: Modifiers,
modifiers: Modifiers,
_layout: u32,
) {
self.modifiers = modifiers;
}
}

Expand All @@ -458,7 +462,21 @@ impl PointerHandler for DataDeviceWindow {
continue;
}
let surface = event.surface.clone();

match event.kind {
Press { button, serial, .. } if button == BTN_LEFT && self.modifiers.ctrl => {
if let Some(seat) =
self.seat_objects.iter().find(|seat| seat.pointer.as_ref() == Some(pointer))
{
println!("Starting an internal drag...");
DragSource::start_internal_drag(
&seat.data_device,
self.window.wl_surface(),
None,
serial,
);
}
}
Press { button, serial, .. } if button == BTN_LEFT => {
if let Some(seat) =
self.seat_objects.iter().find(|seat| seat.pointer.as_ref() == Some(pointer))
Expand All @@ -475,9 +493,7 @@ impl PointerHandler for DataDeviceWindow {
self.drag_sources.push((source, false));
}
}
Motion { .. } => {
// dbg!(event.position);
}
Motion { .. } => {}
_ => {}
}
}
Expand Down Expand Up @@ -562,15 +578,22 @@ impl DataDeviceHandler for DataDeviceWindow {
_conn: &Connection,
_qh: &QueueHandle<Self>,
wl_data_device: &WlDataDevice,
x: f64,
y: f64,
_surface: &wl_surface::WlSurface,
) {
println!("Data device enter x: {x:.2} y: {y:.2}");
let data_device = &self
.seat_objects
.iter()
.find(|seat| seat.data_device.inner() == wl_data_device)
.unwrap()
.data_device;
let drag_offer = data_device.data().drag_offer().unwrap();
println!("data offer entered x: {:.2} y: {:.2}", drag_offer.x, drag_offer.y);

let Some(drag_offer) = data_device.data().drag_offer() else {
println!("Internal drag");
return;
};

// Accept the first mime type we support.
if let Some(mime) = drag_offer.with_mime_types(|mime_types| {
Expand All @@ -590,24 +613,18 @@ impl DataDeviceHandler for DataDeviceWindow {
}

fn leave(&mut self, _conn: &Connection, _qh: &QueueHandle<Self>, _data_device: &WlDataDevice) {
println!("Data offer left");
println!("Data device leave event");
}

fn motion(
&mut self,
_conn: &Connection,
_qh: &QueueHandle<Self>,
wl_data_device: &WlDataDevice,
_wl_data_device: &WlDataDevice,
x: f64,
y: f64,
) {
let data_device = &self
.seat_objects
.iter()
.find(|seat| seat.data_device.inner() == wl_data_device)
.unwrap()
.data_device;
let DragOffer { x, y, time, .. } = data_device.data().drag_offer().unwrap();

dbg!((time, x, y));
println!("Data Device motion event x: {:.2} y: {:.2}", x, y);
}

fn selection(
Expand Down Expand Up @@ -702,7 +719,7 @@ impl DataDeviceHandler for DataDeviceWindow {
.unwrap()
.data_device;
if let Some(offer) = data_device.data().drag_offer() {
println!("Dropped: {offer:?}");
println!("Data device dropped event: {offer:?}");
self.dnd_offers.push((offer.clone(), Vec::new(), None));
let cur_offer = self.dnd_offers.last_mut().unwrap();
let mime_type = match offer.with_mime_types(pick_mime) {
Expand Down Expand Up @@ -770,6 +787,8 @@ impl DataDeviceHandler for DataDeviceWindow {
cur_offer.0.finish();
}
}
} else {
println!("Internal drop performed");
}
}
}
Expand Down
31 changes: 24 additions & 7 deletions src/data_device_manager/data_device.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ use std::{
sync::{Arc, Mutex},
};

use wayland_client::protocol::wl_surface::WlSurface;

use crate::{
data_device_manager::data_offer::DataDeviceOffer,
reexports::client::{
Expand Down Expand Up @@ -37,15 +39,30 @@ pub trait DataDeviceHandler: Sized {
// );

/// The data device pointer has entered a surface at the provided location
fn enter(&mut self, conn: &Connection, qh: &QueueHandle<Self>, data_device: &WlDataDevice);
fn enter(
&mut self,
conn: &Connection,
qh: &QueueHandle<Self>,
data_device: &WlDataDevice,
x: f64,
y: f64,
wl_surface: &WlSurface,
);

/// The drag and drop pointer has left the surface and the session ends.
/// The offer will be destroyed unless it was previously dropped.
/// In the case of a dropped offer, the client must destroy it manually after it is finished.
fn leave(&mut self, conn: &Connection, qh: &QueueHandle<Self>, data_device: &WlDataDevice);

/// Drag and Drop motion.
fn motion(&mut self, conn: &Connection, qh: &QueueHandle<Self>, data_device: &WlDataDevice);
fn motion(
&mut self,
conn: &Connection,
qh: &QueueHandle<Self>,
data_device: &WlDataDevice,
x: f64,
y: f64,
);

/// Advertises a new selection.
fn selection(&mut self, conn: &Connection, qh: &QueueHandle<Self>, data_device: &WlDataDevice);
Expand Down Expand Up @@ -129,13 +146,13 @@ where
}

let data = offer.data::<DataOfferData>().unwrap();
data.to_dnd_offer(serial, surface, x, y, None);
data.to_dnd_offer(serial, surface.clone(), x, y, None);

inner.drag_offer = Some(offer.clone());
// XXX Drop done here to prevent Mutex deadlocks.
drop(inner);
state.enter(conn, qh, data_device);
}
// XXX Drop done here to prevent Mutex deadlocks.
drop(inner);
state.enter(conn, qh, data_device, x, y, &surface);
}
Event::Leave => {
// We must destroy the offer we've got on enter.
Expand All @@ -159,7 +176,7 @@ where

// XXX Drop done here to prevent Mutex deadlocks.
drop(inner);
state.motion(conn, qh, data_device);
state.motion(conn, qh, data_device, x, y);
}
Event::Drop => {
if let Some(offer) = inner.drag_offer.take() {
Expand Down

0 comments on commit 096ce4f

Please sign in to comment.