From e4688fedd544e03f732ac8563bb0e10ed441fd64 Mon Sep 17 00:00:00 2001 From: Luke Wilde Date: Sat, 5 Nov 2022 15:36:03 +0000 Subject: [PATCH] LibWeb: Make keyboard events properly fire into a focused iframe Google Docs focuses a "text event target" iframe using Window.focus on the iframe's contentWindow. Doing so makes the iframe's document the focused element we have to fire text events at. However, in the top level browsing context, the focused element is still the iframe, so we have to repeat the keyboard event steps but with the iframe's nested browsing context instead. --- .../Libraries/LibWeb/Page/EventHandler.cpp | 50 +++++++++++-------- Userland/Libraries/LibWeb/Page/EventHandler.h | 2 + 2 files changed, 30 insertions(+), 22 deletions(-) diff --git a/Userland/Libraries/LibWeb/Page/EventHandler.cpp b/Userland/Libraries/LibWeb/Page/EventHandler.cpp index 47343d2cff..6e304be957 100644 --- a/Userland/Libraries/LibWeb/Page/EventHandler.cpp +++ b/Userland/Libraries/LibWeb/Page/EventHandler.cpp @@ -657,6 +657,32 @@ constexpr bool should_ignore_keydown_event(u32 code_point) return code_point == 0 || code_point == 27; } +bool EventHandler::fire_keyboard_event(FlyString const& event_name, HTML::BrowsingContext& browsing_context, KeyCode key, unsigned int modifiers, u32 code_point) +{ + JS::NonnullGCPtr document = *browsing_context.active_document(); + if (!document) + return false; + + if (JS::GCPtr focused_element = document->focused_element()) { + if (is(*focused_element)) { + auto& browsing_context_container = verify_cast(*focused_element); + if (browsing_context_container.nested_browsing_context()) + return fire_keyboard_event(event_name, *browsing_context_container.nested_browsing_context(), key, modifiers, code_point); + } + + auto event = UIEvents::KeyboardEvent::create_from_platform_event(document->realm(), event_name, key, modifiers, code_point); + return focused_element->dispatch_event(*event); + } + + // FIXME: De-duplicate this. This is just to prevent wasting a KeyboardEvent alloction 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 body = document->body()) + return body->dispatch_event(*event); + + return document->root().dispatch_event(*event); +} + bool EventHandler::handle_keydown(KeyCode key, unsigned modifiers, u32 code_point) { if (!m_browsing_context.active_document()) @@ -745,32 +771,12 @@ bool EventHandler::handle_keydown(KeyCode key, unsigned modifiers, u32 code_poin return true; } - auto event = UIEvents::KeyboardEvent::create_from_platform_event(document->realm(), UIEvents::EventNames::keydown, key, modifiers, code_point); - - if (JS::GCPtr focused_element = document->focused_element()) - return focused_element->dispatch_event(*event); - - if (JS::GCPtr body = m_browsing_context.active_document()->body()) - return body->dispatch_event(*event); - - return document->root().dispatch_event(*event); + return fire_keyboard_event(UIEvents::EventNames::keydown, m_browsing_context, key, modifiers, code_point); } bool EventHandler::handle_keyup(KeyCode key, unsigned modifiers, u32 code_point) { - JS::GCPtr document = m_browsing_context.active_document(); - if (!document) - return false; - - auto event = UIEvents::KeyboardEvent::create_from_platform_event(document->realm(), UIEvents::EventNames::keyup, key, modifiers, code_point); - - if (JS::GCPtr focused_element = document->focused_element()) - return document->focused_element()->dispatch_event(*event); - - if (JS::GCPtr body = document->body()) - return body->dispatch_event(*event); - - return document->root().dispatch_event(*event); + return fire_keyboard_event(UIEvents::EventNames::keyup, m_browsing_context, key, modifiers, code_point); } void EventHandler::set_mouse_event_tracking_layout_node(Layout::Node* layout_node) diff --git a/Userland/Libraries/LibWeb/Page/EventHandler.h b/Userland/Libraries/LibWeb/Page/EventHandler.h index fa302c9695..e5ef43c7e6 100644 --- a/Userland/Libraries/LibWeb/Page/EventHandler.h +++ b/Userland/Libraries/LibWeb/Page/EventHandler.h @@ -39,6 +39,8 @@ private: bool focus_next_element(); bool focus_previous_element(); + bool fire_keyboard_event(FlyString const& event_name, HTML::BrowsingContext& browsing_context, KeyCode key, unsigned modifiers, u32 code_point); + Layout::InitialContainingBlock* layout_root(); Layout::InitialContainingBlock const* layout_root() const;