1 /****************************************************************************
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
6 ** This file is part of the plugins of the Qt Toolkit.
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
40 ****************************************************************************/
42 #include "qwindowsintegration.h"
43 #include "qwindowsbackingstore.h"
44 #include "qwindowswindow.h"
45 #include "qwindowscontext.h"
46 #if defined(QT_OPENGL_ES_2)
47 # include "qwindowseglcontext.h"
48 # include <QtGui/QOpenGLContext>
49 #elif !defined(QT_NO_OPENGL)
50 # include "qwindowsglcontext.h"
52 #include "qwindowsscreen.h"
53 #include "qwindowstheme.h"
54 #include "qwindowsservices.h"
55 #ifndef QT_NO_FREETYPE
56 # include "qwindowsfontdatabase_ft.h"
58 #include "qwindowsfontdatabase.h"
59 #include "qwindowsguieventdispatcher.h"
60 #ifndef QT_NO_CLIPBOARD
61 # include "qwindowsclipboard.h"
63 #include "qwindowsdrag.h"
64 #include "qwindowsinputcontext.h"
65 #include "qwindowskeymapper.h"
66 # ifndef QT_NO_ACCESSIBILITY
67 #include "accessible/qwindowsaccessibility.h"
70 #include <qpa/qplatformnativeinterface.h>
71 #include <qpa/qwindowsysteminterface.h>
72 #include <QtGui/QBackingStore>
73 #include <QtGui/private/qpixmap_raster_p.h>
74 #include <QtGui/private/qguiapplication_p.h>
76 #include <QtCore/private/qeventdispatcher_win_p.h>
77 #include <QtCore/QDebug>
82 \class QWindowsNativeInterface
83 \brief Provides access to native handles.
85 Currently implemented keys
89 \li releaseDC Releases the previously acquired DC and returns 0.
93 \ingroup qt-lighthouse-win
96 class QWindowsNativeInterface : public QPlatformNativeInterface
101 virtual void *nativeResourceForContext(const QByteArray &resource, QOpenGLContext *context);
103 virtual void *nativeResourceForWindow(const QByteArray &resource, QWindow *window);
104 virtual void *nativeResourceForBackingStore(const QByteArray &resource, QBackingStore *bs);
106 Q_INVOKABLE void *createMessageWindow(const QString &classNameTemplate,
107 const QString &windowName,
108 void *eventProc) const;
111 void *QWindowsNativeInterface::nativeResourceForWindow(const QByteArray &resource, QWindow *window)
113 if (!window || !window->handle()) {
114 qWarning("%s: '%s' requested for null window or window without handle.", __FUNCTION__, resource.constData());
117 QWindowsWindow *bw = static_cast<QWindowsWindow *>(window->handle());
118 if (resource == "handle")
120 if (window->surfaceType() == QWindow::RasterSurface) {
121 if (resource == "getDC")
123 if (resource == "releaseDC") {
128 qWarning("%s: Invalid key '%s' requested.", __FUNCTION__, resource.constData());
132 void *QWindowsNativeInterface::nativeResourceForBackingStore(const QByteArray &resource, QBackingStore *bs)
134 if (!bs || !bs->handle()) {
135 qWarning("%s: '%s' requested for null backingstore or backingstore without handle.", __FUNCTION__, resource.constData());
138 QWindowsBackingStore *wbs = static_cast<QWindowsBackingStore *>(bs->handle());
139 if (resource == "getDC")
141 qWarning("%s: Invalid key '%s' requested.", __FUNCTION__, resource.constData());
146 void *QWindowsNativeInterface::nativeResourceForContext(const QByteArray &resource, QOpenGLContext *context)
148 if (!context || !context->handle()) {
149 qWarning("%s: '%s' requested for null context or context without handle.", __FUNCTION__, resource.constData());
152 #ifdef QT_OPENGL_ES_2
153 QWindowsEGLContext *windowsEglContext = static_cast<QWindowsEGLContext *>(context->handle());
154 if (resource == QByteArrayLiteral("eglDisplay"))
155 return windowsEglContext->eglDisplay();
156 if (resource == QByteArrayLiteral("eglContext"))
157 return windowsEglContext->eglContext();
158 if (resource == QByteArrayLiteral("eglConfig"))
159 return windowsEglContext->eglConfig();
160 #else // QT_OPENGL_ES_2
161 QWindowsGLContext *windowsContext = static_cast<QWindowsGLContext *>(context->handle());
162 if (resource == QByteArrayLiteral("renderingContext"))
163 return windowsContext->renderingContext();
164 #endif // !QT_OPENGL_ES_2
166 qWarning("%s: Invalid key '%s' requested.", __FUNCTION__, resource.constData());
169 #endif // !QT_NO_OPENGL
172 \brief Creates a non-visible window handle for filtering messages.
175 void *QWindowsNativeInterface::createMessageWindow(const QString &classNameTemplate,
176 const QString &windowName,
177 void *eventProc) const
179 QWindowsContext *ctx = QWindowsContext::instance();
180 const HWND hwnd = ctx->createDummyWindow(classNameTemplate,
181 (wchar_t*)windowName.utf16(),
187 \class QWindowsIntegration
188 \brief QPlatformIntegration implementation for Windows.
190 \ingroup qt-lighthouse-win
193 struct QWindowsIntegrationPrivate
195 #if defined(QT_OPENGL_ES_2)
196 typedef QSharedPointer<QWindowsEGLStaticContext> QEGLStaticContextPtr;
197 #elif !defined(QT_NO_OPENGL)
198 typedef QSharedPointer<QOpenGLStaticContext> QOpenGLStaticContextPtr;
201 QWindowsIntegrationPrivate();
202 ~QWindowsIntegrationPrivate();
204 QWindowsContext m_context;
205 QPlatformFontDatabase *m_fontDatabase;
206 QWindowsNativeInterface m_nativeInterface;
207 #ifndef QT_NO_CLIPBOARD
208 QWindowsClipboard m_clipboard;
211 QWindowsGuiEventDispatcher *m_eventDispatcher;
212 #if defined(QT_OPENGL_ES_2)
213 QEGLStaticContextPtr m_staticEGLContext;
214 #elif !defined(QT_NO_OPENGL)
215 QOpenGLStaticContextPtr m_staticOpenGLContext;
217 QWindowsInputContext m_inputContext;
218 #ifndef QT_NO_ACCESSIBILITY
219 QWindowsAccessibility m_accessibility;
221 QWindowsServices m_services;
224 QWindowsIntegrationPrivate::QWindowsIntegrationPrivate()
225 : m_fontDatabase(0), m_eventDispatcher(new QWindowsGuiEventDispatcher)
229 QWindowsIntegrationPrivate::~QWindowsIntegrationPrivate()
232 delete m_fontDatabase;
235 QWindowsIntegration::QWindowsIntegration() :
236 d(new QWindowsIntegrationPrivate)
238 QGuiApplicationPrivate::instance()->setEventDispatcher(d->m_eventDispatcher);
239 #ifndef QT_NO_CLIPBOARD
240 d->m_clipboard.registerViewer();
242 d->m_context.screenManager().handleScreenChanges();
245 QWindowsIntegration::~QWindowsIntegration()
247 if (QWindowsContext::verboseIntegration)
248 qDebug("%s", __FUNCTION__);
251 bool QWindowsIntegration::hasCapability(QPlatformIntegration::Capability cap) const
254 case ThreadedPixmaps:
260 # ifdef QT_OPENGL_ES_2
261 return QWindowsEGLContext::hasThreadedOpenGLCapability();
264 # endif // QT_OPENGL_ES_2
265 #endif // !QT_NO_OPENGL
269 return QPlatformIntegration::hasCapability(cap);
274 QPlatformPixmap *QWindowsIntegration::createPlatformPixmap(QPlatformPixmap::PixelType type) const
276 return new QRasterPlatformPixmap(type);
279 QPlatformWindow *QWindowsIntegration::createPlatformWindow(QWindow *window) const
281 QWindowsWindow::WindowData requested;
282 requested.flags = window->windowFlags();
283 requested.geometry = window->geometry();
284 const QWindowsWindow::WindowData obtained
285 = QWindowsWindow::WindowData::create(window, requested, window->windowTitle());
286 if (QWindowsContext::verboseIntegration || QWindowsContext::verboseWindows)
288 << __FUNCTION__ << '<' << window << '\n'
289 << " Requested: " << requested.geometry << "frame incl.: "
290 << QWindowsGeometryHint::positionIncludesFrame(window)
292 << QWindowsWindow::debugWindowFlags(requested.flags) << '\n'
293 << " Obtained : " << obtained.geometry << " Margins "
294 << obtained.frame << " Flags="
295 << QWindowsWindow::debugWindowFlags(obtained.flags)
296 << " Handle=" << obtained.hwnd << '\n';
299 if (requested.flags != obtained.flags)
300 window->setWindowFlags(obtained.flags);
301 return new QWindowsWindow(window, obtained);
304 QPlatformBackingStore *QWindowsIntegration::createPlatformBackingStore(QWindow *window) const
306 if (QWindowsContext::verboseIntegration)
307 qDebug() << __FUNCTION__ << window;
308 return new QWindowsBackingStore(window);
312 QPlatformOpenGLContext
313 *QWindowsIntegration::createPlatformOpenGLContext(QOpenGLContext *context) const
315 if (QWindowsContext::verboseIntegration)
316 qDebug() << __FUNCTION__ << context->format();
317 #ifdef QT_OPENGL_ES_2
318 if (d->m_staticEGLContext.isNull()) {
319 QWindowsEGLStaticContext *staticContext = QWindowsEGLStaticContext::create();
322 d->m_staticEGLContext = QSharedPointer<QWindowsEGLStaticContext>(staticContext);
324 return new QWindowsEGLContext(d->m_staticEGLContext, context->format(), context->handle());
325 #else // QT_OPENGL_ES_2
326 if (d->m_staticOpenGLContext.isNull())
327 d->m_staticOpenGLContext =
328 QSharedPointer<QOpenGLStaticContext>(QOpenGLStaticContext::create());
329 QScopedPointer<QWindowsGLContext> result(new QWindowsGLContext(d->m_staticOpenGLContext, context));
330 if (result->isValid())
331 return result.take();
333 #endif // !QT_OPENGL_ES_2
335 #endif // !QT_NO_OPENGL
337 /* Workaround for QTBUG-24205: In 'Auto', pick the FreeType engine for
338 * QML2 applications. */
340 enum FontDatabaseOption {
341 FontDatabaseFreeType,
345 static inline FontDatabaseOption fontDatabaseOption(const QObject &nativeInterface)
347 const QVariant argumentV = nativeInterface.property("fontengine");
348 if (argumentV.isValid()) {
349 const QString argument = argumentV.toString();
350 if (argument == QLatin1String("freetype"))
351 return FontDatabaseFreeType;
352 if (argument == QLatin1String("native"))
353 return FontDatabaseNative;
355 return FontDatabaseNative;
358 QPlatformFontDatabase *QWindowsIntegration::fontDatabase() const
360 if (!d->m_fontDatabase) {
361 #ifdef QT_NO_FREETYPE
362 d->m_fontDatabase = new QWindowsFontDatabase();
364 FontDatabaseOption option = fontDatabaseOption(d->m_nativeInterface);
365 if (option == FontDatabaseFreeType) {
366 d->m_fontDatabase = new QWindowsFontDatabaseFT;
368 d->m_fontDatabase = new QWindowsFontDatabase;
372 return d->m_fontDatabase;
375 #ifdef SPI_GETKEYBOARDSPEED
376 static inline int keyBoardAutoRepeatRateMS()
379 if (SystemParametersInfo(SPI_GETKEYBOARDSPEED, 0, &time, 0))
380 return time ? 1000 / static_cast<int>(time) : 500;
385 QVariant QWindowsIntegration::styleHint(QPlatformIntegration::StyleHint hint) const
388 case QPlatformIntegration::CursorFlashTime:
389 if (const unsigned timeMS = GetCaretBlinkTime())
390 return QVariant(int(timeMS));
392 #ifdef SPI_GETKEYBOARDSPEED
393 case KeyboardAutoRepeatRate:
394 return QVariant(keyBoardAutoRepeatRateMS());
396 case QPlatformIntegration::StartDragTime:
397 case QPlatformIntegration::StartDragDistance:
398 case QPlatformIntegration::KeyboardInputInterval:
399 case QPlatformIntegration::ShowIsFullScreen:
400 case QPlatformIntegration::PasswordMaskDelay:
401 case QPlatformIntegration::StartDragVelocity:
402 break; // Not implemented
403 case QPlatformIntegration::FontSmoothingGamma:
404 return QVariant(QWindowsFontDatabase::fontSmoothingGamma());
405 case QPlatformIntegration::MouseDoubleClickInterval:
406 if (const int ms = GetDoubleClickTime())
409 case QPlatformIntegration::UseRtlExtensions:
410 return QVariant(d->m_context.useRTLExtensions());
412 return QPlatformIntegration::styleHint(hint);
415 Qt::KeyboardModifiers QWindowsIntegration::queryKeyboardModifiers() const
417 return QWindowsKeyMapper::queryKeyboardModifiers();
420 QPlatformNativeInterface *QWindowsIntegration::nativeInterface() const
422 return &d->m_nativeInterface;
425 #ifndef QT_NO_CLIPBOARD
426 QPlatformClipboard * QWindowsIntegration::clipboard() const
428 return &d->m_clipboard;
430 #endif // !QT_NO_CLIPBOARD
432 QPlatformDrag *QWindowsIntegration::drag() const
437 QPlatformInputContext * QWindowsIntegration::inputContext() const
439 return &d->m_inputContext;
442 #ifndef QT_NO_ACCESSIBILITY
443 QPlatformAccessibility *QWindowsIntegration::accessibility() const
445 return &d->m_accessibility;
449 QWindowsIntegration *QWindowsIntegration::instance()
451 return static_cast<QWindowsIntegration *>(QGuiApplicationPrivate::platformIntegration());
454 QAbstractEventDispatcher * QWindowsIntegration::guiThreadEventDispatcher() const
456 return d->m_eventDispatcher;
459 QStringList QWindowsIntegration::themeNames() const
461 return QStringList(QLatin1String(QWindowsTheme::name));
464 QPlatformTheme *QWindowsIntegration::createPlatformTheme(const QString &name) const
466 if (name == QLatin1String(QWindowsTheme::name))
467 return new QWindowsTheme;
468 return QPlatformIntegration::createPlatformTheme(name);
471 QPlatformServices *QWindowsIntegration::services() const
473 return &d->m_services;
478 #include "qwindowsintegration.moc"