drag-rs
Start a drag operation out of a window on macOS, Windows and Linux (via GTK).
Built for Tauri, winit, tao or wry.
Setup
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
.
Rust
- 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::HasWindowHandle
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 = tao::event_loop::EventLoop::new();let window = tao::window::WindowBuilder::new().build(&event_loop).unwrap();let webview = wry::WebViewBuilder::new().build(&window).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,);- 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(())})
Tauri Plugin
tauri-plugin-drag
- Add the
tauri-plugin-drag
dependency:
$ cargo add tauri-plugin-drag
- Install the
@crabnebula/tauri-plugin-drag
NPM package containing the API bindings:
npm add @crabnebula/tauri-plugin-drag
yarn add @crabnebula/tauri-plugin-drag
pnpm 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");}
- Add permissions
capabilities/default.json
{ ... "permissions": [ ... "drag:default" ]}
- 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' })
tauri-plugin-drag-as-window
- 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:
npm add @crabnebula/tauri-plugin-drag-as-window
yarn add @crabnebula/tauri-plugin-drag-as-window
pnpm 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");}
- Add permissions
capabilities/default.json
{ ... "permissions": [ ... "drag-as-window:default" ]}
- Afterwards all the plugin’s APIs are available through the JavaScript guest bindings:
import { dragAsWindow, dragBack } from "@crabnebula/tauri-plugin-drag-as-window";import { getCurrentWebviewWindow, WebviewWindow } from "@tauri-apps/api/webviewWindow";// alternatively you can pass a DOM element instead of its selectordragAsWindow('#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) => { getCurrentWebviewWindow().close() })}