mirror of
https://github.com/servo/servo.git
synced 2025-06-06 16:45:39 +00:00
* winit: add minibrowser feature that depends on egui{,-winit} * winit: carve out some space at the top of headed windows * winit: minimal toolbar and egui/winit integration (but no painting) * winit: try to paint with egui_glow (doesn’t work yet) * winit: add comment about toolbar size * Add framebuffer object, set it as glow's target * compositing: clear only the viewport, not the whole framebuffer * plumb the actual size of the egui toolbar to webrender * fix formatting * winit: fix crash when fbo is zero * winit: don’t bother binding the framebuffer object * winit: remove unsafe and get toolbar_height * winit: location field should reflect the current top-level url * [NFC] winit: move Minibrowser out of App::run * winit: clean up toolbar height code * winit: make App own the Minibrowser if any * winit: make the go button work * winit:make the location field reflect the current top-level url * winit: allow enabling minibrowser from command line * winit: tell compositor to repaint WR and flush when we repaint * winit: fix bug where location field edits would get overridden * winit: borrow the minibrowser once in App::handle_events * winit: address todo about viewport origin coordinates * winit: fix some minor problems with comments and errors * winit: update location field once per HistoryChanged event * winit: rename Window::set_toolbar_size to set_toolbar_height * winit: take toolbar height into account in hit testing * winit: pass egui only relevant CursorMoved events * winit: scratch that, coalesce minibrowser updates instead * ensure both minibrowser and WR are repainted on every frame * compositing: only skip framebuffer clear in external present mode * winit: destroy egui glow Painter when shutting down * winit: clean up and fix license lint * fix duplicate versions lint by downgrading bytemuck_derive 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) * fix duplicate versions lint by disabling egui-winit/links (we don’t need support for hyperlinks in our use of egui) * squelch duplicate versions lint by excluding clipboard-win * winit: fix compile warnings * winit: make gleam an optional dependency under /minibrowser * winit: remove cargo feature, since it’s not really optional * winit: extract Minibrowser and related code to separate module * winit: remove unnecessary trailing comma * winit: simplify the ServoUrl serialisation optimisation --------- Co-authored-by: atbrakhi <atbrakhi@igalia.com>
110 lines
4 KiB
Rust
110 lines
4 KiB
Rust
/* 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<Vec<MinibrowserEvent>>,
|
||
pub toolbar_height: Cell<f32>,
|
||
location: RefCell<String>,
|
||
|
||
/// Whether the location has been edited by the user without clicking Go.
|
||
location_dirty: Cell<bool>,
|
||
}
|
||
|
||
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<dyn WindowPortsMethods>,
|
||
app_event_queue: &mut Vec<EmbedderEvent>,
|
||
) {
|
||
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<dyn WindowPortsMethods>) -> bool {
|
||
if !self.location_dirty.get() {
|
||
if let Some(location) = browser.current_url_string() {
|
||
self.location = RefCell::new(location.to_owned());
|
||
return true;
|
||
}
|
||
}
|
||
|
||
false
|
||
}
|
||
}
|