diff --git a/Libraries/LibGUI/Event.h b/Libraries/LibGUI/Event.h index 7b6b472176e..c518a694a1d 100644 --- a/Libraries/LibGUI/Event.h +++ b/Libraries/LibGUI/Event.h @@ -60,6 +60,7 @@ public: WindowCloseRequest, ContextMenu, EnabledChange, + DragMove, Drop, __Begin_WM_Events, @@ -306,6 +307,23 @@ private: int m_wheel_delta { 0 }; }; +class DragEvent final : public Event { +public: + DragEvent(Type type, const Gfx::Point& position, const String& data_type) + : Event(type) + , m_position(position) + , m_data_type(data_type) + { + } + + const Gfx::Point& position() const { return m_position; } + const String& data_type() const { return m_data_type; } + +private: + Gfx::Point m_position; + String m_data_type; +}; + class DropEvent final : public Event { public: DropEvent(const Gfx::Point& position, const String& text, const String& data_type, const String& data) diff --git a/Libraries/LibGUI/Widget.cpp b/Libraries/LibGUI/Widget.cpp index b4b2ccc0842..0997b527731 100644 --- a/Libraries/LibGUI/Widget.cpp +++ b/Libraries/LibGUI/Widget.cpp @@ -26,8 +26,6 @@ #include #include -#include -#include #include #include #include @@ -46,6 +44,8 @@ #include #include #include +#include +#include #include namespace GUI { @@ -182,6 +182,8 @@ void Widget::event(Core::Event& event) return handle_mouseup_event(static_cast(event)); case Event::MouseWheel: return mousewheel_event(static_cast(event)); + case Event::DragMove: + return drag_move_event(static_cast(event)); case Event::Drop: return drop_event(static_cast(event)); case Event::Enter: @@ -379,6 +381,12 @@ void Widget::change_event(Event&) { } +void Widget::drag_move_event(DragEvent& event) +{ + dbg() << class_name() << "{" << this << "} DRAG MOVE position: " << event.position() << ", data_type: '" << event.data_type() << "'"; + event.ignore(); +} + void Widget::drop_event(DropEvent& event) { dbg() << class_name() << "{" << this << "} DROP position: " << event.position() << ", text: '" << event.text() << "'"; diff --git a/Libraries/LibGUI/Widget.h b/Libraries/LibGUI/Widget.h index 9ecb8fe8c13..d294673dcad 100644 --- a/Libraries/LibGUI/Widget.h +++ b/Libraries/LibGUI/Widget.h @@ -303,6 +303,7 @@ protected: virtual void leave_event(Core::Event&); virtual void child_event(Core::ChildEvent&) override; virtual void change_event(Event&); + virtual void drag_move_event(DragEvent&); virtual void drop_event(DropEvent&); private: diff --git a/Libraries/LibGUI/Window.cpp b/Libraries/LibGUI/Window.cpp index c93e9d00e8d..a0b5dc87c2f 100644 --- a/Libraries/LibGUI/Window.cpp +++ b/Libraries/LibGUI/Window.cpp @@ -319,6 +319,16 @@ void Window::event(Core::Event& event) if (event.type() > Event::__Begin_WM_Events && event.type() < Event::__End_WM_Events) return wm_event(static_cast(event)); + if (event.type() == Event::DragMove) { + if (!m_main_widget) + return; + auto& drag_event = static_cast(event); + auto result = m_main_widget->hit_test(drag_event.position()); + auto local_event = make(static_cast(drag_event.type()), result.local_position, drag_event.data_type()); + ASSERT(result.widget); + return result.widget->dispatch_event(*local_event, this); + } + Core::Object::event(event); } diff --git a/Libraries/LibGUI/WindowServerConnection.cpp b/Libraries/LibGUI/WindowServerConnection.cpp index 3ea6a6a5728..bfcc000f2ea 100644 --- a/Libraries/LibGUI/WindowServerConnection.cpp +++ b/Libraries/LibGUI/WindowServerConnection.cpp @@ -24,8 +24,6 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include -#include #include #include #include @@ -36,6 +34,8 @@ #include #include #include +#include +#include //#define GEVENTLOOP_DEBUG @@ -217,8 +217,12 @@ void WindowServerConnection::handle(const Messages::WindowClient::MouseMove& mes dbgprintf("WID=%d MouseMove %d,%d,%d\n", message.window_id(), message.mouse_position().x(), message.mouse_position().y(), message.wheel_delta(); #endif - if (auto* window = Window::from_window_id(message.window_id())) - Core::EventLoop::current().post_event(*window, make(Event::MouseMove, message.mouse_position(), message.buttons(), to_gmousebutton(message.button()), message.modifiers(), message.wheel_delta())); + if (auto* window = Window::from_window_id(message.window_id())) { + if (message.is_drag()) + Core::EventLoop::current().post_event(*window, make(Event::DragMove, message.mouse_position(), message.drag_data_type())); + else + Core::EventLoop::current().post_event(*window, make(Event::MouseMove, message.mouse_position(), message.buttons(), to_gmousebutton(message.button()), message.modifiers(), message.wheel_delta())); + } } void WindowServerConnection::handle(const Messages::WindowClient::MouseDoubleClick& message) diff --git a/Servers/WindowServer/Event.h b/Servers/WindowServer/Event.h index 8b7bd97d13a..781f2df903b 100644 --- a/Servers/WindowServer/Event.h +++ b/Servers/WindowServer/Event.h @@ -117,6 +117,11 @@ public: unsigned buttons() const { return m_buttons; } unsigned modifiers() const { return m_modifiers; } int wheel_delta() const { return m_wheel_delta; } + bool is_drag() const { return m_drag; } + const String& drag_data_type() const { return m_drag_data_type; } + + void set_drag(bool b) { m_drag = b; } + void set_drag_data_type(const String& drag_data_type) { m_drag_data_type = drag_data_type; } MouseEvent translated(const Gfx::Point& delta) const { return MouseEvent((Type)type(), m_position.translated(delta), m_buttons, m_button, m_modifiers, m_wheel_delta); } @@ -126,6 +131,8 @@ private: MouseButton m_button { MouseButton::None }; unsigned m_modifiers { 0 }; int m_wheel_delta { 0 }; + bool m_drag { false }; + String m_drag_data_type; }; class ResizeEvent final : public Event { diff --git a/Servers/WindowServer/Window.cpp b/Servers/WindowServer/Window.cpp index a25cc5aa0c2..a322d72cdd3 100644 --- a/Servers/WindowServer/Window.cpp +++ b/Servers/WindowServer/Window.cpp @@ -114,7 +114,7 @@ void Window::handle_mouse_event(const MouseEvent& event) switch (event.type()) { case Event::MouseMove: - m_client->post_message(Messages::WindowClient::MouseMove(m_window_id, event.position(), (u32)event.button(), event.buttons(), event.modifiers(), event.wheel_delta())); + m_client->post_message(Messages::WindowClient::MouseMove(m_window_id, event.position(), (u32)event.button(), event.buttons(), event.modifiers(), event.wheel_delta(), event.is_drag(), event.drag_data_type())); break; case Event::MouseDown: m_client->post_message(Messages::WindowClient::MouseDown(m_window_id, event.position(), (u32)event.button(), event.buttons(), event.modifiers(), event.wheel_delta())); diff --git a/Servers/WindowServer/WindowClient.ipc b/Servers/WindowServer/WindowClient.ipc index e1b8e8398a0..4e3c077a7d4 100644 --- a/Servers/WindowServer/WindowClient.ipc +++ b/Servers/WindowServer/WindowClient.ipc @@ -1,7 +1,7 @@ endpoint WindowClient = 4 { Paint(i32 window_id, Gfx::Size window_size, Vector rects) =| - MouseMove(i32 window_id, Gfx::Point mouse_position, u32 button, u32 buttons, u32 modifiers, i32 wheel_delta) =| + MouseMove(i32 window_id, Gfx::Point mouse_position, u32 button, u32 buttons, u32 modifiers, i32 wheel_delta, bool is_drag, String drag_data_type) =| MouseDown(i32 window_id, Gfx::Point mouse_position, u32 button, u32 buttons, u32 modifiers, i32 wheel_delta) =| MouseDoubleClick(i32 window_id, Gfx::Point mouse_position, u32 button, u32 buttons, u32 modifiers, i32 wheel_delta) =| MouseUp(i32 window_id, Gfx::Point mouse_position, u32 button, u32 buttons, u32 modifiers, i32 wheel_delta) =| diff --git a/Servers/WindowServer/WindowManager.cpp b/Servers/WindowServer/WindowManager.cpp index 2a7d7383b1e..689cb5734c6 100644 --- a/Servers/WindowServer/WindowManager.cpp +++ b/Servers/WindowServer/WindowManager.cpp @@ -594,6 +594,21 @@ bool WindowManager::process_ongoing_drag(MouseEvent& event, Window*& hovered_win { if (!m_dnd_client) return false; + + if (event.type() == Event::MouseMove) { + // We didn't let go of the drag yet, see if we should send some drag move events.. + for_each_visible_window_from_front_to_back([&](Window& window) { + if (!window.rect().contains(event.position())) + return IterationDecision::Continue; + hovered_window = &window; + auto translated_event = event.translated(-window.position()); + translated_event.set_drag(true); + translated_event.set_drag_data_type(m_dnd_data_type); + deliver_mouse_event(window, translated_event); + return IterationDecision::Break; + }); + } + if (!(event.type() == Event::MouseUp && event.button() == MouseButton::Left)) return true;