diff options
author | bors-servo <lbergstrom+bors@mozilla.com> | 2016-06-16 08:53:56 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2016-06-16 08:53:56 -0500 |
commit | d620ab71c41431c3fb040162f554faefb9abfbd7 (patch) | |
tree | 902c90598821bee9998194bb14f65c7b3e9bbab9 /components/script/script_thread.rs | |
parent | ff67f80f36106cba4a89c48d8c8d59c9880856c7 (diff) | |
parent | 2bff131535987da0330737f78fb23291593db30d (diff) | |
download | servo-d620ab71c41431c3fb040162f554faefb9abfbd7.tar.gz servo-d620ab71c41431c3fb040162f554faefb9abfbd7.zip |
Auto merge of #10225 - jmr0:visibility_api, r=jdm
Implement non-visible pipeline and iframe visibility methods
This addresses #9566 and a good part of #9751, specifically:
* Pipeline has a notion of visibility
* IFrame setVisible/getVisible interface with IFrame's pipeline visibility
* IFrame mozbrowservisibilitychange responds to changes in visibility
* Pipeline visibility is used to limit animations (requestAnimationFrame does not tick animations when hidden) and to increase timer intervals (currently set to a minimum of 1 second while hidden)
Absent for now are any changes to the Document API and general implementation of the Page Visibility API, since the more interesting parts require knowledge of whether the user agent is minimized, OS screen locked, etc.
cc @paulrouget @jdm
<!-- Reviewable:start -->
---
This change is [<img src="https://reviewable.io/review_button.svg" height="35" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/10225)
<!-- Reviewable:end -->
Diffstat (limited to 'components/script/script_thread.rs')
-rw-r--r-- | components/script/script_thread.rs | 60 |
1 files changed, 60 insertions, 0 deletions
diff --git a/components/script/script_thread.rs b/components/script/script_thread.rs index 4750a8d6390..3459e5ddcfa 100644 --- a/components/script/script_thread.rs +++ b/components/script/script_thread.rs @@ -140,6 +140,8 @@ struct InProgressLoad { clip_rect: Option<Rect<f32>>, /// Window is frozen (navigated away while loading for example). is_frozen: bool, + /// Window is visible. + is_visible: bool, /// The requested URL of the load. url: Url, } @@ -158,6 +160,7 @@ impl InProgressLoad { window_size: window_size, clip_rect: None, is_frozen: false, + is_visible: true, url: url, } } @@ -919,6 +922,10 @@ impl ScriptThread { self.handle_freeze_msg(pipeline_id), ConstellationControlMsg::Thaw(pipeline_id) => self.handle_thaw_msg(pipeline_id), + ConstellationControlMsg::ChangeFrameVisibilityStatus(pipeline_id, visible) => + self.handle_visibility_change_msg(pipeline_id, visible), + ConstellationControlMsg::NotifyVisibilityChange(containing_id, pipeline_id, visible) => + self.handle_visibility_change_complete_msg(containing_id, pipeline_id, visible), ConstellationControlMsg::MozBrowserEvent(parent_pipeline_id, subpage_id, event) => @@ -1232,6 +1239,55 @@ impl ScriptThread { reports_chan.send(reports); } + /// To slow/speed up timers and manage any other script thread resource based on visibility. + /// Returns true if successful. + fn alter_resource_utilization(&self, id: PipelineId, visible: bool) -> bool { + if let Some(root_context) = self.browsing_context.get() { + if let Some(ref inner_context) = root_context.find(id) { + let window = inner_context.active_window(); + if visible { + window.speed_up_timers(); + } else { + window.slow_down_timers(); + } + return true; + } + } + false + } + + /// Updates iframe element after a change in visibility + fn handle_visibility_change_complete_msg(&self, containing_id: PipelineId, id: PipelineId, visible: bool) { + if let Some(root_context) = self.browsing_context.get() { + if let Some(ref inner_context) = root_context.find(containing_id) { + if let Some(iframe) = inner_context.active_document().find_iframe_by_pipeline(id) { + iframe.change_visibility_status(visible); + } + } + } + } + + /// Handle visibility change message + fn handle_visibility_change_msg(&self, id: PipelineId, visible: bool) { + let resources_altered = self.alter_resource_utilization(id, visible); + + // Separate message sent since parent script thread could be different (Iframe of different + // domain) + self.constellation_chan.send(ConstellationMsg::VisibilityChangeComplete(id, visible)).unwrap(); + + if !resources_altered { + let mut loads = self.incomplete_loads.borrow_mut(); + if let Some(ref mut load) = loads.iter_mut().find(|load| load.pipeline_id == id) { + load.is_visible = visible; + return; + } + } else { + return; + } + + warn!("change visibility message sent to nonexistent pipeline"); + } + /// Handles freeze message fn handle_freeze_msg(&self, id: PipelineId) { if let Some(root_context) = self.browsing_context.get() { @@ -1707,6 +1763,10 @@ impl ScriptThread { window.freeze(); } + if !incomplete.is_visible { + self.alter_resource_utilization(browsing_context.pipeline(), false); + } + context_remover.neuter(); document.get_current_parser().unwrap() |