Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add WindowProxy to file drop handler closure #140

Merged
merged 8 commits into from
Apr 2, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changes/window-file-drop-handler.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"wry": minor
---

Adds a `WindowProxy` to the file drop handler closure - `WindowFileDropHandler`.
2 changes: 1 addition & 1 deletion examples/dragndrop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ fn main() -> Result<()> {
},
None,
None,
Some(Box::new(|data| {
Some(Box::new(|_, data| {
println!("Window 1: {:?}", data);
false // Returning true will block the OS default behaviour.
})),
Expand Down
30 changes: 21 additions & 9 deletions src/application/general.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
use crate::{
application::{App, AppProxy, InnerWebViewAttributes, InnerWindowAttributes},
ApplicationProxy, Attributes, CustomProtocol, Error, Event as WryEvent, Icon, Message, Result,
WebView, WebViewBuilder, WindowEvent as WryWindowEvent, WindowMessage, WindowProxy,
WindowRpcHandler,
WebView, WebViewBuilder, WindowEvent as WryWindowEvent, WindowFileDropHandler, WindowMessage,
WindowProxy, WindowRpcHandler,
};

#[cfg(target_os = "windows")]
Expand Down Expand Up @@ -46,8 +46,6 @@ use {
winit::platform::windows::WindowExtWindows,
};

use crate::FileDropHandler;

type EventLoopProxy = winit::event_loop::EventLoopProxy<Message>;

#[derive(Clone)]
Expand All @@ -68,7 +66,7 @@ impl AppProxy for InnerApplicationProxy {
fn add_window(
&self,
attributes: Attributes,
file_drop_handler: Option<FileDropHandler>,
file_drop_handler: Option<WindowFileDropHandler>,
rpc_handler: Option<WindowRpcHandler>,
custom_protocol: Option<CustomProtocol>,
) -> Result<WindowId> {
Expand Down Expand Up @@ -150,7 +148,7 @@ impl App for InnerApplication {
fn create_webview(
&mut self,
attributes: Attributes,
file_drop_handler: Option<FileDropHandler>,
file_drop_handler: Option<WindowFileDropHandler>,
rpc_handler: Option<WindowRpcHandler>,
custom_protocol: Option<CustomProtocol>,
) -> Result<Self::Id> {
Expand Down Expand Up @@ -407,7 +405,7 @@ fn _create_webview(
window: Window,
custom_protocol: Option<CustomProtocol>,
rpc_handler: Option<WindowRpcHandler>,
file_drop_handler: Option<FileDropHandler>,
file_drop_handler: Option<WindowFileDropHandler>,

attributes: InnerWebViewAttributes,
) -> Result<WebView> {
Expand All @@ -425,10 +423,11 @@ fn _create_webview(
webview = webview.register_protocol(protocol.name, protocol.handler)
}

let proxy_ = proxy.clone();
webview = webview.set_rpc_handler(Box::new(move |mut request| {
let proxy = WindowProxy::new(
ApplicationProxy {
inner: proxy.clone(),
inner: proxy_.clone(),
},
window_id,
);
Expand All @@ -448,7 +447,20 @@ fn _create_webview(
}
}));

webview = webview.set_file_drop_handler(file_drop_handler);
webview = webview.set_file_drop_handler(Some(Box::new(move |event| {
let proxy = WindowProxy::new(
ApplicationProxy {
inner: proxy.clone(),
},
window_id,
);

if let Some(file_drop_handler) = &file_drop_handler {
file_drop_handler(proxy, event)
} else {
false
}
})));

webview = match attributes.url {
Some(url) => webview.load_url(&url)?,
Expand Down
28 changes: 21 additions & 7 deletions src/application/gtkrs.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::{
application::{App, AppProxy, InnerWebViewAttributes, InnerWindowAttributes},
ApplicationProxy, Attributes, CustomProtocol, Error, Event as WryEvent, FileDropHandler, Icon,
Message, Result, WebView, WebViewBuilder, WindowEvent as WryWindowEvent, WindowMessage,
ApplicationProxy, Attributes, CustomProtocol, Error, Event as WryEvent, Icon, Message, Result,
WebView, WebViewBuilder, WindowEvent as WryWindowEvent, WindowFileDropHandler, WindowMessage,
WindowProxy, WindowRpcHandler,
};

Expand Down Expand Up @@ -51,7 +51,7 @@ impl AppProxy for InnerApplicationProxy {
fn add_window(
&self,
attributes: Attributes,
file_drop_handler: Option<FileDropHandler>,
file_drop_handler: Option<WindowFileDropHandler>,
rpc_handler: Option<WindowRpcHandler>,
custom_protocol: Option<CustomProtocol>,
) -> Result<WindowId> {
Expand Down Expand Up @@ -104,7 +104,7 @@ impl App for InnerApplication {
fn create_webview(
&mut self,
attributes: Attributes,
file_drop_handler: Option<FileDropHandler>,
file_drop_handler: Option<WindowFileDropHandler>,
rpc_handler: Option<WindowRpcHandler>,
custom_protocol: Option<CustomProtocol>,
) -> Result<Self::Id> {
Expand Down Expand Up @@ -452,7 +452,7 @@ fn _create_webview(
window: ApplicationWindow,
custom_protocol: Option<CustomProtocol>,
rpc_handler: Option<WindowRpcHandler>,
file_drop_handler: Option<FileDropHandler>,
file_drop_handler: Option<WindowFileDropHandler>,

attributes: InnerWebViewAttributes,
) -> Result<WebView> {
Expand All @@ -470,10 +470,11 @@ fn _create_webview(
webview = webview.register_protocol(protocol.name, protocol.handler);
}

let proxy_ = proxy.clone();
webview = webview.set_rpc_handler(Box::new(move |mut request| {
let proxy = WindowProxy::new(
ApplicationProxy {
inner: proxy.clone(),
inner: proxy_.clone(),
},
window_id,
);
Expand All @@ -493,7 +494,20 @@ fn _create_webview(
}
}));

webview = webview.set_file_drop_handler(file_drop_handler);
webview = webview.set_file_drop_handler(Some(Box::new(move |event| {
let proxy = WindowProxy::new(
ApplicationProxy {
inner: proxy.clone(),
},
window_id,
);

if let Some(file_drop_handler) = &file_drop_handler {
file_drop_handler(proxy, event)
} else {
false
}
})));

let webview = webview.build()?;
Ok(webview)
Expand Down
12 changes: 6 additions & 6 deletions src/application/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ mod attributes;
pub use attributes::{Attributes, CustomProtocol, Icon, WindowRpcHandler};
pub(crate) use attributes::{InnerWebViewAttributes, InnerWindowAttributes};

use crate::{FileDropHandler, Result};
use crate::{Result, WindowFileDropHandler};

use std::sync::mpsc::Sender;

Expand Down Expand Up @@ -64,7 +64,7 @@ pub enum Message {
NewWindow(
Attributes,
Sender<WindowId>,
Option<FileDropHandler>,
Option<WindowFileDropHandler>,
Option<WindowRpcHandler>,
Option<CustomProtocol>,
),
Expand Down Expand Up @@ -97,7 +97,7 @@ impl ApplicationProxy {
attributes: Attributes,
rpc_handler: Option<WindowRpcHandler>,
custom_protocol: Option<CustomProtocol>,
file_drop_handler: Option<FileDropHandler>,
file_drop_handler: Option<WindowFileDropHandler>,
) -> Result<WindowProxy> {
let id = self
.inner
Expand All @@ -116,7 +116,7 @@ trait AppProxy {
fn add_window(
&self,
attributes: Attributes,
file_drop_handler: Option<FileDropHandler>,
file_drop_handler: Option<WindowFileDropHandler>,
rpc_handler: Option<WindowRpcHandler>,
custom_protocol: Option<CustomProtocol>,
) -> Result<WindowId>;
Expand Down Expand Up @@ -353,7 +353,7 @@ impl Application {
attributes: Attributes,
rpc_handler: Option<WindowRpcHandler>,
custom_protocol: Option<CustomProtocol>,
file_drop_handler: Option<FileDropHandler>,
file_drop_handler: Option<WindowFileDropHandler>,
) -> Result<WindowProxy> {
let id =
self
Expand Down Expand Up @@ -392,7 +392,7 @@ trait App: Sized {
fn create_webview(
&mut self,
attributes: Attributes,
file_drop_handler: Option<FileDropHandler>,
file_drop_handler: Option<WindowFileDropHandler>,
rpc_handler: Option<WindowRpcHandler>,
custom_protocol: Option<CustomProtocol>,
) -> Result<Self::Id>;
Expand Down
30 changes: 28 additions & 2 deletions src/file_drop.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
use std::path::PathBuf;

use crate::WindowProxy;

/// An event enumeration sent to [`FileDropHandler`].
#[derive(Debug, Serialize, Clone)]
pub enum FileDropEvent {
Expand All @@ -11,11 +13,35 @@ pub enum FileDropEvent {
Cancelled,
}

/// A listener closure to process incoming [`FileDropEvent`] of the window.
/// A listener closure to process incoming [`FileDropEvent`] of the webview.
///
/// Users can pass a [`WindowFileDropHandler`] to [`Application::add_window_with_configs`](crate::Application::add_window_with_configs)
/// to register incoming file drop events to a closure.
///
/// # Blocking OS Default Behavior
/// Return `true` in the callback to block the OS' default behavior of handling a file drop.
///
/// Note, that if you do block this behavior, it won't be possible to drop files on `<input type="file">` forms.
/// Also note, that it's not possible to manually set the value of a `<input type="file">` via JavaScript for security reasons.
pub type FileDropHandler = Box<dyn Fn(FileDropEvent) -> bool + Send>;
///
/// # Example
///
/// ```no_run
/// use wry::{Application, Result, WindowProxy, FileDropEvent};
///
/// fn main() -> Result<()> {
/// let mut app = Application::new()?;
/// let file_drop = Box::new(|window: WindowProxy, event: FileDropEvent| {
/// // Use the `WindowProxy` to modify the window, eg: `set_fullscreen` etc.
/// //
/// // Use the `FileDropEvent` to see the current state of the file drop.
/// //
/// // Return `true` to block the default file drop behavior of the OS.
/// false
/// });
/// app.add_window_with_configs(Default::default(), None, None, Some(file_drop))?;
/// app.run();
/// Ok(())
/// }
/// ```
pub type WindowFileDropHandler = Box<dyn Fn(WindowProxy, FileDropEvent) -> bool + Send>;
33 changes: 17 additions & 16 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,34 +70,35 @@ extern crate thiserror;
#[macro_use]
extern crate objc;

mod file_drop;
#[cfg(feature = "file-drop")]
pub use file_drop::{FileDropEvent, FileDropHandler};
#[cfg(not(feature = "file-drop"))]
pub(crate) use file_drop::{FileDropEvent, FileDropHandler};
use std::sync::mpsc::{RecvError, SendError};

pub use serde_json::Value;
use url::ParseError;
#[cfg(not(target_os = "linux"))]
use winit::window::BadIcon;

#[cfg(feature = "protocol")]
pub use application::CustomProtocol;
#[cfg(not(feature = "protocol"))]
pub(crate) use application::CustomProtocol;

mod application;
pub mod webview;

pub use application::{
Application, ApplicationProxy, Attributes, Event, Icon, Message, WindowEvent, WindowId,
WindowMessage, WindowProxy, WindowRpcHandler,
};
pub use serde_json::Value;
#[cfg(not(feature = "file-drop"))]
pub(crate) use file_drop::FileDropEvent;
#[cfg(feature = "file-drop")]
pub use file_drop::{FileDropEvent, WindowFileDropHandler};
#[cfg(not(feature = "file-drop"))]
pub(crate) use webview::FileDropHandler;
#[cfg(feature = "file-drop")]
pub use webview::FileDropHandler;
pub(crate) use webview::{RpcHandler, WebView, WebViewBuilder};
pub use webview::{RpcRequest, RpcResponse};

#[cfg(not(target_os = "linux"))]
use winit::window::BadIcon;

use std::sync::mpsc::{RecvError, SendError};

use url::ParseError;
mod application;
mod file_drop;
pub mod webview;

/// Convenient type alias of Result type for wry.
pub type Result<T> = std::result::Result<T, Error>;
Expand Down
4 changes: 2 additions & 2 deletions src/webview/linux/file_drop.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
use crate::{FileDropEvent, FileDropHandler};

use std::{cell::Cell, path::PathBuf, rc::Rc};

use gtk::WidgetExt;
use webkit2gtk::WebView;

use crate::{webview::FileDropHandler, FileDropEvent};

pub(crate) fn connect_drag_event(webview: Rc<WebView>, handler: FileDropHandler) {
let listener = Rc::new((handler, Cell::new(None)));

Expand Down
14 changes: 7 additions & 7 deletions src/webview/linux/mod.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,3 @@
mod file_drop;

use crate::{
webview::{mimetype::MimeType, WV},
Error, FileDropHandler, Result, RpcHandler,
};

use std::{path::PathBuf, rc::Rc};

use gdk::RGBA;
Expand All @@ -18,6 +11,13 @@ use webkit2gtk::{
WebContextExt, WebView, WebViewExt, WebViewExtManual,
};

use crate::{
webview::{mimetype::MimeType, FileDropHandler, WV},
Error, Result, RpcHandler,
};

mod file_drop;

pub struct InnerWebView {
webview: Rc<WebView>,
}
Expand Down
11 changes: 4 additions & 7 deletions src/webview/macos/file_drop.rs
Original file line number Diff line number Diff line change
@@ -1,24 +1,21 @@
use crate::{FileDropEvent, FileDropHandler};

use std::{
ffi::{c_void, CStr},
path::PathBuf,
};

use once_cell::sync::Lazy;

use cocoa::base::{id, BOOL, YES};
use objc::{
declare::ClassDecl,
runtime::{Object, Sel},
runtime::{class_getInstanceMethod, method_getImplementation, Object, Sel},
};
use once_cell::sync::Lazy;

use crate::{webview::FileDropHandler, FileDropEvent};

pub(crate) type NSDragOperation = cocoa::foundation::NSUInteger;
#[allow(non_upper_case_globals)]
const NSDragOperationLink: NSDragOperation = 2;

use objc::runtime::{class_getInstanceMethod, method_getImplementation};

static OBJC_DRAGGING_ENTERED: Lazy<extern "C" fn(*const Object, Sel, id) -> NSDragOperation> =
Lazy::new(|| unsafe {
std::mem::transmute(method_getImplementation(class_getInstanceMethod(
Expand Down
Loading