Start a drag operation out of a window on macOS, Windows and Linux (via GTK).
Tested for tao (latest), winit (latest), wry (v0.24) and tauri (v1) windows. Due to the GTK-based implementation, winit currently cannot leverage this crate on Linux yet.
This project also includes a Tauri plugin for simplified usage on Tauri apps.
There's two ways to consume this crate API: from Rust code via the drag
crate or from Tauri's frontend via tauri-plugin-drag
or tauri-plugin-drag-as-window
.
- Add the
drag
dependency:
$ cargo add drag
-
Define the drag item and preview icon:
let item = drag::DragItem::Files(vec![std::fs::canonicalize("./examples/icon.png").unwrap()]); let preview_icon = drag::Image::Raw(include_bytes!("../../icon.png").to_vec());
-
Use the
drag::start_drag
function. It takes a&T: raw_window_handle::HasRawWindowHandle
type on macOS and Windows, and a>k::ApplicationWindow
on Linux:- tao:
let event_loop = tao::event_loop::EventLoop::new(); let window = tao::window::WindowBuilder::new().build(&event_loop).unwrap(); drag::start_drag( #[cfg(target_os = "linux")] { use tao::platform::unix::WindowExtUnix; window.gtk_window() }, #[cfg(not(target_os = "linux"))] &window, item, preview_icon, );
- wry:
let event_loop = wry::application::event_loop::EventLoop::new(); let window = wry::application::window::WindowBuilder::new().build(&event_loop).unwrap(); let webview = wry::webview::WebViewBuilder::new(window).unwrap().build().unwrap(); drag::start_drag( #[cfg(target_os = "linux")] { use wry::application::platform::unix::WindowExtUnix; webview.window().gtk_window() }, #[cfg(not(target_os = "linux"))] &webview.window(), item, preview_icon, );
- winit:
let event_loop = winit::event_loop::EventLoop::new().unwrap(); let window = winit::window::WindowBuilder::new().build(&event_loop).unwrap(); let _ = drag::start_drag(&window, item, preview_icon);
- tauri:
tauri::Builder::default() .setup(|app| { let window = app.get_window("main").unwrap(); drag::start_drag( #[cfg(target_os = "linux")] &window.gtk_window()?, #[cfg(not(target_os = "linux"))] &window, item, preview_icon ); Ok(()) })
- Add the
tauri-plugin-drag
dependency:
$ cargo add tauri-plugin-drag
- Install the
@crabnebula/tauri-plugin-drag
NPM package containing the API bindings:
pnpm add @crabnebula/tauri-plugin-drag
# or
npm add @crabnebula/tauri-plugin-drag
# or
yarn add @crabnebula/tauri-plugin-drag
- Register the core plugin with Tauri:
src-tauri/src/main.rs
fn main() {
tauri::Builder::default()
.plugin(tauri_plugin_drag::init())
.run(tauri::generate_context!())
.expect("error while running tauri application");
}
- Afterwards all the plugin's APIs are available through the JavaScript guest bindings:
import { startDrag } from "@crabnebula/tauri-plugin-drag";
startDrag({ item: ['/path/to/drag/file'], icon: '/path/to/icon/image' })
- Add the
tauri-plugin-drag-as-window
dependency:
$ cargo add tauri-plugin-drag-as-window
- Install the
@crabnebula/tauri-plugin-drag-as-window
NPM package containing the API bindings:
pnpm add @crabnebula/tauri-plugin-drag-as-window
# or
npm add @crabnebula/tauri-plugin-drag-as-window
# or
yarn add @crabnebula/tauri-plugin-drag-as-window
- Register the core plugin with Tauri:
src-tauri/src/main.rs
fn main() {
tauri::Builder::default()
.plugin(tauri_plugin_drag_as_window::init())
.run(tauri::generate_context!())
.expect("error while running tauri application");
}
- Afterwards all the plugin's APIs are available through the JavaScript guest bindings:
import { dragAsWindow, dragBack } from "@crabnebula/tauri-plugin-drag-as-window";
import { appWindow, WebviewWindow } from "@tauri-apps/api/window";
// alternatively you can pass a DOM element instead of its selector
dragAsWindow('#my-drag-element', (payload) => {
console.log('dropped!')
// create the window with the content from the current element (that's is up to you!)
new WebviewWindow('label', {
x: payload.cursorPos.x,
y: payload.cursorPos.y,
})
})
const el = document.querySelector('#my-drag-element')
el.ondragstart = (event) => {
event.preventDefault()
dragBack(event.target, { data: 'some data' }, (payload) => {
appWindow.close()
})
}
Running the examples:
cargo run --bin [tauri-app|winit-app|tao-app|wry-app]
Additional drag as window examples are available for tauri and wry:
cargo run --bin [tauri-app-dragout|wry-app-dragout]
MIT or MIT/Apache 2.0 where applicable.