From f5cecd70d6aa297dae081a41dca4e8f60f57f737 Mon Sep 17 00:00:00 2001 From: Jonathan Kelley Date: Thu, 20 Jun 2024 16:18:26 -0700 Subject: [PATCH] Fix cross-platform mudabar, wire up better CI (#75) * fix cross-platform winit with muda bar fixes also wire up better CI * Follow up for `winit` backend and CI (#77) * Fix menu on windows * Refactor menu initialization * Fix missing gtk in CI * Create CONTRIBUTING.MD * Add info text --------- Co-authored-by: Matt Hunzinger --- .github/workflows/ci.yml | 80 ++++++++++++++++++++++++++++- .gitignore | 3 +- CONTRIBUTING.MD | 43 ++++++++++++++++ packages/dioxus-blitz/Cargo.toml | 2 +- packages/dioxus-blitz/src/lib.rs | 5 +- packages/dioxus-blitz/src/window.rs | 78 +++++++++++++--------------- 6 files changed, 166 insertions(+), 45 deletions(-) create mode 100644 CONTRIBUTING.MD diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e5196cb7..ccec2385 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,10 +1,14 @@ +name: CI + on: pull_request: push: branches: - main -name: CI +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true env: RUSTDOCFLAGS: "-D warnings" @@ -69,3 +73,77 @@ jobs: - uses: actions/checkout@v4 - uses: dtolnay/rust-toolchain@stable - run: cargo doc + + # just cargo check for now + matrix_test: + runs-on: ${{ matrix.platform.os }} + if: github.event.pull_request.draft == false + env: + RUST_CARGO_COMMAND: ${{ matrix.platform.cross == true && 'cross' || 'cargo' }} + strategy: + matrix: + platform: + - { + target: x86_64-pc-windows-msvc, + os: windows-latest, + cross: false, + command: "test", + args: "--all --tests", + setup: "" + } + - { + target: x86_64-apple-darwin, + os: macos-latest, + cross: false, + command: "test", + args: "--all --tests", + setup: "" + } + - { + target: x86_64-unknown-linux-gnu, + os: ubuntu-latest, + cross: false, + command: "test", + args: "--all --tests", + setup: "sudo apt-get update; sudo apt-get install --no-install-recommends \ + libasound2-dev \ + libatk1.0-dev \ + libgtk-3-dev \ + libudev-dev \ + libpango1.0-dev \ + libxdo-dev" + } + + steps: + - uses: actions/checkout@v4 + - name: install stable + uses: dtolnay/rust-toolchain@master + with: + toolchain: stable + targets: ${{ matrix.platform.target }} + components: rustfmt + + - name: Install cross + if: ${{ matrix.platform.cross == true }} + uses: taiki-e/install-action@cross + + - name: Free Disk Space (Ubuntu) + if: ${{ matrix.platform.os == 'ubuntu-latest' }} + uses: jlumbroso/free-disk-space@v1.3.1 + with: # speed things up a bit + large-packages: false + docker-images: false + swap-storage: false + + - uses: Swatinem/rust-cache@v2 + with: + key: "${{ matrix.platform.target }}" + cache-all-crates: "true" + save-if: ${{ github.ref == 'refs/heads/main' }} + + - name: Setup + run: ${{ matrix.platform.setup }} + + - name: test + run: | + ${{ env.RUST_CARGO_COMMAND }} ${{ matrix.platform.command }} ${{ matrix.platform.args }} --target ${{ matrix.platform.target }} diff --git a/.gitignore b/.gitignore index 0e74c65c..bd2dfa56 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ /target /Cargo.lock .DS_Store -experiments \ No newline at end of file +experiments +/.vscode diff --git a/CONTRIBUTING.MD b/CONTRIBUTING.MD new file mode 100644 index 00000000..708b13a9 --- /dev/null +++ b/CONTRIBUTING.MD @@ -0,0 +1,43 @@ +# Contributing to Blitz + +Welcome to the Dioxus community! +Blitz is a "native" HTML/CSS renderer built to support the "Dioxus Native" project. It is effectively a lightweight webview except that the JavaScript engine is replaced with a native Rust API which allows Rust reactivity / state management libraries like Dioxus to interface with it directly. + +Talk to us in: the #native channel in the [Dioxus Discord](https://discord.gg/BWTrn6d3) + +## Development + +### Windows +Building Blitz requires Python, which can be installed from the Windows app store. + +### Linux +Requirements: + * asound2 + * atk1.0 + * gtk-3 + * udev + * pango1.0 + * xdo + +For example on Ubuntu you can install these by running: +```sh +sudo apt-get update +sudo apt-get install \ + libasound2-dev \ + libatk1.0-dev \ + libgtk-3-dev \ + libudev-dev \ + libpango1.0-dev \ + libxdo-dev +``` + +### VSCode +You can add the following JSON to your `.vscode/settings.json` to automically build Blitz on all supported targets. +```json +{ + "rust-analyzer.check.features": "all", + "rust-analyzer.cargo.features": "all", + "rust-analyzer.check.allTargets": true, + "rust-analyzer.cargo.allTargets": true +} +``` diff --git a/packages/dioxus-blitz/Cargo.toml b/packages/dioxus-blitz/Cargo.toml index 93702b22..b5d3e342 100644 --- a/packages/dioxus-blitz/Cargo.toml +++ b/packages/dioxus-blitz/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -winit = "0.30.2" +winit = { version = "0.30.2", features = ["rwh_06"] } muda = { version = "0.11.5", features = ["serde"] } tokio = { workspace = true, features = ["full"] } dioxus = { workspace = true } diff --git a/packages/dioxus-blitz/src/lib.rs b/packages/dioxus-blitz/src/lib.rs index 6c922c5c..b661e67b 100644 --- a/packages/dioxus-blitz/src/lib.rs +++ b/packages/dioxus-blitz/src/lib.rs @@ -12,7 +12,7 @@ use documents::DioxusDocument; use muda::{MenuEvent, MenuId}; use std::collections::HashMap; use url::Url; -use winit::event_loop::{EventLoop, EventLoopBuilder}; +use winit::event_loop::EventLoop; use winit::window::WindowId; use winit::{ event::{Event, WindowEvent}, @@ -108,6 +108,9 @@ fn launch_with_window(window: View<'static, Doc>) { #[cfg(not(any(target_os = "android", target_os = "ios")))] let mut initial = true; + // the move to winit wants us to use a struct with a run method instead of the callback approach + // we want to just keep the callback approach for now + #[allow(deprecated)] event_loop .run(move |event, event_loop| { event_loop.set_control_flow(ControlFlow::Wait); diff --git a/packages/dioxus-blitz/src/window.rs b/packages/dioxus-blitz/src/window.rs index 3ee7ab0a..f7fa1448 100644 --- a/packages/dioxus-blitz/src/window.rs +++ b/packages/dioxus-blitz/src/window.rs @@ -1,31 +1,20 @@ use crate::waker::UserWindowEvent; use blitz::{RenderState, Renderer, Viewport}; use blitz_dom::DocumentLike; -use wgpu::rwh::HasWindowHandle; use winit::keyboard::PhysicalKey; -use winit::window::WindowAttributes; +#[allow(unused)] +use wgpu::rwh::HasWindowHandle; + +use muda::{AboutMetadata, Menu, MenuId, MenuItem, PredefinedMenuItem, Submenu}; use std::sync::Arc; use std::task::Waker; use vello::Scene; use winit::dpi::LogicalSize; use winit::event::{ElementState, MouseButton}; use winit::event_loop::{ActiveEventLoop, EventLoopProxy}; -#[cfg(any( - target_os = "linux", - target_os = "dragonfly", - target_os = "freebsd", - target_os = "netbsd", - target_os = "openbsd" -))] -use winit::platform::unix::WindowExtUnix; -#[cfg(target_os = "windows")] -use winit::platform::windows::WindowExtWindows; use winit::{event::WindowEvent, keyboard::KeyCode, keyboard::ModifiersState, window::Window}; -#[cfg(not(target_os = "macos"))] -use muda::{AboutMetadata, Menu, MenuId, MenuItem, PredefinedMenuItem, Submenu}; - pub(crate) struct View<'s, Doc: DocumentLike> { pub(crate) renderer: Renderer<'s, Window, Doc>, pub(crate) scene: Scene, @@ -33,6 +22,9 @@ pub(crate) struct View<'s, Doc: DocumentLike> { /// The state of the keyboard modifiers (ctrl, shift, etc). Winit/Tao don't track these for us so we /// need to store them in order to have access to them when processing keypress events keyboard_modifiers: ModifiersState, + + /// Main menu bar of this view's window. + menu: Option, } impl<'a, Doc: DocumentLike> View<'a, Doc> { @@ -42,6 +34,7 @@ impl<'a, Doc: DocumentLike> View<'a, Doc> { scene: Scene::new(), waker: None, keyboard_modifiers: Default::default(), + menu: None, } } } @@ -224,7 +217,7 @@ impl<'a, Doc: DocumentLike> View<'a, Doc> { }; if let RenderState::Active(state) = &self.renderer.render_state { - state.window.set_cursor_icon(tao_cursor); + state.window.set_cursor(tao_cursor); self.request_redraw(); } } @@ -248,7 +241,6 @@ impl<'a, Doc: DocumentLike> View<'a, Doc> { winit::event::MouseScrollDelta::PixelDelta(offsets) => { self.renderer.scroll_by(offsets.y) } - _ => {} }; self.request_redraw(); } @@ -290,26 +282,10 @@ impl<'a, Doc: DocumentLike> View<'a, Doc> { })) .unwrap(); - #[cfg(target_os = "windows")] - { - use winit::raw_window_handle::*; - if let RawWindowHandle::Win32(handle) = window.window_handle().unwrap().as_raw() { - build_menu().init_for_hwnd(handle.hwnd.get()).unwrap(); - } - } - #[cfg(target_os = "linux")] - { - build_menu() - .init_for_gtk_window(window.gtk_window(), window.default_vbox()) - .unwrap(); - } - - // !TODO - this may not be the right way to do this, but it's a start - // #[cfg(target_os = "macos")] - // { - // menu_bar.init_for_nsapp(); - // build_menu().set_as_windows_menu_for_nsapp(); - // } + self.menu = Some(init_menu( + #[cfg(target_os = "windows")] + &window, + )); let size: winit::dpi::PhysicalSize = window.inner_size(); let mut viewport = Viewport::new((size.width, size.height)); @@ -334,21 +310,41 @@ impl<'a, Doc: DocumentLike> View<'a, Doc> { } } -#[cfg(not(target_os = "macos"))] -fn build_menu() -> Menu { +/// Initialize the default menu bar. +pub fn init_menu(#[cfg(target_os = "windows")] window: &Window) -> Menu { let menu = Menu::new(); // Build the about section let about = Submenu::new("About", true); - about .append_items(&[ &PredefinedMenuItem::about("Dioxus".into(), Option::from(AboutMetadata::default())), &MenuItem::with_id(MenuId::new("dev.show_layout"), "Show layout", true, None), ]) .unwrap(); - menu.append(&about).unwrap(); + #[cfg(target_os = "windows")] + { + use winit::raw_window_handle::*; + if let RawWindowHandle::Win32(handle) = window.window_handle().unwrap().as_raw() { + menu.init_for_hwnd(handle.hwnd.get()).unwrap(); + } + } + + // todo: menu on linux + // #[cfg(target_os = "linux")] + // { + // use winit::platform::unix::WindowExtUnix; + // menu.init_for_gtk_window(window.gtk_window(), window.default_vbox()) + // .unwrap(); + // } + + #[cfg(target_os = "macos")] + { + use winit::platform::macos::WindowExtMacOS; + menu.init_for_nsapp(); + } + menu }