mirror of
https://github.com/servo/servo.git
synced 2025-07-03 05:23:38 +01:00
Update Constellation to track focused BrowsingContext instead of Pipeline
This commit is contained in:
parent
80379c8f93
commit
dab49a217f
1 changed files with 70 additions and 50 deletions
|
@ -289,8 +289,10 @@ pub struct Constellation<Message, LTF, STF> {
|
|||
/// we store a `SessionHistoryChange` object for the navigation in progress.
|
||||
pending_changes: Vec<SessionHistoryChange>,
|
||||
|
||||
/// The currently focused pipeline for key events.
|
||||
focus_pipeline_id: Option<PipelineId>,
|
||||
/// The currently focused browsing context for key events. The focused
|
||||
/// 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,
|
||||
/// and the namespaces are allocated by the constellation.
|
||||
|
@ -606,7 +608,7 @@ where
|
|||
// We initialize the namespace at 2, since we reserved
|
||||
// namespace 0 for the embedder, and 0 for the constellation
|
||||
next_pipeline_namespace_id: PipelineNamespaceId(2),
|
||||
focus_pipeline_id: None,
|
||||
focused_browsing_context_id: None,
|
||||
time_profiler_chan: state.time_profiler_chan,
|
||||
mem_profiler_chan: state.mem_profiler_chan,
|
||||
window_size: WindowSizeData {
|
||||
|
@ -961,14 +963,12 @@ where
|
|||
self.handle_get_pipeline(browsing_context_id, resp_chan);
|
||||
},
|
||||
FromCompositorMsg::GetFocusTopLevelBrowsingContext(resp_chan) => {
|
||||
let focus_browsing_context = self
|
||||
.focus_pipeline_id
|
||||
.and_then(|pipeline_id| self.pipelines.get(&pipeline_id))
|
||||
.map(|pipeline| pipeline.top_level_browsing_context_id)
|
||||
.filter(|&top_level_browsing_context_id| {
|
||||
let browsing_context_id =
|
||||
BrowsingContextId::from(top_level_browsing_context_id);
|
||||
self.browsing_contexts.contains_key(&browsing_context_id)
|
||||
let focus_browsing_context = self.focused_browsing_context_id
|
||||
.and_then(|ctx_id| self.browsing_contexts.get(&ctx_id))
|
||||
.map(|ctx| ctx.top_level_id)
|
||||
.filter(|&top_level_ctx_id| {
|
||||
let ctx_id = BrowsingContextId::from(top_level_ctx_id);
|
||||
self.browsing_contexts.contains_key(&ctx_id)
|
||||
});
|
||||
let _ = resp_chan.send(focus_browsing_context);
|
||||
},
|
||||
|
@ -1644,9 +1644,10 @@ where
|
|||
let is_private = false;
|
||||
let is_visible = true;
|
||||
|
||||
if self.focus_pipeline_id.is_none() {
|
||||
self.focus_pipeline_id = Some(pipeline_id);
|
||||
if self.focused_browsing_context_id.is_none() {
|
||||
self.focused_browsing_context_id = Some(browsing_context_id);
|
||||
}
|
||||
|
||||
self.joint_session_histories
|
||||
.insert(top_level_browsing_context_id, JointSessionHistory::new());
|
||||
self.new_pipeline(
|
||||
|
@ -2622,11 +2623,18 @@ where
|
|||
}
|
||||
|
||||
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
|
||||
// the compositor.
|
||||
match self.focus_pipeline_id {
|
||||
Some(pipeline_id) => {
|
||||
// Send to the focused browsing contexts' current pipeline. If it
|
||||
// doesn't exist, fall back to sending to the compositor.
|
||||
match self.focused_browsing_context_id {
|
||||
Some(browsing_context_id) => {
|
||||
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 result = match self.pipelines.get(&pipeline_id) {
|
||||
Some(pipeline) => pipeline.event_loop.send(msg),
|
||||
|
@ -2727,37 +2735,46 @@ where
|
|||
}
|
||||
|
||||
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) {
|
||||
Some(pipeline) => pipeline.browsing_context_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) {
|
||||
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 {
|
||||
Some(info) => info,
|
||||
None => return debug!("Pipeline {:?} focus has no parent.", pipeline_id),
|
||||
Some(parent_id) => parent_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)
|
||||
// telling it to mark the iframe element as focused.
|
||||
// Send a message to the parent of the provided browsing context (if it
|
||||
// exists) telling it to mark the iframe element as focused.
|
||||
let msg = ConstellationControlMsg::FocusIFrame(parent_pipeline_id, browsing_context_id);
|
||||
let result = match self.pipelines.get(&parent_pipeline_id) {
|
||||
Some(pipeline) => pipeline.event_loop.send(msg),
|
||||
let (result, parent_browsing_context_id) = match self.pipelines.get(&parent_pipeline_id) {
|
||||
Some(pipeline) => {
|
||||
let result = pipeline.event_loop.send(msg);
|
||||
(result, pipeline.browsing_context_id)
|
||||
},
|
||||
None => return warn!("Pipeline {:?} focus after closure.", parent_pipeline_id),
|
||||
};
|
||||
if let Err(e) = result {
|
||||
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(
|
||||
|
@ -3095,11 +3112,11 @@ where
|
|||
change.browsing_context_id, change.new_pipeline_id
|
||||
);
|
||||
|
||||
// If the currently focused pipeline is the one being changed (or a child
|
||||
// of the pipeline being changed) then update the focus pipeline to be
|
||||
// the replacement.
|
||||
if self.focused_pipeline_is_descendant_of(change.browsing_context_id) {
|
||||
self.focus_pipeline_id = Some(change.new_pipeline_id);
|
||||
// If the currently focused browsing context is a child of the browsing
|
||||
// context in which the page is being loaded, then update the focused
|
||||
// browsing context to that one.
|
||||
if self.focused_browsing_context_is_descendant_of(change.browsing_context_id) {
|
||||
self.focused_browsing_context_id = Some(change.browsing_context_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);
|
||||
}
|
||||
|
||||
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) {
|
||||
let pipelines_to_evict = {
|
||||
let session_history = self.get_joint_session_history(top_level_browsing_context_id);
|
||||
|
@ -3393,16 +3421,15 @@ where
|
|||
&mut self,
|
||||
pipeline_states: HashMap<PipelineId, Epoch>,
|
||||
) -> ReadyToSave {
|
||||
// Note that this function can panic, due to ipc-channel creation failure.
|
||||
// avoiding this panic would require a mechanism for dealing
|
||||
// Note that this function can panic, due to ipc-channel creation
|
||||
// failure. Avoiding this panic would require a mechanism for dealing
|
||||
// with low-resource scenarios.
|
||||
//
|
||||
// If there is no focus browsing context yet, the initial page has
|
||||
// not loaded, so there is nothing to save yet.
|
||||
let top_level_browsing_context_id = self
|
||||
.focus_pipeline_id
|
||||
.and_then(|pipeline_id| self.pipelines.get(&pipeline_id))
|
||||
.map(|pipeline| pipeline.top_level_browsing_context_id);
|
||||
let top_level_browsing_context_id = self.focused_browsing_context_id
|
||||
.and_then(|ctx_id| self.browsing_contexts.get(&ctx_id))
|
||||
.map(|ctx| ctx.top_level_id);
|
||||
let top_level_browsing_context_id = match top_level_browsing_context_id {
|
||||
Some(id) => id,
|
||||
None => return ReadyToSave::NoTopLevelBrowsingContext,
|
||||
|
@ -3881,11 +3908,4 @@ where
|
|||
.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)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue