Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

script: Start rework to better match the specification HTML event loop #31505

Merged
merged 13 commits into from
May 13, 2024
2 changes: 1 addition & 1 deletion components/script/dom/abstractworkerglobalscope.rs
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ pub fn run_worker_event_loop<T, WorkerMsg, Event>(
while !scope.is_closing() {
// Batch all events that are ready.
// The task queue will throttle non-priority tasks if necessary.
match task_queue.try_recv() {
match task_queue.take_tasks_and_recv() {
Err(_) => match devtools_port.map(|port| port.try_recv()) {
None => {},
Some(Err(_)) => break,
Expand Down
64 changes: 61 additions & 3 deletions components/script/dom/document.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,9 @@ use profile_traits::ipc as profile_ipc;
use profile_traits::time::{TimerMetadata, TimerMetadataFrameType, TimerMetadataReflowType};
use script_layout_interface::{PendingRestyle, ReflowGoal, TrustedNodeAddress};
use script_traits::{
AnimationState, DocumentActivity, MouseButton, MouseEventType, MsDuration, ScriptMsg,
TouchEventType, TouchId, UntrustedNodeAddress, WheelDelta,
AnimationState, AnimationTickType, CompositorEvent, DocumentActivity, MouseButton,
MouseEventType, MsDuration, ScriptMsg, TouchEventType, TouchId, UntrustedNodeAddress,
WheelDelta,
};
use servo_arc::Arc;
use servo_atoms::Atom;
Expand Down Expand Up @@ -446,6 +447,16 @@ pub struct Document {
dirty_root: MutNullableDom<Element>,
/// <https://html.spec.whatwg.org/multipage/#will-declaratively-refresh>
declarative_refresh: DomRefCell<Option<DeclarativeRefresh>>,
/// Pending composition events, to be handled at the next rendering opportunity.
#[no_trace]
#[ignore_malloc_size_of = "CompositorEvent contains data from outside crates"]
pending_compositor_events: DomRefCell<Vec<CompositorEvent>>,
/// The index of the last mouse move event in the pending compositor events queue.
mouse_move_event_index: DomRefCell<Option<usize>>,
/// Pending animation ticks, to be handled at the next rendering opportunity.
#[no_trace]
#[ignore_malloc_size_of = "AnimationTickType contains data from an outside crate"]
pending_animation_ticks: DomRefCell<AnimationTickType>,
}

#[derive(JSTraceable, MallocSizeOf)]
Expand Down Expand Up @@ -1217,7 +1228,7 @@ impl Document {
}

#[allow(unsafe_code)]
pub unsafe fn handle_mouse_event(
pub unsafe fn handle_mouse_button_event(
&self,
button: MouseButton,
client_point: Point2D<f32>,
Expand Down Expand Up @@ -3211,7 +3222,54 @@ impl Document {
animations: DomRefCell::new(Animations::new()),
dirty_root: Default::default(),
declarative_refresh: Default::default(),
pending_animation_ticks: Default::default(),
pending_compositor_events: Default::default(),
mouse_move_event_index: Default::default(),
}
}

/// Note a pending animation tick, to be processed at the next `update_the_rendering` task.
pub fn note_pending_animation_tick(&self, tick_type: AnimationTickType) {
self.pending_animation_ticks.borrow_mut().extend(tick_type);
}

/// As part of a `update_the_rendering` task, tick all pending animations.
pub fn tick_all_animations(&self) {
let tick_type = mem::take(&mut *self.pending_animation_ticks.borrow_mut());
if tick_type.contains(AnimationTickType::REQUEST_ANIMATION_FRAME) {
self.run_the_animation_frame_callbacks();
}
if tick_type.contains(AnimationTickType::CSS_ANIMATIONS_AND_TRANSITIONS) {
self.maybe_mark_animating_nodes_as_dirty();
}
}

/// Note a pending compositor event, to be processed at the next `update_the_rendering` task.
pub fn note_pending_compositor_event(&self, event: CompositorEvent) {
let mut pending_compositor_events = self.pending_compositor_events.borrow_mut();
if matches!(event, CompositorEvent::MouseMoveEvent { .. }) {
// First try to replace any existing mouse move event.
if let Some(mouse_move_event) = self
.mouse_move_event_index
.borrow()
.and_then(|index| pending_compositor_events.get_mut(index))
{
*mouse_move_event = event;
return;
}

*self.mouse_move_event_index.borrow_mut() =
Some(self.pending_compositor_events.borrow().len());
}

self.pending_compositor_events.borrow_mut().push(event);
}

/// Get pending compositor events, for processing within an `update_the_rendering` task.
pub fn take_pending_compositor_events(&self) -> Vec<CompositorEvent> {
// Reset the mouse event index.
*self.mouse_move_event_index.borrow_mut() = None;
mem::take(&mut *self.pending_compositor_events.borrow_mut())
}

pub fn set_csp_list(&self, csp_list: Option<CspList>) {
Expand Down
19 changes: 8 additions & 11 deletions components/script/dom/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use std::ptr::NonNull;
use std::rc::Rc;
use std::sync::atomic::Ordering;
use std::sync::{Arc, Mutex};
use std::{cmp, env};
use std::{cmp, env, mem};

use app_units::Au;
use backtrace::Backtrace;
Expand Down Expand Up @@ -220,9 +220,9 @@ pub struct Window {
#[no_trace]
devtools_marker_sender: DomRefCell<Option<IpcSender<Option<TimelineMarker>>>>,

/// Pending resize event, if any.
/// Pending resize events, if any.
#[no_trace]
resize_event: Cell<Option<(WindowSizeData, WindowSizeType)>>,
resize_events: DomRefCell<Vec<(WindowSizeData, WindowSizeType)>>,

/// Parent id associated with this page, if any.
#[no_trace]
Expand Down Expand Up @@ -2328,14 +2328,12 @@ impl Window {
.set(self.pending_reflow_count.get() + 1);
}

pub fn set_resize_event(&self, event: WindowSizeData, event_type: WindowSizeType) {
self.resize_event.set(Some((event, event_type)));
pub fn add_resize_event(&self, event: WindowSizeData, event_type: WindowSizeType) {
self.resize_events.borrow_mut().push((event, event_type));
}

pub fn steal_resize_event(&self) -> Option<(WindowSizeData, WindowSizeType)> {
let event = self.resize_event.get();
self.resize_event.set(None);
event
pub fn steal_resize_events(&self) -> Vec<(WindowSizeData, WindowSizeType)> {
mem::take(&mut self.resize_events.borrow_mut())
}

pub fn set_page_clip_rect_with_new_viewport(&self, viewport: UntypedRect<f32>) -> bool {
Expand Down Expand Up @@ -2459,7 +2457,6 @@ impl Window {
);
event.upcast::<Event>().fire(mql.upcast::<EventTarget>());
}
self.Document().react_to_environment_changes();
}

/// Set whether to use less resources by running timers at a heavily limited rate.
Expand Down Expand Up @@ -2606,7 +2603,7 @@ impl Window {
bluetooth_thread,
bluetooth_extra_permission_data: BluetoothExtraPermissionData::new(),
page_clip_rect: Cell::new(MaxRect::max_rect()),
resize_event: Default::default(),
resize_events: Default::default(),
window_size: Cell::new(window_size),
current_viewport: Cell::new(initial_viewport.to_untyped()),
suppress_reflow: Cell::new(true),
Expand Down