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 4151c803599..f3892dc33c7 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/ServoApp.vcxproj b/support/hololens/ServoApp/ServoApp.vcxproj
index 917ec117664..04dee348d67 100644
--- a/support/hololens/ServoApp/ServoApp.vcxproj
+++ b/support/hololens/ServoApp/ServoApp.vcxproj
@@ -14,7 +14,7 @@
Windows Store
10.0
10.0.17763.0
- 10.0.17134.0
+ 10.0.17763.0
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;