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"
47 # include "qwindowsglcontext.h"
49 #include "qwindowsscreen.h"
50 #include "qwindowstheme.h"
51 #include "qwindowsservices.h"
52 #ifndef QT_NO_FREETYPE
53 # include "qwindowsfontdatabase_ft.h"
55 #include "qwindowsfontdatabase.h"
56 #include "qwindowsguieventdispatcher.h"
57 #ifndef QT_NO_CLIPBOARD
58 # include "qwindowsclipboard.h"
60 #include "qwindowsdrag.h"
61 #include "qwindowsinputcontext.h"
62 #include "qwindowskeymapper.h"
63 # ifndef QT_NO_ACCESSIBILITY
64 #include "accessible/qwindowsaccessibility.h"
67 #include <qpa/qplatformnativeinterface.h>
68 #include <QtGui/QWindowSystemInterface>
69 #include <QtGui/QBackingStore>
70 #include <QtGui/private/qpixmap_raster_p.h>
71 #include <QtGui/private/qguiapplication_p.h>
73 #include <QtCore/private/qeventdispatcher_win_p.h>
74 #include <QtCore/QDebug>
79 \class QWindowsNativeInterface
80 \brief Provides access to native handles.
82 Currently implemented keys
86 \li releaseDC Releases the previously acquired DC and returns 0.
89 \ingroup qt-lighthouse-win
92 class QWindowsNativeInterface : public QPlatformNativeInterface
97 virtual void *nativeResourceForContext(const QByteArray &resource, QOpenGLContext *context);
99 virtual void *nativeResourceForWindow(const QByteArray &resource, QWindow *window);
100 virtual void *nativeResourceForBackingStore(const QByteArray &resource, QBackingStore *bs);
101 virtual EventFilter setEventFilter(const QByteArray &eventType, EventFilter filter)
102 { return QWindowsContext::instance()->setEventFilter(eventType, filter); }
104 Q_INVOKABLE void *createMessageWindow(const QString &classNameTemplate,
105 const QString &windowName,
106 void *eventProc) const;
109 void *QWindowsNativeInterface::nativeResourceForWindow(const QByteArray &resource, QWindow *window)
111 if (!window || !window->handle()) {
112 qWarning("%s: '%s' requested for null window or window without handle.", __FUNCTION__, resource.constData());
115 QWindowsWindow *bw = static_cast<QWindowsWindow *>(window->handle());
116 if (resource == "handle")
118 if (window->surfaceType() == QWindow::RasterSurface) {
119 if (resource == "getDC")
121 if (resource == "releaseDC") {
126 qWarning("%s: Invalid key '%s' requested.", __FUNCTION__, resource.constData());
130 void *QWindowsNativeInterface::nativeResourceForBackingStore(const QByteArray &resource, QBackingStore *bs)
132 if (!bs || !bs->handle()) {
133 qWarning("%s: '%s' requested for null backingstore or backingstore without handle.", __FUNCTION__, resource.constData());
136 QWindowsBackingStore *wbs = static_cast<QWindowsBackingStore *>(bs->handle());
137 if (resource == "getDC")
139 qWarning("%s: Invalid key '%s' requested.", __FUNCTION__, resource.constData());
144 void *QWindowsNativeInterface::nativeResourceForContext(const QByteArray &resource, QOpenGLContext *context)
146 if (!context || !context->handle()) {
147 qWarning("%s: '%s' requested for null context or context without handle.", __FUNCTION__, resource.constData());
150 QWindowsGLContext *windowsContext = static_cast<QWindowsGLContext *>(context->handle());
151 if (resource == "renderingContext")
152 return windowsContext->renderingContext();
154 qWarning("%s: Invalid key '%s' requested.", __FUNCTION__, resource.constData());
157 #endif // !QT_NO_OPENGL
160 \brief Creates a non-visible window handle for filtering messages.
163 void *QWindowsNativeInterface::createMessageWindow(const QString &classNameTemplate,
164 const QString &windowName,
165 void *eventProc) const
167 QWindowsContext *ctx = QWindowsContext::instance();
168 const HWND hwnd = ctx->createDummyWindow(classNameTemplate,
169 (wchar_t*)windowName.utf16(),
175 \class QWindowsIntegration
176 \brief QPlatformIntegration implementation for Windows.
177 \ingroup qt-lighthouse-win
180 struct QWindowsIntegrationPrivate
183 typedef QSharedPointer<QOpenGLStaticContext> QOpenGLStaticContextPtr;
186 QWindowsIntegrationPrivate();
187 ~QWindowsIntegrationPrivate();
189 QWindowsContext m_context;
190 QPlatformFontDatabase *m_fontDatabase;
191 QWindowsNativeInterface m_nativeInterface;
192 #ifndef QT_NO_CLIPBOARD
193 QWindowsClipboard m_clipboard;
196 QWindowsGuiEventDispatcher *m_eventDispatcher;
198 QOpenGLStaticContextPtr m_staticOpenGLContext;
200 QWindowsInputContext m_inputContext;
201 #ifndef QT_NO_ACCESSIBILITY
202 QWindowsAccessibility m_accessibility;
204 QWindowsServices m_services;
207 QWindowsIntegrationPrivate::QWindowsIntegrationPrivate()
208 : m_fontDatabase(0), m_eventDispatcher(new QWindowsGuiEventDispatcher)
212 QWindowsIntegrationPrivate::~QWindowsIntegrationPrivate()
215 delete m_fontDatabase;
218 QWindowsIntegration::QWindowsIntegration() :
219 d(new QWindowsIntegrationPrivate)
221 QGuiApplicationPrivate::instance()->setEventDispatcher(d->m_eventDispatcher);
222 #ifndef QT_NO_CLIPBOARD
223 d->m_clipboard.registerViewer();
225 d->m_context.screenManager().handleScreenChanges();
228 QWindowsIntegration::~QWindowsIntegration()
230 if (QWindowsContext::verboseIntegration)
231 qDebug("%s", __FUNCTION__);
234 bool QWindowsIntegration::hasCapability(QPlatformIntegration::Capability cap) const
237 case ThreadedPixmaps:
246 return QPlatformIntegration::hasCapability(cap);
251 QPlatformPixmap *QWindowsIntegration::createPlatformPixmap(QPlatformPixmap::PixelType type) const
253 return new QRasterPlatformPixmap(type);
256 QPlatformWindow *QWindowsIntegration::createPlatformWindow(QWindow *window) const
258 QWindowsWindow::WindowData requested;
259 requested.flags = window->windowFlags();
260 requested.geometry = window->geometry();
261 const QWindowsWindow::WindowData obtained
262 = QWindowsWindow::WindowData::create(window, requested, window->windowTitle());
263 if (QWindowsContext::verboseIntegration || QWindowsContext::verboseWindows)
265 << __FUNCTION__ << '<' << window << '\n'
266 << " Requested: " << requested.geometry << "frame incl.: "
267 << QWindowsGeometryHint::positionIncludesFrame(window)
269 << QWindowsWindow::debugWindowFlags(requested.flags) << '\n'
270 << " Obtained : " << obtained.geometry << " Margins "
271 << obtained.frame << " Flags="
272 << QWindowsWindow::debugWindowFlags(obtained.flags)
273 << " Handle=" << obtained.hwnd << '\n';
276 if (requested.flags != obtained.flags)
277 window->setWindowFlags(obtained.flags);
278 return new QWindowsWindow(window, obtained);
281 QPlatformBackingStore *QWindowsIntegration::createPlatformBackingStore(QWindow *window) const
283 if (QWindowsContext::verboseIntegration)
284 qDebug() << __FUNCTION__ << window;
285 return new QWindowsBackingStore(window);
289 QPlatformOpenGLContext
290 *QWindowsIntegration::createPlatformOpenGLContext(QOpenGLContext *context) const
292 if (QWindowsContext::verboseIntegration)
293 qDebug() << __FUNCTION__ << context->format();
294 if (d->m_staticOpenGLContext.isNull())
295 d->m_staticOpenGLContext =
296 QSharedPointer<QOpenGLStaticContext>(QOpenGLStaticContext::create());
297 QScopedPointer<QWindowsGLContext> result(new QWindowsGLContext(d->m_staticOpenGLContext, context));
298 if (result->isValid())
299 return result.take();
302 #endif // !QT_NO_OPENGL
304 /* Workaround for QTBUG-24205: In 'Auto', pick the FreeType engine for
305 * QML2 applications. */
307 enum FontDatabaseOption {
308 FontDatabaseFreeType,
312 static inline FontDatabaseOption fontDatabaseOption(const QObject &nativeInterface)
314 const QVariant argumentV = nativeInterface.property("fontengine");
315 if (argumentV.isValid()) {
316 const QString argument = argumentV.toString();
317 if (argument == QLatin1String("freetype"))
318 return FontDatabaseFreeType;
319 if (argument == QLatin1String("native"))
320 return FontDatabaseNative;
322 return FontDatabaseNative;
325 QPlatformFontDatabase *QWindowsIntegration::fontDatabase() const
327 if (!d->m_fontDatabase) {
328 #ifdef QT_NO_FREETYPE
329 d->m_fontDatabase = new QWindowsFontDatabase();
331 FontDatabaseOption option = fontDatabaseOption(d->m_nativeInterface);
332 if (option == FontDatabaseFreeType) {
333 d->m_fontDatabase = new QWindowsFontDatabaseFT;
335 d->m_fontDatabase = new QWindowsFontDatabase;
339 return d->m_fontDatabase;
342 #ifdef SPI_GETKEYBOARDSPEED
343 static inline int keyBoardAutoRepeatRateMS()
346 if (SystemParametersInfo(SPI_GETKEYBOARDSPEED, 0, &time, 0))
347 return time ? 1000 / static_cast<int>(time) : 500;
352 QVariant QWindowsIntegration::styleHint(QPlatformIntegration::StyleHint hint) const
355 case QPlatformIntegration::CursorFlashTime:
356 if (const unsigned timeMS = GetCaretBlinkTime())
357 return QVariant(int(timeMS));
359 #ifdef SPI_GETKEYBOARDSPEED
360 case KeyboardAutoRepeatRate:
361 return QVariant(keyBoardAutoRepeatRateMS());
363 case QPlatformIntegration::StartDragTime:
364 case QPlatformIntegration::StartDragDistance:
365 case QPlatformIntegration::KeyboardInputInterval:
366 case QPlatformIntegration::ShowIsFullScreen:
367 case QPlatformIntegration::PasswordMaskDelay:
368 break; // Not implemented
369 case QPlatformIntegration::FontSmoothingGamma:
370 return QVariant(QWindowsFontDatabase::fontSmoothingGamma());
371 case QPlatformIntegration::MouseDoubleClickInterval:
372 if (const int ms = GetDoubleClickTime())
376 return QPlatformIntegration::styleHint(hint);
379 Qt::KeyboardModifiers QWindowsIntegration::queryKeyboardModifiers() const
381 return QWindowsKeyMapper::queryKeyboardModifiers();
384 QPlatformNativeInterface *QWindowsIntegration::nativeInterface() const
386 return &d->m_nativeInterface;
389 #ifndef QT_NO_CLIPBOARD
390 QPlatformClipboard * QWindowsIntegration::clipboard() const
392 return &d->m_clipboard;
394 #endif // !QT_NO_CLIPBOARD
396 QPlatformDrag *QWindowsIntegration::drag() const
401 QPlatformInputContext * QWindowsIntegration::inputContext() const
403 return &d->m_inputContext;
406 #ifndef QT_NO_ACCESSIBILITY
407 QPlatformAccessibility *QWindowsIntegration::accessibility() const
409 return &d->m_accessibility;
413 QWindowsIntegration *QWindowsIntegration::instance()
415 return static_cast<QWindowsIntegration *>(QGuiApplicationPrivate::platformIntegration());
418 QAbstractEventDispatcher * QWindowsIntegration::guiThreadEventDispatcher() const
420 return d->m_eventDispatcher;
423 QStringList QWindowsIntegration::themeNames() const
425 return QStringList(QLatin1String(QWindowsTheme::name));
428 QPlatformTheme *QWindowsIntegration::createPlatformTheme(const QString &name) const
430 if (name == QLatin1String(QWindowsTheme::name))
431 return new QWindowsTheme;
432 return QPlatformIntegration::createPlatformTheme(name);
435 QPlatformServices *QWindowsIntegration::services() const
437 return &d->m_services;
442 #include "qwindowsintegration.moc"