Update Constellation to track focused BrowsingContext instead of Pipeline

This commit is contained in:
mandreyel 2018-09-14 14:58:02 +02:00
parent 80379c8f93
commit dab49a217f

View file

@ -289,8 +289,10 @@ pub struct Constellation<Message, LTF, STF> {
/// we store a `SessionHistoryChange` object for the navigation in progress. /// we store a `SessionHistoryChange` object for the navigation in progress.
pending_changes: Vec<SessionHistoryChange>, pending_changes: Vec<SessionHistoryChange>,
/// The currently focused pipeline for key events. /// The currently focused browsing context for key events. The focused
focus_pipeline_id: Option<PipelineId>, /// pipeline is the current entry of the focused browsing
/// context.
focused_browsing_context_id: Option<BrowsingContextId>,
/// Pipeline IDs are namespaced in order to avoid name collisions, /// Pipeline IDs are namespaced in order to avoid name collisions,
/// and the namespaces are allocated by the constellation. /// and the namespaces are allocated by the constellation.
@ -606,7 +608,7 @@ where
// We initialize the namespace at 2, since we reserved // We initialize the namespace at 2, since we reserved
// namespace 0 for the embedder, and 0 for the constellation // namespace 0 for the embedder, and 0 for the constellation
next_pipeline_namespace_id: PipelineNamespaceId(2), next_pipeline_namespace_id: PipelineNamespaceId(2),
focus_pipeline_id: None, focused_browsing_context_id: None,
time_profiler_chan: state.time_profiler_chan, time_profiler_chan: state.time_profiler_chan,
mem_profiler_chan: state.mem_profiler_chan, mem_profiler_chan: state.mem_profiler_chan,
window_size: WindowSizeData { window_size: WindowSizeData {
@ -961,14 +963,12 @@ where
self.handle_get_pipeline(browsing_context_id, resp_chan); self.handle_get_pipeline(browsing_context_id, resp_chan);
}, },
FromCompositorMsg::GetFocusTopLevelBrowsingContext(resp_chan) => { FromCompositorMsg::GetFocusTopLevelBrowsingContext(resp_chan) => {
let focus_browsing_context = self let focus_browsing_context = self.focused_browsing_context_id
.focus_pipeline_id .and_then(|ctx_id| self.browsing_contexts.get(&ctx_id))
.and_then(|pipeline_id| self.pipelines.get(&pipeline_id)) .map(|ctx| ctx.top_level_id)
.map(|pipeline| pipeline.top_level_browsing_context_id) .filter(|&top_level_ctx_id| {
.filter(|&top_level_browsing_context_id| { let ctx_id = BrowsingContextId::from(top_level_ctx_id);
let browsing_context_id = self.browsing_contexts.contains_key(&ctx_id)
BrowsingContextId::from(top_level_browsing_context_id);
self.browsing_contexts.contains_key(&browsing_context_id)
}); });
let _ = resp_chan.send(focus_browsing_context); let _ = resp_chan.send(focus_browsing_context);
}, },
@ -1644,9 +1644,10 @@ where
let is_private = false; let is_private = false;
let is_visible = true; let is_visible = true;
if self.focus_pipeline_id.is_none() { if self.focused_browsing_context_id.is_none() {
self.focus_pipeline_id = Some(pipeline_id); self.focused_browsing_context_id = Some(browsing_context_id);
} }
self.joint_session_histories self.joint_session_histories
.insert(top_level_browsing_context_id, JointSessionHistory::new()); .insert(top_level_browsing_context_id, JointSessionHistory::new());
self.new_pipeline( self.new_pipeline(
@ -2622,11 +2623,18 @@ where
} }
fn handle_key_msg(&mut self, ch: Option<char>, key: Key, state: KeyState, mods: KeyModifiers) { fn handle_key_msg(&mut self, ch: Option<char>, key: Key, state: KeyState, mods: KeyModifiers) {
// Send to the explicitly focused pipeline. If it doesn't exist, fall back to sending to // Send to the focused browsing contexts' current pipeline. If it
// the compositor. // doesn't exist, fall back to sending to the compositor.
match self.focus_pipeline_id { match self.focused_browsing_context_id {
Some(pipeline_id) => { Some(browsing_context_id) => {
let event = CompositorEvent::KeyEvent(ch, key, state, mods); let event = CompositorEvent::KeyEvent(ch, key, state, mods);
let pipeline_id = match self.browsing_contexts.get(&browsing_context_id) {
Some(ctx) => ctx.pipeline_id,
None => return warn!(
"Got key event for nonexistent browsing context {}.",
browsing_context_id,
),
};
let msg = ConstellationControlMsg::SendEvent(pipeline_id, event); let msg = ConstellationControlMsg::SendEvent(pipeline_id, event);
let result = match self.pipelines.get(&pipeline_id) { let result = match self.pipelines.get(&pipeline_id) {
Some(pipeline) => pipeline.event_loop.send(msg), Some(pipeline) => pipeline.event_loop.send(msg),
@ -2727,37 +2735,46 @@ where
} }
fn handle_focus_msg(&mut self, pipeline_id: PipelineId) { fn handle_focus_msg(&mut self, pipeline_id: PipelineId) {
self.focus_pipeline_id = Some(pipeline_id);
// Focus parent iframes recursively
self.focus_parent_pipeline(pipeline_id);
}
fn focus_parent_pipeline(&mut self, pipeline_id: PipelineId) {
let browsing_context_id = match self.pipelines.get(&pipeline_id) { let browsing_context_id = match self.pipelines.get(&pipeline_id) {
Some(pipeline) => pipeline.browsing_context_id, Some(pipeline) => pipeline.browsing_context_id,
None => return warn!("Pipeline {:?} focus parent after closure.", pipeline_id), None => return warn!("Pipeline {:?} focus parent after closure.", pipeline_id),
}; };
self.focused_browsing_context_id = Some(browsing_context_id);
// Focus parent iframes recursively
self.focus_parent_pipeline(browsing_context_id);
}
fn focus_parent_pipeline(&mut self, browsing_context_id: BrowsingContextId) {
let parent_pipeline_id = match self.browsing_contexts.get(&browsing_context_id) { let parent_pipeline_id = match self.browsing_contexts.get(&browsing_context_id) {
Some(ctx) => ctx.parent_pipeline_id, Some(ctx) => ctx.parent_pipeline_id,
None => return warn!("Browsing context {:?} focus parent after closure.", browsing_context_id), None => return warn!(
"Browsing context {:?} focus parent after closure.",
browsing_context_id
),
}; };
let parent_pipeline_id = match parent_pipeline_id { let parent_pipeline_id = match parent_pipeline_id {
Some(info) => info, Some(parent_id) => parent_id,
None => return debug!("Pipeline {:?} focus has no parent.", pipeline_id), None => return debug!(
"Browsing context {:?} focus has no parent.",
browsing_context_id
),
}; };
// Send a message to the parent of the provided pipeline (if it exists) // Send a message to the parent of the provided browsing context (if it
// telling it to mark the iframe element as focused. // exists) telling it to mark the iframe element as focused.
let msg = ConstellationControlMsg::FocusIFrame(parent_pipeline_id, browsing_context_id); let msg = ConstellationControlMsg::FocusIFrame(parent_pipeline_id, browsing_context_id);
let result = match self.pipelines.get(&parent_pipeline_id) { let (result, parent_browsing_context_id) = match self.pipelines.get(&parent_pipeline_id) {
Some(pipeline) => pipeline.event_loop.send(msg), Some(pipeline) => {
let result = pipeline.event_loop.send(msg);
(result, pipeline.browsing_context_id)
},
None => return warn!("Pipeline {:?} focus after closure.", parent_pipeline_id), None => return warn!("Pipeline {:?} focus after closure.", parent_pipeline_id),
}; };
if let Err(e) = result { if let Err(e) = result {
self.handle_send_error(parent_pipeline_id, e); self.handle_send_error(parent_pipeline_id, e);
} }
self.focus_parent_pipeline(parent_pipeline_id); self.focus_parent_pipeline(parent_browsing_context_id);
} }
fn handle_remove_iframe_msg( fn handle_remove_iframe_msg(
@ -3095,11 +3112,11 @@ where
change.browsing_context_id, change.new_pipeline_id change.browsing_context_id, change.new_pipeline_id
); );
// If the currently focused pipeline is the one being changed (or a child // If the currently focused browsing context is a child of the browsing
// of the pipeline being changed) then update the focus pipeline to be // context in which the page is being loaded, then update the focused
// the replacement. // browsing context to that one.
if self.focused_pipeline_is_descendant_of(change.browsing_context_id) { if self.focused_browsing_context_is_descendant_of(change.browsing_context_id) {
self.focus_pipeline_id = Some(change.new_pipeline_id); self.focused_browsing_context_id = Some(change.browsing_context_id);
} }
let (old_pipeline_id, top_level_id) = let (old_pipeline_id, top_level_id) =
@ -3243,6 +3260,17 @@ where
self.update_frame_tree_if_active(change.top_level_browsing_context_id); self.update_frame_tree_if_active(change.top_level_browsing_context_id);
} }
fn focused_browsing_context_is_descendant_of(
&self,
browsing_context_id: BrowsingContextId
) -> bool {
self.focused_browsing_context_id.map_or(false, |focus_ctx_id| {
focus_ctx_id == browsing_context_id || self
.fully_active_descendant_browsing_contexts_iter(browsing_context_id)
.any(|nested_ctx| nested_ctx.id == focus_ctx_id)
})
}
fn trim_history(&mut self, top_level_browsing_context_id: TopLevelBrowsingContextId) { fn trim_history(&mut self, top_level_browsing_context_id: TopLevelBrowsingContextId) {
let pipelines_to_evict = { let pipelines_to_evict = {
let session_history = self.get_joint_session_history(top_level_browsing_context_id); let session_history = self.get_joint_session_history(top_level_browsing_context_id);
@ -3393,16 +3421,15 @@ where
&mut self, &mut self,
pipeline_states: HashMap<PipelineId, Epoch>, pipeline_states: HashMap<PipelineId, Epoch>,
) -> ReadyToSave { ) -> ReadyToSave {
// Note that this function can panic, due to ipc-channel creation failure. // Note that this function can panic, due to ipc-channel creation
// avoiding this panic would require a mechanism for dealing // failure. Avoiding this panic would require a mechanism for dealing
// with low-resource scenarios. // with low-resource scenarios.
// //
// If there is no focus browsing context yet, the initial page has // If there is no focus browsing context yet, the initial page has
// not loaded, so there is nothing to save yet. // not loaded, so there is nothing to save yet.
let top_level_browsing_context_id = self let top_level_browsing_context_id = self.focused_browsing_context_id
.focus_pipeline_id .and_then(|ctx_id| self.browsing_contexts.get(&ctx_id))
.and_then(|pipeline_id| self.pipelines.get(&pipeline_id)) .map(|ctx| ctx.top_level_id);
.map(|pipeline| pipeline.top_level_browsing_context_id);
let top_level_browsing_context_id = match top_level_browsing_context_id { let top_level_browsing_context_id = match top_level_browsing_context_id {
Some(id) => id, Some(id) => id,
None => return ReadyToSave::NoTopLevelBrowsingContext, None => return ReadyToSave::NoTopLevelBrowsingContext,
@ -3881,11 +3908,4 @@ where
.send(ToCompositorMsg::SetFrameTree(frame_tree)); .send(ToCompositorMsg::SetFrameTree(frame_tree));
} }
} }
fn focused_pipeline_is_descendant_of(&self, browsing_context_id: BrowsingContextId) -> bool {
self.focus_pipeline_id.map_or(false, |pipeline_id| {
self.fully_active_descendant_browsing_contexts_iter(browsing_context_id)
.any(|browsing_context| browsing_context.pipeline_id == pipeline_id)
})
}
} }