Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qwindowscontext.cpp
Go to the documentation of this file.
1// Copyright (C) 2013 Samuel Gaist <samuel.gaist@edeltech.ch>
2// Copyright (C) 2016 The Qt Company Ltd.
3// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
4
5#include "qwindowscontext.h"
7#include "qwindowswindow.h"
8#include "qwindowskeymapper.h"
12#include "qtwindowsglobal.h"
13#include "qwindowsmenu.h"
16#if QT_CONFIG(tabletevent)
18#endif
19#include "qwindowstheme.h"
20#include <private/qguiapplication_p.h>
21#if QT_CONFIG(accessibility)
23#endif
24#if QT_CONFIG(sessionmanager)
25# include <private/qsessionmanager_p.h>
27#endif
28#include "qwindowsscreen.h"
29#include "qwindowstheme.h"
30
31#include <QtGui/qwindow.h>
32#include <qpa/qwindowsysteminterface.h>
33#include <qpa/qwindowsysteminterface_p.h>
34#include <qpa/qplatformnativeinterface.h>
35#include <QtGui/qguiapplication.h>
36#include <QtGui/qopenglcontext.h>
37#include <QtGui/qpointingdevice.h>
38
39#include <QtCore/qset.h>
40#include <QtCore/qhash.h>
41#include <QtCore/qlibraryinfo.h>
42#include <QtCore/qstringlist.h>
43#include <QtCore/qdebug.h>
44#include <QtCore/qsysinfo.h>
45#include <QtCore/qscopedpointer.h>
46#include <QtCore/quuid.h>
47#include <QtCore/private/qwinregistry_p.h>
48#if QT_CONFIG(cpp_winrt)
49# include <QtCore/private/qfactorycacheregistration_p.h>
50#endif
51#include <QtCore/private/qsystemerror_p.h>
52
53#include <QtGui/private/qwindowsguieventdispatcher_p.h>
54#include <QtGui/private/qwindowsthemecache_p.h>
55
56#include <stdlib.h>
57#include <stdio.h>
58#include <windowsx.h>
59#include <dbt.h>
60#include <wtsapi32.h>
61#include <shellscalingapi.h>
62
64
65using namespace Qt::StringLiterals;
66
67Q_LOGGING_CATEGORY(lcQpaWindow, "qt.qpa.window")
68Q_LOGGING_CATEGORY(lcQpaEvents, "qt.qpa.events")
69Q_LOGGING_CATEGORY(lcQpaGl, "qt.qpa.gl")
70Q_LOGGING_CATEGORY(lcQpaMime, "qt.qpa.mime")
71Q_LOGGING_CATEGORY(lcQpaInputMethods, "qt.qpa.input.methods")
72Q_LOGGING_CATEGORY(lcQpaDialogs, "qt.qpa.dialogs")
73Q_LOGGING_CATEGORY(lcQpaMenus, "qt.qpa.menus")
74Q_LOGGING_CATEGORY(lcQpaTablet, "qt.qpa.input.tablet")
75Q_LOGGING_CATEGORY(lcQpaAccessibility, "qt.qpa.accessibility")
76Q_LOGGING_CATEGORY(lcQpaUiAutomation, "qt.qpa.uiautomation")
77Q_LOGGING_CATEGORY(lcQpaTrayIcon, "qt.qpa.trayicon")
78Q_LOGGING_CATEGORY(lcQpaScreen, "qt.qpa.screen")
79
80int QWindowsContext::verbose = 0;
81
82#if !defined(LANG_SYRIAC)
83# define LANG_SYRIAC 0x5a
84#endif
85
86static inline bool useRTL_Extensions()
87{
88 // Since the IsValidLanguageGroup/IsValidLocale functions always return true on
89 // Vista, check the Keyboard Layouts for enabling RTL.
90 if (const int nLayouts = GetKeyboardLayoutList(0, nullptr)) {
91 QScopedArrayPointer<HKL> lpList(new HKL[nLayouts]);
92 GetKeyboardLayoutList(nLayouts, lpList.data());
93 for (int i = 0; i < nLayouts; ++i) {
94 switch (PRIMARYLANGID((quintptr)lpList[i])) {
95 case LANG_ARABIC:
96 case LANG_HEBREW:
97 case LANG_FARSI:
98 case LANG_SYRIAC:
99 return true;
100 default:
101 break;
102 }
103 }
104 }
105 return false;
106}
107
108#if QT_CONFIG(sessionmanager)
109static inline QWindowsSessionManager *platformSessionManager()
110{
111 auto *guiPrivate = static_cast<QGuiApplicationPrivate*>(QObjectPrivate::get(qApp));
112 auto *managerPrivate = static_cast<QSessionManagerPrivate*>(QObjectPrivate::get(guiPrivate->session_manager));
113 return static_cast<QWindowsSessionManager *>(managerPrivate->platformSessionManager);
114}
115
116static inline bool sessionManagerInteractionBlocked()
117{
118 return platformSessionManager()->isInteractionBlocked();
119}
120#else // QT_CONFIG(sessionmanager)
121static inline bool sessionManagerInteractionBlocked() { return false; }
122#endif
123
124QWindowsContext *QWindowsContext::m_instance = nullptr;
125
159
161
163 : m_oleInitializeResult(OleInitialize(nullptr))
164{
167 m_displayContext = GetDC(nullptr);
168 m_defaultDPI = GetDeviceCaps(m_displayContext, LOGPIXELSY);
169 if (useRTL_Extensions()) {
172 }
173 if (FAILED(m_oleInitializeResult)) {
174 qWarning() << "QWindowsContext: OleInitialize() failed: "
175 << QSystemError::windowsComString(m_oleInitializeResult);
176 }
177}
178
181{
182#ifdef Q_CC_MSVC
183# pragma warning( disable : 4996 )
184#endif
185 m_instance = this;
186 // ### FIXME: Remove this once the logging system has other options of configurations.
187 const QByteArray bv = qgetenv("QT_QPA_VERBOSE");
188 if (!bv.isEmpty())
190}
191
193{
194#if QT_CONFIG(tabletevent)
195 d->m_tabletSupport.reset(); // Destroy internal window before unregistering classes.
196#endif
197
198 if (d->m_powerNotification)
199 UnregisterPowerSettingNotification(d->m_powerNotification);
200
201 if (d->m_powerDummyWindow)
202 DestroyWindow(d->m_powerDummyWindow);
203
205
206 unregisterWindowClasses();
207 if (d->m_oleInitializeResult == S_OK || d->m_oleInitializeResult == S_FALSE) {
208#ifdef QT_USE_FACTORY_CACHE_REGISTRATION
209 detail::QWinRTFactoryCacheRegistration::clearAllCaches();
210#endif
211 OleUninitialize();
212 }
213
214 d->m_screenManager.clearScreens(); // Order: Potentially calls back to the windows.
215 if (d->m_displayContext)
216 ReleaseDC(nullptr, d->m_displayContext);
217 m_instance = nullptr;
218}
219
221{
222 return initTouch(QWindowsIntegration::instance()->options());
223}
224
225bool QWindowsContext::initTouch(unsigned integrationOptions)
226{
228 return true;
229 const bool usePointerHandler = (d->m_systemInfo & QWindowsContext::SI_SupportsPointer) != 0;
230 auto touchDevice = usePointerHandler ? d->m_pointerHandler.touchDevice() : d->m_mouseHandler.touchDevice();
231 if (touchDevice.isNull()) {
232 const bool mouseEmulation =
234 touchDevice = QWindowsPointerHandler::createTouchDevice(mouseEmulation);
235 }
236 if (touchDevice.isNull())
237 return false;
238 d->m_pointerHandler.setTouchDevice(touchDevice);
239 d->m_mouseHandler.setTouchDevice(touchDevice);
241
243
244 // A touch device was plugged while the app is running. Register all windows for touch.
246
247 return true;
248}
249
251{
254 for (QWindowsWindow *w : std::as_const(d->m_windows))
255 w->registerTouchWindow();
256 }
257}
258
260{
261#if QT_CONFIG(tabletevent)
262 d->m_tabletSupport.reset(QWindowsTabletSupport::create());
263 return true;
264#else
265 return false;
266#endif
267}
268
270{
271#if QT_CONFIG(tabletevent)
272 d->m_tabletSupport.reset();
273 return true;
274#else
275 return false;
276#endif
277}
278
279bool QWindowsContext::initPointer(unsigned integrationOptions)
280{
281 if (integrationOptions & QWindowsIntegration::DontUseWMPointer)
282 return false;
283
285 return true;
286}
287
288extern "C" LRESULT QT_WIN_CALLBACK qWindowsPowerWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
289{
290 if (message != WM_POWERBROADCAST || wParam != PBT_POWERSETTINGCHANGE)
291 return DefWindowProc(hwnd, message, wParam, lParam);
292
293 static bool initialized = false; // ignore the initial change
294 if (!initialized) {
295 initialized = true;
296 return DefWindowProc(hwnd, message, wParam, lParam);
297 }
298
299 auto setting = reinterpret_cast<const POWERBROADCAST_SETTING *>(lParam);
300 if (setting) {
301 auto data = reinterpret_cast<const DWORD *>(&setting->Data);
302 if (*data == 1) {
303 // Repaint the windows when returning from sleeping display mode.
304 const auto tlw = QGuiApplication::topLevelWindows();
305 for (auto w : tlw) {
306 if (w->isVisible() && w->windowState() != Qt::WindowMinimized) {
307 if (auto tw = QWindowsWindow::windowsWindowOf(w)) {
308 if (HWND hwnd = tw->handle()) {
309 InvalidateRect(hwnd, nullptr, false);
310 }
311 }
312 }
313 }
314 }
315 }
316 return DefWindowProc(hwnd, message, wParam, lParam);
317}
318
320{
321 if (d->m_powerNotification)
322 return false;
323
324 d->m_powerDummyWindow = createDummyWindow(QStringLiteral("PowerDummyWindow"), L"QtPowerDummyWindow", qWindowsPowerWindowProc);
325 if (!d->m_powerDummyWindow)
326 return false;
327
328 d->m_powerNotification = RegisterPowerSettingNotification(d->m_powerDummyWindow, &GUID_MONITOR_POWER_ON, DEVICE_NOTIFY_WINDOW_HANDLE);
329 if (!d->m_powerNotification) {
330 DestroyWindow(d->m_powerDummyWindow);
331 d->m_powerDummyWindow = nullptr;
332 return false;
333 }
334 return true;
335}
336
338{
339#if QT_CONFIG(tabletevent)
341#else
342 Q_UNUSED(a);
343#endif
344}
345
350
351[[nodiscard]] static inline QtWindows::DpiAwareness
353{
354 // IsValidDpiAwarenessContext() will handle the NULL pointer case.
355 if (!IsValidDpiAwarenessContext(context))
357 if (AreDpiAwarenessContextsEqual(context, DPI_AWARENESS_CONTEXT_UNAWARE_GDISCALED))
359 if (AreDpiAwarenessContextsEqual(context, DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2))
361 if (AreDpiAwarenessContextsEqual(context, DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE))
363 if (AreDpiAwarenessContextsEqual(context, DPI_AWARENESS_CONTEXT_SYSTEM_AWARE))
365 if (AreDpiAwarenessContextsEqual(context, DPI_AWARENESS_CONTEXT_UNAWARE))
368}
369
371{
372 if (!hwnd)
374 const auto context = GetWindowDpiAwarenessContext(hwnd);
376}
377
379{
380 // Although we have GetDpiAwarenessContextForProcess(), however,
381 // it's only available on Win10 1903+, which is a little higher
382 // than Qt's minimum supported version (1809), so we can't use it.
383 // Luckily, MS docs said GetThreadDpiAwarenessContext() will also
384 // return the default DPI_AWARENESS_CONTEXT for the process if
385 // SetThreadDpiAwarenessContext() was never called. So we can use
386 // it as an equivalent.
387 const auto context = GetThreadDpiAwarenessContext();
389}
390
391[[nodiscard]] static inline DPI_AWARENESS_CONTEXT
410
411#ifndef QT_NO_DEBUG_STREAM
413{
414 const QDebugStateSaver saver(d);
415 QString message = u"QtWindows::DpiAwareness::"_s;
416 switch (dpiAwareness) {
418 message += u"Invalid"_s;
419 break;
421 message += u"Unaware"_s;
422 break;
424 message += u"System"_s;
425 break;
427 message += u"PerMonitor"_s;
428 break;
430 message += u"PerMonitorVersion2"_s;
431 break;
433 message += u"Unaware_GdiScaled"_s;
434 break;
435 }
436 d.nospace().noquote() << message;
437 return d;
438}
439#endif
440
442{
443 qCDebug(lcQpaWindow) << __FUNCTION__ << dpiAwareness;
444 if (processDpiAwareness() == dpiAwareness)
445 return true;
446 const auto context = qtDpiAwarenessToDpiAwarenessContext(dpiAwareness);
447 if (!IsValidDpiAwarenessContext(context)) {
448 qCWarning(lcQpaWindow) << dpiAwareness << "is not supported by current system.";
449 return false;
450 }
451 if (!SetProcessDpiAwarenessContext(context)) {
452 qCWarning(lcQpaWindow).noquote().nospace()
453 << "SetProcessDpiAwarenessContext() failed: "
454 << QSystemError::windowsString()
455 << "\nQt's default DPI awareness context is "
456 << "DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2. If you know what you "
457 << "are doing, you can overwrite this default using qt.conf "
458 << "(https://doc.qt.io/qt-6/highdpi.html#configuring-windows).";
459 return false;
460 }
463 return true;
464}
465
467{
468 return m_instance;
469}
470
472{
473 return d->m_systemInfo;
474}
475
477{
478 return d->m_keyMapper.useRTLExtensions();
479}
480
485
490
491QSharedPointer<QWindowCreationContext> QWindowsContext::setWindowCreationContext(const QSharedPointer<QWindowCreationContext> &ctx)
492{
493 const QSharedPointer<QWindowCreationContext> old = d->m_creationContext;
495 return old;
496}
497
498QSharedPointer<QWindowCreationContext> QWindowsContext::windowCreationContext() const
499{
500 return d->m_creationContext;
501}
502
504{
505 return d->m_defaultDPI;
506}
507
509{
510 return d->m_displayContext;
511}
512
514{
515 return d->m_keyMapper.keyGrabber();
516}
517
522
524{
525 static QString result;
526 if (result.isEmpty()) {
528 str << "Qt" << QT_VERSION_MAJOR << QT_VERSION_MINOR << QT_VERSION_PATCH;
530 str << 'd';
531#ifdef QT_NAMESPACE
532# define xstr(s) str(s)
533# define str(s) #s
534 str << xstr(QT_NAMESPACE);
535# undef str
536# undef xstr
537#endif
538 }
539 return result;
540}
541
542// Window class registering code (from qapplication_win.cpp)
543
545{
546 Q_ASSERT(w);
547 const Qt::WindowFlags flags = w->flags();
548 const Qt::WindowFlags type = flags & Qt::WindowType_Mask;
549 // Determine style and icon.
550 uint style = CS_DBLCLKS;
551 bool icon = true;
552 // The following will not set CS_OWNDC for any widget window, even if it contains a
553 // QOpenGLWidget or QQuickWidget later on. That cannot be detected at this stage.
554 if (w->surfaceType() == QSurface::OpenGLSurface || (flags & Qt::MSWindowsOwnDC))
555 style |= CS_OWNDC;
557 && (type == Qt::Popup || w->property("_q_windowsDropShadow").toBool())) {
558 style |= CS_DROPSHADOW;
559 }
560 switch (type) {
561 case Qt::Tool:
562 case Qt::ToolTip:
563 case Qt::Popup:
564 style |= CS_SAVEBITS; // Save/restore background
565 icon = false;
566 break;
567 case Qt::Dialog:
569 icon = false; // QTBUG-2027, dialogs without system menu.
570 break;
571 }
572 // Create a unique name for the flag combination
573 QString cname = classNamePrefix();
574 cname += "QWindow"_L1;
575 switch (type) {
576 case Qt::Tool:
577 cname += "Tool"_L1;
578 break;
579 case Qt::ToolTip:
580 cname += "ToolTip"_L1;
581 break;
582 case Qt::Popup:
583 cname += "Popup"_L1;
584 break;
585 default:
586 break;
587 }
588 if (style & CS_DROPSHADOW)
589 cname += "DropShadow"_L1;
590 if (style & CS_SAVEBITS)
591 cname += "SaveBits"_L1;
592 if (style & CS_OWNDC)
593 cname += "OwnDC"_L1;
594 if (icon)
595 cname += "Icon"_L1;
596
597 return registerWindowClass(cname, qWindowsWndProc, style, nullptr, icon);
598}
599
601 WNDPROC proc,
602 unsigned style,
603 HBRUSH brush,
604 bool icon)
605{
606 // since multiple Qt versions can be used in one process
607 // each one has to have window class names with a unique name
608 // The first instance gets the unmodified name; if the class
609 // has already been registered by another instance of Qt then
610 // add a UUID. The check needs to be performed for each name
611 // in case new message windows are added (QTBUG-81347).
612 // Note: GetClassInfo() returns != 0 when a class exists.
613 const auto appInstance = static_cast<HINSTANCE>(GetModuleHandle(nullptr));
614 WNDCLASS wcinfo;
615 const bool classExists = GetClassInfo(appInstance, reinterpret_cast<LPCWSTR>(cname.utf16()), &wcinfo) != FALSE
616 && wcinfo.lpfnWndProc != proc;
617
618 if (classExists)
619 cname += QUuid::createUuid().toString();
620
621 if (d->m_registeredWindowClassNames.contains(cname)) // already registered in our list
622 return cname;
623
624 WNDCLASSEX wc;
625 wc.cbSize = sizeof(WNDCLASSEX);
626 wc.style = style;
627 wc.lpfnWndProc = proc;
628 wc.cbClsExtra = 0;
629 wc.cbWndExtra = 0;
630 wc.hInstance = appInstance;
631 wc.hCursor = nullptr;
632 wc.hbrBackground = brush;
633 if (icon) {
634 wc.hIcon = static_cast<HICON>(LoadImage(appInstance, L"IDI_ICON1", IMAGE_ICON, 0, 0, LR_DEFAULTSIZE));
635 if (wc.hIcon) {
636 int sw = GetSystemMetrics(SM_CXSMICON);
637 int sh = GetSystemMetrics(SM_CYSMICON);
638 wc.hIconSm = static_cast<HICON>(LoadImage(appInstance, L"IDI_ICON1", IMAGE_ICON, sw, sh, 0));
639 } else {
640 wc.hIcon = static_cast<HICON>(LoadImage(nullptr, IDI_APPLICATION, IMAGE_ICON, 0, 0, LR_DEFAULTSIZE | LR_SHARED));
641 wc.hIconSm = nullptr;
642 }
643 } else {
644 wc.hIcon = nullptr;
645 wc.hIconSm = nullptr;
646 }
647
648 wc.lpszMenuName = nullptr;
649 wc.lpszClassName = reinterpret_cast<LPCWSTR>(cname.utf16());
650 ATOM atom = RegisterClassEx(&wc);
651 if (!atom)
652 qErrnoWarning("QApplication::regClass: Registering window class '%s' failed.",
653 qPrintable(cname));
654
656 qCDebug(lcQpaWindow).nospace() << __FUNCTION__ << ' ' << cname
657 << " style=0x" << Qt::hex << style << Qt::dec
658 << " brush=" << brush << " icon=" << icon << " atom=" << atom;
659 return cname;
660}
661
662void QWindowsContext::unregisterWindowClasses()
663{
664 const auto appInstance = static_cast<HINSTANCE>(GetModuleHandle(nullptr));
665
666 for (const QString &name : std::as_const(d->m_registeredWindowClassNames)) {
667 if (!UnregisterClass(reinterpret_cast<LPCWSTR>(name.utf16()), appInstance) && QWindowsContext::verbose)
668 qErrnoWarning("UnregisterClass failed for '%s'", qPrintable(name));
669 }
671}
672
674{
675 return GetDeviceCaps(d->m_displayContext, BITSPIXEL);
676}
677
679{
680 d->m_windows.insert(hwnd, w);
681}
682
684{
686 if (it != d->m_windows.end()) {
687 if (d->m_keyMapper.keyGrabber() == it.value()->window())
688 d->m_keyMapper.setKeyGrabber(nullptr);
689 d->m_windows.erase(it);
690 }
691}
692
694{
695 for (auto it = d->m_windows.cbegin(), end = d->m_windows.cend(); it != end; ++it) {
696 if ((*it)->menuBar() == mb)
697 return *it;
698 }
699 return nullptr;
700}
701
703{
704 return d->m_windows.value(hwnd);
705}
706
708{
710
711 // Requested hwnd may also be a child of a platform window in case of embedded native windows.
712 // Find the closest parent that has a platform window.
713 if (!window) {
714 for (HWND w = hwnd; w; w = GetParent(w)) {
715 window = d->m_windows.value(w);
716 if (window)
717 break;
718 }
719 }
720
721 return window;
722}
723
725{
726 if (const QWindowsWindow *bw = findPlatformWindow(hwnd))
727 return bw->window();
728 return nullptr;
729}
730
736
744
757static inline bool findPlatformWindowHelper(const POINT &screenPoint, unsigned cwexFlags,
759 HWND *hwnd, QWindowsWindow **result)
760{
761 POINT point = screenPoint;
762 screenToClient(*hwnd, &point);
763 // Returns parent if inside & none matched.
764 const HWND child = ChildWindowFromPointEx(*hwnd, point, cwexFlags);
765 if (!child || child == *hwnd)
766 return false;
767 if (QWindowsWindow *window = context->findPlatformWindow(child)) {
768 *result = window;
769 *hwnd = child;
770 return true;
771 }
772 // QTBUG-40555: despite CWP_SKIPINVISIBLE, it is possible to hit on invisible
773 // full screen windows of other applications that have WS_EX_TRANSPARENT set
774 // (for example created by screen sharing applications). In that case, try to
775 // find a Qt window by searching again with CWP_SKIPTRANSPARENT.
776 // Note that Qt 5 uses WS_EX_TRANSPARENT for Qt::WindowTransparentForInput
777 // as well.
778 if (!(cwexFlags & CWP_SKIPTRANSPARENT)
779 && (GetWindowLongPtr(child, GWL_EXSTYLE) & WS_EX_TRANSPARENT)) {
780 const HWND nonTransparentChild = ChildWindowFromPointEx(*hwnd, point, cwexFlags | CWP_SKIPTRANSPARENT);
781 if (!nonTransparentChild || nonTransparentChild == *hwnd)
782 return false;
783 if (QWindowsWindow *nonTransparentWindow = context->findPlatformWindow(nonTransparentChild)) {
784 *result = nonTransparentWindow;
785 *hwnd = nonTransparentChild;
786 return true;
787 }
788 }
789 *hwnd = child;
790 return true;
791}
792
794 const QPoint &screenPointIn,
795 unsigned cwex_flags) const
796{
797 QWindowsWindow *result = nullptr;
798 const POINT screenPoint = { screenPointIn.x(), screenPointIn.y() };
799 while (findPlatformWindowHelper(screenPoint, cwex_flags, this, &parent, &result)) {}
800 // QTBUG-40815: ChildWindowFromPointEx() can hit on special windows from
801 // screen recorder applications like ScreenToGif. Fall back to WindowFromPoint().
802 if (result == nullptr) {
803 if (const HWND window = WindowFromPoint(screenPoint))
805 }
806 return result;
807}
808
810{
811 bool result = false;
812 const DWORD sessionId = WTSGetActiveConsoleSessionId();
813 if (sessionId != 0xFFFFFFFF) {
814 LPTSTR buffer = nullptr;
815 DWORD size = 0;
816#if !defined(Q_CC_MINGW)
817 if (WTSQuerySessionInformation(WTS_CURRENT_SERVER_HANDLE, sessionId,
818 WTSSessionInfoEx, &buffer, &size) == TRUE
819 && size > 0) {
820 const WTSINFOEXW *info = reinterpret_cast<WTSINFOEXW *>(buffer);
821 result = info->Level == 1 && info->Data.WTSInfoExLevel1.SessionFlags == WTS_SESSIONSTATE_LOCK;
822 WTSFreeMemory(buffer);
823 }
824#else // MinGW as of 7.3 does not have WTSINFOEXW in wtsapi32.h
825 // Retrieve the flags which are at offset 16 due to padding for 32/64bit alike.
826 if (WTSQuerySessionInformation(WTS_CURRENT_SERVER_HANDLE, sessionId,
827 WTS_INFO_CLASS(25), &buffer, &size) == TRUE
828 && size >= 20) {
829 const DWORD *p = reinterpret_cast<DWORD *>(buffer);
830 const DWORD level = *p;
831 const DWORD sessionFlags = *(p + 4);
832 result = level == 1 && sessionFlags == 1;
833 WTSFreeMemory(buffer);
834 }
835#endif // Q_CC_MINGW
836 }
837 return result;
838}
839
844
849
851{
852#if QT_CONFIG(tabletevent)
853 return d->m_tabletSupport.data();
854#else
855 return 0;
856#endif
857}
858
865 const wchar_t *windowName,
866 WNDPROC wndProc, DWORD style)
867{
868 if (!wndProc)
869 wndProc = DefWindowProc;
870 QString className = registerWindowClass(classNamePrefix() + classNameIn, wndProc);
871 return CreateWindowEx(0, reinterpret_cast<LPCWSTR>(className.utf16()),
872 windowName, style,
873 CW_USEDEFAULT, CW_USEDEFAULT,
874 CW_USEDEFAULT, CW_USEDEFAULT,
875 HWND_MESSAGE, nullptr, static_cast<HINSTANCE>(GetModuleHandle(nullptr)), nullptr);
876}
877
879{
880 // Force WM_NCCALCSIZE to adjust margin
881 SetWindowPos(hwnd, nullptr, 0, 0, 0, 0,
882 SWP_FRAMECHANGED | SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_NOOWNERZORDER);
883}
884
885bool QWindowsContext::systemParametersInfo(unsigned action, unsigned param, void *out,
886 unsigned dpi)
887{
888 const BOOL result = dpi != 0
889 ? SystemParametersInfoForDpi(action, param, out, 0, dpi)
890 : SystemParametersInfo(action, param, out, 0);
891 return result == TRUE;
892}
893
894bool QWindowsContext::systemParametersInfoForScreen(unsigned action, unsigned param, void *out,
895 const QPlatformScreen *screen)
896{
897 return systemParametersInfo(action, param, out, screen ? unsigned(screen->logicalDpi().first) : 0u);
898}
899
900bool QWindowsContext::systemParametersInfoForWindow(unsigned action, unsigned param, void *out,
901 const QPlatformWindow *win)
902{
903 return systemParametersInfoForScreen(action, param, out, win ? win->screen() : nullptr);
904}
905
906bool QWindowsContext::nonClientMetrics(NONCLIENTMETRICS *ncm, unsigned dpi)
907{
908 memset(ncm, 0, sizeof(NONCLIENTMETRICS));
909 ncm->cbSize = sizeof(NONCLIENTMETRICS);
910 return systemParametersInfo(SPI_GETNONCLIENTMETRICS, ncm->cbSize, ncm, dpi);
911}
912
914 const QPlatformScreen *screen)
915{
916 const int dpi = screen ? qRound(screen->logicalDpi().first) : 0;
917 return nonClientMetrics(ncm, unsigned(dpi));
918}
919
921{
922 return nonClientMetricsForScreen(ncm, win ? win->screen() : nullptr);
923}
924
926{
927 return qobject_cast<QWindowsInputContext *>(QWindowsIntegration::instance()->inputContext());
928}
929
931{
932 // DPI aware V2 processes always have NonClientDpiScaling enabled.
934 return true;
935
936 return window->isTopLevel()
938#if QT_CONFIG(opengl) // /QTBUG-62901, EnableNonClientDpiScaling has problems with GL
939 && (window->surfaceType() != QSurface::OpenGLSurface
941#endif
942 ;
943}
944
945static inline bool isInputMessage(UINT m)
946{
947 switch (m) {
948 case WM_IME_STARTCOMPOSITION:
949 case WM_IME_ENDCOMPOSITION:
950 case WM_IME_COMPOSITION:
951 case WM_INPUT:
952 case WM_TOUCH:
953 case WM_MOUSEHOVER:
954 case WM_MOUSELEAVE:
955 case WM_NCMOUSEHOVER:
956 case WM_NCMOUSELEAVE:
957 case WM_SIZING:
958 case WM_MOVING:
959 case WM_SYSCOMMAND:
960 case WM_COMMAND:
961 case WM_DWMNCRENDERINGCHANGED:
962 case WM_PAINT:
963 return true;
964 default:
965 break;
966 }
967 return (m >= WM_MOUSEFIRST && m <= WM_MOUSELAST)
968 || (m >= WM_NCMOUSEMOVE && m <= WM_NCXBUTTONDBLCLK)
969 || (m >= WM_KEYFIRST && m <= WM_KEYLAST);
970}
971
972// Note: This only works within WM_NCCREATE
973static bool enableNonClientDpiScaling(HWND hwnd)
974{
975 bool result = false;
977 result = EnableNonClientDpiScaling(hwnd) != FALSE;
978 if (!result) {
979 const DWORD errorCode = GetLastError();
980 qErrnoWarning(int(errorCode), "EnableNonClientDpiScaling() failed for HWND %p (%lu)",
981 hwnd, errorCode);
982 }
983 }
984 return result;
985}
986
995 WPARAM wParam, LPARAM lParam,
996 LRESULT *result,
997 QWindowsWindow **platformWindowPtr)
998{
999 *result = 0;
1000
1001 MSG msg;
1002 msg.hwnd = hwnd; // re-create MSG structure
1003 msg.message = message;
1004 msg.wParam = wParam;
1005 msg.lParam = lParam;
1006 msg.time = GetMessageTime();
1007 msg.pt.x = msg.pt.y = 0;
1009 msg.pt.x = GET_X_LPARAM(lParam);
1010 msg.pt.y = GET_Y_LPARAM(lParam);
1011 // For non-client-area messages, these are screen coordinates (as expected
1012 // in the MSG structure), otherwise they are client coordinates.
1013 if (!(et & QtWindows::NonClientEventFlag)) {
1014 clientToScreen(msg.hwnd, &msg.pt);
1015 }
1016 } else {
1017 GetCursorPos(&msg.pt);
1018 }
1019
1020 QWindowsWindow *platformWindow = findPlatformWindow(hwnd);
1021 *platformWindowPtr = platformWindow;
1022
1023 // Run the native event filters. QTBUG-67095: Exclude input messages which are sent
1024 // by QEventDispatcherWin32::processEvents()
1025 if (!isInputMessage(msg.message) && filterNativeEvent(&msg, result))
1026 return true;
1027
1028 if (platformWindow && filterNativeEvent(platformWindow->window(), &msg, result))
1029 return true;
1030
1033 // Disable IME assuming this is a special implementation hooking into keyboard input.
1034 // "Real" IME implementations should use a native event filter intercepting IME events.
1035 if (!windowsInputContext) {
1036 QWindowsInputContext::setWindowsImeEnabled(platformWindow, false);
1037 return false;
1038 }
1039 switch (et) {
1041 return windowsInputContext->startComposition(hwnd);
1043 return windowsInputContext->composition(hwnd, lParam);
1045 return windowsInputContext->endComposition(hwnd);
1047 return windowsInputContext->handleIME_Request(wParam, lParam, result);
1048 default:
1049 break;
1050 }
1051 } // InputMethodEventFlag
1052
1053 switch (et) {
1056 return sessionManagerInteractionBlocked() || d->m_mouseHandler.translateGestureEvent(platformWindow->window(), hwnd, et, msg, result);
1057 break;
1060 // TODO: Release/regrab mouse if a popup has mouse grab.
1061 return false;
1063 if (platformWindow && !platformWindow->testFlag(QWindowsWindow::WithinDestroy)) {
1064 qWarning() << "External WM_DESTROY received for " << platformWindow->window()
1065 << ", parent: " << platformWindow->window()->parent()
1066 << ", transient parent: " << platformWindow->window()->transientParent();
1067 }
1068 return false;
1070 return false;
1071 case QtWindows::CursorEvent: // Sent to windows that do not have capture (see QTBUG-58590).
1074 return true;
1075 }
1076 break;
1078 return false;
1080#if QT_CONFIG(accessibility)
1081 return QWindowsUiaAccessibility::handleWmGetObject(hwnd, wParam, lParam, result);
1082#else
1083 return false;
1084#endif
1087 // Only refresh the window theme if the user changes the personalize settings.
1088 if ((wParam == 0) && (lParam != 0) // lParam sometimes may be NULL.
1089 && (wcscmp(reinterpret_cast<LPCWSTR>(lParam), L"ImmersiveColorSet") == 0)) {
1091 }
1093 }
1094 default:
1095 break;
1096 }
1097
1098 // Before CreateWindowEx() returns, some events are sent,
1099 // for example WM_GETMINMAXINFO asking for size constraints for top levels.
1100 // Pass on to current creation context
1101 if (!platformWindow && !d->m_creationContext.isNull()) {
1102 switch (et) {
1104 d->m_creationContext->applyToMinMaxInfo(reinterpret_cast<MINMAXINFO *>(lParam));
1105 return true;
1107 d->m_creationContext->obtainedSize = QSize(LOWORD(lParam), HIWORD(lParam));
1108 return true;
1110 d->m_creationContext->obtainedPos = QPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
1111 return true;
1114 // DPI aware V2 processes always have NonClientDpiScaling enabled
1115 // and there is no need to make an API call to manually enable.
1117 enableNonClientDpiScaling(msg.hwnd);
1118 }
1119 return false;
1125 default:
1126 break;
1127 }
1128 }
1129 if (platformWindow) {
1130 // Suppress events sent during DestroyWindow() for native children.
1131 if (platformWindow->testFlag(QWindowsWindow::WithinDestroy))
1132 return false;
1134 qCDebug(lcQpaEvents) << "Event window: " << platformWindow->window();
1135 } else {
1136 qWarning("%s: No Qt Window found for event 0x%x (%s), hwnd=0x%p.",
1137 __FUNCTION__, message,
1139 return false;
1140 }
1141
1142 switch (et) {
1145 break;
1146 // See if there are any touch devices added
1147 if (wParam == DBT_DEVNODES_CHANGED)
1148 initTouch();
1149 break;
1152 wic->handleInputLanguageChanged(wParam, lParam);
1153 Q_FALLTHROUGH();
1159 return sessionManagerInteractionBlocked() || d->m_keyMapper.translateKeyEvent(platformWindow->window(), hwnd, msg, result);
1162 return true;
1163 if (QWindowsPopupMenu::notifyAboutToShow(reinterpret_cast<HMENU>(wParam)))
1164 return true;
1165 if (platformWindow == nullptr || platformWindow->menuBar() == nullptr)
1166 return false;
1167 return platformWindow->menuBar()->notifyAboutToShow(reinterpret_cast<HMENU>(wParam));
1170 return true;
1171 if (QWindowsPopupMenu::notifyTriggered(LOWORD(wParam)))
1172 return true;
1173 if (platformWindow == nullptr || platformWindow->menuBar() == nullptr)
1174 return false;
1175 return platformWindow->menuBar()->notifyTriggered(LOWORD(wParam));
1177 platformWindow->handleMoved();
1178 return true;
1180 platformWindow->handleResized(static_cast<int>(wParam), lParam);
1181 return true;
1183 platformWindow->getSizeHints(reinterpret_cast<MINMAXINFO *>(lParam));
1184 return true;// maybe available on some SDKs revisit WM_NCCALCSIZE
1186 return QWindowsGeometryHint::handleCalculateSize(platformWindow->customMargins(), msg, result);
1188 return platformWindow->handleNonClientHitTest(QPoint(msg.pt.x, msg.pt.y), result);
1190 return platformWindow->handleGeometryChanging(&msg);
1192 return platformWindow->handleWmPaint(hwnd, message, wParam, lParam, result);
1194 if (!platformWindow->frameStrutEventsEnabled())
1195 break;
1197 return sessionManagerInteractionBlocked() || d->m_pointerHandler.translateMouseEvent(platformWindow->window(), hwnd, et, msg, result);
1198 else
1199 return sessionManagerInteractionBlocked() || d->m_mouseHandler.translateMouseEvent(platformWindow->window(), hwnd, et, msg, result);
1201 if (!platformWindow->frameStrutEventsEnabled())
1202 break;
1204 return sessionManagerInteractionBlocked() || d->m_pointerHandler.translatePointerEvent(platformWindow->window(), hwnd, et, msg, result);
1205 break;
1207 platformWindow->setFlag(QWindowsWindow::ResizeMoveActive);
1208 if (!IsZoomed(hwnd))
1209 platformWindow->updateRestoreGeometry();
1210 return true;
1212 platformWindow->clearFlag(QWindowsWindow::ResizeMoveActive);
1213 platformWindow->checkForScreenChanged();
1214 handleExitSizeMove(platformWindow->window());
1215 if (!IsZoomed(hwnd))
1216 platformWindow->updateRestoreGeometry();
1217 return true;
1220 return sessionManagerInteractionBlocked() || d->m_mouseHandler.translateScrollEvent(platformWindow->window(), hwnd, msg, result);
1221 break;
1225 {
1226 QWindow *window = platformWindow->window();
1227 while (window && (window->flags() & Qt::WindowTransparentForInput))
1228 window = window->parent();
1229 if (!window)
1230 return false;
1233 else
1235 }
1236 break;
1239 return sessionManagerInteractionBlocked() || d->m_mouseHandler.translateTouchEvent(platformWindow->window(), hwnd, et, msg, result);
1240 break;
1243 return sessionManagerInteractionBlocked() || d->m_pointerHandler.translatePointerEvent(platformWindow->window(), hwnd, et, msg, result);
1244 break;
1245 case QtWindows::FocusInEvent: // see QWindowsWindow::requestActivateWindow().
1247 handleFocusEvent(et, platformWindow);
1248 return true;
1249 case QtWindows::ShowEventOnParentRestoring: // QTBUG-40696, prevent Windows from re-showing hidden transient children (dialogs).
1250 if (!platformWindow->window()->isVisible()) {
1251 *result = 0;
1252 return true;
1253 }
1254 break;
1256 platformWindow->handleHidden();
1257 return false;// Indicate transient children should be hidden by windows (SW_PARENTCLOSING)
1259 QWindowSystemInterface::handleCloseEvent(platformWindow->window());
1260 return true;
1262 QWindowsThemeCache::clearThemeCache(platformWindow->handle());
1263 // Switch from Aero to Classic changes margins.
1265 theme->windowsThemeChanged(platformWindow->window());
1266 return true;
1267 }
1269 platformWindow->handleCompositionSettingsChanged();
1270 return true;
1272 if (platformWindow->window()->flags() & Qt::WindowDoesNotAcceptFocus) {
1273 *result = LRESULT(MA_NOACTIVATE);
1274 return true;
1275 }
1276#if QT_CONFIG(tabletevent)
1277 if (!d->m_tabletSupport.isNull())
1278 d->m_tabletSupport->notifyActivate();
1279#endif // QT_CONFIG(tabletevent)
1280 if (platformWindow->testFlag(QWindowsWindow::BlockedByModal))
1281 if (const QWindow *modalWindow = QGuiApplication::modalWindow()) {
1282 QWindowsWindow *platformWindow = QWindowsWindow::windowsWindowOf(modalWindow);
1283 Q_ASSERT(platformWindow);
1284 platformWindow->alertWindow();
1285 }
1286 break;
1289 if (platformWindow->window()->flags() & Qt::WindowDoesNotAcceptFocus) {
1290 *result = LRESULT(MA_NOACTIVATE);
1291 return true;
1292 }
1293 break;
1294#ifndef QT_NO_CONTEXTMENU
1296 return handleContextMenuEvent(platformWindow->window(), msg);
1297#endif
1299#ifndef QT_NO_WHATSTHIS
1300 QWindowSystemInterface::handleEnterWhatsThisEvent();
1301 return true;
1302#endif
1303 } break;
1305 platformWindow->handleDpiScaledSize(wParam, lParam, result);
1306 return true;
1308 platformWindow->handleDpiChanged(hwnd, wParam, lParam);
1309 return true;
1311 platformWindow->handleDpiChangedAfterParent(hwnd);
1312 return true;
1313#if QT_CONFIG(sessionmanager)
1315 QWindowsSessionManager *sessionManager = platformSessionManager();
1316 if (sessionManager->isActive()) { // bogus message from windows
1317 *result = sessionManager->wasCanceled() ? 0 : 1;
1318 return true;
1319 }
1320
1321 sessionManager->setActive(true);
1322 sessionManager->blocksInteraction();
1323 sessionManager->clearCancellation();
1324
1325 auto *qGuiAppPriv = static_cast<QGuiApplicationPrivate*>(QObjectPrivate::get(qApp));
1326 qGuiAppPriv->commitData();
1327
1328 if (lParam & ENDSESSION_LOGOFF)
1329 fflush(nullptr);
1330
1331 *result = sessionManager->wasCanceled() ? 0 : 1;
1332 return true;
1333 }
1335 QWindowsSessionManager *sessionManager = platformSessionManager();
1336
1337 sessionManager->setActive(false);
1338 sessionManager->allowsInteraction();
1339 const bool endsession = wParam != 0;
1340
1341 // we receive the message for each toplevel window included internal hidden ones,
1342 // but the aboutToQuit signal should be emitted only once.
1343 auto *qGuiAppPriv = static_cast<QGuiApplicationPrivate*>(QObjectPrivate::get(qApp));
1344 if (endsession && !qGuiAppPriv->aboutToQuitEmitted) {
1345 qGuiAppPriv->aboutToQuitEmitted = true;
1346 int index = QGuiApplication::staticMetaObject.indexOfSignal("aboutToQuit()");
1347 qApp->qt_metacall(QMetaObject::InvokeMetaMethod, index, nullptr);
1348 // since the process will be killed immediately quit() has no real effect
1350 }
1351 return true;
1352 }
1353#endif // !defined(QT_NO_SESSIONMANAGER)
1355 // Apply application badge if this is the first time we have a taskbar
1356 // button, or after Explorer restart.
1357 QWindowsIntegration::instance()->updateApplicationBadge();
1358 break;
1359 default:
1360 break;
1361 }
1362 return false;
1363}
1364
1365/* Compress activation events. If the next focus window is already known
1366 * at the time the current one receives focus-out, pass that to
1367 * QWindowSystemInterface instead of sending 0 and ignore its consecutive
1368 * focus-in event.
1369 * This helps applications that do handling in focus-out events. */
1370void QWindowsContext::handleFocusEvent(QtWindows::WindowsEventType et,
1371 QWindowsWindow *platformWindow)
1372{
1373 QWindow *nextActiveWindow = nullptr;
1374 if (et == QtWindows::FocusInEvent) {
1375 QWindow *topWindow = QWindowsWindow::topLevelOf(platformWindow->window());
1376 QWindow *modalWindow = nullptr;
1377 if (QGuiApplicationPrivate::instance()->isWindowBlocked(topWindow, &modalWindow) && topWindow != modalWindow) {
1378 modalWindow->requestActivate();
1379 return;
1380 }
1381 // QTBUG-32867: Invoking WinAPI SetParent() can cause focus-in for the
1382 // window which is not desired for native child widgets.
1383 if (platformWindow->testFlag(QWindowsWindow::WithinSetParent)) {
1384 QWindow *currentFocusWindow = QGuiApplication::focusWindow();
1385 if (currentFocusWindow && currentFocusWindow != platformWindow->window()) {
1386 currentFocusWindow->requestActivate();
1387 return;
1388 }
1389 }
1390 nextActiveWindow = platformWindow->window();
1391 } else {
1392 // Focus out: Is the next window known and different
1393 // from the receiving the focus out.
1394 if (const HWND nextActiveHwnd = GetFocus())
1395 if (QWindowsWindow *nextActivePlatformWindow = findClosestPlatformWindow(nextActiveHwnd))
1396 if (nextActivePlatformWindow != platformWindow)
1397 nextActiveWindow = nextActivePlatformWindow->window();
1398 }
1399 if (nextActiveWindow != d->m_lastActiveWindow) {
1400 d->m_lastActiveWindow = nextActiveWindow;
1402 }
1403}
1404
1405#ifndef QT_NO_CONTEXTMENU
1406bool QWindowsContext::handleContextMenuEvent(QWindow *window, const MSG &msg)
1407{
1408 bool mouseTriggered = false;
1409 QPoint globalPos;
1410 QPoint pos;
1411 if (msg.lParam != int(0xffffffff)) {
1412 mouseTriggered = true;
1413 globalPos.setX(msg.pt.x);
1414 globalPos.setY(msg.pt.y);
1415 pos = QWindowsGeometryHint::mapFromGlobal(msg.hwnd, globalPos);
1416
1417 RECT clientRect;
1418 if (GetClientRect(msg.hwnd, &clientRect)) {
1419 if (pos.x() < clientRect.left || pos.x() >= clientRect.right ||
1420 pos.y() < clientRect.top || pos.y() >= clientRect.bottom)
1421 {
1422 // This is the case that user has right clicked in the window's caption,
1423 // We should call DefWindowProc() to display a default shortcut menu
1424 // instead of sending a Qt window system event.
1425 return false;
1426 }
1427 }
1428 }
1429
1430 QWindowSystemInterface::handleContextMenuEvent(window, mouseTriggered, pos, globalPos,
1431 keyMapper()->queryKeyboardModifiers());
1432 return true;
1433}
1434#endif
1435
1436void QWindowsContext::handleExitSizeMove(QWindow *window)
1437{
1438 // Windows can be moved/resized by:
1439 // 1) User moving a window by dragging the title bar: Causes a sequence
1440 // of WM_NCLBUTTONDOWN, WM_NCMOUSEMOVE but no WM_NCLBUTTONUP,
1441 // leaving the left mouse button 'pressed'
1442 // 2) User choosing Resize/Move from System menu and using mouse/cursor keys:
1443 // No mouse events are received
1444 // 3) Programmatically via QSizeGrip calling QPlatformWindow::startSystemResize/Move():
1445 // Mouse is left in pressed state after press on size grip (inside window),
1446 // no further mouse events are received
1447 // For cases 1,3, intercept WM_EXITSIZEMOVE to sync the buttons.
1448 const Qt::MouseButtons currentButtons = QWindowsMouseHandler::queryMouseButtons();
1449 const Qt::MouseButtons appButtons = QGuiApplication::mouseButtons();
1450 if (currentButtons == appButtons)
1451 return;
1452 const Qt::KeyboardModifiers keyboardModifiers = keyMapper()->queryKeyboardModifiers();
1453 const QPoint globalPos = QWindowsCursor::mousePosition();
1454 const QPlatformWindow *platWin = window->handle();
1455 const QPoint localPos = platWin->mapFromGlobal(globalPos);
1456 const QEvent::Type type = platWin->geometry().contains(globalPos)
1459 if (appButtons.testFlag(button) && !currentButtons.testFlag(button)) {
1461 currentButtons, button, type, keyboardModifiers);
1462 }
1463 }
1466 else
1468}
1469
1471{
1472 return d->m_asyncExpose;
1473}
1474
1479
1480DWORD QWindowsContext::readAdvancedExplorerSettings(const wchar_t *subKey, DWORD defaultValue)
1481{
1482 const auto value =
1483 QWinRegistryKey(HKEY_CURRENT_USER,
1484 LR"(Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced)")
1485 .dwordValue(subKey);
1486 return value.second ? value.first : defaultValue;
1487}
1488
1489static inline bool isEmptyRect(const RECT &rect)
1490{
1491 return rect.right - rect.left == 0 && rect.bottom - rect.top == 0;
1492}
1493
1494static inline QMargins marginsFromRects(const RECT &frame, const RECT &client)
1495{
1496 return QMargins(client.left - frame.left, client.top - frame.top,
1497 frame.right - client.right, frame.bottom - client.bottom);
1498}
1499
1500static RECT rectFromNcCalcSize(UINT message, WPARAM wParam, LPARAM lParam, int n)
1501{
1502 RECT result = {0, 0, 0, 0};
1503 if (message == WM_NCCALCSIZE && wParam)
1504 result = reinterpret_cast<const NCCALCSIZE_PARAMS *>(lParam)->rgrc[n];
1505 return result;
1506}
1507
1508static inline bool isMinimized(HWND hwnd)
1509{
1510 WINDOWPLACEMENT windowPlacement;
1511 windowPlacement.length = sizeof(WINDOWPLACEMENT);
1512 return GetWindowPlacement(hwnd, &windowPlacement) && windowPlacement.showCmd == SW_SHOWMINIMIZED;
1513}
1514
1515static inline bool isTopLevel(HWND hwnd)
1516{
1517 return (GetWindowLongPtr(hwnd, GWL_STYLE) & WS_CHILD) == 0;
1518}
1519
1528extern "C" LRESULT QT_WIN_CALLBACK qWindowsWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
1529{
1530 LRESULT result;
1531 const QtWindows::WindowsEventType et = windowsEventType(message, wParam, lParam);
1532 QWindowsWindow *platformWindow = nullptr;
1533 const RECT ncCalcSizeFrame = rectFromNcCalcSize(message, wParam, lParam, 0);
1534 const bool handled = QWindowsContext::instance()->windowsProc(hwnd, message, et, wParam, lParam, &result, &platformWindow);
1535 if (QWindowsContext::verbose > 1 && lcQpaEvents().isDebugEnabled()) {
1536 if (const char *eventName = QWindowsGuiEventDispatcher::windowsMessageName(message)) {
1537 qCDebug(lcQpaEvents).nospace() << "EVENT: hwd=" << hwnd << ' ' << eventName
1538 << " msg=0x" << Qt::hex << message << " et=0x" << et << Qt::dec << " wp="
1539 << int(wParam) << " at " << GET_X_LPARAM(lParam) << ','
1540 << GET_Y_LPARAM(lParam) << " handled=" << handled;
1541 }
1542 }
1543 if (!handled)
1544 result = DefWindowProc(hwnd, message, wParam, lParam);
1545
1546 // Capture WM_NCCALCSIZE on top level windows and obtain the window margins by
1547 // subtracting the rectangles before and after processing. This will correctly
1548 // capture client code overriding the message and allow for per-monitor margins
1549 // for High DPI (QTBUG-53255, QTBUG-40578).
1550 if (message == WM_NCCALCSIZE && !isEmptyRect(ncCalcSizeFrame) && isTopLevel(hwnd) && !isMinimized(hwnd)) {
1551 const QMargins margins =
1552 marginsFromRects(ncCalcSizeFrame, rectFromNcCalcSize(message, wParam, lParam, 0));
1553 if (margins.left() >= 0) {
1554 if (platformWindow) {
1555 qCDebug(lcQpaWindow) << __FUNCTION__ << "WM_NCCALCSIZE for" << hwnd << margins;
1556 platformWindow->setFullFrameMargins(margins);
1557 } else {
1558 const QSharedPointer<QWindowCreationContext> ctx = QWindowsContext::instance()->windowCreationContext();
1559 if (!ctx.isNull())
1560 ctx->margins = margins;
1561 }
1562 }
1563 }
1564 return result;
1565}
1566
1567
1568static inline QByteArray nativeEventType() { return QByteArrayLiteral("windows_generic_MSG"); }
1569
1570// Send to QAbstractEventDispatcher
1572{
1574 qintptr filterResult = 0;
1575 if (dispatcher && dispatcher->filterNativeEvent(nativeEventType(), msg, &filterResult)) {
1576 *result = LRESULT(filterResult);
1577 return true;
1578 }
1579 return false;
1580}
1581
1582// Send to QWindowSystemInterface
1584{
1585 qintptr filterResult = 0;
1586 if (QWindowSystemInterface::handleNativeEvent(window, nativeEventType(), msg, &filterResult)) {
1587 *result = LRESULT(filterResult);
1588 return true;
1589 }
1590 return false;
1591}
1592
static JNINativeMethod methods[]
static QAbstractEventDispatcher * instance(QThread *thread=nullptr)
Returns a pointer to the event dispatcher object for the specified thread.
bool filterNativeEvent(const QByteArray &eventType, void *message, qintptr *result)
Sends message through the event filters that were set by installNativeEventFilter().
\inmodule QtCore
Definition qbytearray.h:57
static void quit()
\threadsafe
\inmodule QtCore
\inmodule QtCore
Type
This enum type defines the valid event types in Qt.
Definition qcoreevent.h:51
@ NonClientAreaMouseButtonRelease
Definition qcoreevent.h:214
@ MouseButtonRelease
Definition qcoreevent.h:61
static QGuiApplicationPrivate * instance()
static QWindowList topLevelWindows()
Returns a list of the top-level windows in the application.
static QWindow * modalWindow()
Returns the most recently shown modal window.
static QWindow * focusWindow()
Returns the QWindow that receives events tied to focus, such as key events.
static Qt::MouseButtons mouseButtons()
Returns the current state of the buttons on the mouse.
const_iterator cbegin() const noexcept
Definition qhash.h:1214
iterator find(const Key &key)
Returns an iterator pointing to the item with the key in the hash.
Definition qhash.h:1291
iterator erase(const_iterator it)
Definition qhash.h:1233
T value(const Key &key) const noexcept
Definition qhash.h:1054
iterator end() noexcept
Returns an \l{STL-style iterators}{STL-style iterator} pointing to the imaginary item after the last ...
Definition qhash.h:1216
const_iterator cend() const noexcept
Definition qhash.h:1218
iterator insert(const Key &key, const T &value)
Inserts a new item with the key and a value of value.
Definition qhash.h:1303
static bool isDebugBuild() noexcept Q_DECL_CONST_FUNCTION
static void setFilterRules(const QString &rules)
Configures which categories and message types should be enabled through a set of rules.
\inmodule QtCore
Definition qmargins.h:24
constexpr int left() const noexcept
Returns the left margin.
Definition qmargins.h:106
Native interface to QPlatformWindow. \inmodule QtGui.
static QObjectPrivate * get(QObject *o)
Definition qobject_p.h:150
static OpenGLModuleType openGLModuleType()
Returns the underlying OpenGL implementation type.
virtual Qt::KeyboardModifiers queryKeyboardModifiers() const
The QPlatformScreen class provides an abstraction for visual displays.
The QPlatformWindow class provides an abstraction for top-level windows.
QWindow * window() const
Returns the window which belongs to the QPlatformWindow.
\inmodule QtCore\reentrant
Definition qpoint.h:25
constexpr void setY(int y) noexcept
Sets the y coordinate of this point to the given y coordinate.
Definition qpoint.h:145
constexpr void setX(int x) noexcept
Sets the x coordinate of this point to the given x coordinate.
Definition qpoint.h:140
void clear()
Definition qset.h:61
bool contains(const T &value) const
Definition qset.h:71
iterator insert(const T &value)
Definition qset.h:155
bool isNull() const noexcept
Returns true if this object refers to \nullptr.
\inmodule QtCore
Definition qsize.h:25
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
static QString fromLocal8Bit(QByteArrayView ba)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qstring.cpp:5949
@ OpenGLSurface
Definition qsurface.h:32
\inmodule QtCore
static QUuid createUuid()
On any platform other than Windows, this function returns a new UUID with variant QUuid::DCE and vers...
Definition quuid.cpp:997
QScreen * screen() const
Returns the screen the widget is on.
Definition qwidget.cpp:2496
std::pair< DWORD, bool > dwordValue(QStringView subKey) const
static bool handleNativeEvent(QWindow *window, const QByteArray &eventType, void *message, qintptr *result)
Passes a native event identified by eventType to the window.
static void handleFocusWindowChanged(QWindow *window, Qt::FocusReason r=Qt::OtherFocusReason)
static void handleContextMenuEvent(QWindow *window, bool mouseTriggered, const QPoint &pos, const QPoint &globalPos, Qt::KeyboardModifiers modifiers)
static bool handleMouseEvent(QWindow *window, const QPointF &local, const QPointF &global, Qt::MouseButtons state, Qt::MouseButton button, QEvent::Type type, Qt::KeyboardModifiers mods=Qt::NoModifier, Qt::MouseEventSource source=Qt::MouseEventNotSynthesized)
static void registerInputDevice(const QInputDevice *device)
static bool handleCloseEvent(QWindow *window)
\inmodule QtGui
Definition qwindow.h:63
Singleton container for all relevant information.
QSharedPointer< QWindowCreationContext > windowCreationContext() const
QWindowsScreenManager & screenManager()
static QString classNamePrefix()
QWindowsWindow * findClosestPlatformWindow(HWND) const
QWindow * findWindow(HWND) const
bool asyncExpose() const
void addWindow(HWND, QWindowsWindow *w)
static bool systemParametersInfoForScreen(unsigned action, unsigned param, void *out, const QPlatformScreen *screen=nullptr)
static DWORD readAdvancedExplorerSettings(const wchar_t *subKey, DWORD defaultValue)
static bool setProcessDpiAwareness(QtWindows::DpiAwareness dpiAwareness)
HDC displayContext() const
static bool shouldHaveNonClientDpiScaling(const QWindow *window)
QWindowsTabletSupport * tabletSupport() const
static bool systemParametersInfoForWindow(unsigned action, unsigned param, void *out, const QPlatformWindow *win=nullptr)
QString registerWindowClass(const QWindow *w)
static void setTabletAbsoluteRange(int a)
static void forceNcCalcSize(HWND hwnd)
QWindowsWindow * findPlatformWindowAt(HWND parent, const QPoint &screenPoint, unsigned cwex_flags) const
void setKeyGrabber(QWindow *hwnd)
static bool nonClientMetrics(NONCLIENTMETRICS *ncm, unsigned dpi=0)
HWND createDummyWindow(const QString &classNameIn, const wchar_t *windowName, WNDPROC wndProc=nullptr, DWORD style=WS_OVERLAPPED)
Convenience to create a non-visible, message-only dummy window for example used as clipboard watcher ...
void setAsyncExpose(bool value)
QSharedPointer< QWindowCreationContext > setWindowCreationContext(const QSharedPointer< QWindowCreationContext > &ctx)
static QtWindows::DpiAwareness windowDpiAwareness(HWND hwnd)
bool windowsProc(HWND hwnd, UINT message, QtWindows::WindowsEventType et, WPARAM wParam, LPARAM lParam, LRESULT *result, QWindowsWindow **platformWindowPtr)
Main windows procedure registered for windows.
unsigned systemInfo() const
static QtWindows::DpiAwareness processDpiAwareness()
QWindowsWindow * findPlatformWindow(HWND) const
QWindow * keyGrabber() const
QWindow * windowUnderMouse() const
QPlatformKeyMapper * keyMapper() const
bool useRTLExtensions() const
bool initPointer(unsigned integrationOptions)
static bool systemParametersInfo(unsigned action, unsigned param, void *out, unsigned dpi=0)
QWindowsMimeRegistry & mimeConverter() const
static bool nonClientMetricsForWindow(NONCLIENTMETRICS *ncm, const QPlatformWindow *win=nullptr)
static bool isSessionLocked()
int screenDepth() const
bool initPowerNotificationHandler()
HandleBaseWindowHash & windows()
static QWindowsContext * instance()
static bool nonClientMetricsForScreen(NONCLIENTMETRICS *ncm, const QPlatformScreen *screen=nullptr)
static bool filterNativeEvent(MSG *msg, LRESULT *result)
void setDetectAltGrModifier(bool a)
static bool hasOverrideCursor()
static QPoint mousePosition()
static void enforceOverrideCursor()
static const char * windowsMessageName(UINT msg)
Windows Input context implementation.
static void setWindowsImeEnabled(QWindowsWindow *platformWindow, bool enabled)
static QWindowsIntegration * instance()
Translates Windows keys to QWindowSystemInterface events.
bool translateKeyEvent(QWindow *widget, HWND hwnd, const MSG &msg, LRESULT *result)
To be called from the window procedure.
void setUseRTLExtensions(bool e)
QWindow * keyGrabber() const
bool useRTLExtensions() const
void setKeyGrabber(QWindow *w)
void setDetectAltGrModifier(bool a)
Windows native menu bar.
Manages the list of QWindowsMimeConverter instances.
Windows mouse handler.
static Qt::MouseButtons queryMouseButtons()
bool translateScrollEvent(QWindow *window, HWND hwnd, MSG msg, LRESULT *result)
bool translateTouchEvent(QWindow *widget, HWND hwnd, QtWindows::WindowsEventType t, MSG msg, LRESULT *result)
void setTouchDevice(const QPointingDevicePtr &d)
QWindow * windowUnderMouse() const
bool translateGestureEvent(QWindow *window, HWND hwnd, QtWindows::WindowsEventType, MSG msg, LRESULT *)
const QPointingDevicePtr & touchDevice() const
bool translateMouseEvent(QWindow *widget, HWND hwnd, QtWindows::WindowsEventType t, MSG msg, LRESULT *result)
QWindow * windowUnderMouse() const
static QPointingDevicePtr createTouchDevice(bool mouseEmulation)
const QPointingDevicePtr & touchDevice() const
bool translatePointerEvent(QWindow *window, HWND hwnd, QtWindows::WindowsEventType et, MSG msg, LRESULT *result)
bool translateMouseEvent(QWindow *window, HWND hwnd, QtWindows::WindowsEventType et, MSG msg, LRESULT *result)
void setTouchDevice(const QPointingDevicePtr &d)
static bool notifyAboutToShow(HMENU hmenu)
static bool notifyTriggered(uint id)
Manages a list of QWindowsScreen.
bool handleScreenChanges()
Synchronizes the screen list, adds new screens, removes deleted ones and propagates resolution change...
Tablet support for Windows.
static void setAbsoluteRange(int a)
static QWindowsTabletSupport * create()
static void handleSettingsChanged()
static QWindowsTheme * instance()
Raster or OpenGL Window.
static QWindowsWindow * windowsWindowOf(const QWindow *w)
bool testFlag(unsigned f) const
static void settingsChanged()
static bool handleGeometryChangingMessage(MSG *message, const QWindow *qWindow, const QMargins &marginsDp)
static const char * embeddedNativeParentHandleProperty
static QWindow * topLevelOf(QWindow *w)
@ WithinSetParent
Automatic mouse capture on button press.
void setFullFrameMargins(const QMargins &newMargins)
EGLContext ctx
QString str
[2]
QPushButton * button
[2]
QSet< QString >::iterator it
rect
[4]
void qErrnoWarning(const char *msg,...)
Combined button and popup list for selecting options.
Q_GUI_EXPORT void clearThemeCache(HWND hwnd)
WindowsEventType
Enumerations for WM_XX events.
@ PointerActivateWindowEvent
@ InputMethodEndCompositionEvent
@ QueryEndSessionApplicationEvent
@ ShowEventOnParentRestoring
@ InputMethodCompositionEvent
@ InputMethodOpenCandidateWindowEvent
@ MouseActivateWindowEvent
@ DpiChangedAfterParentEvent
@ InputMethodStartCompositionEvent
@ EndSessionApplicationEvent
@ CompositionSettingsChanged
@ InputMethodCloseCandidateWindowEvent
@ AccessibleObjectFromWindowRequest
@ WindowMinimized
Definition qnamespace.h:253
QTextStream & hex(QTextStream &stream)
Calls QTextStream::setIntegerBase(16) on stream and returns stream.
MouseButton
Definition qnamespace.h:56
@ LeftButton
Definition qnamespace.h:58
@ RightButton
Definition qnamespace.h:59
@ MiddleButton
Definition qnamespace.h:60
QTextStream & dec(QTextStream &stream)
Calls QTextStream::setIntegerBase(10) on stream and returns stream.
@ WindowDoesNotAcceptFocus
Definition qnamespace.h:236
@ MSWindowsOwnDC
Definition qnamespace.h:222
@ ToolTip
Definition qnamespace.h:213
@ Popup
Definition qnamespace.h:211
@ WindowType_Mask
Definition qnamespace.h:220
@ Dialog
Definition qnamespace.h:208
@ NoDropShadowWindowHint
Definition qnamespace.h:244
@ WindowTransparentForInput
Definition qnamespace.h:234
@ Tool
Definition qnamespace.h:212
@ WindowSystemMenuHint
Definition qnamespace.h:227
@ ActiveWindowFocusReason
Definition brush.cpp:5
static void * context
#define QByteArrayLiteral(str)
Definition qbytearray.h:52
#define Q_FALLTHROUGH()
#define qApp
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
#define WM_TOUCH
int qRound(qfloat16 d) noexcept
Definition qfloat16.h:327
#define qWarning
Definition qlogging.h:166
#define Q_LOGGING_CATEGORY(name,...)
#define qCWarning(category,...)
#define qCDebug(category,...)
const GLfloat * m
GLenum GLuint GLint level
GLfloat GLfloat GLfloat w
[0]
GLboolean GLboolean GLboolean GLboolean a
[7]
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLuint index
[2]
GLuint GLuint end
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLenum GLuint buffer
GLenum type
GLbitfield flags
GLuint GLsizei const GLchar * message
GLenum const GLint * param
GLuint name
GLfloat n
GLuint64EXT * result
[6]
GLfloat GLfloat p
[1]
GLenum GLenum GLenum input
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
#define qPrintable(string)
Definition qstring.h:1531
#define QStringLiteral(str)
#define CS_DROPSHADOW
Definition qt_windows.h:97
QScreen * screen
[1]
Definition main.cpp:29
Q_CORE_EXPORT QByteArray qgetenv(const char *varName)
#define Q_UNUSED(x)
#define DPI_AWARENESS_CONTEXT_UNAWARE
QtWindows::WindowsEventType windowsEventType(UINT message, WPARAM wParamIn, LPARAM lParamIn)
#define DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE
#define DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2
#define DPI_AWARENESS_CONTEXT_SYSTEM_AWARE
#define DPI_AWARENESS_CONTEXT_UNAWARE_GDISCALED
size_t quintptr
Definition qtypes.h:167
unsigned int uint
Definition qtypes.h:34
ptrdiff_t qintptr
Definition qtypes.h:166
struct tagMSG MSG
long HRESULT
LRESULT QT_WIN_CALLBACK qWindowsPowerWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
#define LANG_SYRIAC
static bool enableNonClientDpiScaling(HWND hwnd)
static bool isInputMessage(UINT m)
static DPI_AWARENESS_CONTEXT qtDpiAwarenessToDpiAwarenessContext(QtWindows::DpiAwareness dpiAwareness)
static bool useRTL_Extensions()
static bool sessionManagerInteractionBlocked()
static QWindowsInputContext * windowsInputContext()
static QtWindows::DpiAwareness dpiAwarenessContextToQtDpiAwareness(DPI_AWARENESS_CONTEXT context)
QDebug operator<<(QDebug d, QtWindows::DpiAwareness dpiAwareness)
static bool findPlatformWindowHelper(const POINT &screenPoint, unsigned cwexFlags, const QWindowsContext *context, HWND *hwnd, QWindowsWindow **result)
Find a child window at a screen point.
LRESULT QT_WIN_CALLBACK qWindowsWndProc(HWND, UINT, WPARAM, LPARAM)
static void clientToScreen(HWND hwnd, POINT *wP)
static void screenToClient(HWND hwnd, POINT *wP)
const char className[16]
[1]
Definition qwizard.cpp:100
QWidget * win
Definition settings.cpp:6
QTextStream out(stdout)
[7]
application x qt windows mime
[2]
QObject::connect nullptr
QLayoutItem * child
[0]
aWidget window() -> setWindowTitle("New Window Title")
[2]
QFrame frame
[0]
QHostInfo info
[0]
const QWindow * window
void applyToMinMaxInfo(MINMAXINFO *mmi) const
QWindowsMouseHandler m_mouseHandler
const HRESULT m_oleInitializeResult
QWindowsKeyMapper m_keyMapper
QSet< QString > m_registeredWindowClassNames
QSharedPointer< QWindowCreationContext > m_creationContext
QWindowsPointerHandler m_pointerHandler
QWindowsScreenManager m_screenManager
QWindowsMimeRegistry m_mimeConverter
QWindowsContext::HandleBaseWindowHash m_windows
static QPoint mapFromGlobal(const HWND hwnd, const QPoint &)
static bool handleCalculateSize(const QMargins &customMargins, const MSG &msg, LRESULT *result)