Use the snapshot from the previous commit to let CompositorThread apply experimental viewport wheel deltas when async scrolling is enabled. The event handler first performs synchronous admission on the main thread, then enqueues a compositor scroll command instead of mutating live document scroll state directly. Rasterize accepted scrolls through the same compositor presentation path added earlier. The compositor stores the newest async viewport offset so the next main-thread display-list recording can adopt it before repainting, preventing older paints from snapping the visible position backward. Keep DOM wheel dispatch on the main thread. When the compositor already performed the default action, dispatch the wheel as non-cancelable and suppress a second default scroll. Non-viewport targets, nested scrollers, and pages with blocking wheel listeners stay synchronous.
72 lines
3 KiB
C++
72 lines
3 KiB
C++
/*
|
|
* Copyright (c) 2022, Aliaksandr Kalenik <kalenik.aliaksandr@gmail.com>
|
|
*
|
|
* SPDX-License-Identifier: BSD-2-Clause
|
|
*/
|
|
|
|
#include <LibWeb/Bindings/Intrinsics.h>
|
|
#include <LibWeb/Bindings/WheelEvent.h>
|
|
#include <LibWeb/HTML/EventNames.h>
|
|
#include <LibWeb/HTML/WindowProxy.h>
|
|
#include <LibWeb/UIEvents/EventNames.h>
|
|
#include <LibWeb/UIEvents/KeyCode.h>
|
|
#include <LibWeb/UIEvents/WheelEvent.h>
|
|
#include <LibWeb/WebIDL/ExceptionOr.h>
|
|
|
|
namespace Web::UIEvents {
|
|
|
|
GC_DEFINE_ALLOCATOR(WheelEvent);
|
|
|
|
WheelEvent::WheelEvent(JS::Realm& realm, FlyString const& event_name, Bindings::WheelEventInit const& event_init, double page_x, double page_y, double offset_x, double offset_y)
|
|
: MouseEvent(realm, event_name, event_init, page_x, page_y, offset_x, offset_y)
|
|
, m_delta_x(event_init.delta_x)
|
|
, m_delta_y(event_init.delta_y)
|
|
, m_delta_z(event_init.delta_z)
|
|
, m_delta_mode(event_init.delta_mode)
|
|
{
|
|
}
|
|
|
|
WheelEvent::~WheelEvent() = default;
|
|
|
|
void WheelEvent::initialize(JS::Realm& realm)
|
|
{
|
|
WEB_SET_PROTOTYPE_FOR_INTERFACE(WheelEvent);
|
|
Base::initialize(realm);
|
|
}
|
|
|
|
GC::Ref<WheelEvent> WheelEvent::construct_impl(JS::Realm& realm, FlyString const& event_name, Bindings::WheelEventInit const& wheel_event_init)
|
|
{
|
|
return create(realm, event_name, wheel_event_init, wheel_event_init.client_x, wheel_event_init.client_y, wheel_event_init.client_x, wheel_event_init.client_y);
|
|
}
|
|
|
|
GC::Ref<WheelEvent> WheelEvent::create(JS::Realm& realm, FlyString const& event_name, Bindings::WheelEventInit const& event_init, double page_x, double page_y, double offset_x, double offset_y)
|
|
{
|
|
return realm.create<WheelEvent>(realm, event_name, event_init, page_x, page_y, offset_x, offset_y);
|
|
}
|
|
|
|
WebIDL::ExceptionOr<GC::Ref<WheelEvent>> WheelEvent::create_from_platform_event(JS::Realm& realm, GC::Ptr<HTML::WindowProxy> window_proxy, FlyString const& event_name, CSSPixelPoint screen, CSSPixelPoint page, CSSPixelPoint client, CSSPixelPoint offset, double delta_x, double delta_y, unsigned button, unsigned buttons, unsigned modifiers, WheelEventIsCancelable is_cancelable)
|
|
{
|
|
Bindings::WheelEventInit event_init {};
|
|
event_init.ctrl_key = modifiers & Mod_Ctrl;
|
|
event_init.shift_key = modifiers & Mod_Shift;
|
|
event_init.alt_key = modifiers & Mod_Alt;
|
|
event_init.meta_key = modifiers & Mod_Super;
|
|
event_init.screen_x = screen.x().to_double();
|
|
event_init.screen_y = screen.y().to_double();
|
|
event_init.client_x = client.x().to_double();
|
|
event_init.client_y = client.y().to_double();
|
|
event_init.button = button;
|
|
event_init.buttons = buttons;
|
|
event_init.delta_x = delta_x;
|
|
event_init.delta_y = delta_y;
|
|
event_init.delta_mode = WheelDeltaMode::DOM_DELTA_PIXEL;
|
|
event_init.view = window_proxy;
|
|
auto event = WheelEvent::create(realm, event_name, event_init, page.x().to_double(), page.y().to_double(), offset.x().to_double(), offset.y().to_double());
|
|
event->set_is_trusted(true);
|
|
event->set_bubbles(true);
|
|
event->set_cancelable(is_cancelable == WheelEventIsCancelable::Yes);
|
|
event->set_composed(true);
|
|
return event;
|
|
}
|
|
|
|
}
|