Prechádzať zdrojové kódy

LibWeb: Run the unfocusing steps when a click does not focus anything

For example, when clicking the document body outside of a focused input
element, we should unfocus that element.
Timothy Flynn 1 rok pred
rodič
commit
fd297a3248

+ 2 - 0
Tests/LibWeb/Text/expected/input-click-to-unfocus.txt

@@ -0,0 +1,2 @@
+   focus
+blur

+ 23 - 0
Tests/LibWeb/Text/input/input-click-to-unfocus.html

@@ -0,0 +1,23 @@
+<input id=input type=text>
+<script src="include.js"></script>
+<script>
+    test(() => {
+        let input = document.getElementById("input");
+
+        input.addEventListener("focus", () => {
+            println("focus");
+        });
+
+        input.addEventListener("blur", () => {
+            println("blur");
+        });
+
+        input.focus();
+
+        const rect = input.getBoundingClientRect();
+        const x = rect.x + rect.width;
+        const y = rect.y + rect.height;
+
+        internals.click(x + 10, y + 10);
+    })
+</script>

+ 10 - 0
Userland/Libraries/LibWeb/Internals/Internals.cpp

@@ -84,6 +84,16 @@ void Internals::commit_text()
     page->handle_keydown(Key_Return, 0, 0);
 }
 
+void Internals::click(double x, double y)
+{
+    auto* page = global_object().browsing_context()->page();
+    if (!page)
+        return;
+
+    page->handle_mousedown({ x, y }, { x, y }, 1, 0, 0);
+    page->handle_mouseup({ x, y }, { x, y }, 1, 0, 0);
+}
+
 WebIDL::ExceptionOr<bool> Internals::dispatch_user_activated_event(DOM::EventTarget& target, DOM::Event& event)
 {
     event.set_is_trusted(true);

+ 2 - 0
Userland/Libraries/LibWeb/Internals/Internals.h

@@ -25,6 +25,8 @@ public:
     void send_text(HTML::HTMLElement&, String const&);
     void commit_text();
 
+    void click(double x, double y);
+
     WebIDL::ExceptionOr<bool> dispatch_user_activated_event(DOM::EventTarget&, DOM::Event& event);
 
 private:

+ 2 - 0
Userland/Libraries/LibWeb/Internals/Internals.idl

@@ -10,6 +10,8 @@
     undefined sendText(HTMLElement target, DOMString text);
     undefined commitText();
 
+    undefined click(double x, double y);
+
     boolean dispatchUserActivatedEvent(EventTarget target, Event event);
 
 };

+ 3 - 0
Userland/Libraries/LibWeb/Page/EventHandler.cpp

@@ -409,6 +409,9 @@ bool EventHandler::handle_mousedown(CSSPixelPoint position, CSSPixelPoint screen
                 // If we didn't focus anything, place the document text cursor at the mouse position.
                 // FIXME: This is all rather strange. Find a better solution.
                 if (!did_focus_something) {
+                    if (auto* focused_element = document->focused_element())
+                        HTML::run_unfocusing_steps(focused_element);
+
                     auto& realm = document->realm();
                     m_browsing_context->set_cursor_position(DOM::Position::create(realm, *paintable->dom_node(), result->index_in_node));
                     if (auto selection = document->get_selection()) {