Skip to content

Commit

Permalink
Fix cross-platform mudabar, wire up better CI (#75)
Browse files Browse the repository at this point in the history
* 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 <[email protected]>
  • Loading branch information
jkelleyrtp and matthunz authored Jun 20, 2024
1 parent 2e99ca1 commit f5cecd7
Show file tree
Hide file tree
Showing 6 changed files with 166 additions and 45 deletions.
80 changes: 79 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -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"
Expand Down Expand Up @@ -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/[email protected]
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 }}
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
/target
/Cargo.lock
.DS_Store
experiments
experiments
/.vscode
43 changes: 43 additions & 0 deletions CONTRIBUTING.MD
Original file line number Diff line number Diff line change
@@ -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
}
```
2 changes: 1 addition & 1 deletion packages/dioxus-blitz/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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 }
Expand Down
5 changes: 4 additions & 1 deletion packages/dioxus-blitz/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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},
Expand Down Expand Up @@ -108,6 +108,9 @@ fn launch_with_window<Doc: DocumentLike + 'static>(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);
Expand Down
78 changes: 37 additions & 41 deletions packages/dioxus-blitz/src/window.rs
Original file line number Diff line number Diff line change
@@ -1,38 +1,30 @@
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,
pub(crate) waker: Option<Waker>,
/// 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<Menu>,
}

impl<'a, Doc: DocumentLike> View<'a, Doc> {
Expand All @@ -42,6 +34,7 @@ impl<'a, Doc: DocumentLike> View<'a, Doc> {
scene: Scene::new(),
waker: None,
keyboard_modifiers: Default::default(),
menu: None,
}
}
}
Expand Down Expand Up @@ -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();
}
}
Expand All @@ -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();
}
Expand Down Expand Up @@ -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<u32> = window.inner_size();
let mut viewport = Viewport::new((size.width, size.height));
Expand All @@ -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
}

0 comments on commit f5cecd7

Please sign in to comment.