diff --git a/examples/data_device.rs b/examples/data_device.rs index 61c08b66e..fd3381552 100644 --- a/examples/data_device.rs +++ b/examples/data_device.rs @@ -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(); @@ -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(), @@ -177,6 +179,7 @@ struct DataDeviceWindow { window: Window, keyboard: Option, keyboard_focus: bool, + modifiers: Modifiers, pointer: Option, dnd_offers: Vec<(DragOffer, Vec, Option)>, selection_offers: Vec<(SelectionOffer, Vec, Option)>, @@ -437,9 +440,10 @@ impl KeyboardHandler for DataDeviceWindow { _: &QueueHandle, _: &wl_keyboard::WlKeyboard, _serial: u32, - _modifiers: Modifiers, + modifiers: Modifiers, _layout: u32, ) { + self.modifiers = modifiers; } } @@ -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)) @@ -475,9 +493,7 @@ impl PointerHandler for DataDeviceWindow { self.drag_sources.push((source, false)); } } - Motion { .. } => { - // dbg!(event.position); - } + Motion { .. } => {} _ => {} } } @@ -562,15 +578,22 @@ impl DataDeviceHandler for DataDeviceWindow { _conn: &Connection, _qh: &QueueHandle, 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| { @@ -590,24 +613,18 @@ impl DataDeviceHandler for DataDeviceWindow { } fn leave(&mut self, _conn: &Connection, _qh: &QueueHandle, _data_device: &WlDataDevice) { - println!("Data offer left"); + println!("Data device leave event"); } fn motion( &mut self, _conn: &Connection, _qh: &QueueHandle, - 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( @@ -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) { @@ -770,6 +787,8 @@ impl DataDeviceHandler for DataDeviceWindow { cur_offer.0.finish(); } } + } else { + println!("Internal drop performed"); } } } diff --git a/src/data_device_manager/data_device.rs b/src/data_device_manager/data_device.rs index ad51a8b70..087e457f4 100644 --- a/src/data_device_manager/data_device.rs +++ b/src/data_device_manager/data_device.rs @@ -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::{ @@ -37,7 +39,15 @@ pub trait DataDeviceHandler: Sized { // ); /// The data device pointer has entered a surface at the provided location - fn enter(&mut self, conn: &Connection, qh: &QueueHandle, data_device: &WlDataDevice); + fn enter( + &mut self, + conn: &Connection, + qh: &QueueHandle, + 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. @@ -45,7 +55,14 @@ pub trait DataDeviceHandler: Sized { fn leave(&mut self, conn: &Connection, qh: &QueueHandle, data_device: &WlDataDevice); /// Drag and Drop motion. - fn motion(&mut self, conn: &Connection, qh: &QueueHandle, data_device: &WlDataDevice); + fn motion( + &mut self, + conn: &Connection, + qh: &QueueHandle, + data_device: &WlDataDevice, + x: f64, + y: f64, + ); /// Advertises a new selection. fn selection(&mut self, conn: &Connection, qh: &QueueHandle, data_device: &WlDataDevice); @@ -129,13 +146,13 @@ where } let data = offer.data::().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. @@ -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() {