feat: return window
This commit is contained in:
1 parent
8ce1d8a70a
commit
22e71a71bd
4 files changed
+175
-35
No files matched your search
@@ -1,13 +1,17 @@
|
||||
use std::cell::RefCell;
|
||||
use std::rc::Rc;
|
||||
use std::rc::Weak;
|
||||
|
||||
use crate::create_new_window;
|
||||
use crate::eval::EvalResult;
|
||||
use crate::events::IpcMessage;
|
||||
use crate::Config;
|
||||
use crate::WebviewHandler;
|
||||
use dioxus_core::ScopeState;
|
||||
use dioxus_core::VirtualDom;
|
||||
use serde_json::Value;
|
||||
use wry::application::event_loop::EventLoopProxy;
|
||||
use wry::application::event_loop::EventLoopWindowTarget;
|
||||
#[cfg(target_os = "ios")]
|
||||
use wry::application::platform::ios::WindowExtIOS;
|
||||
use wry::application::window::Fullscreen as WryFullscreen;
|
||||
@@ -24,7 +28,7 @@ pub fn use_window(cx: &ScopeState) -> &DesktopContext {
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
pub type WebviewQueue = Rc<RefCell<Vec<(VirtualDom, crate::cfg::Config)>>>;
|
||||
pub(crate) type WebviewQueue = Rc<RefCell<Vec<WebviewHandler>>>;
|
||||
|
||||
/// An imperative interface to the current window.
|
||||
///
|
||||
@@ -51,6 +55,8 @@ pub struct DesktopContext {
|
||||
|
||||
pub(super) pending_windows: WebviewQueue,
|
||||
|
||||
pub(crate) event_loop: EventLoopWindowTarget<UserWindowEvent>,
|
||||
|
||||
#[cfg(target_os = "ios")]
|
||||
pub(crate) views: Rc<RefCell<Vec<*mut objc::runtime::Object>>>,
|
||||
}
|
||||
@@ -65,10 +71,16 @@ impl std::ops::Deref for DesktopContext {
|
||||
}
|
||||
|
||||
impl DesktopContext {
|
||||
pub(crate) fn new(webview: Rc<WebView>, proxy: ProxyType, webviews: WebviewQueue) -> Self {
|
||||
pub(crate) fn new(
|
||||
webview: Rc<WebView>,
|
||||
proxy: ProxyType,
|
||||
event_loop: EventLoopWindowTarget<UserWindowEvent>,
|
||||
webviews: WebviewQueue,
|
||||
) -> Self {
|
||||
Self {
|
||||
webview,
|
||||
proxy,
|
||||
event_loop,
|
||||
eval: tokio::sync::broadcast::channel(8).0,
|
||||
pending_windows: webviews,
|
||||
#[cfg(target_os = "ios")]
|
||||
@@ -77,11 +89,36 @@ impl DesktopContext {
|
||||
}
|
||||
|
||||
/// Create a new window using the props and window builder
|
||||
pub fn new_window(&self, dom: VirtualDom, cfg: Config) {
|
||||
self.pending_windows.borrow_mut().push((dom, cfg));
|
||||
///
|
||||
/// Returns the webview handle for the new window.
|
||||
///
|
||||
/// You can use this to control other windows from the current window.
|
||||
///
|
||||
/// Be careful to not create a cycle of windows, or you might leak memory.
|
||||
pub fn new_window(&self, dom: VirtualDom, cfg: Config) -> Weak<WebView> {
|
||||
let window = create_new_window(
|
||||
cfg,
|
||||
&self.event_loop,
|
||||
&self.proxy,
|
||||
dom,
|
||||
&self.pending_windows,
|
||||
);
|
||||
|
||||
let id = window.webview.window().id();
|
||||
|
||||
self.proxy
|
||||
.send_event(UserWindowEvent(EventData::NewWindow, self.id()))
|
||||
.send_event(UserWindowEvent(EventData::NewWindow, id))
|
||||
.unwrap();
|
||||
|
||||
self.proxy
|
||||
.send_event(UserWindowEvent(EventData::Poll, id))
|
||||
.unwrap();
|
||||
|
||||
let webview = window.webview.clone();
|
||||
|
||||
self.pending_windows.borrow_mut().push(window);
|
||||
|
||||
Rc::downgrade(&webview)
|
||||
}
|
||||
|
||||
/// trigger the drag-window event
|
||||
@@ -115,6 +152,13 @@ impl DesktopContext {
|
||||
.send_event(UserWindowEvent(EventData::CloseWindow, self.id()));
|
||||
}
|
||||
|
||||
/// close window
|
||||
pub fn close_window(&self, id: WindowId) {
|
||||
let _ = self
|
||||
.proxy
|
||||
.send_event(UserWindowEvent(EventData::CloseWindow, id));
|
||||
}
|
||||
|
||||
/// change window to fullscreen
|
||||
pub fn set_fullscreen(&self, fullscreen: bool) {
|
||||
if let Some(handle) = self.webview.window().current_monitor() {
|
||||
@@ -209,10 +253,10 @@ impl DesktopContext {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct UserWindowEvent(pub EventData, pub WindowId);
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum EventData {
|
||||
Poll,
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Deserialize, Serialize, Debug)]
|
||||
#[derive(Deserialize, Serialize, Debug, Clone)]
|
||||
pub struct IpcMessage {
|
||||
method: String,
|
||||
params: serde_json::Value,
|
||||
|
||||
+41
-27
@@ -17,16 +17,16 @@ mod hot_reload;
|
||||
|
||||
pub use cfg::Config;
|
||||
pub use desktop_context::{use_window, DesktopContext};
|
||||
use desktop_context::{EventData, UserWindowEvent};
|
||||
use desktop_context::{EventData, UserWindowEvent, WebviewQueue};
|
||||
use dioxus_core::*;
|
||||
use dioxus_html::HtmlEvent;
|
||||
pub use eval::{use_eval, EvalResult};
|
||||
use futures_util::{pin_mut, FutureExt};
|
||||
use std::cell::RefCell;
|
||||
use std::collections::HashMap;
|
||||
use std::rc::Rc;
|
||||
use std::task::Waker;
|
||||
pub use tao::dpi::{LogicalSize, PhysicalSize};
|
||||
use tao::event_loop::{EventLoopProxy, EventLoopWindowTarget};
|
||||
pub use tao::window::WindowBuilder;
|
||||
use tao::{
|
||||
event::{Event, StartCause, WindowEvent},
|
||||
@@ -105,8 +105,6 @@ pub fn launch_cfg(root: Component, config_builder: Config) {
|
||||
/// }
|
||||
/// ```
|
||||
pub fn launch_with_props<P: 'static>(root: Component<P>, props: P, cfg: Config) {
|
||||
let mut _dom = VirtualDom::new_with_props(root, props);
|
||||
|
||||
let event_loop = EventLoop::<UserWindowEvent>::with_user_event();
|
||||
|
||||
let proxy = event_loop.create_proxy();
|
||||
@@ -125,9 +123,18 @@ pub fn launch_with_props<P: 'static>(root: Component<P>, props: P, cfg: Config)
|
||||
// Store them in a hashmap so we can remove them when they're closed
|
||||
let mut webviews = HashMap::<WindowId, WebviewHandler>::new();
|
||||
|
||||
let queue = Rc::new(RefCell::new(vec![(_dom, cfg)]));
|
||||
let queue = WebviewQueue::default();
|
||||
|
||||
event_loop.run(move |window_event, event_loop, control_flow| {
|
||||
// By default, we'll create a new window when the app starts
|
||||
queue.borrow_mut().push(create_new_window(
|
||||
cfg,
|
||||
&event_loop,
|
||||
&proxy,
|
||||
VirtualDom::new_with_props(root, props),
|
||||
&queue,
|
||||
));
|
||||
|
||||
event_loop.run(move |window_event, _event_loop, control_flow| {
|
||||
*control_flow = ControlFlow::Wait;
|
||||
|
||||
match window_event {
|
||||
@@ -153,28 +160,9 @@ pub fn launch_with_props<P: 'static>(root: Component<P>, props: P, cfg: Config)
|
||||
|
||||
Event::NewEvents(StartCause::Init)
|
||||
| Event::UserEvent(UserWindowEvent(EventData::NewWindow, _)) => {
|
||||
for (dom, mut cfg) in queue.borrow_mut().drain(..) {
|
||||
let webview = webview::build(&mut cfg, event_loop, proxy.clone());
|
||||
|
||||
dom.base_scope().provide_context(DesktopContext::new(
|
||||
webview.clone(),
|
||||
proxy.clone(),
|
||||
queue.clone(),
|
||||
));
|
||||
|
||||
let id = webview.window().id();
|
||||
|
||||
// We want to poll the virtualdom and the event loop at the same time, so the waker will be connected to both
|
||||
let waker = waker::tao_waker(&proxy, id);
|
||||
|
||||
let handler = WebviewHandler {
|
||||
webview,
|
||||
waker,
|
||||
dom,
|
||||
};
|
||||
|
||||
for handler in queue.borrow_mut().drain(..) {
|
||||
let id = handler.webview.window().id();
|
||||
webviews.insert(id, handler);
|
||||
|
||||
_ = proxy.send_event(UserWindowEvent(EventData::Poll, id));
|
||||
}
|
||||
}
|
||||
@@ -246,6 +234,32 @@ pub fn launch_with_props<P: 'static>(root: Component<P>, props: P, cfg: Config)
|
||||
})
|
||||
}
|
||||
|
||||
fn create_new_window(
|
||||
mut cfg: Config,
|
||||
event_loop: &EventLoopWindowTarget<UserWindowEvent>,
|
||||
proxy: &EventLoopProxy<UserWindowEvent>,
|
||||
dom: VirtualDom,
|
||||
queue: &WebviewQueue,
|
||||
) -> WebviewHandler {
|
||||
let webview = webview::build(&mut cfg, event_loop, proxy.clone());
|
||||
|
||||
dom.base_scope().provide_context(DesktopContext::new(
|
||||
webview.clone(),
|
||||
proxy.clone(),
|
||||
event_loop.clone(),
|
||||
queue.clone(),
|
||||
));
|
||||
|
||||
let id = webview.window().id();
|
||||
|
||||
// We want to poll the virtualdom and the event loop at the same time, so the waker will be connected to both
|
||||
WebviewHandler {
|
||||
webview,
|
||||
dom,
|
||||
waker: waker::tao_waker(proxy, id),
|
||||
}
|
||||
}
|
||||
|
||||
struct WebviewHandler {
|
||||
dom: VirtualDom,
|
||||
webview: Rc<wry::webview::WebView>,
|
||||
|
||||
Reference in new issue
Block a user