1
0
Эх сурвалжийг харах

Merge pull request #180 from mrxiaozhuox/borderless-frame

Add support for desktop context, borderless frames, minimize, maximize, and other window-related goodies through the imperative `use_window` hook.
Jonathan Kelley 3 жил өмнө
parent
commit
0c0f638c47

+ 1 - 0
.gitignore

@@ -1,4 +1,5 @@
 /target
+/dist
 Cargo.lock
 .DS_Store
 

+ 38 - 0
examples/borderless.rs

@@ -0,0 +1,38 @@
+use dioxus::prelude::*;
+
+fn main() {
+    dioxus::desktop::launch_cfg(app, |cfg| {
+        cfg.with_window(|w| w.with_title("BorderLess Demo").with_decorations(false))
+    });
+}
+
+fn app(cx: Scope) -> Element {
+    let window = dioxus::desktop::use_window(&cx);
+
+    cx.render(rsx!(
+        link { href:"https://unpkg.com/tailwindcss@^2/dist/tailwind.min.css", rel:"stylesheet" }
+        header {
+            class: "text-gray-400 bg-gray-900 body-font",
+            onmousedown: move |_| window.drag(),
+            div {
+                class: "container mx-auto flex flex-wrap p-5 flex-col md:flex-row items-center",
+                a { class: "flex title-font font-medium items-center text-white mb-4 md:mb-0",
+                    span { class: "ml-3 text-xl", "Dioxus"}
+                }
+                nav { class: "md:ml-auto flex flex-wrap items-center text-base justify-center" }
+                button {
+                    class: "inline-flex items-center bg-gray-800 border-0 py-1 px-3 focus:outline-none hover:bg-gray-700 rounded text-base mt-4 md:mt-0",
+                    onmousedown: |evt| evt.cancel_bubble(),
+                    onclick: move |_| window.minimize(true),
+                    "Minimize"
+                }
+                button {
+                    class: "inline-flex items-center bg-gray-800 border-0 py-1 px-3 focus:outline-none hover:bg-gray-700 rounded text-base mt-4 md:mt-0",
+                    onmousedown: |evt| evt.cancel_bubble(),
+                    onclick: move |_| window.close(),
+                    "Close"
+                }
+            }
+        }
+    ))
+}

+ 52 - 85
packages/desktop/src/desktop_context.rs

@@ -1,100 +1,67 @@
-use std::cell::RefCell;
+use std::rc::Rc;
 
-use dioxus::prelude::Scope;
-use dioxus_core as dioxus;
-use dioxus_core::{Context, Element, LazyNodes, NodeFactory, Properties};
-use dioxus_core_macro::Props;
+use dioxus_core::ScopeState;
+use wry::application::event_loop::EventLoopProxy;
 
-/*
-This module provides a set of Dioxus components to easily manage windows, tabs, etc.
+use crate::UserWindowEvent;
 
-Windows can be created anywhere in the tree, making them very flexible for things like modals, etc.
+type ProxyType = EventLoopProxy<UserWindowEvent>;
 
-*/
-pub struct DesktopContext {}
-
-impl DesktopContext {
-    fn add_window(&mut self) {
-        //
-    }
-    fn close_window(&mut self) {
-        //
-    }
-}
-
-enum WindowHandlers {
-    Resized(Box<dyn Fn()>),
-    Moved(Box<dyn Fn()>),
-    CloseRequested(Box<dyn Fn()>),
-    Destroyed(Box<dyn Fn()>),
-    DroppedFile(Box<dyn Fn()>),
-    HoveredFile(Box<dyn Fn()>),
-    HoverFileCancelled(Box<dyn Fn()>),
-    ReceivedTimeText(Box<dyn Fn()>),
-    Focused(Box<dyn Fn()>),
-}
-
-#[derive(Props)]
-pub struct WebviewWindowProps<'a> {
-    onclose: &'a dyn FnMut(()),
-
-    onopen: &'a dyn FnMut(()),
-
-    /// focuse me
-    onfocused: &'a dyn FnMut(()),
-
-    children: Element,
-}
-
-/// A handle to a
-///
-///
-///
+/// Desktop-Window handle api context
 ///
+/// you can use this context control some window event
 ///
+/// you can use `cx.consume_context::<DesktopContext>` to get this context
 ///
-///
-///
-///
-pub fn WebviewWindow(cx: Scope<WebviewWindowProps>) -> Element {
-    let dtcx = cx.consume_state::<RefCell<DesktopContext>>()?;
-
-    cx.use_hook(|_| {});
-
-    // render the children directly
-    todo!()
-    // cx.render(LazyNodes::new(move |f: NodeFactory| {
-    //     f.fragment_from_iter(cx.children())
-    // }))
+/// ```rust
+///     let desktop = cx.consume_context::<DesktopContext>().unwrap();
+/// ```
+#[derive(Clone)]
+pub struct DesktopContext {
+    proxy: ProxyType,
 }
 
-pub struct WindowHandle {}
+impl DesktopContext {
+    pub(crate) fn new(proxy: ProxyType) -> Self {
+        Self { proxy }
+    }
 
-/// Get a handle to the current window from inside a component
-pub fn use_current_window(cx: Scope) -> Option<WindowHandle> {
-    todo!()
-}
+    /// trigger the drag-window event
+    ///
+    /// Moves the window with the left mouse button until the button is released.
+    ///
+    /// you need use it in `onmousedown` event:
+    /// ```rust
+    /// onmousedown: move |_| { desktop.drag_window(); }
+    /// ```
+    pub fn drag(&self) {
+        let _ = self.proxy.send_event(UserWindowEvent::DragWindow);
+    }
 
-#[test]
-fn syntax_works() {
-    use dioxus_core as dioxus;
-    use dioxus_core::prelude::*;
-    use dioxus_core_macro::*;
-    use dioxus_hooks::*;
-    use dioxus_html as dioxus_elements;
+    /// set window minimize state
+    pub fn minimize(&self, minimized: bool) {
+        let _ = self.proxy.send_event(UserWindowEvent::Minimize(minimized));
+    }
 
-    static App: Component = |cx| {
-        cx.render(rsx! {
-            // left window
-            WebviewWindow {
-                onclose: move |evt| {}
-                onopen: move |evt| {}
-                onfocused: move |evt| {}
+    /// set window maximize state
+    pub fn maximize(&self, maximized: bool) {
+        let _ = self.proxy.send_event(UserWindowEvent::Maximize(maximized));
+    }
 
-                div {
+    /// close window
+    pub fn close(&self) {
+        let _ = self.proxy.send_event(UserWindowEvent::CloseWindow);
+    }
+
+    /// set window to focus
+    pub fn focus(&self) {
+        let _ = self.proxy.send_event(UserWindowEvent::FocusWindow);
+    }
+}
 
-                }
-            }
-        })
-    };
+/// use this function can get the `DesktopContext` context.
+pub fn use_window(cx: &ScopeState) -> &Rc<DesktopContext> {
+    cx.use_hook(|_| cx.consume_context::<DesktopContext>())
+        .as_ref()
+        .unwrap()
 }

+ 48 - 0
packages/desktop/src/lib.rs

@@ -51,10 +51,13 @@
 //! Make sure to read the [Dioxus Guide](https://dioxuslabs.com/guide) if you already haven't!
 
 pub mod cfg;
+pub mod desktop_context;
 pub mod escape;
 pub mod events;
 
 use cfg::DesktopConfig;
+pub use desktop_context::use_window;
+use desktop_context::DesktopContext;
 use dioxus_core::*;
 use std::{
     collections::{HashMap, VecDeque},
@@ -283,6 +286,41 @@ pub fn launch_with_props<P: 'static + Send>(
                 //
                 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.
+                            let _ = window.drag_window();
+                        }
+                    }
+                    UserWindowEvent::CloseWindow => {
+                        // close window
+                        *control_flow = ControlFlow::Exit;
+                    }
+                    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::FocusWindow => {
+                        for webview in desktop.webviews.values() {
+                            let window = webview.window();
+                            window.set_focus();
+                        }
+                    }
                 }
             }
             Event::MainEventsCleared => {}
@@ -297,6 +335,11 @@ pub fn launch_with_props<P: 'static + Send>(
 
 pub enum UserWindowEvent {
     Update,
+    DragWindow,
+    CloseWindow,
+    FocusWindow,
+    Minimize(bool),
+    Maximize(bool),
 }
 
 pub struct DesktopController {
@@ -323,6 +366,7 @@ impl DesktopController {
         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()
@@ -334,6 +378,10 @@ impl DesktopController {
                 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