From 557183c8e180ddee0a5929ba0d7f3aa410ed1bc9 Mon Sep 17 00:00:00 2001 From: Delan Azabani Date: Thu, 6 Jul 2023 16:04:38 +0800 Subject: [PATCH 01/42] winit: add minibrowser feature that depends on egui{,-winit} --- Cargo.lock | 317 ++++++++++++++++++++++++++++++++++++++--- ports/winit/Cargo.toml | 5 +- 2 files changed, 302 insertions(+), 20 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d945407f3ec3..c47f5275f908 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -48,6 +48,17 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aae1277d39aeec15cb388266ecc24b11c80469deae6067e17a1a7aa9e5c1f234" +[[package]] +name = "ahash" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c99f64d1e06488f620f932677e24bc6e2897582980441ae90a671415bd7ec2f" +dependencies = [ + "cfg-if 1.0.0", + "once_cell", + "version_check", +] + [[package]] name = "aho-corasick" version = "0.7.18" @@ -139,6 +150,24 @@ dependencies = [ "serde", ] +[[package]] +name = "arboard" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6041616acea41d67c4a984709ddab1587fd0b10efe5cc563fee954d2f011854" +dependencies = [ + "clipboard-win 4.5.0", + "log", + "objc", + "objc-foundation", + "objc_id", + "once_cell", + "parking_lot 0.12.0", + "thiserror", + "winapi", + "x11rb", +] + [[package]] name = "array-init" version = "0.1.1" @@ -789,7 +818,7 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "25a904646c0340239dcf7c51677b33928bf24fdf424b79a57909c0109075b2e7" dependencies = [ - "clipboard-win", + "clipboard-win 2.2.0", "objc", "objc-foundation", "objc_id", @@ -805,6 +834,17 @@ dependencies = [ "winapi", ] +[[package]] +name = "clipboard-win" +version = "4.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7191c27c2357d9b7ef96baac1773290d4ca63b24205b82a3fd8a0637afcf0362" +dependencies = [ + "error-code", + "str-buf", + "winapi", +] + [[package]] name = "cmake" version = "0.1.49" @@ -1477,12 +1517,52 @@ dependencies = [ "wio", ] +[[package]] +name = "ecolor" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e479a7fa3f23d4e794f8b2f8b3568dd4e47886ad1b12c9c095e141cb591eb63" + +[[package]] +name = "egui" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3aef8ec3ae1b772f340170c65bf27d5b8c28f543a0116c844d2ac08d01123e7" +dependencies = [ + "ahash", + "epaint", + "log", + "nohash-hasher", +] + +[[package]] +name = "egui-winit" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a49155fd4a0a4fb21224407a91de0030847972ef90fc64edb63621caea61cb2" +dependencies = [ + "arboard", + "egui", + "instant", + "log", + "raw-window-handle 0.5.0", + "smithay-clipboard", + "webbrowser", + "winit", +] + [[package]] name = "either" version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" +[[package]] +name = "emath" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3857d743a6e0741cdd60b622a74c7a36ea75f5f8f11b793b41d905d2c9721a4b" + [[package]] name = "embedder_traits" version = "0.0.1" @@ -1561,6 +1641,22 @@ dependencies = [ "termcolor", ] +[[package]] +name = "epaint" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09333964d4d57f40a85338ba3ca5ed4716070ab184dcfed966b35491c5c64f3b" +dependencies = [ + "ab_glyph", + "ahash", + "atomic_refcell", + "ecolor", + "emath", + "log", + "nohash-hasher", + "parking_lot 0.12.0", +] + [[package]] name = "errno" version = "0.2.8" @@ -1582,6 +1678,16 @@ dependencies = [ "libc", ] +[[package]] +name = "error-code" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64f18991e7bf11e7ffee451b5318b5c1a73c52d0d0ada6e5a3017c8c1ced6a21" +dependencies = [ + "libc", + "str-buf", +] + [[package]] name = "euclid" version = "0.22.7" @@ -1924,6 +2030,16 @@ dependencies = [ "version_check", ] +[[package]] +name = "gethostname" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1ebd34e35c46e00bb73e81363248d627782724609fe1b6396f553f68fe3862e" +dependencies = [ + "libc", + "winapi", +] + [[package]] name = "getopts" version = "0.2.17" @@ -2694,6 +2810,15 @@ version = "0.6.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "12cb882ccb290b8646e554b157ab0b71e64e8d5bef775cd66b6531e52d302669" +[[package]] +name = "home" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5444c27eef6923071f7ebcc33e3444508466a76f7a2b93da00ed6e19f30c1ddb" +dependencies = [ + "windows-sys 0.48.0", +] + [[package]] name = "html5ever" version = "0.26.0" @@ -3037,6 +3162,22 @@ dependencies = [ "walkdir", ] +[[package]] +name = "jni" +version = "0.21.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a87aa2bb7d2af34197c04845522473242e1aa17c12f4935d5856491a7fb8c97" +dependencies = [ + "cesu8", + "cfg-if 1.0.0", + "combine", + "jni-sys", + "log", + "thiserror", + "walkdir", + "windows-sys 0.45.0", +] + [[package]] name = "jni-sys" version = "0.3.0" @@ -4127,6 +4268,12 @@ version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb" +[[package]] +name = "nohash-hasher" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bf50223579dc7cdcfb3bfcacf7069ff68243f8c363f62ffa99cf000a6b9c451" + [[package]] name = "nom" version = "7.1.3" @@ -5559,6 +5706,8 @@ dependencies = [ "backtrace", "cc", "clipboard", + "egui", + "egui-winit", "euclid", "getopts", "image 0.24.6", @@ -6020,7 +6169,7 @@ dependencies = [ "android_logger", "cc", "gstreamer", - "jni", + "jni 0.18.0", "libc", "log", "serde_json", @@ -6086,6 +6235,16 @@ dependencies = [ "wayland-protocols", ] +[[package]] +name = "smithay-clipboard" +version = "0.6.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a345c870a1fae0b1b779085e81b51e614767c239e93503588e54c5b17f4b0e8" +dependencies = [ + "smithay-client-toolkit", + "wayland-client", +] + [[package]] name = "socket2" version = "0.3.19" @@ -6174,6 +6333,12 @@ dependencies = [ "lock_api", ] +[[package]] +name = "str-buf" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e08d8363704e6c71fc928674353e6b7c23dcea9d82d7012c8faf2a3a025f8d0" + [[package]] name = "strict-num" version = "0.1.0" @@ -7001,9 +7166,9 @@ checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" [[package]] name = "version_check" -version = "0.9.2" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5a972e5669d67ba988ce3dc826706fb0a8b01471c088cb0b6110b805cc36aed" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" [[package]] name = "void" @@ -7225,6 +7390,23 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "webbrowser" +version = "0.8.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd222aa310eb7532e3fd427a5d7db7e44bc0b0cf1c1e21139c345325511a85b6" +dependencies = [ + "core-foundation 0.9.3", + "home", + "jni 0.21.1", + "log", + "ndk-context", + "objc", + "raw-window-handle 0.5.0", + "url", + "web-sys", +] + [[package]] name = "webdriver" version = "0.44.0" @@ -7500,6 +7682,15 @@ dependencies = [ "winapi", ] +[[package]] +name = "winapi-wsapoll" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44c17110f57155602a80dca10be03852116403c9ff3cd25b079d666f2aa3df6e" +dependencies = [ + "winapi", +] + [[package]] name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" @@ -7512,13 +7703,13 @@ version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", + "windows_aarch64_gnullvm 0.42.1", + "windows_aarch64_msvc 0.42.1", + "windows_i686_gnu 0.42.1", + "windows_i686_msvc 0.42.1", + "windows_x86_64_gnu 0.42.1", + "windows_x86_64_gnullvm 0.42.1", + "windows_x86_64_msvc 0.42.1", ] [[package]] @@ -7527,7 +7718,16 @@ version = "0.45.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" dependencies = [ - "windows-targets", + "windows-targets 0.42.1", +] + +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets 0.48.1", ] [[package]] @@ -7536,13 +7736,28 @@ version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e2522491fbfcd58cc84d47aeb2958948c4b8982e9a2d8a2a35bbaed431390e7" dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", + "windows_aarch64_gnullvm 0.42.1", + "windows_aarch64_msvc 0.42.1", + "windows_i686_gnu 0.42.1", + "windows_i686_msvc 0.42.1", + "windows_x86_64_gnu 0.42.1", + "windows_x86_64_gnullvm 0.42.1", + "windows_x86_64_msvc 0.42.1", +] + +[[package]] +name = "windows-targets" +version = "0.48.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05d4b17490f70499f20b9e791dcf6a299785ce8af4d709018206dc5b4953e95f" +dependencies = [ + "windows_aarch64_gnullvm 0.48.0", + "windows_aarch64_msvc 0.48.0", + "windows_i686_gnu 0.48.0", + "windows_i686_msvc 0.48.0", + "windows_x86_64_gnu 0.48.0", + "windows_x86_64_gnullvm 0.48.0", + "windows_x86_64_msvc 0.48.0", ] [[package]] @@ -7551,42 +7766,84 @@ version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8c9864e83243fdec7fc9c5444389dcbbfd258f745e7853198f365e3c4968a608" +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" + [[package]] name = "windows_aarch64_msvc" version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4c8b1b673ffc16c47a9ff48570a9d85e25d265735c503681332589af6253c6c7" +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" + [[package]] name = "windows_i686_gnu" version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "de3887528ad530ba7bdbb1faa8275ec7a1155a45ffa57c37993960277145d640" +[[package]] +name = "windows_i686_gnu" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" + [[package]] name = "windows_i686_msvc" version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bf4d1122317eddd6ff351aa852118a2418ad4214e6613a50e0191f7004372605" +[[package]] +name = "windows_i686_msvc" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" + [[package]] name = "windows_x86_64_gnu" version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c1040f221285e17ebccbc2591ffdc2d44ee1f9186324dd3e84e99ac68d699c45" +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" + [[package]] name = "windows_x86_64_gnullvm" version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "628bfdf232daa22b0d64fdb62b09fcc36bb01f05a3939e20ab73aaf9470d0463" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" + [[package]] name = "windows_x86_64_msvc" version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "447660ad36a13288b1db4d4248e857b510e8c3a225c822ba4fb748c0aafecffd" +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" + [[package]] name = "winit" version = "0.28.3" @@ -7697,6 +7954,28 @@ dependencies = [ "pkg-config", ] +[[package]] +name = "x11rb" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "592b4883219f345e712b3209c62654ebda0bb50887f330cbd018d0f654bfd507" +dependencies = [ + "gethostname", + "nix 0.24.3", + "winapi", + "winapi-wsapoll", + "x11rb-protocol", +] + +[[package]] +name = "x11rb-protocol" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56b245751c0ac9db0e006dc812031482784e434630205a93c73cfefcaabeac67" +dependencies = [ + "nix 0.24.3", +] + [[package]] name = "xcb" version = "0.8.2" diff --git a/ports/winit/Cargo.toml b/ports/winit/Cargo.toml index 7f471728b755..cca0a600c310 100644 --- a/ports/winit/Cargo.toml +++ b/ports/winit/Cargo.toml @@ -27,7 +27,7 @@ ProductName = "Servo" [features] debugmozjs = ["libservo/debugmozjs"] -default = ["webdriver", "max_log_level"] +default = ["webdriver", "max_log_level", "minibrowser"] egl = ["libservo/egl"] jitspew = ["libservo/jitspew"] js_backtrace = ["libservo/js_backtrace"] @@ -36,6 +36,7 @@ layout-2020 = ["libservo/layout-2020"] max_log_level = ["log/release_max_level_info"] media-dummy = ["libservo/media-dummy"] media-gstreamer = ["libservo/media-gstreamer"] +minibrowser = ["dep:egui", "dep:egui-winit"] native-bluetooth = ["libservo/native-bluetooth"] no-wgl = ["libservo/no-wgl"] profilemozjs = ["libservo/profilemozjs"] @@ -48,6 +49,8 @@ xr-profile = ["libservo/xr-profile"] [target.'cfg(not(target_os = "android"))'.dependencies] backtrace = "0.3" clipboard = "0.5" +egui = { version = "0.22.0", optional = true } +egui-winit = { version = "0.22.0", optional = true } euclid = "0.22" getopts = "0.2.11" keyboard-types = "0.6" From 7bb3db569b2258be20a425e2ba4f1bc102ee6887 Mon Sep 17 00:00:00 2001 From: Delan Azabani Date: Thu, 6 Jul 2023 16:08:32 +0800 Subject: [PATCH 02/42] winit: carve out some space at the top of headed windows --- ports/winit/headed_window.rs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/ports/winit/headed_window.rs b/ports/winit/headed_window.rs index 318f2083828b..1ed61e7f0bbe 100644 --- a/ports/winit/headed_window.rs +++ b/ports/winit/headed_window.rs @@ -525,8 +525,12 @@ impl WindowMethods for Window { let PhysicalSize { width, height } = self .winit_window .inner_size(); - let inner_size = (Size2D::new(width as f32, height as f32) * dpr).to_i32(); - let viewport = DeviceIntRect::new(Point2D::zero(), inner_size); + + let toolbar_height = 32f32; // TODO get real value from egui + let viewport_origin = Point2D::new(0f32, toolbar_height * 0f32).to_i32(); // TODO this misbehaves + let viewport_size = (Size2D::new(width as f32, height as f32 - toolbar_height) * dpr).to_i32(); + let viewport = DeviceIntRect::new(viewport_origin, viewport_size); + let framebuffer = DeviceIntSize::from_untyped(viewport.size.to_untyped()); EmbedderCoordinates { viewport, From 8947018c6a43924ec2cb85748c83ed0c52384698 Mon Sep 17 00:00:00 2001 From: Delan Azabani Date: Thu, 6 Jul 2023 16:10:32 +0800 Subject: [PATCH 03/42] winit: minimal toolbar and egui/winit integration (but no painting) --- ports/winit/app.rs | 64 +++++++++++++++++++++++++++++++++- ports/winit/headed_window.rs | 4 +++ ports/winit/headless_window.rs | 4 +++ ports/winit/window_trait.rs | 1 + 4 files changed, 72 insertions(+), 1 deletion(-) diff --git a/ports/winit/app.rs b/ports/winit/app.rs index d22edee25aa4..7ceab0d31394 100644 --- a/ports/winit/app.rs +++ b/ports/winit/app.rs @@ -9,6 +9,8 @@ use crate::embedder::EmbedderCallbacks; use crate::events_loop::{EventsLoop, ServoEvent}; use crate::window_trait::WindowPortsMethods; use crate::{headed_window, headless_window}; +use egui::{RawInput, TopBottomPanel}; +use egui_winit::EventResponse; use winit::window::WindowId; use winit::event_loop::EventLoopWindowTarget; use servo::compositing::windowing::WindowEvent; @@ -62,6 +64,50 @@ impl App { windows: HashMap::new(), }; + struct Minibrowser { + integration: egui_winit::State, + egui: egui::Context, + location: RefCell, + } + + impl Minibrowser { + fn update(&mut self, window: &winit::window::Window) { + let Self { integration, egui, location } = self; + let input = integration.take_egui_input(window); + let output = egui.clone().run(input, |ctx| { + TopBottomPanel::top("toolbar").show(ctx, |ui| { + ui.allocate_ui_with_layout( + ui.available_size(), + egui::Layout::right_to_left(egui::Align::Center), + |ui| { + if ui.button("go").clicked() { + // TODO go + dbg!("go clicked"); + } + ui.add_sized( + ui.available_size(), + egui::TextEdit::singleline(&mut *location.borrow_mut()), + ); + }, + ); + }); + dbg!(ctx.used_rect()); + }); + integration.handle_platform_output(window, egui, output.platform_output); + } + } + + // Set up egui context for minibrowser ui + let mut minibrowser = window.winit_window().map(|window| Minibrowser { + integration: egui_winit::State::new(window), + egui: egui::Context::default(), + location: RefCell::new(String::default()), + }); + + if let Some(minibrowser) = minibrowser.as_mut() { + minibrowser.update(window.winit_window().unwrap()); + } + let ev_waker = events_loop.create_event_loop_waker(); events_loop.run_forever(move |e, w, control_flow| { if let winit::event::Event::NewEvents(winit::event::StartCause::Init) = e { @@ -114,7 +160,23 @@ impl App { } // Handle the event - app.winit_event_to_servo_event(e); + let response = match e { + winit::event::Event::WindowEvent { ref event, .. } => { + if let Some(minibrowser) = minibrowser.as_mut() { + minibrowser.integration.on_event(&minibrowser.egui, &event) + } else { + EventResponse { consumed: false, repaint: false } + } + } + _ => EventResponse { consumed: false, repaint: false }, + }; + // TODO how do we handle the tab key? (see doc for consumed) + if !response.consumed { + app.winit_event_to_servo_event(e); + } + if response.repaint { + minibrowser.as_mut().unwrap().update(window.winit_window().unwrap()); + } let animating = app.is_animating(); diff --git a/ports/winit/headed_window.rs b/ports/winit/headed_window.rs index 1ed61e7f0bbe..87b61f7474b7 100644 --- a/ports/winit/headed_window.rs +++ b/ports/winit/headed_window.rs @@ -504,6 +504,10 @@ impl WindowPortsMethods for Window { self.xr_window_poses.borrow_mut().push(pose.clone()); Box::new(XRWindow { winit_window, pose }) } + + fn winit_window(&self) -> Option<&winit::window::Window> { + Some(&self.winit_window) + } } impl WindowMethods for Window { diff --git a/ports/winit/headless_window.rs b/ports/winit/headless_window.rs index 7402a5c5221f..e533ab9713ec 100644 --- a/ports/winit/headless_window.rs +++ b/ports/winit/headless_window.rs @@ -108,6 +108,10 @@ impl WindowPortsMethods for Window { ) -> Box { unimplemented!() } + + fn winit_window(&self) -> Option<&winit::window::Window> { + None + } } impl WindowMethods for Window { diff --git a/ports/winit/window_trait.rs b/ports/winit/window_trait.rs index d44c853e0d37..411ddf6c60b4 100644 --- a/ports/winit/window_trait.rs +++ b/ports/winit/window_trait.rs @@ -31,4 +31,5 @@ pub trait WindowPortsMethods: WindowMethods { &self, events_loop: &winit::event_loop::EventLoopWindowTarget ) -> Box; + fn winit_window(&self) -> Option<&winit::window::Window>; } From f9460afb9da697a3508831a32a5b747d7bdb91cc Mon Sep 17 00:00:00 2001 From: Delan Azabani Date: Thu, 6 Jul 2023 17:43:43 +0800 Subject: [PATCH 04/42] =?UTF-8?q?winit:=20try=20to=20paint=20with=20egui?= =?UTF-8?q?=5Fglow=20(doesn=E2=80=99t=20work=20yet)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Cargo.lock | 144 +++++++++++++++++++++++++++++------------ ports/winit/Cargo.toml | 4 +- ports/winit/app.rs | 32 ++++++--- 3 files changed, 128 insertions(+), 52 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c47f5275f908..45ebdbdf7eb8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -215,7 +215,7 @@ checksum = "d7d78656ba01f1b93024b7c3a0467f1608e4be67d725749fdcd7d2c7678fd7a2" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.103", ] [[package]] @@ -237,7 +237,7 @@ checksum = "e4655ae1a7b0cdf149156f780c5bf3f1352bc53cbd9e0a361a7ef7b22947e965" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.103", ] [[package]] @@ -366,7 +366,7 @@ dependencies = [ "regex", "rustc-hash", "shlex", - "syn", + "syn 1.0.103", "which", ] @@ -581,6 +581,20 @@ name = "bytemuck" version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "17febce684fd15d89027105661fec94afb475cb995fbc59d2865198446ba2eea" +dependencies = [ + "bytemuck_derive", +] + +[[package]] +name = "bytemuck_derive" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdde5c9cd29ebd706ce1b35600920a33550e402fc998a2e53ad3b42c3c47a192" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.23", +] [[package]] name = "byteorder" @@ -719,7 +733,7 @@ dependencies = [ "quote", "serde", "serde_json", - "syn", + "syn 1.0.103", "tempfile", "toml", ] @@ -1202,7 +1216,7 @@ dependencies = [ "quote", "serde", "smallvec", - "syn", + "syn 1.0.103", ] [[package]] @@ -1212,7 +1226,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dfae75de57f2b2e85e8768c3ea840fd159c8f33e2b6522c7835b7abac81be16e" dependencies = [ "quote", - "syn", + "syn 1.0.103", ] [[package]] @@ -1232,7 +1246,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cd670e5ff58768ef624207fb95709ce63b8d05573fb9a05165f0eef471ea6a3a" dependencies = [ "procedural-masquerade", - "syn", + "syn 1.0.103", ] [[package]] @@ -1272,7 +1286,7 @@ dependencies = [ "ident_case", "proc-macro2", "quote", - "syn", + "syn 1.0.103", ] [[package]] @@ -1283,7 +1297,7 @@ checksum = "d9b5a2f4ac4969822c62224815d069952656cadc7084fdca9751e6d959189b72" dependencies = [ "darling_core", "quote", - "syn", + "syn 1.0.103", ] [[package]] @@ -1319,7 +1333,7 @@ dependencies = [ name = "deny_public_fields" version = "0.0.1" dependencies = [ - "syn", + "syn 1.0.103", "synstructure", ] @@ -1337,7 +1351,7 @@ dependencies = [ "darling", "proc-macro2", "quote", - "syn", + "syn 1.0.103", "synstructure", ] @@ -1349,7 +1363,7 @@ checksum = "2127768764f1556535c01b5326ef94bd60ff08dcfbdc544d53e69ed155610f5d" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.103", ] [[package]] @@ -1470,7 +1484,7 @@ name = "dom_struct" version = "0.0.1" dependencies = [ "quote", - "syn", + "syn 1.0.103", ] [[package]] @@ -1479,7 +1493,7 @@ version = "0.0.1" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.103", ] [[package]] @@ -1522,6 +1536,9 @@ name = "ecolor" version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2e479a7fa3f23d4e794f8b2f8b3568dd4e47886ad1b12c9c095e141cb591eb63" +dependencies = [ + "bytemuck", +] [[package]] name = "egui" @@ -1551,6 +1568,22 @@ dependencies = [ "winit", ] +[[package]] +name = "egui_glow" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f8c2752cdf1b0ef5fcda59a898cacabad974d4f5880e92a420b2c917022da64" +dependencies = [ + "bytemuck", + "egui", + "egui-winit", + "glow", + "log", + "memoffset", + "wasm-bindgen", + "web-sys", +] + [[package]] name = "either" version = "1.6.1" @@ -1562,6 +1595,9 @@ name = "emath" version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3857d743a6e0741cdd60b622a74c7a36ea75f5f8f11b793b41d905d2c9721a4b" +dependencies = [ + "bytemuck", +] [[package]] name = "embedder_traits" @@ -1625,7 +1661,7 @@ checksum = "1df9d0cef4b051baf3ef7f9b1674273dc78cd56e02cba60fa187f9c0ff4ff5e0" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.103", ] [[package]] @@ -1650,6 +1686,7 @@ dependencies = [ "ab_glyph", "ahash", "atomic_refcell", + "bytemuck", "ecolor", "emath", "log", @@ -1958,7 +1995,7 @@ checksum = "3eb14ed937631bd8b8b8977f2c198443447a8355b6e3ca599f38c975e5a963b6" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.103", ] [[package]] @@ -2349,6 +2386,18 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574" +[[package]] +name = "glow" +version = "0.12.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "807edf58b70c0b5b2181dd39fe1839dbdb3ba02645630dc5f753e23da307f762" +dependencies = [ + "js-sys", + "slotmap", + "wasm-bindgen", + "web-sys", +] + [[package]] name = "glslopt" version = "0.1.8" @@ -2830,7 +2879,7 @@ dependencies = [ "markup5ever", "proc-macro2", "quote", - "syn", + "syn 1.0.103", ] [[package]] @@ -3216,7 +3265,7 @@ name = "jstraceable_derive" version = "0.0.1" dependencies = [ "proc-macro2", - "syn", + "syn 1.0.103", "synstructure", ] @@ -3726,7 +3775,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "632647502a8bfa82458c07134791fffa7a719f00427d1afd79c3cb6d4960a982" dependencies = [ "proc-macro2", - "syn", + "syn 1.0.103", "synstructure", ] @@ -4302,7 +4351,7 @@ checksum = "876a53fff98e03a936a674b29568b0e605f06b29372c2489ff4de23f1949743d" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.103", ] [[package]] @@ -4397,7 +4446,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn", + "syn 1.0.103", ] [[package]] @@ -4515,7 +4564,7 @@ checksum = "b501e44f11665960c7e7fcf062c7d96a14ade4aa98116c004b2e37b5be7d736c" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.103", ] [[package]] @@ -4694,7 +4743,7 @@ source = "git+https://github.com/jdm/webrender?branch=crash-backtrace#415b9ba326 dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.103", "synstructure", "unicode-xid", ] @@ -4812,7 +4861,7 @@ dependencies = [ "proc-macro-hack", "proc-macro2", "quote", - "syn", + "syn 1.0.103", ] [[package]] @@ -4859,7 +4908,7 @@ checksum = "044964427019eed9d49d9d5bbce6047ef18f37100ea400912a9fa4a3523ab12a" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.103", ] [[package]] @@ -4870,7 +4919,7 @@ checksum = "f8e8d2bf0b23038a4424865103a4df472855692821aab4e4f5c3312d461d9e5f" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.103", ] [[package]] @@ -4980,9 +5029,9 @@ checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5" [[package]] name = "proc-macro2" -version = "1.0.47" +version = "1.0.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ea3d908b0e36316caf9e9e2c4625cdde190a7e6f440d794667ed17a1855e725" +checksum = "7b368fba921b0dce7e60f5e04ec15e565b3303972b42bcfde1d0713b881959eb" dependencies = [ "unicode-ident", ] @@ -5053,9 +5102,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.18" +version = "1.0.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1feb54ed693b93a84e14094943b84b7c4eae204c512b7ccb95ab0c66d278ad1" +checksum = "573015e8ab27661678357f27dc26460738fd2b6c86e46f386fde94cb5d913105" dependencies = [ "proc-macro2", ] @@ -5673,7 +5722,7 @@ checksum = "cbd1ae72adb44aab48f325a02444a5fc079349a8d804c1fc922aed3f7454c74e" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.103", ] [[package]] @@ -5708,8 +5757,10 @@ dependencies = [ "clipboard", "egui", "egui-winit", + "egui_glow", "euclid", "getopts", + "glow", "image 0.24.6", "keyboard-types", "lazy_static", @@ -5985,7 +6036,7 @@ dependencies = [ "itertools", "proc-macro2", "quote", - "syn", + "syn 1.0.103", ] [[package]] @@ -6006,7 +6057,7 @@ source = "git+https://github.com/servo/media#f53ac0a03a1413362e15d39d1527466986d dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.103", ] [[package]] @@ -6443,7 +6494,7 @@ dependencies = [ "derive_common", "proc-macro2", "quote", - "syn", + "syn 1.0.103", "synstructure", ] @@ -6568,6 +6619,17 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "syn" +version = "2.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59fb7d6d8281a51045d62b8eb3a7d1ce347b76f312af50cd3dc0af39c87c1737" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + [[package]] name = "synstructure" version = "0.12.6" @@ -6576,7 +6638,7 @@ checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.103", "unicode-xid", ] @@ -6659,7 +6721,7 @@ checksum = "1fb327af4685e4d03fa8cbcf1716380da910eeb2bb8be417e7f9fd3fb164f36f" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.103", ] [[package]] @@ -6775,7 +6837,7 @@ dependencies = [ "derive_common", "proc-macro2", "quote", - "syn", + "syn 1.0.103", "synstructure", ] @@ -6824,7 +6886,7 @@ checksum = "e44da00bfc73a25f814cd8d7e57a68a5c31b74b3152a0a1d1f590c97ed06265a" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.103", ] [[package]] @@ -6835,7 +6897,7 @@ checksum = "b557f72f448c511a979e2564e55d74e6c4432fc96ff4f6241bc6bded342643b7" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.103", ] [[package]] @@ -7262,7 +7324,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn", + "syn 1.0.103", "wasm-bindgen-shared", ] @@ -7284,7 +7346,7 @@ checksum = "2aff81306fcac3c7515ad4e177f521b5c9a15f2b08f4e32d823066102f35a5f6" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.103", "wasm-bindgen-backend", "wasm-bindgen-shared", ] diff --git a/ports/winit/Cargo.toml b/ports/winit/Cargo.toml index cca0a600c310..925011c0d890 100644 --- a/ports/winit/Cargo.toml +++ b/ports/winit/Cargo.toml @@ -36,7 +36,7 @@ layout-2020 = ["libservo/layout-2020"] max_log_level = ["log/release_max_level_info"] media-dummy = ["libservo/media-dummy"] media-gstreamer = ["libservo/media-gstreamer"] -minibrowser = ["dep:egui", "dep:egui-winit"] +minibrowser = ["dep:egui", "dep:egui-winit", "dep:egui_glow", "dep:glow"] native-bluetooth = ["libservo/native-bluetooth"] no-wgl = ["libservo/no-wgl"] profilemozjs = ["libservo/profilemozjs"] @@ -50,9 +50,11 @@ xr-profile = ["libservo/xr-profile"] backtrace = "0.3" clipboard = "0.5" egui = { version = "0.22.0", optional = true } +egui_glow = { version = "0.22.0", optional = true, features = ["winit"] } egui-winit = { version = "0.22.0", optional = true } euclid = "0.22" getopts = "0.2.11" +glow = { version = "0.12.2", optional = true } keyboard-types = "0.6" lazy_static = "1" libc = "0.2" diff --git a/ports/winit/app.rs b/ports/winit/app.rs index 7ceab0d31394..79c0fd12ac95 100644 --- a/ports/winit/app.rs +++ b/ports/winit/app.rs @@ -23,6 +23,7 @@ use std::collections::HashMap; use std::env; use std::mem; use std::rc::Rc; +use std::sync::Arc; use webxr::glwindow::GlWindowDiscovery; pub struct App { @@ -65,16 +66,14 @@ impl App { }; struct Minibrowser { - integration: egui_winit::State, - egui: egui::Context, + context: egui_glow::EguiGlow, location: RefCell, } impl Minibrowser { fn update(&mut self, window: &winit::window::Window) { - let Self { integration, egui, location } = self; - let input = integration.take_egui_input(window); - let output = egui.clone().run(input, |ctx| { + let Self { context, location } = self; + let _duration = context.run(window, |ctx| { TopBottomPanel::top("toolbar").show(ctx, |ui| { ui.allocate_ui_with_layout( ui.available_size(), @@ -93,14 +92,27 @@ impl App { }); dbg!(ctx.used_rect()); }); - integration.handle_platform_output(window, egui, output.platform_output); + context.paint(window); } } + // TODO maybe we need to bind a framebuffer object? + // => glow::Context::create_framebuffer_from_gl_name says “Creates a framebuffer from an + // external GL name. This can be useful when a framebuffer is created outside of glow + // (e.g: via surfman or another crate that supports sharing of buffers between GL + // contexts), but glow needs to set it as a target.” + // => see Servo::new in components/servo/lib.rs for how to do this + // let fbo = window.webrender_surfman().context_surface_info().unwrap().unwrap().framebuffer_object; + // Set up egui context for minibrowser ui - let mut minibrowser = window.winit_window().map(|window| Minibrowser { - integration: egui_winit::State::new(window), - egui: egui::Context::default(), + // Adapted from https://github.com/emilk/egui/blob/9478e50d012c5138551c38cbee16b07bc1fcf283/crates/egui_glow/examples/pure_glow.rs + let gl = unsafe { + glow::Context::from_loader_function(|s| { + window.webrender_surfman().get_proc_address(s) + }) + }; + let mut minibrowser = window.winit_window().map(|_| Minibrowser { + context: egui_glow::EguiGlow::new(events_loop.as_winit(), Arc::new(gl), None), location: RefCell::new(String::default()), }); @@ -163,7 +175,7 @@ impl App { let response = match e { winit::event::Event::WindowEvent { ref event, .. } => { if let Some(minibrowser) = minibrowser.as_mut() { - minibrowser.integration.on_event(&minibrowser.egui, &event) + minibrowser.context.on_event(&event) } else { EventResponse { consumed: false, repaint: false } } From 4e01fde22fe3f15e710a77c9b9ddba4f852a525f Mon Sep 17 00:00:00 2001 From: Delan Azabani Date: Thu, 6 Jul 2023 18:05:49 +0800 Subject: [PATCH 05/42] winit: add comment about toolbar size --- ports/winit/app.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ports/winit/app.rs b/ports/winit/app.rs index 79c0fd12ac95..babc0f5c5c6a 100644 --- a/ports/winit/app.rs +++ b/ports/winit/app.rs @@ -90,6 +90,9 @@ impl App { }, ); }); + + // Get the toolbar size + // TODO somehow pass this to the headed Window::get_coordinates dbg!(ctx.used_rect()); }); context.paint(window); From 7103b4bc0acb88f3381d128a0f89ae5cf700b561 Mon Sep 17 00:00:00 2001 From: atbrakhi Date: Tue, 11 Jul 2023 10:52:19 +0200 Subject: [PATCH 06/42] Add framebuffer object, set it as glow's target --- Cargo.lock | 1 + ports/winit/Cargo.toml | 1 + ports/winit/app.rs | 46 +++++++++++++++++++++++++++++++++--------- 3 files changed, 39 insertions(+), 9 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 45ebdbdf7eb8..f5f66a0709f0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5760,6 +5760,7 @@ dependencies = [ "egui_glow", "euclid", "getopts", + "gleam", "glow", "image 0.24.6", "keyboard-types", diff --git a/ports/winit/Cargo.toml b/ports/winit/Cargo.toml index 925011c0d890..29cab289b20c 100644 --- a/ports/winit/Cargo.toml +++ b/ports/winit/Cargo.toml @@ -54,6 +54,7 @@ egui_glow = { version = "0.22.0", optional = true, features = ["winit"] } egui-winit = { version = "0.22.0", optional = true } euclid = "0.22" getopts = "0.2.11" +gleam = "0.12" glow = { version = "0.12.2", optional = true } keyboard-types = "0.6" lazy_static = "1" diff --git a/ports/winit/app.rs b/ports/winit/app.rs index babc0f5c5c6a..15b99e100087 100644 --- a/ports/winit/app.rs +++ b/ports/winit/app.rs @@ -9,8 +9,10 @@ use crate::embedder::EmbedderCallbacks; use crate::events_loop::{EventsLoop, ServoEvent}; use crate::window_trait::WindowPortsMethods; use crate::{headed_window, headless_window}; -use egui::{RawInput, TopBottomPanel}; +use egui::TopBottomPanel; use egui_winit::EventResponse; +use gleam::gl; +use glow::{NativeFramebuffer, HasContext}; use winit::window::WindowId; use winit::event_loop::EventLoopWindowTarget; use servo::compositing::windowing::WindowEvent; @@ -21,9 +23,11 @@ use servo::Servo; use std::cell::{Cell, RefCell}; use std::collections::HashMap; use std::env; +use std::num::NonZeroU32; use std::mem; use std::rc::Rc; use std::sync::Arc; +use surfman::GLApi; use webxr::glwindow::GlWindowDiscovery; pub struct App { @@ -99,21 +103,44 @@ impl App { } } - // TODO maybe we need to bind a framebuffer object? - // => glow::Context::create_framebuffer_from_gl_name says “Creates a framebuffer from an - // external GL name. This can be useful when a framebuffer is created outside of glow - // (e.g: via surfman or another crate that supports sharing of buffers between GL - // contexts), but glow needs to set it as a target.” - // => see Servo::new in components/servo/lib.rs for how to do this - // let fbo = window.webrender_surfman().context_surface_info().unwrap().unwrap().framebuffer_object; + // Create FrameBufferObject + let webrender_surfman = window.webrender_surfman(); + let webrender_gl = match webrender_surfman.connection().gl_api() { + GLApi::GL => unsafe { gl::GlFns::load_with(|s| webrender_surfman.get_proc_address(s)) }, + GLApi::GLES => unsafe { + gl::GlesFns::load_with(|s| webrender_surfman.get_proc_address(s)) + }, + }; + + // Make sure the gl context is made current. + webrender_surfman.make_gl_context_current().unwrap(); + debug_assert_eq!(webrender_gl.get_error(), gleam::gl::NO_ERROR,); + + // Bind the webrender framebuffer + let framebuffer_object = webrender_surfman + .context_surface_info() + .unwrap_or(None) + .map(|info| info.framebuffer_object) + .unwrap_or(0); + + let native_framebuffer = NativeFramebuffer(NonZeroU32::new(framebuffer_object).unwrap()); + + let framebuffer_object = native_framebuffer.0.get(); // Set up egui context for minibrowser ui // Adapted from https://github.com/emilk/egui/blob/9478e50d012c5138551c38cbee16b07bc1fcf283/crates/egui_glow/examples/pure_glow.rs let gl = unsafe { glow::Context::from_loader_function(|s| { - window.webrender_surfman().get_proc_address(s) + webrender_surfman.get_proc_address(s) }) }; + + // glow needs to set framebuffer as a target + unsafe { + gl.bind_framebuffer(glow::FRAMEBUFFER, Some(NativeFramebuffer(NonZeroU32::new(framebuffer_object).unwrap()))); + }; + + let mut minibrowser = window.winit_window().map(|_| Minibrowser { context: egui_glow::EguiGlow::new(events_loop.as_winit(), Arc::new(gl), None), location: RefCell::new(String::default()), @@ -185,6 +212,7 @@ impl App { } _ => EventResponse { consumed: false, repaint: false }, }; + // TODO how do we handle the tab key? (see doc for consumed) if !response.consumed { app.winit_event_to_servo_event(e); From 3be6a179687f4b9026d38dfba34608deec8fd523 Mon Sep 17 00:00:00 2001 From: Delan Azabani Date: Tue, 11 Jul 2023 18:20:34 +0800 Subject: [PATCH 07/42] compositing: clear only the viewport, not the whole framebuffer --- components/compositing/compositor.rs | 5 ----- 1 file changed, 5 deletions(-) diff --git a/components/compositing/compositor.rs b/components/compositing/compositor.rs index b453547365f8..36fadfe33804 100644 --- a/components/compositing/compositor.rs +++ b/components/compositing/compositor.rs @@ -1678,11 +1678,6 @@ impl IOCompositor { let gl = &self.webrender_gl; self.assert_gl_framebuffer_complete(); - // Make framebuffer fully transparent. - gl.clear_color(0.0, 0.0, 0.0, 0.0); - gl.clear(gleam::gl::COLOR_BUFFER_BIT); - self.assert_gl_framebuffer_complete(); - // Make the viewport white. let viewport = self.embedder_coordinates.get_flipped_viewport(); gl.scissor( From 9eb92a2f29394cb8782b9fdaf8d71f61f4487db0 Mon Sep 17 00:00:00 2001 From: atbrakhi Date: Tue, 11 Jul 2023 16:33:12 +0200 Subject: [PATCH 08/42] plumb the actual size of the egui toolbar to webrender --- ports/winit/app.rs | 14 ++++++++------ ports/winit/headed_window.rs | 6 +++++- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/ports/winit/app.rs b/ports/winit/app.rs index 15b99e100087..11f3580ab740 100644 --- a/ports/winit/app.rs +++ b/ports/winit/app.rs @@ -30,6 +30,8 @@ use std::sync::Arc; use surfman::GLApi; use webxr::glwindow::GlWindowDiscovery; +pub static mut TOOLBAR_HEIGHT: f32 = 0.0; + pub struct App { servo: Option>, browser: RefCell>, @@ -70,8 +72,8 @@ impl App { }; struct Minibrowser { - context: egui_glow::EguiGlow, - location: RefCell, + context: egui_glow::EguiGlow, + location: RefCell, } impl Minibrowser { @@ -95,9 +97,9 @@ impl App { ); }); - // Get the toolbar size - // TODO somehow pass this to the headed Window::get_coordinates - dbg!(ctx.used_rect()); + unsafe { + TOOLBAR_HEIGHT = ctx.used_rect().height(); + } }); context.paint(window); } @@ -143,7 +145,7 @@ impl App { let mut minibrowser = window.winit_window().map(|_| Minibrowser { context: egui_glow::EguiGlow::new(events_loop.as_winit(), Arc::new(gl), None), - location: RefCell::new(String::default()), + location: RefCell::new(String::default()) }); if let Some(minibrowser) = minibrowser.as_mut() { diff --git a/ports/winit/headed_window.rs b/ports/winit/headed_window.rs index 87b61f7474b7..7a82483a4055 100644 --- a/ports/winit/headed_window.rs +++ b/ports/winit/headed_window.rs @@ -4,6 +4,7 @@ //! A winit window implementation. +use crate::app; use crate::events_loop::{EventsLoop, ServoEvent}; use crate::keyutils::keyboard_event_from_winit; use crate::window_trait::{WindowPortsMethods, LINE_HEIGHT}; @@ -530,7 +531,10 @@ impl WindowMethods for Window { .winit_window .inner_size(); - let toolbar_height = 32f32; // TODO get real value from egui + let value = unsafe { app::TOOLBAR_HEIGHT }; + dbg!(value); + + let toolbar_height = value; let viewport_origin = Point2D::new(0f32, toolbar_height * 0f32).to_i32(); // TODO this misbehaves let viewport_size = (Size2D::new(width as f32, height as f32 - toolbar_height) * dpr).to_i32(); let viewport = DeviceIntRect::new(viewport_origin, viewport_size); From 034a831e2c73b5091cad4b84418f25b5791bda60 Mon Sep 17 00:00:00 2001 From: atbrakhi Date: Tue, 11 Jul 2023 17:42:35 +0200 Subject: [PATCH 09/42] fix formatting --- ports/winit/app.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/ports/winit/app.rs b/ports/winit/app.rs index 11f3580ab740..32cd586045a9 100644 --- a/ports/winit/app.rs +++ b/ports/winit/app.rs @@ -139,7 +139,9 @@ impl App { // glow needs to set framebuffer as a target unsafe { - gl.bind_framebuffer(glow::FRAMEBUFFER, Some(NativeFramebuffer(NonZeroU32::new(framebuffer_object).unwrap()))); + gl.bind_framebuffer( + glow::FRAMEBUFFER, + Some(NativeFramebuffer(NonZeroU32::new(framebuffer_object).unwrap()))); }; From e495886064a98df2bcfa6cbdea28933a721f2fe1 Mon Sep 17 00:00:00 2001 From: Delan Azabani Date: Wed, 12 Jul 2023 20:02:48 +0800 Subject: [PATCH 10/42] winit: fix crash when fbo is zero --- ports/winit/app.rs | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/ports/winit/app.rs b/ports/winit/app.rs index 32cd586045a9..da89bd00db0b 100644 --- a/ports/winit/app.rs +++ b/ports/winit/app.rs @@ -122,15 +122,9 @@ impl App { let framebuffer_object = webrender_surfman .context_surface_info() .unwrap_or(None) - .map(|info| info.framebuffer_object) - .unwrap_or(0); + .and_then(|info| NonZeroU32::new(info.framebuffer_object)) + .map(NativeFramebuffer); - let native_framebuffer = NativeFramebuffer(NonZeroU32::new(framebuffer_object).unwrap()); - - let framebuffer_object = native_framebuffer.0.get(); - - // Set up egui context for minibrowser ui - // Adapted from https://github.com/emilk/egui/blob/9478e50d012c5138551c38cbee16b07bc1fcf283/crates/egui_glow/examples/pure_glow.rs let gl = unsafe { glow::Context::from_loader_function(|s| { webrender_surfman.get_proc_address(s) @@ -139,12 +133,12 @@ impl App { // glow needs to set framebuffer as a target unsafe { - gl.bind_framebuffer( - glow::FRAMEBUFFER, - Some(NativeFramebuffer(NonZeroU32::new(framebuffer_object).unwrap()))); + gl.bind_framebuffer(glow::FRAMEBUFFER, framebuffer_object); }; + // Set up egui context for minibrowser ui + // Adapted from https://github.com/emilk/egui/blob/9478e50d012c5138551c38cbee16b07bc1fcf283/crates/egui_glow/examples/pure_glow.rs let mut minibrowser = window.winit_window().map(|_| Minibrowser { context: egui_glow::EguiGlow::new(events_loop.as_winit(), Arc::new(gl), None), location: RefCell::new(String::default()) From e9f8c3c0bbbdc6166f9006dc69d88a11103e2b2d Mon Sep 17 00:00:00 2001 From: Delan Azabani Date: Wed, 12 Jul 2023 20:11:34 +0800 Subject: [PATCH 11/42] =?UTF-8?q?winit:=20don=E2=80=99t=20bother=20binding?= =?UTF-8?q?=20the=20framebuffer=20object?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ports/winit/app.rs | 22 +++------------------- 1 file changed, 3 insertions(+), 19 deletions(-) diff --git a/ports/winit/app.rs b/ports/winit/app.rs index da89bd00db0b..205ae2f1634e 100644 --- a/ports/winit/app.rs +++ b/ports/winit/app.rs @@ -105,7 +105,7 @@ impl App { } } - // Create FrameBufferObject + // Make sure the gl context is made current. let webrender_surfman = window.webrender_surfman(); let webrender_gl = match webrender_surfman.connection().gl_api() { GLApi::GL => unsafe { gl::GlFns::load_with(|s| webrender_surfman.get_proc_address(s)) }, @@ -113,29 +113,13 @@ impl App { gl::GlesFns::load_with(|s| webrender_surfman.get_proc_address(s)) }, }; - - // Make sure the gl context is made current. - webrender_surfman.make_gl_context_current().unwrap(); - debug_assert_eq!(webrender_gl.get_error(), gleam::gl::NO_ERROR,); - - // Bind the webrender framebuffer - let framebuffer_object = webrender_surfman - .context_surface_info() - .unwrap_or(None) - .and_then(|info| NonZeroU32::new(info.framebuffer_object)) - .map(NativeFramebuffer); - let gl = unsafe { glow::Context::from_loader_function(|s| { webrender_surfman.get_proc_address(s) }) }; - - // glow needs to set framebuffer as a target - unsafe { - gl.bind_framebuffer(glow::FRAMEBUFFER, framebuffer_object); - }; - + webrender_surfman.make_gl_context_current().unwrap(); + debug_assert_eq!(webrender_gl.get_error(), gleam::gl::NO_ERROR,); // Set up egui context for minibrowser ui // Adapted from https://github.com/emilk/egui/blob/9478e50d012c5138551c38cbee16b07bc1fcf283/crates/egui_glow/examples/pure_glow.rs From a8e1e5be3ed5810dc0cbc0215d1d96b3e92ab612 Mon Sep 17 00:00:00 2001 From: atbrakhi Date: Sun, 16 Jul 2023 23:30:00 +0200 Subject: [PATCH 12/42] winit: remove unsafe and get toolbar_height --- ports/winit/app.rs | 13 ++++++------- ports/winit/headed_window.rs | 13 ++++++++----- ports/winit/headless_window.rs | 4 ++++ ports/winit/window_trait.rs | 1 + 4 files changed, 19 insertions(+), 12 deletions(-) diff --git a/ports/winit/app.rs b/ports/winit/app.rs index 205ae2f1634e..94acbd449b2e 100644 --- a/ports/winit/app.rs +++ b/ports/winit/app.rs @@ -30,8 +30,6 @@ use std::sync::Arc; use surfman::GLApi; use webxr::glwindow::GlWindowDiscovery; -pub static mut TOOLBAR_HEIGHT: f32 = 0.0; - pub struct App { servo: Option>, browser: RefCell>, @@ -77,8 +75,9 @@ impl App { } impl Minibrowser { - fn update(&mut self, window: &winit::window::Window) { + fn update(&mut self, window: &winit::window::Window) -> f32 { let Self { context, location } = self; + let mut toolbar_height= 0.0; let _duration = context.run(window, |ctx| { TopBottomPanel::top("toolbar").show(ctx, |ui| { ui.allocate_ui_with_layout( @@ -97,11 +96,11 @@ impl App { ); }); - unsafe { - TOOLBAR_HEIGHT = ctx.used_rect().height(); - } + toolbar_height = ctx.used_rect().height(); }); context.paint(window); + + toolbar_height } } @@ -129,7 +128,7 @@ impl App { }); if let Some(minibrowser) = minibrowser.as_mut() { - minibrowser.update(window.winit_window().unwrap()); + window.set_toolbar_size(minibrowser.update(window.winit_window().unwrap())); } let ev_waker = events_loop.create_event_loop_waker(); diff --git a/ports/winit/headed_window.rs b/ports/winit/headed_window.rs index 7a82483a4055..ef8130c7677c 100644 --- a/ports/winit/headed_window.rs +++ b/ports/winit/headed_window.rs @@ -4,7 +4,6 @@ //! A winit window implementation. -use crate::app; use crate::events_loop::{EventsLoop, ServoEvent}; use crate::keyutils::keyboard_event_from_winit; use crate::window_trait::{WindowPortsMethods, LINE_HEIGHT}; @@ -54,6 +53,7 @@ pub struct Window { webrender_surfman: WebrenderSurfman, screen_size: Size2D, inner_size: Cell>, + toolbar_size: Cell, mouse_down_button: Cell>, mouse_down_point: Cell>, primary_monitor: winit::monitor::MonitorHandle, @@ -157,6 +157,7 @@ impl Window { device_pixels_per_px, xr_window_poses: RefCell::new(vec![]), modifiers_state: Cell::new(ModifiersState::empty()), + toolbar_size: Cell::new(0.0), // Initial value } } @@ -509,6 +510,10 @@ impl WindowPortsMethods for Window { fn winit_window(&self) -> Option<&winit::window::Window> { Some(&self.winit_window) } + + fn set_toolbar_size(&self, height: f32) { + self.toolbar_size.set(height); + } } impl WindowMethods for Window { @@ -531,10 +536,8 @@ impl WindowMethods for Window { .winit_window .inner_size(); - let value = unsafe { app::TOOLBAR_HEIGHT }; - dbg!(value); - - let toolbar_height = value; + // Get the height of toolbar for minibrowser + let toolbar_height = self.toolbar_size.get(); let viewport_origin = Point2D::new(0f32, toolbar_height * 0f32).to_i32(); // TODO this misbehaves let viewport_size = (Size2D::new(width as f32, height as f32 - toolbar_height) * dpr).to_i32(); let viewport = DeviceIntRect::new(viewport_origin, viewport_size); diff --git a/ports/winit/headless_window.rs b/ports/winit/headless_window.rs index e533ab9713ec..531d077d708e 100644 --- a/ports/winit/headless_window.rs +++ b/ports/winit/headless_window.rs @@ -112,6 +112,10 @@ impl WindowPortsMethods for Window { fn winit_window(&self) -> Option<&winit::window::Window> { None } + + fn set_toolbar_size(&self, _height: f32) { + // Skip for now + } } impl WindowMethods for Window { diff --git a/ports/winit/window_trait.rs b/ports/winit/window_trait.rs index 411ddf6c60b4..4bac0aea917e 100644 --- a/ports/winit/window_trait.rs +++ b/ports/winit/window_trait.rs @@ -32,4 +32,5 @@ pub trait WindowPortsMethods: WindowMethods { events_loop: &winit::event_loop::EventLoopWindowTarget ) -> Box; fn winit_window(&self) -> Option<&winit::window::Window>; + fn set_toolbar_size(&self, height: f32); } From aac08c7b58562f71c47477b15d13394fe166b492 Mon Sep 17 00:00:00 2001 From: atbrakhi Date: Mon, 17 Jul 2023 22:38:39 +0200 Subject: [PATCH 13/42] winit: location field should reflect the current top-level url --- ports/winit/app.rs | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/ports/winit/app.rs b/ports/winit/app.rs index 94acbd449b2e..b5a776606800 100644 --- a/ports/winit/app.rs +++ b/ports/winit/app.rs @@ -12,7 +12,6 @@ use crate::{headed_window, headless_window}; use egui::TopBottomPanel; use egui_winit::EventResponse; use gleam::gl; -use glow::{NativeFramebuffer, HasContext}; use winit::window::WindowId; use winit::event_loop::EventLoopWindowTarget; use servo::compositing::windowing::WindowEvent; @@ -23,7 +22,6 @@ use servo::Servo; use std::cell::{Cell, RefCell}; use std::collections::HashMap; use std::env; -use std::num::NonZeroU32; use std::mem; use std::rc::Rc; use std::sync::Arc; @@ -70,8 +68,8 @@ impl App { }; struct Minibrowser { - context: egui_glow::EguiGlow, - location: RefCell, + context: egui_glow::EguiGlow, + location: RefCell, } impl Minibrowser { @@ -124,7 +122,7 @@ impl App { // Adapted from https://github.com/emilk/egui/blob/9478e50d012c5138551c38cbee16b07bc1fcf283/crates/egui_glow/examples/pure_glow.rs let mut minibrowser = window.winit_window().map(|_| Minibrowser { context: egui_glow::EguiGlow::new(events_loop.as_winit(), Arc::new(gl), None), - location: RefCell::new(String::default()) + location: RefCell::new(ServoUrl::into_string(get_default_url())) }); if let Some(minibrowser) = minibrowser.as_mut() { @@ -311,6 +309,7 @@ fn get_default_url() -> ServoUrl { // or a blank page in case the homepage is not set either. let cwd = env::current_dir().unwrap(); let cmdline_url = opts::get().url.clone(); + let pref_url = { let homepage_url = pref!(shell.homepage); parse_url_or_filename(&cwd, &homepage_url).ok() From 37ea3f0f98803f7e34e961424024add213aa70bf Mon Sep 17 00:00:00 2001 From: Delan Azabani Date: Wed, 26 Jul 2023 14:39:32 +0800 Subject: [PATCH 14/42] [NFC] winit: move Minibrowser out of App::run --- ports/winit/app.rs | 70 +++++++++++++++++++++++----------------------- 1 file changed, 35 insertions(+), 35 deletions(-) diff --git a/ports/winit/app.rs b/ports/winit/app.rs index 2583ecc65f18..b6fb43b5a6c1 100644 --- a/ports/winit/app.rs +++ b/ports/winit/app.rs @@ -36,6 +36,41 @@ pub struct App { windows: HashMap>, } +struct Minibrowser { + context: egui_glow::EguiGlow, + location: RefCell, +} + +impl Minibrowser { + fn update(&mut self, window: &winit::window::Window) -> f32 { + let Self { context, location } = self; + let mut toolbar_height= 0.0; + let _duration = context.run(window, |ctx| { + TopBottomPanel::top("toolbar").show(ctx, |ui| { + ui.allocate_ui_with_layout( + ui.available_size(), + egui::Layout::right_to_left(egui::Align::Center), + |ui| { + if ui.button("go").clicked() { + // TODO go + dbg!("go clicked"); + } + ui.add_sized( + ui.available_size(), + egui::TextEdit::singleline(&mut *location.borrow_mut()), + ); + }, + ); + }); + + toolbar_height = ctx.used_rect().height(); + }); + context.paint(window); + + toolbar_height + } +} + impl App { pub fn run( no_native_titlebar: bool, @@ -67,41 +102,6 @@ impl App { windows: HashMap::new(), }; - struct Minibrowser { - context: egui_glow::EguiGlow, - location: RefCell, - } - - impl Minibrowser { - fn update(&mut self, window: &winit::window::Window) -> f32 { - let Self { context, location } = self; - let mut toolbar_height= 0.0; - let _duration = context.run(window, |ctx| { - TopBottomPanel::top("toolbar").show(ctx, |ui| { - ui.allocate_ui_with_layout( - ui.available_size(), - egui::Layout::right_to_left(egui::Align::Center), - |ui| { - if ui.button("go").clicked() { - // TODO go - dbg!("go clicked"); - } - ui.add_sized( - ui.available_size(), - egui::TextEdit::singleline(&mut *location.borrow_mut()), - ); - }, - ); - }); - - toolbar_height = ctx.used_rect().height(); - }); - context.paint(window); - - toolbar_height - } - } - // Make sure the gl context is made current. let webrender_surfman = window.webrender_surfman(); let webrender_gl = match webrender_surfman.connection().gl_api() { From d71796269092dca16dfeb9da288b5e024bf2a1fc Mon Sep 17 00:00:00 2001 From: Delan Azabani Date: Wed, 26 Jul 2023 14:54:49 +0800 Subject: [PATCH 15/42] winit: clean up toolbar height code --- ports/winit/app.rs | 16 ++++++++-------- ports/winit/headless_window.rs | 2 +- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/ports/winit/app.rs b/ports/winit/app.rs index b6fb43b5a6c1..e45376ce5539 100644 --- a/ports/winit/app.rs +++ b/ports/winit/app.rs @@ -39,12 +39,12 @@ pub struct App { struct Minibrowser { context: egui_glow::EguiGlow, location: RefCell, + toolbar_height: Cell, } impl Minibrowser { - fn update(&mut self, window: &winit::window::Window) -> f32 { - let Self { context, location } = self; - let mut toolbar_height= 0.0; + fn update(&mut self, window: &winit::window::Window) { + let Self { context, location, toolbar_height } = self; let _duration = context.run(window, |ctx| { TopBottomPanel::top("toolbar").show(ctx, |ui| { ui.allocate_ui_with_layout( @@ -63,11 +63,9 @@ impl Minibrowser { ); }); - toolbar_height = ctx.used_rect().height(); + toolbar_height.set(ctx.used_rect().height()); }); context.paint(window); - - toolbar_height } } @@ -122,11 +120,13 @@ impl App { // Adapted from https://github.com/emilk/egui/blob/9478e50d012c5138551c38cbee16b07bc1fcf283/crates/egui_glow/examples/pure_glow.rs let mut minibrowser = window.winit_window().map(|_| Minibrowser { context: egui_glow::EguiGlow::new(events_loop.as_winit(), Arc::new(gl), None), - location: RefCell::new(ServoUrl::into_string(get_default_url())) + location: RefCell::new(ServoUrl::into_string(get_default_url())), + toolbar_height: 0f32.into(), }); if let Some(minibrowser) = minibrowser.as_mut() { - window.set_toolbar_size(minibrowser.update(window.winit_window().unwrap())); + minibrowser.update(window.winit_window().unwrap()); + window.set_toolbar_size(minibrowser.toolbar_height.get()); } let ev_waker = events_loop.create_event_loop_waker(); diff --git a/ports/winit/headless_window.rs b/ports/winit/headless_window.rs index 0e91466c4c86..93a88de94e40 100644 --- a/ports/winit/headless_window.rs +++ b/ports/winit/headless_window.rs @@ -114,7 +114,7 @@ impl WindowPortsMethods for Window { } fn set_toolbar_size(&self, _height: f32) { - // Skip for now + unreachable!("only reachable in headed Window") } } From dda07d9561e50629bcfe670ee0c48d7d8f2b4077 Mon Sep 17 00:00:00 2001 From: Delan Azabani Date: Wed, 26 Jul 2023 15:56:01 +0800 Subject: [PATCH 16/42] winit: make App own the Minibrowser if any --- ports/winit/app.rs | 62 ++++++++++++++++++++++++++-------------------- 1 file changed, 35 insertions(+), 27 deletions(-) diff --git a/ports/winit/app.rs b/ports/winit/app.rs index e45376ce5539..29e8296e6a54 100644 --- a/ports/winit/app.rs +++ b/ports/winit/app.rs @@ -19,7 +19,7 @@ use servo::config::opts::{self, parse_url_or_filename}; use servo::servo_config::pref; use servo::servo_url::ServoUrl; use servo::Servo; -use std::cell::{Cell, RefCell}; +use std::cell::{Cell, RefCell, RefMut}; use std::collections::HashMap; use std::env; @@ -34,6 +34,7 @@ pub struct App { event_queue: RefCell>, suspended: Cell, windows: HashMap>, + minibrowser: Option>, } struct Minibrowser { @@ -98,33 +99,36 @@ impl App { servo: None, suspended: Cell::new(false), windows: HashMap::new(), + minibrowser: None, }; - // Make sure the gl context is made current. - let webrender_surfman = window.webrender_surfman(); - let webrender_gl = match webrender_surfman.connection().gl_api() { - GLApi::GL => unsafe { gl::GlFns::load_with(|s| webrender_surfman.get_proc_address(s)) }, - GLApi::GLES => unsafe { - gl::GlesFns::load_with(|s| webrender_surfman.get_proc_address(s)) - }, - }; - let gl = unsafe { - glow::Context::from_loader_function(|s| { - webrender_surfman.get_proc_address(s) - }) - }; - webrender_surfman.make_gl_context_current().unwrap(); - debug_assert_eq!(webrender_gl.get_error(), gleam::gl::NO_ERROR,); - - // Set up egui context for minibrowser ui - // Adapted from https://github.com/emilk/egui/blob/9478e50d012c5138551c38cbee16b07bc1fcf283/crates/egui_glow/examples/pure_glow.rs - let mut minibrowser = window.winit_window().map(|_| Minibrowser { - context: egui_glow::EguiGlow::new(events_loop.as_winit(), Arc::new(gl), None), - location: RefCell::new(ServoUrl::into_string(get_default_url())), - toolbar_height: 0f32.into(), - }); + if window.winit_window().is_some() { + // Make sure the gl context is made current. + let webrender_surfman = window.webrender_surfman(); + let webrender_gl = match webrender_surfman.connection().gl_api() { + GLApi::GL => unsafe { gl::GlFns::load_with(|s| webrender_surfman.get_proc_address(s)) }, + GLApi::GLES => unsafe { + gl::GlesFns::load_with(|s| webrender_surfman.get_proc_address(s)) + }, + }; + let gl = unsafe { + glow::Context::from_loader_function(|s| { + webrender_surfman.get_proc_address(s) + }) + }; + webrender_surfman.make_gl_context_current().unwrap(); + debug_assert_eq!(webrender_gl.get_error(), gleam::gl::NO_ERROR,); + + // Set up egui context for minibrowser ui + // Adapted from https://github.com/emilk/egui/blob/9478e50d012c5138551c38cbee16b07bc1fcf283/crates/egui_glow/examples/pure_glow.rs + app.minibrowser = Some(Minibrowser { + context: egui_glow::EguiGlow::new(events_loop.as_winit(), Arc::new(gl), None), + location: RefCell::new(ServoUrl::into_string(get_default_url())), + toolbar_height: 0f32.into(), + }.into()); + } - if let Some(minibrowser) = minibrowser.as_mut() { + if let Some(mut minibrowser) = app.minibrowser() { minibrowser.update(window.winit_window().unwrap()); window.set_toolbar_size(minibrowser.toolbar_height.get()); } @@ -183,7 +187,7 @@ impl App { // Handle the event let response = match e { winit::event::Event::WindowEvent { ref event, .. } => { - if let Some(minibrowser) = minibrowser.as_mut() { + if let Some(mut minibrowser) = app.minibrowser() { minibrowser.context.on_event(&event) } else { EventResponse { consumed: false, repaint: false } @@ -197,7 +201,7 @@ impl App { app.queue_embedder_events_for_winit_event(e); } if response.repaint { - minibrowser.as_mut().unwrap().update(window.winit_window().unwrap()); + app.minibrowser().unwrap().update(window.winit_window().unwrap()); } let animating = app.is_animating(); @@ -320,6 +324,10 @@ impl App { } false } + + fn minibrowser(&self) -> Option> { + self.minibrowser.as_ref().map(|x| x.borrow_mut()) + } } fn get_default_url() -> ServoUrl { From 6717cf03018603388d850ee3ceaa9c8eb93bd298 Mon Sep 17 00:00:00 2001 From: Delan Azabani Date: Wed, 26 Jul 2023 16:21:37 +0800 Subject: [PATCH 17/42] winit: make the go button work --- ports/winit/app.rs | 38 +++++++++++++++++++++++++++++++++----- ports/winit/browser.rs | 4 ++++ 2 files changed, 37 insertions(+), 5 deletions(-) diff --git a/ports/winit/app.rs b/ports/winit/app.rs index 29e8296e6a54..f8cffc9d062b 100644 --- a/ports/winit/app.rs +++ b/ports/winit/app.rs @@ -39,13 +39,14 @@ pub struct App { struct Minibrowser { context: egui_glow::EguiGlow, + event_queue: RefCell>, location: RefCell, toolbar_height: Cell, } impl Minibrowser { fn update(&mut self, window: &winit::window::Window) { - let Self { context, location, toolbar_height } = self; + let Self { context, event_queue, location, toolbar_height } = self; let _duration = context.run(window, |ctx| { TopBottomPanel::top("toolbar").show(ctx, |ui| { ui.allocate_ui_with_layout( @@ -53,8 +54,7 @@ impl Minibrowser { egui::Layout::right_to_left(egui::Align::Center), |ui| { if ui.button("go").clicked() { - // TODO go - dbg!("go clicked"); + event_queue.borrow_mut().push(MinibrowserEvent::Go); } ui.add_sized( ui.available_size(), @@ -70,6 +70,10 @@ impl Minibrowser { } } +enum MinibrowserEvent { + Go, +} + impl App { pub fn run( no_native_titlebar: bool, @@ -123,6 +127,7 @@ impl App { // Adapted from https://github.com/emilk/egui/blob/9478e50d012c5138551c38cbee16b07bc1fcf283/crates/egui_glow/examples/pure_glow.rs app.minibrowser = Some(Minibrowser { context: egui_glow::EguiGlow::new(events_loop.as_winit(), Arc::new(gl), None), + event_queue: RefCell::new(vec![]), location: RefCell::new(ServoUrl::into_string(get_default_url())), toolbar_height: 0f32.into(), }.into()); @@ -271,6 +276,26 @@ impl App { } } + /// Takes any outstanding events from the [Minibrowser], converting them to [EmbedderEvent] and + /// routing those to the App event queue. + fn queue_embedder_events_for_minibrowser_events(&self) { + if let Some(minibrowser) = self.minibrowser() { + for event in minibrowser.event_queue.borrow_mut().drain(..) { + match event { + MinibrowserEvent::Go => { + let browser_id = self.browser.borrow().browser_id().unwrap(); + let location = minibrowser.location.borrow(); + let Ok(url) = ServoUrl::parse(&location) else { + warn!("failed to parse location"); + break; + }; + self.event_queue.borrow_mut().push(EmbedderEvent::LoadUrl(browser_id, url)); + }, + } + } + } + } + /// Pumps events and messages between the embedder and Servo, where embedder events flow /// towards Servo and embedder messages flow away from Servo, and also runs the compositor. /// @@ -279,8 +304,6 @@ impl App { /// collect embedder messages from the various Servo components, then take them out of the /// Servo interface so that the Browser can handle them. fn handle_events(&mut self) -> bool { - let mut browser = self.browser.borrow_mut(); - // FIXME: // As of now, we support only one browser (self.browser) // but have multiple windows (dom.webxr.glwindow). We forward @@ -288,6 +311,11 @@ impl App { // browser instance. Pressing the "a" key on the glwindow // will send a key event to the servo window. + // Consume and handle any events from the Minibrowser. + self.queue_embedder_events_for_minibrowser_events(); + + let mut browser = self.browser.borrow_mut(); + // Take any outstanding embedder events from the App and its Windows. let mut embedder_events = self.get_events(); for (_win_id, window) in &self.windows { diff --git a/ports/winit/browser.rs b/ports/winit/browser.rs index d29b47a3ab0f..0d2e165091bd 100644 --- a/ports/winit/browser.rs +++ b/ports/winit/browser.rs @@ -72,6 +72,10 @@ where } } + pub fn browser_id(&self) -> Option { + self.browser_id + } + pub fn get_events(&mut self) -> Vec { std::mem::take(&mut self.event_queue) } From 8cd288e7914d38bd2b0101069d51c789c7459ac9 Mon Sep 17 00:00:00 2001 From: atbrakhi Date: Thu, 27 Jul 2023 15:50:11 +0200 Subject: [PATCH 18/42] winit:make the location field reflect the current top-level url --- ports/winit/app.rs | 19 +++++++++++++++---- ports/winit/browser.rs | 4 ++++ 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/ports/winit/app.rs b/ports/winit/app.rs index f8cffc9d062b..af38d08b0229 100644 --- a/ports/winit/app.rs +++ b/ports/winit/app.rs @@ -44,6 +44,10 @@ struct Minibrowser { toolbar_height: Cell, } +enum MinibrowserEvent { + Go, +} + impl Minibrowser { fn update(&mut self, window: &winit::window::Window) { let Self { context, event_queue, location, toolbar_height } = self; @@ -70,10 +74,6 @@ impl Minibrowser { } } -enum MinibrowserEvent { - Go, -} - impl App { pub fn run( no_native_titlebar: bool, @@ -296,6 +296,15 @@ impl App { } } + /// Updated the location in toolbar if browser history state has changed. + fn update_location_in_toolbar(&self) { + if let Some(mut minibrowser) = self.minibrowser() { + if let Some(current_url) = self.browser.borrow().current_top_level_url() { + minibrowser.location = RefCell::new(ServoUrl::into_string(current_url)); + } + } + } + /// Pumps events and messages between the embedder and Servo, where embedder events flow /// towards Servo and embedder messages flow away from Servo, and also runs the compositor. /// @@ -314,6 +323,8 @@ impl App { // Consume and handle any events from the Minibrowser. self.queue_embedder_events_for_minibrowser_events(); + self.update_location_in_toolbar(); + let mut browser = self.browser.borrow_mut(); // Take any outstanding embedder events from the App and its Windows. diff --git a/ports/winit/browser.rs b/ports/winit/browser.rs index 0d2e165091bd..fa30d5cf9db0 100644 --- a/ports/winit/browser.rs +++ b/ports/winit/browser.rs @@ -76,6 +76,10 @@ where self.browser_id } + pub fn current_top_level_url(&self) -> Option { + self.current_url.clone() + } + pub fn get_events(&mut self) -> Vec { std::mem::take(&mut self.event_queue) } From e8c4deafe7c5c18468b80194a724a40d1f040ad3 Mon Sep 17 00:00:00 2001 From: atbrakhi Date: Mon, 31 Jul 2023 13:24:23 +0200 Subject: [PATCH 19/42] winit: allow enabling minibrowser from command line --- ports/winit/app.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ports/winit/app.rs b/ports/winit/app.rs index af38d08b0229..4a5de924e7f1 100644 --- a/ports/winit/app.rs +++ b/ports/winit/app.rs @@ -106,7 +106,7 @@ impl App { minibrowser: None, }; - if window.winit_window().is_some() { + if opts::get().minibrowser && window.winit_window().is_some() { // Make sure the gl context is made current. let webrender_surfman = window.webrender_surfman(); let webrender_gl = match webrender_surfman.connection().gl_api() { From 0d9f487e5396c22f3b8fc0329c9b415e515e0b0c Mon Sep 17 00:00:00 2001 From: Delan Azabani Date: Thu, 3 Aug 2023 13:59:57 +0800 Subject: [PATCH 20/42] winit: tell compositor to repaint WR and flush when we repaint --- ports/winit/app.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/ports/winit/app.rs b/ports/winit/app.rs index 4a5de924e7f1..f03a0b553ff6 100644 --- a/ports/winit/app.rs +++ b/ports/winit/app.rs @@ -45,7 +45,11 @@ struct Minibrowser { } enum MinibrowserEvent { + /// Go button clicked. Go, + + /// Minibrowser repainted and needs glFlush. + Repaint, } impl Minibrowser { @@ -71,6 +75,7 @@ impl Minibrowser { toolbar_height.set(ctx.used_rect().height()); }); context.paint(window); + event_queue.borrow_mut().push(MinibrowserEvent::Repaint); } } @@ -291,6 +296,9 @@ impl App { }; self.event_queue.borrow_mut().push(EmbedderEvent::LoadUrl(browser_id, url)); }, + MinibrowserEvent::Repaint => { + self.event_queue.borrow_mut().push(EmbedderEvent::Refresh); + }, } } } From b4df0ac0eedf332c61729b99368712f904f98565 Mon Sep 17 00:00:00 2001 From: Delan Azabani Date: Thu, 3 Aug 2023 14:14:29 +0800 Subject: [PATCH 21/42] winit: fix bug where location field edits would get overridden --- ports/winit/app.rs | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/ports/winit/app.rs b/ports/winit/app.rs index f03a0b553ff6..71ced676e384 100644 --- a/ports/winit/app.rs +++ b/ports/winit/app.rs @@ -40,8 +40,11 @@ pub struct App { struct Minibrowser { context: egui_glow::EguiGlow, event_queue: RefCell>, - location: RefCell, toolbar_height: Cell, + location: RefCell, + + /// Whether the location has been edited by the user without clicking Go. + location_dirty: Cell, } enum MinibrowserEvent { @@ -54,7 +57,7 @@ enum MinibrowserEvent { impl Minibrowser { fn update(&mut self, window: &winit::window::Window) { - let Self { context, event_queue, location, toolbar_height } = self; + let Self { context, event_queue, location, location_dirty, toolbar_height } = self; let _duration = context.run(window, |ctx| { TopBottomPanel::top("toolbar").show(ctx, |ui| { ui.allocate_ui_with_layout( @@ -63,11 +66,14 @@ impl Minibrowser { |ui| { if ui.button("go").clicked() { event_queue.borrow_mut().push(MinibrowserEvent::Go); + location_dirty.set(false); } - ui.add_sized( + if ui.add_sized( ui.available_size(), egui::TextEdit::singleline(&mut *location.borrow_mut()), - ); + ).changed() { + location_dirty.set(true); + } }, ); }); @@ -133,8 +139,9 @@ impl App { app.minibrowser = Some(Minibrowser { context: egui_glow::EguiGlow::new(events_loop.as_winit(), Arc::new(gl), None), event_queue: RefCell::new(vec![]), - location: RefCell::new(ServoUrl::into_string(get_default_url())), toolbar_height: 0f32.into(), + location: RefCell::new(ServoUrl::into_string(get_default_url())), + location_dirty: false.into(), }.into()); } @@ -304,11 +311,13 @@ impl App { } } - /// Updated the location in toolbar if browser history state has changed. + /// Updates the location in toolbar if browser history state has changed. fn update_location_in_toolbar(&self) { if let Some(mut minibrowser) = self.minibrowser() { - if let Some(current_url) = self.browser.borrow().current_top_level_url() { - minibrowser.location = RefCell::new(ServoUrl::into_string(current_url)); + if !minibrowser.location_dirty.get() { + if let Some(current_url) = self.browser.borrow().current_top_level_url() { + minibrowser.location = RefCell::new(ServoUrl::into_string(current_url)); + } } } } From 8dfdf5723e06a4a6733b5198a8cd21874b00b981 Mon Sep 17 00:00:00 2001 From: Delan Azabani Date: Thu, 3 Aug 2023 17:40:40 +0800 Subject: [PATCH 22/42] winit: borrow the minibrowser once in App::handle_events --- ports/winit/app.rs | 49 ++++++++++++++++++++++------------------------ 1 file changed, 23 insertions(+), 26 deletions(-) diff --git a/ports/winit/app.rs b/ports/winit/app.rs index 71ced676e384..d7f7f3bf9bfe 100644 --- a/ports/winit/app.rs +++ b/ports/winit/app.rs @@ -290,34 +290,30 @@ impl App { /// Takes any outstanding events from the [Minibrowser], converting them to [EmbedderEvent] and /// routing those to the App event queue. - fn queue_embedder_events_for_minibrowser_events(&self) { - if let Some(minibrowser) = self.minibrowser() { - for event in minibrowser.event_queue.borrow_mut().drain(..) { - match event { - MinibrowserEvent::Go => { - let browser_id = self.browser.borrow().browser_id().unwrap(); - let location = minibrowser.location.borrow(); - let Ok(url) = ServoUrl::parse(&location) else { - warn!("failed to parse location"); - break; - }; - self.event_queue.borrow_mut().push(EmbedderEvent::LoadUrl(browser_id, url)); - }, - MinibrowserEvent::Repaint => { - self.event_queue.borrow_mut().push(EmbedderEvent::Refresh); - }, - } + fn queue_embedder_events_for_minibrowser_events(&self, minibrowser: &mut RefMut) { + for event in minibrowser.event_queue.borrow_mut().drain(..) { + match event { + MinibrowserEvent::Go => { + let browser_id = self.browser.borrow().browser_id().unwrap(); + let location = minibrowser.location.borrow(); + let Ok(url) = ServoUrl::parse(&location) else { + warn!("failed to parse location"); + break; + }; + self.event_queue.borrow_mut().push(EmbedderEvent::LoadUrl(browser_id, url)); + }, + MinibrowserEvent::Repaint => { + self.event_queue.borrow_mut().push(EmbedderEvent::Refresh); + }, } } } /// Updates the location in toolbar if browser history state has changed. - fn update_location_in_toolbar(&self) { - if let Some(mut minibrowser) = self.minibrowser() { - if !minibrowser.location_dirty.get() { - if let Some(current_url) = self.browser.borrow().current_top_level_url() { - minibrowser.location = RefCell::new(ServoUrl::into_string(current_url)); - } + fn update_location_in_toolbar(&self, minibrowser: &mut RefMut) { + if !minibrowser.location_dirty.get() { + if let Some(current_url) = self.browser.borrow().current_top_level_url() { + minibrowser.location = RefCell::new(ServoUrl::into_string(current_url)); } } } @@ -338,9 +334,10 @@ impl App { // will send a key event to the servo window. // Consume and handle any events from the Minibrowser. - self.queue_embedder_events_for_minibrowser_events(); - - self.update_location_in_toolbar(); + if let Some(mut minibrowser) = self.minibrowser() { + self.queue_embedder_events_for_minibrowser_events(&mut minibrowser); + self.update_location_in_toolbar(&mut minibrowser); + } let mut browser = self.browser.borrow_mut(); From bb5cbf85811de394127a6652855a2666f91b0901 Mon Sep 17 00:00:00 2001 From: Delan Azabani Date: Thu, 3 Aug 2023 17:58:15 +0800 Subject: [PATCH 23/42] winit: address todo about viewport origin coordinates --- ports/winit/headed_window.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ports/winit/headed_window.rs b/ports/winit/headed_window.rs index 503d09abf86e..e024af7ea473 100644 --- a/ports/winit/headed_window.rs +++ b/ports/winit/headed_window.rs @@ -537,7 +537,7 @@ impl WindowMethods for Window { // Get the height of toolbar for minibrowser let toolbar_height = self.toolbar_size.get(); - let viewport_origin = Point2D::new(0f32, toolbar_height * 0f32).to_i32(); // TODO this misbehaves + let viewport_origin = Point2D::new(0f32, 0f32).to_i32(); // bottom left let viewport_size = (Size2D::new(width as f32, height as f32 - toolbar_height) * dpr).to_i32(); let viewport = DeviceIntRect::new(viewport_origin, viewport_size); From 0ab250cbb4282934a2b5d74d34abdec960f65d88 Mon Sep 17 00:00:00 2001 From: Delan Azabani Date: Fri, 4 Aug 2023 10:15:06 +0800 Subject: [PATCH 24/42] winit: fix some minor problems with comments and errors --- ports/winit/app.rs | 3 +-- ports/winit/headed_window.rs | 11 ++++++----- ports/winit/headless_window.rs | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/ports/winit/app.rs b/ports/winit/app.rs index d7f7f3bf9bfe..1b75ea1086c8 100644 --- a/ports/winit/app.rs +++ b/ports/winit/app.rs @@ -309,7 +309,7 @@ impl App { } } - /// Updates the location in toolbar if browser history state has changed. + /// Updates the location field, if the user hasn’t started editing it. fn update_location_in_toolbar(&self, minibrowser: &mut RefMut) { if !minibrowser.location_dirty.get() { if let Some(current_url) = self.browser.borrow().current_top_level_url() { @@ -388,7 +388,6 @@ fn get_default_url() -> ServoUrl { // or a blank page in case the homepage is not set either. let cwd = env::current_dir().unwrap(); let cmdline_url = opts::get().url.clone(); - let pref_url = { let homepage_url = pref!(shell.homepage); parse_url_or_filename(&cwd, &homepage_url).ok() diff --git a/ports/winit/headed_window.rs b/ports/winit/headed_window.rs index e024af7ea473..d2fe1cfbe3d9 100644 --- a/ports/winit/headed_window.rs +++ b/ports/winit/headed_window.rs @@ -156,7 +156,7 @@ impl Window { device_pixels_per_px, xr_window_poses: RefCell::new(vec![]), modifiers_state: Cell::new(ModifiersState::empty()), - toolbar_size: Cell::new(0.0), // Initial value + toolbar_size: Cell::new(0.0), } } @@ -535,11 +535,12 @@ impl WindowMethods for Window { .winit_window .inner_size(); - // Get the height of toolbar for minibrowser + // Subtract the minibrowser toolbar height if any let toolbar_height = self.toolbar_size.get(); - let viewport_origin = Point2D::new(0f32, 0f32).to_i32(); // bottom left - let viewport_size = (Size2D::new(width as f32, height as f32 - toolbar_height) * dpr).to_i32(); - let viewport = DeviceIntRect::new(viewport_origin, viewport_size); + let inner_size = Size2D::new(width as f32, height as f32) * dpr; + let viewport_size = inner_size - Size2D::new(0f32, toolbar_height); + let viewport_origin = DeviceIntPoint::zero(); // bottom left + let viewport = DeviceIntRect::new(viewport_origin, viewport_size.to_i32()); let framebuffer = DeviceIntSize::from_untyped(viewport.size.to_untyped()); EmbedderCoordinates { diff --git a/ports/winit/headless_window.rs b/ports/winit/headless_window.rs index 93a88de94e40..d26a1a9ef6d6 100644 --- a/ports/winit/headless_window.rs +++ b/ports/winit/headless_window.rs @@ -114,7 +114,7 @@ impl WindowPortsMethods for Window { } fn set_toolbar_size(&self, _height: f32) { - unreachable!("only reachable in headed Window") + unimplemented!("headless Window only") } } From bbc658799897d3168e75bc3fe71a5ebce6b405f9 Mon Sep 17 00:00:00 2001 From: Delan Azabani Date: Fri, 4 Aug 2023 10:32:58 +0800 Subject: [PATCH 25/42] winit: update location field once per HistoryChanged event --- ports/winit/app.rs | 5 +++-- ports/winit/browser.rs | 14 ++++++++++++-- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/ports/winit/app.rs b/ports/winit/app.rs index 1b75ea1086c8..b472182fe92d 100644 --- a/ports/winit/app.rs +++ b/ports/winit/app.rs @@ -309,10 +309,11 @@ impl App { } } - /// Updates the location field, if the user hasn’t started editing it. + /// Updates the location field when the [Browser] says it has changed, unless the user has + /// started editing it without clicking Go. fn update_location_in_toolbar(&self, minibrowser: &mut RefMut) { if !minibrowser.location_dirty.get() { - if let Some(current_url) = self.browser.borrow().current_top_level_url() { + if let Some(current_url) = self.browser.borrow_mut().take_top_level_url_change() { minibrowser.location = RefCell::new(ServoUrl::into_string(current_url)); } } diff --git a/ports/winit/browser.rs b/ports/winit/browser.rs index fa30d5cf9db0..5d7afabd07f5 100644 --- a/ports/winit/browser.rs +++ b/ports/winit/browser.rs @@ -31,6 +31,8 @@ use tinyfiledialogs::{self, MessageBoxIcon, OkCancel, YesNo}; pub struct Browser { current_url: Option, + current_url_taken: bool, + /// id of the top level browsing context. It is unique as tabs /// are not supported yet. None until created. browser_id: Option, @@ -57,6 +59,7 @@ where Browser { title: None, current_url: None, + current_url_taken: false, browser_id: None, browsers: Vec::new(), window, @@ -76,8 +79,14 @@ where self.browser_id } - pub fn current_top_level_url(&self) -> Option { - self.current_url.clone() + /// Returns current_url iff there has been a HistoryChanged event since the last call. + pub fn take_top_level_url_change(&mut self) -> Option { + if self.current_url_taken { + None + } else { + self.current_url_taken = true; + self.current_url.clone() + } } pub fn get_events(&mut self) -> Vec { @@ -445,6 +454,7 @@ where }, EmbedderMsg::HistoryChanged(urls, current) => { self.current_url = Some(urls[current].clone()); + self.current_url_taken = false; }, EmbedderMsg::SetFullscreenState(state) => { self.window.set_fullscreen(state); From 728a41f32209dcdaa5a0054f351577c21cf0369b Mon Sep 17 00:00:00 2001 From: Delan Azabani Date: Fri, 4 Aug 2023 12:36:05 +0800 Subject: [PATCH 26/42] winit: rename Window::set_toolbar_size to set_toolbar_height --- ports/winit/app.rs | 2 +- ports/winit/headed_window.rs | 10 +++++----- ports/winit/headless_window.rs | 2 +- ports/winit/window_trait.rs | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/ports/winit/app.rs b/ports/winit/app.rs index b472182fe92d..6a23689542a7 100644 --- a/ports/winit/app.rs +++ b/ports/winit/app.rs @@ -147,7 +147,7 @@ impl App { if let Some(mut minibrowser) = app.minibrowser() { minibrowser.update(window.winit_window().unwrap()); - window.set_toolbar_size(minibrowser.toolbar_height.get()); + window.set_toolbar_height(minibrowser.toolbar_height.get()); } let ev_waker = events_loop.create_event_loop_waker(); diff --git a/ports/winit/headed_window.rs b/ports/winit/headed_window.rs index d2fe1cfbe3d9..5584edbbc49b 100644 --- a/ports/winit/headed_window.rs +++ b/ports/winit/headed_window.rs @@ -52,7 +52,7 @@ pub struct Window { webrender_surfman: WebrenderSurfman, screen_size: Size2D, inner_size: Cell>, - toolbar_size: Cell, + toolbar_height: Cell, mouse_down_button: Cell>, mouse_down_point: Cell>, primary_monitor: winit::monitor::MonitorHandle, @@ -156,7 +156,7 @@ impl Window { device_pixels_per_px, xr_window_poses: RefCell::new(vec![]), modifiers_state: Cell::new(ModifiersState::empty()), - toolbar_size: Cell::new(0.0), + toolbar_height: Cell::new(0.0), } } @@ -510,8 +510,8 @@ impl WindowPortsMethods for Window { Some(&self.winit_window) } - fn set_toolbar_size(&self, height: f32) { - self.toolbar_size.set(height); + fn set_toolbar_height(&self, height: f32) { + self.toolbar_height.set(height); } } @@ -536,7 +536,7 @@ impl WindowMethods for Window { .inner_size(); // Subtract the minibrowser toolbar height if any - let toolbar_height = self.toolbar_size.get(); + let toolbar_height = self.toolbar_height.get(); let inner_size = Size2D::new(width as f32, height as f32) * dpr; let viewport_size = inner_size - Size2D::new(0f32, toolbar_height); let viewport_origin = DeviceIntPoint::zero(); // bottom left diff --git a/ports/winit/headless_window.rs b/ports/winit/headless_window.rs index d26a1a9ef6d6..ad8d29011fd5 100644 --- a/ports/winit/headless_window.rs +++ b/ports/winit/headless_window.rs @@ -113,7 +113,7 @@ impl WindowPortsMethods for Window { None } - fn set_toolbar_size(&self, _height: f32) { + fn set_toolbar_height(&self, _height: f32) { unimplemented!("headless Window only") } } diff --git a/ports/winit/window_trait.rs b/ports/winit/window_trait.rs index f0db06520769..8f780735c234 100644 --- a/ports/winit/window_trait.rs +++ b/ports/winit/window_trait.rs @@ -32,5 +32,5 @@ pub trait WindowPortsMethods: WindowMethods { events_loop: &winit::event_loop::EventLoopWindowTarget ) -> Box; fn winit_window(&self) -> Option<&winit::window::Window>; - fn set_toolbar_size(&self, height: f32); + fn set_toolbar_height(&self, height: f32); } From 3e56ccb3e9f4a8d102b820f23e40c770505d9a05 Mon Sep 17 00:00:00 2001 From: Delan Azabani Date: Fri, 4 Aug 2023 12:37:10 +0800 Subject: [PATCH 27/42] winit: take toolbar height into account in hit testing --- ports/winit/headed_window.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/ports/winit/headed_window.rs b/ports/winit/headed_window.rs index 5584edbbc49b..60d008ff72ba 100644 --- a/ports/winit/headed_window.rs +++ b/ports/winit/headed_window.rs @@ -406,8 +406,9 @@ impl WindowPortsMethods for Window { } }, winit::event::WindowEvent::CursorMoved { position, .. } => { - let (x, y): (i32, i32) = position.into(); - self.mouse_pos.set(Point2D::new(x, y)); + let (x, y): (f64, f64) = position.into(); + let y = y - f64::from(self.toolbar_height.get()); + self.mouse_pos.set(Point2D::new(x, y).to_i32()); self.event_queue .borrow_mut() .push(EmbedderEvent::MouseWindowMoveEventClass(Point2D::new( From ffc971de935aa90979213db8adc8472251e82ecc Mon Sep 17 00:00:00 2001 From: Delan Azabani Date: Tue, 8 Aug 2023 17:29:59 +0800 Subject: [PATCH 28/42] winit: pass egui only relevant CursorMoved events --- ports/winit/app.rs | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/ports/winit/app.rs b/ports/winit/app.rs index 6a23689542a7..114cac763ce4 100644 --- a/ports/winit/app.rs +++ b/ports/winit/app.rs @@ -10,7 +10,6 @@ use crate::events_loop::{EventsLoop, WakerEvent}; use crate::window_trait::WindowPortsMethods; use crate::{headed_window, headless_window}; use egui::TopBottomPanel; -use egui_winit::EventResponse; use gleam::gl; use winit::window::WindowId; use winit::event_loop::EventLoopWindowTarget; @@ -202,24 +201,27 @@ impl App { } // Handle the event - let response = match e { - winit::event::Event::WindowEvent { ref event, .. } => { - if let Some(mut minibrowser) = app.minibrowser() { - minibrowser.context.on_event(&event) - } else { - EventResponse { consumed: false, repaint: false } + if let Some(mut minibrowser) = app.minibrowser() { + if let winit::event::Event::WindowEvent { ref event, .. } = e { + if match event { + winit::event::WindowEvent::CursorMoved { position, .. } + => position.y < minibrowser.toolbar_height.get().into(), + _ => true, + } { + let response = minibrowser.context.on_event(&event); + if response.repaint { + minibrowser.update(window.winit_window().unwrap()); + } + + // TODO how do we handle the tab key? (see doc for consumed) + if !response.consumed { + app.queue_embedder_events_for_winit_event(e); + } } } - _ => EventResponse { consumed: false, repaint: false }, - }; - - // TODO how do we handle the tab key? (see doc for consumed) - if !response.consumed { + } else { app.queue_embedder_events_for_winit_event(e); } - if response.repaint { - app.minibrowser().unwrap().update(window.winit_window().unwrap()); - } let animating = app.is_animating(); From 62ec187c2d8f89957f64c10a2cd1320ef47ef145 Mon Sep 17 00:00:00 2001 From: Delan Azabani Date: Tue, 8 Aug 2023 18:01:58 +0800 Subject: [PATCH 29/42] winit: scratch that, coalesce minibrowser updates instead --- ports/winit/app.rs | 117 ++++++++++++++++++++++++--------------------- 1 file changed, 63 insertions(+), 54 deletions(-) diff --git a/ports/winit/app.rs b/ports/winit/app.rs index 114cac763ce4..377a52674509 100644 --- a/ports/winit/app.rs +++ b/ports/winit/app.rs @@ -151,47 +151,60 @@ impl App { let ev_waker = events_loop.create_event_loop_waker(); events_loop.run_forever(move |e, w, control_flow| { - if let winit::event::Event::NewEvents(winit::event::StartCause::Init) = e { - let surfman = window.webrender_surfman(); + match e { + winit::event::Event::NewEvents(winit::event::StartCause::Init) => { + let surfman = window.webrender_surfman(); + + let xr_discovery = if pref!(dom.webxr.glwindow.enabled) && ! opts::get().headless { + let window = window.clone(); + // This should be safe because run_forever does, in fact, + // run forever. The event loop window target doesn't get + // moved, and does outlast this closure, and we won't + // ever try to make use of it once shutdown begins and + // it stops being valid. + let w = unsafe { + std::mem::transmute::< + &EventLoopWindowTarget, + &'static EventLoopWindowTarget + >(w.unwrap()) + }; + let factory = Box::new(move || Ok(window.new_glwindow(w))); + Some(GlWindowDiscovery::new( + surfman.connection(), + surfman.adapter(), + surfman.context_attributes(), + factory, + )) + } else { + None + }; - let xr_discovery = if pref!(dom.webxr.glwindow.enabled) && ! opts::get().headless { let window = window.clone(); - // This should be safe because run_forever does, in fact, - // run forever. The event loop window target doesn't get - // moved, and does outlast this closure, and we won't - // ever try to make use of it once shutdown begins and - // it stops being valid. - let w = unsafe { - std::mem::transmute::< - &EventLoopWindowTarget, - &'static EventLoopWindowTarget - >(w.unwrap()) - }; - let factory = Box::new(move || Ok(window.new_glwindow(w))); - Some(GlWindowDiscovery::new( - surfman.connection(), - surfman.adapter(), - surfman.context_attributes(), - factory, - )) - } else { - None - }; - - let window = window.clone(); - // Implements embedder methods, used by libservo and constellation. - let embedder = Box::new(EmbedderCallbacks::new( - ev_waker.clone(), - xr_discovery, - )); - - let servo_data = Servo::new(embedder, window.clone(), user_agent.clone()); - let mut servo = servo_data.servo; - servo.handle_events(vec![EmbedderEvent::NewBrowser(get_default_url(), servo_data.browser_id)]); - servo.setup_logging(); - - app.windows.insert(window.id(), window.clone()); - app.servo = Some(servo); + // Implements embedder methods, used by libservo and constellation. + let embedder = Box::new(EmbedderCallbacks::new( + ev_waker.clone(), + xr_discovery, + )); + + let servo_data = Servo::new(embedder, window.clone(), user_agent.clone()); + let mut servo = servo_data.servo; + servo.handle_events(vec![EmbedderEvent::NewBrowser(get_default_url(), servo_data.browser_id)]); + servo.setup_logging(); + + app.windows.insert(window.id(), window.clone()); + app.servo = Some(servo); + } + + // TODO does windows still need this workaround? + // https://github.com/emilk/egui/blob/9478e50d012c5138551c38cbee16b07bc1fcf283/crates/egui_glow/examples/pure_glow.rs#L203 + // winit::event::Event::RedrawEventsCleared => todo!(), + winit::event::Event::RedrawRequested(_) => { + if let Some(mut minibrowser) = app.minibrowser() { + minibrowser.update(window.winit_window().unwrap()); + } + } + + _ => {} } // If self.servo is None here, it means that we're in the process of shutting down, @@ -201,25 +214,21 @@ impl App { } // Handle the event + let mut consumed = false; if let Some(mut minibrowser) = app.minibrowser() { if let winit::event::Event::WindowEvent { ref event, .. } = e { - if match event { - winit::event::WindowEvent::CursorMoved { position, .. } - => position.y < minibrowser.toolbar_height.get().into(), - _ => true, - } { - let response = minibrowser.context.on_event(&event); - if response.repaint { - minibrowser.update(window.winit_window().unwrap()); - } - - // TODO how do we handle the tab key? (see doc for consumed) - if !response.consumed { - app.queue_embedder_events_for_winit_event(e); - } + let response = minibrowser.context.on_event(&event); + if response.repaint { + // Request a redraw event that will in turn trigger a minibrowser update. + // This allows us to coalesce minibrowser updates across multiple events. + window.winit_window().unwrap().request_redraw(); } + + // TODO how do we handle the tab key? (see doc for consumed) + consumed = response.consumed; } - } else { + } + if !consumed { app.queue_embedder_events_for_winit_event(e); } From d1ea04177aebe1fb11f8f31e2221093ffeb5c293 Mon Sep 17 00:00:00 2001 From: Delan Azabani Date: Wed, 9 Aug 2023 20:50:56 +0800 Subject: [PATCH 30/42] ensure both minibrowser and WR are repainted on every frame --- components/compositing/compositor.rs | 37 ++++++- components/compositing/lib.rs | 3 + components/constellation/constellation.rs | 6 ++ components/embedder_traits/lib.rs | 3 + components/servo/lib.rs | 8 ++ ports/winit/app.rs | 89 ++++++++++----- ports/winit/browser.rs | 9 +- ports/winit/egui_glue.rs | 125 ++++++++++++++++++++++ ports/winit/main2.rs | 1 + 9 files changed, 251 insertions(+), 30 deletions(-) create mode 100644 ports/winit/egui_glue.rs diff --git a/components/compositing/compositor.rs b/components/compositing/compositor.rs index 4340d59bbd10..d98d83ad6640 100644 --- a/components/compositing/compositor.rs +++ b/components/compositing/compositor.rs @@ -230,6 +230,13 @@ pub struct IOCompositor { /// taken before the render is complete will not reflect the /// most up to date rendering. waiting_on_pending_frame: bool, + + /// Whether to send a ReadyToPresent message to the constellation after rendering a new frame, + /// allowing external code to draw to the framebuffer and decide when to present the frame. + external_present: bool, + + /// Waiting for external code to call present. + waiting_on_present: bool, } #[derive(Clone, Copy)] @@ -382,6 +389,8 @@ impl IOCompositor { exit_after_load, convert_mouse_to_touch, waiting_on_pending_frame: false, + external_present: false, + waiting_on_present: false, } } @@ -1525,6 +1534,12 @@ impl IOCompositor { target: CompositeTarget, rect: Option>, ) -> Result, UnableToComposite> { + if self.waiting_on_present { + return Err(UnableToComposite::NotReadyToPaintImage( + NotReadyToPaint::WaitingOnConstellation, + )); + } + let size = self.embedder_coordinates.framebuffer.to_u32(); if let Err(err) = self.webrender_surfman.make_gl_context_current() { @@ -1703,8 +1718,15 @@ impl IOCompositor { }; // Perform the page flip. This will likely block for a while. - if let Err(err) = self.webrender_surfman.present() { - warn!("Failed to present surface: {:?}", err); + if self.external_present { + self.waiting_on_present = true; + let msg = + ConstellationMsg::ReadyToPresent(self.root_pipeline.top_level_browsing_context_id); + if let Err(e) = self.constellation_chan.send(msg) { + warn!("Sending event to constellation failed ({:?}).", e); + } + } else { + self.present(); } self.composition_request = CompositionRequest::NoCompositingNecessary; @@ -1715,6 +1737,13 @@ impl IOCompositor { Ok(rv) } + pub fn present(&mut self) { + if let Err(err) = self.webrender_surfman.present() { + warn!("Failed to present surface: {:?}", err); + } + self.waiting_on_present = false; + } + fn composite_if_necessary(&mut self, reason: CompositingReason) { if self.composition_request == CompositionRequest::NoCompositingNecessary { if self.is_running_problem_test { @@ -1914,6 +1943,10 @@ impl IOCompositor { None => eprintln!("Unable to locate path to save captures"), } } + + pub fn set_external_present(&mut self, value: bool) { + self.external_present = value; + } } /// Why we performed a composite. This is used for debugging. diff --git a/components/compositing/lib.rs b/components/compositing/lib.rs index 4f29cfc16621..554f36df8334 100644 --- a/components/compositing/lib.rs +++ b/components/compositing/lib.rs @@ -109,6 +109,8 @@ pub enum ConstellationMsg { ChangeBrowserVisibility(TopLevelBrowsingContextId, bool), /// Virtual keyboard was dismissed IMEDismissed, + /// Compositing done, but external code needs to present. + ReadyToPresent(TopLevelBrowsingContextId), } impl fmt::Debug for ConstellationMsg { @@ -142,6 +144,7 @@ impl fmt::Debug for ConstellationMsg { ChangeBrowserVisibility(..) => "ChangeBrowserVisibility", IMEDismissed => "IMEDismissed", ClearCache => "ClearCache", + ReadyToPresent(..) => "ReadyToPresent", }; write!(formatter, "ConstellationMsg::{}", variant) } diff --git a/components/constellation/constellation.rs b/components/constellation/constellation.rs index 5982f5ce76d1..cf4ca3eb41bc 100644 --- a/components/constellation/constellation.rs +++ b/components/constellation/constellation.rs @@ -1551,6 +1551,12 @@ where FromCompositorMsg::ChangeBrowserVisibility(top_level_browsing_context_id, visible) => { self.handle_change_browser_visibility(top_level_browsing_context_id, visible); }, + FromCompositorMsg::ReadyToPresent(top_level_browsing_context_id) => { + self.embedder_proxy.send(( + Some(top_level_browsing_context_id), + EmbedderMsg::ReadyToPresent, + )); + }, } } diff --git a/components/embedder_traits/lib.rs b/components/embedder_traits/lib.rs index 8654732735d3..da117823340f 100644 --- a/components/embedder_traits/lib.rs +++ b/components/embedder_traits/lib.rs @@ -212,6 +212,8 @@ pub enum EmbedderMsg { MediaSessionEvent(MediaSessionEvent), /// Report the status of Devtools Server with a token that can be used to bypass the permission prompt. OnDevtoolsStarted(Result, String), + /// Compositing done, but external code needs to present. + ReadyToPresent, } impl Debug for EmbedderMsg { @@ -248,6 +250,7 @@ impl Debug for EmbedderMsg { EmbedderMsg::MediaSessionEvent(..) => write!(f, "MediaSessionEvent"), EmbedderMsg::OnDevtoolsStarted(..) => write!(f, "OnDevtoolsStarted"), EmbedderMsg::ShowContextMenu(..) => write!(f, "ShowContextMenu"), + EmbedderMsg::ReadyToPresent => write!(f, "ReadyToPresent"), } } } diff --git a/components/servo/lib.rs b/components/servo/lib.rs index 0738452b1627..6aeb7807b8ce 100644 --- a/components/servo/lib.rs +++ b/components/servo/lib.rs @@ -796,6 +796,14 @@ where pub fn deinit(self) { self.compositor.deinit(); } + + pub fn set_external_present(&mut self, value: bool) { + self.compositor.set_external_present(value) + } + + pub fn present(&mut self) { + self.compositor.present(); + } } fn create_embedder_channel( diff --git a/ports/winit/app.rs b/ports/winit/app.rs index 377a52674509..deea2dd19075 100644 --- a/ports/winit/app.rs +++ b/ports/winit/app.rs @@ -5,11 +5,12 @@ //! Application entry point, runs the event loop. use crate::browser::Browser; +use crate::egui_glue; use crate::embedder::EmbedderCallbacks; use crate::events_loop::{EventsLoop, WakerEvent}; use crate::window_trait::WindowPortsMethods; use crate::{headed_window, headless_window}; -use egui::TopBottomPanel; +use egui::{TopBottomPanel, Rect, Pos2, Vec2, Sense}; use gleam::gl; use winit::window::WindowId; use winit::event_loop::EventLoopWindowTarget; @@ -37,7 +38,7 @@ pub struct App { } struct Minibrowser { - context: egui_glow::EguiGlow, + context: egui_glue::EguiGlow, event_queue: RefCell>, toolbar_height: Cell, location: RefCell, @@ -49,12 +50,16 @@ struct Minibrowser { enum MinibrowserEvent { /// Go button clicked. Go, +} - /// Minibrowser repainted and needs glFlush. - Repaint, +/// Action to be taken by the caller of [`App::handle_events`]. +enum PumpResult { + Shutdown, + Present, } impl Minibrowser { + /// Update the minibrowser, but don’t paint. fn update(&mut self, window: &winit::window::Window) { let Self { context, event_queue, location, location_dirty, toolbar_height } = self; let _duration = context.run(window, |ctx| { @@ -79,8 +84,11 @@ impl Minibrowser { toolbar_height.set(ctx.used_rect().height()); }); - context.paint(window); - event_queue.borrow_mut().push(MinibrowserEvent::Repaint); + } + + /// Paint the minibrowser, as of the last update. + fn paint(&mut self, window: &winit::window::Window) { + self.context.paint(window); } } @@ -136,7 +144,7 @@ impl App { // Set up egui context for minibrowser ui // Adapted from https://github.com/emilk/egui/blob/9478e50d012c5138551c38cbee16b07bc1fcf283/crates/egui_glow/examples/pure_glow.rs app.minibrowser = Some(Minibrowser { - context: egui_glow::EguiGlow::new(events_loop.as_winit(), Arc::new(gl), None), + context: egui_glue::EguiGlow::new(events_loop.as_winit(), Arc::new(gl), None), event_queue: RefCell::new(vec![]), toolbar_height: 0f32.into(), location: RefCell::new(ServoUrl::into_string(get_default_url())), @@ -188,6 +196,11 @@ impl App { let servo_data = Servo::new(embedder, window.clone(), user_agent.clone()); let mut servo = servo_data.servo; + + // If we have a minibrowser, ask the compositor to notify us when a new frame + // is ready to present, so that we can paint the minibrowser then present. + servo.set_external_present(app.minibrowser.is_some()); + servo.handle_events(vec![EmbedderEvent::NewBrowser(get_default_url(), servo_data.browser_id)]); servo.setup_logging(); @@ -201,6 +214,10 @@ impl App { winit::event::Event::RedrawRequested(_) => { if let Some(mut minibrowser) = app.minibrowser() { minibrowser.update(window.winit_window().unwrap()); + + // Tell Servo to repaint, which will in turn allow us to repaint the + // minibrowser and present a complete frame without partial updates. + app.event_queue.borrow_mut().push(EmbedderEvent::Refresh); } } @@ -241,10 +258,28 @@ impl App { *control_flow = winit::event_loop::ControlFlow::Poll; } - let stop = app.handle_events(); - if stop { - *control_flow = winit::event_loop::ControlFlow::Exit; - app.servo.take().unwrap().deinit(); + // Consume and handle any events from the Minibrowser. + if let Some(mut minibrowser) = app.minibrowser() { + app.queue_embedder_events_for_minibrowser_events(&mut minibrowser); + if app.update_location_in_toolbar(&mut minibrowser) { + // Update the minibrowser immediately. While we could update by requesting a + // redraw, doing so would delay the location update by two frames. + minibrowser.update(window.winit_window().unwrap()); + } + } + + match app.handle_events() { + Some(PumpResult::Shutdown) => { + *control_flow = winit::event_loop::ControlFlow::Exit; + app.servo.take().unwrap().deinit(); + }, + Some(PumpResult::Present) => { + if let Some(mut minibrowser) = app.minibrowser() { + minibrowser.paint(window.winit_window().unwrap()); + } + app.servo.as_mut().unwrap().present(); + }, + None => {}, } }); } @@ -313,21 +348,21 @@ impl App { }; self.event_queue.borrow_mut().push(EmbedderEvent::LoadUrl(browser_id, url)); }, - MinibrowserEvent::Repaint => { - self.event_queue.borrow_mut().push(EmbedderEvent::Refresh); - }, } } } /// Updates the location field when the [Browser] says it has changed, unless the user has /// started editing it without clicking Go. - fn update_location_in_toolbar(&self, minibrowser: &mut RefMut) { + fn update_location_in_toolbar(&self, minibrowser: &mut RefMut) -> bool { if !minibrowser.location_dirty.get() { if let Some(current_url) = self.browser.borrow_mut().take_top_level_url_change() { minibrowser.location = RefCell::new(ServoUrl::into_string(current_url)); + return true; } } + + false } /// Pumps events and messages between the embedder and Servo, where embedder events flow @@ -337,7 +372,9 @@ impl App { /// Window queues to the Browser queue, and from the Browser queue to Servo. We receive and /// collect embedder messages from the various Servo components, then take them out of the /// Servo interface so that the Browser can handle them. - fn handle_events(&mut self) -> bool { + fn handle_events(&mut self) -> Option { + let mut browser = self.browser.borrow_mut(); + // FIXME: // As of now, we support only one browser (self.browser) // but have multiple windows (dom.webxr.glwindow). We forward @@ -345,14 +382,6 @@ impl App { // browser instance. Pressing the "a" key on the glwindow // will send a key event to the servo window. - // Consume and handle any events from the Minibrowser. - if let Some(mut minibrowser) = self.minibrowser() { - self.queue_embedder_events_for_minibrowser_events(&mut minibrowser); - self.update_location_in_toolbar(&mut minibrowser); - } - - let mut browser = self.browser.borrow_mut(); - // Take any outstanding embedder events from the App and its Windows. let mut embedder_events = self.get_events(); for (_win_id, window) in &self.windows { @@ -365,16 +394,17 @@ impl App { // Take any new embedder messages from Servo itself. let mut embedder_messages = self.servo.as_mut().unwrap().get_events(); let mut need_resize = false; + let mut need_present = false; loop { // Consume and handle those embedder messages. - browser.handle_servo_events(embedder_messages); + need_present |= browser.handle_servo_events(embedder_messages); // Route embedder events from the Browser to the relevant Servo components, // receives and collects embedder messages from various Servo components, // and runs the compositor. need_resize |= self.servo.as_mut().unwrap().handle_events(browser.get_events()); if browser.shutdown_requested() { - return true; + return Some(PumpResult::Shutdown); } // Take any new embedder messages from Servo itself. @@ -386,8 +416,13 @@ impl App { if need_resize { self.servo.as_mut().unwrap().repaint_synchronously(); + need_present = true; + } + if need_present { + Some(PumpResult::Present) + } else { + None } - false } fn minibrowser(&self) -> Option> { diff --git a/ports/winit/browser.rs b/ports/winit/browser.rs index 5d7afabd07f5..c298ffeb1764 100644 --- a/ports/winit/browser.rs +++ b/ports/winit/browser.rs @@ -281,7 +281,8 @@ where self.event_queue.push(event); } - pub fn handle_servo_events(&mut self, events: Vec<(Option, EmbedderMsg)>) { + pub fn handle_servo_events(&mut self, events: Vec<(Option, EmbedderMsg)>) -> bool { + let mut need_present = false; for (browser_id, msg) in events { match msg { EmbedderMsg::Status(_status) => { @@ -529,8 +530,14 @@ where EmbedderMsg::ShowContextMenu(sender, ..) => { let _ = sender.send(ContextMenuResult::Ignored); }, + EmbedderMsg::ReadyToPresent => { + // eprintln!("ReadyToPresent"); + need_present = true; + }, } } + + need_present } } diff --git a/ports/winit/egui_glue.rs b/ports/winit/egui_glue.rs new file mode 100644 index 000000000000..8af0329819e9 --- /dev/null +++ b/ports/winit/egui_glue.rs @@ -0,0 +1,125 @@ +//! A modified version of EguiGlow [from egui_glow 0.22.0][0] that retains its shapes, +//! allowing [`EguiGlow::paint`] to be called multiple times. +//! +//! [0]: https://github.com/emilk/egui/blob/0.22.0/crates/egui_glow/src/winit.rs + +// Copyright (c) 2018-2021 Emil Ernerfeldt +// +// Permission is hereby granted, free of charge, to any +// person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the +// Software without restriction, including without +// limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software +// is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice +// shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +// IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +use egui_glow::ShaderVersion; +pub use egui_winit; +use egui_winit::winit; +pub use egui_winit::EventResponse; + +/// Use [`egui`] from a [`glow`] app based on [`winit`]. +pub struct EguiGlow { + pub egui_ctx: egui::Context, + pub egui_winit: egui_winit::State, + pub painter: egui_glow::Painter, + + shapes: Vec, + textures_delta: egui::TexturesDelta, +} + +impl EguiGlow { + /// For automatic shader version detection set `shader_version` to `None`. + pub fn new( + event_loop: &winit::event_loop::EventLoopWindowTarget, + gl: std::sync::Arc, + shader_version: Option, + ) -> Self { + let painter = egui_glow::Painter::new(gl, "", shader_version) + .map_err(|err| { + log::error!("error occurred in initializing painter:\n{err}"); + }) + .unwrap(); + + Self { + egui_ctx: Default::default(), + egui_winit: egui_winit::State::new(event_loop), + painter, + shapes: Default::default(), + textures_delta: Default::default(), + } + } + + pub fn on_event(&mut self, event: &winit::event::WindowEvent<'_>) -> EventResponse { + self.egui_winit.on_event(&self.egui_ctx, event) + } + + /// Returns the `Duration` of the timeout after which egui should be repainted even if there's no new events. + /// + /// Call [`Self::paint`] later to paint. + pub fn run( + &mut self, + window: &winit::window::Window, + run_ui: impl FnMut(&egui::Context), + ) -> std::time::Duration { + let raw_input = self.egui_winit.take_egui_input(window); + let egui::FullOutput { + platform_output, + repaint_after, + textures_delta, + shapes, + } = self.egui_ctx.run(raw_input, run_ui); + + self.egui_winit + .handle_platform_output(window, &self.egui_ctx, platform_output); + + self.shapes = shapes; + self.textures_delta.append(textures_delta); + repaint_after + } + + /// Paint the results of the last call to [`Self::run`]. + pub fn paint(&mut self, window: &winit::window::Window) { + /////// let shapes = std::mem::take(&mut self.shapes); + let shapes = &self.shapes; + let mut textures_delta = std::mem::take(&mut self.textures_delta); + + for (id, image_delta) in textures_delta.set { + self.painter.set_texture(id, &image_delta); + } + + /////// let clipped_primitives = self.egui_ctx.tessellate(shapes); + let clipped_primitives = self.egui_ctx.tessellate(shapes.clone()); + let dimensions: [u32; 2] = window.inner_size().into(); + self.painter.paint_primitives( + dimensions, + self.egui_ctx.pixels_per_point(), + &clipped_primitives, + ); + + for id in textures_delta.free.drain(..) { + self.painter.free_texture(id); + } + } + + /// Call to release the allocated graphics resources. + pub fn destroy(&mut self) { + self.painter.destroy(); + } +} diff --git a/ports/winit/main2.rs b/ports/winit/main2.rs index 51997ab2c5ba..b0ba39fdd184 100644 --- a/ports/winit/main2.rs +++ b/ports/winit/main2.rs @@ -14,6 +14,7 @@ mod app; mod backtrace; mod browser; mod crash_handler; +mod egui_glue; mod embedder; mod events_loop; mod headed_window; From f7a13a7291fbfecfd0549abb3024037a7bfec36c Mon Sep 17 00:00:00 2001 From: Delan Azabani Date: Wed, 9 Aug 2023 21:41:59 +0800 Subject: [PATCH 31/42] compositing: only skip framebuffer clear in external present mode --- components/compositing/compositor.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/components/compositing/compositor.rs b/components/compositing/compositor.rs index d98d83ad6640..4509910a7e11 100644 --- a/components/compositing/compositor.rs +++ b/components/compositing/compositor.rs @@ -1762,6 +1762,13 @@ impl IOCompositor { let gl = &self.webrender_gl; self.assert_gl_framebuffer_complete(); + if !self.external_present { + // Make framebuffer fully transparent. + gl.clear_color(0.0, 0.0, 0.0, 0.0); + gl.clear(gleam::gl::COLOR_BUFFER_BIT); + self.assert_gl_framebuffer_complete(); + } + // Make the viewport white. let viewport = self.embedder_coordinates.get_flipped_viewport(); gl.scissor( From 8b8a2018ae891d52b311d9623b772a04efb0cf33 Mon Sep 17 00:00:00 2001 From: Delan Azabani Date: Thu, 10 Aug 2023 13:43:30 +0800 Subject: [PATCH 32/42] winit: destroy egui glow Painter when shutting down --- ports/winit/app.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ports/winit/app.rs b/ports/winit/app.rs index deea2dd19075..294609025b9b 100644 --- a/ports/winit/app.rs +++ b/ports/winit/app.rs @@ -272,6 +272,9 @@ impl App { Some(PumpResult::Shutdown) => { *control_flow = winit::event_loop::ControlFlow::Exit; app.servo.take().unwrap().deinit(); + if let Some(mut minibrowser) = app.minibrowser() { + minibrowser.context.destroy(); + } }, Some(PumpResult::Present) => { if let Some(mut minibrowser) = app.minibrowser() { From 2a31b390d32fb3d65f91b3db0c3d8931e037d274 Mon Sep 17 00:00:00 2001 From: Delan Azabani Date: Thu, 10 Aug 2023 13:44:05 +0800 Subject: [PATCH 33/42] winit: clean up and fix license lint --- ports/winit/browser.rs | 2 +- ports/winit/egui_glue.rs | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/ports/winit/browser.rs b/ports/winit/browser.rs index c298ffeb1764..93143b2afecf 100644 --- a/ports/winit/browser.rs +++ b/ports/winit/browser.rs @@ -281,6 +281,7 @@ where self.event_queue.push(event); } + /// Returns true iff the caller needs to manually present a new frame. pub fn handle_servo_events(&mut self, events: Vec<(Option, EmbedderMsg)>) -> bool { let mut need_present = false; for (browser_id, msg) in events { @@ -531,7 +532,6 @@ where let _ = sender.send(ContextMenuResult::Ignored); }, EmbedderMsg::ReadyToPresent => { - // eprintln!("ReadyToPresent"); need_present = true; }, } diff --git a/ports/winit/egui_glue.rs b/ports/winit/egui_glue.rs index 8af0329819e9..0e7f61a6b20b 100644 --- a/ports/winit/egui_glue.rs +++ b/ports/winit/egui_glue.rs @@ -1,3 +1,7 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ + //! A modified version of EguiGlow [from egui_glow 0.22.0][0] that retains its shapes, //! allowing [`EguiGlow::paint`] to be called multiple times. //! From dac5b140c2119614bca2b60c0e434437626cacdb Mon Sep 17 00:00:00 2001 From: Delan Azabani Date: Thu, 10 Aug 2023 14:03:14 +0800 Subject: [PATCH 34/42] fix duplicate versions lint by downgrading bytemuck_derive MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit was egui_glow ^0.22.0 (0.22.0) → egui/bytemuck ^0.22.0 (0.22.0) → epaint/bytemuck ^0.22.0 (0.22.0) → bytemuck ^1.7.2 (1.13.1) → bytemuck_derive ^1.4 (1.4.1) → syn ^2.0.1 (2.0.28) now lock has bytemuck_derive 1.4.0 → syn ^1.0.99 (1.0.103) --- Cargo.lock | 87 ++++++++++++++++++++++++------------------------------ 1 file changed, 38 insertions(+), 49 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 52f5b4716deb..2ff9aa6b59f0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -221,7 +221,7 @@ checksum = "d7d78656ba01f1b93024b7c3a0467f1608e4be67d725749fdcd7d2c7678fd7a2" dependencies = [ "proc-macro2", "quote", - "syn 1.0.103", + "syn", ] [[package]] @@ -243,7 +243,7 @@ checksum = "e4655ae1a7b0cdf149156f780c5bf3f1352bc53cbd9e0a361a7ef7b22947e965" dependencies = [ "proc-macro2", "quote", - "syn 1.0.103", + "syn", ] [[package]] @@ -372,7 +372,7 @@ dependencies = [ "regex", "rustc-hash", "shlex", - "syn 1.0.103", + "syn", "which", ] @@ -584,13 +584,13 @@ dependencies = [ [[package]] name = "bytemuck_derive" -version = "1.4.1" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdde5c9cd29ebd706ce1b35600920a33550e402fc998a2e53ad3b42c3c47a192" +checksum = "1aca418a974d83d40a0c1f0c5cba6ff4bc28d8df099109ca459a2118d40b6322" dependencies = [ "proc-macro2", "quote", - "syn 2.0.27", + "syn", ] [[package]] @@ -724,7 +724,7 @@ dependencies = [ "quote", "serde", "serde_json", - "syn 1.0.103", + "syn", "tempfile", "toml", ] @@ -1212,7 +1212,7 @@ dependencies = [ "quote", "serde", "smallvec", - "syn 1.0.103", + "syn", ] [[package]] @@ -1222,7 +1222,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dfae75de57f2b2e85e8768c3ea840fd159c8f33e2b6522c7835b7abac81be16e" dependencies = [ "quote", - "syn 1.0.103", + "syn", ] [[package]] @@ -1242,7 +1242,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cd670e5ff58768ef624207fb95709ce63b8d05573fb9a05165f0eef471ea6a3a" dependencies = [ "procedural-masquerade", - "syn 1.0.103", + "syn", ] [[package]] @@ -1282,7 +1282,7 @@ dependencies = [ "ident_case", "proc-macro2", "quote", - "syn 1.0.103", + "syn", ] [[package]] @@ -1293,7 +1293,7 @@ checksum = "9c972679f83bdf9c42bd905396b6c3588a843a17f0f16dfcfa3e2c5d57441835" dependencies = [ "darling_core", "quote", - "syn 1.0.103", + "syn", ] [[package]] @@ -1335,7 +1335,7 @@ dependencies = [ name = "deny_public_fields" version = "0.0.1" dependencies = [ - "syn 1.0.103", + "syn", "synstructure", ] @@ -1353,7 +1353,7 @@ dependencies = [ "darling", "proc-macro2", "quote", - "syn 1.0.103", + "syn", "synstructure", ] @@ -1365,7 +1365,7 @@ checksum = "2127768764f1556535c01b5326ef94bd60ff08dcfbdc544d53e69ed155610f5d" dependencies = [ "proc-macro2", "quote", - "syn 1.0.103", + "syn", ] [[package]] @@ -1477,7 +1477,7 @@ name = "dom_struct" version = "0.0.1" dependencies = [ "quote", - "syn 1.0.103", + "syn", ] [[package]] @@ -1486,7 +1486,7 @@ version = "0.0.1" dependencies = [ "proc-macro2", "quote", - "syn 1.0.103", + "syn", ] [[package]] @@ -1654,7 +1654,7 @@ checksum = "1df9d0cef4b051baf3ef7f9b1674273dc78cd56e02cba60fa187f9c0ff4ff5e0" dependencies = [ "proc-macro2", "quote", - "syn 1.0.103", + "syn", ] [[package]] @@ -1980,7 +1980,7 @@ checksum = "3eb14ed937631bd8b8b8977f2c198443447a8355b6e3ca599f38c975e5a963b6" dependencies = [ "proc-macro2", "quote", - "syn 1.0.103", + "syn", ] [[package]] @@ -2836,7 +2836,7 @@ dependencies = [ "markup5ever", "proc-macro2", "quote", - "syn 1.0.103", + "syn", ] [[package]] @@ -3174,7 +3174,7 @@ name = "jstraceable_derive" version = "0.0.1" dependencies = [ "proc-macro2", - "syn 1.0.103", + "syn", "synstructure", ] @@ -3668,7 +3668,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "632647502a8bfa82458c07134791fffa7a719f00427d1afd79c3cb6d4960a982" dependencies = [ "proc-macro2", - "syn 1.0.103", + "syn", "synstructure", ] @@ -4225,7 +4225,7 @@ checksum = "876a53fff98e03a936a674b29568b0e605f06b29372c2489ff4de23f1949743d" dependencies = [ "proc-macro2", "quote", - "syn 1.0.103", + "syn", ] [[package]] @@ -4320,7 +4320,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 1.0.103", + "syn", ] [[package]] @@ -4441,7 +4441,7 @@ checksum = "b501e44f11665960c7e7fcf062c7d96a14ade4aa98116c004b2e37b5be7d736c" dependencies = [ "proc-macro2", "quote", - "syn 1.0.103", + "syn", ] [[package]] @@ -4592,7 +4592,7 @@ version = "0.2.1" dependencies = [ "proc-macro2", "quote", - "syn 1.0.103", + "syn", "synstructure", "unicode-xid", ] @@ -4681,7 +4681,7 @@ dependencies = [ "proc-macro-hack", "proc-macro2", "quote", - "syn 1.0.103", + "syn", ] [[package]] @@ -4710,7 +4710,7 @@ checksum = "f8e8d2bf0b23038a4424865103a4df472855692821aab4e4f5c3312d461d9e5f" dependencies = [ "proc-macro2", "quote", - "syn 1.0.103", + "syn", ] [[package]] @@ -5471,7 +5471,7 @@ checksum = "4f1d362ca8fc9c3e3a7484440752472d68a6caa98f1ab81d99b5dfe517cec852" dependencies = [ "proc-macro2", "quote", - "syn 1.0.103", + "syn", ] [[package]] @@ -5778,7 +5778,7 @@ dependencies = [ "itertools", "proc-macro2", "quote", - "syn 1.0.103", + "syn", ] [[package]] @@ -5799,7 +5799,7 @@ source = "git+https://github.com/servo/media#f53ac0a03a1413362e15d39d1527466986d dependencies = [ "proc-macro2", "quote", - "syn 1.0.103", + "syn", ] [[package]] @@ -6212,7 +6212,7 @@ dependencies = [ "derive_common", "proc-macro2", "quote", - "syn 1.0.103", + "syn", "synstructure", ] @@ -6337,17 +6337,6 @@ dependencies = [ "unicode-ident", ] -[[package]] -name = "syn" -version = "2.0.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b60f673f44a8255b9c8c657daf66a596d435f2da81a555b06dc644d080ba45e0" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - [[package]] name = "synstructure" version = "0.12.6" @@ -6356,7 +6345,7 @@ checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f" dependencies = [ "proc-macro2", "quote", - "syn 1.0.103", + "syn", "unicode-xid", ] @@ -6433,7 +6422,7 @@ checksum = "1fb327af4685e4d03fa8cbcf1716380da910eeb2bb8be417e7f9fd3fb164f36f" dependencies = [ "proc-macro2", "quote", - "syn 1.0.103", + "syn", ] [[package]] @@ -6568,7 +6557,7 @@ dependencies = [ "derive_common", "proc-macro2", "quote", - "syn 1.0.103", + "syn", "synstructure", ] @@ -6598,7 +6587,7 @@ checksum = "d266c00fde287f55d3f1c3e96c500c362a2b8c695076ec180f27918820bc6df8" dependencies = [ "proc-macro2", "quote", - "syn 1.0.103", + "syn", ] [[package]] @@ -7007,7 +6996,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 1.0.103", + "syn", "wasm-bindgen-shared", ] @@ -7029,7 +7018,7 @@ checksum = "2aff81306fcac3c7515ad4e177f521b5c9a15f2b08f4e32d823066102f35a5f6" dependencies = [ "proc-macro2", "quote", - "syn 1.0.103", + "syn", "wasm-bindgen-backend", "wasm-bindgen-shared", ] From 1a4ce1f6aed09d817f98ee807f692c7e8da0485d Mon Sep 17 00:00:00 2001 From: Delan Azabani Date: Thu, 10 Aug 2023 14:37:24 +0800 Subject: [PATCH 35/42] fix duplicate versions lint by disabling egui-winit/links MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit (we don’t need support for hyperlinks in our use of egui) --- Cargo.lock | 143 +++++------------------------------------ ports/winit/Cargo.toml | 2 +- 2 files changed, 18 insertions(+), 127 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 2ff9aa6b59f0..3694278d9c55 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1557,7 +1557,6 @@ dependencies = [ "log", "raw-window-handle 0.5.0", "smithay-clipboard", - "webbrowser", "winit", ] @@ -1695,7 +1694,7 @@ checksum = "50d6a0976c999d473fe89ad888d5a284e55366d9dc9038b1ba2aa15128c4afa0" dependencies = [ "errno-dragonfly", "libc", - "windows-sys 0.45.0", + "windows-sys", ] [[package]] @@ -2816,15 +2815,6 @@ version = "0.6.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "12cb882ccb290b8646e554b157ab0b71e64e8d5bef775cd66b6531e52d302669" -[[package]] -name = "home" -version = "0.5.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5444c27eef6923071f7ebcc33e3444508466a76f7a2b93da00ed6e19f30c1ddb" -dependencies = [ - "windows-sys 0.48.0", -] - [[package]] name = "html5ever" version = "0.26.0" @@ -3032,7 +3022,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1abeb7a0dd0f8181267ff8adc397075586500b81b28a73e8a0208b00fc170fb3" dependencies = [ "libc", - "windows-sys 0.45.0", + "windows-sys", ] [[package]] @@ -3120,22 +3110,6 @@ dependencies = [ "walkdir", ] -[[package]] -name = "jni" -version = "0.21.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a87aa2bb7d2af34197c04845522473242e1aa17c12f4935d5856491a7fb8c97" -dependencies = [ - "cesu8", - "cfg-if 1.0.0", - "combine", - "jni-sys", - "log", - "thiserror", - "walkdir", - "windows-sys 0.45.0", -] - [[package]] name = "jni-sys" version = "0.3.0" @@ -3880,7 +3854,7 @@ dependencies = [ "libc", "log", "wasi 0.11.0+wasi-snapshot-preview1", - "windows-sys 0.45.0", + "windows-sys", ] [[package]] @@ -4537,7 +4511,7 @@ dependencies = [ "libc", "redox_syscall 0.2.13", "smallvec", - "windows-sys 0.45.0", + "windows-sys", ] [[package]] @@ -5157,7 +5131,7 @@ dependencies = [ "io-lifetimes", "libc", "linux-raw-sys", - "windows-sys 0.45.0", + "windows-sys", ] [[package]] @@ -5950,7 +5924,7 @@ dependencies = [ "android_logger", "cc", "gstreamer", - "jni 0.18.0", + "jni", "libc", "log", "serde_json", @@ -6372,7 +6346,7 @@ dependencies = [ "fastrand", "redox_syscall 0.3.4", "rustix", - "windows-sys 0.45.0", + "windows-sys", ] [[package]] @@ -6576,7 +6550,7 @@ dependencies = [ "pin-project-lite", "socket2", "tokio-macros", - "windows-sys 0.45.0", + "windows-sys", ] [[package]] @@ -7124,23 +7098,6 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "webbrowser" -version = "0.8.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd222aa310eb7532e3fd427a5d7db7e44bc0b0cf1c1e21139c345325511a85b6" -dependencies = [ - "core-foundation 0.9.3", - "home", - "jni 0.21.1", - "log", - "ndk-context", - "objc", - "raw-window-handle 0.5.0", - "url", - "web-sys", -] - [[package]] name = "webdriver" version = "0.48.0" @@ -7430,16 +7387,7 @@ version = "0.45.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" dependencies = [ - "windows-targets 0.42.1", -] - -[[package]] -name = "windows-sys" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" -dependencies = [ - "windows-targets 0.48.1", + "windows-targets", ] [[package]] @@ -7448,28 +7396,13 @@ version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e2522491fbfcd58cc84d47aeb2958948c4b8982e9a2d8a2a35bbaed431390e7" dependencies = [ - "windows_aarch64_gnullvm 0.42.1", - "windows_aarch64_msvc 0.42.1", - "windows_i686_gnu 0.42.1", - "windows_i686_msvc 0.42.1", - "windows_x86_64_gnu 0.42.1", - "windows_x86_64_gnullvm 0.42.1", - "windows_x86_64_msvc 0.42.1", -] - -[[package]] -name = "windows-targets" -version = "0.48.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05d4b17490f70499f20b9e791dcf6a299785ce8af4d709018206dc5b4953e95f" -dependencies = [ - "windows_aarch64_gnullvm 0.48.0", - "windows_aarch64_msvc 0.48.0", - "windows_i686_gnu 0.48.0", - "windows_i686_msvc 0.48.0", - "windows_x86_64_gnu 0.48.0", - "windows_x86_64_gnullvm 0.48.0", - "windows_x86_64_msvc 0.48.0", + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", ] [[package]] @@ -7478,84 +7411,42 @@ version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8c9864e83243fdec7fc9c5444389dcbbfd258f745e7853198f365e3c4968a608" -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" - [[package]] name = "windows_aarch64_msvc" version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4c8b1b673ffc16c47a9ff48570a9d85e25d265735c503681332589af6253c6c7" -[[package]] -name = "windows_aarch64_msvc" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" - [[package]] name = "windows_i686_gnu" version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "de3887528ad530ba7bdbb1faa8275ec7a1155a45ffa57c37993960277145d640" -[[package]] -name = "windows_i686_gnu" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" - [[package]] name = "windows_i686_msvc" version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bf4d1122317eddd6ff351aa852118a2418ad4214e6613a50e0191f7004372605" -[[package]] -name = "windows_i686_msvc" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" - [[package]] name = "windows_x86_64_gnu" version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c1040f221285e17ebccbc2591ffdc2d44ee1f9186324dd3e84e99ac68d699c45" -[[package]] -name = "windows_x86_64_gnu" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" - [[package]] name = "windows_x86_64_gnullvm" version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "628bfdf232daa22b0d64fdb62b09fcc36bb01f05a3939e20ab73aaf9470d0463" -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" - [[package]] name = "windows_x86_64_msvc" version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "447660ad36a13288b1db4d4248e857b510e8c3a225c822ba4fb748c0aafecffd" -[[package]] -name = "windows_x86_64_msvc" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" - [[package]] name = "winit" version = "0.28.3" @@ -7587,7 +7478,7 @@ dependencies = [ "wayland-protocols", "wayland-scanner", "web-sys", - "windows-sys 0.45.0", + "windows-sys", "x11-dl", ] diff --git a/ports/winit/Cargo.toml b/ports/winit/Cargo.toml index f294b7f95b4d..671c15779cb7 100644 --- a/ports/winit/Cargo.toml +++ b/ports/winit/Cargo.toml @@ -51,7 +51,7 @@ backtrace = { workspace = true } clipboard = "0.5" egui = { version = "0.22.0", optional = true } egui_glow = { version = "0.22.0", optional = true, features = ["winit"] } -egui-winit = { version = "0.22.0", optional = true } +egui-winit = { version = "0.22.0", optional = true, default-features = false, features = ["clipboard", "wayland"] } euclid = { workspace = true } getopts = { workspace = true } gleam = "0.12" From 573820c758cb940b3e807d1c3cd55a3e17d7a29d Mon Sep 17 00:00:00 2001 From: Delan Azabani Date: Thu, 10 Aug 2023 14:48:36 +0800 Subject: [PATCH 36/42] squelch duplicate versions lint by excluding clipboard-win --- servo-tidy.toml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/servo-tidy.toml b/servo-tidy.toml index 88c1b5539713..3675e6252f78 100644 --- a/servo-tidy.toml +++ b/servo-tidy.toml @@ -75,6 +75,9 @@ packages = [ # Temporarily duplicated until ipc-channels and gleam can be upgrded. "uuid", + + # winit port minibrowser (servo/servo#30049) + "clipboard-win", ] # Files that are ignored for all tidy and lint checks. files = [ From 95dabae772f77725e8785181a72277b2b9d8447e Mon Sep 17 00:00:00 2001 From: Delan Azabani Date: Thu, 10 Aug 2023 14:52:08 +0800 Subject: [PATCH 37/42] winit: fix compile warnings --- ports/winit/app.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ports/winit/app.rs b/ports/winit/app.rs index 294609025b9b..0ea1666cb6dc 100644 --- a/ports/winit/app.rs +++ b/ports/winit/app.rs @@ -10,7 +10,7 @@ use crate::embedder::EmbedderCallbacks; use crate::events_loop::{EventsLoop, WakerEvent}; use crate::window_trait::WindowPortsMethods; use crate::{headed_window, headless_window}; -use egui::{TopBottomPanel, Rect, Pos2, Vec2, Sense}; +use egui::TopBottomPanel; use gleam::gl; use winit::window::WindowId; use winit::event_loop::EventLoopWindowTarget; From bd114b56ac660fb0d16dd754db5e1bc13d4b43bd Mon Sep 17 00:00:00 2001 From: Delan Azabani Date: Thu, 10 Aug 2023 15:12:09 +0800 Subject: [PATCH 38/42] winit: make gleam an optional dependency under /minibrowser --- ports/winit/Cargo.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ports/winit/Cargo.toml b/ports/winit/Cargo.toml index 671c15779cb7..45173f471b2e 100644 --- a/ports/winit/Cargo.toml +++ b/ports/winit/Cargo.toml @@ -36,7 +36,7 @@ js_backtrace = ["libservo/js_backtrace"] max_log_level = ["log/release_max_level_info"] media-dummy = ["libservo/media-dummy"] media-gstreamer = ["libservo/media-gstreamer"] -minibrowser = ["dep:egui", "dep:egui-winit", "dep:egui_glow", "dep:glow"] +minibrowser = ["dep:egui", "dep:egui-winit", "dep:egui_glow", "dep:gleam", "dep:glow"] native-bluetooth = ["libservo/native-bluetooth"] no-wgl = ["libservo/no-wgl"] profilemozjs = ["libservo/profilemozjs"] @@ -54,7 +54,7 @@ egui_glow = { version = "0.22.0", optional = true, features = ["winit"] } egui-winit = { version = "0.22.0", optional = true, default-features = false, features = ["clipboard", "wayland"] } euclid = { workspace = true } getopts = { workspace = true } -gleam = "0.12" +gleam = { version = "0.12", optional = true } glow = { version = "0.12.2", optional = true } keyboard-types = { workspace = true } lazy_static = { workspace = true } From 00d61872126774efdf70f91a26074ae1332c1a2e Mon Sep 17 00:00:00 2001 From: Delan Azabani Date: Mon, 14 Aug 2023 16:33:38 +0800 Subject: [PATCH 39/42] =?UTF-8?q?winit:=20remove=20cargo=20feature,=20sinc?= =?UTF-8?q?e=20it=E2=80=99s=20not=20really=20optional?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ports/winit/Cargo.toml | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/ports/winit/Cargo.toml b/ports/winit/Cargo.toml index 45173f471b2e..fdb68774b6ae 100644 --- a/ports/winit/Cargo.toml +++ b/ports/winit/Cargo.toml @@ -30,13 +30,12 @@ ProductName = "Servo" [features] debugmozjs = ["libservo/debugmozjs"] -default = ["webdriver", "max_log_level", "minibrowser"] +default = ["webdriver", "max_log_level"] jitspew = ["libservo/jitspew"] js_backtrace = ["libservo/js_backtrace"] max_log_level = ["log/release_max_level_info"] media-dummy = ["libservo/media-dummy"] media-gstreamer = ["libservo/media-gstreamer"] -minibrowser = ["dep:egui", "dep:egui-winit", "dep:egui_glow", "dep:gleam", "dep:glow"] native-bluetooth = ["libservo/native-bluetooth"] no-wgl = ["libservo/no-wgl"] profilemozjs = ["libservo/profilemozjs"] @@ -49,13 +48,13 @@ xr-profile = ["libservo/xr-profile"] [target.'cfg(not(target_os = "android"))'.dependencies] backtrace = { workspace = true } clipboard = "0.5" -egui = { version = "0.22.0", optional = true } -egui_glow = { version = "0.22.0", optional = true, features = ["winit"] } -egui-winit = { version = "0.22.0", optional = true, default-features = false, features = ["clipboard", "wayland"] } +egui = "0.22.0" +egui_glow = { version = "0.22.0", features = ["winit"] } +egui-winit = { version = "0.22.0", default-features = false, features = ["clipboard", "wayland"] } euclid = { workspace = true } getopts = { workspace = true } -gleam = { version = "0.12", optional = true } -glow = { version = "0.12.2", optional = true } +gleam = "0.12" +glow = "0.12.2" keyboard-types = { workspace = true } lazy_static = { workspace = true } libc = { workspace = true } From 06e0d2987e42a1fd542a34697be3f7ca37ecdc62 Mon Sep 17 00:00:00 2001 From: Delan Azabani Date: Mon, 14 Aug 2023 17:07:12 +0800 Subject: [PATCH 40/42] winit: extract Minibrowser and related code to separate module --- ports/winit/app.rs | 103 ++-------------------------------- ports/winit/main2.rs | 1 + ports/winit/minibrowser.rs | 110 +++++++++++++++++++++++++++++++++++++ 3 files changed, 117 insertions(+), 97 deletions(-) create mode 100644 ports/winit/minibrowser.rs diff --git a/ports/winit/app.rs b/ports/winit/app.rs index 0ea1666cb6dc..f5b7d56d622c 100644 --- a/ports/winit/app.rs +++ b/ports/winit/app.rs @@ -5,12 +5,11 @@ //! Application entry point, runs the event loop. use crate::browser::Browser; -use crate::egui_glue; use crate::embedder::EmbedderCallbacks; use crate::events_loop::{EventsLoop, WakerEvent}; +use crate::minibrowser::Minibrowser; use crate::window_trait::WindowPortsMethods; use crate::{headed_window, headless_window}; -use egui::TopBottomPanel; use gleam::gl; use winit::window::WindowId; use winit::event_loop::EventLoopWindowTarget; @@ -24,7 +23,6 @@ use std::collections::HashMap; use std::env; use std::rc::Rc; -use std::sync::Arc; use surfman::GLApi; use webxr::glwindow::GlWindowDiscovery; @@ -37,61 +35,12 @@ pub struct App { minibrowser: Option>, } -struct Minibrowser { - context: egui_glue::EguiGlow, - event_queue: RefCell>, - toolbar_height: Cell, - location: RefCell, - - /// Whether the location has been edited by the user without clicking Go. - location_dirty: Cell, -} - -enum MinibrowserEvent { - /// Go button clicked. - Go, -} - /// Action to be taken by the caller of [`App::handle_events`]. enum PumpResult { Shutdown, Present, } -impl Minibrowser { - /// Update the minibrowser, but don’t paint. - fn update(&mut self, window: &winit::window::Window) { - let Self { context, event_queue, location, location_dirty, toolbar_height } = self; - let _duration = context.run(window, |ctx| { - TopBottomPanel::top("toolbar").show(ctx, |ui| { - ui.allocate_ui_with_layout( - ui.available_size(), - egui::Layout::right_to_left(egui::Align::Center), - |ui| { - if ui.button("go").clicked() { - event_queue.borrow_mut().push(MinibrowserEvent::Go); - location_dirty.set(false); - } - if ui.add_sized( - ui.available_size(), - egui::TextEdit::singleline(&mut *location.borrow_mut()), - ).changed() { - location_dirty.set(true); - } - }, - ); - }); - - toolbar_height.set(ctx.used_rect().height()); - }); - } - - /// Paint the minibrowser, as of the last update. - fn paint(&mut self, window: &winit::window::Window) { - self.context.paint(window); - } -} - impl App { pub fn run( no_native_titlebar: bool, @@ -133,23 +82,12 @@ impl App { gl::GlesFns::load_with(|s| webrender_surfman.get_proc_address(s)) }, }; - let gl = unsafe { - glow::Context::from_loader_function(|s| { - webrender_surfman.get_proc_address(s) - }) - }; webrender_surfman.make_gl_context_current().unwrap(); debug_assert_eq!(webrender_gl.get_error(), gleam::gl::NO_ERROR,); // Set up egui context for minibrowser ui // Adapted from https://github.com/emilk/egui/blob/9478e50d012c5138551c38cbee16b07bc1fcf283/crates/egui_glow/examples/pure_glow.rs - app.minibrowser = Some(Minibrowser { - context: egui_glue::EguiGlow::new(events_loop.as_winit(), Arc::new(gl), None), - event_queue: RefCell::new(vec![]), - toolbar_height: 0f32.into(), - location: RefCell::new(ServoUrl::into_string(get_default_url())), - location_dirty: false.into(), - }.into()); + app.minibrowser = Some(Minibrowser::new(&webrender_surfman, &events_loop).into()); } if let Some(mut minibrowser) = app.minibrowser() { @@ -260,8 +198,10 @@ impl App { // Consume and handle any events from the Minibrowser. if let Some(mut minibrowser) = app.minibrowser() { - app.queue_embedder_events_for_minibrowser_events(&mut minibrowser); - if app.update_location_in_toolbar(&mut minibrowser) { + let browser = &mut app.browser.borrow_mut(); + let app_event_queue = &mut app.event_queue.borrow_mut(); + minibrowser.queue_embedder_events_for_minibrowser_events(browser, app_event_queue); + if minibrowser.update_location_in_toolbar(browser) { // Update the minibrowser immediately. While we could update by requesting a // redraw, doing so would delay the location update by two frames. minibrowser.update(window.winit_window().unwrap()); @@ -337,37 +277,6 @@ impl App { } } - /// Takes any outstanding events from the [Minibrowser], converting them to [EmbedderEvent] and - /// routing those to the App event queue. - fn queue_embedder_events_for_minibrowser_events(&self, minibrowser: &mut RefMut) { - for event in minibrowser.event_queue.borrow_mut().drain(..) { - match event { - MinibrowserEvent::Go => { - let browser_id = self.browser.borrow().browser_id().unwrap(); - let location = minibrowser.location.borrow(); - let Ok(url) = ServoUrl::parse(&location) else { - warn!("failed to parse location"); - break; - }; - self.event_queue.borrow_mut().push(EmbedderEvent::LoadUrl(browser_id, url)); - }, - } - } - } - - /// Updates the location field when the [Browser] says it has changed, unless the user has - /// started editing it without clicking Go. - fn update_location_in_toolbar(&self, minibrowser: &mut RefMut) -> bool { - if !minibrowser.location_dirty.get() { - if let Some(current_url) = self.browser.borrow_mut().take_top_level_url_change() { - minibrowser.location = RefCell::new(ServoUrl::into_string(current_url)); - return true; - } - } - - false - } - /// Pumps events and messages between the embedder and Servo, where embedder events flow /// towards Servo and embedder messages flow away from Servo, and also runs the compositor. /// diff --git a/ports/winit/main2.rs b/ports/winit/main2.rs index b0ba39fdd184..07d931c21abb 100644 --- a/ports/winit/main2.rs +++ b/ports/winit/main2.rs @@ -20,6 +20,7 @@ mod events_loop; mod headed_window; mod headless_window; mod keyutils; +mod minibrowser; mod prefs; mod resources; mod window_trait; diff --git a/ports/winit/minibrowser.rs b/ports/winit/minibrowser.rs new file mode 100644 index 000000000000..c1c33b27bd3d --- /dev/null +++ b/ports/winit/minibrowser.rs @@ -0,0 +1,110 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ + + use std::{cell::{RefCell, Cell}, sync::Arc}; + +use egui::TopBottomPanel; +use servo::{servo_url::ServoUrl, compositing::windowing::EmbedderEvent}; +use servo::webrender_surfman::WebrenderSurfman; + +use crate::{egui_glue::EguiGlow, events_loop::EventsLoop, browser::Browser, window_trait::WindowPortsMethods}; + +pub struct Minibrowser { + pub context: EguiGlow, + pub event_queue: RefCell>, + pub toolbar_height: Cell, + location: RefCell, + + /// Whether the location has been edited by the user without clicking Go. + location_dirty: Cell, +} + +pub enum MinibrowserEvent { + /// Go button clicked. + Go, +} + +impl Minibrowser { + pub fn new(webrender_surfman: &WebrenderSurfman, events_loop: &EventsLoop) -> Self { + let gl = unsafe { + glow::Context::from_loader_function(|s| { + webrender_surfman.get_proc_address(s) + }) + }; + + Self { + context: EguiGlow::new(events_loop.as_winit(), Arc::new(gl), None), + event_queue: RefCell::new(vec![]), + toolbar_height: 0f32.into(), + location: RefCell::new(String::default()), + location_dirty: false.into(), + } + } + + /// Update the minibrowser, but don’t paint. + pub fn update(&mut self, window: &winit::window::Window) { + let Self { context, event_queue, location, location_dirty, toolbar_height } = self; + let _duration = context.run(window, |ctx| { + TopBottomPanel::top("toolbar").show(ctx, |ui| { + ui.allocate_ui_with_layout( + ui.available_size(), + egui::Layout::right_to_left(egui::Align::Center), + |ui| { + if ui.button("go").clicked() { + event_queue.borrow_mut().push(MinibrowserEvent::Go); + location_dirty.set(false); + } + if ui.add_sized( + ui.available_size(), + egui::TextEdit::singleline(&mut *location.borrow_mut()), + ).changed() { + location_dirty.set(true); + } + }, + ); + }); + + toolbar_height.set(ctx.used_rect().height()); + }); + } + + /// Paint the minibrowser, as of the last update. + pub fn paint(&mut self, window: &winit::window::Window) { + self.context.paint(window); + } + + /// Takes any outstanding events from the [Minibrowser], converting them to [EmbedderEvent] and + /// routing those to the App event queue. + pub fn queue_embedder_events_for_minibrowser_events( + &self, browser: &Browser, + app_event_queue: &mut Vec, + ) { + for event in self.event_queue.borrow_mut().drain(..) { + match event { + MinibrowserEvent::Go => { + let browser_id = browser.browser_id().unwrap(); + let location = self.location.borrow(); + let Ok(url) = ServoUrl::parse(&location) else { + warn!("failed to parse location"); + break; + }; + app_event_queue.push(EmbedderEvent::LoadUrl(browser_id, url)); + }, + } + } + } + + /// Updates the location field when the [Browser] says it has changed, unless the user has + /// started editing it without clicking Go. + pub fn update_location_in_toolbar(&mut self, browser: &mut Browser) -> bool { + if !self.location_dirty.get() { + if let Some(current_url) = browser.take_top_level_url_change() { + self.location = RefCell::new(ServoUrl::into_string(current_url)); + return true; + } + } + + false + } +} From ebdb00783024faa76abea961aced11a746b95ac4 Mon Sep 17 00:00:00 2001 From: Delan Azabani Date: Mon, 14 Aug 2023 17:13:39 +0800 Subject: [PATCH 41/42] winit: remove unnecessary trailing comma --- ports/winit/app.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ports/winit/app.rs b/ports/winit/app.rs index f5b7d56d622c..290ca0bc38a1 100644 --- a/ports/winit/app.rs +++ b/ports/winit/app.rs @@ -83,7 +83,7 @@ impl App { }, }; webrender_surfman.make_gl_context_current().unwrap(); - debug_assert_eq!(webrender_gl.get_error(), gleam::gl::NO_ERROR,); + debug_assert_eq!(webrender_gl.get_error(), gleam::gl::NO_ERROR); // Set up egui context for minibrowser ui // Adapted from https://github.com/emilk/egui/blob/9478e50d012c5138551c38cbee16b07bc1fcf283/crates/egui_glow/examples/pure_glow.rs From b01b10c591801be4736ccd501cfa292c9a361bc7 Mon Sep 17 00:00:00 2001 From: Delan Azabani Date: Mon, 14 Aug 2023 17:25:56 +0800 Subject: [PATCH 42/42] winit: simplify the ServoUrl serialisation optimisation --- ports/winit/browser.rs | 16 +++++----------- ports/winit/minibrowser.rs | 4 ++-- 2 files changed, 7 insertions(+), 13 deletions(-) diff --git a/ports/winit/browser.rs b/ports/winit/browser.rs index 93143b2afecf..e46c51e5e9fd 100644 --- a/ports/winit/browser.rs +++ b/ports/winit/browser.rs @@ -31,7 +31,7 @@ use tinyfiledialogs::{self, MessageBoxIcon, OkCancel, YesNo}; pub struct Browser { current_url: Option, - current_url_taken: bool, + current_url_string: Option, /// id of the top level browsing context. It is unique as tabs /// are not supported yet. None until created. @@ -59,7 +59,7 @@ where Browser { title: None, current_url: None, - current_url_taken: false, + current_url_string: None, browser_id: None, browsers: Vec::new(), window, @@ -79,14 +79,8 @@ where self.browser_id } - /// Returns current_url iff there has been a HistoryChanged event since the last call. - pub fn take_top_level_url_change(&mut self) -> Option { - if self.current_url_taken { - None - } else { - self.current_url_taken = true; - self.current_url.clone() - } + pub fn current_url_string(&self) -> Option<&str> { + self.current_url_string.as_deref() } pub fn get_events(&mut self) -> Vec { @@ -456,7 +450,7 @@ where }, EmbedderMsg::HistoryChanged(urls, current) => { self.current_url = Some(urls[current].clone()); - self.current_url_taken = false; + self.current_url_string = Some(urls[current].clone().into_string()); }, EmbedderMsg::SetFullscreenState(state) => { self.window.set_fullscreen(state); diff --git a/ports/winit/minibrowser.rs b/ports/winit/minibrowser.rs index c1c33b27bd3d..48afc9d59360 100644 --- a/ports/winit/minibrowser.rs +++ b/ports/winit/minibrowser.rs @@ -99,8 +99,8 @@ impl Minibrowser { /// started editing it without clicking Go. pub fn update_location_in_toolbar(&mut self, browser: &mut Browser) -> bool { if !self.location_dirty.get() { - if let Some(current_url) = browser.take_top_level_url_change() { - self.location = RefCell::new(ServoUrl::into_string(current_url)); + if let Some(location) = browser.current_url_string() { + self.location = RefCell::new(location.to_owned()); return true; } }