Propagate drop events to ancestors

When a drop event is not handled by a drag & drop enabled widget then
look for the next drag & drop enabled ancestor to propagate the drop
This commit is contained in:
Martín Capello 2024-09-20 14:52:26 -03:00
parent 365bad61d5
commit 96ed89db8a
3 changed files with 17 additions and 9 deletions

View File

@ -4485,6 +4485,12 @@ void Timeline::onDragLeave(ui::DragEvent& e)
void Timeline::onDrag(ui::DragEvent& e)
{
Widget::onDrag(e);
// Dropping images into the timeline is not supported yet, so do nothing.
if (e.hasImage()) {
return;
}
m_range.clearRange();
setHot(hitTest(nullptr, e.position()));
switch (m_hot.part) {
@ -4561,9 +4567,9 @@ void Timeline::onDrop(ui::DragEvent& e)
tx.commit();
m_document->notifyGeneralUpdate();
});
e.handled(true);
}
e.handled(true);
m_state = STATE_STANDBY;
m_range.clearRange();
m_dropRange.clearRange();

View File

@ -2041,9 +2041,8 @@ bool Manager::sendMessageToWidget(Message* msg, Widget* widget)
return used;
}
Widget* Manager::pickForDragAndDrop(const gfx::Point& pt)
Widget* Manager::findForDragAndDrop(Widget* widget)
{
Widget* widget = pick(pt);
// If widget doesn't support drag & drop, try to find the nearest ancestor
// that supports it.
while(widget && !widget->hasFlags(ALLOW_DROP))
@ -2054,7 +2053,7 @@ Widget* Manager::pickForDragAndDrop(const gfx::Point& pt)
void Manager::dragEnter(os::DragEvent& ev)
{
Widget* widget = pickForDragAndDrop(ev.position());
Widget* widget = findForDragAndDrop(pick(ev.position()));
ASSERT(!widget || widget && widget->hasFlags(ALLOW_DROP));
@ -2078,7 +2077,7 @@ void Manager::dragLeave(os::DragEvent& ev)
void Manager::drag(os::DragEvent& ev)
{
Widget* widget = pickForDragAndDrop(ev.position());
Widget* widget = findForDragAndDrop(pick(ev.position()));
ASSERT(!widget || widget && widget->hasFlags(ALLOW_DROP));
@ -2102,17 +2101,20 @@ void Manager::drag(os::DragEvent& ev)
void Manager::drop(os::DragEvent& ev)
{
m_dragOverWidget = nullptr;
Widget* widget = pickForDragAndDrop(ev.position());
Widget* widget = findForDragAndDrop(pick(ev.position()));
ASSERT(!widget || widget && widget->hasFlags(ALLOW_DROP));
if (widget) {
DragEvent uiev(this, widget, ev);
DragEvent uiev(this, widget, ev);
while (widget) {
widget->onDrop(uiev);
if (uiev.handled()) {
ev.acceptDrop(true);
return;
}
// Propagate unhandled drop events to ancestors.
// TODO: Should we propagate dragEnter, dragLeave and drag events too?
widget = findForDragAndDrop(widget->parent());
}
// There were no widget that accepted the drop, then see if we can treat it

View File

@ -163,7 +163,7 @@ namespace ui {
int pumpQueue();
bool sendMessageToWidget(Message* msg, Widget* widget);
Widget* pickForDragAndDrop(const gfx::Point& pt);
Widget* findForDragAndDrop(Widget* widget);
void dragEnter(os::DragEvent& ev) override;
void dragLeave(os::DragEvent& ev) override;
void drag(os::DragEvent& ev) override;