Add Windows to the Lighthouse.
[profile/ivi/qtbase.git] / src / plugins / platforms / windows / qwindowscontext.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (info@qt.nokia.com)
6 **
7 ** This file is part of the plugins of the Qt Toolkit.
8 **
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** GNU Lesser General Public License Usage
11 ** This file may be used under the terms of the GNU Lesser General Public
12 ** License version 2.1 as published by the Free Software Foundation and
13 ** appearing in the file LICENSE.LGPL included in the packaging of this
14 ** file. Please review the following information to ensure the GNU Lesser
15 ** General Public License version 2.1 requirements will be met:
16 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17 **
18 ** In addition, as a special exception, Nokia gives you certain additional
19 ** rights. These rights are described in the Nokia Qt LGPL Exception
20 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
21 **
22 ** GNU General Public License Usage
23 ** Alternatively, this file may be used under the terms of the GNU General
24 ** Public License version 3.0 as published by the Free Software Foundation
25 ** and appearing in the file LICENSE.GPL included in the packaging of this
26 ** file. Please review the following information to ensure the GNU General
27 ** Public License version 3.0 requirements will be met:
28 ** http://www.gnu.org/copyleft/gpl.html.
29 **
30 ** Other Usage
31 ** Alternatively, this file may be used in accordance with the terms and
32 ** conditions contained in a signed written agreement between you and Nokia.
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
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
50 #include <QtGui/QWindow>
51 #include <QtGui/QWindowSystemInterface>
52
53 #include <QtCore/QSet>
54 #include <QtCore/QHash>
55 #include <QtCore/QStringList>
56 #include <QtCore/QDebug>
57 #include <QtCore/QSysInfo>
58 #include <QtCore/QScopedArrayPointer>
59 #include <QtCore/private/qsystemlibrary_p.h>
60
61 #include <stdlib.h>
62 #include <stdio.h>
63 #include <windowsx.h>
64
65 QT_BEGIN_NAMESPACE
66
67 // Verbosity of components
68 int QWindowsContext::verboseIntegration = 0;
69 int QWindowsContext::verboseWindows = 0;
70 int QWindowsContext::verboseEvents = 0;
71 int QWindowsContext::verboseBackingStore = 0;
72 int QWindowsContext::verboseFonts = 0;
73 int QWindowsContext::verboseGL = 0;
74 int QWindowsContext::verboseOLE = 0;
75
76 // Get verbosity of components from "foo:2,bar:3"
77 static inline int componentVerbose(const char *v, const char *keyWord)
78 {
79     if (const char *k = strstr(v, keyWord)) {
80         k += qstrlen(keyWord);
81         if (*k == ':') {
82             ++k;
83             if (isdigit(*k))
84                 return *k - '0';
85         }
86     }
87     return 0;
88 }
89
90 static inline bool hasTouchSupport(QSysInfo::WinVersion wv)
91 {
92     enum { QT_SM_DIGITIZER = 94, QT_NID_INTEGRATED_TOUCH = 0x1,
93            QT_NID_EXTERNAL_TOUCH = 0x02, QT_NID_MULTI_INPUT = 0x40 };
94
95     return wv < QSysInfo::WV_WINDOWS7 ? false :
96            (GetSystemMetrics(QT_SM_DIGITIZER) & (QT_NID_INTEGRATED_TOUCH | QT_NID_EXTERNAL_TOUCH | QT_NID_MULTI_INPUT)) != 0;
97 }
98
99 #if !defined(LANG_SYRIAC)
100 #    define LANG_SYRIAC 0x5a
101 #endif
102
103 static inline bool useRTL_Extensions(QSysInfo::WinVersion ver)
104 {
105     if ((ver & QSysInfo::WV_NT_based) && (ver >= QSysInfo::WV_VISTA)) {
106         // Since the IsValidLanguageGroup/IsValidLocale functions always return true on
107         // Vista, check the Keyboard Layouts for enabling RTL.
108         if (const UINT nLayouts = GetKeyboardLayoutList(0, 0)) {
109             QScopedArrayPointer<HKL> lpList(new HKL[nLayouts]);
110             GetKeyboardLayoutList(nLayouts, lpList.data());
111             for (UINT i = 0; i < nLayouts; ++i) {
112                 switch (PRIMARYLANGID((quintptr)lpList[i])) {
113                 case LANG_ARABIC:
114                 case LANG_HEBREW:
115                 case LANG_FARSI:
116                 case LANG_SYRIAC:
117                     return true;
118                 default:
119                     break;
120                 }
121             }
122         }
123         return false;
124     } // NT/Vista
125     // Pre-NT: figure out whether a RTL language is installed
126     return IsValidLanguageGroup(LGRPID_ARABIC, LGRPID_INSTALLED)
127                             || IsValidLanguageGroup(LGRPID_HEBREW, LGRPID_INSTALLED)
128                             || IsValidLocale(MAKELCID(MAKELANGID(LANG_ARABIC, SUBLANG_DEFAULT), SORT_DEFAULT), LCID_INSTALLED)
129                             || IsValidLocale(MAKELCID(MAKELANGID(LANG_HEBREW, SUBLANG_DEFAULT), SORT_DEFAULT), LCID_INSTALLED)
130                             || IsValidLocale(MAKELCID(MAKELANGID(LANG_SYRIAC, SUBLANG_DEFAULT), SORT_DEFAULT), LCID_INSTALLED)
131                             || IsValidLocale(MAKELCID(MAKELANGID(LANG_FARSI, SUBLANG_DEFAULT), SORT_DEFAULT), LCID_INSTALLED);
132 }
133
134 /*!
135     \class QWindowsUser32DLL
136     \brief Struct that contains dynamically resolved symbols of User32.dll.
137
138     The stub libraries shipped with the MinGW compiler miss some of the
139     functions. They need to be retrieved dynamically.
140
141     In addition, touch-related functions are available only from Windows onwards.
142     These need to resolved dynamically for Q_CC_MSVC as well.
143
144     \ingroup qt-lighthouse-win
145 */
146
147 QWindowsUser32DLL::QWindowsUser32DLL() :
148     setLayeredWindowAttributes(0), updateLayeredWindow(0),
149     updateLayeredWindowIndirect(0),
150     isHungAppWindow(0),
151     registerTouchWindow(0), getTouchInputInfo(0), closeTouchInputHandle(0)
152 {
153 }
154
155 void QWindowsUser32DLL::init()
156 {
157     QSystemLibrary library(QStringLiteral("user32"));
158     // MinGW (g++ 3.4.5) accepts only C casts.
159     setLayeredWindowAttributes = (SetLayeredWindowAttributes)(library.resolve("SetLayeredWindowAttributes"));
160     updateLayeredWindow = (UpdateLayeredWindow)(library.resolve("UpdateLayeredWindow"));
161     updateLayeredWindowIndirect = (UpdateLayeredWindowIndirect)(library.resolve("UpdateLayeredWindowIndirect"));
162
163     Q_ASSERT(setLayeredWindowAttributes && updateLayeredWindow
164              && updateLayeredWindowIndirect);
165
166     isHungAppWindow = (IsHungAppWindow)library.resolve("IsHungAppWindow");
167 }
168
169 bool QWindowsUser32DLL::initTouch()
170 {
171     QSystemLibrary library(QStringLiteral("user32"));
172     registerTouchWindow = (RegisterTouchWindow)(library.resolve("RegisterTouchWindow"));
173     getTouchInputInfo = (GetTouchInputInfo)(library.resolve("GetTouchInputInfo"));
174     closeTouchInputHandle = (CloseTouchInputHandle)(library.resolve("CloseTouchInputHandle"));
175     return registerTouchWindow && getTouchInputInfo && getTouchInputInfo;
176 }
177
178 QWindowsUser32DLL QWindowsContext::user32dll;
179
180 QWindowsContext *QWindowsContext::m_instance = 0;
181
182 /*!
183     \class QWindowsContext
184     \brief Singleton container for all relevant information.
185
186     Holds state information formerly stored in \c qapplication_win.cpp.
187     \ingroup qt-lighthouse-win
188 */
189
190 typedef QHash<HWND, QWindowsWindow *> HandleBaseWindowHash;
191
192 struct QWindowsContextPrivate {
193     explicit QWindowsContextPrivate(bool isOpenGL);
194
195     const bool m_isOpenGL;
196     unsigned m_systemInfo;
197     QSet<QString> m_registeredWindowClassNames;
198     HandleBaseWindowHash m_windows;
199     HDC m_displayContext;
200     const int m_defaultDPI;
201     QWindowsKeyMapper m_keyMapper;
202     QWindowsMouseHandler m_mouseHandler;
203     QWindowsMimeConverter m_mimeConverter;
204     QSharedPointer<QWindowCreationContext> m_creationContext;
205     const HRESULT m_oleInitializeResult;
206 };
207
208 QWindowsContextPrivate::QWindowsContextPrivate(bool isOpenGL) :
209     m_isOpenGL(isOpenGL),
210     m_systemInfo(0),
211     m_displayContext(GetDC(0)),
212     m_defaultDPI(GetDeviceCaps(m_displayContext,LOGPIXELSY)),
213     m_oleInitializeResult(OleInitialize(NULL))
214 {
215     QWindowsContext::user32dll.init();
216
217     const QSysInfo::WinVersion ver = QSysInfo::windowsVersion();
218
219     if (hasTouchSupport(ver) && QWindowsContext::user32dll.initTouch())
220         m_systemInfo |= QWindowsContext::SI_SupportsTouch;
221
222     if (useRTL_Extensions(ver)) {
223         m_systemInfo |= QWindowsContext::SI_RTL_Extensions;
224         m_keyMapper.setUseRTLExtensions(true);
225     }
226 }
227
228 QWindowsContext::QWindowsContext(bool isOpenGL) :
229     d(new QWindowsContextPrivate(isOpenGL))
230 {
231 #ifdef Q_CC_MSVC
232 #    pragma warning( disable : 4996 )
233 #endif
234     m_instance = this;
235     if (const char *v = getenv("QT_LIGHTHOUSE_WINDOWS_VERBOSE")) {
236         QWindowsContext::verboseIntegration = componentVerbose(v, "integration");
237         QWindowsContext::verboseWindows = componentVerbose(v, "windows");
238         QWindowsContext::verboseEvents = componentVerbose(v, "events");
239         QWindowsContext::verboseBackingStore = componentVerbose(v, "backingstore");
240         QWindowsContext::verboseFonts = componentVerbose(v, "fonts");
241         QWindowsContext::verboseGL = componentVerbose(v, "gl");
242         QWindowsContext::verboseOLE = componentVerbose(v, "ole");
243     }
244 }
245
246 QWindowsContext::~QWindowsContext()
247 {
248     unregisterWindowClasses();
249     if (d->m_oleInitializeResult == S_OK || d->m_oleInitializeResult == S_FALSE)
250         OleUninitialize();
251
252     m_instance = 0;
253 }
254
255 QWindowsContext *QWindowsContext::instance()
256 {
257     return m_instance;
258 }
259
260 unsigned QWindowsContext::systemInfo() const
261 {
262     return d->m_systemInfo;
263 }
264
265 void QWindowsContext::setWindowCreationContext(const QSharedPointer<QWindowCreationContext> &ctx)
266 {
267     d->m_creationContext = ctx;
268 }
269
270 bool QWindowsContext::isOpenGL() const
271 {
272     return d->m_isOpenGL;
273 }
274
275 int QWindowsContext::defaultDPI() const
276 {
277     return d->m_defaultDPI;
278 }
279
280 HDC QWindowsContext::displayContext() const
281 {
282     return d->m_displayContext;
283 }
284
285 QWindow *QWindowsContext::keyGrabber() const
286 {
287     return d->m_keyMapper.keyGrabber();
288 }
289
290 void QWindowsContext::setKeyGrabber(QWindow *w)
291 {
292     d->m_keyMapper.setKeyGrabber(w);
293 }
294
295 // Window class registering code (from qapplication_win.cpp)
296 // If 0 is passed as the widget pointer, register a window class
297 // for QWidget as default. This is used in QGLTemporaryContext
298 // during GL initialization, where we don't want to use temporary
299 // QWidgets or QGLWidgets, neither do we want to have separate code
300 // to register window classes.
301
302 QString QWindowsContext::registerWindowClass(const QWindow *w, bool isGL)
303 {
304     const Qt::WindowFlags flags = w ? w->windowFlags() : (Qt::WindowFlags)0;
305     const Qt::WindowFlags type = flags & Qt::WindowType_Mask;
306
307     uint style = 0;
308     bool icon = false;
309     QString cname = "Qt5";
310     if (w && isGL) {
311         cname += QStringLiteral("QGLWindow");
312         style = CS_DBLCLKS|CS_OWNDC;
313         icon  = true;
314     } else if (w && (flags & Qt::MSWindowsOwnDC)) {
315         cname += QStringLiteral("QWindowOwnDC");
316         style = CS_DBLCLKS|CS_OWNDC;
317         icon  = true;
318     } else if (w && (type == Qt::Tool || type == Qt::ToolTip)) {
319         style = CS_DBLCLKS;
320         if (w->inherits("QTipLabel") || w->inherits("QAlphaWidget")) {
321             if ((QSysInfo::WindowsVersion >= QSysInfo::WV_XP
322                 && QSysInfo::WindowsVersion < QSysInfo::WV_NT_based)) {
323                 style |= CS_DROPSHADOW;
324             }
325             cname += QStringLiteral("QToolTip");
326         } else {
327             cname += QStringLiteral("QTool");
328         }
329         style |= CS_SAVEBITS;
330         icon = false;
331     } else if (w && (type == Qt::Popup)) {
332         cname += QStringLiteral("QPopup");
333         style = CS_DBLCLKS|CS_SAVEBITS;
334         if ((QSysInfo::WindowsVersion >= QSysInfo::WV_XP
335             && QSysInfo::WindowsVersion < QSysInfo::WV_NT_based))
336             style |= CS_DROPSHADOW;
337         icon = false;
338     } else {
339         cname += QStringLiteral("QWindow");
340         style = CS_DBLCLKS;
341         icon  = true;
342     }
343
344     // force CS_OWNDC when the GL graphics system is
345     // used as the default renderer
346     if (d->m_isOpenGL)
347         style |= CS_OWNDC;
348
349     HBRUSH brush = 0;
350     if (w && !isGL)
351         brush = GetSysColorBrush(COLOR_WINDOW);
352     return registerWindowClass(cname, qWindowsWndProc, style, brush, icon);
353 }
354
355 QString QWindowsContext::registerWindowClass(QString cname,
356                                              WNDPROC proc,
357                                              unsigned style,
358                                              HBRUSH brush,
359                                              bool icon)
360 {
361     // since multiple Qt versions can be used in one process
362     // each one has to have window class names with a unique name
363     // The first instance gets the unmodified name; if the class
364     // has already been registered by another instance of Qt then
365     // add an instance-specific ID, the address of the window proc.
366     static int classExists = -1;
367
368     const HINSTANCE appInstance = (HINSTANCE)GetModuleHandle(0);
369     if (classExists == -1) {
370         WNDCLASS wcinfo;
371         classExists = GetClassInfo(appInstance, (wchar_t*)cname.utf16(), &wcinfo);
372         classExists = classExists && wcinfo.lpfnWndProc != proc;
373     }
374
375     if (classExists)
376         cname += QString::number((quintptr)proc);
377
378     if (d->m_registeredWindowClassNames.contains(cname))        // already registered in our list
379         return cname;
380
381     WNDCLASSEX wc;
382     wc.cbSize       = sizeof(WNDCLASSEX);
383     wc.style        = style;
384     wc.lpfnWndProc  = proc;
385     wc.cbClsExtra   = 0;
386     wc.cbWndExtra   = 0;
387     wc.hInstance    = appInstance;
388     if (icon) {
389         wc.hIcon = (HICON)LoadImage(appInstance, L"IDI_ICON1", IMAGE_ICON, 0, 0, LR_DEFAULTSIZE);
390         if (wc.hIcon) {
391             int sw = GetSystemMetrics(SM_CXSMICON);
392             int sh = GetSystemMetrics(SM_CYSMICON);
393             wc.hIconSm = (HICON)LoadImage(appInstance, L"IDI_ICON1", IMAGE_ICON, sw, sh, 0);
394         } else {
395             wc.hIcon = (HICON)LoadImage(0, IDI_APPLICATION, IMAGE_ICON, 0, 0, LR_DEFAULTSIZE | LR_SHARED);
396             wc.hIconSm = 0;
397         }
398     } else {
399         wc.hIcon    = 0;
400         wc.hIconSm  = 0;
401     }
402     wc.hCursor      = 0;
403     wc.hbrBackground = brush;
404     wc.lpszMenuName  = 0;
405     wc.lpszClassName = (wchar_t*)cname.utf16();
406     ATOM atom = RegisterClassEx(&wc);
407
408     if (!atom)
409         qErrnoWarning("QApplication::regClass: Registering window class '%s' failed.",
410                       qPrintable(cname));
411
412     d->m_registeredWindowClassNames.insert(cname);
413     if (QWindowsContext::verboseIntegration || QWindowsContext::verboseWindows)
414         qDebug().nospace() << __FUNCTION__ << ' ' << cname
415                  << " style=0x" << QString::number(style, 16)
416                  << " brush=" << brush << " icon=" << icon << " atom=" << atom;
417     return cname;
418 }
419
420 void QWindowsContext::unregisterWindowClasses()
421 {
422     const HINSTANCE appInstance = (HINSTANCE)GetModuleHandle(0);
423
424     foreach (const QString &name,  d->m_registeredWindowClassNames) {
425         if (QWindowsContext::verboseIntegration)
426             qDebug() << __FUNCTION__ << name;
427         UnregisterClass((wchar_t*)name.utf16(), appInstance);
428     }
429     d->m_registeredWindowClassNames.clear();
430 }
431
432 int QWindowsContext::screenDepth() const
433 {
434     return GetDeviceCaps(d->m_displayContext, BITSPIXEL);
435 }
436
437 QString QWindowsContext::windowsErrorMessage(unsigned long errorCode)
438 {
439     QString rc = QString::fromLatin1("#%1: ").arg(errorCode);
440     ushort *lpMsgBuf;
441
442     const int len = FormatMessage(
443             FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
444             NULL, errorCode, 0, (LPTSTR)&lpMsgBuf, 0, NULL);
445     if (len) {
446         rc = QString::fromUtf16(lpMsgBuf, len);
447         LocalFree(lpMsgBuf);
448     } else {
449         rc += QString::fromLatin1("<unknown error>");
450     }
451     return rc;
452 }
453
454 void QWindowsContext::addWindow(HWND hwnd, QWindowsWindow *w)
455 {
456     d->m_windows.insert(hwnd, w);
457 }
458
459 void QWindowsContext::removeWindow(HWND hwnd)
460 {
461     const HandleBaseWindowHash::iterator it = d->m_windows.find(hwnd);
462     if (it != d->m_windows.end()) {
463         if (d->m_keyMapper.keyGrabber() == it.value()->window())
464             d->m_keyMapper.setKeyGrabber(0);
465         d->m_windows.erase(it);
466     }
467 }
468
469 QWindowsWindow *QWindowsContext::findPlatformWindow(HWND hwnd) const
470 {
471     return d->m_windows.value(hwnd);
472 }
473
474 QWindow *QWindowsContext::findWindow(HWND hwnd) const
475 {
476     if (const QWindowsWindow *bw = findPlatformWindow(hwnd))
477             return bw->window();
478     return 0;
479 }
480
481 QWindow *QWindowsContext::windowUnderMouse() const
482 {
483     return d->m_mouseHandler.windowUnderMouse();
484 }
485
486 /*!
487     \brief Find a child window at a screen point.
488
489     Deep search for a QWindow at global point, skipping non-owned
490     windows (accessibility?). Implemented using ChildWindowFromPointEx()
491     instead of (historically used) WindowFromPoint() to get a well-defined
492     behaviour for hidden/transparent windows.
493
494     \a cwex_flags are flags of ChildWindowFromPointEx().
495     \a parent is the parent window, pass GetDesktopWindow() for top levels.
496 */
497
498 QWindowsWindow *QWindowsContext::findPlatformWindowAt(HWND parent,
499                                                           const QPoint &screenPointIn,
500                                                           unsigned cwex_flags) const
501 {
502     QWindowsWindow *result = 0;
503     const POINT screenPoint = { screenPointIn.x(), screenPointIn.y() };
504     while (true) {
505         POINT point = screenPoint;
506         ScreenToClient(parent, &point);
507         // Returns parent if inside & none matched.
508         const HWND child = ChildWindowFromPointEx(parent, point, cwex_flags);
509         if (child && child != parent) {
510             if (QWindowsWindow *window = findPlatformWindow(child))
511                 result = window;
512             parent = child;
513         } else {
514             break;
515         }
516     }
517     return result;
518 }
519
520 QWindowsMimeConverter &QWindowsContext::mimeConverter() const
521 {
522     return d->m_mimeConverter;
523 }
524
525 /*!
526     \brief Convenience to create a non-visible dummy window
527     for example used as clipboard watcher or for GL.
528 */
529
530 HWND QWindowsContext::createDummyWindow(const QString &classNameIn,
531                                         const wchar_t *windowName,
532                                         WNDPROC wndProc, DWORD style)
533 {
534     if (!wndProc)
535         wndProc = DefWindowProc;
536     QString className = registerWindowClass(classNameIn, wndProc);
537     return CreateWindowEx(0, (wchar_t*)className.utf16(),
538                           windowName, style,
539                           CW_USEDEFAULT, CW_USEDEFAULT,
540                           CW_USEDEFAULT, CW_USEDEFAULT,
541                           0, NULL, (HINSTANCE)GetModuleHandle(0), NULL);
542 }
543
544 /*!
545     \brief Common COM error strings.
546 */
547
548 QByteArray QWindowsContext::comErrorString(HRESULT hr)
549 {
550     switch (hr) {
551     case S_OK:
552         return QByteArray("S_OK");
553     case S_FALSE:
554         return QByteArray("S_FALSE");
555     case E_UNEXPECTED:
556         return QByteArray("E_UNEXPECTED");
557     case CO_E_ALREADYINITIALIZED:
558         return QByteArray("CO_E_ALREADYINITIALIZED");
559     case CO_E_NOTINITIALIZED:
560         return QByteArray("CO_E_NOTINITIALIZED");
561     case RPC_E_CHANGED_MODE:
562         return QByteArray("RPC_E_CHANGED_MODE");
563     case OLE_E_WRONGCOMPOBJ:
564         return QByteArray("OLE_E_WRONGCOMPOBJ");
565     case CO_E_NOT_SUPPORTED:
566         return QByteArray("CO_E_NOT_SUPPORTED");
567     case E_NOTIMPL:
568         return QByteArray("E_NOTIMPL");
569     case E_INVALIDARG:
570         return QByteArray("");
571     case E_NOINTERFACE:
572         return QByteArray("");
573     case E_POINTER:
574         return QByteArray("");
575     case E_HANDLE:
576         return QByteArray("");
577     case E_ABORT:
578         return QByteArray("");
579     case E_FAIL:
580         return QByteArray("");
581     case E_ACCESSDENIED:
582         return QByteArray("");
583     default:
584         break;
585     }
586     return "Unknown error 0x" + QByteArray::number(quint64(hr), 16);
587 }
588
589 /*!
590      \brief Main windows procedure registered for windows.
591
592      \sa QWindowsGuiEventDispatcher
593 */
594
595 bool QWindowsContext::windowsProc(HWND hwnd, UINT message,
596                                   QtWindows::WindowsEventType et,
597                                   WPARAM wParam, LPARAM lParam, LRESULT *result)
598 {
599     *result = 0;
600     // Events without an associated QWindow or events we are not interested in.
601     switch (et) {
602     case QtWindows::DeactivateApplicationEvent:
603     case QtWindows::DeactivateWindowEvent:
604         QWindowSystemInterface::handleWindowActivated(0);
605         return true;
606     case QtWindows::ClipboardEvent:
607     case QtWindows::DestroyEvent:
608     case QtWindows::UnknownEvent:
609         return false;
610     default:
611         break;
612     }
613
614     QWindowsWindow *platformWindow = findPlatformWindow(hwnd);
615     // Before CreateWindowEx() returns, some events are sent,
616     // for example WM_GETMINMAXINFO asking for size constraints for top levels.
617     // Pass on to current creation context
618     if (!platformWindow && !d->m_creationContext.isNull()) {
619         switch (et) {
620         case QtWindows::QuerySizeHints:
621             d->m_creationContext->applyToMinMaxInfo(reinterpret_cast<MINMAXINFO *>(lParam));
622             return true;
623         case QtWindows::ResizeEvent:
624             d->m_creationContext->obtainedGeometry.setSize(QSize(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)));
625             return true;
626         case QtWindows::MoveEvent:
627             d->m_creationContext->obtainedGeometry.moveTo(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
628             return true;
629         case QtWindows::CalculateSize:
630             return false;
631         default:
632             break;
633         }
634     }
635     if (platformWindow) {
636         if (QWindowsContext::verboseEvents > 1)
637             qDebug().nospace() << "Event window: " << platformWindow->window();
638     } else {
639         qWarning("%s: No Qt Window found for event 0x%x (%s), hwnd=0x%p.",
640                  __FUNCTION__, message,
641                  QWindowsGuiEventDispatcher::windowsMessageName(message), hwnd);
642         return false;
643     }
644
645     MSG msg;
646     msg.hwnd = hwnd;         // re-create MSG structure
647     msg.message = message;   // time and pt fields ignored
648     msg.wParam = wParam;
649     msg.lParam = lParam;
650     msg.pt.x = GET_X_LPARAM(lParam);
651     msg.pt.y = GET_Y_LPARAM(lParam);
652
653     switch (et) {
654     case QtWindows::KeyDownEvent:
655     case QtWindows::KeyEvent:
656     case QtWindows::InputMethodKeyEvent:
657     case QtWindows::InputMethodKeyDownEvent:
658         return d->m_keyMapper.translateKeyEvent(platformWindow->window(), hwnd, msg, result);
659     case QtWindows::MoveEvent:
660         platformWindow->handleMoved();
661         return true;
662     case QtWindows::ResizeEvent:
663         platformWindow->handleResized((int)wParam);
664         return true;
665     case QtWindows::QuerySizeHints:
666         platformWindow->getSizeHints(reinterpret_cast<MINMAXINFO *>(lParam));
667         return true;
668     case QtWindows::CalculateSize:
669         // NCCALCSIZE_PARAMS structure if wParam==TRUE
670         if (wParam && QWindowsContext::verboseWindows) {
671             const NCCALCSIZE_PARAMS *ncp = reinterpret_cast<NCCALCSIZE_PARAMS *>(lParam);
672             qDebug() << platformWindow->window() << *ncp;
673         }
674         break;
675     case QtWindows::ExposeEvent:
676         platformWindow->handleWmPaint(hwnd, message, wParam, lParam);
677         return true;
678     case QtWindows::MouseWheelEvent:
679     case QtWindows::MouseEvent:
680     case QtWindows::NonClientMouseEvent:
681     case QtWindows::LeaveEvent:
682         return d->m_mouseHandler.translateMouseEvent(platformWindow->window(), hwnd, et, msg, result);
683     case QtWindows::TouchEvent:
684         return d->m_mouseHandler.translateTouchEvent(platformWindow->window(), hwnd, et, msg, result);
685     case QtWindows::ActivateWindowEvent:
686         QWindowSystemInterface::handleWindowActivated(platformWindow->window());
687         return true;
688     case QtWindows::ShowEvent:
689         platformWindow->handleShown();
690         return true;
691     case QtWindows::HideEvent:
692         platformWindow->handleHidden();
693         return true;
694     case QtWindows::CloseEvent:
695         QWindowSystemInterface::handleCloseEvent(platformWindow->window());
696         return true;
697     default:
698         break;
699     }
700     return false;
701 }
702
703 /*!
704     \brief Windows functions for actual windows.
705
706     There is another one for timers, sockets, etc in
707     QEventDispatcherWin32.
708
709     \ingroup qt-lighthouse-win
710 */
711
712 extern "C" LRESULT QT_WIN_CALLBACK qWindowsWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
713 {
714     LRESULT result;
715     const QtWindows::WindowsEventType et = windowsEventType(message, wParam);
716     const bool handled = QWindowsContext::instance()->windowsProc(hwnd, message, et, wParam, lParam, &result);
717     const bool guiEventsQueued = QWindowSystemInterface::windowSystemEventsQueued();
718     if (QWindowsContext::verboseEvents > 1)
719         if (const char *eventName = QWindowsGuiEventDispatcher::windowsMessageName(message))
720             qDebug("EVENT: hwd=%p %s msg=0x%x et=0x%x wp=%d at %d,%d handled=%d gui=%d",
721                    hwnd, eventName, message, et, int(wParam),
722                    GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), handled, guiEventsQueued);
723     if (guiEventsQueued) {
724         const QWindowsGuiEventDispatcher::DispatchContext dispatchContext =
725             QWindowsGuiEventDispatcher::currentDispatchContext();
726         if (dispatchContext.first)
727             QWindowSystemInterface::sendWindowSystemEvents(dispatchContext.first, dispatchContext.second);
728     }
729     if (!handled)
730         result = DefWindowProc(hwnd, message, wParam, lParam);
731     return result;
732 }
733
734 QT_END_NAMESPACE