mirror of
https://github.com/SerenityOS/serenity.git
synced 2025-01-23 18:02:05 -05:00
WindowServer+LibGUI: Add a "drag move" event
This allows windows/widgets to learn when something is being dragged over them. They can then repaint themselves somehow to indicate that they are willing to accept a drop. Currently this is piggybacking somewhat on the mouse event mechanism in WindowServer. I'm not sure that's the best design but it seemed easier to do it this way right now.
This commit is contained in:
parent
7590270e13
commit
3ce80bec97
9 changed files with 71 additions and 8 deletions
|
@ -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)
|
||||
|
|
|
@ -26,8 +26,6 @@
|
|||
|
||||
#include <AK/Assertions.h>
|
||||
#include <AK/JsonObject.h>
|
||||
#include <LibGfx/Bitmap.h>
|
||||
#include <LibGfx/Palette.h>
|
||||
#include <LibGUI/Action.h>
|
||||
#include <LibGUI/Application.h>
|
||||
#include <LibGUI/Button.h>
|
||||
|
@ -46,6 +44,8 @@
|
|||
#include <LibGUI/Widget.h>
|
||||
#include <LibGUI/Window.h>
|
||||
#include <LibGUI/WindowServerConnection.h>
|
||||
#include <LibGfx/Bitmap.h>
|
||||
#include <LibGfx/Palette.h>
|
||||
#include <unistd.h>
|
||||
|
||||
namespace GUI {
|
||||
|
@ -182,6 +182,8 @@ void Widget::event(Core::Event& event)
|
|||
return handle_mouseup_event(static_cast<MouseEvent&>(event));
|
||||
case Event::MouseWheel:
|
||||
return mousewheel_event(static_cast<MouseEvent&>(event));
|
||||
case Event::DragMove:
|
||||
return drag_move_event(static_cast<DragEvent&>(event));
|
||||
case Event::Drop:
|
||||
return drop_event(static_cast<DropEvent&>(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() << "'";
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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<WMEvent&>(event));
|
||||
|
||||
if (event.type() == Event::DragMove) {
|
||||
if (!m_main_widget)
|
||||
return;
|
||||
auto& drag_event = static_cast<DragEvent&>(event);
|
||||
auto result = m_main_widget->hit_test(drag_event.position());
|
||||
auto local_event = make<DragEvent>(static_cast<Event::Type>(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);
|
||||
}
|
||||
|
||||
|
|
|
@ -24,8 +24,6 @@
|
|||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <LibGfx/Palette.h>
|
||||
#include <LibGfx/SystemTheme.h>
|
||||
#include <LibGUI/Action.h>
|
||||
#include <LibGUI/Application.h>
|
||||
#include <LibGUI/Clipboard.h>
|
||||
|
@ -36,6 +34,8 @@
|
|||
#include <LibGUI/Widget.h>
|
||||
#include <LibGUI/Window.h>
|
||||
#include <LibGUI/WindowServerConnection.h>
|
||||
#include <LibGfx/Palette.h>
|
||||
#include <LibGfx/SystemTheme.h>
|
||||
|
||||
//#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<MouseEvent>(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<DragEvent>(Event::DragMove, message.mouse_position(), message.drag_data_type()));
|
||||
else
|
||||
Core::EventLoop::current().post_event(*window, make<MouseEvent>(Event::MouseMove, message.mouse_position(), message.buttons(), to_gmousebutton(message.button()), message.modifiers(), message.wheel_delta()));
|
||||
}
|
||||
}
|
||||
|
||||
void WindowServerConnection::handle(const Messages::WindowClient::MouseDoubleClick& message)
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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()));
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
endpoint WindowClient = 4
|
||||
{
|
||||
Paint(i32 window_id, Gfx::Size window_size, Vector<Gfx::Rect> 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) =|
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue