LibWeb+LibWebView+WebContent: Return a named enum from UI event handlers

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
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

@ -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)