[Interest] Click and hold on close button
Giuseppe D'Angelo
giuseppe.dangelo at kdab.com
Thu Aug 29 16:32:42 CEST 2019
Il 27/08/19 20:09, Murphy, Sean ha scritto:
> I've attached a sample application below that can be used to test.
> When you build and launch it, a QLabel blinks between green and
> "normal", switching palettes every second. On Windows, if you
> click and hold on any of those 3 buttons, and while holding the
> mouse, move off the original button so that the release event
> doesn't happen on the same button, the blinking will cease the
> entire time you have the button pressed. Do the same thing on
> Linux and the QLabel keeps blinking happily the entire time.
Please put aside the "conspiracy theories".
The very simple reason that the event loop blocks is that Qt doesn't
know what to do with that event, and it ends up calling DefWindowProc
[1], "the default window procedure to provide default processing for any
window messages that an application does not process" [2]. That is a
blocking call (!); execution stays in there until the OS knows what to
do, which seems to be not until you release the mouse button.
If you enable QPA logging in the qt.qpa.events category (e.g. via
QT_LOGGING_RULES), and add "verbose" > 2 to your QPA plugin loading
(e.g. -platform windows:verbose=2) you'll see the mouse press correctly
received by Qt.
If also you run your app in a debugger and make it print a stack trace
while keeping the mouse pressed on a window decoration button, you'll
see the stack trace in there.
E.g.
> C:\> timeout 5 & cdb -p 12345
> [timeout trips into the debugger]
> 0:010> ~* k
>
> 0 Id: d90.3334 Suspend: 1 Teb: 00000095`0578d000 Unfrozen
> Child-SP RetAddr Call Site
> 00000095`058fbad8 00007ffb`72b44f7a win32u!NtUserMessageCall+0x14
> 00000095`058fbae0 00007ffb`72b4470f USER32!RealDefWindowProcWorker+0x1fa
> 00000095`058fbbe0 00007ffb`6ecb984e USER32!RealDefWindowProcW+0x4f
> 00000095`058fbc20 00007ffb`6ecd24f7 UxTheme!DoMsgDefault+0x2e
> 00000095`058fbc60 00007ffb`6ecbc49f UxTheme!OnDwpNcLButtonDown+0xa7
> 00000095`058fbca0 00007ffb`6ecbbf81 UxTheme!_ThemeDefWindowProc+0x50f
> 00000095`058fbe80 00007ffb`72b44c4f UxTheme!ThemeDefWindowProcW+0x11
> 00000095`058fbec0 00007ffb`38488d92 USER32!DefWindowProcW+0x1bf
> 00000095`058fbf30 00007ffb`72b4681d qwindowsd!qWindowsWndProc+0x422
> 00000095`058fc170 00007ffb`72b46212 USER32!UserCallWinProcCheckWow+0x2bd
> 00000095`058fc300 00007ffb`3a30d443 USER32!DispatchMessageWorker+0x1e2
> 00000095`058fc380 00007ffb`385524f4 Qt5Cored!QEventDispatcherWin32::processEvents+0x5c3
This also answers why other applications don't freeze -- they must be
handling the event internally, keeping their event loops unstuck. For
instance, Chromium / Firefox may just be using client-side decorations,
and handling clicks on the decoration buttons themselves. (This has
nothing to do with the fact that their rendering is out of process,
etc.; actually it's highly likely that you need an event loop running in
the "main" application, in order to gather the rendering from the other
processes.)
So why does Qt call into a blocking Win32 API from the main thread? I
have absolutely no idea; I'm not a Windows user and I know close to 0
Win32 API programming. Event loop code looks hairy enough, but if anyone
knows if there's a "better" way to handle these events, please submit
bug reports.
> [1] https://code.woboq.org/qt5/qtbase/src/plugins/platforms/windows/qwindowscontext.cpp.html#1600
> [2] https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-defwindowprocw
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: 4329 bytes
Desc: Firma crittografica S/MIME
URL: <http://lists.qt-project.org/pipermail/interest/attachments/20190829/9db47e4d/attachment.bin>
More information about the Interest
mailing list