diff --git a/Cargo.lock b/Cargo.lock index ea00f1fb..e9ae6cc1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -126,6 +126,12 @@ version = "0.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3fb67a6e08acf24fdeccbac2cb6ac4305825bd1f117462e0e6f2f193345ad56" +[[package]] +name = "as-raw-xcb-connection" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "175571dd1d178ced59193a6fc02dde1b972eb0bc56c892cde9beeceac5bf0f6b" + [[package]] name = "ash" version = "0.38.0+1.3.281" @@ -557,6 +563,15 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f079e83a288787bcd14a6aea84cee5c87a67c5a3e660c30f557a3d24761b3527" +[[package]] +name = "cgl" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ced0551234e87afee12411d535648dd89d2e7f34c78b753395567aff3d447ff" +dependencies = [ + "libc", +] + [[package]] name = "chacha20" version = "0.10.2" @@ -874,6 +889,7 @@ dependencies = [ name = "craft-ui" version = "0.1.0" dependencies = [ + "eframe", "egui", "egui_extras", "egui_kittest", @@ -1121,6 +1137,9 @@ dependencies = [ "egui", "egui-wgpu", "egui-winit", + "egui_glow", + "glutin", + "glutin-winit", "image", "js-sys", "log", @@ -1216,6 +1235,20 @@ dependencies = [ "resvg", ] +[[package]] +name = "egui_glow" +version = "0.36.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "606ed4167daf341e5753d703285c4c1d562324b2c07aa8f405cd7d066fe58f3b" +dependencies = [ + "bytemuck", + "egui", + "glow", + "log", + "profiling", + "winit", +] + [[package]] name = "egui_kittest" version = "0.36.2" @@ -1730,6 +1763,62 @@ dependencies = [ "web-sys", ] +[[package]] +name = "glutin" +version = "0.32.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12124de845cacfebedff80e877bb37b5b75c34c5a4c89e47e1cdd67fb6041325" +dependencies = [ + "bitflags 2.13.2", + "cfg_aliases", + "cgl", + "dispatch2", + "glutin_egl_sys", + "glutin_glx_sys", + "glutin_wgl_sys", + "libloading", + "objc2 0.6.5", + "objc2-app-kit 0.3.2", + "objc2-core-foundation", + "objc2-foundation 0.3.2", + "once_cell", + "raw-window-handle", + "windows-sys 0.52.0", + "x11-dl", +] + +[[package]] +name = "glutin-winit" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85edca7075f8fc728f28cb8fbb111a96c3b89e930574369e3e9c27eb75d3788f" +dependencies = [ + "cfg_aliases", + "glutin", + "raw-window-handle", + "winit", +] + +[[package]] +name = "glutin_egl_sys" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c4680ba6195f424febdc3ba46e7a42a0e58743f2edb115297b86d7f8ecc02d2" +dependencies = [ + "gl_generator", + "windows-sys 0.52.0", +] + +[[package]] +name = "glutin_glx_sys" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a7bb2938045a88b612499fbcba375a77198e01306f52272e692f8c1f3751185" +dependencies = [ + "gl_generator", + "x11-dl", +] + [[package]] name = "glutin_wgl_sys" version = "0.6.1" @@ -5999,6 +6088,7 @@ dependencies = [ "atomic-waker", "bitflags 2.13.2", "block2 0.5.1", + "bytemuck", "calloop 0.13.0", "cfg_aliases", "concurrent-queue", @@ -6014,6 +6104,7 @@ dependencies = [ "objc2-foundation 0.2.2", "objc2-ui-kit 0.2.2", "orbclient", + "percent-encoding", "pin-project", "raw-window-handle", "redox_syscall 0.4.1", @@ -6026,6 +6117,8 @@ dependencies = [ "web-sys", "web-time", "windows-sys 0.52.0", + "x11-dl", + "x11rb", "xkbcommon-dl", ] @@ -6084,13 +6177,28 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3ad82d2a33cdc9674dc7465672f271e096168fcdbe0f799d9e6db8c5892679dc" +[[package]] +name = "x11-dl" +version = "2.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38735924fedd5314a6e548792904ed8c6de6636285cb9fec04d5b1db85c1516f" +dependencies = [ + "libc", + "once_cell", + "pkg-config", +] + [[package]] name = "x11rb" version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9993aa5be5a26815fe2c3eacfc1fde061fc1a1f094bf1ad2a18bf9c495dd7414" dependencies = [ + "as-raw-xcb-connection", "gethostname", + "libc", + "libloading", + "once_cell", "rustix 1.1.5", "x11rb-protocol", ] diff --git a/crates/ui/Cargo.toml b/crates/ui/Cargo.toml index b5fc3bbd..554ed27f 100644 --- a/crates/ui/Cargo.toml +++ b/crates/ui/Cargo.toml @@ -26,4 +26,9 @@ egui = { workspace = true, features = ["default_fonts"] } serde_json = "1" egui_extras = { version = "0.36", default-features = false, features = ["svg"] } egui_kittest = { version = "0.36", features = ["wgpu"] } +eframe = { version = "0.36", default-features = false, features = ["wgpu", "x11", "default_fonts"] } image = { version = "0.25", default-features = false, features = ["png"] } + +[[example]] +name = "docking_native" +required-features = ["native-windows"] diff --git a/crates/ui/examples/docking_native.rs b/crates/ui/examples/docking_native.rs new file mode 100644 index 00000000..6a6940ca --- /dev/null +++ b/crates/ui/examples/docking_native.rs @@ -0,0 +1,53 @@ +//! Docking with floating panels in their own OS windows. Run with +//! `cargo run -p craft-ui --example docking_native --features native-windows`. +//! +//! Prints every action it applies and every native window's place, for checking moves by +//! hand or under a headless X server. + +use craft_ui::docking::{DockArea, DockContent, DockStyle, Floating, Layout, Node}; +use craft_ui::layout::{SplitAxis, SplitSize}; + +struct Panels; + +impl DockContent for Panels { + fn body(&mut self, ui: &mut egui::Ui, panel: &u32) { + ui.label(format!("Body of panel {panel}")); + } + + fn logical_label(&self, panel: &u32) -> String { + format!("Panel {panel}") + } +} + +struct App { + layout: Layout, +} + +impl eframe::App for App { + fn ui(&mut self, ui: &mut egui::Ui, _frame: &mut eframe::Frame) { + let style = DockStyle::from_ui(ui); + let out = DockArea::new(egui::Id::new("dock")).show_content(ui, &self.layout, &style, &mut Panels); + if !out.actions.is_empty() { + println!("actions {:?}", out.actions); + if let Err(error) = self.layout.apply_all(out.actions, |_| Default::default()) { + println!("rejected {error:?}"); + } + for window in &self.layout.floating { + println!("window {} panels {:?} native {:?}", window.id, window.panels().collect::>(), window.native); + } + } + if !out.forwarded_events.is_empty() { + println!("forwarded {:?} {:?}", out.forwarded_events, out.forwarded_modifiers); + } + } +} + +fn main() -> eframe::Result { + let tabs = |panels: &[u32]| Node::Tabs { panels: panels.to_vec(), active: 0 }; + let layout = Layout { + root: Some(Node::Split { axis: SplitAxis::Horizontal, size: SplitSize::Ratio(0.5), first: Box::new(tabs(&[1, 2])), second: Box::new(tabs(&[3, 4])) }), + floating: vec![Floating::single(vec![5, 6], 0, [300.0, 200.0, 320.0, 260.0]), Floating::single(vec![7], 0, [700.0, 300.0, 260.0, 200.0])], + }; + let options = eframe::NativeOptions { viewport: egui::ViewportBuilder::default().with_inner_size([1000.0, 700.0]).with_position([0.0, 0.0]), ..Default::default() }; + eframe::run_native("Docking", options, Box::new(|_| Ok(Box::new(App { layout })))) +}