1 /****************************************************************************
2 **
3 ** Copyright (C) 2016 The Qt Company Ltd.
4 ** Copyright (C) 2013 Samuel Gaist <samuel.gaist@edeltech.ch>
5 ** Contact: https://www.qt.io/licensing/
6 **
7 ** This file is part of the plugins of the Qt Toolkit.
8 **
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** Commercial License Usage
11 ** Licensees holding valid commercial Qt licenses may use this file in
12 ** accordance with the commercial license agreement provided with the
13 ** Software or, alternatively, in accordance with the terms contained in
14 ** a written agreement between you and The Qt Company. For licensing terms
15 ** and conditions see https://www.qt.io/terms-conditions. For further
16 ** information use the contact form at https://www.qt.io/contact-us.
17 **
18 ** GNU Lesser General Public License Usage
19 ** Alternatively, this file may be used under the terms of the GNU Lesser
20 ** General Public License version 3 as published by the Free Software
21 ** Foundation and appearing in the file LICENSE.LGPL3 included in the
22 ** packaging of this file. Please review the following information to
23 ** ensure the GNU Lesser General Public License version 3 requirements
24 ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
25 **
26 ** GNU General Public License Usage
27 ** Alternatively, this file may be used under the terms of the GNU
28 ** General Public License version 2.0 or (at your option) the GNU General
29 ** Public license version 3 or any later version approved by the KDE Free
30 ** Qt Foundation. The licenses are as published by the Free Software
31 ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
32 ** included in the packaging of this file. Please review the following
33 ** information to ensure the GNU General Public License requirements will
34 ** be met: https://www.gnu.org/licenses/gpl-2.0.html and
35 ** https://www.gnu.org/licenses/gpl-3.0.html.
36 **
37 ** $QT_END_LICENSE$
38 **
39 ****************************************************************************/
40 
41 #include "qwindowsintegration.h"
42 #include "qwindowswindow.h"
43 #include "qwindowscontext.h"
44 #include "qwin10helpers.h"
45 #include "qwindowsmenu.h"
46 #include "qwindowsopenglcontext.h"
47 
48 #include "qwindowsscreen.h"
49 #include "qwindowstheme.h"
50 #include "qwindowsservices.h"
51 #ifndef QT_NO_FREETYPE
52 #  include <QtFontDatabaseSupport/private/qwindowsfontdatabase_ft_p.h>
53 #endif
54 #if QT_CONFIG(clipboard)
55 #  include "qwindowsclipboard.h"
56 #  if QT_CONFIG(draganddrop)
57 #    include "qwindowsdrag.h"
58 #  endif
59 #endif
60 #include "qwindowsinputcontext.h"
61 #include "qwindowskeymapper.h"
62 #if QT_CONFIG(accessibility)
63 #  include "uiautomation/qwindowsuiaaccessibility.h"
64 #endif
65 
66 #include <qpa/qplatformnativeinterface.h>
67 #include <qpa/qwindowsysteminterface.h>
68 #if QT_CONFIG(sessionmanager)
69 #  include "qwindowssessionmanager.h"
70 #endif
71 #include <QtGui/qtouchdevice.h>
72 #include <QtGui/private/qguiapplication_p.h>
73 #include <QtGui/private/qhighdpiscaling_p.h>
74 #include <QtGui/qpa/qplatforminputcontextfactory_p.h>
75 #include <QtGui/qpa/qplatformcursor.h>
76 
77 #include <QtEventDispatcherSupport/private/qwindowsguieventdispatcher_p.h>
78 
79 #include <QtCore/qdebug.h>
80 #include <QtCore/qvariant.h>
81 
82 #include <limits.h>
83 
84 #if defined(QT_OPENGL_ES_2) || defined(QT_OPENGL_DYNAMIC)
85 #  include "qwindowseglcontext.h"
86 #endif
87 #if !defined(QT_NO_OPENGL) && !defined(QT_OPENGL_ES_2)
88 #  include "qwindowsglcontext.h"
89 #endif
90 
91 #include "qwindowsopengltester.h"
92 
initOpenGlBlacklistResources()93 static inline void initOpenGlBlacklistResources()
94 {
95     Q_INIT_RESOURCE(openglblacklists);
96 }
97 
98 QT_BEGIN_NAMESPACE
99 
100 /*!
101     \class QWindowsIntegration
102     \brief QPlatformIntegration implementation for Windows.
103     \internal
104 
105     \section1 Programming Considerations
106 
107     The platform plugin should run on Desktop Windows from Windows XP onwards
108     and Windows Embedded.
109 
110     It should compile with:
111     \list
112     \li Microsoft Visual Studio 2013 or later (using the Microsoft Windows SDK,
113         (\c Q_CC_MSVC).
114     \li Stock \l{http://mingw.org/}{MinGW} (\c Q_CC_MINGW).
115         This version ships with headers that are missing a lot of WinAPI.
116     \li MinGW distributions using GCC 4.7 or higher and a recent MinGW-w64 runtime API,
117         such as \l{http://tdm-gcc.tdragon.net/}{TDM-GCC}, or
118         \l{http://mingwbuilds.sourceforge.net/}{MinGW-builds}
119         (\c Q_CC_MINGW and \c __MINGW64_VERSION_MAJOR indicating the version).
120         MinGW-w64 provides more complete headers (compared to stock MinGW from mingw.org),
121         including a considerable part of the Windows SDK.
122     \endlist
123 
124     When using a function from the WinAPI, the minimum supported Windows version
125     and Windows Embedded support should be checked. If the function is not supported
126     on Windows XP or is not present in the MinGW-headers, it should be dynamically
127     resolved. For this purpose, QWindowsContext has static structs like
128     QWindowsUser32DLL and QWindowsShell32DLL. All function pointers should go to
129     these structs to avoid lookups in several places.
130 
131 */
132 
133 struct QWindowsIntegrationPrivate
134 {
135     Q_DISABLE_COPY_MOVE(QWindowsIntegrationPrivate)
136     explicit QWindowsIntegrationPrivate(const QStringList &paramList);
137     ~QWindowsIntegrationPrivate();
138 
139     unsigned m_options = 0;
140     QWindowsContext m_context;
141     QPlatformFontDatabase *m_fontDatabase = nullptr;
142 #if QT_CONFIG(clipboard)
143     QWindowsClipboard m_clipboard;
144 #  if QT_CONFIG(draganddrop)
145     QWindowsDrag m_drag;
146 #  endif
147 #endif
148 #ifndef QT_NO_OPENGL
149     QMutex m_staticContextLock;
150     QScopedPointer<QWindowsStaticOpenGLContext> m_staticOpenGLContext;
151 #endif // QT_NO_OPENGL
152     QScopedPointer<QPlatformInputContext> m_inputContext;
153 #if QT_CONFIG(accessibility)
154    QWindowsUiaAccessibility m_accessibility;
155 #endif
156     QWindowsServices m_services;
157 };
158 
159 template <typename IntType>
parseIntOption(const QString & parameter,const QLatin1String & option,IntType minimumValue,IntType maximumValue,IntType * target)160 bool parseIntOption(const QString &parameter,const QLatin1String &option,
161                     IntType minimumValue, IntType maximumValue, IntType *target)
162 {
163     const int valueLength = parameter.size() - option.size() - 1;
164     if (valueLength < 1 || !parameter.startsWith(option) || parameter.at(option.size()) != u'=')
165         return false;
166     bool ok;
167     const QStringRef valueRef = parameter.rightRef(valueLength);
168     const int value = valueRef.toInt(&ok);
169     if (ok) {
170         if (value >= minimumValue && value <= maximumValue)
171             *target = static_cast<IntType>(value);
172         else {
173             qWarning() << "Value" << value << "for option" << option << "out of range"
174                 << minimumValue << ".." << maximumValue;
175         }
176     } else {
177         qWarning() << "Invalid value" << valueRef << "for option" << option;
178     }
179     return true;
180 }
181 
parseOptions(const QStringList & paramList,int * tabletAbsoluteRange,QtWindows::ProcessDpiAwareness * dpiAwareness)182 static inline unsigned parseOptions(const QStringList &paramList,
183                                     int *tabletAbsoluteRange,
184                                     QtWindows::ProcessDpiAwareness *dpiAwareness)
185 {
186     unsigned options = 0;
187     for (const QString &param : paramList) {
188         if (param.startsWith(u"fontengine=")) {
189             if (param.endsWith(u"freetype")) {
190                 options |= QWindowsIntegration::FontDatabaseFreeType;
191             } else if (param.endsWith(u"native")) {
192                 options |= QWindowsIntegration::FontDatabaseNative;
193             }
194         } else if (param.startsWith(u"dialogs=")) {
195             if (param.endsWith(u"xp")) {
196                 options |= QWindowsIntegration::XpNativeDialogs;
197             } else if (param.endsWith(u"none")) {
198                 options |= QWindowsIntegration::NoNativeDialogs;
199             }
200         } else if (param == u"altgr") {
201             options |= QWindowsIntegration::DetectAltGrModifier;
202         } else if (param == u"gl=gdi") {
203             options |= QWindowsIntegration::DisableArb;
204         } else if (param == u"nodirectwrite") {
205             options |= QWindowsIntegration::DontUseDirectWriteFonts;
206         } else if (param == u"nocolorfonts") {
207             options |= QWindowsIntegration::DontUseColorFonts;
208         } else if (param == u"nomousefromtouch") {
209             options |= QWindowsIntegration::DontPassOsMouseEventsSynthesizedFromTouch;
210         } else if (parseIntOption(param, QLatin1String("verbose"), 0, INT_MAX, &QWindowsContext::verbose)
211             || parseIntOption(param, QLatin1String("tabletabsoluterange"), 0, INT_MAX, tabletAbsoluteRange)
212             || parseIntOption(param, QLatin1String("dpiawareness"), QtWindows::ProcessDpiUnaware, QtWindows::ProcessPerMonitorDpiAware, dpiAwareness)) {
213         } else if (param == u"menus=native") {
214             options |= QWindowsIntegration::AlwaysUseNativeMenus;
215         } else if (param == u"menus=none") {
216             options |= QWindowsIntegration::NoNativeMenus;
217         } else if (param == u"nowmpointer") {
218             options |= QWindowsIntegration::DontUseWMPointer;
219         } else if (param == u"reverse") {
220             options |= QWindowsIntegration::RtlEnabled;
221         } else if (param == u"darkmode=1") {
222             options |= QWindowsIntegration::DarkModeWindowFrames;
223         } else if (param == u"darkmode=2") {
224             options |= QWindowsIntegration::DarkModeWindowFrames | QWindowsIntegration::DarkModeStyle;
225         } else {
226             qWarning() << "Unknown option" << param;
227         }
228     }
229     return options;
230 }
231 
QWindowsIntegrationPrivate(const QStringList & paramList)232 QWindowsIntegrationPrivate::QWindowsIntegrationPrivate(const QStringList &paramList)
233 {
234     initOpenGlBlacklistResources();
235 
236     static bool dpiAwarenessSet = false;
237     int tabletAbsoluteRange = -1;
238     // Default to per-monitor awareness to avoid being scaled when monitors with different DPI
239     // are connected to Windows 8.1
240     QtWindows::ProcessDpiAwareness dpiAwareness = QtWindows::ProcessPerMonitorDpiAware;
241     m_options = parseOptions(paramList, &tabletAbsoluteRange, &dpiAwareness);
242     QWindowsFontDatabase::setFontOptions(m_options);
243 
244     if (m_context.initPointer(m_options)) {
245         QCoreApplication::setAttribute(Qt::AA_CompressHighFrequencyEvents);
246     } else {
247         m_context.initTablet(m_options);
248         if (tabletAbsoluteRange >= 0)
249             m_context.setTabletAbsoluteRange(tabletAbsoluteRange);
250     }
251 
252     if (!dpiAwarenessSet) { // Set only once in case of repeated instantiations of QGuiApplication.
253         if (!QCoreApplication::testAttribute(Qt::AA_PluginApplication)) {
254             m_context.setProcessDpiAwareness(dpiAwareness);
255             qCDebug(lcQpaWindows)
256                 << __FUNCTION__ << "DpiAwareness=" << dpiAwareness
257                 << "effective process DPI awareness=" << QWindowsContext::processDpiAwareness();
258         }
259         dpiAwarenessSet = true;
260     }
261 
262     m_context.initTouch(m_options);
263     QPlatformCursor::setCapability(QPlatformCursor::OverrideCursor);
264 
265     m_context.initPowerNotificationHandler();
266 }
267 
~QWindowsIntegrationPrivate()268 QWindowsIntegrationPrivate::~QWindowsIntegrationPrivate()
269 {
270     delete m_fontDatabase;
271 }
272 
273 QWindowsIntegration *QWindowsIntegration::m_instance = nullptr;
274 
QWindowsIntegration(const QStringList & paramList)275 QWindowsIntegration::QWindowsIntegration(const QStringList &paramList) :
276     d(new QWindowsIntegrationPrivate(paramList))
277 {
278     m_instance = this;
279 #if QT_CONFIG(clipboard)
280     d->m_clipboard.registerViewer();
281 #endif
282     d->m_context.screenManager().handleScreenChanges();
283     d->m_context.setDetectAltGrModifier((d->m_options & DetectAltGrModifier) != 0);
284 }
285 
~QWindowsIntegration()286 QWindowsIntegration::~QWindowsIntegration()
287 {
288     m_instance = nullptr;
289 }
290 
initialize()291 void QWindowsIntegration::initialize()
292 {
293     QString icStr = QPlatformInputContextFactory::requested();
294     icStr.isNull() ? d->m_inputContext.reset(new QWindowsInputContext)
295                    : d->m_inputContext.reset(QPlatformInputContextFactory::create(icStr));
296 }
297 
hasCapability(QPlatformIntegration::Capability cap) const298 bool QWindowsIntegration::hasCapability(QPlatformIntegration::Capability cap) const
299 {
300     switch (cap) {
301     case ThreadedPixmaps:
302         return true;
303 #ifndef QT_NO_OPENGL
304     case OpenGL:
305         return true;
306     case ThreadedOpenGL:
307         if (const QWindowsStaticOpenGLContext *glContext = QWindowsIntegration::staticOpenGLContext())
308             return glContext->supportsThreadedOpenGL();
309         return false;
310 #endif // !QT_NO_OPENGL
311     case WindowMasks:
312         return true;
313     case MultipleWindows:
314         return true;
315     case ForeignWindows:
316         return true;
317     case RasterGLSurface:
318         return true;
319     case AllGLFunctionsQueryable:
320         return true;
321     case SwitchableWidgetComposition:
322         return false; // QTBUG-68329 QTBUG-53515 QTBUG-54734
323     default:
324         return QPlatformIntegration::hasCapability(cap);
325     }
326     return false;
327 }
328 
createPlatformWindow(QWindow * window) const329 QPlatformWindow *QWindowsIntegration::createPlatformWindow(QWindow *window) const
330 {
331     if (window->type() == Qt::Desktop) {
332         auto *result = new QWindowsDesktopWindow(window);
333         qCDebug(lcQpaWindows) << "Desktop window:" << window
334             << Qt::showbase << Qt::hex << result->winId() << Qt::noshowbase << Qt::dec << result->geometry();
335         return result;
336     }
337 
338     QWindowsWindowData requested;
339     requested.flags = window->flags();
340     requested.geometry = window->isTopLevel()
341         ? QHighDpi::toNativePixels(window->geometry(), window)
342         : QHighDpi::toNativeLocalPosition(window->geometry(), window);
343     // Apply custom margins (see  QWindowsWindow::setCustomMargins())).
344     const QVariant customMarginsV = window->property("_q_windowsCustomMargins");
345     if (customMarginsV.isValid())
346         requested.customMargins = qvariant_cast<QMargins>(customMarginsV);
347 
348     QWindowsWindowData obtained =
349         QWindowsWindowData::create(window, requested,
350                                    QWindowsWindow::formatWindowTitle(window->title()));
351     qCDebug(lcQpaWindows).nospace()
352         << __FUNCTION__ << ' ' << window
353         << "\n    Requested: " << requested.geometry << " frame incl.="
354         << QWindowsGeometryHint::positionIncludesFrame(window)
355         << ' ' << requested.flags
356         << "\n    Obtained : " << obtained.geometry << " margins=" << obtained.fullFrameMargins
357         << " handle=" << obtained.hwnd << ' ' << obtained.flags << '\n';
358 
359     if (Q_UNLIKELY(!obtained.hwnd))
360         return nullptr;
361 
362     QWindowsWindow *result = createPlatformWindowHelper(window, obtained);
363     Q_ASSERT(result);
364 
365     if (window->isTopLevel() && !QWindowsContext::shouldHaveNonClientDpiScaling(window))
366         result->setFlag(QWindowsWindow::DisableNonClientScaling);
367 
368     if (QWindowsMenuBar *menuBarToBeInstalled = QWindowsMenuBar::menuBarOf(window))
369         menuBarToBeInstalled->install(result);
370 
371     return result;
372 }
373 
createForeignWindow(QWindow * window,WId nativeHandle) const374 QPlatformWindow *QWindowsIntegration::createForeignWindow(QWindow *window, WId nativeHandle) const
375 {
376     const HWND hwnd = reinterpret_cast<HWND>(nativeHandle);
377     if (!IsWindow(hwnd)) {
378        qWarning("Windows QPA: Invalid foreign window ID %p.", hwnd);
379        return nullptr;
380     }
381     auto *result = new QWindowsForeignWindow(window, hwnd);
382     const QRect obtainedGeometry = result->geometry();
383     QScreen *screen = nullptr;
384     if (const QPlatformScreen *pScreen = result->screenForGeometry(obtainedGeometry))
385         screen = pScreen->screen();
386     if (screen && screen != window->screen())
387         window->setScreen(screen);
388     qCDebug(lcQpaWindows) << "Foreign window:" << window << Qt::showbase << Qt::hex
389         << result->winId() << Qt::noshowbase << Qt::dec << obtainedGeometry << screen;
390     return result;
391 }
392 
393 // Overridden to return a QWindowsDirect2DWindow in Direct2D plugin.
createPlatformWindowHelper(QWindow * window,const QWindowsWindowData & data) const394 QWindowsWindow *QWindowsIntegration::createPlatformWindowHelper(QWindow *window, const QWindowsWindowData &data) const
395 {
396     return new QWindowsWindow(window, data);
397 }
398 
399 #ifndef QT_NO_OPENGL
400 
doCreate()401 QWindowsStaticOpenGLContext *QWindowsStaticOpenGLContext::doCreate()
402 {
403 #if defined(QT_OPENGL_DYNAMIC)
404     QWindowsOpenGLTester::Renderer requestedRenderer = QWindowsOpenGLTester::requestedRenderer();
405     switch (requestedRenderer) {
406     case QWindowsOpenGLTester::DesktopGl:
407         if (QWindowsStaticOpenGLContext *glCtx = QOpenGLStaticContext::create()) {
408             if ((QWindowsOpenGLTester::supportedRenderers(requestedRenderer) & QWindowsOpenGLTester::DisableRotationFlag)
409                 && !QWindowsScreen::setOrientationPreference(Qt::LandscapeOrientation)) {
410                 qCWarning(lcQpaGl, "Unable to disable rotation.");
411             }
412             return glCtx;
413         }
414         qCWarning(lcQpaGl, "System OpenGL failed. Falling back to Software OpenGL.");
415         return QOpenGLStaticContext::create(true);
416     // If ANGLE is requested, use it, don't try anything else.
417     case QWindowsOpenGLTester::AngleRendererD3d9:
418     case QWindowsOpenGLTester::AngleRendererD3d11:
419     case QWindowsOpenGLTester::AngleRendererD3d11Warp:
420         return QWindowsEGLStaticContext::create(requestedRenderer);
421     case QWindowsOpenGLTester::Gles:
422         return QWindowsEGLStaticContext::create(requestedRenderer);
423     case QWindowsOpenGLTester::SoftwareRasterizer:
424         if (QWindowsStaticOpenGLContext *swCtx = QOpenGLStaticContext::create(true))
425             return swCtx;
426         qCWarning(lcQpaGl, "Software OpenGL failed. Falling back to system OpenGL.");
427         if (QWindowsOpenGLTester::supportedRenderers(requestedRenderer) & QWindowsOpenGLTester::DesktopGl)
428             return QOpenGLStaticContext::create();
429         return nullptr;
430     default:
431         break;
432     }
433 
434     const QWindowsOpenGLTester::Renderers supportedRenderers = QWindowsOpenGLTester::supportedRenderers(requestedRenderer);
435     if (supportedRenderers.testFlag(QWindowsOpenGLTester::DisableProgramCacheFlag)
436         && !QCoreApplication::testAttribute(Qt::AA_DisableShaderDiskCache)) {
437         QCoreApplication::setAttribute(Qt::AA_DisableShaderDiskCache);
438     }
439     if (supportedRenderers & QWindowsOpenGLTester::DesktopGl) {
440         if (QWindowsStaticOpenGLContext *glCtx = QOpenGLStaticContext::create()) {
441             if ((supportedRenderers & QWindowsOpenGLTester::DisableRotationFlag)
442                 && !QWindowsScreen::setOrientationPreference(Qt::LandscapeOrientation)) {
443                 qCWarning(lcQpaGl, "Unable to disable rotation.");
444             }
445             return glCtx;
446         }
447     }
448     if (QWindowsOpenGLTester::Renderers glesRenderers = supportedRenderers & QWindowsOpenGLTester::GlesMask) {
449         if (QWindowsEGLStaticContext *eglCtx = QWindowsEGLStaticContext::create(glesRenderers))
450             return eglCtx;
451     }
452     return QOpenGLStaticContext::create(true);
453 #elif defined(QT_OPENGL_ES_2)
454     QWindowsOpenGLTester::Renderers glesRenderers = QWindowsOpenGLTester::requestedGlesRenderer();
455     if (glesRenderers == QWindowsOpenGLTester::InvalidRenderer)
456         glesRenderers = QWindowsOpenGLTester::supportedRenderers(QWindowsOpenGLTester::AngleRendererD3d11);
457     return QWindowsEGLStaticContext::create(glesRenderers);
458 #elif !defined(QT_NO_OPENGL)
459     return QOpenGLStaticContext::create();
460 #endif
461 }
462 
create()463 QWindowsStaticOpenGLContext *QWindowsStaticOpenGLContext::create()
464 {
465     return QWindowsStaticOpenGLContext::doCreate();
466 }
467 
createPlatformOpenGLContext(QOpenGLContext * context) const468 QPlatformOpenGLContext *QWindowsIntegration::createPlatformOpenGLContext(QOpenGLContext *context) const
469 {
470     qCDebug(lcQpaGl) << __FUNCTION__ << context->format();
471     if (QWindowsStaticOpenGLContext *staticOpenGLContext = QWindowsIntegration::staticOpenGLContext()) {
472         QScopedPointer<QWindowsOpenGLContext> result(staticOpenGLContext->createContext(context));
473         if (result->isValid())
474             return result.take();
475     }
476     return nullptr;
477 }
478 
openGLModuleType()479 QOpenGLContext::OpenGLModuleType QWindowsIntegration::openGLModuleType()
480 {
481 #if defined(QT_OPENGL_ES_2)
482     return QOpenGLContext::LibGLES;
483 #elif !defined(QT_OPENGL_DYNAMIC)
484     return QOpenGLContext::LibGL;
485 #else
486     if (const QWindowsStaticOpenGLContext *staticOpenGLContext = QWindowsIntegration::staticOpenGLContext())
487         return staticOpenGLContext->moduleType();
488     return QOpenGLContext::LibGL;
489 #endif
490 }
491 
staticOpenGLContext()492 QWindowsStaticOpenGLContext *QWindowsIntegration::staticOpenGLContext()
493 {
494     QWindowsIntegration *integration = QWindowsIntegration::instance();
495     if (!integration)
496         return nullptr;
497     QWindowsIntegrationPrivate *d = integration->d.data();
498     QMutexLocker lock(&d->m_staticContextLock);
499     if (d->m_staticOpenGLContext.isNull())
500         d->m_staticOpenGLContext.reset(QWindowsStaticOpenGLContext::create());
501     return d->m_staticOpenGLContext.data();
502 }
503 #endif // !QT_NO_OPENGL
504 
fontDatabase() const505 QPlatformFontDatabase *QWindowsIntegration::fontDatabase() const
506 {
507     if (!d->m_fontDatabase) {
508 #ifdef QT_NO_FREETYPE
509         d->m_fontDatabase = new QWindowsFontDatabase();
510 #else // QT_NO_FREETYPE
511         if (d->m_options & QWindowsIntegration::FontDatabaseFreeType)
512             d->m_fontDatabase = new QWindowsFontDatabaseFT;
513         else
514             d->m_fontDatabase = new QWindowsFontDatabase;
515 #endif // QT_NO_FREETYPE
516     }
517     return d->m_fontDatabase;
518 }
519 
520 #ifdef SPI_GETKEYBOARDSPEED
keyBoardAutoRepeatRateMS()521 static inline int keyBoardAutoRepeatRateMS()
522 {
523   DWORD time = 0;
524   if (SystemParametersInfo(SPI_GETKEYBOARDSPEED, 0, &time, 0))
525       return time ? 1000 / static_cast<int>(time) : 500;
526   return 30;
527 }
528 #endif
529 
styleHint(QPlatformIntegration::StyleHint hint) const530 QVariant QWindowsIntegration::styleHint(QPlatformIntegration::StyleHint hint) const
531 {
532     switch (hint) {
533     case QPlatformIntegration::CursorFlashTime:
534         if (const unsigned timeMS = GetCaretBlinkTime())
535             return QVariant(timeMS != INFINITE ? int(timeMS) * 2 : 0);
536         break;
537 #ifdef SPI_GETKEYBOARDSPEED
538     case KeyboardAutoRepeatRate:
539         return QVariant(keyBoardAutoRepeatRateMS());
540 #endif
541     case QPlatformIntegration::ShowIsMaximized:
542     case QPlatformIntegration::StartDragTime:
543     case QPlatformIntegration::StartDragDistance:
544     case QPlatformIntegration::KeyboardInputInterval:
545     case QPlatformIntegration::ShowIsFullScreen:
546     case QPlatformIntegration::PasswordMaskDelay:
547     case QPlatformIntegration::StartDragVelocity:
548         break; // Not implemented
549     case QPlatformIntegration::FontSmoothingGamma:
550         return QVariant(QWindowsFontDatabase::fontSmoothingGamma());
551     case QPlatformIntegration::MouseDoubleClickInterval:
552         if (const UINT ms = GetDoubleClickTime())
553             return QVariant(int(ms));
554         break;
555     case QPlatformIntegration::UseRtlExtensions:
556         return QVariant(d->m_context.useRTLExtensions());
557     default:
558         break;
559     }
560     return QPlatformIntegration::styleHint(hint);
561 }
562 
queryKeyboardModifiers() const563 Qt::KeyboardModifiers QWindowsIntegration::queryKeyboardModifiers() const
564 {
565     return QWindowsKeyMapper::queryKeyboardModifiers();
566 }
567 
possibleKeys(const QKeyEvent * e) const568 QList<int> QWindowsIntegration::possibleKeys(const QKeyEvent *e) const
569 {
570     return d->m_context.possibleKeys(e);
571 }
572 
573 #if QT_CONFIG(clipboard)
clipboard() const574 QPlatformClipboard * QWindowsIntegration::clipboard() const
575 {
576     return &d->m_clipboard;
577 }
578 #  if QT_CONFIG(draganddrop)
drag() const579 QPlatformDrag *QWindowsIntegration::drag() const
580 {
581     return &d->m_drag;
582 }
583 #  endif // QT_CONFIG(draganddrop)
584 #endif // !QT_NO_CLIPBOARD
585 
inputContext() const586 QPlatformInputContext * QWindowsIntegration::inputContext() const
587 {
588     return d->m_inputContext.data();
589 }
590 
591 #if QT_CONFIG(accessibility)
accessibility() const592 QPlatformAccessibility *QWindowsIntegration::accessibility() const
593 {
594     return &d->m_accessibility;
595 }
596 #endif
597 
options() const598 unsigned QWindowsIntegration::options() const
599 {
600     return d->m_options;
601 }
602 
603 #if QT_CONFIG(sessionmanager)
createPlatformSessionManager(const QString & id,const QString & key) const604 QPlatformSessionManager *QWindowsIntegration::createPlatformSessionManager(const QString &id, const QString &key) const
605 {
606     return new QWindowsSessionManager(id, key);
607 }
608 #endif
609 
createEventDispatcher() const610 QAbstractEventDispatcher * QWindowsIntegration::createEventDispatcher() const
611 {
612     return new QWindowsGuiEventDispatcher;
613 }
614 
themeNames() const615 QStringList QWindowsIntegration::themeNames() const
616 {
617     return QStringList(QLatin1String(QWindowsTheme::name));
618 }
619 
createPlatformTheme(const QString & name) const620 QPlatformTheme *QWindowsIntegration::createPlatformTheme(const QString &name) const
621 {
622     if (name == QLatin1String(QWindowsTheme::name))
623         return new QWindowsTheme;
624     return QPlatformIntegration::createPlatformTheme(name);
625 }
626 
services() const627 QPlatformServices *QWindowsIntegration::services() const
628 {
629     return &d->m_services;
630 }
631 
beep() const632 void QWindowsIntegration::beep() const
633 {
634     MessageBeep(MB_OK);  // For QApplication
635 }
636 
637 #if QT_CONFIG(vulkan)
createPlatformVulkanInstance(QVulkanInstance * instance) const638 QPlatformVulkanInstance *QWindowsIntegration::createPlatformVulkanInstance(QVulkanInstance *instance) const
639 {
640     return new QWindowsVulkanInstance(instance);
641 }
642 #endif
643 
644 QT_END_NAMESPACE
645