Clean up desktop's lib.rs

This commit is contained in:
Christoph Grabo 2022-02-13 19:59:25 +01:00
parent e7a0e5f1d9
commit 2828f45e12
No known key found for this signature in database
GPG key ID: 1FE689DF1A1AEE6C

View file

@ -3,31 +3,28 @@
#![doc(html_favicon_url = "https://avatars.githubusercontent.com/u/79236386")]
pub mod cfg;
mod controller;
pub mod desktop_context;
pub mod escape;
pub mod events;
mod protocol;
mod user_window_events;
use cfg::DesktopConfig;
use controller::DesktopController;
pub use desktop_context::use_window;
use desktop_context::DesktopContext;
use dioxus_core::*;
use std::{
collections::{HashMap, VecDeque},
sync::atomic::AtomicBool,
sync::{Arc, RwLock},
};
use events::parse_ipc_message;
use tao::{
event::{Event, StartCause, WindowEvent},
event_loop::{ControlFlow, EventLoop},
window::{Window, WindowId},
window::Window,
};
pub use wry;
pub use wry::application as tao;
use wry::{
application::{event_loop::EventLoopProxy, window::Fullscreen},
webview::RpcRequest,
webview::{WebView, WebViewBuilder},
};
use wry::webview::WebViewBuilder;
use crate::events::trigger_from_serialized;
/// Launch the WebView and run the event loop.
///
@ -194,114 +191,8 @@ pub fn launch_with_props<P: 'static + Send>(
_ => {}
},
Event::UserEvent(_evt) => {
//
match _evt {
UserWindowEvent::Update => desktop.try_load_ready_webviews(),
UserWindowEvent::DragWindow => {
// this loop just run once, because dioxus-desktop is unsupport multi-window.
for webview in desktop.webviews.values() {
let window = webview.window();
// start to drag the window.
// if the drag_window have any err. we don't do anything.
if window.fullscreen().is_some() {
return;
}
let _ = window.drag_window();
}
}
UserWindowEvent::CloseWindow => {
// close window
*control_flow = ControlFlow::Exit;
}
UserWindowEvent::Visible(state) => {
for webview in desktop.webviews.values() {
let window = webview.window();
window.set_visible(state);
}
}
UserWindowEvent::Minimize(state) => {
// this loop just run once, because dioxus-desktop is unsupport multi-window.
for webview in desktop.webviews.values() {
let window = webview.window();
// change window minimized state.
window.set_minimized(state);
}
}
UserWindowEvent::Maximize(state) => {
// this loop just run once, because dioxus-desktop is unsupport multi-window.
for webview in desktop.webviews.values() {
let window = webview.window();
// change window maximized state.
window.set_maximized(state);
}
}
UserWindowEvent::Fullscreen(state) => {
for webview in desktop.webviews.values() {
let window = webview.window();
let current_monitor = window.current_monitor();
if current_monitor.is_none() {
return;
}
let fullscreen = if state {
Some(Fullscreen::Borderless(current_monitor))
} else {
None
};
window.set_fullscreen(fullscreen);
}
}
UserWindowEvent::FocusWindow => {
for webview in desktop.webviews.values() {
let window = webview.window();
window.set_focus();
}
}
UserWindowEvent::Resizable(state) => {
for webview in desktop.webviews.values() {
let window = webview.window();
window.set_resizable(state);
}
}
UserWindowEvent::AlwaysOnTop(state) => {
for webview in desktop.webviews.values() {
let window = webview.window();
window.set_always_on_top(state);
}
}
UserWindowEvent::CursorVisible(state) => {
for webview in desktop.webviews.values() {
let window = webview.window();
window.set_cursor_visible(state);
}
}
UserWindowEvent::CursorGrab(state) => {
for webview in desktop.webviews.values() {
let window = webview.window();
let _ = window.set_cursor_grab(state);
}
}
UserWindowEvent::SetTitle(content) => {
for webview in desktop.webviews.values() {
let window = webview.window();
window.set_title(&content);
}
}
UserWindowEvent::SetDecorations(state) => {
for webview in desktop.webviews.values() {
let window = webview.window();
window.set_decorations(state);
}
}
}
Event::UserEvent(user_event) => {
user_window_events::handler(user_event, &mut desktop, control_flow)
}
Event::MainEventsCleared => {}
Event::Resumed => {}
@ -312,118 +203,3 @@ pub fn launch_with_props<P: 'static + Send>(
}
})
}
pub enum UserWindowEvent {
Update,
DragWindow,
CloseWindow,
FocusWindow,
Visible(bool),
Minimize(bool),
Maximize(bool),
Resizable(bool),
AlwaysOnTop(bool),
Fullscreen(bool),
CursorVisible(bool),
CursorGrab(bool),
SetTitle(String),
SetDecorations(bool),
}
pub struct DesktopController {
pub proxy: EventLoopProxy<UserWindowEvent>,
pub webviews: HashMap<WindowId, WebView>,
pub sender: futures_channel::mpsc::UnboundedSender<SchedulerMsg>,
pub pending_edits: Arc<RwLock<VecDeque<String>>>,
pub quit_app_on_close: bool,
pub is_ready: Arc<AtomicBool>,
}
impl DesktopController {
// Launch the virtualdom on its own thread managed by tokio
// returns the desktop state
pub fn new_on_tokio<P: Send + 'static>(
root: Component<P>,
props: P,
evt: EventLoopProxy<UserWindowEvent>,
) -> Self {
let edit_queue = Arc::new(RwLock::new(VecDeque::new()));
let pending_edits = edit_queue.clone();
let (sender, receiver) = futures_channel::mpsc::unbounded::<SchedulerMsg>();
let return_sender = sender.clone();
let proxy = evt.clone();
let desktop_context_proxy = proxy.clone();
std::thread::spawn(move || {
// We create the runtime as multithreaded, so you can still "spawn" onto multiple threads
let runtime = tokio::runtime::Builder::new_multi_thread()
.enable_all()
.build()
.unwrap();
runtime.block_on(async move {
let mut dom =
VirtualDom::new_with_props_and_scheduler(root, props, (sender, receiver));
let window_context = DesktopContext::new(desktop_context_proxy);
dom.base_scope().provide_context(window_context);
let edits = dom.rebuild();
edit_queue
.write()
.unwrap()
.push_front(serde_json::to_string(&edits.edits).unwrap());
loop {
dom.wait_for_work().await;
let mut muts = dom.work_with_deadline(|| false);
while let Some(edit) = muts.pop() {
edit_queue
.write()
.unwrap()
.push_front(serde_json::to_string(&edit.edits).unwrap());
}
let _ = evt.send_event(UserWindowEvent::Update);
}
})
});
Self {
pending_edits,
sender: return_sender,
proxy,
webviews: HashMap::new(),
is_ready: Arc::new(AtomicBool::new(false)),
quit_app_on_close: true,
}
}
pub fn close_window(&mut self, window_id: WindowId, control_flow: &mut ControlFlow) {
self.webviews.remove(&window_id);
if self.webviews.is_empty() && self.quit_app_on_close {
*control_flow = ControlFlow::Exit;
}
}
pub fn try_load_ready_webviews(&mut self) {
if self.is_ready.load(std::sync::atomic::Ordering::Relaxed) {
let mut queue = self.pending_edits.write().unwrap();
let (_id, view) = self.webviews.iter_mut().next().unwrap();
while let Some(edit) = queue.pop_back() {
view.evaluate_script(&format!("window.interpreter.handleEdits({})", edit))
.unwrap();
}
} else {
println!("waiting for ready");
}
}
}