Clear mousedown activation state whenever primary mousedown tracking is reset. Also route local link drag cancellation through the drag-and-drop end path when Escape, viewport leave, or mouseup outside the viewport ends the drag. These paths can otherwise leave drag input suppression active after the user has ended or canceled the drag, or skip the required dragend event for source cleanup. Add an internals mouseLeave primitive and a focused text test. It covers stale :active state, dragend dispatch for cancellations, viewport leave, outside-viewport mouseup, Escape canceling, and later click delivery after each canceled drag.
70 lines
3 KiB
C++
70 lines
3 KiB
C++
/*
|
|
* Copyright (c) 2024-2026, Tim Flynn <trflynn89@serenityos.org>
|
|
*
|
|
* SPDX-License-Identifier: BSD-2-Clause
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include <AK/RefPtr.h>
|
|
#include <LibGC/Ptr.h>
|
|
#include <LibJS/Heap/Cell.h>
|
|
#include <LibWeb/Forward.h>
|
|
#include <LibWeb/HTML/DragDataStore.h>
|
|
#include <LibWeb/Page/EventResult.h>
|
|
#include <LibWeb/PixelUnits.h>
|
|
|
|
namespace Web {
|
|
|
|
class DragAndDropEventHandler {
|
|
public:
|
|
void visit_edges(JS::Cell::Visitor& visitor) const;
|
|
|
|
bool has_ongoing_drag_and_drop_operation() const { return !m_drag_data_store.is_null(); }
|
|
|
|
EventResult handle_drag_start(JS::Realm&, GC::Ptr<DOM::Node> drag_target, 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&, GC::Ref<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_drag_cancel(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);
|
|
|
|
void reset();
|
|
|
|
private:
|
|
enum class Cancelled {
|
|
No,
|
|
Yes,
|
|
};
|
|
EventResult handle_drag_end(JS::Realm&, Cancelled, CSSPixelPoint screen_position, CSSPixelPoint page_offset, CSSPixelPoint client_offset, CSSPixelPoint offset, unsigned button, unsigned buttons, unsigned modifiers);
|
|
|
|
GC::Ref<HTML::DragEvent> fire_a_drag_and_drop_event(
|
|
JS::Realm&,
|
|
GC::Ptr<DOM::EventTarget> target,
|
|
FlyString const& name,
|
|
CSSPixelPoint screen_position,
|
|
CSSPixelPoint page_offset,
|
|
CSSPixelPoint client_offset,
|
|
CSSPixelPoint offset,
|
|
unsigned button,
|
|
unsigned buttons,
|
|
unsigned modifiers,
|
|
GC::Ptr<DOM::EventTarget> related_target = nullptr);
|
|
|
|
bool allow_text_drop(GC::Ref<DOM::Node>) const;
|
|
|
|
RefPtr<HTML::DragDataStore> m_drag_data_store;
|
|
|
|
// https://html.spec.whatwg.org/multipage/dnd.html#source-node
|
|
GC::Ptr<DOM::EventTarget> m_source_node;
|
|
|
|
// https://html.spec.whatwg.org/multipage/dnd.html#immediate-user-selection
|
|
GC::Ptr<DOM::Node> m_immediate_user_selection;
|
|
|
|
// https://html.spec.whatwg.org/multipage/dnd.html#current-target-element
|
|
GC::Ptr<DOM::Node> m_current_target_element;
|
|
|
|
// https://html.spec.whatwg.org/multipage/dnd.html#current-drag-operation
|
|
FlyString m_current_drag_operation;
|
|
};
|
|
|
|
}
|