Преглед на файлове

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.
Luke Wilde преди 2 години
родител
ревизия
e4688fedd5
променени са 2 файла, в които са добавени 30 реда и са изтрити 22 реда
  1. 28 22
      Userland/Libraries/LibWeb/Page/EventHandler.cpp
  2. 2 0
      Userland/Libraries/LibWeb/Page/EventHandler.h

+ 28 - 22
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;
     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<DOM::Document> document = *browsing_context.active_document();
+    if (!document)
+        return false;
+
+    if (JS::GCPtr<DOM::Element> focused_element = document->focused_element()) {
+        if (is<HTML::BrowsingContextContainer>(*focused_element)) {
+            auto& browsing_context_container = verify_cast<HTML::BrowsingContextContainer>(*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<HTML::HTMLElement> 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)
 bool EventHandler::handle_keydown(KeyCode key, unsigned modifiers, u32 code_point)
 {
 {
     if (!m_browsing_context.active_document())
     if (!m_browsing_context.active_document())
@@ -745,32 +771,12 @@ bool EventHandler::handle_keydown(KeyCode key, unsigned modifiers, u32 code_poin
         return true;
         return true;
     }
     }
 
 
-    auto event = UIEvents::KeyboardEvent::create_from_platform_event(document->realm(), UIEvents::EventNames::keydown, key, modifiers, code_point);
-
-    if (JS::GCPtr<DOM::Element> focused_element = document->focused_element())
-        return focused_element->dispatch_event(*event);
-
-    if (JS::GCPtr<HTML::HTMLElement> 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)
 bool EventHandler::handle_keyup(KeyCode key, unsigned modifiers, u32 code_point)
 {
 {
-    JS::GCPtr<DOM::Document> 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<DOM::Element> focused_element = document->focused_element())
-        return document->focused_element()->dispatch_event(*event);
-
-    if (JS::GCPtr<HTML::HTMLElement> 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)
 void EventHandler::set_mouse_event_tracking_layout_node(Layout::Node* layout_node)

+ 2 - 0
Userland/Libraries/LibWeb/Page/EventHandler.h

@@ -39,6 +39,8 @@ private:
     bool focus_next_element();
     bool focus_next_element();
     bool focus_previous_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* layout_root();
     Layout::InitialContainingBlock const* layout_root() const;
     Layout::InitialContainingBlock const* layout_root() const;