[Development] QPushButton: drag and drop

Giuseppe D'Angelo giuseppe.dangelo at kdab.com
Sat Jun 4 00:08:13 CEST 2022

On 03/06/2022 23:05, Volker Hilsheimer wrote:
> If we were to deliver a mouseReleaseEvent to the widget that initiated the drag via QDrag::exec after the exec returns, then we handle the mouseReleaseEvent twice.

Why twice? It receives only one?

Note that the infrastructure for sending a release when the drag ends is 
already there:

> https://github.com/qt/qtbase/blob/dev/src/gui/kernel/qsimpledrag.cpp#L125

It's just that in QtWidgets it never reaches the widget, as it gets 
filtered out by QApplicationPrivate::pickMouseReceiver (called by 

Given the blame on that code shows no changes since Nokia times, 
something just tells me that this has never worked properly and people 
started 1) relying on the release to be never received, and/or 2) add 
workarounds for that.

This isn't the only case where Qt event handling is very very 
inconsistent. Leave/Enter events are also extremely unreliable (if a 
widget is shown under the cursor, you may or may not get a enter event. 
Same for a widget moving on its own, moving under or outside the cursor.)

> In the case of the button, it would mean that we emit clicked() if the drag is dropped inside the button. Check the following, which simulates that Qt would do that. Drag from the button, and drop the drag inside the button. The button now emits clicked(). You most certainly don’t want slot connected to that signal to execute in that interaction.

That's kind of an orthogonal story, that is, adding DND support on top 
of a class that already uses mouse interactions isn't always possible. 
But you could say the same for any other event-driven interaction when 
you start messing with the received events. What if tomorrow we add DND 
support to QPushButton itself, with the related logic in the mouse event 
handlers? Then the overrides in the testcase will break (they might 
_re_start DND).

> This is of course a special case, but it shows that we can’t just start delivering MouseButtonRelease events to widgets when a drag operation finishes, because they would suddenly execute mouseReleaseEvent code in a state in which they don’t expect it to.

Yes, I'm not claiming that this should be a fix to cherry-pick back. 
Being likely a 10+ yo behavior, it's dev material only.

> For instance, QAbstractItemView does not expect to get a mouseReleaseEvent when QAbstractItemView::startDrag returns. I didn’t test it, but it start the editor of the item that was dragged, which might crash when that index got removed by the drag!
> Widgets that support drag’n’drop need to reset their state when QDrag::exec returns, and must be able to rely that they don’t get a mouseReleaseEvent when that mouse release already was processed by the drag’n’drop system to end the drag.

But this simply can't be done reliably in general, as you don't 
necessarily have access to that state so you can't reset it. Again, what 
if tomorrow QPushButton starts drawing itself differently depending on 
mouse movements, and wants to see the release to reset its drawing?

My 2 c,
Giuseppe D'Angelo | giuseppe.dangelo at kdab.com | Senior Software Engineer
KDAB (France) S.A.S., a KDAB Group company
Tel. France +33 (0)4 90 84 08 53, http://www.kdab.com
KDAB - The Qt, C++ and OpenGL Experts
-------------- next part --------------
A non-text attachment was scrubbed...
Name: smime.p7s
Type: application/pkcs7-signature
Size: 4244 bytes
Desc: S/MIME Cryptographic Signature
URL: <http://lists.qt-project.org/pipermail/development/attachments/20220604/2e0120ae/attachment-0001.bin>

More information about the Development mailing list