mirror of
https://github.com/servo/servo.git
synced 2025-09-01 02:28:21 +01:00
libservo: Move animation tracking from WindowMethods
to delegates (#36400)
This changes removes animation tracking from the `WindowMethods` trait and moves it to `ServoDelegate` and `WebViewDelegate`. - Animation changes per-`WebView` are now triggered in the compositor only when the value is updated there, rather than right after ticking animations. - Both `WebView` and `Servo` now expose an `animation()` method, so tracking animation state actually becomes unecessary in many cases, such as that of desktop servoshell, which can just read the value when the event loop spins. Testing: No tests necessary as the API layer is still untested. Later, tests will be added for the `WebView` API and this can be tested then. Signed-off-by: Martin Robinson <mrobinson@igalia.com> Signed-off-by: Martin Robinson <mrobinson@igalia.com>
This commit is contained in:
parent
935db71183
commit
2fe57cc2a2
15 changed files with 153 additions and 125 deletions
|
@ -13,7 +13,7 @@ use std::{env, fs};
|
|||
|
||||
use euclid::Scale;
|
||||
use log::{info, trace, warn};
|
||||
use servo::compositing::windowing::{AnimationState, WindowMethods};
|
||||
use servo::compositing::windowing::WindowMethods;
|
||||
use servo::config::opts::Opts;
|
||||
use servo::config::prefs::Preferences;
|
||||
use servo::servo_config::pref;
|
||||
|
@ -146,9 +146,6 @@ impl App {
|
|||
fn hidpi_factor(&self) -> Scale<f32, DeviceIndependentPixel, DevicePixel> {
|
||||
self.0.hidpi_factor()
|
||||
}
|
||||
fn set_animation_state(&self, state: AnimationState) {
|
||||
self.0.set_animation_state(state);
|
||||
}
|
||||
}
|
||||
|
||||
let mut user_content_manager = UserContentManager::new();
|
||||
|
@ -183,8 +180,12 @@ impl App {
|
|||
self.state = AppState::Running(running_state);
|
||||
}
|
||||
|
||||
pub fn is_animating(&self) -> bool {
|
||||
self.windows.iter().any(|(_, window)| window.is_animating())
|
||||
pub(crate) fn animating(&self) -> bool {
|
||||
match self.state {
|
||||
AppState::Initializing => false,
|
||||
AppState::Running(ref running_app_state) => running_app_state.servo().animating(),
|
||||
AppState::ShuttingDown => false,
|
||||
}
|
||||
}
|
||||
|
||||
/// Handle events with winit contexts
|
||||
|
@ -401,10 +402,8 @@ impl ApplicationHandler<WakerEvent> for App {
|
|||
window.handle_winit_event(state.clone(), event);
|
||||
}
|
||||
|
||||
let animating = self.is_animating();
|
||||
|
||||
// Block until the window gets an event
|
||||
if !animating || self.suspended.get() {
|
||||
if !self.animating() || self.suspended.get() {
|
||||
event_loop.set_control_flow(ControlFlow::Wait);
|
||||
} else {
|
||||
event_loop.set_control_flow(ControlFlow::Poll);
|
||||
|
@ -427,7 +426,7 @@ impl ApplicationHandler<WakerEvent> for App {
|
|||
);
|
||||
self.t = now;
|
||||
|
||||
if !matches!(self.state, AppState::Running(_)) {
|
||||
if !matches!(self.state, AppState::Running(..)) {
|
||||
return;
|
||||
};
|
||||
let Some(window) = self.windows.values().next() else {
|
||||
|
@ -435,10 +434,8 @@ impl ApplicationHandler<WakerEvent> for App {
|
|||
};
|
||||
let window = window.clone();
|
||||
|
||||
let animating = self.is_animating();
|
||||
|
||||
// Block until the window gets an event
|
||||
if !animating || self.suspended.get() {
|
||||
if !self.animating() || self.suspended.get() {
|
||||
event_loop.set_control_flow(ControlFlow::Wait);
|
||||
} else {
|
||||
event_loop.set_control_flow(ControlFlow::Poll);
|
||||
|
|
|
@ -96,7 +96,7 @@ impl EventsLoop {
|
|||
if !app.handle_events_with_headless() {
|
||||
break;
|
||||
}
|
||||
if !app.is_animating() {
|
||||
if !app.animating() {
|
||||
*flag.lock().unwrap() = false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@ use euclid::{Angle, Length, Point2D, Rotation3D, Scale, Size2D, UnknownUnit, Vec
|
|||
use keyboard_types::{Modifiers, ShortcutMatcher};
|
||||
use log::{debug, info};
|
||||
use raw_window_handle::{HasDisplayHandle, HasWindowHandle, RawWindowHandle};
|
||||
use servo::compositing::windowing::{AnimationState, WebRenderDebugOption, WindowMethods};
|
||||
use servo::compositing::windowing::{WebRenderDebugOption, WindowMethods};
|
||||
use servo::servo_config::pref;
|
||||
use servo::servo_geometry::DeviceIndependentPixel;
|
||||
use servo::webrender_api::ScrollLocation;
|
||||
|
@ -62,7 +62,6 @@ pub struct Window {
|
|||
/// A map of winit's key codes to key values that are interpreted from
|
||||
/// winit's ReceivedChar events.
|
||||
keys_down: RefCell<HashMap<LogicalKey, Key>>,
|
||||
animation_state: Cell<AnimationState>,
|
||||
fullscreen: Cell<bool>,
|
||||
device_pixel_ratio_override: Option<f32>,
|
||||
xr_window_poses: RefCell<Vec<Rc<XRWindowPose>>>,
|
||||
|
@ -151,7 +150,6 @@ impl Window {
|
|||
webview_relative_mouse_point: Cell::new(Point2D::zero()),
|
||||
last_pressed: Cell::new(None),
|
||||
keys_down: RefCell::new(HashMap::new()),
|
||||
animation_state: Cell::new(AnimationState::Idle),
|
||||
fullscreen: Cell::new(false),
|
||||
inner_size: Cell::new(inner_size),
|
||||
monitor,
|
||||
|
@ -570,10 +568,6 @@ impl WindowPortsMethods for Window {
|
|||
self.winit_window.set_cursor_visible(true);
|
||||
}
|
||||
|
||||
fn is_animating(&self) -> bool {
|
||||
self.animation_state.get() == AnimationState::Animating
|
||||
}
|
||||
|
||||
fn id(&self) -> winit::window::WindowId {
|
||||
self.winit_window.id()
|
||||
}
|
||||
|
@ -772,10 +766,6 @@ impl WindowMethods for Window {
|
|||
self.device_pixel_ratio_override()
|
||||
.unwrap_or_else(|| self.device_hidpi_factor())
|
||||
}
|
||||
|
||||
fn set_animation_state(&self, state: AnimationState) {
|
||||
self.animation_state.set(state);
|
||||
}
|
||||
}
|
||||
|
||||
fn winit_phase_to_touch_event_type(phase: TouchPhase) -> TouchEventType {
|
||||
|
|
|
@ -9,7 +9,7 @@ use std::rc::Rc;
|
|||
|
||||
use euclid::num::Zero;
|
||||
use euclid::{Length, Scale, Size2D};
|
||||
use servo::compositing::windowing::{AnimationState, WindowMethods};
|
||||
use servo::compositing::windowing::WindowMethods;
|
||||
use servo::servo_geometry::DeviceIndependentPixel;
|
||||
use servo::webrender_api::units::{DeviceIntSize, DevicePixel};
|
||||
use servo::{RenderingContext, ScreenGeometry, SoftwareRenderingContext};
|
||||
|
@ -20,7 +20,6 @@ use crate::desktop::window_trait::WindowPortsMethods;
|
|||
use crate::prefs::ServoShellPreferences;
|
||||
|
||||
pub struct Window {
|
||||
animation_state: Cell<AnimationState>,
|
||||
fullscreen: Cell<bool>,
|
||||
device_pixel_ratio_override: Option<Scale<f32, DeviceIndependentPixel, DevicePixel>>,
|
||||
inner_size: Cell<DeviceIntSize>,
|
||||
|
@ -50,7 +49,6 @@ impl Window {
|
|||
});
|
||||
|
||||
let window = Window {
|
||||
animation_state: Cell::new(AnimationState::Idle),
|
||||
fullscreen: Cell::new(false),
|
||||
device_pixel_ratio_override,
|
||||
inner_size: Cell::new(inner_size),
|
||||
|
@ -120,10 +118,6 @@ impl WindowPortsMethods for Window {
|
|||
self.fullscreen.get()
|
||||
}
|
||||
|
||||
fn is_animating(&self) -> bool {
|
||||
self.animation_state.get() == AnimationState::Animating
|
||||
}
|
||||
|
||||
fn handle_winit_event(&self, _: Rc<RunningAppState>, _: winit::event::WindowEvent) {
|
||||
// Not expecting any winit events.
|
||||
}
|
||||
|
@ -157,8 +151,4 @@ impl WindowMethods for Window {
|
|||
self.device_pixel_ratio_override()
|
||||
.unwrap_or_else(|| self.device_hidpi_factor())
|
||||
}
|
||||
|
||||
fn set_animation_state(&self, state: AnimationState) {
|
||||
self.animation_state.set(state);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,7 +28,6 @@ pub trait WindowPortsMethods: WindowMethods {
|
|||
fn page_height(&self) -> f32;
|
||||
fn get_fullscreen(&self) -> bool;
|
||||
fn handle_winit_event(&self, state: Rc<RunningAppState>, event: winit::event::WindowEvent);
|
||||
fn is_animating(&self) -> bool;
|
||||
fn set_title(&self, _title: &str) {}
|
||||
/// Request a new inner size for the window, not including external decorations.
|
||||
fn request_resize(&self, webview: &WebView, inner_size: DeviceIntSize)
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/* 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 std::cell::{Ref, RefCell, RefMut};
|
||||
use std::cell::{Cell, Ref, RefCell, RefMut};
|
||||
use std::collections::HashMap;
|
||||
use std::rc::Rc;
|
||||
|
||||
|
@ -11,7 +11,7 @@ use keyboard_types::{CompositionEvent, CompositionState};
|
|||
use log::{debug, error, info, warn};
|
||||
use raw_window_handle::{RawWindowHandle, WindowHandle};
|
||||
use servo::base::id::WebViewId;
|
||||
use servo::compositing::windowing::{AnimationState, EmbedderMethods, WindowMethods};
|
||||
use servo::compositing::windowing::{EmbedderMethods, WindowMethods};
|
||||
use servo::euclid::{Point2D, Rect, Scale, Size2D, Vector2D};
|
||||
use servo::servo_geometry::DeviceIndependentPixel;
|
||||
use servo::webrender_api::ScrollLocation;
|
||||
|
@ -86,9 +86,16 @@ struct RunningAppStateInner {
|
|||
focused_webview_id: Option<WebViewId>,
|
||||
|
||||
context_menu_sender: Option<IpcSender<ContextMenuResult>>,
|
||||
|
||||
/// Whether or not the animation state has changed. This is used to trigger
|
||||
/// host callbacks indicating that animation state has changed.
|
||||
animating_state_changed: Rc<Cell<bool>>,
|
||||
}
|
||||
|
||||
struct ServoShellServoDelegate {
|
||||
animating_state_changed: Rc<Cell<bool>>,
|
||||
}
|
||||
|
||||
struct ServoShellServoDelegate;
|
||||
impl ServoDelegate for ServoShellServoDelegate {
|
||||
fn notify_devtools_server_started(&self, _servo: &Servo, port: u16, _token: String) {
|
||||
info!("Devtools Server running on port {port}");
|
||||
|
@ -101,6 +108,10 @@ impl ServoDelegate for ServoShellServoDelegate {
|
|||
fn notify_error(&self, _servo: &Servo, error: ServoError) {
|
||||
error!("Saw Servo error: {error:?}!");
|
||||
}
|
||||
|
||||
fn notify_animating_changed(&self, _animating: bool) {
|
||||
self.animating_state_changed.set(true);
|
||||
}
|
||||
}
|
||||
|
||||
impl WebViewDelegate for RunningAppState {
|
||||
|
@ -263,7 +274,10 @@ impl RunningAppState {
|
|||
.or_else(|| Url::parse("about:blank").ok())
|
||||
.unwrap();
|
||||
|
||||
servo.set_delegate(Rc::new(ServoShellServoDelegate));
|
||||
let animating_state_changed = Rc::new(Cell::new(false));
|
||||
servo.set_delegate(Rc::new(ServoShellServoDelegate {
|
||||
animating_state_changed: animating_state_changed.clone(),
|
||||
}));
|
||||
|
||||
let app_state = Rc::new(Self {
|
||||
rendering_context,
|
||||
|
@ -276,6 +290,7 @@ impl RunningAppState {
|
|||
webviews: Default::default(),
|
||||
creation_order: vec![],
|
||||
focused_webview_id: None,
|
||||
animating_state_changed,
|
||||
}),
|
||||
});
|
||||
|
||||
|
@ -345,6 +360,12 @@ impl RunningAppState {
|
|||
if !should_continue {
|
||||
self.callbacks.host_callbacks.on_shutdown_complete();
|
||||
}
|
||||
if self.inner().animating_state_changed.get() {
|
||||
self.inner().animating_state_changed.set(false);
|
||||
self.callbacks
|
||||
.host_callbacks
|
||||
.on_animating_changed(self.servo.animating());
|
||||
}
|
||||
}
|
||||
|
||||
/// Load an URL.
|
||||
|
@ -684,10 +705,4 @@ impl WindowMethods for ServoWindowCallbacks {
|
|||
fn hidpi_factor(&self) -> Scale<f32, DeviceIndependentPixel, DevicePixel> {
|
||||
self.hidpi_factor
|
||||
}
|
||||
|
||||
fn set_animation_state(&self, state: AnimationState) {
|
||||
debug!("WindowMethods::set_animation_state: {:?}", state);
|
||||
self.host_callbacks
|
||||
.on_animating_changed(state == AnimationState::Animating);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue