1 /****************************************************************************
3 ** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
6 ** This file is part of the plugins of the Qt Toolkit.
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia. For licensing terms and
14 ** conditions see http://qt.digia.com/licensing. For further information
15 ** use the contact form at http://qt.digia.com/contact-us.
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights. These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file. Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
40 ****************************************************************************/
42 #include "qwindowscontext.h"
43 #include "qwindowswindow.h"
44 #include "qwindowskeymapper.h"
45 #include "qwindowsguieventdispatcher.h"
46 #include "qwindowsmousehandler.h"
47 #include "qtwindowsglobal.h"
48 #include "qwindowsmime.h"
49 #include "qwindowsinputcontext.h"
50 #ifndef QT_NO_ACCESSIBILITY
51 #include "accessible/qwindowsaccessibility.h"
53 #include "qwindowsscreen.h"
54 #include "qwindowstheme.h"
56 #include <QtGui/QWindow>
57 #include <qpa/qwindowsysteminterface.h>
58 #include <qpa/qplatformnativeinterface.h>
59 #include <QtGui/QGuiApplication>
61 #include <QtCore/QSet>
62 #include <QtCore/QHash>
63 #include <QtCore/QStringList>
64 #include <QtCore/QDebug>
65 #include <QtCore/QSysInfo>
66 #include <QtCore/QScopedArrayPointer>
67 #include <QtCore/private/qsystemlibrary_p.h>
75 // Verbosity of components
76 int QWindowsContext::verboseIntegration = 0;
77 int QWindowsContext::verboseWindows = 0;
78 int QWindowsContext::verboseEvents = 0;
79 int QWindowsContext::verboseBackingStore = 0;
80 int QWindowsContext::verboseFonts = 0;
81 int QWindowsContext::verboseGL = 0;
82 int QWindowsContext::verboseOLE = 0;
83 int QWindowsContext::verboseInputMethods = 0;
84 int QWindowsContext::verboseDialogs = 0;
85 int QWindowsContext::verboseTheming = 0;
87 // Get verbosity of components from "foo:2,bar:3"
88 static inline int componentVerbose(const char *v, const char *keyWord)
90 if (const char *k = strstr(v, keyWord)) {
91 k += qstrlen(keyWord);
101 static inline bool hasTouchSupport(QSysInfo::WinVersion wv)
103 enum { QT_SM_DIGITIZER = 94, QT_NID_INTEGRATED_TOUCH = 0x1,
104 QT_NID_EXTERNAL_TOUCH = 0x02, QT_NID_MULTI_INPUT = 0x40 };
106 return wv < QSysInfo::WV_WINDOWS7 ? false :
107 (GetSystemMetrics(QT_SM_DIGITIZER) & (QT_NID_INTEGRATED_TOUCH | QT_NID_EXTERNAL_TOUCH | QT_NID_MULTI_INPUT)) != 0;
110 #if !defined(LANG_SYRIAC)
111 # define LANG_SYRIAC 0x5a
114 static inline bool useRTL_Extensions(QSysInfo::WinVersion ver)
116 // This is SDK dependent on CE so out of scope for now
117 if (QSysInfo::windowsVersion() & QSysInfo::WV_CE_based)
119 if ((ver & QSysInfo::WV_NT_based) && (ver >= QSysInfo::WV_VISTA)) {
120 // Since the IsValidLanguageGroup/IsValidLocale functions always return true on
121 // Vista, check the Keyboard Layouts for enabling RTL.
122 if (const UINT nLayouts = GetKeyboardLayoutList(0, 0)) {
123 QScopedArrayPointer<HKL> lpList(new HKL[nLayouts]);
124 GetKeyboardLayoutList(nLayouts, lpList.data());
125 for (UINT i = 0; i < nLayouts; ++i) {
126 switch (PRIMARYLANGID((quintptr)lpList[i])) {
140 // Pre-NT: figure out whether a RTL language is installed
141 return IsValidLanguageGroup(LGRPID_ARABIC, LGRPID_INSTALLED)
142 || IsValidLanguageGroup(LGRPID_HEBREW, LGRPID_INSTALLED)
143 || IsValidLocale(MAKELCID(MAKELANGID(LANG_ARABIC, SUBLANG_DEFAULT), SORT_DEFAULT), LCID_INSTALLED)
144 || IsValidLocale(MAKELCID(MAKELANGID(LANG_HEBREW, SUBLANG_DEFAULT), SORT_DEFAULT), LCID_INSTALLED)
145 || IsValidLocale(MAKELCID(MAKELANGID(LANG_SYRIAC, SUBLANG_DEFAULT), SORT_DEFAULT), LCID_INSTALLED)
146 || IsValidLocale(MAKELCID(MAKELANGID(LANG_FARSI, SUBLANG_DEFAULT), SORT_DEFAULT), LCID_INSTALLED);
153 \class QWindowsUser32DLL
154 \brief Struct that contains dynamically resolved symbols of User32.dll.
156 The stub libraries shipped with the MinGW compiler miss some of the
157 functions. They need to be retrieved dynamically.
159 In addition, touch-related functions are available only from Windows onwards.
160 These need to resolved dynamically for Q_CC_MSVC as well.
162 \sa QWindowsShell32DLL
165 \ingroup qt-lighthouse-win
170 QWindowsUser32DLL::QWindowsUser32DLL() :
171 setLayeredWindowAttributes(0), updateLayeredWindow(0),
172 updateLayeredWindowIndirect(0),
174 registerTouchWindow(0), getTouchInputInfo(0), closeTouchInputHandle(0)
178 void QWindowsUser32DLL::init()
180 QSystemLibrary library(QStringLiteral("user32"));
181 // MinGW (g++ 3.4.5) accepts only C casts.
182 setLayeredWindowAttributes = (SetLayeredWindowAttributes)(library.resolve("SetLayeredWindowAttributes"));
183 updateLayeredWindow = (UpdateLayeredWindow)(library.resolve("UpdateLayeredWindow"));
184 if (!setLayeredWindowAttributes || !updateLayeredWindow)
185 qFatal("This version of Windows is not supported (User32.dll is missing the symbols 'SetLayeredWindowAttributes', 'UpdateLayeredWindow').");
187 updateLayeredWindowIndirect = (UpdateLayeredWindowIndirect)(library.resolve("UpdateLayeredWindowIndirect"));
188 isHungAppWindow = (IsHungAppWindow)library.resolve("IsHungAppWindow");
191 bool QWindowsUser32DLL::initTouch()
193 QSystemLibrary library(QStringLiteral("user32"));
194 registerTouchWindow = (RegisterTouchWindow)(library.resolve("RegisterTouchWindow"));
195 getTouchInputInfo = (GetTouchInputInfo)(library.resolve("GetTouchInputInfo"));
196 closeTouchInputHandle = (CloseTouchInputHandle)(library.resolve("CloseTouchInputHandle"));
197 return registerTouchWindow && getTouchInputInfo && getTouchInputInfo;
201 \class QWindowsShell32DLL
202 \brief Struct that contains dynamically resolved symbols of Shell32.dll.
204 The stub libraries shipped with the MinGW compiler miss some of the
205 functions. They need to be retrieved dynamically.
207 \sa QWindowsUser32DLL
210 \ingroup qt-lighthouse-win
213 QWindowsShell32DLL::QWindowsShell32DLL()
214 : sHCreateItemFromParsingName(0)
215 , sHGetStockIconInfo(0)
219 void QWindowsShell32DLL::init()
221 QSystemLibrary library(QStringLiteral("shell32"));
222 sHCreateItemFromParsingName = (SHCreateItemFromParsingName)(library.resolve("SHCreateItemFromParsingName"));
223 sHGetStockIconInfo = (SHGetStockIconInfo)library.resolve("SHGetStockIconInfo");
226 QWindowsUser32DLL QWindowsContext::user32dll;
227 QWindowsShell32DLL QWindowsContext::shell32dll;
229 #endif // !Q_OS_WINCE
231 QWindowsContext *QWindowsContext::m_instance = 0;
234 \class QWindowsContext
235 \brief Singleton container for all relevant information.
237 Holds state information formerly stored in \c qapplication_win.cpp.
240 \ingroup qt-lighthouse-win
243 typedef QHash<HWND, QWindowsWindow *> HandleBaseWindowHash;
245 struct QWindowsContextPrivate {
247 QWindowsContextPrivate();
249 unsigned m_systemInfo;
250 QSet<QString> m_registeredWindowClassNames;
251 HandleBaseWindowHash m_windows;
252 HDC m_displayContext;
253 const int m_defaultDPI;
254 QWindowsKeyMapper m_keyMapper;
255 QWindowsMouseHandler m_mouseHandler;
256 QWindowsMimeConverter m_mimeConverter;
257 QWindowsScreenManager m_screenManager;
258 QSharedPointer<QWindowCreationContext> m_creationContext;
259 const HRESULT m_oleInitializeResult;
260 const QByteArray m_eventType;
261 QWindow *m_lastActiveWindow;
265 QWindowsContextPrivate::QWindowsContextPrivate() :
267 m_displayContext(GetDC(0)),
268 m_defaultDPI(GetDeviceCaps(m_displayContext,LOGPIXELSY)),
269 m_oleInitializeResult(OleInitialize(NULL)),
270 m_eventType(QByteArrayLiteral("windows_generic_MSG")),
271 m_lastActiveWindow(0), m_asyncExpose(0)
274 QWindowsContext::user32dll.init();
275 QWindowsContext::shell32dll.init();
278 const QSysInfo::WinVersion ver = QSysInfo::windowsVersion();
280 if (hasTouchSupport(ver) && QWindowsContext::user32dll.initTouch())
281 m_systemInfo |= QWindowsContext::SI_SupportsTouch;
284 if (useRTL_Extensions(ver)) {
285 m_systemInfo |= QWindowsContext::SI_RTL_Extensions;
286 m_keyMapper.setUseRTLExtensions(true);
290 QWindowsContext::QWindowsContext() :
291 d(new QWindowsContextPrivate)
294 # pragma warning( disable : 4996 )
297 const QByteArray bv = qgetenv("QT_QPA_VERBOSE");
299 const char *v = bv.data();
300 QWindowsContext::verboseIntegration = componentVerbose(v, "integration");
301 QWindowsContext::verboseWindows = componentVerbose(v, "windows");
302 QWindowsContext::verboseEvents = componentVerbose(v, "events");
303 QWindowsContext::verboseBackingStore = componentVerbose(v, "backingstore");
304 QWindowsContext::verboseFonts = componentVerbose(v, "fonts");
305 QWindowsContext::verboseGL = componentVerbose(v, "gl");
306 QWindowsContext::verboseOLE = componentVerbose(v, "ole");
307 QWindowsContext::verboseInputMethods = componentVerbose(v, "im");
308 QWindowsContext::verboseDialogs = componentVerbose(v, "dialogs");
309 QWindowsContext::verboseTheming = componentVerbose(v, "theming");
313 QWindowsContext::~QWindowsContext()
315 unregisterWindowClasses();
316 if (d->m_oleInitializeResult == S_OK || d->m_oleInitializeResult == S_FALSE)
319 d->m_screenManager.clearScreens(); // Order: Potentially calls back to the windows.
323 QWindowsContext *QWindowsContext::instance()
328 unsigned QWindowsContext::systemInfo() const
330 return d->m_systemInfo;
333 bool QWindowsContext::useRTLExtensions() const
335 return d->m_keyMapper.useRTLExtensions();
338 QList<int> QWindowsContext::possibleKeys(const QKeyEvent *e) const
340 return d->m_keyMapper.possibleKeys(e);
343 void QWindowsContext::setWindowCreationContext(const QSharedPointer<QWindowCreationContext> &ctx)
345 d->m_creationContext = ctx;
348 int QWindowsContext::defaultDPI() const
350 return d->m_defaultDPI;
353 HDC QWindowsContext::displayContext() const
355 return d->m_displayContext;
358 QWindow *QWindowsContext::keyGrabber() const
360 return d->m_keyMapper.keyGrabber();
363 void QWindowsContext::setKeyGrabber(QWindow *w)
365 d->m_keyMapper.setKeyGrabber(w);
368 // Window class registering code (from qapplication_win.cpp)
369 // If 0 is passed as the widget pointer, register a window class
370 // for QWidget as default. This is used in QGLTemporaryContext
371 // during GL initialization, where we don't want to use temporary
372 // QWidgets or QGLWidgets, neither do we want to have separate code
373 // to register window classes.
375 QString QWindowsContext::registerWindowClass(const QWindow *w, bool isGL)
377 const Qt::WindowFlags flags = w ? w->windowFlags() : (Qt::WindowFlags)0;
378 const Qt::WindowFlags type = flags & Qt::WindowType_Mask;
382 QString cname = QStringLiteral("Qt5");
384 cname += QStringLiteral("QGLWindow");
385 style = CS_DBLCLKS|CS_OWNDC;
387 } else if (w && (flags & Qt::MSWindowsOwnDC)) {
388 cname += QStringLiteral("QWindowOwnDC");
389 style = CS_DBLCLKS|CS_OWNDC;
391 } else if (w && (type == Qt::Tool || type == Qt::ToolTip)) {
393 if (w->inherits("QTipLabel") || w->inherits("QAlphaWidget")) {
394 if ((QSysInfo::WindowsVersion >= QSysInfo::WV_XP
395 && (QSysInfo::WindowsVersion & QSysInfo::WV_NT_based))) {
396 style |= CS_DROPSHADOW;
398 cname += QStringLiteral("QToolTip");
400 cname += QStringLiteral("QTool");
402 style |= CS_SAVEBITS;
404 } else if (w && (type == Qt::Popup)) {
405 cname += QStringLiteral("QPopup");
406 style = CS_DBLCLKS|CS_SAVEBITS;
407 if ((QSysInfo::WindowsVersion >= QSysInfo::WV_XP
408 && (QSysInfo::WindowsVersion & QSysInfo::WV_NT_based)))
409 style |= CS_DROPSHADOW;
412 cname += QStringLiteral("QWindow");
419 brush = GetSysColorBrush(COLOR_WINDOW);
420 return registerWindowClass(cname, qWindowsWndProc, style, brush, icon);
423 QString QWindowsContext::registerWindowClass(QString cname,
429 // since multiple Qt versions can be used in one process
430 // each one has to have window class names with a unique name
431 // The first instance gets the unmodified name; if the class
432 // has already been registered by another instance of Qt then
433 // add an instance-specific ID, the address of the window proc.
434 static int classExists = -1;
436 const HINSTANCE appInstance = (HINSTANCE)GetModuleHandle(0);
437 if (classExists == -1) {
439 classExists = GetClassInfo(appInstance, (wchar_t*)cname.utf16(), &wcinfo);
440 classExists = classExists && wcinfo.lpfnWndProc != proc;
444 cname += QString::number((quintptr)proc);
446 if (d->m_registeredWindowClassNames.contains(cname)) // already registered in our list
451 wc.cbSize = sizeof(WNDCLASSEX);
456 wc.lpfnWndProc = proc;
459 wc.hInstance = appInstance;
462 wc.hbrBackground = brush;
464 wc.hIcon = (HICON)LoadImage(appInstance, L"IDI_ICON1", IMAGE_ICON, 0, 0, LR_DEFAULTSIZE);
466 int sw = GetSystemMetrics(SM_CXSMICON);
467 int sh = GetSystemMetrics(SM_CYSMICON);
468 wc.hIconSm = (HICON)LoadImage(appInstance, L"IDI_ICON1", IMAGE_ICON, sw, sh, 0);
470 wc.hIcon = (HICON)LoadImage(0, IDI_APPLICATION, IMAGE_ICON, 0, 0, LR_DEFAULTSIZE | LR_SHARED);
479 wc.hIcon = (HICON)LoadImage(appInstance, L"IDI_ICON1", IMAGE_ICON, 0, 0, LR_DEFAULTSIZE);
486 wc.lpszClassName = (wchar_t*)cname.utf16();
488 ATOM atom = RegisterClassEx(&wc);
490 ATOM atom = RegisterClass(&wc);
494 qErrnoWarning("QApplication::regClass: Registering window class '%s' failed.",
497 d->m_registeredWindowClassNames.insert(cname);
498 if (QWindowsContext::verboseIntegration || QWindowsContext::verboseWindows)
499 qDebug().nospace() << __FUNCTION__ << ' ' << cname
500 << " style=0x" << QString::number(style, 16)
501 << " brush=" << brush << " icon=" << icon << " atom=" << atom;
505 void QWindowsContext::unregisterWindowClasses()
507 const HINSTANCE appInstance = (HINSTANCE)GetModuleHandle(0);
509 foreach (const QString &name, d->m_registeredWindowClassNames) {
510 if (QWindowsContext::verboseIntegration)
511 qDebug() << __FUNCTION__ << name;
512 UnregisterClass((wchar_t*)name.utf16(), appInstance);
514 d->m_registeredWindowClassNames.clear();
517 int QWindowsContext::screenDepth() const
519 return GetDeviceCaps(d->m_displayContext, BITSPIXEL);
522 QString QWindowsContext::windowsErrorMessage(unsigned long errorCode)
524 QString rc = QString::fromLatin1("#%1: ").arg(errorCode);
527 const int len = FormatMessage(
528 FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
529 NULL, errorCode, 0, (LPTSTR)&lpMsgBuf, 0, NULL);
531 rc = QString::fromUtf16(lpMsgBuf, len);
534 rc += QString::fromLatin1("<unknown error>");
539 void QWindowsContext::addWindow(HWND hwnd, QWindowsWindow *w)
541 d->m_windows.insert(hwnd, w);
544 void QWindowsContext::removeWindow(HWND hwnd)
546 const HandleBaseWindowHash::iterator it = d->m_windows.find(hwnd);
547 if (it != d->m_windows.end()) {
548 if (d->m_keyMapper.keyGrabber() == it.value()->window())
549 d->m_keyMapper.setKeyGrabber(0);
550 d->m_windows.erase(it);
554 QWindowsWindow *QWindowsContext::findPlatformWindow(HWND hwnd) const
556 return d->m_windows.value(hwnd);
559 QWindowsWindow *QWindowsContext::findClosestPlatformWindow(HWND hwnd) const
561 QWindowsWindow *window = d->m_windows.value(hwnd);
563 // Requested hwnd may also be a child of a platform window in case of embedded native windows.
564 // Find the closest parent that has a platform window.
566 for (HWND w = hwnd; w; w = GetParent(w)) {
567 window = d->m_windows.value(w);
576 QWindow *QWindowsContext::findWindow(HWND hwnd) const
578 if (const QWindowsWindow *bw = findPlatformWindow(hwnd))
583 QWindow *QWindowsContext::windowUnderMouse() const
585 return d->m_mouseHandler.windowUnderMouse();
589 \brief Find a child window at a screen point.
591 Deep search for a QWindow at global point, skipping non-owned
592 windows (accessibility?). Implemented using ChildWindowFromPointEx()
593 instead of (historically used) WindowFromPoint() to get a well-defined
594 behaviour for hidden/transparent windows.
596 \a cwex_flags are flags of ChildWindowFromPointEx().
597 \a parent is the parent window, pass GetDesktopWindow() for top levels.
600 QWindowsWindow *QWindowsContext::findPlatformWindowAt(HWND parent,
601 const QPoint &screenPointIn,
602 unsigned cwex_flags) const
604 QWindowsWindow *result = 0;
605 const POINT screenPoint = { screenPointIn.x(), screenPointIn.y() };
607 POINT point = screenPoint;
608 ScreenToClient(parent, &point);
609 // Returns parent if inside & none matched.
610 const HWND child = ChildWindowFromPointEx(parent, point, cwex_flags);
611 if (child && child != parent) {
612 if (QWindowsWindow *window = findPlatformWindow(child))
622 QWindowsMimeConverter &QWindowsContext::mimeConverter() const
624 return d->m_mimeConverter;
627 QWindowsScreenManager &QWindowsContext::screenManager()
629 return d->m_screenManager;
633 \brief Convenience to create a non-visible, message-only dummy
634 window for example used as clipboard watcher or for GL.
637 HWND QWindowsContext::createDummyWindow(const QString &classNameIn,
638 const wchar_t *windowName,
639 WNDPROC wndProc, DWORD style)
642 wndProc = DefWindowProc;
643 QString className = registerWindowClass(classNameIn, wndProc);
644 return CreateWindowEx(0, (wchar_t*)className.utf16(),
646 CW_USEDEFAULT, CW_USEDEFAULT,
647 CW_USEDEFAULT, CW_USEDEFAULT,
648 HWND_MESSAGE, NULL, (HINSTANCE)GetModuleHandle(0), NULL);
652 \brief Common COM error strings.
655 QByteArray QWindowsContext::comErrorString(HRESULT hr)
659 return QByteArrayLiteral("S_OK");
661 return QByteArrayLiteral("S_FALSE");
663 return QByteArrayLiteral("E_UNEXPECTED");
664 case CO_E_ALREADYINITIALIZED:
665 return QByteArrayLiteral("CO_E_ALREADYINITIALIZED");
666 case CO_E_NOTINITIALIZED:
667 return QByteArrayLiteral("CO_E_NOTINITIALIZED");
668 case RPC_E_CHANGED_MODE:
669 return QByteArrayLiteral("RPC_E_CHANGED_MODE");
670 case OLE_E_WRONGCOMPOBJ:
671 return QByteArrayLiteral("OLE_E_WRONGCOMPOBJ");
672 case CO_E_NOT_SUPPORTED:
673 return QByteArrayLiteral("CO_E_NOT_SUPPORTED");
675 return QByteArrayLiteral("E_NOTIMPL");
677 return QByteArrayLiteral("E_INVALIDARG");
679 return QByteArrayLiteral("E_NOINTERFACE");
681 return QByteArrayLiteral("E_POINTER");
683 return QByteArrayLiteral("E_HANDLE");
685 return QByteArrayLiteral("E_ABORT");
687 return QByteArrayLiteral("E_FAIL");
688 case RPC_E_WRONG_THREAD:
689 return QByteArrayLiteral("RPC_E_WRONG_THREAD");
690 case RPC_E_THREAD_NOT_INIT:
691 return QByteArrayLiteral("RPC_E_THREAD_NOT_INIT");
695 return "Unknown error 0x" + QByteArray::number(quint64(hr), 16);
699 \brief Main windows procedure registered for windows.
701 \sa QWindowsGuiEventDispatcher
704 bool QWindowsContext::windowsProc(HWND hwnd, UINT message,
705 QtWindows::WindowsEventType et,
706 WPARAM wParam, LPARAM lParam, LRESULT *result)
711 msg.hwnd = hwnd; // re-create MSG structure
712 msg.message = message; // time and pt fields ignored
715 msg.pt.x = GET_X_LPARAM(lParam);
716 msg.pt.y = GET_Y_LPARAM(lParam);
718 // Run the native event filters.
719 long filterResult = 0;
720 QAbstractEventDispatcher* dispatcher = QAbstractEventDispatcher::instance();
721 if (dispatcher && dispatcher->filterNativeEvent(d->m_eventType, &msg, &filterResult)) {
722 *result = LRESULT(filterResult);
726 QWindowsWindow *platformWindow = findPlatformWindow(hwnd);
727 if (platformWindow) {
729 if (QWindowSystemInterface::handleNativeEvent(platformWindow->window(), d->m_eventType, &msg, &filterResult)) {
730 *result = LRESULT(filterResult);
736 case QtWindows::InputMethodStartCompositionEvent:
737 return QWindowsInputContext::instance()->startComposition(hwnd);
738 case QtWindows::InputMethodCompositionEvent:
739 return QWindowsInputContext::instance()->composition(hwnd, lParam);
740 case QtWindows::InputMethodEndCompositionEvent:
741 return QWindowsInputContext::instance()->endComposition(hwnd);
742 case QtWindows::InputMethodRequest:
743 return QWindowsInputContext::instance()->handleIME_Request(wParam, lParam, result);
744 case QtWindows::InputMethodOpenCandidateWindowEvent:
745 case QtWindows::InputMethodCloseCandidateWindowEvent:
746 // TODO: Release/regrab mouse if a popup has mouse grab.
748 case QtWindows::ClipboardEvent:
749 case QtWindows::DestroyEvent:
751 case QtWindows::UnknownEvent:
753 case QtWindows::AccessibleObjectFromWindowRequest:
754 #ifndef QT_NO_ACCESSIBILITY
755 return QWindowsAccessibility::handleAccessibleObjectFromWindowRequest(hwnd, wParam, lParam, result);
759 case QtWindows::DisplayChangedEvent:
760 return d->m_screenManager.handleDisplayChange(wParam, lParam);
761 case QtWindows::SettingChangedEvent:
762 return d->m_screenManager.handleScreenChanges();
767 // Before CreateWindowEx() returns, some events are sent,
768 // for example WM_GETMINMAXINFO asking for size constraints for top levels.
769 // Pass on to current creation context
770 if (!platformWindow && !d->m_creationContext.isNull()) {
772 #ifndef Q_OS_WINCE // maybe available on some SDKs revisit WM_GETMINMAXINFO
773 case QtWindows::QuerySizeHints:
774 d->m_creationContext->applyToMinMaxInfo(reinterpret_cast<MINMAXINFO *>(lParam));
777 case QtWindows::ResizeEvent:
778 d->m_creationContext->obtainedGeometry.setSize(QSize(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)));
780 case QtWindows::MoveEvent:
781 d->m_creationContext->obtainedGeometry.moveTo(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
783 case QtWindows::CalculateSize:
789 if (platformWindow) {
790 // Suppress events sent during DestroyWindow() for native children.
791 if (platformWindow->testFlag(QWindowsWindow::WithinDestroy))
793 if (QWindowsContext::verboseEvents > 1)
794 qDebug().nospace() << "Event window: " << platformWindow->window();
796 qWarning("%s: No Qt Window found for event 0x%x (%s), hwnd=0x%p.",
797 __FUNCTION__, message,
798 QWindowsGuiEventDispatcher::windowsMessageName(message), hwnd);
803 case QtWindows::KeyDownEvent:
804 case QtWindows::KeyEvent:
805 case QtWindows::InputMethodKeyEvent:
806 case QtWindows::InputMethodKeyDownEvent:
807 return d->m_keyMapper.translateKeyEvent(platformWindow->window(), hwnd, msg, result);
808 case QtWindows::MoveEvent:
809 platformWindow->handleMoved();
811 case QtWindows::ResizeEvent:
812 platformWindow->handleResized((int)wParam);
814 #ifndef Q_OS_WINCE // maybe available on some SDKs revisit WM_GETMINMAXINFO
815 case QtWindows::QuerySizeHints:
816 platformWindow->getSizeHints(reinterpret_cast<MINMAXINFO *>(lParam));
817 return true;// maybe available on some SDKs revisit WM_NCCALCSIZE
818 case QtWindows::CalculateSize:
819 // NCCALCSIZE_PARAMS structure if wParam==TRUE
820 if (wParam && QWindowsContext::verboseWindows) {
821 const NCCALCSIZE_PARAMS *ncp = reinterpret_cast<NCCALCSIZE_PARAMS *>(lParam);
822 qDebug() << platformWindow->window() << *ncp;
826 case QtWindows::ExposeEvent:
827 return platformWindow->handleWmPaint(hwnd, message, wParam, lParam);
828 case QtWindows::NonClientMouseEvent:
829 if (platformWindow->frameStrutEventsEnabled())
830 return d->m_mouseHandler.translateMouseEvent(platformWindow->window(), hwnd, et, msg, result);
832 /* the mouse tracking on windows already handles the reset of the cursor
833 * and does not like somebody else handling it.
834 * on WINCE its necessary to handle this event to get the correct cursor
837 case QtWindows::CursorEvent:
839 QWindowsWindow::baseWindowOf(platformWindow->window())->applyCursor();
843 case QtWindows::MouseWheelEvent:
844 case QtWindows::MouseEvent:
845 case QtWindows::LeaveEvent:
846 return d->m_mouseHandler.translateMouseEvent(platformWindow->window(), hwnd, et, msg, result);
847 case QtWindows::TouchEvent:
848 return d->m_mouseHandler.translateTouchEvent(platformWindow->window(), hwnd, et, msg, result);
849 case QtWindows::FocusInEvent: // see QWindowsWindow::requestActivateWindow().
850 case QtWindows::FocusOutEvent:
851 handleFocusEvent(et, platformWindow);
853 case QtWindows::ShowEvent:
854 platformWindow->handleShown();
856 case QtWindows::HideEvent:
857 platformWindow->handleHidden();
859 case QtWindows::CloseEvent:
860 QWindowSystemInterface::handleCloseEvent(platformWindow->window());
862 case QtWindows::ThemeChanged: // ### fixme: Compress these events?
863 if (QWindowsTheme *theme = QWindowsTheme::instance())
864 theme->windowsThemeChanged(platformWindow->window());
867 case QtWindows::ActivateWindowEvent:
868 if (platformWindow->testFlag(QWindowsWindow::BlockedByModal))
869 if (const QWindow *modalWindow = QGuiApplication::modalWindow())
870 QWindowsWindow::baseWindowOf(modalWindow)->alertWindow();
873 #ifndef QT_NO_CONTEXTMENU
874 case QtWindows::ContextMenu:
875 handleContextMenuEvent(platformWindow->window(), msg);
884 /* Compress activation events. If the next focus window is already known
885 * at the time the current one receives focus-out, pass that to
886 * QWindowSystemInterface instead of sending 0 and ignore its consecutive
888 * This helps applications that do handling in focus-out events. */
889 void QWindowsContext::handleFocusEvent(QtWindows::WindowsEventType et,
890 QWindowsWindow *platformWindow)
892 QWindow *nextActiveWindow = 0;
893 if (et == QtWindows::FocusInEvent) {
894 nextActiveWindow = platformWindow->window();
896 // Focus out: Is the next window known and different
897 // from the receiving the focus out.
898 if (const HWND nextActiveHwnd = GetFocus())
899 if (QWindowsWindow *nextActivePlatformWindow = findClosestPlatformWindow(nextActiveHwnd))
900 if (nextActivePlatformWindow != platformWindow)
901 nextActiveWindow = nextActivePlatformWindow->window();
903 if (nextActiveWindow != d->m_lastActiveWindow) {
904 d->m_lastActiveWindow = nextActiveWindow;
905 QWindowSystemInterface::handleWindowActivated(nextActiveWindow);
909 #ifndef QT_NO_CONTEXTMENU
910 void QWindowsContext::handleContextMenuEvent(QWindow *window, const MSG &msg)
912 bool mouseTriggered = false;
915 if (msg.lParam != (int)0xffffffff) {
916 mouseTriggered = true;
917 globalPos.setX(msg.pt.x);
918 globalPos.setY(msg.pt.y);
919 pos = QWindowsGeometryHint::mapFromGlobal(msg.hwnd, globalPos);
922 QWindowSystemInterface::handleContextMenuEvent(window, mouseTriggered, pos, globalPos,
923 QWindowsKeyMapper::queryKeyboardModifiers());
927 bool QWindowsContext::asyncExpose() const
929 return d->m_asyncExpose;
932 void QWindowsContext::setAsyncExpose(bool value)
934 d->m_asyncExpose = value;
938 \brief Windows functions for actual windows.
940 There is another one for timers, sockets, etc in
941 QEventDispatcherWin32.
943 \ingroup qt-lighthouse-win
946 extern "C" LRESULT QT_WIN_CALLBACK qWindowsWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
949 const QtWindows::WindowsEventType et = windowsEventType(message, wParam);
950 const bool handled = QWindowsContext::instance()->windowsProc(hwnd, message, et, wParam, lParam, &result);
951 if (QWindowsContext::verboseEvents > 1)
952 if (const char *eventName = QWindowsGuiEventDispatcher::windowsMessageName(message))
953 qDebug("EVENT: hwd=%p %s msg=0x%x et=0x%x wp=%d at %d,%d handled=%d",
954 hwnd, eventName, message, et, int(wParam),
955 GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), handled);
957 result = DefWindowProc(hwnd, message, wParam, lParam);