mirror of
https://github.com/storytold/pdfcraft.git
synced 2026-10-29 12:38:58 -06:00
Files dragged from outside onto the Pages panel are inserted at the gap under the pointer (with a drop indicator) instead of opening as new documents. Files dropped beside the panel still open as before. On Windows, winit sends no pointer moves while files are dragged over the window, so the cursor is read with GetPhysicalCursorPos (winsafe "user" feature). This also makes the page grid show and use the gap under the pointer during a drag on Windows. Linux/BSD still have no pointer during a drag and keep the existing fallback. Tests: two new kittest cases in tests/editing.rs (drop on the panel inserts at the gap / at the end; drop beside the panel opens a document). The Windows cursor path was checked by hand.
41 lines
2.0 KiB
Rust
41 lines
2.0 KiB
Rust
//! Where the pointer is while files are dragged over the window. The windowing layer reports
|
|
//! that a file hovers, but not where, and sends no pointer moves until the drag ends; the
|
|
//! system has to be asked.
|
|
|
|
/// The pointer in this window's coordinates (egui points), when the system can tell.
|
|
#[cfg(target_os = "macos")]
|
|
pub(crate) fn in_window(ctx: &egui::Context) -> Option<egui::Pos2> {
|
|
use objc2_app_kit::{NSEvent, NSScreen};
|
|
// AppKit's screen list is only for the main thread (where egui runs).
|
|
let mtm = objc2::MainThreadMarker::new()?;
|
|
// Screen coordinates start at the bottom-left of the first screen; windows at their top-left.
|
|
let top = NSScreen::screens(mtm).firstObject()?.frame().size.height;
|
|
let pointer = NSEvent::mouseLocation();
|
|
let inner = ctx.input(|i| i.viewport().inner_rect)?;
|
|
// egui's points are the system's, divided by the zoom factor.
|
|
let zoom = ctx.zoom_factor().max(0.01) as f64;
|
|
let (x, y) = (pointer.x / zoom, (top - pointer.y) / zoom);
|
|
let pos = egui::pos2(x as f32 - inner.min.x, y as f32 - inner.min.y);
|
|
(pos.x.is_finite() && pos.y.is_finite()).then_some(pos)
|
|
}
|
|
|
|
/// The pointer in this window's coordinates (egui points), when the system can tell.
|
|
#[cfg(windows)]
|
|
pub(crate) fn in_window(ctx: &egui::Context) -> Option<egui::Pos2> {
|
|
// Physical screen pixels, whatever this thread's DPI awareness.
|
|
let pointer = winsafe::GetPhysicalCursorPos().ok()?;
|
|
let inner = ctx.input(|i| i.viewport().inner_rect)?;
|
|
// egui places the window in points: physical pixels over the pixels per point (zoom included).
|
|
let ppp = ctx.pixels_per_point();
|
|
if !(ppp.is_finite() && ppp > 0.0) {
|
|
return None;
|
|
}
|
|
let pos = egui::pos2(pointer.x as f32 / ppp - inner.min.x, pointer.y as f32 / ppp - inner.min.y);
|
|
(pos.x.is_finite() && pos.y.is_finite()).then_some(pos)
|
|
}
|
|
|
|
#[cfg(not(any(target_os = "macos", windows)))]
|
|
pub(crate) fn in_window(_ctx: &egui::Context) -> Option<egui::Pos2> {
|
|
None
|
|
}
|