From 84006ba76d1d6d7f64104d4c708e83610d6938df Mon Sep 17 00:00:00 2001 From: Martin Robinson Date: Mon, 10 Feb 2025 05:14:16 +0100 Subject: [PATCH] libservo: Remove message-based API (#35366) Signed-off-by: Martin Robinson --- components/compositing/compositor.rs | 27 +- components/compositing/windowing.rs | 167 +---- components/constellation/tracing.rs | 1 - components/servo/lib.rs | 894 +++++++++------------------ components/shared/embedder/lib.rs | 3 - 5 files changed, 301 insertions(+), 791 deletions(-) diff --git a/components/compositing/compositor.rs b/components/compositing/compositor.rs index 7ba12d2cc32..6aa3e74518f 100644 --- a/components/compositing/compositor.rs +++ b/components/compositing/compositor.rs @@ -482,25 +482,25 @@ impl IOCompositor { self.shutdown_state = ShutdownState::FinishedShuttingDown; } - fn handle_browser_message(&mut self, msg: CompositorMsg) -> bool { + fn handle_browser_message(&mut self, msg: CompositorMsg) { trace_msg_from_constellation!(msg, "{msg:?}"); match self.shutdown_state { ShutdownState::NotShuttingDown => {}, ShutdownState::ShuttingDown => { - return self.handle_browser_message_while_shutting_down(msg) + self.handle_browser_message_while_shutting_down(msg); + return; }, ShutdownState::FinishedShuttingDown => { - error!("compositor shouldn't be handling messages after shutting down"); - return false; + // Messages to the compositor are ignored after shutdown is complete. + return; }, } match msg { CompositorMsg::ShutdownComplete => { - warn!("Received `ShutdownComplete` while not shutting down."); + error!("Received `ShutdownComplete` while not shutting down."); self.finish_shutting_down(); - return false; }, CompositorMsg::ChangeRunningAnimationsState(pipeline_id, animation_state) => { @@ -605,8 +605,6 @@ impl IOCompositor { self.handle_cross_process_message(cross_proces_message); }, } - - true } /// Accept messages from content processes that need to be relayed to the WebRender @@ -843,11 +841,10 @@ impl IOCompositor { /// When that involves generating WebRender ids, our approach here is to simply /// generate them, but assume they will never be used, since once shutting down the /// compositor no longer does any WebRender frame generation. - fn handle_browser_message_while_shutting_down(&mut self, msg: CompositorMsg) -> bool { + fn handle_browser_message_while_shutting_down(&mut self, msg: CompositorMsg) { match msg { CompositorMsg::ShutdownComplete => { self.finish_shutting_down(); - return false; }, CompositorMsg::PipelineExited(pipeline_id, sender) => { debug!("Compositor got pipeline exited: {:?}", pipeline_id); @@ -902,7 +899,6 @@ impl IOCompositor { debug!("Ignoring message ({:?} while shutting down", msg); }, } - true } /// Queue a new frame in the transaction and increase the pending frames count. @@ -2311,7 +2307,7 @@ impl IOCompositor { feature = "tracing", tracing::instrument(skip_all, fields(servo_profiling = true), level = "trace") )] - pub fn receive_messages(&mut self) -> bool { + pub fn receive_messages(&mut self) { // Check for new messages coming from the other threads in the system. let mut compositor_messages = vec![]; let mut found_recomposite_msg = false; @@ -2330,11 +2326,12 @@ impl IOCompositor { } } for msg in compositor_messages { - if !self.handle_browser_message(msg) { - return false; + self.handle_browser_message(msg); + + if self.shutdown_state == ShutdownState::FinishedShuttingDown { + return; } } - true } #[cfg_attr( diff --git a/components/compositing/windowing.rs b/components/compositing/windowing.rs index 8db640a89a1..5587799bfdc 100644 --- a/components/compositing/windowing.rs +++ b/components/compositing/windowing.rs @@ -4,23 +4,13 @@ //! Abstract windowing methods. The concrete implementations of these can be found in `platform/`. -use std::fmt::{Debug, Error, Formatter}; -use std::time::Duration; +use std::fmt::Debug; -use base::id::{PipelineId, TopLevelBrowsingContextId, WebViewId}; -use embedder_traits::{ - ClipboardEventType, EventLoopWaker, GamepadEvent, MediaSessionActionType, MouseButton, Theme, - TouchEventType, TouchId, TraversalDirection, WheelDelta, -}; +use embedder_traits::{EventLoopWaker, MouseButton}; use euclid::Scale; -use keyboard_types::{CompositionEvent, KeyboardEvent}; use net::protocols::ProtocolRegistry; use servo_geometry::{DeviceIndependentIntRect, DeviceIndependentIntSize, DeviceIndependentPixel}; -use servo_url::ServoUrl; -use webrender_api::units::{ - DeviceIntPoint, DeviceIntRect, DeviceIntSize, DevicePixel, DevicePoint, DeviceRect, -}; -use webrender_api::ScrollLocation; +use webrender_api::units::{DeviceIntRect, DeviceIntSize, DevicePixel, DevicePoint}; #[derive(Clone)] pub enum MouseWindowEvent { @@ -37,157 +27,6 @@ pub enum WebRenderDebugOption { RenderTargetDebug, } -/// Events that the embedder sends to Servo, including events from the windowing system. -#[derive(Clone)] -pub enum EmbedderEvent { - /// Sent when no message has arrived, but the event loop was kicked for some reason (perhaps - /// by another Servo subsystem). - /// - /// FIXME(pcwalton): This is kind of ugly and may not work well with multiprocess Servo. - /// It's possible that this should be something like - /// `CompositorMessageWindowEvent(compositor_thread::Msg)` instead. - Idle, - /// Sent when part of the window is marked dirty and needs to be redrawn. Before sending this - /// message, the window must make the same GL context as in `PrepareRenderingEvent` current. - Refresh, - /// Sent when the platform theme changes. - ThemeChange(Theme), - /// Sent when a navigation request from script is allowed/refused. - AllowNavigationResponse(PipelineId, bool), - /// Sent when a new URL is to be loaded. - LoadUrl(TopLevelBrowsingContextId, ServoUrl), - /// Sent when a mouse hit test is to be performed. - MouseWindowEventClass(MouseWindowEvent), - /// Sent when a mouse move. - MouseWindowMoveEventClass(DevicePoint), - /// Touch event: type, identifier, point - Touch(TouchEventType, TouchId, DevicePoint), - /// Sent when user moves the mouse wheel. - Wheel(WheelDelta, DevicePoint), - /// Sent when the user scrolls. The first point is the delta and the second point is the - /// origin. - Scroll(ScrollLocation, DeviceIntPoint, TouchEventType), - /// Sent when the user zooms. - Zoom(f32), - /// Simulated "pinch zoom" gesture for non-touch platforms (e.g. ctrl-scrollwheel). - PinchZoom(f32), - /// Sent when the user resets zoom to default. - ResetZoom, - /// Sent when the user uses chrome navigation (i.e. backspace or shift-backspace). - Navigation(TopLevelBrowsingContextId, TraversalDirection), - /// Sent when the user quits the application - Quit, - /// Sent when the user exits from fullscreen mode - ExitFullScreen(TopLevelBrowsingContextId), - /// Sent when a key input state changes - Keyboard(WebViewId, KeyboardEvent), - /// Sent for IME composition updates - IMEComposition(CompositionEvent), - /// Sent when Ctr+R/Apple+R is called to reload the current page. - Reload(TopLevelBrowsingContextId), - /// Create a new top-level browsing context. - NewWebView(ServoUrl, TopLevelBrowsingContextId), - /// Close a top-level browsing context. - CloseWebView(TopLevelBrowsingContextId), - /// Panic a top-level browsing context. - SendError(Option, String), - /// Move and/or resize a webview to the given rect. - MoveResizeWebView(TopLevelBrowsingContextId, DeviceRect), - /// Start painting a webview, and optionally stop painting all others. - ShowWebView(TopLevelBrowsingContextId, bool), - /// Stop painting a webview. - HideWebView(TopLevelBrowsingContextId), - /// Start painting a webview on top of all others, and optionally stop painting all others. - RaiseWebViewToTop(TopLevelBrowsingContextId, bool), - /// Make a webview focused. - FocusWebView(TopLevelBrowsingContextId), - /// Make none of the webviews focused. - BlurWebView, - /// Toggles a debug flag in WebRender - ToggleWebRenderDebug(WebRenderDebugOption), - /// Capture current WebRender - CaptureWebRender, - /// Clear the network cache. - ClearCache, - /// Toggle sampling profiler with the given sampling rate and max duration. - ToggleSamplingProfiler(Duration, Duration), - /// Sent when the user triggers a media action through the UA exposed media UI - /// (play, pause, seek, etc.). - MediaSessionAction(MediaSessionActionType), - /// Set whether to use less resources, by stopping animations and running timers at a heavily limited rate. - SetWebViewThrottled(TopLevelBrowsingContextId, bool), - /// Virtual keyboard was dismissed - IMEDismissed, - /// Sent when new Gamepad information is available. - Gamepad(GamepadEvent), - /// Vertical Synchronization tick - Vsync, - /// Sent when access to clipboard is required - ClipboardAction(ClipboardEventType), -} - -impl Debug for EmbedderEvent { - fn fmt(&self, f: &mut Formatter) -> Result<(), Error> { - match *self { - EmbedderEvent::Idle => write!(f, "Idle"), - EmbedderEvent::Refresh => write!(f, "Refresh"), - EmbedderEvent::ThemeChange(..) => write!(f, "ThemeChange"), - EmbedderEvent::Keyboard(..) => write!(f, "Keyboard"), - EmbedderEvent::IMEComposition(..) => write!(f, "IMEComposition"), - EmbedderEvent::AllowNavigationResponse(..) => write!(f, "AllowNavigationResponse"), - EmbedderEvent::LoadUrl(..) => write!(f, "LoadUrl"), - EmbedderEvent::MouseWindowEventClass(..) => write!(f, "Mouse"), - EmbedderEvent::MouseWindowMoveEventClass(..) => write!(f, "MouseMove"), - EmbedderEvent::Touch(..) => write!(f, "Touch"), - EmbedderEvent::Wheel(..) => write!(f, "Wheel"), - EmbedderEvent::Scroll(..) => write!(f, "Scroll"), - EmbedderEvent::Zoom(..) => write!(f, "Zoom"), - EmbedderEvent::PinchZoom(..) => write!(f, "PinchZoom"), - EmbedderEvent::ResetZoom => write!(f, "ResetZoom"), - EmbedderEvent::Navigation(..) => write!(f, "Navigation"), - EmbedderEvent::Quit => write!(f, "Quit"), - EmbedderEvent::Reload(..) => write!(f, "Reload"), - EmbedderEvent::NewWebView(_, TopLevelBrowsingContextId(webview_id)) => { - write!(f, "NewWebView({webview_id:?})") - }, - EmbedderEvent::SendError(..) => write!(f, "SendError"), - EmbedderEvent::CloseWebView(TopLevelBrowsingContextId(webview_id)) => { - write!(f, "CloseWebView({webview_id:?})") - }, - EmbedderEvent::MoveResizeWebView(webview_id, _) => { - write!(f, "MoveResizeWebView({webview_id:?})") - }, - EmbedderEvent::ShowWebView(TopLevelBrowsingContextId(webview_id), hide_others) => { - write!(f, "ShowWebView({webview_id:?}, {hide_others})") - }, - EmbedderEvent::HideWebView(TopLevelBrowsingContextId(webview_id)) => { - write!(f, "HideWebView({webview_id:?})") - }, - EmbedderEvent::RaiseWebViewToTop( - TopLevelBrowsingContextId(webview_id), - hide_others, - ) => { - write!(f, "RaiseWebViewToTop({webview_id:?}, {hide_others})") - }, - EmbedderEvent::FocusWebView(TopLevelBrowsingContextId(webview_id)) => { - write!(f, "FocusWebView({webview_id:?})") - }, - EmbedderEvent::BlurWebView => write!(f, "BlurWebView"), - EmbedderEvent::ToggleWebRenderDebug(..) => write!(f, "ToggleWebRenderDebug"), - EmbedderEvent::CaptureWebRender => write!(f, "CaptureWebRender"), - EmbedderEvent::ToggleSamplingProfiler(..) => write!(f, "ToggleSamplingProfiler"), - EmbedderEvent::ExitFullScreen(..) => write!(f, "ExitFullScreen"), - EmbedderEvent::MediaSessionAction(..) => write!(f, "MediaSessionAction"), - EmbedderEvent::SetWebViewThrottled(..) => write!(f, "SetWebViewThrottled"), - EmbedderEvent::IMEDismissed => write!(f, "IMEDismissed"), - EmbedderEvent::ClearCache => write!(f, "ClearCache"), - EmbedderEvent::Gamepad(..) => write!(f, "Gamepad"), - EmbedderEvent::Vsync => write!(f, "Vsync"), - EmbedderEvent::ClipboardAction(_) => write!(f, "ClipboardAction"), - } - } -} - #[derive(Clone, Copy, Debug, PartialEq)] pub enum AnimationState { Idle, diff --git a/components/constellation/tracing.rs b/components/constellation/tracing.rs index 08451cd804d..11c05d88700 100644 --- a/components/constellation/tracing.rs +++ b/components/constellation/tracing.rs @@ -243,7 +243,6 @@ mod from_script { Self::PromptPermission(..) => target_variant!("PromptPermission"), Self::ShowIME(..) => target_variant!("ShowIME"), Self::HideIME(..) => target_variant!("HideIME"), - Self::Shutdown => target_variant!("Shutdown"), Self::ReportProfile(..) => target_variant!("ReportProfile"), Self::MediaSessionEvent(..) => target_variant!("MediaSessionEvent"), Self::OnDevtoolsStarted(..) => target_variant!("OnDevtoolsStarted"), diff --git a/components/servo/lib.rs b/components/servo/lib.rs index f32151e27e8..bb55854b519 100644 --- a/components/servo/lib.rs +++ b/components/servo/lib.rs @@ -40,8 +40,7 @@ use canvas::canvas_paint_thread::CanvasPaintThread; use canvas::WebGLComm; use canvas_traits::webgl::{GlType, WebGLThreads}; use clipboard_delegate::StringRequest; -use compositing::webview::UnknownWebView; -use compositing::windowing::{EmbedderEvent, EmbedderMethods, WindowMethods}; +use compositing::windowing::{EmbedderMethods, WindowMethods}; use compositing::{CompositeTarget, IOCompositor, InitialCompositorState, ShutdownState}; use compositing_traits::{CompositorMsg, CompositorProxy, CompositorReceiver, ConstellationMsg}; #[cfg(all( @@ -78,7 +77,7 @@ use ipc_channel::router::ROUTER; pub use keyboard_types::*; #[cfg(feature = "layout_2013")] pub use layout_thread_2013; -use log::{error, trace, warn, Log, Metadata, Record}; +use log::{warn, Log, Metadata, Record}; use media::{GLPlayerThreads, GlApi, NativeDisplay, WindowGLContext}; use net::protocols::ProtocolRegistry; use net::resource_thread::new_resource_threads; @@ -193,7 +192,6 @@ pub struct Servo { compositor: Rc>, constellation_proxy: ConstellationProxy, embedder_receiver: Receiver, - messages_for_embedder: RefCell>, /// A map [`WebView`]s that are managed by this [`Servo`] instance. These are stored /// as `Weak` references so that the embedding application can control their lifetime. /// When accessed, `Servo` will be reponsible for cleaning up the invalid `Weak` @@ -539,7 +537,6 @@ impl Servo { compositor: Rc::new(RefCell::new(compositor)), constellation_proxy: ConstellationProxy::new(constellation_chan), embedder_receiver, - messages_for_embedder: Default::default(), webviews: Default::default(), _js_engine_setup: js_engine_setup, } @@ -615,323 +612,6 @@ impl Servo { ) } - fn handle_window_event(&self, event: EmbedderEvent) { - match event { - EmbedderEvent::Idle => {}, - - EmbedderEvent::Refresh => { - self.compositor.borrow_mut().composite(); - }, - EmbedderEvent::ThemeChange(theme) => { - let msg = ConstellationMsg::ThemeChange(theme); - if let Err(e) = self.constellation_proxy.try_send(msg) { - warn!( - "Sending platform theme change to constellation failed ({:?}).", - e - ) - } - }, - EmbedderEvent::AllowNavigationResponse(pipeline_id, allowed) => { - let msg = ConstellationMsg::AllowNavigationResponse(pipeline_id, allowed); - if let Err(e) = self.constellation_proxy.try_send(msg) { - warn!( - "Sending allow navigation to constellation failed ({:?}).", - e - ); - } - }, - - EmbedderEvent::LoadUrl(webview_id, url) => { - let msg = ConstellationMsg::LoadUrl(webview_id, url); - if let Err(e) = self.constellation_proxy.try_send(msg) { - warn!("Sending load url to constellation failed ({:?}).", e); - } - }, - - EmbedderEvent::ClearCache => { - let msg = ConstellationMsg::ClearCache; - if let Err(e) = self.constellation_proxy.try_send(msg) { - warn!("Sending clear cache to constellation failed ({:?}).", e); - } - }, - - EmbedderEvent::MouseWindowEventClass(mouse_window_event) => { - self.compositor - .borrow_mut() - .on_mouse_window_event_class(mouse_window_event); - }, - - EmbedderEvent::MouseWindowMoveEventClass(cursor) => { - self.compositor - .borrow_mut() - .on_mouse_window_move_event_class(cursor); - }, - - EmbedderEvent::Touch(event_type, identifier, location) => { - self.compositor - .borrow_mut() - .on_touch_event(event_type, identifier, location); - }, - - EmbedderEvent::Wheel(delta, location) => { - self.compositor.borrow_mut().on_wheel_event(delta, location); - }, - - EmbedderEvent::Scroll(scroll_location, cursor, phase) => { - self.compositor - .borrow_mut() - .on_scroll_event(scroll_location, cursor, phase); - }, - - EmbedderEvent::Zoom(magnification) => { - self.compositor - .borrow_mut() - .on_zoom_window_event(magnification); - }, - - EmbedderEvent::ResetZoom => { - self.compositor.borrow_mut().on_zoom_reset_window_event(); - }, - - EmbedderEvent::PinchZoom(zoom) => { - self.compositor - .borrow_mut() - .on_pinch_zoom_window_event(zoom); - }, - - EmbedderEvent::Navigation(webview_id, direction) => { - let msg = ConstellationMsg::TraverseHistory(webview_id, direction); - if let Err(e) = self.constellation_proxy.try_send(msg) { - warn!("Sending navigation to constellation failed ({:?}).", e); - } - self.messages_for_embedder - .borrow_mut() - .push(EmbedderMsg::Status(webview_id, None)); - }, - - EmbedderEvent::Keyboard(webview_id, key_event) => { - let msg = ConstellationMsg::Keyboard(webview_id, key_event); - if let Err(e) = self.constellation_proxy.try_send(msg) { - warn!("Sending keyboard event to constellation failed ({:?}).", e); - } - }, - - EmbedderEvent::IMEComposition(ime_event) => { - let msg = ConstellationMsg::IMECompositionEvent(ime_event); - if let Err(e) = self.constellation_proxy.try_send(msg) { - warn!( - "Sending composition event to constellation failed ({:?}).", - e - ); - } - }, - - EmbedderEvent::IMEDismissed => { - let msg = ConstellationMsg::IMEDismissed; - if let Err(e) = self.constellation_proxy.try_send(msg) { - warn!( - "Sending IMEDismissed event to constellation failed ({:?}).", - e - ); - } - }, - - EmbedderEvent::Quit => { - self.compositor.borrow_mut().maybe_start_shutting_down(); - }, - - EmbedderEvent::ExitFullScreen(webview_id) => { - let msg = ConstellationMsg::ExitFullScreen(webview_id); - if let Err(e) = self.constellation_proxy.try_send(msg) { - warn!("Sending exit fullscreen to constellation failed ({:?}).", e); - } - }, - - EmbedderEvent::Reload(webview_id) => { - let msg = ConstellationMsg::Reload(webview_id); - if let Err(e) = self.constellation_proxy.try_send(msg) { - warn!("Sending reload to constellation failed ({:?}).", e); - } - }, - - EmbedderEvent::ToggleSamplingProfiler(rate, max_duration) => { - if let Err(e) = self - .constellation_proxy - .try_send(ConstellationMsg::ToggleProfiler(rate, max_duration)) - { - warn!("Sending profiler toggle to constellation failed ({:?}).", e); - } - }, - - EmbedderEvent::ToggleWebRenderDebug(option) => { - self.compositor.borrow_mut().toggle_webrender_debug(option); - }, - - EmbedderEvent::CaptureWebRender => { - self.compositor.borrow_mut().capture_webrender(); - }, - - EmbedderEvent::NewWebView(url, webview_id) => { - let msg = ConstellationMsg::NewWebView(url, webview_id); - if let Err(e) = self.constellation_proxy.try_send(msg) { - warn!( - "Sending NewBrowser message to constellation failed ({:?}).", - e - ); - } - }, - - EmbedderEvent::FocusWebView(webview_id) => { - let msg = ConstellationMsg::FocusWebView(webview_id); - if let Err(e) = self.constellation_proxy.try_send(msg) { - warn!( - "Sending FocusBrowser message to constellation failed ({:?}).", - e - ); - } - }, - - EmbedderEvent::CloseWebView(webview_id) => { - let msg = ConstellationMsg::CloseWebView(webview_id); - if let Err(e) = self.constellation_proxy.try_send(msg) { - warn!( - "Sending CloseBrowser message to constellation failed ({:?}).", - e - ); - } - }, - - EmbedderEvent::MoveResizeWebView(webview_id, rect) => { - self.compositor - .borrow_mut() - .move_resize_webview(webview_id, rect); - }, - EmbedderEvent::ShowWebView(webview_id, hide_others) => { - if let Err(UnknownWebView(webview_id)) = self - .compositor - .borrow_mut() - .show_webview(webview_id, hide_others) - { - warn!("{webview_id}: ShowWebView on unknown webview id"); - } - }, - EmbedderEvent::HideWebView(webview_id) => { - if let Err(UnknownWebView(webview_id)) = - self.compositor.borrow_mut().hide_webview(webview_id) - { - warn!("{webview_id}: HideWebView on unknown webview id"); - } - }, - EmbedderEvent::RaiseWebViewToTop(webview_id, hide_others) => { - if let Err(UnknownWebView(webview_id)) = self - .compositor - .borrow_mut() - .raise_webview_to_top(webview_id, hide_others) - { - warn!("{webview_id}: RaiseWebViewToTop on unknown webview id"); - } - }, - EmbedderEvent::BlurWebView => { - self.send_to_constellation(ConstellationMsg::BlurWebView); - }, - - EmbedderEvent::SendError(webview_id, e) => { - let msg = ConstellationMsg::SendError(webview_id, e); - if let Err(e) = self.constellation_proxy.try_send(msg) { - warn!( - "Sending SendError message to constellation failed ({:?}).", - e - ); - } - }, - - EmbedderEvent::MediaSessionAction(a) => { - let msg = ConstellationMsg::MediaSessionAction(a); - if let Err(e) = self.constellation_proxy.try_send(msg) { - warn!( - "Sending MediaSessionAction message to constellation failed ({:?}).", - e - ); - } - }, - - EmbedderEvent::SetWebViewThrottled(webview_id, throttled) => { - let msg = ConstellationMsg::SetWebViewThrottled(webview_id, throttled); - if let Err(e) = self.constellation_proxy.try_send(msg) { - warn!( - "Sending SetWebViewThrottled to constellation failed ({:?}).", - e - ); - } - }, - - EmbedderEvent::Gamepad(gamepad_event) => { - let msg = ConstellationMsg::Gamepad(gamepad_event); - if let Err(e) = self.constellation_proxy.try_send(msg) { - warn!("Sending Gamepad event to constellation failed ({:?}).", e); - } - }, - EmbedderEvent::Vsync => { - self.compositor.borrow_mut().on_vsync(); - }, - EmbedderEvent::ClipboardAction(clipboard_event) => { - self.send_to_constellation(ConstellationMsg::Clipboard(clipboard_event)); - }, - } - } - - fn send_to_constellation(&self, msg: ConstellationMsg) { - let variant_name = msg.variant_name(); - if let Err(e) = self.constellation_proxy.try_send(msg) { - warn!("Sending {variant_name} to constellation failed: {e:?}"); - } - } - - fn receive_messages(&self) { - while let Ok(message) = self.embedder_receiver.try_recv() { - match (message, self.compositor.borrow().shutdown_state) { - (_, ShutdownState::FinishedShuttingDown) => { - error!( - "embedder shouldn't be handling messages after compositor has shut down" - ); - }, - - (_, ShutdownState::ShuttingDown) => {}, - - (EmbedderMsg::Keyboard(webview_id, key_event), ShutdownState::NotShuttingDown) => { - self.messages_for_embedder - .borrow_mut() - .push(EmbedderMsg::Keyboard(webview_id, key_event)); - }, - - (message, ShutdownState::NotShuttingDown) => { - self.messages_for_embedder.borrow_mut().push(message); - }, - } - } - } - - pub fn get_events(&self) -> Vec { - std::mem::take(&mut *self.messages_for_embedder.borrow_mut()) - } - - pub fn handle_events(&self, events: impl IntoIterator) { - if self.compositor.borrow_mut().receive_messages() { - self.receive_messages(); - } - for event in events { - trace!("servo <- embedder EmbedderEvent {:?}", event); - self.handle_window_event(event); - } - if self.compositor.borrow().shutdown_state != ShutdownState::FinishedShuttingDown { - self.compositor.borrow_mut().perform_updates(); - } else { - self.messages_for_embedder - .borrow_mut() - .push(EmbedderMsg::Shutdown); - } - } - /// Spin the Servo event loop, which: /// /// - Performs updates in the compositor, such as queued pinch zoom events @@ -941,11 +621,19 @@ impl Servo { /// The return value of this method indicates whether or not Servo, false indicates that Servo /// has finished shutting down and you should not spin the event loop any longer. pub fn spin_event_loop(&self) -> bool { - if self.compositor.borrow_mut().receive_messages() { - self.receive_messages(); + if self.compositor.borrow().shutdown_state == ShutdownState::FinishedShuttingDown { + return false; + } + + self.compositor.borrow_mut().receive_messages(); + + // Only handle incoming embedder messages if the compositor hasn't already started shutting down. + if self.compositor.borrow().shutdown_state == ShutdownState::NotShuttingDown { + while let Ok(message) = self.embedder_receiver.try_recv() { + self.handle_embedder_message(message) + } } - self.call_delegate_methods(); if self.constellation_proxy.disconnected() { self.delegate() .notify_error(self, ServoError::LostConnectionWithBackend); @@ -1030,299 +718,289 @@ impl Servo { .and_then(WebView::from_weak_handle) } - fn call_delegate_methods(&self) { - let events = self.get_events(); - for event in events { - match event { - EmbedderMsg::Status(webview_id, status_text) => { - if let Some(webview) = self.get_webview_handle(webview_id) { - webview.set_status_text(status_text); + fn handle_embedder_message(&self, message: EmbedderMsg) { + match message { + EmbedderMsg::Status(webview_id, status_text) => { + if let Some(webview) = self.get_webview_handle(webview_id) { + webview.set_status_text(status_text); + } + }, + EmbedderMsg::ChangePageTitle(webview_id, title) => { + if let Some(webview) = self.get_webview_handle(webview_id) { + webview.set_page_title(title); + } + }, + EmbedderMsg::MoveTo(webview_id, position) => { + if let Some(webview) = self.get_webview_handle(webview_id) { + webview.delegate().request_move_to(webview, position); + } + }, + EmbedderMsg::ResizeTo(webview_id, size) => { + if let Some(webview) = self.get_webview_handle(webview_id) { + webview.delegate().request_resize_to(webview, size); + } + }, + EmbedderMsg::Prompt(webview_id, prompt_definition, prompt_origin) => { + if let Some(webview) = self.get_webview_handle(webview_id) { + webview + .delegate() + .show_prompt(webview, prompt_definition, prompt_origin); + } + }, + EmbedderMsg::ShowContextMenu(webview_id, ipc_sender, title, items) => { + if let Some(webview) = self.get_webview_handle(webview_id) { + webview + .delegate() + .show_context_menu(webview, ipc_sender, title, items); + } + }, + EmbedderMsg::AllowNavigationRequest(webview_id, pipeline_id, servo_url) => { + if let Some(webview) = self.get_webview_handle(webview_id) { + let request = NavigationRequest { + url: servo_url.into_url(), + pipeline_id, + constellation_proxy: self.constellation_proxy.clone(), + response_sent: false, + }; + webview.delegate().request_navigation(webview, request); + } + }, + EmbedderMsg::AllowOpeningWebView(webview_id, response_sender) => { + if let Some(webview) = self.get_webview_handle(webview_id) { + let new_webview = webview.delegate().request_open_auxiliary_webview(webview); + let _ = response_sender.send(new_webview.map(|webview| webview.id())); + } + }, + EmbedderMsg::WebViewOpened(webview_id) => { + if let Some(webview) = self.get_webview_handle(webview_id) { + webview.delegate().notify_ready_to_show(webview); + } + }, + EmbedderMsg::WebViewClosed(webview_id) => { + if let Some(webview) = self.get_webview_handle(webview_id) { + webview.delegate().notify_closed(webview); + } + }, + EmbedderMsg::WebViewFocused(webview_id) => { + for id in self.webviews.borrow().keys() { + if let Some(webview) = self.get_webview_handle(*id) { + let focused = webview.id() == webview_id; + webview.set_focused(focused); } - }, - EmbedderMsg::ChangePageTitle(webview_id, title) => { - if let Some(webview) = self.get_webview_handle(webview_id) { - webview.set_page_title(title); + } + }, + EmbedderMsg::WebViewBlurred => { + for id in self.webviews.borrow().keys() { + if let Some(webview) = self.get_webview_handle(*id) { + webview.set_focused(false); } - }, - EmbedderMsg::MoveTo(webview_id, position) => { - if let Some(webview) = self.get_webview_handle(webview_id) { - webview.delegate().request_move_to(webview, position); - } - }, - EmbedderMsg::ResizeTo(webview_id, size) => { - if let Some(webview) = self.get_webview_handle(webview_id) { - webview.delegate().request_resize_to(webview, size); - } - }, - EmbedderMsg::Prompt(webview_id, prompt_definition, prompt_origin) => { - if let Some(webview) = self.get_webview_handle(webview_id) { - webview - .delegate() - .show_prompt(webview, prompt_definition, prompt_origin); - } - }, - EmbedderMsg::ShowContextMenu(webview_id, ipc_sender, title, items) => { - if let Some(webview) = self.get_webview_handle(webview_id) { - webview - .delegate() - .show_context_menu(webview, ipc_sender, title, items); - } - }, - EmbedderMsg::AllowNavigationRequest(webview_id, pipeline_id, servo_url) => { - if let Some(webview) = self.get_webview_handle(webview_id) { - let request = NavigationRequest { - url: servo_url.into_url(), - pipeline_id, - constellation_proxy: self.constellation_proxy.clone(), - response_sent: false, - }; - webview.delegate().request_navigation(webview, request); - } - }, - EmbedderMsg::AllowOpeningWebView(webview_id, response_sender) => { - if let Some(webview) = self.get_webview_handle(webview_id) { - let new_webview = - webview.delegate().request_open_auxiliary_webview(webview); - let _ = response_sender.send(new_webview.map(|webview| webview.id())); - } - }, - EmbedderMsg::WebViewOpened(webview_id) => { - if let Some(webview) = self.get_webview_handle(webview_id) { - webview.delegate().notify_ready_to_show(webview); - } - }, - EmbedderMsg::WebViewClosed(webview_id) => { - if let Some(webview) = self.get_webview_handle(webview_id) { - webview.delegate().notify_closed(webview); - } - }, - EmbedderMsg::WebViewFocused(webview_id) => { - for id in self.webviews.borrow().keys() { - if let Some(webview) = self.get_webview_handle(*id) { - let focused = webview.id() == webview_id; - webview.set_focused(focused); - } - } - }, - EmbedderMsg::WebViewBlurred => { - for id in self.webviews.borrow().keys() { - if let Some(webview) = self.get_webview_handle(*id) { - webview.set_focused(false); - } - } - }, - EmbedderMsg::AllowUnload(webview_id, response_sender) => { - if let Some(webview) = self.get_webview_handle(webview_id) { - let request = AllowOrDenyRequest { - response_sender, - response_sent: false, - default_response: true, - }; - webview.delegate().request_unload(webview, request); - } - }, - EmbedderMsg::Keyboard(webview_id, keyboard_event) => { - if let Some(webview) = self.get_webview_handle(webview_id) { - webview - .delegate() - .notify_keyboard_event(webview, keyboard_event); - } - }, - EmbedderMsg::ClearClipboard(webview_id) => { - if let Some(webview) = self.get_webview_handle(webview_id) { - webview.clipboard_delegate().clear(webview); - } - }, - EmbedderMsg::GetClipboardText(webview_id, result_sender) => { - if let Some(webview) = self.get_webview_handle(webview_id) { - webview - .clipboard_delegate() - .get_text(webview, StringRequest::from(result_sender)); - } - }, - EmbedderMsg::SetClipboardText(webview_id, string) => { - if let Some(webview) = self.get_webview_handle(webview_id) { - webview.clipboard_delegate().set_text(webview, string); - } - }, - EmbedderMsg::SetCursor(webview_id, cursor) => { - if let Some(webview) = self.get_webview_handle(webview_id) { - webview.set_cursor(cursor); - } - }, - EmbedderMsg::NewFavicon(webview_id, url) => { - if let Some(webview) = self.get_webview_handle(webview_id) { - webview.set_favicon_url(url.into_url()); - } - }, - EmbedderMsg::NotifyLoadStatusChanged(webview_id, load_status) => { - if let Some(webview) = self.get_webview_handle(webview_id) { - webview.set_load_status(load_status); - } - }, - EmbedderMsg::HistoryChanged(webview_id, urls, current_index) => { - if let Some(webview) = self.get_webview_handle(webview_id) { - let urls: Vec<_> = urls.into_iter().map(ServoUrl::into_url).collect(); - let current_url = urls[current_index].clone(); + } + }, + EmbedderMsg::AllowUnload(webview_id, response_sender) => { + if let Some(webview) = self.get_webview_handle(webview_id) { + let request = AllowOrDenyRequest { + response_sender, + response_sent: false, + default_response: true, + }; + webview.delegate().request_unload(webview, request); + } + }, + EmbedderMsg::Keyboard(webview_id, keyboard_event) => { + if let Some(webview) = self.get_webview_handle(webview_id) { + webview + .delegate() + .notify_keyboard_event(webview, keyboard_event); + } + }, + EmbedderMsg::ClearClipboard(webview_id) => { + if let Some(webview) = self.get_webview_handle(webview_id) { + webview.clipboard_delegate().clear(webview); + } + }, + EmbedderMsg::GetClipboardText(webview_id, result_sender) => { + if let Some(webview) = self.get_webview_handle(webview_id) { + webview + .clipboard_delegate() + .get_text(webview, StringRequest::from(result_sender)); + } + }, + EmbedderMsg::SetClipboardText(webview_id, string) => { + if let Some(webview) = self.get_webview_handle(webview_id) { + webview.clipboard_delegate().set_text(webview, string); + } + }, + EmbedderMsg::SetCursor(webview_id, cursor) => { + if let Some(webview) = self.get_webview_handle(webview_id) { + webview.set_cursor(cursor); + } + }, + EmbedderMsg::NewFavicon(webview_id, url) => { + if let Some(webview) = self.get_webview_handle(webview_id) { + webview.set_favicon_url(url.into_url()); + } + }, + EmbedderMsg::NotifyLoadStatusChanged(webview_id, load_status) => { + if let Some(webview) = self.get_webview_handle(webview_id) { + webview.set_load_status(load_status); + } + }, + EmbedderMsg::HistoryChanged(webview_id, urls, current_index) => { + if let Some(webview) = self.get_webview_handle(webview_id) { + let urls: Vec<_> = urls.into_iter().map(ServoUrl::into_url).collect(); + let current_url = urls[current_index].clone(); - webview.delegate().notify_history_changed( - webview.clone(), - urls, - current_index, - ); - webview.set_url(current_url); - } - }, - EmbedderMsg::SetFullscreenState(webview_id, fullscreen) => { - if let Some(webview) = self.get_webview_handle(webview_id) { - webview - .delegate() - .request_fullscreen_state_change(webview, fullscreen); - } - }, - EmbedderMsg::WebResourceRequested( - webview_id, - web_resource_request, - response_sender, - ) => { - let webview = - webview_id.and_then(|webview_id| self.get_webview_handle(webview_id)); - if let Some(webview) = webview.clone() { - webview.delegate().intercept_web_resource_load( - webview, - &web_resource_request, - response_sender.clone(), - ); - } - - self.delegate().intercept_web_resource_load( + webview + .delegate() + .notify_history_changed(webview.clone(), urls, current_index); + webview.set_url(current_url); + } + }, + EmbedderMsg::SetFullscreenState(webview_id, fullscreen) => { + if let Some(webview) = self.get_webview_handle(webview_id) { + webview + .delegate() + .request_fullscreen_state_change(webview, fullscreen); + } + }, + EmbedderMsg::WebResourceRequested( + webview_id, + web_resource_request, + response_sender, + ) => { + let webview = webview_id.and_then(|webview_id| self.get_webview_handle(webview_id)); + if let Some(webview) = webview.clone() { + webview.delegate().intercept_web_resource_load( webview, &web_resource_request, + response_sender.clone(), + ); + } + + self.delegate().intercept_web_resource_load( + webview, + &web_resource_request, + response_sender, + ); + }, + EmbedderMsg::Panic(webview_id, reason, backtrace) => { + if let Some(webview) = self.get_webview_handle(webview_id) { + webview + .delegate() + .notify_crashed(webview, reason, backtrace); + } + }, + EmbedderMsg::GetSelectedBluetoothDevice(webview_id, items, response_sender) => { + if let Some(webview) = self.get_webview_handle(webview_id) { + webview.delegate().show_bluetooth_device_dialog( + webview, + items, response_sender, ); - }, - EmbedderMsg::Panic(webview_id, reason, backtrace) => { - if let Some(webview) = self.get_webview_handle(webview_id) { - webview - .delegate() - .notify_crashed(webview, reason, backtrace); - } - }, - EmbedderMsg::GetSelectedBluetoothDevice(webview_id, items, response_sender) => { - if let Some(webview) = self.get_webview_handle(webview_id) { - webview.delegate().show_bluetooth_device_dialog( - webview, - items, - response_sender, - ); - } - }, - EmbedderMsg::SelectFiles( - webview_id, - filter_patterns, - allow_select_multiple, - response_sender, - ) => { - if let Some(webview) = self.get_webview_handle(webview_id) { - webview.delegate().show_file_selection_dialog( - webview, - filter_patterns, - allow_select_multiple, - response_sender, - ); - } - }, - EmbedderMsg::PromptPermission(webview_id, permission_prompt, result_sender) => { - if let Some(webview) = self.get_webview_handle(webview_id) { - webview.delegate().request_permission( - webview, - permission_prompt, - result_sender, - ); - } - }, - EmbedderMsg::ShowIME(webview_id, input_method_type, text, multiline, position) => { - if let Some(webview) = self.get_webview_handle(webview_id) { - webview.delegate().show_ime( - webview, - input_method_type, - text, - multiline, - position, - ); - } - }, - EmbedderMsg::HideIME(webview_id) => { - if let Some(webview) = self.get_webview_handle(webview_id) { - webview.delegate().hide_ime(webview); - } - }, - EmbedderMsg::ReportProfile(_items) => {}, - EmbedderMsg::MediaSessionEvent(webview_id, media_session_event) => { - if let Some(webview) = self.get_webview_handle(webview_id) { - webview - .delegate() - .notify_media_session_event(webview, media_session_event); - } - }, - EmbedderMsg::OnDevtoolsStarted(port, token) => match port { - Ok(port) => self - .delegate() - .notify_devtools_server_started(self, port, token), - Err(()) => self - .delegate() - .notify_error(self, ServoError::DevtoolsFailedToStart), - }, - EmbedderMsg::RequestDevtoolsConnection(response_sender) => { - self.delegate().request_devtools_connection( - self, - AllowOrDenyRequest { - response_sender, - response_sent: false, - default_response: false, - }, + } + }, + EmbedderMsg::SelectFiles( + webview_id, + filter_patterns, + allow_select_multiple, + response_sender, + ) => { + if let Some(webview) = self.get_webview_handle(webview_id) { + webview.delegate().show_file_selection_dialog( + webview, + filter_patterns, + allow_select_multiple, + response_sender, ); - }, - EmbedderMsg::ReadyToPresent(webview_ids) => { - for webview_id in webview_ids { - if let Some(webview) = self.get_webview_handle(webview_id) { - webview.delegate().notify_new_frame_ready(webview); - } - } - }, - EmbedderMsg::EventDelivered(webview_id, event) => { + } + }, + EmbedderMsg::PromptPermission(webview_id, permission_prompt, result_sender) => { + if let Some(webview) = self.get_webview_handle(webview_id) { + webview.delegate().request_permission( + webview, + permission_prompt, + result_sender, + ); + } + }, + EmbedderMsg::ShowIME(webview_id, input_method_type, text, multiline, position) => { + if let Some(webview) = self.get_webview_handle(webview_id) { + webview.delegate().show_ime( + webview, + input_method_type, + text, + multiline, + position, + ); + } + }, + EmbedderMsg::HideIME(webview_id) => { + if let Some(webview) = self.get_webview_handle(webview_id) { + webview.delegate().hide_ime(webview); + } + }, + EmbedderMsg::ReportProfile(_items) => {}, + EmbedderMsg::MediaSessionEvent(webview_id, media_session_event) => { + if let Some(webview) = self.get_webview_handle(webview_id) { + webview + .delegate() + .notify_media_session_event(webview, media_session_event); + } + }, + EmbedderMsg::OnDevtoolsStarted(port, token) => match port { + Ok(port) => self + .delegate() + .notify_devtools_server_started(self, port, token), + Err(()) => self + .delegate() + .notify_error(self, ServoError::DevtoolsFailedToStart), + }, + EmbedderMsg::RequestDevtoolsConnection(response_sender) => { + self.delegate().request_devtools_connection( + self, + AllowOrDenyRequest { + response_sender, + response_sent: false, + default_response: false, + }, + ); + }, + EmbedderMsg::ReadyToPresent(webview_ids) => { + for webview_id in webview_ids { if let Some(webview) = self.get_webview_handle(webview_id) { - webview.delegate().notify_event_delivered(webview, event); + webview.delegate().notify_new_frame_ready(webview); } - }, - EmbedderMsg::PlayGamepadHapticEffect( - webview_id, - gamepad_index, - gamepad_haptic_effect_type, - ipc_sender, - ) => { - if let Some(webview) = self.get_webview_handle(webview_id) { - webview.delegate().play_gamepad_haptic_effect( - webview, - gamepad_index, - gamepad_haptic_effect_type, - ipc_sender, - ); - } - }, - EmbedderMsg::StopGamepadHapticEffect(webview_id, gamepad_index, ipc_sender) => { - if let Some(webview) = self.get_webview_handle(webview_id) { - webview.delegate().stop_gamepad_haptic_effect( - webview, - gamepad_index, - ipc_sender, - ); - } - }, - EmbedderMsg::Shutdown => { - // This message isn't necessary in the new API -- it's the return value of `spin_event_loop`. - }, - } + } + }, + EmbedderMsg::EventDelivered(webview_id, event) => { + if let Some(webview) = self.get_webview_handle(webview_id) { + webview.delegate().notify_event_delivered(webview, event); + } + }, + EmbedderMsg::PlayGamepadHapticEffect( + webview_id, + gamepad_index, + gamepad_haptic_effect_type, + ipc_sender, + ) => { + if let Some(webview) = self.get_webview_handle(webview_id) { + webview.delegate().play_gamepad_haptic_effect( + webview, + gamepad_index, + gamepad_haptic_effect_type, + ipc_sender, + ); + } + }, + EmbedderMsg::StopGamepadHapticEffect(webview_id, gamepad_index, ipc_sender) => { + if let Some(webview) = self.get_webview_handle(webview_id) { + webview.delegate().stop_gamepad_haptic_effect( + webview, + gamepad_index, + ipc_sender, + ); + } + }, } } } diff --git a/components/shared/embedder/lib.rs b/components/shared/embedder/lib.rs index 5ca911ff05a..b1aae2f3ad4 100644 --- a/components/shared/embedder/lib.rs +++ b/components/shared/embedder/lib.rs @@ -229,8 +229,6 @@ pub enum EmbedderMsg { ), /// Request to hide the IME when the editable element is blurred. HideIME(WebViewId), - /// Servo has shut down - Shutdown, /// Report a complete sampled profile ReportProfile(Vec), /// Notifies the embedder about media session events @@ -293,7 +291,6 @@ impl Debug for EmbedderMsg { EmbedderMsg::PromptPermission(..) => write!(f, "PromptPermission"), EmbedderMsg::ShowIME(..) => write!(f, "ShowIME"), EmbedderMsg::HideIME(..) => write!(f, "HideIME"), - EmbedderMsg::Shutdown => write!(f, "Shutdown"), EmbedderMsg::AllowOpeningWebView(..) => write!(f, "AllowOpeningWebView"), EmbedderMsg::WebViewOpened(..) => write!(f, "WebViewOpened"), EmbedderMsg::WebViewClosed(..) => write!(f, "WebViewClosed"),