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() : sHCreateItemFromParsingName(0)
217 void QWindowsShell32DLL::init()
219 QSystemLibrary library(QStringLiteral("shell32"));
220 sHCreateItemFromParsingName = (SHCreateItemFromParsingName)(library.resolve("SHCreateItemFromParsingName"));
223 QWindowsUser32DLL QWindowsContext::user32dll;
224 QWindowsShell32DLL QWindowsContext::shell32dll;
226 #endif // !Q_OS_WINCE
228 QWindowsContext *QWindowsContext::m_instance = 0;
231 \class QWindowsContext
232 \brief Singleton container for all relevant information.
234 Holds state information formerly stored in \c qapplication_win.cpp.
237 \ingroup qt-lighthouse-win
240 typedef QHash<HWND, QWindowsWindow *> HandleBaseWindowHash;
242 struct QWindowsContextPrivate {
244 QWindowsContextPrivate();
246 unsigned m_systemInfo;
247 QSet<QString> m_registeredWindowClassNames;
248 HandleBaseWindowHash m_windows;
249 HDC m_displayContext;
250 const int m_defaultDPI;
251 QWindowsKeyMapper m_keyMapper;
252 QWindowsMouseHandler m_mouseHandler;
253 QWindowsMimeConverter m_mimeConverter;
254 QWindowsScreenManager m_screenManager;
255 QSharedPointer<QWindowCreationContext> m_creationContext;
256 const HRESULT m_oleInitializeResult;
257 const QByteArray m_eventType;
258 QWindow *m_lastActiveWindow;
261 QWindowsContextPrivate::QWindowsContextPrivate() :
263 m_displayContext(GetDC(0)),
264 m_defaultDPI(GetDeviceCaps(m_displayContext,LOGPIXELSY)),
265 m_oleInitializeResult(OleInitialize(NULL)),
266 m_eventType(QByteArrayLiteral("windows_generic_MSG")),
267 m_lastActiveWindow(0)
270 QWindowsContext::user32dll.init();
271 QWindowsContext::shell32dll.init();
274 const QSysInfo::WinVersion ver = QSysInfo::windowsVersion();
276 if (hasTouchSupport(ver) && QWindowsContext::user32dll.initTouch())
277 m_systemInfo |= QWindowsContext::SI_SupportsTouch;
280 if (useRTL_Extensions(ver)) {
281 m_systemInfo |= QWindowsContext::SI_RTL_Extensions;
282 m_keyMapper.setUseRTLExtensions(true);
286 QWindowsContext::QWindowsContext() :
287 d(new QWindowsContextPrivate)
290 # pragma warning( disable : 4996 )
293 const QByteArray bv = qgetenv("QT_QPA_VERBOSE");
295 const char *v = bv.data();
296 QWindowsContext::verboseIntegration = componentVerbose(v, "integration");
297 QWindowsContext::verboseWindows = componentVerbose(v, "windows");
298 QWindowsContext::verboseEvents = componentVerbose(v, "events");
299 QWindowsContext::verboseBackingStore = componentVerbose(v, "backingstore");
300 QWindowsContext::verboseFonts = componentVerbose(v, "fonts");
301 QWindowsContext::verboseGL = componentVerbose(v, "gl");
302 QWindowsContext::verboseOLE = componentVerbose(v, "ole");
303 QWindowsContext::verboseInputMethods = componentVerbose(v, "im");
304 QWindowsContext::verboseDialogs = componentVerbose(v, "dialogs");
305 QWindowsContext::verboseTheming = componentVerbose(v, "theming");
309 QWindowsContext::~QWindowsContext()
311 unregisterWindowClasses();
312 if (d->m_oleInitializeResult == S_OK || d->m_oleInitializeResult == S_FALSE)
315 d->m_screenManager.clearScreens(); // Order: Potentially calls back to the windows.
319 QWindowsContext *QWindowsContext::instance()
324 unsigned QWindowsContext::systemInfo() const
326 return d->m_systemInfo;
329 bool QWindowsContext::useRTLExtensions() const
331 return d->m_keyMapper.useRTLExtensions();
334 QList<int> QWindowsContext::possibleKeys(const QKeyEvent *e) const
336 return d->m_keyMapper.possibleKeys(e);
339 void QWindowsContext::setWindowCreationContext(const QSharedPointer<QWindowCreationContext> &ctx)
341 d->m_creationContext = ctx;
344 int QWindowsContext::defaultDPI() const
346 return d->m_defaultDPI;
349 HDC QWindowsContext::displayContext() const
351 return d->m_displayContext;
354 QWindow *QWindowsContext::keyGrabber() const
356 return d->m_keyMapper.keyGrabber();
359 void QWindowsContext::setKeyGrabber(QWindow *w)
361 d->m_keyMapper.setKeyGrabber(w);
364 // Window class registering code (from qapplication_win.cpp)
365 // If 0 is passed as the widget pointer, register a window class
366 // for QWidget as default. This is used in QGLTemporaryContext
367 // during GL initialization, where we don't want to use temporary
368 // QWidgets or QGLWidgets, neither do we want to have separate code
369 // to register window classes.
371 QString QWindowsContext::registerWindowClass(const QWindow *w, bool isGL)
373 const Qt::WindowFlags flags = w ? w->windowFlags() : (Qt::WindowFlags)0;
374 const Qt::WindowFlags type = flags & Qt::WindowType_Mask;
378 QString cname = QStringLiteral("Qt5");
380 cname += QStringLiteral("QGLWindow");
381 style = CS_DBLCLKS|CS_OWNDC;
383 } else if (w && (flags & Qt::MSWindowsOwnDC)) {
384 cname += QStringLiteral("QWindowOwnDC");
385 style = CS_DBLCLKS|CS_OWNDC;
387 } else if (w && (type == Qt::Tool || type == Qt::ToolTip)) {
389 if (w->inherits("QTipLabel") || w->inherits("QAlphaWidget")) {
390 if ((QSysInfo::WindowsVersion >= QSysInfo::WV_XP
391 && (QSysInfo::WindowsVersion & QSysInfo::WV_NT_based))) {
392 style |= CS_DROPSHADOW;
394 cname += QStringLiteral("QToolTip");
396 cname += QStringLiteral("QTool");
398 style |= CS_SAVEBITS;
400 } else if (w && (type == Qt::Popup)) {
401 cname += QStringLiteral("QPopup");
402 style = CS_DBLCLKS|CS_SAVEBITS;
403 if ((QSysInfo::WindowsVersion >= QSysInfo::WV_XP
404 && (QSysInfo::WindowsVersion & QSysInfo::WV_NT_based)))
405 style |= CS_DROPSHADOW;
408 cname += QStringLiteral("QWindow");
415 brush = GetSysColorBrush(COLOR_WINDOW);
416 return registerWindowClass(cname, qWindowsWndProc, style, brush, icon);
419 QString QWindowsContext::registerWindowClass(QString cname,
425 // since multiple Qt versions can be used in one process
426 // each one has to have window class names with a unique name
427 // The first instance gets the unmodified name; if the class
428 // has already been registered by another instance of Qt then
429 // add an instance-specific ID, the address of the window proc.
430 static int classExists = -1;
432 const HINSTANCE appInstance = (HINSTANCE)GetModuleHandle(0);
433 if (classExists == -1) {
435 classExists = GetClassInfo(appInstance, (wchar_t*)cname.utf16(), &wcinfo);
436 classExists = classExists && wcinfo.lpfnWndProc != proc;
440 cname += QString::number((quintptr)proc);
442 if (d->m_registeredWindowClassNames.contains(cname)) // already registered in our list
447 wc.cbSize = sizeof(WNDCLASSEX);
452 wc.lpfnWndProc = proc;
455 wc.hInstance = appInstance;
458 wc.hbrBackground = brush;
460 wc.hIcon = (HICON)LoadImage(appInstance, L"IDI_ICON1", IMAGE_ICON, 0, 0, LR_DEFAULTSIZE);
462 int sw = GetSystemMetrics(SM_CXSMICON);
463 int sh = GetSystemMetrics(SM_CYSMICON);
464 wc.hIconSm = (HICON)LoadImage(appInstance, L"IDI_ICON1", IMAGE_ICON, sw, sh, 0);
466 wc.hIcon = (HICON)LoadImage(0, IDI_APPLICATION, IMAGE_ICON, 0, 0, LR_DEFAULTSIZE | LR_SHARED);
475 wc.hIcon = (HICON)LoadImage(appInstance, L"IDI_ICON1", IMAGE_ICON, 0, 0, LR_DEFAULTSIZE);
482 wc.lpszClassName = (wchar_t*)cname.utf16();
484 ATOM atom = RegisterClassEx(&wc);
486 ATOM atom = RegisterClass(&wc);
490 qErrnoWarning("QApplication::regClass: Registering window class '%s' failed.",
493 d->m_registeredWindowClassNames.insert(cname);
494 if (QWindowsContext::verboseIntegration || QWindowsContext::verboseWindows)
495 qDebug().nospace() << __FUNCTION__ << ' ' << cname
496 << " style=0x" << QString::number(style, 16)
497 << " brush=" << brush << " icon=" << icon << " atom=" << atom;
501 void QWindowsContext::unregisterWindowClasses()
503 const HINSTANCE appInstance = (HINSTANCE)GetModuleHandle(0);
505 foreach (const QString &name, d->m_registeredWindowClassNames) {
506 if (QWindowsContext::verboseIntegration)
507 qDebug() << __FUNCTION__ << name;
508 UnregisterClass((wchar_t*)name.utf16(), appInstance);
510 d->m_registeredWindowClassNames.clear();
513 int QWindowsContext::screenDepth() const
515 return GetDeviceCaps(d->m_displayContext, BITSPIXEL);
518 QString QWindowsContext::windowsErrorMessage(unsigned long errorCode)
520 QString rc = QString::fromLatin1("#%1: ").arg(errorCode);
523 const int len = FormatMessage(
524 FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
525 NULL, errorCode, 0, (LPTSTR)&lpMsgBuf, 0, NULL);
527 rc = QString::fromUtf16(lpMsgBuf, len);
530 rc += QString::fromLatin1("<unknown error>");
535 void QWindowsContext::addWindow(HWND hwnd, QWindowsWindow *w)
537 d->m_windows.insert(hwnd, w);
540 void QWindowsContext::removeWindow(HWND hwnd)
542 const HandleBaseWindowHash::iterator it = d->m_windows.find(hwnd);
543 if (it != d->m_windows.end()) {
544 if (d->m_keyMapper.keyGrabber() == it.value()->window())
545 d->m_keyMapper.setKeyGrabber(0);
546 d->m_windows.erase(it);
550 QWindowsWindow *QWindowsContext::findPlatformWindow(HWND hwnd) const
552 return d->m_windows.value(hwnd);
555 QWindowsWindow *QWindowsContext::findClosestPlatformWindow(HWND hwnd) const
557 QWindowsWindow *window = d->m_windows.value(hwnd);
559 // Requested hwnd may also be a child of a platform window in case of embedded native windows.
560 // Find the closest parent that has a platform window.
562 for (HWND w = hwnd; w; w = GetParent(w)) {
563 window = d->m_windows.value(w);
572 QWindow *QWindowsContext::findWindow(HWND hwnd) const
574 if (const QWindowsWindow *bw = findPlatformWindow(hwnd))
579 QWindow *QWindowsContext::windowUnderMouse() const
581 return d->m_mouseHandler.windowUnderMouse();
585 \brief Find a child window at a screen point.
587 Deep search for a QWindow at global point, skipping non-owned
588 windows (accessibility?). Implemented using ChildWindowFromPointEx()
589 instead of (historically used) WindowFromPoint() to get a well-defined
590 behaviour for hidden/transparent windows.
592 \a cwex_flags are flags of ChildWindowFromPointEx().
593 \a parent is the parent window, pass GetDesktopWindow() for top levels.
596 QWindowsWindow *QWindowsContext::findPlatformWindowAt(HWND parent,
597 const QPoint &screenPointIn,
598 unsigned cwex_flags) const
600 QWindowsWindow *result = 0;
601 const POINT screenPoint = { screenPointIn.x(), screenPointIn.y() };
603 POINT point = screenPoint;
604 ScreenToClient(parent, &point);
605 // Returns parent if inside & none matched.
606 const HWND child = ChildWindowFromPointEx(parent, point, cwex_flags);
607 if (child && child != parent) {
608 if (QWindowsWindow *window = findPlatformWindow(child))
618 QWindowsMimeConverter &QWindowsContext::mimeConverter() const
620 return d->m_mimeConverter;
623 QWindowsScreenManager &QWindowsContext::screenManager()
625 return d->m_screenManager;
629 \brief Convenience to create a non-visible, message-only dummy
630 window for example used as clipboard watcher or for GL.
633 HWND QWindowsContext::createDummyWindow(const QString &classNameIn,
634 const wchar_t *windowName,
635 WNDPROC wndProc, DWORD style)
638 wndProc = DefWindowProc;
639 QString className = registerWindowClass(classNameIn, wndProc);
640 return CreateWindowEx(0, (wchar_t*)className.utf16(),
642 CW_USEDEFAULT, CW_USEDEFAULT,
643 CW_USEDEFAULT, CW_USEDEFAULT,
644 HWND_MESSAGE, NULL, (HINSTANCE)GetModuleHandle(0), NULL);
648 \brief Common COM error strings.
651 QByteArray QWindowsContext::comErrorString(HRESULT hr)
655 return QByteArrayLiteral("S_OK");
657 return QByteArrayLiteral("S_FALSE");
659 return QByteArrayLiteral("E_UNEXPECTED");
660 case CO_E_ALREADYINITIALIZED:
661 return QByteArrayLiteral("CO_E_ALREADYINITIALIZED");
662 case CO_E_NOTINITIALIZED:
663 return QByteArrayLiteral("CO_E_NOTINITIALIZED");
664 case RPC_E_CHANGED_MODE:
665 return QByteArrayLiteral("RPC_E_CHANGED_MODE");
666 case OLE_E_WRONGCOMPOBJ:
667 return QByteArrayLiteral("OLE_E_WRONGCOMPOBJ");
668 case CO_E_NOT_SUPPORTED:
669 return QByteArrayLiteral("CO_E_NOT_SUPPORTED");
671 return QByteArrayLiteral("E_NOTIMPL");
673 return QByteArrayLiteral("E_INVALIDARG");
675 return QByteArrayLiteral("E_NOINTERFACE");
677 return QByteArrayLiteral("E_POINTER");
679 return QByteArrayLiteral("E_HANDLE");
681 return QByteArrayLiteral("E_ABORT");
683 return QByteArrayLiteral("E_FAIL");
684 case RPC_E_WRONG_THREAD:
685 return QByteArrayLiteral("RPC_E_WRONG_THREAD");
686 case RPC_E_THREAD_NOT_INIT:
687 return QByteArrayLiteral("RPC_E_THREAD_NOT_INIT");
691 return "Unknown error 0x" + QByteArray::number(quint64(hr), 16);
695 \brief Main windows procedure registered for windows.
697 \sa QWindowsGuiEventDispatcher
700 bool QWindowsContext::windowsProc(HWND hwnd, UINT message,
701 QtWindows::WindowsEventType et,
702 WPARAM wParam, LPARAM lParam, LRESULT *result)
707 msg.hwnd = hwnd; // re-create MSG structure
708 msg.message = message; // time and pt fields ignored
711 msg.pt.x = GET_X_LPARAM(lParam);
712 msg.pt.y = GET_Y_LPARAM(lParam);
714 // Run the native event filters.
715 long filterResult = 0;
716 QAbstractEventDispatcher* dispatcher = QAbstractEventDispatcher::instance();
717 if (dispatcher && dispatcher->filterNativeEvent(d->m_eventType, &msg, &filterResult)) {
718 *result = LRESULT(filterResult);
722 QWindowsWindow *platformWindow = findPlatformWindow(hwnd);
723 if (platformWindow) {
725 if (QWindowSystemInterface::handleNativeEvent(platformWindow->window(), d->m_eventType, &msg, &filterResult)) {
726 *result = LRESULT(filterResult);
732 case QtWindows::InputMethodStartCompositionEvent:
733 return QWindowsInputContext::instance()->startComposition(hwnd);
734 case QtWindows::InputMethodCompositionEvent:
735 return QWindowsInputContext::instance()->composition(hwnd, lParam);
736 case QtWindows::InputMethodEndCompositionEvent:
737 return QWindowsInputContext::instance()->endComposition(hwnd);
738 case QtWindows::InputMethodRequest:
739 return QWindowsInputContext::instance()->handleIME_Request(wParam, lParam, result);
740 case QtWindows::InputMethodOpenCandidateWindowEvent:
741 case QtWindows::InputMethodCloseCandidateWindowEvent:
742 // TODO: Release/regrab mouse if a popup has mouse grab.
744 case QtWindows::ClipboardEvent:
745 case QtWindows::DestroyEvent:
747 case QtWindows::UnknownEvent:
749 case QtWindows::AccessibleObjectFromWindowRequest:
750 #ifndef QT_NO_ACCESSIBILITY
751 return QWindowsAccessibility::handleAccessibleObjectFromWindowRequest(hwnd, wParam, lParam, result);
755 case QtWindows::DisplayChangedEvent:
756 return d->m_screenManager.handleDisplayChange(wParam, lParam);
757 case QtWindows::SettingChangedEvent:
758 return d->m_screenManager.handleScreenChanges();
763 // Before CreateWindowEx() returns, some events are sent,
764 // for example WM_GETMINMAXINFO asking for size constraints for top levels.
765 // Pass on to current creation context
766 if (!platformWindow && !d->m_creationContext.isNull()) {
768 #ifndef Q_OS_WINCE // maybe available on some SDKs revisit WM_GETMINMAXINFO
769 case QtWindows::QuerySizeHints:
770 d->m_creationContext->applyToMinMaxInfo(reinterpret_cast<MINMAXINFO *>(lParam));
773 case QtWindows::ResizeEvent:
774 d->m_creationContext->obtainedGeometry.setSize(QSize(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)));
776 case QtWindows::MoveEvent:
777 d->m_creationContext->obtainedGeometry.moveTo(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
779 case QtWindows::CalculateSize:
785 if (platformWindow) {
786 // Suppress events sent during DestroyWindow() for native children.
787 if (platformWindow->testFlag(QWindowsWindow::WithinDestroy))
789 if (QWindowsContext::verboseEvents > 1)
790 qDebug().nospace() << "Event window: " << platformWindow->window();
792 qWarning("%s: No Qt Window found for event 0x%x (%s), hwnd=0x%p.",
793 __FUNCTION__, message,
794 QWindowsGuiEventDispatcher::windowsMessageName(message), hwnd);
799 case QtWindows::KeyDownEvent:
800 case QtWindows::KeyEvent:
801 case QtWindows::InputMethodKeyEvent:
802 case QtWindows::InputMethodKeyDownEvent:
803 return d->m_keyMapper.translateKeyEvent(platformWindow->window(), hwnd, msg, result);
804 case QtWindows::MoveEvent:
805 platformWindow->handleMoved();
807 case QtWindows::ResizeEvent:
808 platformWindow->handleResized((int)wParam);
810 #ifndef Q_OS_WINCE // maybe available on some SDKs revisit WM_GETMINMAXINFO
811 case QtWindows::QuerySizeHints:
812 platformWindow->getSizeHints(reinterpret_cast<MINMAXINFO *>(lParam));
813 return true;// maybe available on some SDKs revisit WM_NCCALCSIZE
814 case QtWindows::CalculateSize:
815 // NCCALCSIZE_PARAMS structure if wParam==TRUE
816 if (wParam && QWindowsContext::verboseWindows) {
817 const NCCALCSIZE_PARAMS *ncp = reinterpret_cast<NCCALCSIZE_PARAMS *>(lParam);
818 qDebug() << platformWindow->window() << *ncp;
822 case QtWindows::ExposeEvent:
823 return platformWindow->handleWmPaint(hwnd, message, wParam, lParam);
824 case QtWindows::NonClientMouseEvent:
825 if (platformWindow->frameStrutEventsEnabled())
826 return d->m_mouseHandler.translateMouseEvent(platformWindow->window(), hwnd, et, msg, result);
828 /* the mouse tracking on windows already handles the reset of the cursor
829 * and does not like somebody else handling it.
830 * on WINCE its necessary to handle this event to get the correct cursor
833 case QtWindows::CursorEvent:
835 QWindowsWindow::baseWindowOf(platformWindow->window())->applyCursor();
839 case QtWindows::MouseWheelEvent:
840 case QtWindows::MouseEvent:
841 case QtWindows::LeaveEvent:
842 return d->m_mouseHandler.translateMouseEvent(platformWindow->window(), hwnd, et, msg, result);
843 case QtWindows::TouchEvent:
844 return d->m_mouseHandler.translateTouchEvent(platformWindow->window(), hwnd, et, msg, result);
845 case QtWindows::FocusInEvent: // see QWindowsWindow::requestActivateWindow().
846 case QtWindows::FocusOutEvent:
847 handleFocusEvent(et, platformWindow);
849 case QtWindows::ShowEvent:
850 platformWindow->handleShown();
852 case QtWindows::HideEvent:
853 platformWindow->handleHidden();
855 case QtWindows::CloseEvent:
856 QWindowSystemInterface::handleCloseEvent(platformWindow->window());
858 case QtWindows::ThemeChanged: // ### fixme: Compress these events?
859 if (QWindowsTheme *theme = QWindowsTheme::instance())
860 theme->windowsThemeChanged(platformWindow->window());
863 case QtWindows::ActivateWindowEvent:
864 if (platformWindow->testFlag(QWindowsWindow::BlockedByModal))
865 if (const QWindow *modalWindow = QGuiApplication::modalWindow())
866 QWindowsWindow::baseWindowOf(modalWindow)->alertWindow();
875 /* Compress activation events. If the next focus window is already known
876 * at the time the current one receives focus-out, pass that to
877 * QWindowSystemInterface instead of sending 0 and ignore its consecutive
879 * This helps applications that do handling in focus-out events. */
880 void QWindowsContext::handleFocusEvent(QtWindows::WindowsEventType et,
881 QWindowsWindow *platformWindow)
883 QWindow *nextActiveWindow = 0;
884 if (et == QtWindows::FocusInEvent) {
885 nextActiveWindow = platformWindow->window();
887 // Focus out: Is the next window known and different
888 // from the receiving the focus out.
889 if (const HWND nextActiveHwnd = GetFocus())
890 if (QWindowsWindow *nextActivePlatformWindow = findClosestPlatformWindow(nextActiveHwnd))
891 if (nextActivePlatformWindow != platformWindow)
892 nextActiveWindow = nextActivePlatformWindow->window();
894 if (nextActiveWindow != d->m_lastActiveWindow) {
895 d->m_lastActiveWindow = nextActiveWindow;
896 QWindowSystemInterface::handleWindowActivated(nextActiveWindow);
901 \brief Windows functions for actual windows.
903 There is another one for timers, sockets, etc in
904 QEventDispatcherWin32.
906 \ingroup qt-lighthouse-win
909 extern "C" LRESULT QT_WIN_CALLBACK qWindowsWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
912 const QtWindows::WindowsEventType et = windowsEventType(message, wParam);
913 const bool handled = QWindowsContext::instance()->windowsProc(hwnd, message, et, wParam, lParam, &result);
914 if (QWindowsContext::verboseEvents > 1)
915 if (const char *eventName = QWindowsGuiEventDispatcher::windowsMessageName(message))
916 qDebug("EVENT: hwd=%p %s msg=0x%x et=0x%x wp=%d at %d,%d handled=%d",
917 hwnd, eventName, message, et, int(wParam),
918 GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), handled);
920 result = DefWindowProc(hwnd, message, wParam, lParam);