LibWeb+LibWebView+WebContent: Return a named enum from UI event handlers
Some checks are pending
CI / Lagom (false, FUZZ, ubuntu-22.04, Linux, Clang) (push) Waiting to run
CI / Lagom (false, NO_FUZZ, macos-14, macOS, Clang) (push) Waiting to run
CI / Lagom (false, NO_FUZZ, ubuntu-22.04, Linux, GNU) (push) Waiting to run
CI / Lagom (true, NO_FUZZ, ubuntu-22.04, Linux, Clang) (push) Waiting to run
Package the js repl as a binary artifact / build-and-package (macos-14, macOS, macOS-universal2) (push) Waiting to run
Package the js repl as a binary artifact / build-and-package (ubuntu-22.04, Linux, Linux-x86_64) (push) Waiting to run
Run test262 and test-wasm / run_and_update_results (push) Waiting to run
Lint Code / lint (push) Waiting to run
Push notes / build (push) Waiting to run

UI event handlers currently return a boolean where false means the event
was cancelled by a script on the page, or otherwise dropped. It has been
a point of confusion for some time now, as it's not particularly clear
what should be returned in some special cases, or how the UI process
should handle the response.

This adds an enumeration with a few states that indicate exactly how the
WebContent process handled the event. This should remove all ambiguity,
and let us properly handle these states going forward.

There should be no behavior change with this patch. It's meant to only
introduce the enum, not change any of our decisions based on the result.
This commit is contained in:
Timothy Flynn 2024-09-12 12:56:31 -04:00 committed by Tim Flynn
parent a64d182583
commit 541968b30d
Notes: github-actions[bot] 2024-09-12 21:39:29 +00:00
15 changed files with 200 additions and 161 deletions

View file

@ -71,7 +71,7 @@ static bool is_primitive_type(ByteString const& type)
static bool is_simple_type(ByteString const& type)
{
// Small types that it makes sense just to pass by value.
return type.is_one_of("AK::CaseSensitivity", "Gfx::Color", "Web::DevicePixels", "Gfx::IntPoint", "Gfx::FloatPoint", "Web::DevicePixelPoint", "Gfx::IntSize", "Gfx::FloatSize", "Web::DevicePixelSize", "Core::File::OpenMode", "Web::Cookie::Source", "Web::HTML::AllowMultipleFiles", "Web::HTML::AudioPlayState", "Web::HTML::HistoryHandlingBehavior");
return type.is_one_of("AK::CaseSensitivity", "Gfx::Color", "Web::DevicePixels", "Gfx::IntPoint", "Gfx::FloatPoint", "Web::DevicePixelPoint", "Gfx::IntSize", "Gfx::FloatSize", "Web::DevicePixelSize", "Core::File::OpenMode", "Web::Cookie::Source", "Web::EventResult", "Web::HTML::AllowMultipleFiles", "Web::HTML::AudioPlayState", "Web::HTML::HistoryHandlingBehavior");
}
static bool is_primitive_or_simple_type(ByteString const& type)

View file

@ -23,7 +23,7 @@ void DragAndDropEventHandler::visit_edges(JS::Cell::Visitor& visitor) const
}
// https://html.spec.whatwg.org/multipage/dnd.html#drag-and-drop-processing-model
bool DragAndDropEventHandler::handle_drag_start(
EventResult DragAndDropEventHandler::handle_drag_start(
JS::Realm& realm,
CSSPixelPoint screen_position,
CSSPixelPoint page_offset,
@ -154,7 +154,7 @@ bool DragAndDropEventHandler::handle_drag_start(
// If the event is canceled, then the drag-and-drop operation should not occur; return.
if (drag_event->cancelled()) {
reset();
return false;
return EventResult::Cancelled;
}
// FIXME: 10. Fire a pointer event at the source node named pointercancel, and fire any other follow-up events as
@ -169,11 +169,11 @@ bool DragAndDropEventHandler::handle_drag_start(
// as distances in CSS pixels from the left side and from the top side of the image respectively.
// 2. The drag data store default feedback.
return true;
return EventResult::Handled;
}
// https://html.spec.whatwg.org/multipage/dnd.html#drag-and-drop-processing-model:queue-a-task
bool DragAndDropEventHandler::handle_drag_move(
EventResult DragAndDropEventHandler::handle_drag_move(
JS::Realm& realm,
JS::NonnullGCPtr<DOM::Document> document,
JS::NonnullGCPtr<DOM::Node> node,
@ -186,7 +186,7 @@ bool DragAndDropEventHandler::handle_drag_move(
unsigned modifiers)
{
if (!has_ongoing_drag_and_drop_operation())
return false;
return EventResult::Cancelled;
auto fire_a_drag_and_drop_event = [&](JS::GCPtr<DOM::EventTarget> target, FlyString const& name, JS::GCPtr<DOM::EventTarget> related_target = nullptr) {
return this->fire_a_drag_and_drop_event(realm, target, name, screen_position, page_offset, client_offset, offset, button, buttons, modifiers, related_target);
@ -320,10 +320,10 @@ bool DragAndDropEventHandler::handle_drag_move(
if (drag_event->cancelled())
return handle_drag_end(realm, Cancelled::Yes, screen_position, page_offset, client_offset, offset, button, buttons, modifiers);
return true;
return EventResult::Handled;
}
bool DragAndDropEventHandler::handle_drag_leave(
EventResult DragAndDropEventHandler::handle_drag_leave(
JS::Realm& realm,
CSSPixelPoint screen_position,
CSSPixelPoint page_offset,
@ -336,7 +336,7 @@ bool DragAndDropEventHandler::handle_drag_leave(
return handle_drag_end(realm, Cancelled::Yes, screen_position, page_offset, client_offset, offset, button, buttons, modifiers);
}
bool DragAndDropEventHandler::handle_drop(
EventResult DragAndDropEventHandler::handle_drop(
JS::Realm& realm,
CSSPixelPoint screen_position,
CSSPixelPoint page_offset,
@ -350,7 +350,7 @@ bool DragAndDropEventHandler::handle_drop(
}
// https://html.spec.whatwg.org/multipage/dnd.html#drag-and-drop-processing-model:event-dnd-drag-3
bool DragAndDropEventHandler::handle_drag_end(
EventResult DragAndDropEventHandler::handle_drag_end(
JS::Realm& realm,
Cancelled cancelled,
CSSPixelPoint screen_position,
@ -362,7 +362,7 @@ bool DragAndDropEventHandler::handle_drag_end(
unsigned modifiers)
{
if (!has_ongoing_drag_and_drop_operation())
return false;
return EventResult::Cancelled;
auto fire_a_drag_and_drop_event = [&](JS::GCPtr<DOM::EventTarget> target, FlyString const& name, JS::GCPtr<DOM::EventTarget> related_target = nullptr) {
return this->fire_a_drag_and_drop_event(realm, target, name, screen_position, page_offset, client_offset, offset, button, buttons, modifiers, related_target);
@ -456,7 +456,7 @@ bool DragAndDropEventHandler::handle_drag_end(
else if (!dropped || m_current_drag_operation == HTML::DataTransferEffect::none) {
// The drag was canceled. If the platform conventions dictate that this be represented to the user (e.g. by
// animating the dragged selection going back to the source of the drag-and-drop operation), then do so.
return false;
return EventResult::Cancelled;
}
// -> Otherwise
else {
@ -464,7 +464,7 @@ bool DragAndDropEventHandler::handle_drag_end(
}
}
return true;
return EventResult::Handled;
}
// https://html.spec.whatwg.org/multipage/dnd.html#fire-a-dnd-event

View file

@ -10,6 +10,7 @@
#include <LibJS/Heap/GCPtr.h>
#include <LibWeb/Forward.h>
#include <LibWeb/HTML/DragDataStore.h>
#include <LibWeb/Page/EventResult.h>
#include <LibWeb/PixelUnits.h>
namespace Web {
@ -20,17 +21,17 @@ public:
bool has_ongoing_drag_and_drop_operation() const { return !m_drag_data_store.is_null(); }
bool handle_drag_start(JS::Realm&, CSSPixelPoint screen_position, CSSPixelPoint page_offset, CSSPixelPoint client_offset, CSSPixelPoint offset, unsigned button, unsigned buttons, unsigned modifiers, Vector<HTML::SelectedFile> files);
bool handle_drag_move(JS::Realm&, JS::NonnullGCPtr<DOM::Document>, JS::NonnullGCPtr<DOM::Node>, CSSPixelPoint screen_position, CSSPixelPoint page_offset, CSSPixelPoint client_offset, CSSPixelPoint offset, unsigned button, unsigned buttons, unsigned modifiers);
bool handle_drag_leave(JS::Realm&, CSSPixelPoint screen_position, CSSPixelPoint page_offset, CSSPixelPoint client_offset, CSSPixelPoint offset, unsigned button, unsigned buttons, unsigned modifiers);
bool handle_drop(JS::Realm&, CSSPixelPoint screen_position, CSSPixelPoint page_offset, CSSPixelPoint client_offset, CSSPixelPoint offset, unsigned button, unsigned buttons, unsigned modifiers);
EventResult handle_drag_start(JS::Realm&, CSSPixelPoint screen_position, CSSPixelPoint page_offset, CSSPixelPoint client_offset, CSSPixelPoint offset, unsigned button, unsigned buttons, unsigned modifiers, Vector<HTML::SelectedFile> files);
EventResult handle_drag_move(JS::Realm&, JS::NonnullGCPtr<DOM::Document>, JS::NonnullGCPtr<DOM::Node>, CSSPixelPoint screen_position, CSSPixelPoint page_offset, CSSPixelPoint client_offset, CSSPixelPoint offset, unsigned button, unsigned buttons, unsigned modifiers);
EventResult handle_drag_leave(JS::Realm&, CSSPixelPoint screen_position, CSSPixelPoint page_offset, CSSPixelPoint client_offset, CSSPixelPoint offset, unsigned button, unsigned buttons, unsigned modifiers);
EventResult handle_drop(JS::Realm&, CSSPixelPoint screen_position, CSSPixelPoint page_offset, CSSPixelPoint client_offset, CSSPixelPoint offset, unsigned button, unsigned buttons, unsigned modifiers);
private:
enum class Cancelled {
No,
Yes,
};
bool handle_drag_end(JS::Realm&, Cancelled, CSSPixelPoint screen_position, CSSPixelPoint page_offset, CSSPixelPoint client_offset, CSSPixelPoint offset, unsigned button, unsigned buttons, unsigned modifiers);
EventResult handle_drag_end(JS::Realm&, Cancelled, CSSPixelPoint screen_position, CSSPixelPoint page_offset, CSSPixelPoint client_offset, CSSPixelPoint offset, unsigned button, unsigned buttons, unsigned modifiers);
JS::NonnullGCPtr<HTML::DragEvent> fire_a_drag_and_drop_event(
JS::Realm&,

View file

@ -165,27 +165,27 @@ Painting::PaintableBox const* EventHandler::paint_root() const
return m_navigable->active_document()->paintable_box();
}
bool EventHandler::handle_mousewheel(CSSPixelPoint viewport_position, CSSPixelPoint screen_position, u32 button, u32 buttons, u32 modifiers, int wheel_delta_x, int wheel_delta_y)
EventResult EventHandler::handle_mousewheel(CSSPixelPoint viewport_position, CSSPixelPoint screen_position, u32 button, u32 buttons, u32 modifiers, int wheel_delta_x, int wheel_delta_y)
{
if (should_ignore_device_input_event())
return false;
return EventResult::Dropped;
if (!m_navigable->active_document())
return false;
return EventResult::Dropped;
if (!m_navigable->active_document()->is_fully_active())
return false;
return EventResult::Dropped;
auto position = viewport_position;
m_navigable->active_document()->update_layout();
if (!paint_root())
return false;
return EventResult::Dropped;
if (modifiers & UIEvents::KeyModifier::Mod_Shift)
swap(wheel_delta_x, wheel_delta_y);
bool handled_event = false;
auto handled_event = EventResult::Dropped;
JS::GCPtr<Painting::Paintable> paintable;
if (auto result = target_for_mouse_position(position); result.has_value())
@ -196,12 +196,13 @@ bool EventHandler::handle_mousewheel(CSSPixelPoint viewport_position, CSSPixelPo
while (containing_block) {
auto handled_scroll_event = containing_block->handle_mousewheel({}, position, buttons, modifiers, wheel_delta_x, wheel_delta_y);
if (handled_scroll_event)
return true;
return EventResult::Handled;
containing_block = containing_block->containing_block();
}
if (paintable->handle_mousewheel({}, position, buttons, modifiers, wheel_delta_x, wheel_delta_y))
return true;
return EventResult::Handled;
auto node = dom_node_for_event_dispatch(*paintable);
@ -211,13 +212,13 @@ bool EventHandler::handle_mousewheel(CSSPixelPoint viewport_position, CSSPixelPo
auto& iframe = static_cast<HTML::HTMLIFrameElement&>(*node);
auto position_in_iframe = position.translated(compute_mouse_event_offset({}, paintable->layout_node()));
iframe.content_navigable()->event_handler().handle_mousewheel(position_in_iframe, screen_position, button, buttons, modifiers, wheel_delta_x, wheel_delta_y);
return false;
return EventResult::Dropped;
}
// Search for the first parent of the hit target that's an element.
Layout::Node* layout_node;
if (!parent_element_for_event_dispatch(*paintable, node, layout_node))
return false;
return EventResult::Dropped;
auto offset = compute_mouse_event_offset(position, *layout_node);
auto client_offset = compute_mouse_event_client_offset(position);
@ -226,31 +227,29 @@ bool EventHandler::handle_mousewheel(CSSPixelPoint viewport_position, CSSPixelPo
m_navigable->active_window()->scroll_by(wheel_delta_x, wheel_delta_y);
}
handled_event = true;
handled_event = EventResult::Handled;
}
}
return handled_event;
}
bool EventHandler::handle_mouseup(CSSPixelPoint viewport_position, CSSPixelPoint screen_position, u32 button, u32 buttons, u32 modifiers)
EventResult EventHandler::handle_mouseup(CSSPixelPoint viewport_position, CSSPixelPoint screen_position, u32 button, u32 buttons, u32 modifiers)
{
if (should_ignore_device_input_event())
return false;
return EventResult::Dropped;
if (!m_navigable->active_document())
return false;
return EventResult::Dropped;
if (!m_navigable->active_document()->is_fully_active())
return false;
return EventResult::Dropped;
auto position = viewport_position;
m_navigable->active_document()->update_layout();
if (!paint_root())
return false;
bool handled_event = false;
return EventResult::Dropped;
JS::GCPtr<Painting::Paintable> paintable;
if (auto result = target_for_mouse_position(position); result.has_value())
@ -258,15 +257,18 @@ bool EventHandler::handle_mouseup(CSSPixelPoint viewport_position, CSSPixelPoint
if (paintable && paintable->wants_mouse_events()) {
if (paintable->handle_mouseup({}, position, button, modifiers) == Painting::Paintable::DispatchEventOfSameName::No)
return false;
return EventResult::Cancelled;
// Things may have changed as a consequence of Layout::Node::handle_mouseup(). Hit test again.
if (!paint_root())
return true;
return EventResult::Handled;
if (auto result = paint_root()->hit_test(position, Painting::HitTestType::Exact); result.has_value())
paintable = result->paintable;
}
auto handled_event = EventResult::Dropped;
if (paintable) {
auto node = dom_node_for_event_dispatch(*paintable);
@ -274,7 +276,7 @@ bool EventHandler::handle_mouseup(CSSPixelPoint viewport_position, CSSPixelPoint
if (is<HTML::HTMLIFrameElement>(*node)) {
if (auto content_navigable = static_cast<HTML::HTMLIFrameElement&>(*node).content_navigable())
return content_navigable->event_handler().handle_mouseup(position.translated(compute_mouse_event_offset({}, paintable->layout_node())), screen_position, button, buttons, modifiers);
return false;
return EventResult::Dropped;
}
// Search for the first parent of the hit target that's an element.
@ -290,7 +292,7 @@ bool EventHandler::handle_mouseup(CSSPixelPoint viewport_position, CSSPixelPoint
auto client_offset = compute_mouse_event_client_offset(position);
auto page_offset = compute_mouse_event_page_offset(client_offset);
node->dispatch_event(UIEvents::MouseEvent::create_from_platform_event(node->realm(), UIEvents::EventNames::mouseup, screen_position, page_offset, client_offset, offset, {}, button, buttons, modifiers).release_value_but_fixme_should_propagate_errors());
handled_event = true;
handled_event = EventResult::Handled;
bool run_activation_behavior = false;
if (node.ptr() == m_mousedown_target) {
@ -364,22 +366,22 @@ after_node_use:
return handled_event;
}
bool EventHandler::handle_mousedown(CSSPixelPoint viewport_position, CSSPixelPoint screen_position, u32 button, u32 buttons, u32 modifiers)
EventResult EventHandler::handle_mousedown(CSSPixelPoint viewport_position, CSSPixelPoint screen_position, u32 button, u32 buttons, u32 modifiers)
{
if (should_ignore_device_input_event())
return false;
return EventResult::Dropped;
if (!m_navigable->active_document())
return false;
return EventResult::Dropped;
if (!m_navigable->active_document()->is_fully_active())
return false;
return EventResult::Dropped;
auto position = viewport_position;
m_navigable->active_document()->update_layout();
if (!paint_root())
return false;
return EventResult::Dropped;
JS::NonnullGCPtr<DOM::Document> document = *m_navigable->active_document();
JS::GCPtr<DOM::Node> node;
@ -389,7 +391,7 @@ bool EventHandler::handle_mousedown(CSSPixelPoint viewport_position, CSSPixelPoi
if (auto result = target_for_mouse_position(position); result.has_value())
paintable = result->paintable;
else
return false;
return EventResult::Dropped;
auto pointer_events = paintable->computed_values().pointer_events();
// FIXME: Handle other values for pointer-events.
@ -400,16 +402,16 @@ bool EventHandler::handle_mousedown(CSSPixelPoint viewport_position, CSSPixelPoi
if (paintable->wants_mouse_events()) {
if (paintable->handle_mousedown({}, position, button, modifiers) == Painting::Paintable::DispatchEventOfSameName::No)
return false;
return EventResult::Cancelled;
}
if (!node)
return false;
return EventResult::Dropped;
if (is<HTML::HTMLIFrameElement>(*node)) {
if (auto content_navigable = static_cast<HTML::HTMLIFrameElement&>(*node).content_navigable())
return content_navigable->event_handler().handle_mousedown(position.translated(compute_mouse_event_offset({}, paintable->layout_node())), screen_position, button, buttons, modifiers);
return false;
return EventResult::Dropped;
}
m_navigable->page().set_focused_navigable({}, m_navigable);
@ -419,7 +421,7 @@ bool EventHandler::handle_mousedown(CSSPixelPoint viewport_position, CSSPixelPoi
// "The topmost event target MUST be the element highest in the rendering order which is capable of being an event target." (https://www.w3.org/TR/uievents/#topmost-event-target)
Layout::Node* layout_node;
if (!parent_element_for_event_dispatch(*paintable, node, layout_node))
return false;
return EventResult::Dropped;
m_mousedown_target = node.ptr();
auto offset = compute_mouse_event_offset(position, *layout_node);
@ -430,7 +432,7 @@ bool EventHandler::handle_mousedown(CSSPixelPoint viewport_position, CSSPixelPoi
// NOTE: Dispatching an event may have disturbed the world.
if (!paint_root() || paint_root() != node->document().paintable_box())
return true;
return EventResult::Accepted;
if (button == UIEvents::MouseButton::Primary) {
if (auto result = paint_root()->hit_test(position, Painting::HitTestType::TextCursor); result.has_value()) {
@ -472,25 +474,26 @@ bool EventHandler::handle_mousedown(CSSPixelPoint viewport_position, CSSPixelPoi
}
}
}
return true;
return EventResult::Handled;
}
bool EventHandler::handle_mousemove(CSSPixelPoint viewport_position, CSSPixelPoint screen_position, u32 buttons, u32 modifiers)
EventResult EventHandler::handle_mousemove(CSSPixelPoint viewport_position, CSSPixelPoint screen_position, u32 buttons, u32 modifiers)
{
if (should_ignore_device_input_event())
return false;
return EventResult::Dropped;
if (!m_navigable->active_document())
return false;
return EventResult::Dropped;
if (!m_navigable->active_document()->is_fully_active())
return false;
return EventResult::Dropped;
auto position = viewport_position;
m_navigable->active_document()->update_layout();
if (!paint_root())
return false;
return EventResult::Dropped;
auto& document = *m_navigable->active_document();
auto& realm = document.realm();
@ -512,7 +515,7 @@ bool EventHandler::handle_mousemove(CSSPixelPoint viewport_position, CSSPixelPoi
if (paintable->wants_mouse_events()) {
document.set_hovered_node(paintable->dom_node());
if (paintable->handle_mousemove({}, position, buttons, modifiers) == Painting::Paintable::DispatchEventOfSameName::No)
return false;
return EventResult::Cancelled;
// FIXME: It feels a bit aggressive to always update the cursor like this.
m_navigable->page().client().page_did_request_cursor_change(Gfx::StandardCursor::None);
@ -523,7 +526,7 @@ bool EventHandler::handle_mousemove(CSSPixelPoint viewport_position, CSSPixelPoi
if (node && is<HTML::HTMLIFrameElement>(*node)) {
if (auto content_navigable = static_cast<HTML::HTMLIFrameElement&>(*node).content_navigable())
return content_navigable->event_handler().handle_mousemove(position.translated(compute_mouse_event_offset({}, paintable->layout_node())), screen_position, buttons, modifiers);
return false;
return EventResult::Dropped;
}
auto const cursor = paintable->computed_values().cursor();
@ -564,12 +567,13 @@ bool EventHandler::handle_mousemove(CSSPixelPoint viewport_position, CSSPixelPoi
bool continue_ = node->dispatch_event(UIEvents::MouseEvent::create_from_platform_event(node->realm(), UIEvents::EventNames::mousemove, screen_position, page_offset, client_offset, offset, movement, 1, buttons, modifiers).release_value_but_fixme_should_propagate_errors());
if (!continue_)
return false;
return EventResult::Cancelled;
// NOTE: Dispatching an event may have disturbed the world.
if (!paint_root() || paint_root() != node->document().paintable_box())
return true;
return EventResult::Accepted;
}
if (m_in_mouse_selection) {
auto hit = paint_root()->hit_test(position, Painting::HitTestType::TextCursor);
auto should_set_cursor_position = true;
@ -610,18 +614,18 @@ bool EventHandler::handle_mousemove(CSSPixelPoint viewport_position, CSSPixelPoi
page.client().page_did_unhover_link();
}
return true;
return EventResult::Handled;
}
bool EventHandler::handle_doubleclick(CSSPixelPoint viewport_position, CSSPixelPoint screen_position, u32 button, u32 buttons, u32 modifiers)
EventResult EventHandler::handle_doubleclick(CSSPixelPoint viewport_position, CSSPixelPoint screen_position, u32 button, u32 buttons, u32 modifiers)
{
if (should_ignore_device_input_event())
return false;
return EventResult::Dropped;
if (!m_navigable->active_document())
return false;
return EventResult::Dropped;
if (!m_navigable->active_document()->is_fully_active())
return false;
return EventResult::Dropped;
auto& document = *m_navigable->active_document();
@ -631,18 +635,18 @@ bool EventHandler::handle_doubleclick(CSSPixelPoint viewport_position, CSSPixelP
document.update_layout();
if (!paint_root())
return false;
return EventResult::Dropped;
JS::GCPtr<Painting::Paintable> paintable;
if (auto result = target_for_mouse_position(position); result.has_value())
paintable = result->paintable;
else
return false;
return EventResult::Dropped;
auto pointer_events = paintable->computed_values().pointer_events();
// FIXME: Handle other values for pointer-events.
if (pointer_events == CSS::PointerEvents::None)
return false;
return EventResult::Cancelled;
auto node = dom_node_for_event_dispatch(*paintable);
@ -651,19 +655,19 @@ bool EventHandler::handle_doubleclick(CSSPixelPoint viewport_position, CSSPixelP
}
if (!node)
return false;
return EventResult::Dropped;
if (is<HTML::HTMLIFrameElement>(*node)) {
if (auto content_navigable = static_cast<HTML::HTMLIFrameElement&>(*node).content_navigable())
return content_navigable->event_handler().handle_doubleclick(position.translated(compute_mouse_event_offset({}, paintable->layout_node())), screen_position, button, buttons, modifiers);
return false;
return EventResult::Dropped;
}
// Search for the first parent of the hit target that's an element.
// "The topmost event target MUST be the element highest in the rendering order which is capable of being an event target." (https://www.w3.org/TR/uievents/#topmost-event-target)
Layout::Node* layout_node;
if (!parent_element_for_event_dispatch(*paintable, node, layout_node))
return false;
return EventResult::Dropped;
auto offset = compute_mouse_event_offset(position, *layout_node);
auto client_offset = compute_mouse_event_client_offset(position);
@ -672,15 +676,15 @@ bool EventHandler::handle_doubleclick(CSSPixelPoint viewport_position, CSSPixelP
// NOTE: Dispatching an event may have disturbed the world.
if (!paint_root() || paint_root() != node->document().paintable_box())
return true;
return EventResult::Accepted;
if (button == UIEvents::MouseButton::Primary) {
if (auto result = paint_root()->hit_test(position, Painting::HitTestType::TextCursor); result.has_value()) {
if (!result->paintable->dom_node())
return true;
return EventResult::Accepted;
if (!is<Painting::TextPaintable>(*result->paintable))
return true;
return EventResult::Accepted;
auto& hit_paintable = static_cast<Painting::TextPaintable const&>(*result->paintable);
auto& hit_dom_node = const_cast<DOM::Text&>(verify_cast<DOM::Text>(*hit_paintable.dom_node()));
@ -701,36 +705,36 @@ bool EventHandler::handle_doubleclick(CSSPixelPoint viewport_position, CSSPixelP
}
}
return true;
return EventResult::Handled;
}
bool EventHandler::handle_drag_and_drop_event(DragEvent::Type type, CSSPixelPoint viewport_position, CSSPixelPoint screen_position, u32 button, u32 buttons, u32 modifiers, Vector<HTML::SelectedFile> files)
EventResult EventHandler::handle_drag_and_drop_event(DragEvent::Type type, CSSPixelPoint viewport_position, CSSPixelPoint screen_position, u32 button, u32 buttons, u32 modifiers, Vector<HTML::SelectedFile> files)
{
if (!m_navigable->active_document())
return false;
return EventResult::Dropped;
if (!m_navigable->active_document()->is_fully_active())
return false;
return EventResult::Dropped;
auto& document = *m_navigable->active_document();
document.update_layout();
if (!paint_root())
return false;
return EventResult::Dropped;
JS::GCPtr<Painting::Paintable> paintable;
if (auto result = target_for_mouse_position(viewport_position); result.has_value())
paintable = result->paintable;
else
return false;
return EventResult::Dropped;
auto node = dom_node_for_event_dispatch(*paintable);
if (!node)
return false;
return EventResult::Dropped;
if (is<HTML::HTMLIFrameElement>(*node)) {
if (auto content_navigable = static_cast<HTML::HTMLIFrameElement&>(*node).content_navigable())
return content_navigable->event_handler().handle_drag_and_drop_event(type, viewport_position.translated(compute_mouse_event_offset({}, paintable->layout_node())), screen_position, button, buttons, modifiers, move(files));
return false;
return EventResult::Dropped;
}
auto offset = compute_mouse_event_offset(viewport_position, paintable->layout_node());
@ -806,13 +810,13 @@ constexpr bool should_ignore_keydown_event(u32 code_point, u32 modifiers)
return code_point == 0 || code_point == 27;
}
bool EventHandler::fire_keyboard_event(FlyString const& event_name, HTML::Navigable& navigable, UIEvents::KeyCode key, u32 modifiers, u32 code_point)
EventResult EventHandler::fire_keyboard_event(FlyString const& event_name, HTML::Navigable& navigable, UIEvents::KeyCode key, u32 modifiers, u32 code_point)
{
JS::GCPtr<DOM::Document> document = navigable.active_document();
if (!document)
return false;
return EventResult::Dropped;
if (!document->is_fully_active())
return false;
return EventResult::Dropped;
if (JS::GCPtr<DOM::Element> focused_element = document->focused_element()) {
if (is<HTML::NavigableContainer>(*focused_element)) {
@ -822,33 +826,31 @@ bool EventHandler::fire_keyboard_event(FlyString const& event_name, HTML::Naviga
}
auto event = UIEvents::KeyboardEvent::create_from_platform_event(document->realm(), event_name, key, modifiers, code_point);
return focused_element->dispatch_event(event);
return focused_element->dispatch_event(event) ? EventResult::Accepted : EventResult::Cancelled;
}
// FIXME: De-duplicate this. This is just to prevent wasting a KeyboardEvent allocation when recursing into an (i)frame.
auto event = UIEvents::KeyboardEvent::create_from_platform_event(document->realm(), event_name, key, modifiers, code_point);
if (JS::GCPtr<HTML::HTMLElement> body = document->body())
return body->dispatch_event(event);
return document->root().dispatch_event(event);
JS::GCPtr target = document->body() ?: &document->root();
return target->dispatch_event(event) ? EventResult::Accepted : EventResult::Cancelled;
}
bool EventHandler::handle_keydown(UIEvents::KeyCode key, u32 modifiers, u32 code_point)
EventResult EventHandler::handle_keydown(UIEvents::KeyCode key, u32 modifiers, u32 code_point)
{
if (!m_navigable->active_document())
return false;
return EventResult::Dropped;
if (!m_navigable->active_document()->is_fully_active())
return false;
return EventResult::Dropped;
JS::NonnullGCPtr<DOM::Document> document = *m_navigable->active_document();
if (!document->layout_node())
return false;
return EventResult::Dropped;
if (key == UIEvents::KeyCode::Key_Tab) {
if (modifiers & UIEvents::KeyModifier::Mod_Shift)
return focus_previous_element();
return focus_next_element();
return focus_previous_element() ? EventResult::Handled : EventResult::Dropped;
return focus_next_element() ? EventResult::Handled : EventResult::Dropped;
}
// https://html.spec.whatwg.org/multipage/interaction.html#close-requests
@ -858,7 +860,7 @@ bool EventHandler::handle_keydown(UIEvents::KeyCode key, u32 modifiers, u32 code
// 8. If closedSomething is true, then return.
if (closed_something)
return true;
return EventResult::Handled;
// 9. Alternative processing: Otherwise, there was nothing watching for a close request. The user agent may
// instead interpret this interaction as some other action, instead of interpreting it as a close request.
@ -886,27 +888,28 @@ bool EventHandler::handle_keydown(UIEvents::KeyCode key, u32 modifiers, u32 code
if (key == UIEvents::KeyCode::Key_Backspace || key == UIEvents::KeyCode::Key_Delete) {
clear_selection();
m_edit_event_handler->handle_delete(document, *range);
return true;
return EventResult::Handled;
}
// FIXME: Text editing shortcut keys (copy/paste etc.) should be handled here.
if (!should_ignore_keydown_event(code_point, modifiers)) {
clear_selection();
m_edit_event_handler->handle_delete(document, *range);
m_edit_event_handler->handle_insert(document, JS::NonnullGCPtr { *document->cursor_position() }, code_point);
document->increment_cursor_position_offset();
return true;
return EventResult::Handled;
}
}
if (auto* element = m_navigable->active_document()->focused_element(); is<HTML::HTMLMediaElement>(element)) {
auto& media_element = static_cast<HTML::HTMLMediaElement&>(*element);
if (media_element.handle_keydown({}, key, modifiers).release_value_but_fixme_should_propagate_errors())
return true;
return EventResult::Handled;
}
bool continue_ = fire_keyboard_event(UIEvents::EventNames::keydown, m_navigable, key, modifiers, code_point);
if (!continue_)
return false;
auto dispatch_result = fire_keyboard_event(UIEvents::EventNames::keydown, m_navigable, key, modifiers, code_point);
if (dispatch_result != EventResult::Accepted)
return dispatch_result;
if (document->cursor_position()) {
auto& node = *document->cursor_position()->node();
@ -914,20 +917,21 @@ bool EventHandler::handle_keydown(UIEvents::KeyCode key, u32 modifiers, u32 code
if (key == UIEvents::KeyCode::Key_Backspace && node.is_editable()) {
if (!document->decrement_cursor_position_offset()) {
// FIXME: Move to the previous node and delete the last character there.
return true;
return EventResult::Handled;
}
m_edit_event_handler->handle_delete_character_after(document, *document->cursor_position());
return true;
return EventResult::Handled;
}
if (key == UIEvents::KeyCode::Key_Delete && node.is_editable()) {
if (document->cursor_position()->offset_is_at_end_of_node()) {
// FIXME: Move to the next node and delete the first character there.
return true;
return EventResult::Handled;
}
m_edit_event_handler->handle_delete_character_after(document, *document->cursor_position());
return true;
return EventResult::Handled;
}
#if defined(AK_OS_MACOS)
@ -977,7 +981,7 @@ bool EventHandler::handle_keydown(UIEvents::KeyCode key, u32 modifiers, u32 code
}
}
return true;
return EventResult::Handled;
}
if (key == UIEvents::KeyCode::Key_Home || key == UIEvents::KeyCode::Key_End) {
@ -997,7 +1001,7 @@ bool EventHandler::handle_keydown(UIEvents::KeyCode key, u32 modifiers, u32 code
}
document->set_cursor_position(DOM::Position::create(realm, node, cursor_edge));
return true;
return EventResult::Handled;
}
if (key == UIEvents::KeyCode::Key_Return && node.is_editable()) {
@ -1014,11 +1018,11 @@ bool EventHandler::handle_keydown(UIEvents::KeyCode key, u32 modifiers, u32 code
if (input_element) {
if (auto* form = input_element->form()) {
form->implicitly_submit_form().release_value_but_fixme_should_propagate_errors();
return true;
return EventResult::Handled;
}
input_element->commit_pending_changes();
return true;
return EventResult::Handled;
}
}
@ -1026,7 +1030,7 @@ bool EventHandler::handle_keydown(UIEvents::KeyCode key, u32 modifiers, u32 code
if (!should_ignore_keydown_event(code_point, modifiers) && node.is_editable()) {
m_edit_event_handler->handle_insert(document, JS::NonnullGCPtr { *document->cursor_position() }, code_point);
document->increment_cursor_position_offset();
return true;
return EventResult::Handled;
}
}
@ -1045,7 +1049,7 @@ bool EventHandler::handle_keydown(UIEvents::KeyCode key, u32 modifiers, u32 code
key == UIEvents::KeyCode::Key_Up ? document->scroll_to_the_beginning_of_the_document() : document->window()->scroll_by(0, INT64_MAX);
else
document->window()->scroll_by(0, key == UIEvents::KeyCode::Key_Up ? -arrow_key_scroll_distance : arrow_key_scroll_distance);
return true;
return EventResult::Handled;
case UIEvents::KeyCode::Key_Left:
case UIEvents::KeyCode::Key_Right:
if (modifiers > UIEvents::KeyModifier::Mod_Alt && modifiers != (UIEvents::KeyModifier::Mod_Alt | UIEvents::KeyModifier::Mod_AltGr))
@ -1054,30 +1058,30 @@ bool EventHandler::handle_keydown(UIEvents::KeyCode key, u32 modifiers, u32 code
document->page().traverse_the_history_by_delta(key == UIEvents::KeyCode::Key_Left ? -1 : 1);
else
document->window()->scroll_by(key == UIEvents::KeyCode::Key_Left ? -arrow_key_scroll_distance : arrow_key_scroll_distance, 0);
return true;
return EventResult::Handled;
case UIEvents::KeyCode::Key_PageUp:
case UIEvents::KeyCode::Key_PageDown:
if (modifiers > UIEvents::KeyModifier::Mod_None)
break;
document->window()->scroll_by(0, key == UIEvents::KeyCode::Key_PageUp ? -page_scroll_distance : page_scroll_distance);
return true;
return EventResult::Handled;
case UIEvents::KeyCode::Key_Home:
document->scroll_to_the_beginning_of_the_document();
return true;
return EventResult::Handled;
case UIEvents::KeyCode::Key_End:
document->window()->scroll_by(0, INT64_MAX);
return true;
return EventResult::Handled;
default:
break;
}
// FIXME: Work out and implement the difference between this and keydown.
return !fire_keyboard_event(UIEvents::EventNames::keypress, m_navigable, key, modifiers, code_point);
return fire_keyboard_event(UIEvents::EventNames::keypress, m_navigable, key, modifiers, code_point);
}
bool EventHandler::handle_keyup(UIEvents::KeyCode key, u32 modifiers, u32 code_point)
EventResult EventHandler::handle_keyup(UIEvents::KeyCode key, u32 modifiers, u32 code_point)
{
return !fire_keyboard_event(UIEvents::EventNames::keyup, m_navigable, key, modifiers, code_point);
return fire_keyboard_event(UIEvents::EventNames::keyup, m_navigable, key, modifiers, code_point);
}
void EventHandler::handle_paste(String const& text)

View file

@ -14,6 +14,7 @@
#include <LibJS/Heap/GCPtr.h>
#include <LibUnicode/Forward.h>
#include <LibWeb/Forward.h>
#include <LibWeb/Page/EventResult.h>
#include <LibWeb/Page/InputEvent.h>
#include <LibWeb/PixelUnits.h>
#include <LibWeb/UIEvents/KeyCode.h>
@ -25,16 +26,16 @@ public:
explicit EventHandler(Badge<HTML::Navigable>, HTML::Navigable&);
~EventHandler();
bool handle_mouseup(CSSPixelPoint, CSSPixelPoint screen_position, unsigned button, unsigned buttons, unsigned modifiers);
bool handle_mousedown(CSSPixelPoint, CSSPixelPoint screen_position, unsigned button, unsigned buttons, unsigned modifiers);
bool handle_mousemove(CSSPixelPoint, CSSPixelPoint screen_position, unsigned buttons, unsigned modifiers);
bool handle_mousewheel(CSSPixelPoint, CSSPixelPoint screen_position, unsigned button, unsigned buttons, unsigned modifiers, int wheel_delta_x, int wheel_delta_y);
bool handle_doubleclick(CSSPixelPoint, CSSPixelPoint screen_position, unsigned button, unsigned buttons, unsigned modifiers);
EventResult handle_mouseup(CSSPixelPoint, CSSPixelPoint screen_position, unsigned button, unsigned buttons, unsigned modifiers);
EventResult handle_mousedown(CSSPixelPoint, CSSPixelPoint screen_position, unsigned button, unsigned buttons, unsigned modifiers);
EventResult handle_mousemove(CSSPixelPoint, CSSPixelPoint screen_position, unsigned buttons, unsigned modifiers);
EventResult handle_mousewheel(CSSPixelPoint, CSSPixelPoint screen_position, unsigned button, unsigned buttons, unsigned modifiers, int wheel_delta_x, int wheel_delta_y);
EventResult handle_doubleclick(CSSPixelPoint, CSSPixelPoint screen_position, unsigned button, unsigned buttons, unsigned modifiers);
bool handle_drag_and_drop_event(DragEvent::Type, CSSPixelPoint, CSSPixelPoint screen_position, unsigned button, unsigned buttons, unsigned modifiers, Vector<HTML::SelectedFile> files);
EventResult handle_drag_and_drop_event(DragEvent::Type, CSSPixelPoint, CSSPixelPoint screen_position, unsigned button, unsigned buttons, unsigned modifiers, Vector<HTML::SelectedFile> files);
bool handle_keydown(UIEvents::KeyCode, unsigned modifiers, u32 code_point);
bool handle_keyup(UIEvents::KeyCode, unsigned modifiers, u32 code_point);
EventResult handle_keydown(UIEvents::KeyCode, unsigned modifiers, u32 code_point);
EventResult handle_keyup(UIEvents::KeyCode, unsigned modifiers, u32 code_point);
void set_mouse_event_tracking_paintable(Painting::Paintable*);
@ -48,7 +49,7 @@ private:
bool focus_next_element();
bool focus_previous_element();
bool fire_keyboard_event(FlyString const& event_name, HTML::Navigable&, UIEvents::KeyCode, unsigned modifiers, u32 code_point);
EventResult fire_keyboard_event(FlyString const& event_name, HTML::Navigable&, UIEvents::KeyCode, unsigned modifiers, u32 code_point);
CSSPixelPoint compute_mouse_event_client_offset(CSSPixelPoint event_page_position) const;
CSSPixelPoint compute_mouse_event_page_offset(CSSPixelPoint event_client_offset) const;
CSSPixelPoint compute_mouse_event_movement(CSSPixelPoint event_client_offset) const;

View file

@ -0,0 +1,28 @@
/*
* Copyright (c) 2024, Tim Flynn <trflynn89@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
namespace Web {
enum class EventResult {
// The event is allowed to continue. It was not cancelled by the page, nor handled explicitly by the WebContent
// process. The UI process is allowed to further process the event.
Accepted,
// The event was accepted, and was handled explicitly by the WebContent process. The UI process should not further
// process the event.
Handled,
// The event was not accepted by the WebContent process (e.g. because the document is no longer active, or a
// drag-and-drop is active).
Dropped,
// The event was cancelled by the page (e.g. by way of e.preventDefault()).
Cancelled,
};
}

View file

@ -186,42 +186,42 @@ DevicePixelRect Page::rounded_device_rect(CSSPixelRect rect) const
};
}
bool Page::handle_mouseup(DevicePixelPoint position, DevicePixelPoint screen_position, unsigned button, unsigned buttons, unsigned modifiers)
EventResult Page::handle_mouseup(DevicePixelPoint position, DevicePixelPoint screen_position, unsigned button, unsigned buttons, unsigned modifiers)
{
return top_level_traversable()->event_handler().handle_mouseup(device_to_css_point(position), device_to_css_point(screen_position), button, buttons, modifiers);
}
bool Page::handle_mousedown(DevicePixelPoint position, DevicePixelPoint screen_position, unsigned button, unsigned buttons, unsigned modifiers)
EventResult Page::handle_mousedown(DevicePixelPoint position, DevicePixelPoint screen_position, unsigned button, unsigned buttons, unsigned modifiers)
{
return top_level_traversable()->event_handler().handle_mousedown(device_to_css_point(position), device_to_css_point(screen_position), button, buttons, modifiers);
}
bool Page::handle_mousemove(DevicePixelPoint position, DevicePixelPoint screen_position, unsigned buttons, unsigned modifiers)
EventResult Page::handle_mousemove(DevicePixelPoint position, DevicePixelPoint screen_position, unsigned buttons, unsigned modifiers)
{
return top_level_traversable()->event_handler().handle_mousemove(device_to_css_point(position), device_to_css_point(screen_position), buttons, modifiers);
}
bool Page::handle_mousewheel(DevicePixelPoint position, DevicePixelPoint screen_position, unsigned button, unsigned buttons, unsigned modifiers, DevicePixels wheel_delta_x, DevicePixels wheel_delta_y)
EventResult Page::handle_mousewheel(DevicePixelPoint position, DevicePixelPoint screen_position, unsigned button, unsigned buttons, unsigned modifiers, DevicePixels wheel_delta_x, DevicePixels wheel_delta_y)
{
return top_level_traversable()->event_handler().handle_mousewheel(device_to_css_point(position), device_to_css_point(screen_position), button, buttons, modifiers, wheel_delta_x.value(), wheel_delta_y.value());
}
bool Page::handle_doubleclick(DevicePixelPoint position, DevicePixelPoint screen_position, unsigned button, unsigned buttons, unsigned modifiers)
EventResult Page::handle_doubleclick(DevicePixelPoint position, DevicePixelPoint screen_position, unsigned button, unsigned buttons, unsigned modifiers)
{
return top_level_traversable()->event_handler().handle_doubleclick(device_to_css_point(position), device_to_css_point(screen_position), button, buttons, modifiers);
}
bool Page::handle_drag_and_drop_event(DragEvent::Type type, DevicePixelPoint position, DevicePixelPoint screen_position, unsigned button, unsigned buttons, unsigned modifiers, Vector<HTML::SelectedFile> files)
EventResult Page::handle_drag_and_drop_event(DragEvent::Type type, DevicePixelPoint position, DevicePixelPoint screen_position, unsigned button, unsigned buttons, unsigned modifiers, Vector<HTML::SelectedFile> files)
{
return top_level_traversable()->event_handler().handle_drag_and_drop_event(type, device_to_css_point(position), device_to_css_point(screen_position), button, buttons, modifiers, move(files));
}
bool Page::handle_keydown(UIEvents::KeyCode key, unsigned modifiers, u32 code_point)
EventResult Page::handle_keydown(UIEvents::KeyCode key, unsigned modifiers, u32 code_point)
{
return focused_navigable().event_handler().handle_keydown(key, modifiers, code_point);
}
bool Page::handle_keyup(UIEvents::KeyCode key, unsigned modifiers, u32 code_point)
EventResult Page::handle_keyup(UIEvents::KeyCode key, unsigned modifiers, u32 code_point)
{
return focused_navigable().event_handler().handle_keyup(key, modifiers, code_point);
}

View file

@ -40,6 +40,7 @@
#include <LibWeb/HTML/TokenizedFeatures.h>
#include <LibWeb/HTML/WebViewHints.h>
#include <LibWeb/Loader/FileRequest.h>
#include <LibWeb/Page/EventResult.h>
#include <LibWeb/Page/InputEvent.h>
#include <LibWeb/PixelUnits.h>
#include <LibWeb/UIEvents/KeyCode.h>
@ -91,16 +92,16 @@ public:
DevicePixelRect enclosing_device_rect(CSSPixelRect) const;
DevicePixelRect rounded_device_rect(CSSPixelRect) const;
bool handle_mouseup(DevicePixelPoint, DevicePixelPoint screen_position, unsigned button, unsigned buttons, unsigned modifiers);
bool handle_mousedown(DevicePixelPoint, DevicePixelPoint screen_position, unsigned button, unsigned buttons, unsigned modifiers);
bool handle_mousemove(DevicePixelPoint, DevicePixelPoint screen_position, unsigned buttons, unsigned modifiers);
bool handle_mousewheel(DevicePixelPoint, DevicePixelPoint screen_position, unsigned button, unsigned buttons, unsigned modifiers, DevicePixels wheel_delta_x, DevicePixels wheel_delta_y);
bool handle_doubleclick(DevicePixelPoint, DevicePixelPoint screen_position, unsigned button, unsigned buttons, unsigned modifiers);
EventResult handle_mouseup(DevicePixelPoint, DevicePixelPoint screen_position, unsigned button, unsigned buttons, unsigned modifiers);
EventResult handle_mousedown(DevicePixelPoint, DevicePixelPoint screen_position, unsigned button, unsigned buttons, unsigned modifiers);
EventResult handle_mousemove(DevicePixelPoint, DevicePixelPoint screen_position, unsigned buttons, unsigned modifiers);
EventResult handle_mousewheel(DevicePixelPoint, DevicePixelPoint screen_position, unsigned button, unsigned buttons, unsigned modifiers, DevicePixels wheel_delta_x, DevicePixels wheel_delta_y);
EventResult handle_doubleclick(DevicePixelPoint, DevicePixelPoint screen_position, unsigned button, unsigned buttons, unsigned modifiers);
bool handle_drag_and_drop_event(DragEvent::Type, DevicePixelPoint, DevicePixelPoint screen_position, unsigned button, unsigned buttons, unsigned modifiers, Vector<HTML::SelectedFile> files);
EventResult handle_drag_and_drop_event(DragEvent::Type, DevicePixelPoint, DevicePixelPoint screen_position, unsigned button, unsigned buttons, unsigned modifiers, Vector<HTML::SelectedFile> files);
bool handle_keydown(UIEvents::KeyCode, unsigned modifiers, u32 code_point);
bool handle_keyup(UIEvents::KeyCode, unsigned modifiers, u32 code_point);
EventResult handle_keydown(UIEvents::KeyCode, unsigned modifiers, u32 code_point);
EventResult handle_keyup(UIEvents::KeyCode, unsigned modifiers, u32 code_point);
Gfx::Palette palette() const;
CSSPixelRect web_exposed_screen_area() const;

View file

@ -147,11 +147,11 @@ void ViewImplementation::enqueue_input_event(Web::InputEvent event)
});
}
void ViewImplementation::did_finish_handling_input_event(Badge<WebContentClient>, bool event_was_accepted)
void ViewImplementation::did_finish_handling_input_event(Badge<WebContentClient>, Web::EventResult event_result)
{
auto event = m_pending_input_events.dequeue();
if (event_was_accepted)
if (event_result == Web::EventResult::Handled)
return;
// Here we handle events that were not consumed or cancelled by the WebContent. Propagate the event back

View file

@ -22,6 +22,7 @@
#include <LibWeb/HTML/ColorPickerUpdateState.h>
#include <LibWeb/HTML/FileFilter.h>
#include <LibWeb/HTML/SelectItem.h>
#include <LibWeb/Page/EventResult.h>
#include <LibWeb/Page/InputEvent.h>
#include <LibWebView/Forward.h>
#include <LibWebView/WebContentClient.h>
@ -61,7 +62,7 @@ public:
float device_pixel_ratio() const { return m_device_pixel_ratio; }
void enqueue_input_event(Web::InputEvent);
void did_finish_handling_input_event(Badge<WebContentClient>, bool event_was_accepted);
void did_finish_handling_input_event(Badge<WebContentClient>, Web::EventResult event_result);
void set_preferred_color_scheme(Web::CSS::PreferredColorScheme);
void set_preferred_contrast(Web::CSS::PreferredContrast);

View file

@ -589,10 +589,10 @@ void WebContentClient::did_request_select_dropdown(u64 page_id, Gfx::IntPoint co
}
}
void WebContentClient::did_finish_handling_input_event(u64 page_id, bool event_was_accepted)
void WebContentClient::did_finish_handling_input_event(u64 page_id, Web::EventResult event_result)
{
if (auto view = view_for_page_id(page_id); view.has_value())
view->did_finish_handling_input_event({}, event_was_accepted);
view->did_finish_handling_input_event({}, event_result);
}
void WebContentClient::did_change_theme_color(u64 page_id, Gfx::Color color)

View file

@ -14,6 +14,7 @@
#include <LibWeb/HTML/FileFilter.h>
#include <LibWeb/HTML/SelectItem.h>
#include <LibWeb/HTML/WebViewHints.h>
#include <LibWeb/Page/EventResult.h>
#include <WebContent/WebContentClientEndpoint.h>
#include <WebContent/WebContentServerEndpoint.h>
@ -105,7 +106,7 @@ private:
virtual void did_request_color_picker(u64 page_id, Color const& current_color) override;
virtual void did_request_file_picker(u64 page_id, Web::HTML::FileFilter const& accepted_file_types, Web::HTML::AllowMultipleFiles) override;
virtual void did_request_select_dropdown(u64 page_id, Gfx::IntPoint content_position, i32 minimum_width, Vector<Web::HTML::SelectItem> const& items) override;
virtual void did_finish_handling_input_event(u64 page_id, bool event_was_accepted) override;
virtual void did_finish_handling_input_event(u64 page_id, Web::EventResult event_result) override;
virtual void did_finish_text_test(u64 page_id) override;
virtual void did_find_in_page(u64 page_id, size_t current_match_index, Optional<size_t> const& total_match_count) override;
virtual void did_change_theme_color(u64 page_id, Gfx::Color color) override;

View file

@ -185,7 +185,7 @@ void ConnectionFromClient::process_next_input_event()
if (!page.has_value())
return;
auto handled = event.event.visit(
auto result = event.event.visit(
[&](Web::KeyEvent const& event) {
switch (event.type) {
case Web::KeyEvent::Type::KeyDown:
@ -214,10 +214,10 @@ void ConnectionFromClient::process_next_input_event()
return page->page().handle_drag_and_drop_event(event.type, event.position, event.screen_position, event.button, event.buttons, event.modifiers, move(event.files));
});
// We have to notify the client about coalesced events, so we do that by saying none of them were handled by the web page->
// We have to notify the client about coalesced events, so we do that by saying none of them were handled by the web page.
for (size_t i = 0; i < event.coalesced_event_count; ++i)
report_finished_handling_input_event(event.page_id, false);
report_finished_handling_input_event(event.page_id, handled);
report_finished_handling_input_event(event.page_id, Web::EventResult::Dropped);
report_finished_handling_input_event(event.page_id, result);
if (!m_input_event_queue.is_empty())
m_input_event_queue_timer->start();
@ -273,9 +273,9 @@ void ConnectionFromClient::enqueue_input_event(QueuedInputEvent event)
m_input_event_queue_timer->start();
}
void ConnectionFromClient::report_finished_handling_input_event(u64 page_id, bool event_was_handled)
void ConnectionFromClient::report_finished_handling_input_event(u64 page_id, Web::EventResult event_result)
{
async_did_finish_handling_input_event(page_id, event_was_handled);
async_did_finish_handling_input_event(page_id, event_result);
}
void ConnectionFromClient::debug_request(u64 page_id, ByteString const& request, ByteString const& argument)

View file

@ -19,6 +19,7 @@
#include <LibWeb/CSS/PreferredMotion.h>
#include <LibWeb/Forward.h>
#include <LibWeb/Loader/FileRequest.h>
#include <LibWeb/Page/EventResult.h>
#include <LibWeb/Page/InputEvent.h>
#include <LibWeb/Platform/Timer.h>
#include <LibWebView/Forward.h>
@ -150,7 +151,7 @@ private:
virtual void system_time_zone_changed() override;
void report_finished_handling_input_event(u64 page_id, bool event_was_handled);
void report_finished_handling_input_event(u64 page_id, Web::EventResult event_was_handled);
NonnullOwnPtr<PageHost> m_page_host;

View file

@ -12,6 +12,7 @@
#include <LibWeb/HTML/SelectedFile.h>
#include <LibWeb/HTML/SelectItem.h>
#include <LibWeb/HTML/WebViewHints.h>
#include <LibWeb/Page/EventResult.h>
#include <LibWeb/Page/Page.h>
#include <LibWebView/Attribute.h>
#include <LibWebView/ProcessHandle.h>
@ -81,7 +82,7 @@ endpoint WebContentClient
did_request_color_picker(u64 page_id, Color current_color) =|
did_request_file_picker(u64 page_id, Web::HTML::FileFilter accepted_file_types, Web::HTML::AllowMultipleFiles allow_multiple_files) =|
did_request_select_dropdown(u64 page_id, Gfx::IntPoint content_position, i32 minimum_width, Vector<Web::HTML::SelectItem> items) =|
did_finish_handling_input_event(u64 page_id, bool event_was_accepted) =|
did_finish_handling_input_event(u64 page_id, Web::EventResult event_result) =|
did_change_theme_color(u64 page_id, Gfx::Color color) =|
did_insert_clipboard_entry(u64 page_id, String data, String presentation_style, String mime_type) =|
did_update_navigation_buttons_state(u64 page_id, bool back_enabled, bool forward_enabled) =|