Skip to content

Commit

Permalink
x11: store translated DnD coords
Browse files Browse the repository at this point in the history
  • Loading branch information
valadaptive committed Jan 10, 2025
1 parent 7d016a6 commit 6f33aa8
Show file tree
Hide file tree
Showing 2 changed files with 13 additions and 35 deletions.
5 changes: 3 additions & 2 deletions src/platform_impl/linux/x11/dnd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use std::path::{Path, PathBuf};
use std::str::Utf8Error;
use std::sync::Arc;

use dpi::PhysicalPosition;
use percent_encoding::percent_decode;
use x11rb::protocol::xproto::{self, ConnectionExt};

Expand Down Expand Up @@ -46,7 +47,7 @@ pub struct Dnd {
// Populated by XdndPosition event handler
pub source_window: Option<xproto::Window>,
// Populated by XdndPosition event handler
pub position: (i16, i16),
pub position: PhysicalPosition<f64>,
// Populated by SelectionNotify event handler (triggered by XdndPosition event handler)
pub result: Option<Result<Vec<PathBuf>, DndDataParseError>>,
// Populated by SelectionNotify event handler (triggered by XdndPosition event handler)
Expand All @@ -60,7 +61,7 @@ impl Dnd {
version: None,
type_list: None,
source_window: None,
position: (0, 0),
position: PhysicalPosition::default(),
result: None,
has_entered: false,
})
Expand Down
43 changes: 10 additions & 33 deletions src/platform_impl/linux/x11/event_processor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -471,15 +471,18 @@ impl EventProcessor {
let source_window = xev.data.get_long(0) as xproto::Window;

// https://www.freedesktop.org/wiki/Specifications/XDND/#xdndposition
// "data.l[2] contains the coordinates of the mouse position relative to the root
// window."
// "data.l[2] = (x << 16) | y"
// Note that coordinates are in "desktop space", not "window space"
// (in X11 parlance, they're root window coordinates)
let packed_coordinates = xev.data.get_long(2);
let x = (packed_coordinates >> 16) as i16;
let y = (packed_coordinates & 0xffff) as i16;
self.dnd.position = (x, y);

let coords = self
.target
.xconn
.translate_coords(self.target.root, window, x, y)
.expect("Failed to translate window coordinates");
self.dnd.position = PhysicalPosition::new(coords.dst_x as f64, coords.dst_y as f64);

// By our own state flow, `version` should never be `None` at this point.
let version = self.dnd.version.unwrap_or(5);
Expand Down Expand Up @@ -530,24 +533,11 @@ impl EventProcessor {
if xev.message_type == atoms[XdndDrop] as c_ulong {
let (source_window, state) = if let Some(source_window) = self.dnd.source_window {
if let Some(Ok(ref path_list)) = self.dnd.result {
let coords = self
.target
.xconn
.translate_coords(
self.target.root,
window,
self.dnd.position.0,
self.dnd.position.1,
)
.expect("Failed to translate window coordinates");

let position = PhysicalPosition::new(coords.dst_x as f64, coords.dst_y as f64);

callback(&self.target, Event::WindowEvent {
window_id,
event: WindowEvent::DragDrop {
paths: path_list.iter().map(Into::into).collect(),
position,
position: self.dnd.position,
},
});
}
Expand Down Expand Up @@ -598,30 +588,17 @@ impl EventProcessor {
let parse_result = self.dnd.parse_data(&mut data);

if let Ok(ref path_list) = parse_result {
let coords = self
.target
.xconn
.translate_coords(
self.target.root,
window,
self.dnd.position.0,
self.dnd.position.1,
)
.expect("Failed to translate window coordinates");

let position = PhysicalPosition::new(coords.dst_x as f64, coords.dst_y as f64);

if self.dnd.has_entered {
callback(&self.target, Event::WindowEvent {
window_id,
event: WindowEvent::DragOver { position },
event: WindowEvent::DragOver { position: self.dnd.position },
});
} else {
let paths = path_list.iter().map(Into::into).collect();
self.dnd.has_entered = true;
callback(&self.target, Event::WindowEvent {
window_id,
event: WindowEvent::DragEnter { paths, position },
event: WindowEvent::DragEnter { paths, position: self.dnd.position },
});
}
}
Expand Down

0 comments on commit 6f33aa8

Please sign in to comment.