mirror of
https://github.com/servo/servo.git
synced 2025-08-10 16:05:43 +01:00
Initial internal support for multiple webviews (#31417)
* Add multiple concurrent top-level browsing contexts Co-authored-by: Delan Azabani <dazabani@igalia.com> * Rename variables and comments There are some variable and comments still use browser as names. This commit renames them to webview. * Update log message from web view to webview * Revert offscreen_framebuffer_id rename * Rename all web view to webview * Cargo fmt * Fix viewport/event/clear coordinates when multiview is disabled * Only deprecate things when multiview is enabled * Update WebViewManger with shown and invisible sets Replace visible_webviews and native_window_is_visible with shown_webviews and invisible_webviews. Add 4 more methods to set them accordingly. The behavior of is_effectively_visible will return true if the wbview is in shown_webviews set but not in invisible_webviews. * Update variant behaviors * Rename WebViewVisibilityChanged to MarkWebViewInvisible * Fix unit test by marking id 3 visible again * Update MarkWebViewInvisible and add UnmarkWebViewInvisible * Update format and doc comments * Clean up doc comments * Address style and naming changes * Rename UpdateWebView to UpdateFrameTreeForWebView * constellation: send frame tree unconditionally over focus and feature * Clarify shown and invisible sets in constellation WebViewManager * Eliminate forward_to_constellation!() * Actually remove the unused macro * Don’t gate compositor changes on multiview feature flag * Update todo in mouse event dispatch * Pass all visible webview ids in a single ReadyToPresent message * Fix compile and lint errors * servoshell: fix gap between minibrowser toolbar and webview * Fix failure in /_mozilla/mozilla/window_resizeTo.html * Fix compile warnings * Remove stray dbg!() * Remove confusing “effectively visible” logic (see #31815, #31816) * Allow embedder to show/hide/raise webviews without ipc * Update root pipeline only when painting order actually changes * Stop gating old focus and SetFrameTree behaviour behind Cargo feature * Use webview_id and WebViewId in webview-related code * Improve logging of webview-related embedder events * Allow webview Show and Raise events to optionally hide all others * Don’t do anything in response to WebViewPaintingOrder * Remove WebViewPaintingOrder, since its payload is unreliable * On MoveResizeWebView, only update root pipeline if rect changed * Rename IOCompositor methods for clarity * compositor: add event tracing; log webview ops even without ipc * Add temporary debug logging * Add more temporary debug logging * Remove temporary logging in compositor * Remove temporary debug logging * Add temporary debug logging, but defer I/O until panic * Capture a backtrace with each crash log entry * Proper error handling without panicking in WebViewManager * Clean up imports in constellation --------- Co-authored-by: Delan Azabani <dazabani@igalia.com> Co-authored-by: Martin Robinson <mrobinson@igalia.com>
This commit is contained in:
parent
18b37e676b
commit
66878fb834
21 changed files with 1142 additions and 434 deletions
|
@ -435,7 +435,7 @@ impl ServoGlue {
|
|||
pub fn resize(&mut self, coordinates: Coordinates) -> Result<(), &'static str> {
|
||||
info!("resize");
|
||||
*self.callbacks.coordinates.borrow_mut() = coordinates;
|
||||
self.process_event(EmbedderEvent::Resize)
|
||||
self.process_event(EmbedderEvent::WindowResize)
|
||||
}
|
||||
|
||||
/// Start scrolling.
|
||||
|
@ -818,7 +818,7 @@ impl ServoGlue {
|
|||
EmbedderMsg::Panic(reason, backtrace) => {
|
||||
self.callbacks.host_callbacks.on_panic(reason, backtrace);
|
||||
},
|
||||
EmbedderMsg::ReadyToPresent => {
|
||||
EmbedderMsg::ReadyToPresent(_webview_ids) => {
|
||||
need_present = true;
|
||||
},
|
||||
EmbedderMsg::Status(..) |
|
||||
|
|
|
@ -124,17 +124,15 @@ impl App {
|
|||
|
||||
if let Some(mut minibrowser) = app.minibrowser() {
|
||||
// Servo is not yet initialised, so there is no `servo_framebuffer_id`.
|
||||
minibrowser.update(window.winit_window().unwrap(), None, "init");
|
||||
minibrowser.update(
|
||||
window.winit_window().unwrap(),
|
||||
&mut app.webviews.borrow_mut(),
|
||||
None,
|
||||
"init",
|
||||
);
|
||||
window.set_toolbar_height(minibrowser.toolbar_height);
|
||||
}
|
||||
|
||||
// Whether or not to recomposite during the next RedrawRequested event.
|
||||
// Normally this is true, including for RedrawRequested events that come from the platform
|
||||
// (e.g. X11 without picom or similar) when an offscreen or obscured window becomes visible.
|
||||
// If we are calling request_redraw in response to the compositor having painted to this
|
||||
// frame, set this to false, so we can avoid an unnecessary recomposite.
|
||||
let mut need_recomposite = true;
|
||||
|
||||
let t_start = Instant::now();
|
||||
let mut t = t_start;
|
||||
let ev_waker = events_loop.create_event_loop_waker();
|
||||
|
@ -208,22 +206,17 @@ impl App {
|
|||
|
||||
// WARNING: do not defer painting or presenting to some later tick of the event
|
||||
// loop or servoshell may become unresponsive! (servo#30312)
|
||||
if need_recomposite {
|
||||
trace!("need_recomposite");
|
||||
app.servo.as_mut().unwrap().recomposite();
|
||||
}
|
||||
if let Some(mut minibrowser) = app.minibrowser() {
|
||||
minibrowser.update(
|
||||
window.winit_window().unwrap(),
|
||||
&mut app.webviews.borrow_mut(),
|
||||
app.servo.as_ref().unwrap().offscreen_framebuffer_id(),
|
||||
"RedrawRequested",
|
||||
);
|
||||
minibrowser.paint(window.winit_window().unwrap());
|
||||
}
|
||||
app.servo.as_mut().unwrap().present();
|
||||
|
||||
// By default, the next RedrawRequested event will need to recomposite.
|
||||
need_recomposite = true;
|
||||
app.servo.as_mut().unwrap().present();
|
||||
}
|
||||
|
||||
// Handle the event
|
||||
|
@ -303,6 +296,7 @@ impl App {
|
|||
// redraw, doing so would delay the location update by two frames.
|
||||
minibrowser.update(
|
||||
window.winit_window().unwrap(),
|
||||
webviews,
|
||||
app.servo.as_ref().unwrap().offscreen_framebuffer_id(),
|
||||
"update_location_in_toolbar",
|
||||
);
|
||||
|
@ -314,13 +308,13 @@ impl App {
|
|||
// The window was resized.
|
||||
trace!("PumpResult::Present::Immediate");
|
||||
|
||||
// Resizes are unusual in that we need to repaint synchronously.
|
||||
// TODO(servo#30049) can we replace this with the simpler Servo::recomposite?
|
||||
app.servo.as_mut().unwrap().repaint_synchronously();
|
||||
|
||||
// If we had resized any of the viewports in response to this, we would need to
|
||||
// call Servo::repaint_synchronously. At the moment we don’t, so there won’t be
|
||||
// any paint scheduled, and calling it would hang the compositor forever.
|
||||
if let Some(mut minibrowser) = app.minibrowser() {
|
||||
minibrowser.update(
|
||||
window.winit_window().unwrap(),
|
||||
&mut app.webviews.borrow_mut(),
|
||||
app.servo.as_ref().unwrap().offscreen_framebuffer_id(),
|
||||
"PumpResult::Present::Immediate",
|
||||
);
|
||||
|
@ -339,10 +333,6 @@ impl App {
|
|||
} else {
|
||||
app.servo.as_mut().unwrap().present();
|
||||
}
|
||||
|
||||
// We don’t need the compositor to paint to this frame during the redraw event.
|
||||
// TODO(servo#30331) broken on macOS?
|
||||
// need_recomposite = false;
|
||||
},
|
||||
Present::None => {},
|
||||
}
|
||||
|
|
|
@ -8,7 +8,6 @@ use std::cell::{Cell, RefCell};
|
|||
use std::collections::HashMap;
|
||||
use std::rc::Rc;
|
||||
|
||||
use euclid::num::Zero;
|
||||
use euclid::{Angle, Length, Point2D, Rotation3D, Scale, Size2D, UnknownUnit, Vector2D, Vector3D};
|
||||
use log::{debug, info, trace};
|
||||
use raw_window_handle::{HasRawDisplayHandle, HasRawWindowHandle};
|
||||
|
@ -309,8 +308,11 @@ impl WindowPortsMethods for Window {
|
|||
}
|
||||
|
||||
fn set_inner_size(&self, size: DeviceIntSize) {
|
||||
let toolbar_height = self.toolbar_height() * self.hidpi_factor();
|
||||
let toolbar_height = toolbar_height.get().ceil() as i32;
|
||||
let total_size = PhysicalSize::new(size.width, size.height + toolbar_height);
|
||||
self.winit_window
|
||||
.set_inner_size::<PhysicalSize<i32>>(PhysicalSize::new(size.width, size.height))
|
||||
.set_inner_size::<PhysicalSize<i32>>(total_size)
|
||||
}
|
||||
|
||||
fn set_position(&self, point: DeviceIntPoint) {
|
||||
|
@ -399,9 +401,7 @@ impl WindowPortsMethods for Window {
|
|||
}
|
||||
},
|
||||
winit::event::WindowEvent::CursorMoved { position, .. } => {
|
||||
let toolbar_height = self.toolbar_height.get() * self.hidpi_factor();
|
||||
let mut position = winit_position_to_euclid_point(position).to_f32();
|
||||
position -= Size2D::from_lengths(Length::zero(), toolbar_height);
|
||||
let position = winit_position_to_euclid_point(position);
|
||||
self.mouse_pos.set(position.to_i32());
|
||||
self.event_queue
|
||||
.borrow_mut()
|
||||
|
@ -476,7 +476,9 @@ impl WindowPortsMethods for Window {
|
|||
.resize(physical_size.to_i32())
|
||||
.expect("Failed to resize");
|
||||
self.inner_size.set(new_size);
|
||||
self.event_queue.borrow_mut().push(EmbedderEvent::Resize);
|
||||
self.event_queue
|
||||
.borrow_mut()
|
||||
.push(EmbedderEvent::WindowResize);
|
||||
}
|
||||
},
|
||||
_ => {},
|
||||
|
@ -510,6 +512,10 @@ impl WindowPortsMethods for Window {
|
|||
Some(&self.winit_window)
|
||||
}
|
||||
|
||||
fn toolbar_height(&self) -> Length<f32, DeviceIndependentPixel> {
|
||||
self.toolbar_height.get()
|
||||
}
|
||||
|
||||
fn set_toolbar_height(&self, height: Length<f32, DeviceIndependentPixel>) {
|
||||
self.toolbar_height.set(height);
|
||||
}
|
||||
|
@ -520,13 +526,8 @@ impl WindowMethods for Window {
|
|||
let window_size = winit_size_to_euclid_size(self.winit_window.outer_size()).to_i32();
|
||||
let window_origin = self.winit_window.outer_position().unwrap_or_default();
|
||||
let window_origin = winit_position_to_euclid_point(window_origin).to_i32();
|
||||
let inner_size = winit_size_to_euclid_size(self.winit_window.inner_size()).to_f32();
|
||||
|
||||
// Subtract the minibrowser toolbar height if any
|
||||
let toolbar_height = self.toolbar_height.get() * self.hidpi_factor();
|
||||
let viewport_size = inner_size - Size2D::from_lengths(Length::zero(), toolbar_height);
|
||||
|
||||
let viewport_origin = DeviceIntPoint::zero(); // bottom left
|
||||
let viewport_size = winit_size_to_euclid_size(self.winit_window.inner_size()).to_f32();
|
||||
let viewport = DeviceIntRect::from_origin_and_size(viewport_origin, viewport_size.to_i32());
|
||||
let screen = self.screen_size.to_i32();
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@ use std::cell::Cell;
|
|||
use std::rc::Rc;
|
||||
use std::sync::RwLock;
|
||||
|
||||
use euclid::num::Zero;
|
||||
use euclid::{Length, Point2D, Rotation3D, Scale, Size2D, UnknownUnit, Vector3D};
|
||||
use log::warn;
|
||||
use servo::compositing::windowing::{
|
||||
|
@ -93,7 +94,7 @@ impl WindowPortsMethods for Window {
|
|||
Ok(()) => {
|
||||
self.inner_size.set(new_size);
|
||||
if let Ok(ref mut queue) = self.event_queue.write() {
|
||||
queue.push(EmbedderEvent::Resize);
|
||||
queue.push(EmbedderEvent::WindowResize);
|
||||
}
|
||||
},
|
||||
Err(error) => warn!("Could not resize window: {error:?}"),
|
||||
|
@ -148,6 +149,10 @@ impl WindowPortsMethods for Window {
|
|||
None
|
||||
}
|
||||
|
||||
fn toolbar_height(&self) -> Length<f32, DeviceIndependentPixel> {
|
||||
Length::zero()
|
||||
}
|
||||
|
||||
fn set_toolbar_height(&self, _height: Length<f32, DeviceIndependentPixel>) {
|
||||
unimplemented!("headless Window only")
|
||||
}
|
||||
|
|
|
@ -7,10 +7,13 @@ use std::num::NonZeroU32;
|
|||
use std::sync::Arc;
|
||||
use std::time::Instant;
|
||||
|
||||
use egui::{CentralPanel, Color32, Frame, Key, Modifiers, PaintCallback, Spinner, TopBottomPanel};
|
||||
use egui::{
|
||||
CentralPanel, Color32, Frame, Key, Modifiers, PaintCallback, Pos2, Spinner, TopBottomPanel,
|
||||
Vec2,
|
||||
};
|
||||
use egui_glow::CallbackFn;
|
||||
use egui_winit::EventResponse;
|
||||
use euclid::{Length, Point2D, Scale};
|
||||
use euclid::{Box2D, Length, Point2D, Scale, Size2D};
|
||||
use gleam::gl;
|
||||
use glow::NativeFramebuffer;
|
||||
use log::{trace, warn};
|
||||
|
@ -19,6 +22,7 @@ use servo::msg::constellation_msg::TraversalDirection;
|
|||
use servo::rendering_context::RenderingContext;
|
||||
use servo::servo_geometry::DeviceIndependentPixel;
|
||||
use servo::servo_url::ServoUrl;
|
||||
use servo::style_traits::DevicePixel;
|
||||
|
||||
use crate::egui_glue::EguiGlow;
|
||||
use crate::events_loop::EventsLoop;
|
||||
|
@ -124,6 +128,7 @@ impl Minibrowser {
|
|||
pub fn update(
|
||||
&mut self,
|
||||
window: &winit::window::Window,
|
||||
webviews: &mut WebViewManager<dyn WindowPortsMethods>,
|
||||
servo_framebuffer_id: Option<gl::GLuint>,
|
||||
reason: &'static str,
|
||||
) {
|
||||
|
@ -203,9 +208,32 @@ impl Minibrowser {
|
|||
// point, but the Context is correct and the TopBottomPanel is wrong.
|
||||
*toolbar_height = Length::new(ctx.available_rect().min.y);
|
||||
|
||||
let scale =
|
||||
Scale::<_, DeviceIndependentPixel, DevicePixel>::new(ctx.pixels_per_point());
|
||||
let Some(focused_webview_id) = webviews.focused_webview_id() else {
|
||||
return;
|
||||
};
|
||||
let Some(webview) = webviews.get_mut(focused_webview_id) else {
|
||||
return;
|
||||
};
|
||||
let mut embedder_events = vec![];
|
||||
CentralPanel::default()
|
||||
.frame(Frame::none())
|
||||
.show(ctx, |ui| {
|
||||
let Pos2 { x, y } = ui.cursor().min;
|
||||
let Vec2 {
|
||||
x: width,
|
||||
y: height,
|
||||
} = ui.available_size();
|
||||
let rect = Box2D::from_origin_and_size(
|
||||
Point2D::new(x, y),
|
||||
Size2D::new(width, height),
|
||||
) * scale;
|
||||
if rect != webview.rect {
|
||||
webview.rect = rect;
|
||||
embedder_events
|
||||
.push(EmbedderEvent::MoveResizeWebView(focused_webview_id, rect));
|
||||
}
|
||||
let min = ui.cursor().min;
|
||||
let size = ui.available_size();
|
||||
let rect = egui::Rect::from_min_size(min, size);
|
||||
|
@ -255,6 +283,10 @@ impl Minibrowser {
|
|||
});
|
||||
});
|
||||
|
||||
if !embedder_events.is_empty() {
|
||||
webviews.handle_window_events(embedder_events);
|
||||
}
|
||||
|
||||
*last_update = now;
|
||||
});
|
||||
}
|
||||
|
|
|
@ -81,7 +81,7 @@ mod from_winit {
|
|||
Self::Suspended => target!("Suspended"),
|
||||
Self::Resumed => target!("Resumed"),
|
||||
Self::MainEventsCleared => target!("MainEventsCleared"),
|
||||
Self::RedrawRequested(_) => target!("RedrawRequested"),
|
||||
Self::RedrawRequested(..) => target!("RedrawRequested"),
|
||||
Self::RedrawEventsCleared => target!("RedrawEventsCleared"),
|
||||
Self::LoopDestroyed => target!("LoopDestroyed"),
|
||||
}
|
||||
|
@ -96,18 +96,18 @@ mod from_winit {
|
|||
};
|
||||
}
|
||||
match self {
|
||||
Self::Resized(_) => target_variant!("Resized"),
|
||||
Self::Moved(_) => target_variant!("Moved"),
|
||||
Self::Resized(..) => target_variant!("Resized"),
|
||||
Self::Moved(..) => target_variant!("Moved"),
|
||||
Self::CloseRequested => target_variant!("CloseRequested"),
|
||||
Self::Destroyed => target_variant!("Destroyed"),
|
||||
Self::DroppedFile(_) => target_variant!("DroppedFile"),
|
||||
Self::HoveredFile(_) => target_variant!("HoveredFile"),
|
||||
Self::DroppedFile(..) => target_variant!("DroppedFile"),
|
||||
Self::HoveredFile(..) => target_variant!("HoveredFile"),
|
||||
Self::HoveredFileCancelled => target_variant!("HoveredFileCancelled"),
|
||||
Self::ReceivedCharacter(_) => target_variant!("ReceivedCharacter"),
|
||||
Self::Focused(_) => target_variant!("Focused"),
|
||||
Self::ReceivedCharacter(..) => target_variant!("ReceivedCharacter"),
|
||||
Self::Focused(..) => target_variant!("Focused"),
|
||||
Self::KeyboardInput { .. } => target_variant!("KeyboardInput"),
|
||||
Self::ModifiersChanged(_) => target_variant!("ModifiersChanged"),
|
||||
Self::Ime(_) => target_variant!("Ime"),
|
||||
Self::ModifiersChanged(..) => target_variant!("ModifiersChanged"),
|
||||
Self::Ime(..) => target_variant!("Ime"),
|
||||
Self::CursorMoved { .. } => target_variant!("CursorMoved"),
|
||||
Self::CursorEntered { .. } => target_variant!("CursorEntered"),
|
||||
Self::CursorLeft { .. } => target_variant!("CursorLeft"),
|
||||
|
@ -118,10 +118,10 @@ mod from_winit {
|
|||
Self::TouchpadRotate { .. } => target_variant!("TouchpadRotate"),
|
||||
Self::TouchpadPressure { .. } => target_variant!("TouchpadPressure"),
|
||||
Self::AxisMotion { .. } => target_variant!("AxisMotion"),
|
||||
Self::Touch(_) => target_variant!("Touch"),
|
||||
Self::Touch(..) => target_variant!("Touch"),
|
||||
Self::ScaleFactorChanged { .. } => target_variant!("ScaleFactorChanged"),
|
||||
Self::ThemeChanged(_) => target_variant!("ThemeChanged"),
|
||||
Self::Occluded(_) => target_variant!("Occluded"),
|
||||
Self::ThemeChanged(..) => target_variant!("ThemeChanged"),
|
||||
Self::Occluded(..) => target_variant!("Occluded"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -139,41 +139,41 @@ mod from_servo {
|
|||
impl LogTarget for servo::embedder_traits::EmbedderMsg {
|
||||
fn log_target(&self) -> &'static str {
|
||||
match self {
|
||||
Self::Status(_) => target!("Status"),
|
||||
Self::ChangePageTitle(_) => target!("ChangePageTitle"),
|
||||
Self::MoveTo(_) => target!("MoveTo"),
|
||||
Self::ResizeTo(_) => target!("ResizeTo"),
|
||||
Self::Prompt(_, _) => target!("Prompt"),
|
||||
Self::ShowContextMenu(_, _, _) => target!("ShowContextMenu"),
|
||||
Self::AllowNavigationRequest(_, _) => target!("AllowNavigationRequest"),
|
||||
Self::AllowOpeningWebView(_) => target!("AllowOpeningWebView"),
|
||||
Self::WebViewOpened(_) => target!("WebViewOpened"),
|
||||
Self::WebViewClosed(_) => target!("WebViewClosed"),
|
||||
Self::WebViewFocused(_) => target!("WebViewFocused"),
|
||||
Self::Status(..) => target!("Status"),
|
||||
Self::ChangePageTitle(..) => target!("ChangePageTitle"),
|
||||
Self::MoveTo(..) => target!("MoveTo"),
|
||||
Self::ResizeTo(..) => target!("ResizeTo"),
|
||||
Self::Prompt(..) => target!("Prompt"),
|
||||
Self::ShowContextMenu(..) => target!("ShowContextMenu"),
|
||||
Self::AllowNavigationRequest(..) => target!("AllowNavigationRequest"),
|
||||
Self::AllowOpeningWebView(..) => target!("AllowOpeningWebView"),
|
||||
Self::WebViewOpened(..) => target!("WebViewOpened"),
|
||||
Self::WebViewClosed(..) => target!("WebViewClosed"),
|
||||
Self::WebViewFocused(..) => target!("WebViewFocused"),
|
||||
Self::WebViewBlurred => target!("WebViewBlurred"),
|
||||
Self::AllowUnload(_) => target!("AllowUnload"),
|
||||
Self::Keyboard(_) => target!("Keyboard"),
|
||||
Self::GetClipboardContents(_) => target!("GetClipboardContents"),
|
||||
Self::SetClipboardContents(_) => target!("SetClipboardContents"),
|
||||
Self::SetCursor(_) => target!("SetCursor"),
|
||||
Self::NewFavicon(_) => target!("NewFavicon"),
|
||||
Self::AllowUnload(..) => target!("AllowUnload"),
|
||||
Self::Keyboard(..) => target!("Keyboard"),
|
||||
Self::GetClipboardContents(..) => target!("GetClipboardContents"),
|
||||
Self::SetClipboardContents(..) => target!("SetClipboardContents"),
|
||||
Self::SetCursor(..) => target!("SetCursor"),
|
||||
Self::NewFavicon(..) => target!("NewFavicon"),
|
||||
Self::HeadParsed => target!("HeadParsed"),
|
||||
Self::HistoryChanged(_, _) => target!("HistoryChanged"),
|
||||
Self::SetFullscreenState(_) => target!("SetFullscreenState"),
|
||||
Self::HistoryChanged(..) => target!("HistoryChanged"),
|
||||
Self::SetFullscreenState(..) => target!("SetFullscreenState"),
|
||||
Self::LoadStart => target!("LoadStart"),
|
||||
Self::LoadComplete => target!("LoadComplete"),
|
||||
Self::Panic(_, _) => target!("Panic"),
|
||||
Self::GetSelectedBluetoothDevice(_, _) => target!("GetSelectedBluetoothDevice"),
|
||||
Self::SelectFiles(_, _, _) => target!("SelectFiles"),
|
||||
Self::PromptPermission(_, _) => target!("PromptPermission"),
|
||||
Self::ShowIME(_, _, _, _) => target!("ShowIME"),
|
||||
Self::Panic(..) => target!("Panic"),
|
||||
Self::GetSelectedBluetoothDevice(..) => target!("GetSelectedBluetoothDevice"),
|
||||
Self::SelectFiles(..) => target!("SelectFiles"),
|
||||
Self::PromptPermission(..) => target!("PromptPermission"),
|
||||
Self::ShowIME(..) => target!("ShowIME"),
|
||||
Self::HideIME => target!("HideIME"),
|
||||
Self::Shutdown => target!("Shutdown"),
|
||||
Self::ReportProfile(_) => target!("ReportProfile"),
|
||||
Self::MediaSessionEvent(_) => target!("MediaSessionEvent"),
|
||||
Self::OnDevtoolsStarted(_, _) => target!("OnDevtoolsStarted"),
|
||||
Self::ReadyToPresent => target!("ReadyToPresent"),
|
||||
Self::EventDelivered(_) => target!("EventDelivered"),
|
||||
Self::ReportProfile(..) => target!("ReportProfile"),
|
||||
Self::MediaSessionEvent(..) => target!("MediaSessionEvent"),
|
||||
Self::OnDevtoolsStarted(..) => target!("OnDevtoolsStarted"),
|
||||
Self::ReadyToPresent(..) => target!("ReadyToPresent"),
|
||||
Self::EventDelivered(..) => target!("EventDelivered"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -193,36 +193,41 @@ mod to_servo {
|
|||
match self {
|
||||
Self::Idle => target!("Idle"),
|
||||
Self::Refresh => target!("Refresh"),
|
||||
Self::Resize => target!("Resize"),
|
||||
Self::AllowNavigationResponse(_, _) => target!("AllowNavigationResponse"),
|
||||
Self::LoadUrl(_, _) => target!("LoadUrl"),
|
||||
Self::MouseWindowEventClass(_) => target!("MouseWindowEventClass"),
|
||||
Self::MouseWindowMoveEventClass(_) => target!("MouseWindowMoveEventClass"),
|
||||
Self::Touch(_, _, _) => target!("Touch"),
|
||||
Self::Wheel(_, _) => target!("Wheel"),
|
||||
Self::Scroll(_, _, _) => target!("Scroll"),
|
||||
Self::Zoom(_) => target!("Zoom"),
|
||||
Self::PinchZoom(_) => target!("PinchZoom"),
|
||||
Self::WindowResize => target!("WindowResize"),
|
||||
Self::AllowNavigationResponse(..) => target!("AllowNavigationResponse"),
|
||||
Self::LoadUrl(..) => target!("LoadUrl"),
|
||||
Self::MouseWindowEventClass(..) => target!("MouseWindowEventClass"),
|
||||
Self::MouseWindowMoveEventClass(..) => target!("MouseWindowMoveEventClass"),
|
||||
Self::Touch(..) => target!("Touch"),
|
||||
Self::Wheel(..) => target!("Wheel"),
|
||||
Self::Scroll(..) => target!("Scroll"),
|
||||
Self::Zoom(..) => target!("Zoom"),
|
||||
Self::PinchZoom(..) => target!("PinchZoom"),
|
||||
Self::ResetZoom => target!("ResetZoom"),
|
||||
Self::Navigation(_, _) => target!("Navigation"),
|
||||
Self::Navigation(..) => target!("Navigation"),
|
||||
Self::Quit => target!("Quit"),
|
||||
Self::ExitFullScreen(_) => target!("ExitFullScreen"),
|
||||
Self::Keyboard(_) => target!("Keyboard"),
|
||||
Self::Reload(_) => target!("Reload"),
|
||||
Self::NewWebView(_, _) => target!("NewWebView"),
|
||||
Self::CloseWebView(_) => target!("CloseWebView"),
|
||||
Self::SendError(_, _) => target!("SendError"),
|
||||
Self::FocusWebView(_) => target!("FocusWebView"),
|
||||
Self::ToggleWebRenderDebug(_) => target!("ToggleWebRenderDebug"),
|
||||
Self::ExitFullScreen(..) => target!("ExitFullScreen"),
|
||||
Self::Keyboard(..) => target!("Keyboard"),
|
||||
Self::Reload(..) => target!("Reload"),
|
||||
Self::NewWebView(..) => target!("NewWebView"),
|
||||
Self::CloseWebView(..) => target!("CloseWebView"),
|
||||
Self::SendError(..) => target!("SendError"),
|
||||
Self::MoveResizeWebView(..) => target!("MoveResizeWebView"),
|
||||
Self::ShowWebView(..) => target!("ShowWebView"),
|
||||
Self::HideWebView(..) => target!("HideWebView"),
|
||||
Self::RaiseWebViewToTop(..) => target!("RaiseWebViewToTop"),
|
||||
Self::FocusWebView(..) => target!("FocusWebView"),
|
||||
Self::BlurWebView => target!("BlurWebView"),
|
||||
Self::ToggleWebRenderDebug(..) => target!("ToggleWebRenderDebug"),
|
||||
Self::CaptureWebRender => target!("CaptureWebRender"),
|
||||
Self::ClearCache => target!("ClearCache"),
|
||||
Self::ToggleSamplingProfiler(_, _) => target!("ToggleSamplingProfiler"),
|
||||
Self::MediaSessionAction(_) => target!("MediaSessionAction"),
|
||||
Self::SetWebViewThrottled(_, _) => target!("SetWebViewThrottled"),
|
||||
Self::ToggleSamplingProfiler(..) => target!("ToggleSamplingProfiler"),
|
||||
Self::MediaSessionAction(..) => target!("MediaSessionAction"),
|
||||
Self::SetWebViewThrottled(..) => target!("SetWebViewThrottled"),
|
||||
Self::IMEDismissed => target!("IMEDismissed"),
|
||||
Self::InvalidateNativeSurface => target!("InvalidateNativeSurface"),
|
||||
Self::ReplaceNativeSurface(_, _) => target!("ReplaceNativeSurface"),
|
||||
Self::Gamepad(_) => target!("Gamepad"),
|
||||
Self::ReplaceNativeSurface(..) => target!("ReplaceNativeSurface"),
|
||||
Self::Gamepad(..) => target!("Gamepad"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,6 +26,7 @@ use servo::script_traits::{
|
|||
};
|
||||
use servo::servo_config::opts;
|
||||
use servo::servo_url::ServoUrl;
|
||||
use servo::webrender_api::units::DeviceRect;
|
||||
use servo::webrender_api::ScrollLocation;
|
||||
use tinyfiledialogs::{self, MessageBoxIcon, OkCancel, YesNo};
|
||||
|
||||
|
@ -60,7 +61,9 @@ pub struct WebViewManager<Window: WindowPortsMethods + ?Sized> {
|
|||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct WebView {}
|
||||
pub struct WebView {
|
||||
pub rect: DeviceRect,
|
||||
}
|
||||
|
||||
pub struct ServoEventResponse {
|
||||
pub need_present: bool,
|
||||
|
@ -111,6 +114,14 @@ where
|
|||
self.focused_webview_id
|
||||
}
|
||||
|
||||
pub fn get_mut(&mut self, webview_id: WebViewId) -> Option<&mut WebView> {
|
||||
self.webviews.get_mut(&webview_id)
|
||||
}
|
||||
|
||||
pub fn focused_webview_id(&self) -> Option<WebViewId> {
|
||||
self.focused_webview_id.clone()
|
||||
}
|
||||
|
||||
pub fn current_url_string(&self) -> Option<&str> {
|
||||
self.current_url_string.as_deref()
|
||||
}
|
||||
|
@ -453,6 +464,20 @@ where
|
|||
self.window.set_position(point);
|
||||
},
|
||||
EmbedderMsg::ResizeTo(size) => {
|
||||
if let Some(webview_id) = webview_id {
|
||||
let new_rect = self.get_mut(webview_id).and_then(|webview| {
|
||||
if webview.rect.size() != size.to_f32() {
|
||||
webview.rect.set_size(size.to_f32());
|
||||
Some(webview.rect)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
});
|
||||
if let Some(new_rect) = new_rect {
|
||||
self.event_queue
|
||||
.push(EmbedderEvent::MoveResizeWebView(webview_id, new_rect));
|
||||
}
|
||||
}
|
||||
self.window.set_inner_size(size);
|
||||
},
|
||||
EmbedderMsg::Prompt(definition, origin) => {
|
||||
|
@ -555,10 +580,22 @@ where
|
|||
};
|
||||
},
|
||||
EmbedderMsg::WebViewOpened(new_webview_id) => {
|
||||
self.webviews.insert(new_webview_id, WebView {});
|
||||
let scale = self.window.hidpi_factor().get();
|
||||
let toolbar = self.window.toolbar_height().get();
|
||||
|
||||
// Adjust for our toolbar height.
|
||||
// TODO: Adjust for egui window decorations if we end up using those
|
||||
let mut rect = self.window.get_coordinates().get_viewport().to_f32();
|
||||
rect.min.y += toolbar * scale;
|
||||
|
||||
self.webviews.insert(new_webview_id, WebView { rect });
|
||||
self.creation_order.push(new_webview_id);
|
||||
self.event_queue
|
||||
.push(EmbedderEvent::FocusWebView(new_webview_id));
|
||||
self.event_queue
|
||||
.push(EmbedderEvent::MoveResizeWebView(new_webview_id, rect));
|
||||
self.event_queue
|
||||
.push(EmbedderEvent::RaiseWebViewToTop(new_webview_id, true));
|
||||
},
|
||||
EmbedderMsg::WebViewClosed(webview_id) => {
|
||||
self.webviews.retain(|&id, _| id != webview_id);
|
||||
|
@ -573,6 +610,10 @@ where
|
|||
},
|
||||
EmbedderMsg::WebViewFocused(webview_id) => {
|
||||
self.focused_webview_id = Some(webview_id);
|
||||
// Show the most recently created webview and hide all others.
|
||||
// TODO: Stop doing this once we have full multiple webviews support
|
||||
self.event_queue
|
||||
.push(EmbedderEvent::ShowWebView(webview_id, true));
|
||||
},
|
||||
EmbedderMsg::WebViewBlurred => {
|
||||
self.focused_webview_id = None;
|
||||
|
@ -681,15 +722,18 @@ where
|
|||
EmbedderMsg::ShowContextMenu(sender, ..) => {
|
||||
let _ = sender.send(ContextMenuResult::Ignored);
|
||||
},
|
||||
EmbedderMsg::ReadyToPresent => {
|
||||
EmbedderMsg::ReadyToPresent(_webview_ids) => {
|
||||
need_present = true;
|
||||
},
|
||||
EmbedderMsg::EventDelivered(event) => {
|
||||
if let (Some(webview_id), CompositorEventVariant::MouseButtonEvent) =
|
||||
(webview_id, event)
|
||||
{
|
||||
// TODO Focus webview and/or raise to top if needed.
|
||||
trace!("{}: Got a mouse button event", webview_id);
|
||||
self.event_queue
|
||||
.push(EmbedderEvent::RaiseWebViewToTop(webview_id, true));
|
||||
self.event_queue
|
||||
.push(EmbedderEvent::FocusWebView(webview_id));
|
||||
}
|
||||
},
|
||||
}
|
||||
|
|
|
@ -47,5 +47,6 @@ pub trait WindowPortsMethods: WindowMethods {
|
|||
events_loop: &winit::event_loop::EventLoopWindowTarget<WakerEvent>,
|
||||
) -> Box<dyn webxr::glwindow::GlWindow>;
|
||||
fn winit_window(&self) -> Option<&winit::window::Window>;
|
||||
fn toolbar_height(&self) -> Length<f32, DeviceIndependentPixel>;
|
||||
fn set_toolbar_height(&self, height: Length<f32, DeviceIndependentPixel>);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue