1 /****************************************************************************
2 **
3 ** Copyright (C) 2013 Samuel Gaist <samuel.gaist@edeltech.ch>
4 ** Copyright (C) 2016 The Qt Company Ltd.
5 ** Contact: https://www.qt.io/licensing/
6 **
7 ** This file is part of the QtCore module of the Qt Toolkit.
8 **
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** Commercial License Usage
11 ** Licensees holding valid commercial Qt licenses may use this file in
12 ** accordance with the commercial license agreement provided with the
13 ** Software or, alternatively, in accordance with the terms contained in
14 ** a written agreement between you and The Qt Company. For licensing terms
15 ** and conditions see https://www.qt.io/terms-conditions. For further
16 ** information use the contact form at https://www.qt.io/contact-us.
17 **
18 ** GNU Lesser General Public License Usage
19 ** Alternatively, this file may be used under the terms of the GNU Lesser
20 ** General Public License version 3 as published by the Free Software
21 ** Foundation and appearing in the file LICENSE.LGPL3 included in the
22 ** packaging of this file. Please review the following information to
23 ** ensure the GNU Lesser General Public License version 3 requirements
24 ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
25 **
26 ** GNU General Public License Usage
27 ** Alternatively, this file may be used under the terms of the GNU
28 ** General Public License version 2.0 or (at your option) the GNU General
29 ** Public license version 3 or any later version approved by the KDE Free
30 ** Qt Foundation. The licenses are as published by the Free Software
31 ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
32 ** included in the packaging of this file. Please review the following
33 ** information to ensure the GNU General Public License requirements will
34 ** be met: https://www.gnu.org/licenses/gpl-2.0.html and
35 ** https://www.gnu.org/licenses/gpl-3.0.html.
36 **
37 ** $QT_END_LICENSE$
38 **
39 ****************************************************************************/
40 
41 #include "qcoreapplication.h"
42 #include "qcoreapplication_p.h"
43 #include "qstringlist.h"
44 #include "qvector.h"
45 #include "qfileinfo.h"
46 #include "qcorecmdlineargs_p.h"
47 #ifndef QT_NO_QOBJECT
48 #include "qmutex.h"
49 #include <private/qthread_p.h>
50 #include <private/qlocking_p.h>
51 #endif
52 #include "qtextstream.h"
53 #include <ctype.h>
54 #include <qt_windows.h>
55 
56 #ifdef Q_OS_WINRT
57 #include <qfunctions_winrt.h>
58 #include <wrl.h>
59 #include <Windows.ApplicationModel.core.h>
60 #include <windows.foundation.h>
61 using namespace ABI::Windows::ApplicationModel;
62 using namespace Microsoft::WRL;
63 using namespace Microsoft::WRL::Wrappers;
64 #endif
65 
66 QT_BEGIN_NAMESPACE
67 
qAppFileName()68 Q_CORE_EXPORT QString qAppFileName()                // get application file name
69 {
70     /*
71       GetModuleFileName() returns the length of the module name, when it has
72       space to store it and 0-terminate; this return is necessarily smaller than
73       the buffer size, as it doesn't include the terminator. When it lacks
74       space, the function returns the full size of the buffer and fills the
75       buffer, truncating the full path to make it fit. We have reports that
76       GetModuleFileName sometimes doesn't set the error number to
77       ERROR_INSUFFICIENT_BUFFER, as claimed by the MSDN documentation; so we
78       only trust the answer when the return is actually less than the buffer
79       size we pass in. (When truncating, except on XP, it does so by enough to
80       still have space to 0-terminate; in either case, it fills the claimed
81       space and returns the size of the space. While XP might thus give us the
82       full name, without a 0 terminator, and return its actual length, we can
83       never be sure that's what's happened until a later call with bigger buffer
84       confirms it by returning less than its buffer size.)
85     */
86     // Full path may be longer than MAX_PATH - expand until we have enough space:
87     QVarLengthArray<wchar_t, MAX_PATH + 1> space;
88     DWORD v;
89     size_t size = 1;
90     do {
91         size += MAX_PATH;
92         space.resize(int(size));
93         v = GetModuleFileName(NULL, space.data(), DWORD(space.size()));
94     } while (Q_UNLIKELY(v >= size));
95 
96     return QString::fromWCharArray(space.data(), v);
97 }
98 
appName() const99 QString QCoreApplicationPrivate::appName() const
100 {
101     return QFileInfo(qAppFileName()).baseName();
102 }
103 
appVersion() const104 QString QCoreApplicationPrivate::appVersion() const
105 {
106     QString applicationVersion;
107 #ifndef QT_BOOTSTRAPPED
108 #  ifdef Q_OS_WINRT
109     HRESULT hr;
110 
111     ComPtr<IPackageStatics> packageFactory;
112     hr = RoGetActivationFactory(
113         HString::MakeReference(RuntimeClass_Windows_ApplicationModel_Package).Get(),
114         IID_PPV_ARGS(&packageFactory));
115     RETURN_IF_FAILED("Failed to create package instance", return QString());
116 
117     ComPtr<IPackage> package;
118     packageFactory->get_Current(&package);
119     RETURN_IF_FAILED("Failed to get current application package", return QString());
120 
121     ComPtr<IPackageId> packageId;
122     package->get_Id(&packageId);
123     RETURN_IF_FAILED("Failed to get current application package ID", return QString());
124 
125     PackageVersion version;
126     packageId->get_Version(&version);
127     RETURN_IF_FAILED("Failed to get current application package version", return QString());
128 
129     applicationVersion = QStringLiteral("%1.%2.%3.%4")
130             .arg(version.Major)
131             .arg(version.Minor)
132             .arg(version.Build)
133             .arg(version.Revision);
134 #  else
135     const QString appFileName = qAppFileName();
136     QVarLengthArray<wchar_t> buffer(appFileName.size() + 1);
137     buffer[appFileName.toWCharArray(buffer.data())] = 0;
138 
139     DWORD versionInfoSize = GetFileVersionInfoSize(buffer.data(), nullptr);
140     if (versionInfoSize) {
141         QVarLengthArray<BYTE> info(static_cast<int>(versionInfoSize));
142         if (GetFileVersionInfo(buffer.data(), 0, versionInfoSize, info.data())) {
143             UINT size;
144             DWORD *fi;
145 
146             if (VerQueryValue(info.data(), __TEXT("\\"),
147                               reinterpret_cast<void **>(&fi), &size) && size) {
148                 const VS_FIXEDFILEINFO *verInfo = reinterpret_cast<const VS_FIXEDFILEINFO *>(fi);
149                 applicationVersion = QStringLiteral("%1.%2.%3.%4")
150                         .arg(HIWORD(verInfo->dwProductVersionMS))
151                         .arg(LOWORD(verInfo->dwProductVersionMS))
152                         .arg(HIWORD(verInfo->dwProductVersionLS))
153                         .arg(LOWORD(verInfo->dwProductVersionLS));
154             }
155         }
156     }
157 #  endif
158 #endif
159     return applicationVersion;
160 }
161 
162 #ifndef Q_OS_WINRT
163 
164 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
qWinAppInst()165 Q_CORE_EXPORT HINSTANCE qWinAppInst()                // get Windows app handle
166 {
167     return GetModuleHandle(0);
168 }
169 
qWinAppPrevInst()170 Q_CORE_EXPORT HINSTANCE qWinAppPrevInst()                // get Windows prev app handle
171 {
172     return 0;
173 }
174 
qWinAppCmdShow()175 Q_CORE_EXPORT int qWinAppCmdShow()                        // get main window show command
176 {
177     STARTUPINFO startupInfo;
178     GetStartupInfo(&startupInfo);
179 
180     return (startupInfo.dwFlags & STARTF_USESHOWWINDOW)
181         ? startupInfo.wShowWindow
182         : SW_SHOWDEFAULT;
183 }
184 #endif
185 
186 #ifndef QT_NO_QOBJECT
187 
188 #if defined(Q_OS_WIN) && !defined(QT_NO_DEBUG_STREAM)
189 /*****************************************************************************
190   Convenience functions for convert WM_* messages into human readable strings,
191   including a nifty QDebug operator<< for simple QDebug() << msg output.
192  *****************************************************************************/
193 QT_BEGIN_INCLUDE_NAMESPACE
194 #include <windowsx.h>
195 #include "qdebug.h"
196 QT_END_INCLUDE_NAMESPACE
197 
198 #if !defined(GET_X_LPARAM)
199 #  define GET_X_LPARAM(lp) ((int)(short)LOWORD(lp))
200 #  define GET_Y_LPARAM(lp) ((int)(short)HIWORD(lp))
201 #endif
202 
203 // The values below should never change. Note that none of the usual
204 // WM_...FIRST & WM_...LAST values are in the list, as they normally have other
205 // WM_... representations
206 
207 template <class IntType>
208 struct QWinMessageMapping {
209     IntType value;
210     const char *name;
211 };
212 
213 #define FLAG_ENTRY(x) {x, #x} // for populating arrays
214 
215 // Looks up a value in a list of QWinMessageMapping
216 template <class IntType>
findWinMessageMapping(const QWinMessageMapping<IntType> * haystack,size_t haystackSize,IntType needle)217 static const char *findWinMessageMapping(const QWinMessageMapping<IntType> *haystack,
218                                          size_t haystackSize,
219                                          IntType needle)
220 {
221     for (auto p = haystack, end = haystack + haystackSize; p < end; ++p) {
222         if (p->value == needle)
223             return p->name;
224     }
225     return nullptr;
226 }
227 
228 // Format flags using a mapping as "Flag1 | Flag2"...
229 template <class IntType>
flagsValue(const QWinMessageMapping<IntType> * haystack,size_t haystackSize,IntType value)230 static QString flagsValue(const QWinMessageMapping<IntType> *haystack,
231                           size_t haystackSize, IntType value)
232 {
233     QString result;
234     for (auto p = haystack, end = haystack + haystackSize; p < end; ++p) {
235         if ((p->value & value) == p->value) {
236             if (!result.isEmpty())
237                 result += QLatin1String(" | ");
238             result += QLatin1String(p->name);
239         }
240     }
241     return result;
242 }
243 
244 // Looks up the WM_ message in the table inside
findWMstr(uint msg)245 static const char *findWMstr(uint msg)
246 {
247     static const QWinMessageMapping<uint> knownWM[] =
248 {{ 0x0000, "WM_NULL" },
249  { 0x0001, "WM_CREATE" },
250  { 0x0002, "WM_DESTROY" },
251  { 0x0003, "WM_MOVE" },
252  { 0x0005, "WM_SIZE" },
253  { 0x0006, "WM_ACTIVATE" },
254  { 0x0007, "WM_SETFOCUS" },
255  { 0x0008, "WM_KILLFOCUS" },
256  { 0x000A, "WM_ENABLE" },
257  { 0x000B, "WM_SETREDRAW" },
258  { 0x000C, "WM_SETTEXT" },
259  { 0x000D, "WM_GETTEXT" },
260  { 0x000E, "WM_GETTEXTLENGTH" },
261  { 0x000F, "WM_PAINT" },
262  { 0x0010, "WM_CLOSE" },
263  { 0x0011, "WM_QUERYENDSESSION" },
264  { 0x0013, "WM_QUERYOPEN" },
265  { 0x0016, "WM_ENDSESSION" },
266  { 0x0012, "WM_QUIT" },
267  { 0x0014, "WM_ERASEBKGND" },
268  { 0x0015, "WM_SYSCOLORCHANGE" },
269  { 0x0018, "WM_SHOWWINDOW" },
270  { 0x001A, "WM_WININICHANGE" },
271  { 0x001B, "WM_DEVMODECHANGE" },
272  { 0x001C, "WM_ACTIVATEAPP" },
273  { 0x001D, "WM_FONTCHANGE" },
274  { 0x001E, "WM_TIMECHANGE" },
275  { 0x001F, "WM_CANCELMODE" },
276  { 0x0020, "WM_SETCURSOR" },
277  { 0x0021, "WM_MOUSEACTIVATE" },
278  { 0x0022, "WM_CHILDACTIVATE" },
279  { 0x0023, "WM_QUEUESYNC" },
280  { 0x0024, "WM_GETMINMAXINFO" },
281  { 0x0026, "WM_PAINTICON" },
282  { 0x0027, "WM_ICONERASEBKGND" },
283  { 0x0028, "WM_NEXTDLGCTL" },
284  { 0x002A, "WM_SPOOLERSTATUS" },
285  { 0x002B, "WM_DRAWITEM" },
286  { 0x002C, "WM_MEASUREITEM" },
287  { 0x002D, "WM_DELETEITEM" },
288  { 0x002E, "WM_VKEYTOITEM" },
289  { 0x002F, "WM_CHARTOITEM" },
290  { 0x0030, "WM_SETFONT" },
291  { 0x0031, "WM_GETFONT" },
292  { 0x0032, "WM_SETHOTKEY" },
293  { 0x0033, "WM_GETHOTKEY" },
294  { 0x0037, "WM_QUERYDRAGICON" },
295  { 0x0039, "WM_COMPAREITEM" },
296  { 0x003D, "WM_GETOBJECT" },
297  { 0x0041, "WM_COMPACTING" },
298  { 0x0044, "WM_COMMNOTIFY" },
299  { 0x0046, "WM_WINDOWPOSCHANGING" },
300  { 0x0047, "WM_WINDOWPOSCHANGED" },
301  { 0x0048, "WM_POWER" },
302  { 0x004A, "WM_COPYDATA" },
303  { 0x004B, "WM_CANCELJOURNAL" },
304  { 0x004E, "WM_NOTIFY" },
305  { 0x0050, "WM_INPUTLANGCHANGEREQUEST" },
306  { 0x0051, "WM_INPUTLANGCHANGE" },
307  { 0x0052, "WM_TCARD" },
308  { 0x0053, "WM_HELP" },
309  { 0x0054, "WM_USERCHANGED" },
310  { 0x0055, "WM_NOTIFYFORMAT" },
311  { 0x007B, "WM_CONTEXTMENU" },
312  { 0x007C, "WM_STYLECHANGING" },
313  { 0x007D, "WM_STYLECHANGED" },
314  { 0x007E, "WM_DISPLAYCHANGE" },
315  { 0x007F, "WM_GETICON" },
316  { 0x0080, "WM_SETICON" },
317  { 0x0081, "WM_NCCREATE" },
318  { 0x0082, "WM_NCDESTROY" },
319  { 0x0083, "WM_NCCALCSIZE" },
320  { 0x0084, "WM_NCHITTEST" },
321  { 0x0085, "WM_NCPAINT" },
322  { 0x0086, "WM_NCACTIVATE" },
323  { 0x0087, "WM_GETDLGCODE" },
324  { 0x0088, "WM_SYNCPAINT" },
325  { 0x00A0, "WM_NCMOUSEMOVE" },
326  { 0x00A1, "WM_NCLBUTTONDOWN" },
327  { 0x00A2, "WM_NCLBUTTONUP" },
328  { 0x00A3, "WM_NCLBUTTONDBLCLK" },
329  { 0x00A4, "WM_NCRBUTTONDOWN" },
330  { 0x00A5, "WM_NCRBUTTONUP" },
331  { 0x00A6, "WM_NCRBUTTONDBLCLK" },
332  { 0x00A7, "WM_NCMBUTTONDOWN" },
333  { 0x00A8, "WM_NCMBUTTONUP" },
334  { 0x00A9, "WM_NCMBUTTONDBLCLK" },
335  { 0x00AB, "WM_NCXBUTTONDOWN" },
336  { 0x00AC, "WM_NCXBUTTONUP" },
337  { 0x00AD, "WM_NCXBUTTONDBLCLK" },
338  { 0x00FF, "WM_INPUT" },
339  { 0x0100, "WM_KEYDOWN" },
340  { 0x0101, "WM_KEYUP" },
341  { 0x0102, "WM_CHAR" },
342  { 0x0103, "WM_DEADCHAR" },
343  { 0x0104, "WM_SYSKEYDOWN" },
344  { 0x0105, "WM_SYSKEYUP" },
345  { 0x0106, "WM_SYSCHAR" },
346  { 0x0107, "WM_SYSDEADCHAR" },
347  { 0x0109, "WM_UNICHAR" },
348  { 0x010D, "WM_IME_STARTCOMPOSITION" },
349  { 0x010E, "WM_IME_ENDCOMPOSITION" },
350  { 0x010F, "WM_IME_COMPOSITION" },
351  { 0x0110, "WM_INITDIALOG" },
352  { 0x0111, "WM_COMMAND" },
353  { 0x0112, "WM_SYSCOMMAND" },
354  { 0x0113, "WM_TIMER" },
355  { 0x0114, "WM_HSCROLL" },
356  { 0x0115, "WM_VSCROLL" },
357  { 0x0116, "WM_INITMENU" },
358  { 0x0117, "WM_INITMENUPOPUP" },
359  { 0x011F, "WM_MENUSELECT" },
360  { 0x0120, "WM_MENUCHAR" },
361  { 0x0121, "WM_ENTERIDLE" },
362  { 0x0122, "WM_MENURBUTTONUP" },
363  { 0x0123, "WM_MENUDRAG" },
364  { 0x0124, "WM_MENUGETOBJECT" },
365  { 0x0125, "WM_UNINITMENUPOPUP" },
366  { 0x0126, "WM_MENUCOMMAND" },
367  { 0x0127, "WM_CHANGEUISTATE" },
368  { 0x0128, "WM_UPDATEUISTATE" },
369  { 0x0129, "WM_QUERYUISTATE" },
370  { 0x0132, "WM_CTLCOLORMSGBOX" },
371  { 0x0133, "WM_CTLCOLOREDIT" },
372  { 0x0134, "WM_CTLCOLORLISTBOX" },
373  { 0x0135, "WM_CTLCOLORBTN" },
374  { 0x0136, "WM_CTLCOLORDLG" },
375  { 0x0137, "WM_CTLCOLORSCROLLBAR" },
376  { 0x0138, "WM_CTLCOLORSTATIC" },
377  { 0x0200, "WM_MOUSEMOVE" },
378  { 0x0201, "WM_LBUTTONDOWN" },
379  { 0x0202, "WM_LBUTTONUP" },
380  { 0x0203, "WM_LBUTTONDBLCLK" },
381  { 0x0204, "WM_RBUTTONDOWN" },
382  { 0x0205, "WM_RBUTTONUP" },
383  { 0x0206, "WM_RBUTTONDBLCLK" },
384  { 0x0207, "WM_MBUTTONDOWN" },
385  { 0x0208, "WM_MBUTTONUP" },
386  { 0x0209, "WM_MBUTTONDBLCLK" },
387  { 0x020A, "WM_MOUSEWHEEL" },
388  { 0x020B, "WM_XBUTTONDOWN" },
389  { 0x020C, "WM_XBUTTONUP" },
390  { 0x020D, "WM_XBUTTONDBLCLK" },
391  { 0x020E, "WM_MOUSEHWHEEL" },
392  { 0x0210, "WM_PARENTNOTIFY" },
393  { 0x0211, "WM_ENTERMENULOOP" },
394  { 0x0212, "WM_EXITMENULOOP" },
395  { 0x0213, "WM_NEXTMENU" },
396  { 0x0214, "WM_SIZING" },
397  { 0x0215, "WM_CAPTURECHANGED" },
398  { 0x0216, "WM_MOVING" },
399  { 0x0218, "WM_POWERBROADCAST" },
400  { 0x0219, "WM_DEVICECHANGE" },
401  { 0x0220, "WM_MDICREATE" },
402  { 0x0221, "WM_MDIDESTROY" },
403  { 0x0222, "WM_MDIACTIVATE" },
404  { 0x0223, "WM_MDIRESTORE" },
405  { 0x0224, "WM_MDINEXT" },
406  { 0x0225, "WM_MDIMAXIMIZE" },
407  { 0x0226, "WM_MDITILE" },
408  { 0x0227, "WM_MDICASCADE" },
409  { 0x0228, "WM_MDIICONARRANGE" },
410  { 0x0229, "WM_MDIGETACTIVE" },
411  { 0x0230, "WM_MDISETMENU" },
412  { 0x0231, "WM_ENTERSIZEMOVE" },
413  { 0x0232, "WM_EXITSIZEMOVE" },
414  { 0x0233, "WM_DROPFILES" },
415  { 0x0234, "WM_MDIREFRESHMENU" },
416  { 0x0241, "WM_NCPOINTERUPDATE"},
417  { 0x0242, "WM_NCPOINTERDOWN"},
418  { 0x0243, "WM_NCPOINTERUP"},
419  { 0x0245, "WM_POINTERUPDATE"},
420  { 0x0246, "WM_POINTERDOWN"},
421  { 0x0247, "WM_POINTERUP"},
422  { 0x0249, "WM_POINTERENTER"},
423  { 0x024A, "WM_POINTERLEAVE"},
424  { 0x0248, "WM_POINTERACTIVATE"},
425  { 0x024C, "WM_POINTERCAPTURECHANGED"},
426  { 0x024D, "WM_TOUCHHITTESTING"},
427  { 0x024E, "WM_POINTERWHEEL"},
428  { 0x024F, "WM_POINTERHWHEEL"},
429  { 0x0250, "DM_POINTERHITTEST"},
430  { 0x0251, "WM_POINTERROUTEDTO"},
431  { 0x0252, "WM_POINTERROUTEDAWAY"},
432  { 0x0253, "WM_POINTERROUTEDRELEASED"},
433  { 0x0281, "WM_IME_SETCONTEXT" },
434  { 0x0282, "WM_IME_NOTIFY" },
435  { 0x0283, "WM_IME_CONTROL" },
436  { 0x0284, "WM_IME_COMPOSITIONFULL" },
437  { 0x0285, "WM_IME_SELECT" },
438  { 0x0286, "WM_IME_CHAR" },
439  { 0x0288, "WM_IME_REQUEST" },
440  { 0x0290, "WM_IME_KEYDOWN" },
441  { 0x0291, "WM_IME_KEYUP" },
442  { 0x02A0, "WM_NCMOUSEHOVER" },
443  { 0x02A1, "WM_MOUSEHOVER" },
444  { 0x02A2, "WM_NCMOUSELEAVE" },
445  { 0x02A3, "WM_MOUSELEAVE" },
446  { 0x02B1, "WM_WTSSESSION_CHANGE" },
447  { 0x02C0, "WM_TABLET_FIRST" },
448  { 0x02C1, "WM_TABLET_FIRST + 1" },
449  { 0x02C2, "WM_TABLET_FIRST + 2" },
450  { 0x02C3, "WM_TABLET_FIRST + 3" },
451  { 0x02C4, "WM_TABLET_FIRST + 4" },
452  { 0x02C5, "WM_TABLET_FIRST + 5" },
453  { 0x02C6, "WM_TABLET_FIRST + 6" },
454  { 0x02C7, "WM_TABLET_FIRST + 7" },
455  { 0x02C8, "WM_TABLET_FIRST + 8" },
456  { 0x02C9, "WM_TABLET_FIRST + 9" },
457  { 0x02CA, "WM_TABLET_FIRST + 10" },
458  { 0x02CB, "WM_TABLET_FIRST + 11" },
459  { 0x02CC, "WM_TABLET_FIRST + 12" },
460  { 0x02CD, "WM_TABLET_FIRST + 13" },
461  { 0x02CE, "WM_TABLET_FIRST + 14" },
462  { 0x02CF, "WM_TABLET_FIRST + 15" },
463  { 0x02D0, "WM_TABLET_FIRST + 16" },
464  { 0x02D1, "WM_TABLET_FIRST + 17" },
465  { 0x02D2, "WM_TABLET_FIRST + 18" },
466  { 0x02D3, "WM_TABLET_FIRST + 19" },
467  { 0x02D4, "WM_TABLET_FIRST + 20" },
468  { 0x02D5, "WM_TABLET_FIRST + 21" },
469  { 0x02D6, "WM_TABLET_FIRST + 22" },
470  { 0x02D7, "WM_TABLET_FIRST + 23" },
471  { 0x02D8, "WM_TABLET_FIRST + 24" },
472  { 0x02D9, "WM_TABLET_FIRST + 25" },
473  { 0x02DA, "WM_TABLET_FIRST + 26" },
474  { 0x02DB, "WM_TABLET_FIRST + 27" },
475  { 0x02DC, "WM_TABLET_FIRST + 28" },
476  { 0x02DD, "WM_TABLET_FIRST + 29" },
477  { 0x02DE, "WM_TABLET_FIRST + 30" },
478  { 0x02DF, "WM_TABLET_LAST" },
479  { 0x02E0, "WM_DPICHANGED" },
480  { 0x0300, "WM_CUT" },
481  { 0x0301, "WM_COPY" },
482  { 0x0302, "WM_PASTE" },
483  { 0x0303, "WM_CLEAR" },
484  { 0x0304, "WM_UNDO" },
485  { 0x0305, "WM_RENDERFORMAT" },
486  { 0x0306, "WM_RENDERALLFORMATS" },
487  { 0x0307, "WM_DESTROYCLIPBOARD" },
488  { 0x0308, "WM_DRAWCLIPBOARD" },
489  { 0x0309, "WM_PAINTCLIPBOARD" },
490  { 0x030A, "WM_VSCROLLCLIPBOARD" },
491  { 0x030B, "WM_SIZECLIPBOARD" },
492  { 0x030C, "WM_ASKCBFORMATNAME" },
493  { 0x030D, "WM_CHANGECBCHAIN" },
494  { 0x030E, "WM_HSCROLLCLIPBOARD" },
495  { 0x030F, "WM_QUERYNEWPALETTE" },
496  { 0x0310, "WM_PALETTEISCHANGING" },
497  { 0x0311, "WM_PALETTECHANGED" },
498  { 0x0312, "WM_HOTKEY" },
499  { 0x0317, "WM_PRINT" },
500  { 0x0318, "WM_PRINTCLIENT" },
501  { 0x0319, "WM_APPCOMMAND" },
502  { 0x031A, "WM_THEMECHANGED" },
503  { 0x0358, "WM_HANDHELDFIRST" },
504  { 0x0359, "WM_HANDHELDFIRST + 1" },
505  { 0x035A, "WM_HANDHELDFIRST + 2" },
506  { 0x035B, "WM_HANDHELDFIRST + 3" },
507  { 0x035C, "WM_HANDHELDFIRST + 4" },
508  { 0x035D, "WM_HANDHELDFIRST + 5" },
509  { 0x035E, "WM_HANDHELDFIRST + 6" },
510  { 0x035F, "WM_HANDHELDLAST" },
511  { 0x0360, "WM_AFXFIRST" },
512  { 0x0361, "WM_AFXFIRST + 1" },
513  { 0x0362, "WM_AFXFIRST + 2" },
514  { 0x0363, "WM_AFXFIRST + 3" },
515  { 0x0364, "WM_AFXFIRST + 4" },
516  { 0x0365, "WM_AFXFIRST + 5" },
517  { 0x0366, "WM_AFXFIRST + 6" },
518  { 0x0367, "WM_AFXFIRST + 7" },
519  { 0x0368, "WM_AFXFIRST + 8" },
520  { 0x0369, "WM_AFXFIRST + 9" },
521  { 0x036A, "WM_AFXFIRST + 10" },
522  { 0x036B, "WM_AFXFIRST + 11" },
523  { 0x036C, "WM_AFXFIRST + 12" },
524  { 0x036D, "WM_AFXFIRST + 13" },
525  { 0x036E, "WM_AFXFIRST + 14" },
526  { 0x036F, "WM_AFXFIRST + 15" },
527  { 0x0370, "WM_AFXFIRST + 16" },
528  { 0x0371, "WM_AFXFIRST + 17" },
529  { 0x0372, "WM_AFXFIRST + 18" },
530  { 0x0373, "WM_AFXFIRST + 19" },
531  { 0x0374, "WM_AFXFIRST + 20" },
532  { 0x0375, "WM_AFXFIRST + 21" },
533  { 0x0376, "WM_AFXFIRST + 22" },
534  { 0x0377, "WM_AFXFIRST + 23" },
535  { 0x0378, "WM_AFXFIRST + 24" },
536  { 0x0379, "WM_AFXFIRST + 25" },
537  { 0x037A, "WM_AFXFIRST + 26" },
538  { 0x037B, "WM_AFXFIRST + 27" },
539  { 0x037C, "WM_AFXFIRST + 28" },
540  { 0x037D, "WM_AFXFIRST + 29" },
541  { 0x037E, "WM_AFXFIRST + 30" },
542  { 0x037F, "WM_AFXLAST" },
543  { 0x0380, "WM_PENWINFIRST" },
544  { 0x0381, "WM_PENWINFIRST + 1" },
545  { 0x0382, "WM_PENWINFIRST + 2" },
546  { 0x0383, "WM_PENWINFIRST + 3" },
547  { 0x0384, "WM_PENWINFIRST + 4" },
548  { 0x0385, "WM_PENWINFIRST + 5" },
549  { 0x0386, "WM_PENWINFIRST + 6" },
550  { 0x0387, "WM_PENWINFIRST + 7" },
551  { 0x0388, "WM_PENWINFIRST + 8" },
552  { 0x0389, "WM_PENWINFIRST + 9" },
553  { 0x038A, "WM_PENWINFIRST + 10" },
554  { 0x038B, "WM_PENWINFIRST + 11" },
555  { 0x038C, "WM_PENWINFIRST + 12" },
556  { 0x038D, "WM_PENWINFIRST + 13" },
557  { 0x038E, "WM_PENWINFIRST + 14" },
558  { 0x038F, "WM_PENWINLAST" },
559  { 0x0400, "WM_USER" },
560  { 0x8000, "WM_APP" }
561  };
562 
563     return findWinMessageMapping(knownWM, sizeof(knownWM) / sizeof(knownWM[0]), msg);
564 }
565 
activateParameter(uint p)566 static const char *activateParameter(uint p)
567 {
568     static const QWinMessageMapping<uint> activeEnum[] = {
569         {WA_ACTIVE, "Activate"}, {WA_INACTIVE, "Deactivate"},
570         {WA_CLICKACTIVE, "Activate by mouseclick"}
571     };
572 
573     return findWinMessageMapping(activeEnum, sizeof(activeEnum) / sizeof(activeEnum[0]), p);
574 }
575 
styleFlags(uint style)576 static QString styleFlags(uint style)
577 {
578     static const QWinMessageMapping<uint> styleFlags[] = {
579         FLAG_ENTRY(WS_BORDER), FLAG_ENTRY(WS_CAPTION), FLAG_ENTRY(WS_CHILD),
580         FLAG_ENTRY(WS_CLIPCHILDREN), FLAG_ENTRY(WS_CLIPSIBLINGS),
581         FLAG_ENTRY(WS_DISABLED), FLAG_ENTRY(WS_DLGFRAME), FLAG_ENTRY(WS_GROUP),
582         FLAG_ENTRY(WS_HSCROLL), FLAG_ENTRY(WS_OVERLAPPED),
583         FLAG_ENTRY(WS_OVERLAPPEDWINDOW), FLAG_ENTRY(WS_ICONIC),
584         FLAG_ENTRY(WS_MAXIMIZE), FLAG_ENTRY(WS_MAXIMIZEBOX),
585         FLAG_ENTRY(WS_MINIMIZE), FLAG_ENTRY(WS_MINIMIZEBOX),
586         FLAG_ENTRY(WS_OVERLAPPEDWINDOW), FLAG_ENTRY(WS_POPUP),
587         FLAG_ENTRY(WS_POPUPWINDOW), FLAG_ENTRY(WS_SIZEBOX),
588         FLAG_ENTRY(WS_SYSMENU), FLAG_ENTRY(WS_TABSTOP), FLAG_ENTRY(WS_THICKFRAME),
589         FLAG_ENTRY(WS_TILED), FLAG_ENTRY(WS_TILEDWINDOW), FLAG_ENTRY(WS_VISIBLE),
590         FLAG_ENTRY(WS_VSCROLL)
591     };
592 
593     return flagsValue(styleFlags, sizeof(styleFlags) / sizeof(styleFlags[0]), style);
594 }
595 
exStyleFlags(uint exStyle)596 static QString exStyleFlags(uint exStyle)
597 {
598     static const QWinMessageMapping<uint> exStyleFlags[] = {
599         FLAG_ENTRY(WS_EX_ACCEPTFILES), FLAG_ENTRY(WS_EX_APPWINDOW),
600         FLAG_ENTRY(WS_EX_CLIENTEDGE), FLAG_ENTRY(WS_EX_DLGMODALFRAME),
601         FLAG_ENTRY(WS_EX_LEFT), FLAG_ENTRY(WS_EX_LEFTSCROLLBAR),
602         FLAG_ENTRY(WS_EX_LTRREADING), FLAG_ENTRY(WS_EX_MDICHILD),
603         FLAG_ENTRY(WS_EX_NOACTIVATE), FLAG_ENTRY(WS_EX_NOPARENTNOTIFY),
604         FLAG_ENTRY(WS_EX_OVERLAPPEDWINDOW), FLAG_ENTRY(WS_EX_PALETTEWINDOW),
605         FLAG_ENTRY(WS_EX_RIGHT), FLAG_ENTRY(WS_EX_RIGHTSCROLLBAR),
606         FLAG_ENTRY(WS_EX_RTLREADING), FLAG_ENTRY(WS_EX_STATICEDGE),
607         FLAG_ENTRY(WS_EX_TOOLWINDOW), FLAG_ENTRY(WS_EX_TOPMOST),
608         FLAG_ENTRY(WS_EX_TRANSPARENT), FLAG_ENTRY(WS_EX_WINDOWEDGE)
609     };
610 
611     return flagsValue(exStyleFlags, sizeof(exStyleFlags) / sizeof(exStyleFlags[0]), exStyle);
612 }
613 
imeCommand(uint cmd)614 static const char *imeCommand(uint cmd)
615 {
616      static const QWinMessageMapping<uint> commands[] = {
617          FLAG_ENTRY(IMN_CHANGECANDIDATE), FLAG_ENTRY(IMN_CLOSECANDIDATE),
618          FLAG_ENTRY(IMN_CLOSESTATUSWINDOW), FLAG_ENTRY(IMN_GUIDELINE),
619          FLAG_ENTRY(IMN_OPENCANDIDATE), FLAG_ENTRY(IMN_OPENSTATUSWINDOW),
620          FLAG_ENTRY(IMN_SETCANDIDATEPOS), FLAG_ENTRY(IMN_SETCOMPOSITIONFONT),
621          FLAG_ENTRY(IMN_SETCOMPOSITIONWINDOW), FLAG_ENTRY(IMN_SETCONVERSIONMODE),
622          FLAG_ENTRY(IMN_SETOPENSTATUS), FLAG_ENTRY(IMN_SETSENTENCEMODE),
623          FLAG_ENTRY(IMN_SETSTATUSWINDOWPOS)
624      };
625 
626      return findWinMessageMapping(commands, sizeof(commands) / sizeof(commands[0]), cmd);
627 }
628 
imeShowFlags(uint flags)629 static QString imeShowFlags(uint flags)
630 {
631     static const QWinMessageMapping<uint> showFlags[] = {
632         FLAG_ENTRY(ISC_SHOWUICOMPOSITIONWINDOW),
633         FLAG_ENTRY(ISC_SHOWUICANDIDATEWINDOW),
634         FLAG_ENTRY(ISC_SHOWUICANDIDATEWINDOW << 1),
635         FLAG_ENTRY(ISC_SHOWUICANDIDATEWINDOW << 2),
636         FLAG_ENTRY(ISC_SHOWUICANDIDATEWINDOW << 3)
637     };
638 
639     return flagsValue(showFlags, sizeof(showFlags) / sizeof(showFlags[0]), flags);
640 }
641 
wmSizeParam(uint p)642 static const char *wmSizeParam(uint p)
643 {
644     static const QWinMessageMapping<uint> sizeParams[] = {
645         FLAG_ENTRY(SIZE_MAXHIDE), FLAG_ENTRY(SIZE_MAXIMIZED),
646         FLAG_ENTRY(SIZE_MAXSHOW), FLAG_ENTRY(SIZE_MINIMIZED),
647         FLAG_ENTRY(SIZE_RESTORED)
648     };
649 
650     return findWinMessageMapping(sizeParams, sizeof(sizeParams) / sizeof(sizeParams[0]), p);
651 }
652 
virtualKeys(uint vk)653 static QString virtualKeys(uint vk)
654 {
655     static const QWinMessageMapping<uint> keys[] = {
656         FLAG_ENTRY(MK_CONTROL), FLAG_ENTRY(MK_LBUTTON), FLAG_ENTRY(MK_MBUTTON),
657         FLAG_ENTRY(MK_RBUTTON), FLAG_ENTRY(MK_SHIFT), FLAG_ENTRY(MK_XBUTTON1),
658         FLAG_ENTRY(MK_XBUTTON2)
659     };
660 
661     return flagsValue(keys, sizeof(keys) / sizeof(keys[0]), vk);
662 }
663 
winPosFlags(uint f)664 static QString winPosFlags(uint f)
665 {
666      static const QWinMessageMapping<uint> winPosValues[] = {
667          FLAG_ENTRY(SWP_DRAWFRAME), FLAG_ENTRY(SWP_FRAMECHANGED),
668          FLAG_ENTRY(SWP_HIDEWINDOW), FLAG_ENTRY(SWP_NOACTIVATE),
669          FLAG_ENTRY(SWP_NOCOPYBITS), FLAG_ENTRY(SWP_NOMOVE),
670          FLAG_ENTRY(SWP_NOOWNERZORDER), FLAG_ENTRY(SWP_NOREDRAW),
671          FLAG_ENTRY(SWP_NOREPOSITION), FLAG_ENTRY(SWP_NOSENDCHANGING),
672          FLAG_ENTRY(SWP_NOSIZE), FLAG_ENTRY(SWP_NOZORDER),
673          FLAG_ENTRY(SWP_SHOWWINDOW)
674      };
675 
676      return flagsValue(winPosValues, sizeof(winPosValues) / sizeof(winPosValues[0]), f);
677 }
678 
winPosInsertAfter(quintptr h)679 static const char *winPosInsertAfter(quintptr h)
680 {
681     static const QWinMessageMapping<quintptr> insertAfterValues[] = {
682         {quintptr(HWND_BOTTOM),    "HWND_BOTTOM"},
683         {quintptr(HWND_NOTOPMOST), "HWND_NOTOPMOST"},
684         {quintptr(HWND_TOP),       "HWND_TOP"},
685         {quintptr(HWND_TOPMOST),   "HWND_TOPMOST"}
686     };
687     return findWinMessageMapping(insertAfterValues, sizeof(insertAfterValues) / sizeof(insertAfterValues[0]), h);
688 }
689 
sessionMgrLogOffOption(uint p)690 static const char *sessionMgrLogOffOption(uint p)
691 {
692 #ifndef ENDSESSION_CLOSEAPP
693 #define ENDSESSION_CLOSEAPP 0x00000001
694 #endif
695 #ifndef ENDSESSION_CRITICAL
696 #define ENDSESSION_CRITICAL 0x40000000
697 #endif
698     static const QWinMessageMapping<uint> values[] = {
699         {ENDSESSION_CLOSEAPP, "Close application"},
700         {ENDSESSION_CRITICAL, "Force application end"},
701         {ENDSESSION_LOGOFF,   "User logoff"}
702     };
703 
704     return findWinMessageMapping(values, sizeof(values) / sizeof(values[0]), p);
705 }
706 
707 // Returns a "human readable" string representation of the MSG and the
708 // information it points to
decodeMSG(const MSG & msg)709 QString decodeMSG(const MSG& msg)
710 {
711     const WPARAM wParam = msg.wParam;
712     const LPARAM lParam = msg.lParam;
713 
714     QString message;
715     // Custom WM_'s
716     if (msg.message > WM_APP)
717         message= QString::fromLatin1("WM_APP + %1").arg(msg.message - WM_APP);
718     else if (msg.message > WM_USER)
719         message = QString::fromLatin1("WM_USER + %1").arg(msg.message - WM_USER);
720     else if (const char *wmmsgC = findWMstr(msg.message))
721         message = QString::fromLatin1(wmmsgC);
722     else
723         message = QString::fromLatin1("WM_(0x%1)").arg(msg.message, 0, 16); // Unknown WM_, so use number
724 
725     // Yes, we want to give the WM_ names 20 chars of space before showing the
726     // decoded message, since some of the common messages are quite long, and
727     // we don't want the decoded information to vary in output position
728     if (message.size() < 20)
729         message.prepend(QString(20 - message.size(), QLatin1Char(' ')));
730     message += QLatin1String(": ");
731 
732     const QString hwndS = QString::asprintf("(%p)", reinterpret_cast<void *>(msg.hwnd));
733     const QString wParamS = QString::asprintf("(%p)", reinterpret_cast<void *>(wParam));
734     const QString lParamS = QString::asprintf("(%p)", reinterpret_cast<void *>(lParam));
735 
736     QString parameters;
737     switch (msg.message) {
738         case WM_ACTIVATE:
739             if (const char *a = activateParameter(uint(wParam)))
740                 parameters += QLatin1String(a);
741             parameters += QLatin1String(" Hwnd ") + hwndS;
742             break;
743         case WM_CAPTURECHANGED:
744             parameters = QLatin1String("Hwnd gaining capture ") + hwndS;
745             break;
746         case WM_CREATE:
747             {
748                 auto lpcs = reinterpret_cast<LPCREATESTRUCT>(lParam);
749                 QString className;
750                 if (lpcs->lpszClass != nullptr) {
751                     className = HIWORD(lpcs->lpszClass) == 0
752                         ? QString::number(LOWORD(lpcs->lpszClass), 16) // Atom
753                         : QString::fromWCharArray(lpcs->lpszClass);
754                 }
755 
756                 const QString windowName = lpcs->lpszName
757                     ? QString::fromWCharArray(lpcs->lpszName) : QString();
758 
759                 parameters = QString::asprintf("x,y(%4d,%4d) w,h(%4d,%4d) className(%s) windowName(%s) parent(0x%p) style(%s) exStyle(%s)",
760                                                lpcs->x, lpcs->y, lpcs->cx, lpcs->cy,
761                                                className.toLatin1().constData(),
762                                                windowName.toLatin1().constData(),
763                                                reinterpret_cast<void *>(lpcs->hwndParent),
764                                                styleFlags(uint(lpcs->style)).toLatin1().constData(),
765                                                exStyleFlags(lpcs->dwExStyle).toLatin1().constData());
766             }
767             break;
768         case WM_DESTROY:
769             parameters = QLatin1String("Destroy hwnd ") + hwndS;
770             break;
771         case 0x02E0u: { // WM_DPICHANGED
772             auto rect = reinterpret_cast<const RECT *>(lParam);
773             QTextStream(&parameters) << "DPI: " << HIWORD(wParam) << ','
774                 << LOWORD(wParam) << ' ' << (rect->right - rect->left) << 'x'
775                 << (rect->bottom - rect->top) << Qt::forcesign << rect->left << rect->top;
776             }
777             break;
778         case WM_IME_NOTIFY:
779             {
780                 parameters = QLatin1String("Command(");
781                 if (const char *c = imeCommand(uint(wParam)))
782                     parameters += QLatin1String(c);
783                 parameters += QLatin1String(" : ") + lParamS;
784             }
785             break;
786         case WM_IME_SETCONTEXT:
787             parameters = QLatin1String("Input context(")
788                          + QLatin1String(wParam == TRUE ? "Active" : "Inactive")
789                          + QLatin1String(") Show flags(")
790                          + imeShowFlags(DWORD(lParam)) + QLatin1Char(')');
791             break;
792         case WM_KILLFOCUS:
793             parameters = QLatin1String("Hwnd gaining keyboard focus ") + wParamS;
794             break;
795         case WM_CHAR:
796         case WM_IME_CHAR:
797         case WM_KEYDOWN:
798         case WM_KEYUP:
799             {
800                 const int nVirtKey  = int(wParam);
801                 const long lKeyData = long(lParam);
802                 int repCount     = (lKeyData & 0xffff);        // Bit 0-15
803                 int scanCode     = (lKeyData & 0xf0000) >> 16; // Bit 16-23
804                 bool contextCode = !!(lKeyData & 0x20000000);  // Bit 29
805                 bool prevState   = !!(lKeyData & 0x40000000);  // Bit 30
806                 bool transState  = !!(lKeyData & 0x80000000);  // Bit 31
807                 parameters = QString::asprintf("Virtual-key(0x%x) Scancode(%d) Rep(%d) Contextcode(%d), Prev state(%d), Trans state(%d)",
808                                                nVirtKey, scanCode, repCount,
809                                                contextCode, prevState, transState);
810             }
811             break;
812         case WM_INPUTLANGCHANGE:
813             parameters = QStringLiteral("Keyboard layout changed");
814             break;
815         case WM_NCACTIVATE:
816             parameters = (msg.wParam? QLatin1String("Active Titlebar") : QLatin1String("Inactive Titlebar"));
817             break;
818         case WM_MOUSEACTIVATE:
819             {
820                 const char *mouseMsg = findWMstr(HIWORD(lParam));
821                 parameters = QString::asprintf("TLW(0x%p) HittestCode(0x%x) MouseMsg(%s)",
822                                                reinterpret_cast<void *>(wParam),
823                                                LOWORD(lParam), mouseMsg ? mouseMsg : "");
824             }
825             break;
826         case WM_MOUSELEAVE:
827             break; // wParam & lParam not used
828         case WM_MOUSEHOVER:
829         case WM_MOUSEWHEEL:
830         case WM_MOUSEHWHEEL:
831         case WM_LBUTTONDBLCLK:
832         case WM_LBUTTONDOWN:
833         case WM_LBUTTONUP:
834         case WM_MBUTTONDBLCLK:
835         case WM_MBUTTONDOWN:
836         case WM_MBUTTONUP:
837         case WM_RBUTTONDBLCLK:
838         case WM_RBUTTONDOWN:
839         case WM_RBUTTONUP:
840         case WM_MOUSEMOVE:
841             parameters = QString::asprintf("x,y(%4d,%4d) Virtual Keys(",
842                                            GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))
843                          + virtualKeys(uint(wParam)) + QLatin1Char(')');
844             break;
845         case WM_MOVE:
846             parameters = QString::asprintf("x,y(%4d,%4d)", LOWORD(lParam), HIWORD(lParam));
847             break;
848         case WM_ERASEBKGND:
849         case WM_PAINT:
850             parameters = QLatin1String("hdc") + wParamS;
851             break;
852         case WM_QUERYNEWPALETTE:
853             break; // lParam & wParam are unused
854         case WM_SETCURSOR:
855             parameters = QString::asprintf("HitTestCode(0x%x) MouseMsg(", LOWORD(lParam));
856             if (const char *mouseMsg = findWMstr(HIWORD(lParam)))
857                 parameters += QLatin1String(mouseMsg);
858             parameters += QLatin1Char(')');
859             break;
860         case WM_SETFOCUS:
861             parameters = QLatin1String("Lost Focus ") + wParamS;
862             break;
863         case WM_SETTEXT:
864             parameters = QLatin1String("Set Text (")
865                          + QString::fromWCharArray(reinterpret_cast<const wchar_t *>(lParam))
866                          + QLatin1Char(')');
867             break;
868         case WM_SIZE:
869             parameters = QString::asprintf("w,h(%4d,%4d) showmode(",
870                                            LOWORD(lParam), HIWORD(lParam));
871             if (const char *showMode = wmSizeParam(uint(wParam)))
872                 parameters += QLatin1String(showMode);
873             parameters += QLatin1Char(')');
874             break;
875         case WM_WINDOWPOSCHANGED:
876             {
877                 auto winPos = reinterpret_cast<LPWINDOWPOS>(lParam);
878                 if (!winPos)
879                     break;
880                 const auto insertAfter = quintptr(winPos->hwndInsertAfter);
881                 parameters = QString::asprintf("x,y(%4d,%4d) w,h(%4d,%4d) flags(%s) hwndAfter(",
882                                                winPos->x, winPos->y, winPos->cx, winPos->cy,
883                                                winPosFlags(winPos->flags).toLatin1().constData());
884                 if (const char *h = winPosInsertAfter(insertAfter))
885                     parameters += QLatin1String(h);
886                 else
887                     parameters += QString::number(insertAfter, 16);
888                 parameters += QLatin1Char(')');
889             }
890             break;
891         case WM_QUERYENDSESSION:
892             parameters = QLatin1String("End session: ");
893             if (const char *logoffOption = sessionMgrLogOffOption(uint(wParam)))
894                 parameters += QLatin1String(logoffOption);
895             break;
896         default:
897             parameters = QLatin1String("wParam") + wParamS + QLatin1String(" lParam") + lParamS;
898             break;
899     }
900 
901     return message + QLatin1String("hwnd") + hwndS + QLatin1Char(' ') + parameters;
902 }
903 
operator <<(QDebug dbg,const MSG & msg)904 QDebug operator<<(QDebug dbg, const MSG &msg)
905 {
906     QDebugStateSaver saver(dbg);
907     dbg.noquote();
908     dbg.nospace();
909     dbg << decodeMSG(msg);
910     return dbg;
911 }
912 #endif
913 
914 #endif // QT_NO_QOBJECT
915 
916 #endif // !defined(Q_OS_WINRT)
917 
918 #ifndef QT_NO_QOBJECT
removePostedTimerEvent(QObject * object,int timerId)919 void QCoreApplicationPrivate::removePostedTimerEvent(QObject *object, int timerId)
920 {
921     QThreadData *data = object->d_func()->threadData.loadRelaxed();
922 
923     const auto locker = qt_scoped_lock(data->postEventList.mutex);
924     if (data->postEventList.size() == 0)
925         return;
926     for (int i = 0; i < data->postEventList.size(); ++i) {
927         const QPostEvent &pe = data->postEventList.at(i);
928         if (pe.receiver == object
929                 && pe.event
930                 && (pe.event->type() == QEvent::Timer || pe.event->type() == QEvent::ZeroTimerEvent)
931                 && static_cast<QTimerEvent *>(pe.event)->timerId() == timerId) {
932             --pe.receiver->d_func()->postedEvents;
933             pe.event->posted = false;
934             delete pe.event;
935             const_cast<QPostEvent &>(pe).event = 0;
936             return;
937         }
938     }
939 }
940 #endif // QT_NO_QOBJECT
941 
942 QT_END_NAMESPACE
943