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:
Martin Robinson 2025-05-26 14:05:38 +02:00 committed by GitHub
parent c96de69e80
commit d3e57a513c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
19 changed files with 201 additions and 74 deletions

View file

@ -17,14 +17,21 @@ use std::rc::Rc;
use anyhow::ensure;
use common::{ServoTest, run_api_tests};
use servo::{
JSValue, JavaScriptEvaluationError, LoadStatus, WebView, WebViewBuilder, WebViewDelegate,
JSValue, JavaScriptEvaluationError, LoadStatus, Theme, WebView, WebViewBuilder, WebViewDelegate,
};
use url::Url;
#[derive(Default)]
struct WebViewDelegateImpl {
url_changed: Cell<bool>,
}
impl WebViewDelegateImpl {
pub(crate) fn reset(&self) {
self.url_changed.set(false);
}
}
impl WebViewDelegate for WebViewDelegateImpl {
fn notify_url_changed(&self, _webview: servo::WebView, _url: url::Url) {
self.url_changed.set(true);
@ -128,10 +135,40 @@ fn test_create_webview_and_immediately_drop_webview_before_shutdown(
Ok(())
}
fn test_theme_change(servo_test: &ServoTest) -> Result<(), anyhow::Error> {
let delegate = Rc::new(WebViewDelegateImpl::default());
let webview = WebViewBuilder::new(servo_test.servo())
.delegate(delegate.clone())
.url(Url::parse("data:text/html,page one").unwrap())
.build();
let is_dark_theme_script = "window.matchMedia('(prefers-color-scheme: dark)').matches";
// The default theme is "light".
let result = evaluate_javascript(servo_test, webview.clone(), is_dark_theme_script);
ensure!(result == Ok(JSValue::Boolean(false)));
// Changing the theme updates the current page.
webview.notify_theme_change(Theme::Dark);
let result = evaluate_javascript(servo_test, webview.clone(), is_dark_theme_script);
ensure!(result == Ok(JSValue::Boolean(true)));
delegate.reset();
webview.load(Url::parse("data:text/html,page two").unwrap());
servo_test.spin(move || Ok(!delegate.url_changed.get()))?;
// The theme persists after a navigation.
let result = evaluate_javascript(servo_test, webview.clone(), is_dark_theme_script);
ensure!(result == Ok(JSValue::Boolean(true)));
Ok(())
}
fn main() {
run_api_tests!(
test_create_webview,
test_evaluate_javascript_basic,
test_theme_change,
// This test needs to be last, as it tests creating and dropping
// a WebView right before shutdown.
test_create_webview_and_immediately_drop_webview_before_shutdown