[Development] QPushButton: drag and drop

Giuseppe D'Angelo giuseppe.dangelo at kdab.com
Thu Jun 9 17:54:35 CEST 2022


On 09/06/2022 17:20, Volker Hilsheimer wrote:
> Let’s put things into a perspective here. You are proposing a flag that we perhaps flip on by default within Qt 6, and that might break a whole ton of widgets out there that today correctly implement drag’n’drop and that will start failing in mysterious, and largely untestable (because testing drag’n’drop requires special tools) ways. “Adventurous” indeed :P
> We are having this discussion is because a widget doesn’t get a QEvent::MouseButtonRelease in symmetry with an earlier MouseButtonPress. As I pointed out earlier, a widget also won’t get a symmetrical MouseButtonRelease when a modal dialog opens in response to press; the release gets eaten by the dialog. (And we have bugs with enter/leave like the one Gatis pointed at, which in my mind are orthogonal to this, and is not addressed by any of the proposals made in this thread so far anyway; but those would be good bugs to fix in order to familiar with the complexity of the code involved here).
> You are suggesting that all widgets in Qt, and possibly thousands of custom widget implementations out there, have to start adding special code to their mouseReleaseEvent, ignoring specially flagged events because someone might
> * subclass that widget class and exec() a QDrag or a QDialog in mousePressEvent
> * or connect to a pressed() signal (if that exists) and do the same

I think there's been a misunderstanding: I am 100% *agreeing* with you 
here. Changing this behavior suddenly/blindly is a a big no-no, exactly 
for the reasons you're stating.

Just like you here I was challenging the claim that "well it's a 
behavior change but any fix is a change so let's fix this". This is what 
I said:

> There's behaviour break and behaviour break.
> which is a long way to say "any QWidget subclass handling mouse events 
> needs to be changed". And that's a very high bar for a behavioral change.

^^^ In other words, I'm NOT for start sending mouse release events around.

Trying to be constructive: the most conservative approach would probably 
be a custom event. Not a mouse release with a special source, another 
event altogether, so that existing widgets do not handle it at all, and 
cannot possibly misbehave. (Then QPushButton & friends could be "fixed" 
by handling this event instead.)

Sending a release instead/in addition to a custom event _might_ be 
added, but only behind an opt-in fence (per-widget attribute), which has 
to be opt-in for a very long time, which makes it unpalatable to me 
(niche use case; noone will enable it => lack of testing; already 
covered by the custom event anyways).

> And since the argument is “we must be symmetrical with our events so widgets don’t remain in a pressed state”, we cannot really fix the one (QDrag) and not the other (QDialog). If a widget author cannot be expected to maintain their widget state before or after calling QDrag::exec in a mousePressEvent handler, then they cannot be expected to manage their widget state before or after calling QDialog::exec, either.
> So, if we deliver the release at the end (or beginning?) of the QDrag, then we have to deliver the release when a modal dialog opens (or closes?), because these are the exact same things (user interface enters a different mode, so events get eaten and handled by that mode, which results in asymmetry). And I am not at all convinced that we should send a QEvent::MouseButtonRelease to a widget that opens a modal dialog in their mousePressEvent handler. I’d consider that a bug, breaking the meaning of “modal”. And a drag’n’drop, as it stands today, is modal (no dialog and window activation state as the visual cue, but instead the mouse cursor shows that you are dragging something; your desktop will behave differently, maybe give you other visual cues).

Indeed modal dialog and modal DND are the same thing here. They could 
both deliver a special event ("mouse grab lost event" or whatever).

(Here's a twist: is the grab truly lost? What if the modal dialog/DND 
closes, and you never released the mouse? Do you still get mouse events 
or not? If yes, do we also need a "mouse grab re-acquired" event? :-))

> Perhaps you don’t agree that QDrag::exec starts a modal user interface state similar to a modal dialog? Then the next question is whether we need to deal with key events during the drag. Should we send shift/alt/control key presses to the widget as well? Today those are entirely handled by the drag’n’drop machinery to switch the drag operation. How about wheeling the mouse during a drag? Either we are modal (events get eaten) or we are not (events get processed by the grabbing or focus widget). Today we are modal. Changing that is a huge change, and IMHO a wrong change, also deviating from how every desktop environment seems to think about “drag and drop”.

But I also agree that DND is modal, where did I say otherwise?

I just don't like the _current QDrag API_ (implemented via blocking 
exec()). But that's another story entirely!

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/20220609/57dcd452/attachment-0001.bin>

More information about the Development mailing list