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 ¶mList);
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 ¶meter,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 ¶mList,
183 int *tabletAbsoluteRange,
184 QtWindows::ProcessDpiAwareness *dpiAwareness)
185 {
186 unsigned options = 0;
187 for (const QString ¶m : 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 ¶mList)
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 ¶mList) :
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