diff --git a/components/compositing/lib.rs b/components/compositing/lib.rs index a6c94697142..9fbb7b69469 100644 --- a/components/compositing/lib.rs +++ b/components/compositing/lib.rs @@ -110,6 +110,8 @@ pub enum ConstellationMsg { ExitFullScreen(TopLevelBrowsingContextId), /// Media session action. MediaSessionAction(MediaSessionActionType), + /// Toggle browser visibility. + ChangeBrowserVisibility(TopLevelBrowsingContextId, bool), } impl fmt::Debug for ConstellationMsg { @@ -141,6 +143,7 @@ impl fmt::Debug for ConstellationMsg { DisableProfiler => "DisableProfiler", ExitFullScreen(..) => "ExitFullScreen", MediaSessionAction(..) => "MediaSessionAction", + ChangeBrowserVisibility(..) => "ChangeBrowserVisibility", }; write!(formatter, "ConstellationMsg::{}", variant) } diff --git a/components/compositing/windowing.rs b/components/compositing/windowing.rs index 93e7c914313..4dfa27a9d02 100644 --- a/components/compositing/windowing.rs +++ b/components/compositing/windowing.rs @@ -105,6 +105,8 @@ pub enum WindowEvent { /// Sent when the user triggers a media action through the UA exposed media UI /// (play, pause, seek, etc.). MediaSessionAction(MediaSessionActionType), + /// Set browser visibility. A hidden browser will not tick the animations. + ChangeBrowserVisibility(TopLevelBrowsingContextId, bool), } impl Debug for WindowEvent { @@ -136,6 +138,7 @@ impl Debug for WindowEvent { WindowEvent::ToggleSamplingProfiler(..) => write!(f, "ToggleSamplingProfiler"), WindowEvent::ExitFullScreen(..) => write!(f, "ExitFullScreen"), WindowEvent::MediaSessionAction(..) => write!(f, "MediaSessionAction"), + WindowEvent::ChangeBrowserVisibility(..) => write!(f, "ChangeBrowserVisibility"), } } } diff --git a/components/constellation/constellation.rs b/components/constellation/constellation.rs index 11dbd627847..3e61f37e2dc 100644 --- a/components/constellation/constellation.rs +++ b/components/constellation/constellation.rs @@ -1681,6 +1681,9 @@ where FromCompositorMsg::MediaSessionAction(action) => { self.handle_media_session_action_msg(action); }, + FromCompositorMsg::ChangeBrowserVisibility(top_level_browsing_context_id, visible) => { + self.handle_change_browser_visibility(top_level_browsing_context_id, visible); + }, } } @@ -4276,6 +4279,32 @@ where } } + fn handle_change_browser_visibility( + &mut self, + top_level_browsing_context_id: TopLevelBrowsingContextId, + visible: bool, + ) { + let browsing_context_id = BrowsingContextId::from(top_level_browsing_context_id); + let pipeline_id = match self.browsing_contexts.get(&browsing_context_id) { + Some(browsing_context) => browsing_context.pipeline_id, + None => { + return warn!( + "Browsing context {} got visibility change event after closure.", + browsing_context_id + ); + }, + }; + match self.pipelines.get(&pipeline_id) { + None => { + return warn!( + "Pipeline {} got visibility change event after closure.", + pipeline_id + ) + }, + Some(pipeline) => pipeline.notify_visibility(visible), + }; + } + fn notify_history_changed(&self, top_level_browsing_context_id: TopLevelBrowsingContextId) { // Send a flat projection of the history to embedder. // The final vector is a concatenation of the LoadData of the past diff --git a/components/servo/lib.rs b/components/servo/lib.rs index c9013e5bcc3..f9d3b91ae82 100644 --- a/components/servo/lib.rs +++ b/components/servo/lib.rs @@ -735,6 +735,19 @@ where ); } }, + + WindowEvent::ChangeBrowserVisibility(top_level_browsing_context_id, visible) => { + let msg = ConstellationMsg::ChangeBrowserVisibility( + top_level_browsing_context_id, + visible, + ); + if let Err(e) = self.constellation_chan.send(msg) { + warn!( + "Sending ChangeBrowserVisibility to constellation failed ({:?}).", + e + ); + } + }, } } diff --git a/ports/libsimpleservo/api/src/lib.rs b/ports/libsimpleservo/api/src/lib.rs index 2489760052f..1d62d642be1 100644 --- a/ports/libsimpleservo/api/src/lib.rs +++ b/ports/libsimpleservo/api/src/lib.rs @@ -487,6 +487,17 @@ impl ServoGlue { self.process_event(WindowEvent::MediaSessionAction(action)) } + pub fn change_visibility(&mut self, visible: bool) -> Result<(), &'static str> { + info!("change_visibility"); + if let Ok(id) = self.get_browser_id() { + let event = WindowEvent::ChangeBrowserVisibility(id, visible); + self.process_event(event) + } else { + // Ignore visibility change if no browser has been created yet. + Ok(()) + } + } + fn process_event(&mut self, event: WindowEvent) -> Result<(), &'static str> { self.events.push(event); if !self.batch_mode { diff --git a/ports/libsimpleservo/capi/src/lib.rs b/ports/libsimpleservo/capi/src/lib.rs index 5bec2fb31ea..b7fad2d95c6 100644 --- a/ports/libsimpleservo/capi/src/lib.rs +++ b/ports/libsimpleservo/capi/src/lib.rs @@ -686,6 +686,14 @@ pub extern "C" fn media_session_action(action: CMediaSessionActionType) { }); } +#[no_mangle] +pub extern "C" fn change_visibility(visible: bool) { + catch_any_panic(|| { + debug!("change_visibility"); + call(|s| s.change_visibility(visible)); + }); +} + pub struct WakeupCallback(extern "C" fn()); impl WakeupCallback { diff --git a/support/hololens/ServoApp/BrowserPage.cpp b/support/hololens/ServoApp/BrowserPage.cpp index 6147c9d3f82..e23a593a7ac 100644 --- a/support/hololens/ServoApp/BrowserPage.cpp +++ b/support/hololens/ServoApp/BrowserPage.cpp @@ -71,6 +71,10 @@ void BrowserPage::BindServoEvents() { ? Visibility::Collapsed : Visibility::Visible); }); + Window::Current().VisibilityChanged( + [=](const auto &, const VisibilityChangedEventArgs &args) { + servoControl().ChangeVisibility(args.Visible()); + }); } void BrowserPage::OnURLFocused(Windows::Foundation::IInspectable const &) { diff --git a/support/hololens/ServoApp/ServoControl/Servo.h b/support/hololens/ServoApp/ServoControl/Servo.h index e0aef56c4ed..f27145ee482 100644 --- a/support/hololens/ServoApp/ServoControl/Servo.h +++ b/support/hololens/ServoApp/ServoControl/Servo.h @@ -56,6 +56,7 @@ public: void Reload() { capi::reload(); } void Stop() { capi::stop(); } bool LoadUri(hstring uri) { return capi::load_uri(*hstring2char(uri)); } + void ChangeVisibility(bool visible) { capi::change_visibility(visible); } bool IsUriValid(hstring uri) { return capi::is_uri_valid(*hstring2char(uri)); } diff --git a/support/hololens/ServoApp/ServoControl/ServoControl.cpp b/support/hololens/ServoApp/ServoControl/ServoControl.cpp index e4df1031804..0ca4070dcd6 100644 --- a/support/hololens/ServoApp/ServoControl/ServoControl.cpp +++ b/support/hololens/ServoApp/ServoControl/ServoControl.cpp @@ -247,6 +247,9 @@ void ServoControl::GoForward() { void ServoControl::Reload() { RunOnGLThread([=] { mServo->Reload(); }); } +void ServoControl::ChangeVisibility(bool visible) { + RunOnGLThread([=] { mServo->ChangeVisibility(visible); }); +} void ServoControl::Stop() { RunOnGLThread([=] { mServo->Stop(); }); } diff --git a/support/hololens/ServoApp/ServoControl/ServoControl.h b/support/hololens/ServoApp/ServoControl/ServoControl.h index ca05373ce96..3b597b91be8 100644 --- a/support/hololens/ServoApp/ServoControl/ServoControl.h +++ b/support/hololens/ServoApp/ServoControl/ServoControl.h @@ -13,6 +13,7 @@ struct ServoControl : ServoControlT, public servo::ServoDelegate { void GoForward(); void Reload(); void Stop(); + void ChangeVisibility(bool); void Shutdown(); hstring LoadURIOrSearch(hstring); void SendMediaSessionAction(int32_t); diff --git a/support/hololens/ServoApp/ServoControl/ServoControl.idl b/support/hololens/ServoApp/ServoControl/ServoControl.idl index 90a5fae8fe3..8e1c60df574 100644 --- a/support/hololens/ServoApp/ServoControl/ServoControl.idl +++ b/support/hololens/ServoApp/ServoControl/ServoControl.idl @@ -14,6 +14,7 @@ namespace ServoApp { void SetTransientMode(Boolean transient); void SetArgs(String args); void Shutdown(); + void ChangeVisibility(Boolean visible); void SendMediaSessionAction(UInt32 action); event EventDelegate OnLoadStarted; event EventDelegate OnLoadEnded;