mirror of
https://github.com/wez/wezterm.git
synced 2024-10-26 15:52:29 +03:00
Implement dispatch_dropped_files
This commit is contained in:
parent
5d6e7c4f98
commit
21a6b0636a
@ -9,19 +9,56 @@ use smithay_client_toolkit::data_device_manager::data_device::{
|
||||
use smithay_client_toolkit::data_device_manager::data_offer::DataOfferHandler;
|
||||
use smithay_client_toolkit::data_device_manager::data_source::DataSourceHandler;
|
||||
use smithay_client_toolkit::data_device_manager::WritePipe;
|
||||
use wayland_client::protocol::wl_data_device_manager::DndAction;
|
||||
use wayland_client::Proxy;
|
||||
|
||||
use crate::wayland::drag_and_drop::SurfaceAndOffer;
|
||||
use crate::wayland::pointer::PointerUserData;
|
||||
use crate::wayland::SurfaceUserData;
|
||||
|
||||
use super::drag_and_drop::{DragAndDrop, SurfaceAndPipe};
|
||||
use super::state::WaylandState;
|
||||
|
||||
pub(super) const TEXT_MIME_TYPE: &str = "text/plain;charset=utf-8";
|
||||
pub(super) const URI_MIME_TYPE: &str = "text/uri-list";
|
||||
|
||||
impl DataDeviceHandler for WaylandState {
|
||||
fn enter(
|
||||
&mut self,
|
||||
_conn: &wayland_client::Connection,
|
||||
_qh: &wayland_client::QueueHandle<Self>,
|
||||
_data_device: DataDevice,
|
||||
data_device: DataDevice,
|
||||
) {
|
||||
todo!()
|
||||
let mut drag_offer = data_device.drag_offer().unwrap();
|
||||
log::trace!(
|
||||
"Data offer entered: {:?}, mime_types: {:?}",
|
||||
drag_offer,
|
||||
data_device.drag_mime_types()
|
||||
);
|
||||
|
||||
if let Some(m) = data_device
|
||||
.drag_mime_types()
|
||||
.iter()
|
||||
.find(|s| *s == URI_MIME_TYPE)
|
||||
{
|
||||
drag_offer.accept_mime_type(*self.last_serial.borrow(), Some(m.clone()));
|
||||
}
|
||||
|
||||
drag_offer.set_actions(DndAction::None | DndAction::Copy, DndAction::None);
|
||||
|
||||
let pointer = self.pointer.as_mut().unwrap();
|
||||
let mut pstate = pointer
|
||||
.pointer()
|
||||
.data::<PointerUserData>()
|
||||
.unwrap()
|
||||
.state
|
||||
.lock()
|
||||
.unwrap();
|
||||
|
||||
let offer = drag_offer.inner().clone();
|
||||
let window_id = SurfaceUserData::from_wl(&drag_offer.surface).window_id;
|
||||
|
||||
pstate.drag_and_drop.offer = Some(SurfaceAndOffer { window_id, offer });
|
||||
}
|
||||
|
||||
fn leave(
|
||||
@ -30,7 +67,17 @@ impl DataDeviceHandler for WaylandState {
|
||||
_qh: &wayland_client::QueueHandle<Self>,
|
||||
_data_device: DataDevice,
|
||||
) {
|
||||
todo!()
|
||||
let pointer = self.pointer.as_mut().unwrap();
|
||||
let mut pstate = pointer
|
||||
.pointer()
|
||||
.data::<PointerUserData>()
|
||||
.unwrap()
|
||||
.state
|
||||
.lock()
|
||||
.unwrap();
|
||||
if let Some(SurfaceAndOffer { offer, .. }) = pstate.drag_and_drop.offer.take() {
|
||||
offer.destroy();
|
||||
}
|
||||
}
|
||||
|
||||
fn motion(
|
||||
@ -39,7 +86,6 @@ impl DataDeviceHandler for WaylandState {
|
||||
_qh: &wayland_client::QueueHandle<Self>,
|
||||
_data_device: DataDevice,
|
||||
) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn selection(
|
||||
@ -48,6 +94,7 @@ impl DataDeviceHandler for WaylandState {
|
||||
_qh: &wayland_client::QueueHandle<Self>,
|
||||
data_device: DataDevice,
|
||||
) {
|
||||
// TODO: handle mime types
|
||||
if let Some(offer) = data_device.selection_offer() {
|
||||
if let Some(copy_and_paste) = self.resolve_copy_and_paste() {
|
||||
copy_and_paste
|
||||
@ -64,7 +111,23 @@ impl DataDeviceHandler for WaylandState {
|
||||
_qh: &wayland_client::QueueHandle<Self>,
|
||||
_data_device: DataDevice,
|
||||
) {
|
||||
todo!()
|
||||
let pointer = self.pointer.as_mut().unwrap();
|
||||
let mut pstate = pointer
|
||||
.pointer()
|
||||
.data::<PointerUserData>()
|
||||
.unwrap()
|
||||
.state
|
||||
.lock()
|
||||
.unwrap();
|
||||
let drag_and_drop = &mut pstate.drag_and_drop;
|
||||
if let Some(SurfaceAndPipe { window_id, read }) = drag_and_drop.create_pipe_for_drop() {
|
||||
std::thread::spawn(move || {
|
||||
if let Some(paths) = DragAndDrop::read_paths_from_pipe(read) {
|
||||
DragAndDrop::dispatch_dropped_files(window_id, paths);
|
||||
}
|
||||
});
|
||||
}
|
||||
// if let Some(SurfaceAndOffer { offer, .. }) = pstate.drag_and_drop.offer.take() {
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,46 +1,45 @@
|
||||
use crate::connection::ConnectionOps;
|
||||
use crate::wayland::{read_pipe_with_timeout, WaylandConnection};
|
||||
use crate::wayland::read_pipe_with_timeout;
|
||||
use crate::ConnectionOps;
|
||||
use filedescriptor::{FileDescriptor, Pipe};
|
||||
use smithay_client_toolkit as toolkit;
|
||||
use std::os::unix::io::AsRawFd;
|
||||
use std::path::PathBuf;
|
||||
use toolkit::reexports::client::protocol::wl_data_device::Event as DataDeviceEvent;
|
||||
use toolkit::reexports::client::protocol::wl_data_offer::WlDataOffer;
|
||||
use url::Url;
|
||||
use wayland_client::protocol::wl_data_device_manager::DndAction;
|
||||
|
||||
use super::data_device::URI_MIME_TYPE;
|
||||
use super::WaylandConnection;
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct DragAndDrop {
|
||||
offer: Option<SurfaceAndOffer>,
|
||||
pub(super) offer: Option<SurfaceAndOffer>,
|
||||
}
|
||||
|
||||
struct SurfaceAndOffer {
|
||||
surface_id: u32,
|
||||
offer: WlDataOffer,
|
||||
pub(super) struct SurfaceAndOffer {
|
||||
pub(super) window_id: usize,
|
||||
pub(super) offer: WlDataOffer,
|
||||
}
|
||||
|
||||
struct SurfaceAndPipe {
|
||||
surface_id: u32,
|
||||
read: FileDescriptor,
|
||||
pub(super) struct SurfaceAndPipe {
|
||||
pub(super) window_id: usize,
|
||||
pub(super) read: FileDescriptor,
|
||||
}
|
||||
|
||||
pub const URI_MIME_TYPE: &str = "text/uri-list";
|
||||
|
||||
impl DragAndDrop {
|
||||
/// Takes the current offer, if any, and initiates a receive into a pipe,
|
||||
/// returning that surface and pipe descriptor.
|
||||
fn create_pipe_for_drop(&mut self) -> Option<SurfaceAndPipe> {
|
||||
let SurfaceAndOffer { surface_id, offer } = self.offer.take()?;
|
||||
pub(super) fn create_pipe_for_drop(&mut self) -> Option<SurfaceAndPipe> {
|
||||
let SurfaceAndOffer { window_id, offer } = self.offer.take()?;
|
||||
let pipe = Pipe::new()
|
||||
.map_err(|err| log::error!("Unable to create pipe: {:#}", err))
|
||||
.ok()?;
|
||||
offer.receive(URI_MIME_TYPE.to_string(), pipe.write.as_raw_fd());
|
||||
let read = pipe.read;
|
||||
offer.finish();
|
||||
Some(SurfaceAndPipe { surface_id, read })
|
||||
Some(SurfaceAndPipe { window_id, read })
|
||||
}
|
||||
|
||||
fn read_paths_from_pipe(read: FileDescriptor) -> Option<Vec<PathBuf>> {
|
||||
pub(super) fn read_paths_from_pipe(read: FileDescriptor) -> Option<Vec<PathBuf>> {
|
||||
read_pipe_with_timeout(read)
|
||||
.map_err(|err| {
|
||||
log::error!("Error while reading pipe from drop result: {:#}", err);
|
||||
@ -68,52 +67,14 @@ impl DragAndDrop {
|
||||
.into()
|
||||
}
|
||||
|
||||
fn dispatch_dropped_files(surface_id: u32, paths: Vec<PathBuf>) {
|
||||
pub(super) fn dispatch_dropped_files(window_id: usize, paths: Vec<PathBuf>) {
|
||||
promise::spawn::spawn_into_main_thread(async move {
|
||||
let conn = WaylandConnection::get().unwrap().wayland();
|
||||
if let Some(&window_id) = conn.surface_to_window_id.borrow().get(&surface_id) {
|
||||
if let Some(handle) = conn.window_by_id(window_id) {
|
||||
let mut inner = handle.borrow_mut();
|
||||
inner.dispatch_dropped_files(paths);
|
||||
}
|
||||
};
|
||||
if let Some(handle) = conn.window_by_id(window_id) {
|
||||
let mut inner = handle.borrow_mut();
|
||||
inner.dispatch_dropped_files(paths);
|
||||
}
|
||||
})
|
||||
.detach();
|
||||
}
|
||||
|
||||
pub fn handle_data_event(&mut self, event: DataDeviceEvent) {
|
||||
match event {
|
||||
DataDeviceEvent::Enter {
|
||||
serial,
|
||||
surface,
|
||||
id,
|
||||
..
|
||||
} => {
|
||||
if let Some(offer) = id {
|
||||
offer.accept(serial, Some(URI_MIME_TYPE.to_string()));
|
||||
offer.set_actions(DndAction::None | DndAction::Copy, DndAction::None);
|
||||
self.offer = Some(SurfaceAndOffer {
|
||||
surface_id: surface.as_ref().id(),
|
||||
offer,
|
||||
});
|
||||
}
|
||||
}
|
||||
DataDeviceEvent::Leave => {
|
||||
if let Some(SurfaceAndOffer { offer, .. }) = self.offer.take() {
|
||||
offer.destroy();
|
||||
}
|
||||
}
|
||||
DataDeviceEvent::Motion { .. } => {}
|
||||
DataDeviceEvent::Drop => {
|
||||
if let Some(SurfaceAndPipe { surface_id, read }) = self.create_pipe_for_drop() {
|
||||
std::thread::spawn(move || {
|
||||
if let Some(paths) = Self::read_paths_from_pipe(read) {
|
||||
Self::dispatch_dropped_files(surface_id, paths);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -8,7 +8,7 @@ pub use self::window::*;
|
||||
pub use connection::*;
|
||||
// pub use output::*;
|
||||
mod copy_and_paste;
|
||||
// mod drag_and_drop;
|
||||
mod drag_and_drop;
|
||||
// mod frame;
|
||||
mod data_device;
|
||||
mod keyboard;
|
||||
|
@ -11,6 +11,7 @@ use wayland_client::{Connection, Proxy, QueueHandle};
|
||||
use wezterm_input_types::MousePress;
|
||||
|
||||
use super::copy_and_paste::CopyAndPaste;
|
||||
use super::drag_and_drop::DragAndDrop;
|
||||
use super::state::WaylandState;
|
||||
use super::WaylandConnection;
|
||||
|
||||
@ -55,10 +56,9 @@ impl PointerHandler for WaylandState {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub(super) struct PointerUserData {
|
||||
pdata: PointerData,
|
||||
state: Mutex<PointerState>,
|
||||
pub(super) state: Mutex<PointerState>,
|
||||
}
|
||||
|
||||
impl PointerUserData {
|
||||
@ -70,10 +70,10 @@ impl PointerUserData {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
struct PointerState {
|
||||
#[derive(Default)]
|
||||
pub(super) struct PointerState {
|
||||
active_surface_id: Option<ObjectId>,
|
||||
// TODO: drag_and_drop: DragAndDrop,
|
||||
pub(super) drag_and_drop: DragAndDrop,
|
||||
serial: u32,
|
||||
}
|
||||
|
||||
|
@ -3,6 +3,7 @@ use std::cell::{RefCell, RefMut};
|
||||
use std::convert::TryInto;
|
||||
use std::io::Read;
|
||||
use std::os::fd::AsRawFd;
|
||||
use std::path::PathBuf;
|
||||
use std::rc::Rc;
|
||||
use std::sync::{Arc, Mutex};
|
||||
use std::time::{Duration, Instant};
|
||||
@ -577,6 +578,10 @@ impl WaylandWindowInner {
|
||||
((pixels as f64) / self.get_dpi_factor()).ceil() as i32
|
||||
}
|
||||
|
||||
pub(super) fn dispatch_dropped_files(&mut self, paths: Vec<PathBuf>) {
|
||||
self.events.dispatch(WindowEvent::DroppedFile(paths));
|
||||
}
|
||||
|
||||
pub(crate) fn dispatch_pending_mouse(&mut self) {
|
||||
let pending_mouse = Arc::clone(&self.pending_mouse);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user