mirror of
https://github.com/servo/servo.git
synced 2025-08-03 04:30:10 +01:00
constellation: Pass system theme to new Pipelines (#37132)
Previously, when the theme was set it was only set on currently active `Window`s. This change makes setting the `Theme` stateful. Now the `Constellation` tracks what theme is applied to a `WebView` and properly passes that value to new `Pipeline`s when they are constructed. In addition, the value is passed to layout when that is constructed as well. Testing: this change adds a unit test. Signed-off-by: Martin Robinson <mrobinson@igalia.com>
This commit is contained in:
parent
c96de69e80
commit
d3e57a513c
19 changed files with 201 additions and 74 deletions
|
@ -172,6 +172,7 @@ use crate::browsingcontext::{
|
|||
AllBrowsingContextsIterator, BrowsingContext, FullyActiveBrowsingContextsIterator,
|
||||
NewBrowsingContextInfo,
|
||||
};
|
||||
use crate::constellation_webview::ConstellationWebView;
|
||||
use crate::event_loop::EventLoop;
|
||||
use crate::pipeline::{InitialPipelineState, Pipeline};
|
||||
use crate::process_manager::ProcessManager;
|
||||
|
@ -229,18 +230,6 @@ struct WebrenderWGPU {
|
|||
wgpu_image_map: WGPUImageMap,
|
||||
}
|
||||
|
||||
/// Servo supports multiple top-level browsing contexts or “webviews”, so `Constellation` needs to
|
||||
/// store webview-specific data for bookkeeping.
|
||||
struct WebView {
|
||||
/// The currently focused browsing context in this webview for key events.
|
||||
/// The focused pipeline is the current entry of the focused browsing
|
||||
/// context.
|
||||
focused_browsing_context_id: BrowsingContextId,
|
||||
|
||||
/// The joint session history for this webview.
|
||||
session_history: JointSessionHistory,
|
||||
}
|
||||
|
||||
/// A browsing context group.
|
||||
///
|
||||
/// <https://html.spec.whatwg.org/multipage/#browsing-context-group>
|
||||
|
@ -324,7 +313,7 @@ pub struct Constellation<STF, SWF> {
|
|||
compositor_proxy: CompositorProxy,
|
||||
|
||||
/// Bookkeeping data for all webviews in the constellation.
|
||||
webviews: WebViewManager<WebView>,
|
||||
webviews: WebViewManager<ConstellationWebView>,
|
||||
|
||||
/// Channels for the constellation to send messages to the public
|
||||
/// resource-related threads. There are two groups of resource threads: one
|
||||
|
@ -895,6 +884,16 @@ where
|
|||
if self.shutting_down {
|
||||
return;
|
||||
}
|
||||
|
||||
let Some(theme) = self
|
||||
.webviews
|
||||
.get(webview_id)
|
||||
.map(ConstellationWebView::theme)
|
||||
else {
|
||||
warn!("Tried to create Pipeline for uknown WebViewId: {webview_id:?}");
|
||||
return;
|
||||
};
|
||||
|
||||
debug!(
|
||||
"{}: Creating new pipeline in {}",
|
||||
pipeline_id, browsing_context_id
|
||||
|
@ -973,6 +972,7 @@ where
|
|||
time_profiler_chan: self.time_profiler_chan.clone(),
|
||||
mem_profiler_chan: self.mem_profiler_chan.clone(),
|
||||
viewport_details: initial_viewport_details,
|
||||
theme,
|
||||
event_loop,
|
||||
load_data,
|
||||
prev_throttled: throttled,
|
||||
|
@ -1436,8 +1436,8 @@ where
|
|||
size_type,
|
||||
);
|
||||
},
|
||||
EmbedderToConstellationMessage::ThemeChange(theme) => {
|
||||
self.handle_theme_change(theme);
|
||||
EmbedderToConstellationMessage::ThemeChange(webview_id, theme) => {
|
||||
self.handle_theme_change(webview_id, theme);
|
||||
},
|
||||
EmbedderToConstellationMessage::TickAnimation(webview_ids) => {
|
||||
self.handle_tick_animation(webview_ids)
|
||||
|
@ -3142,13 +3142,8 @@ where
|
|||
|
||||
// Register this new top-level browsing context id as a webview and set
|
||||
// its focused browsing context to be itself.
|
||||
self.webviews.add(
|
||||
webview_id,
|
||||
WebView {
|
||||
focused_browsing_context_id: browsing_context_id,
|
||||
session_history: JointSessionHistory::new(),
|
||||
},
|
||||
);
|
||||
self.webviews
|
||||
.add(webview_id, ConstellationWebView::new(browsing_context_id));
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#creating-a-new-browsing-context-group
|
||||
let mut new_bc_group: BrowsingContextGroup = Default::default();
|
||||
|
@ -3554,10 +3549,7 @@ where
|
|||
self.pipelines.insert(new_pipeline_id, pipeline);
|
||||
self.webviews.add(
|
||||
new_webview_id,
|
||||
WebView {
|
||||
focused_browsing_context_id: new_browsing_context_id,
|
||||
session_history: JointSessionHistory::new(),
|
||||
},
|
||||
ConstellationWebView::new(new_browsing_context_id),
|
||||
);
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#bcg-append
|
||||
|
@ -5623,18 +5615,31 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
/// Handle theme change events from the embedder and forward them to the script thread
|
||||
/// Handle theme change events from the embedder and forward them to all appropriate `ScriptThread`s.
|
||||
#[cfg_attr(
|
||||
feature = "tracing",
|
||||
tracing::instrument(skip_all, fields(servo_profiling = true), level = "trace")
|
||||
)]
|
||||
fn handle_theme_change(&mut self, theme: Theme) {
|
||||
fn handle_theme_change(&mut self, webview_id: WebViewId, theme: Theme) {
|
||||
let Some(webview) = self.webviews.get_mut(webview_id) else {
|
||||
warn!("Received theme change request for uknown WebViewId: {webview_id:?}");
|
||||
return;
|
||||
};
|
||||
if !webview.set_theme(theme) {
|
||||
return;
|
||||
}
|
||||
|
||||
for pipeline in self.pipelines.values() {
|
||||
let msg = ScriptThreadMessage::ThemeChange(pipeline.id, theme);
|
||||
if let Err(err) = pipeline.event_loop.send(msg) {
|
||||
if pipeline.webview_id != webview_id {
|
||||
continue;
|
||||
}
|
||||
if let Err(error) = pipeline
|
||||
.event_loop
|
||||
.send(ScriptThreadMessage::ThemeChange(pipeline.id, theme))
|
||||
{
|
||||
warn!(
|
||||
"{}: Failed to send theme change event to pipeline ({:?}).",
|
||||
pipeline.id, err
|
||||
"{}: Failed to send theme change event to pipeline ({error:?}).",
|
||||
pipeline.id,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
45
components/constellation/constellation_webview.rs
Normal file
45
components/constellation/constellation_webview.rs
Normal file
|
@ -0,0 +1,45 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use base::id::BrowsingContextId;
|
||||
use embedder_traits::Theme;
|
||||
|
||||
use crate::session_history::JointSessionHistory;
|
||||
|
||||
/// The `Constellation`'s view of a `WebView` in the embedding layer. This tracks all of the
|
||||
/// `Constellation` state for this `WebView`.
|
||||
pub(crate) struct ConstellationWebView {
|
||||
/// The currently focused browsing context in this webview for key events.
|
||||
/// The focused pipeline is the current entry of the focused browsing
|
||||
/// context.
|
||||
pub focused_browsing_context_id: BrowsingContextId,
|
||||
|
||||
/// The joint session history for this webview.
|
||||
pub session_history: JointSessionHistory,
|
||||
|
||||
/// The [`Theme`] that this [`ConstellationWebView`] uses. This is communicated to all
|
||||
/// `ScriptThread`s so that they know how to render the contents of a particular `WebView.
|
||||
theme: Theme,
|
||||
}
|
||||
|
||||
impl ConstellationWebView {
|
||||
pub(crate) fn new(focused_browsing_context_id: BrowsingContextId) -> Self {
|
||||
Self {
|
||||
focused_browsing_context_id,
|
||||
session_history: JointSessionHistory::new(),
|
||||
theme: Theme::Light,
|
||||
}
|
||||
}
|
||||
|
||||
/// Set the [`Theme`] on this [`ConstellationWebView`] returning true if the theme changed.
|
||||
pub(crate) fn set_theme(&mut self, new_theme: Theme) -> bool {
|
||||
let old_theme = std::mem::replace(&mut self.theme, new_theme);
|
||||
old_theme != self.theme
|
||||
}
|
||||
|
||||
/// Get the [`Theme`] of this [`ConstellationWebView`].
|
||||
pub(crate) fn theme(&self) -> Theme {
|
||||
self.theme
|
||||
}
|
||||
}
|
|
@ -9,6 +9,7 @@ mod tracing;
|
|||
|
||||
mod browsingcontext;
|
||||
mod constellation;
|
||||
mod constellation_webview;
|
||||
mod event_loop;
|
||||
mod logging;
|
||||
mod pipeline;
|
||||
|
|
|
@ -25,7 +25,7 @@ use constellation_traits::{LoadData, SWManagerMsg, ScriptToConstellationChan};
|
|||
use crossbeam_channel::{Sender, unbounded};
|
||||
use devtools_traits::{DevtoolsControlMsg, ScriptToDevtoolsControlMsg};
|
||||
use embedder_traits::user_content_manager::UserContentManager;
|
||||
use embedder_traits::{AnimationState, FocusSequenceNumber, ViewportDetails};
|
||||
use embedder_traits::{AnimationState, FocusSequenceNumber, Theme, ViewportDetails};
|
||||
use fonts::{SystemFontServiceProxy, SystemFontServiceProxySender};
|
||||
use ipc_channel::Error;
|
||||
use ipc_channel::ipc::{self, IpcReceiver, IpcSender};
|
||||
|
@ -61,7 +61,7 @@ pub struct Pipeline {
|
|||
/// The ID of the browsing context that contains this Pipeline.
|
||||
pub browsing_context_id: BrowsingContextId,
|
||||
|
||||
/// The ID of the top-level browsing context that contains this Pipeline.
|
||||
/// The [`WebViewId`] of the `WebView` that contains this Pipeline.
|
||||
pub webview_id: WebViewId,
|
||||
|
||||
pub opener: Option<BrowsingContextId>,
|
||||
|
@ -170,6 +170,9 @@ pub struct InitialPipelineState {
|
|||
/// The initial [`ViewportDetails`] to use when starting this new [`Pipeline`].
|
||||
pub viewport_details: ViewportDetails,
|
||||
|
||||
/// The initial [`Theme`] to use when starting this new [`Pipeline`].
|
||||
pub theme: Theme,
|
||||
|
||||
/// The ID of the pipeline namespace for this script thread.
|
||||
pub pipeline_namespace_id: PipelineNamespaceId,
|
||||
|
||||
|
@ -224,6 +227,7 @@ impl Pipeline {
|
|||
opener: state.opener,
|
||||
load_data: state.load_data.clone(),
|
||||
viewport_details: state.viewport_details,
|
||||
theme: state.theme,
|
||||
};
|
||||
|
||||
if let Err(e) = script_chan.send(ScriptThreadMessage::AttachLayout(new_layout_info))
|
||||
|
@ -280,6 +284,7 @@ impl Pipeline {
|
|||
time_profiler_chan: state.time_profiler_chan,
|
||||
mem_profiler_chan: state.mem_profiler_chan,
|
||||
viewport_details: state.viewport_details,
|
||||
theme: state.theme,
|
||||
script_chan: script_chan.clone(),
|
||||
load_data: state.load_data.clone(),
|
||||
script_port,
|
||||
|
@ -494,6 +499,7 @@ pub struct UnprivilegedPipelineContent {
|
|||
time_profiler_chan: time::ProfilerChan,
|
||||
mem_profiler_chan: profile_mem::ProfilerChan,
|
||||
viewport_details: ViewportDetails,
|
||||
theme: Theme,
|
||||
script_chan: IpcSender<ScriptThreadMessage>,
|
||||
load_data: LoadData,
|
||||
script_port: IpcReceiver<ScriptThreadMessage>,
|
||||
|
@ -544,6 +550,7 @@ impl UnprivilegedPipelineContent {
|
|||
memory_profiler_sender: self.mem_profiler_chan.clone(),
|
||||
devtools_server_sender: self.devtools_ipc_sender,
|
||||
viewport_details: self.viewport_details,
|
||||
theme: self.theme,
|
||||
pipeline_namespace_id: self.pipeline_namespace_id,
|
||||
content_process_shutdown_sender: content_process_shutdown_chan,
|
||||
webgl_chan: self.webgl_chan,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue