Stop animations when window is hidden (API + UWP)

This commit is contained in:
Paul Rouget 2020-02-19 14:09:50 +01:00
parent 5597ccf57d
commit 6ddde1a3e1
11 changed files with 77 additions and 0 deletions

View file

@ -110,6 +110,8 @@ pub enum ConstellationMsg {
ExitFullScreen(TopLevelBrowsingContextId), ExitFullScreen(TopLevelBrowsingContextId),
/// Media session action. /// Media session action.
MediaSessionAction(MediaSessionActionType), MediaSessionAction(MediaSessionActionType),
/// Toggle browser visibility.
ChangeBrowserVisibility(TopLevelBrowsingContextId, bool),
} }
impl fmt::Debug for ConstellationMsg { impl fmt::Debug for ConstellationMsg {
@ -141,6 +143,7 @@ impl fmt::Debug for ConstellationMsg {
DisableProfiler => "DisableProfiler", DisableProfiler => "DisableProfiler",
ExitFullScreen(..) => "ExitFullScreen", ExitFullScreen(..) => "ExitFullScreen",
MediaSessionAction(..) => "MediaSessionAction", MediaSessionAction(..) => "MediaSessionAction",
ChangeBrowserVisibility(..) => "ChangeBrowserVisibility",
}; };
write!(formatter, "ConstellationMsg::{}", variant) write!(formatter, "ConstellationMsg::{}", variant)
} }

View file

@ -105,6 +105,8 @@ pub enum WindowEvent {
/// Sent when the user triggers a media action through the UA exposed media UI /// Sent when the user triggers a media action through the UA exposed media UI
/// (play, pause, seek, etc.). /// (play, pause, seek, etc.).
MediaSessionAction(MediaSessionActionType), MediaSessionAction(MediaSessionActionType),
/// Set browser visibility. A hidden browser will not tick the animations.
ChangeBrowserVisibility(TopLevelBrowsingContextId, bool),
} }
impl Debug for WindowEvent { impl Debug for WindowEvent {
@ -136,6 +138,7 @@ impl Debug for WindowEvent {
WindowEvent::ToggleSamplingProfiler(..) => write!(f, "ToggleSamplingProfiler"), WindowEvent::ToggleSamplingProfiler(..) => write!(f, "ToggleSamplingProfiler"),
WindowEvent::ExitFullScreen(..) => write!(f, "ExitFullScreen"), WindowEvent::ExitFullScreen(..) => write!(f, "ExitFullScreen"),
WindowEvent::MediaSessionAction(..) => write!(f, "MediaSessionAction"), WindowEvent::MediaSessionAction(..) => write!(f, "MediaSessionAction"),
WindowEvent::ChangeBrowserVisibility(..) => write!(f, "ChangeBrowserVisibility"),
} }
} }
} }

View file

@ -1681,6 +1681,9 @@ where
FromCompositorMsg::MediaSessionAction(action) => { FromCompositorMsg::MediaSessionAction(action) => {
self.handle_media_session_action_msg(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) { fn notify_history_changed(&self, top_level_browsing_context_id: TopLevelBrowsingContextId) {
// Send a flat projection of the history to embedder. // Send a flat projection of the history to embedder.
// The final vector is a concatenation of the LoadData of the past // The final vector is a concatenation of the LoadData of the past

View file

@ -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
);
}
},
} }
} }

View file

@ -487,6 +487,17 @@ impl ServoGlue {
self.process_event(WindowEvent::MediaSessionAction(action)) 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> { fn process_event(&mut self, event: WindowEvent) -> Result<(), &'static str> {
self.events.push(event); self.events.push(event);
if !self.batch_mode { if !self.batch_mode {

View file

@ -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()); pub struct WakeupCallback(extern "C" fn());
impl WakeupCallback { impl WakeupCallback {

View file

@ -71,6 +71,10 @@ void BrowserPage::BindServoEvents() {
? Visibility::Collapsed ? Visibility::Collapsed
: Visibility::Visible); : Visibility::Visible);
}); });
Window::Current().VisibilityChanged(
[=](const auto &, const VisibilityChangedEventArgs &args) {
servoControl().ChangeVisibility(args.Visible());
});
} }
void BrowserPage::OnURLFocused(Windows::Foundation::IInspectable const &) { void BrowserPage::OnURLFocused(Windows::Foundation::IInspectable const &) {

View file

@ -56,6 +56,7 @@ public:
void Reload() { capi::reload(); } void Reload() { capi::reload(); }
void Stop() { capi::stop(); } void Stop() { capi::stop(); }
bool LoadUri(hstring uri) { return capi::load_uri(*hstring2char(uri)); } bool LoadUri(hstring uri) { return capi::load_uri(*hstring2char(uri)); }
void ChangeVisibility(bool visible) { capi::change_visibility(visible); }
bool IsUriValid(hstring uri) { bool IsUriValid(hstring uri) {
return capi::is_uri_valid(*hstring2char(uri)); return capi::is_uri_valid(*hstring2char(uri));
} }

View file

@ -247,6 +247,9 @@ void ServoControl::GoForward() {
void ServoControl::Reload() { void ServoControl::Reload() {
RunOnGLThread([=] { mServo->Reload(); }); RunOnGLThread([=] { mServo->Reload(); });
} }
void ServoControl::ChangeVisibility(bool visible) {
RunOnGLThread([=] { mServo->ChangeVisibility(visible); });
}
void ServoControl::Stop() { void ServoControl::Stop() {
RunOnGLThread([=] { mServo->Stop(); }); RunOnGLThread([=] { mServo->Stop(); });
} }

View file

@ -13,6 +13,7 @@ struct ServoControl : ServoControlT<ServoControl>, public servo::ServoDelegate {
void GoForward(); void GoForward();
void Reload(); void Reload();
void Stop(); void Stop();
void ChangeVisibility(bool);
void Shutdown(); void Shutdown();
hstring LoadURIOrSearch(hstring); hstring LoadURIOrSearch(hstring);
void SendMediaSessionAction(int32_t); void SendMediaSessionAction(int32_t);

View file

@ -14,6 +14,7 @@ namespace ServoApp {
void SetTransientMode(Boolean transient); void SetTransientMode(Boolean transient);
void SetArgs(String args); void SetArgs(String args);
void Shutdown(); void Shutdown();
void ChangeVisibility(Boolean visible);
void SendMediaSessionAction(UInt32 action); void SendMediaSessionAction(UInt32 action);
event EventDelegate OnLoadStarted; event EventDelegate OnLoadStarted;
event EventDelegate OnLoadEnded; event EventDelegate OnLoadEnded;