Windows QPA plugin: Add \internal to class documentation.
[profile/ivi/qtbase.git] / src / plugins / platforms / windows / qwindowsintegration.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
5 **
6 ** This file is part of the plugins of the Qt Toolkit.
7 **
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.
16 **
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.
20 **
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.
28 **
29 ** Other Usage
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.
32 **
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include "qwindowsintegration.h"
43 #include "qwindowsbackingstore.h"
44 #include "qwindowswindow.h"
45 #include "qwindowscontext.h"
46 #ifndef QT_NO_OPENGL
47 #  include "qwindowsglcontext.h"
48 #endif
49 #include "qwindowsscreen.h"
50 #include "qwindowstheme.h"
51 #include "qwindowsservices.h"
52 #ifndef QT_NO_FREETYPE
53 #  include "qwindowsfontdatabase_ft.h"
54 #endif
55 #include "qwindowsfontdatabase.h"
56 #include "qwindowsguieventdispatcher.h"
57 #ifndef QT_NO_CLIPBOARD
58 #  include "qwindowsclipboard.h"
59 #endif
60 #include "qwindowsdrag.h"
61 #include "qwindowsinputcontext.h"
62 #include "qwindowskeymapper.h"
63 #  ifndef QT_NO_ACCESSIBILITY
64 #include "accessible/qwindowsaccessibility.h"
65 #endif
66
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>
72
73 #include <QtCore/private/qeventdispatcher_win_p.h>
74 #include <QtCore/QDebug>
75
76 QT_BEGIN_NAMESPACE
77
78 /*!
79     \class QWindowsNativeInterface
80     \brief Provides access to native handles.
81
82     Currently implemented keys
83     \list
84     \li handle (HWND)
85     \li getDC (DC)
86     \li releaseDC Releases the previously acquired DC and returns 0.
87     \endlist
88
89     \internal
90     \ingroup qt-lighthouse-win
91 */
92
93 class QWindowsNativeInterface : public QPlatformNativeInterface
94 {
95     Q_OBJECT
96 public:
97 #ifndef QT_NO_OPENGL
98     virtual void *nativeResourceForContext(const QByteArray &resource, QOpenGLContext *context);
99 #endif
100     virtual void *nativeResourceForWindow(const QByteArray &resource, QWindow *window);
101     virtual void *nativeResourceForBackingStore(const QByteArray &resource, QBackingStore *bs);
102     virtual EventFilter setEventFilter(const QByteArray &eventType, EventFilter filter)
103         { return QWindowsContext::instance()->setEventFilter(eventType, filter); }
104
105     Q_INVOKABLE void *createMessageWindow(const QString &classNameTemplate,
106                                           const QString &windowName,
107                                           void *eventProc) const;
108 };
109
110 void *QWindowsNativeInterface::nativeResourceForWindow(const QByteArray &resource, QWindow *window)
111 {
112     if (!window || !window->handle()) {
113         qWarning("%s: '%s' requested for null window or window without handle.", __FUNCTION__, resource.constData());
114         return 0;
115     }
116     QWindowsWindow *bw = static_cast<QWindowsWindow *>(window->handle());
117     if (resource == "handle")
118         return bw->handle();
119     if (window->surfaceType() == QWindow::RasterSurface) {
120         if (resource == "getDC")
121             return bw->getDC();
122         if (resource == "releaseDC") {
123             bw->releaseDC();
124             return 0;
125         }
126     }
127     qWarning("%s: Invalid key '%s' requested.", __FUNCTION__, resource.constData());
128     return 0;
129 }
130
131 void *QWindowsNativeInterface::nativeResourceForBackingStore(const QByteArray &resource, QBackingStore *bs)
132 {
133     if (!bs || !bs->handle()) {
134         qWarning("%s: '%s' requested for null backingstore or backingstore without handle.", __FUNCTION__, resource.constData());
135         return 0;
136     }
137     QWindowsBackingStore *wbs = static_cast<QWindowsBackingStore *>(bs->handle());
138     if (resource == "getDC")
139         return wbs->getDC();
140     qWarning("%s: Invalid key '%s' requested.", __FUNCTION__, resource.constData());
141     return 0;
142 }
143
144 #ifndef QT_NO_OPENGL
145 void *QWindowsNativeInterface::nativeResourceForContext(const QByteArray &resource, QOpenGLContext *context)
146 {
147     if (!context || !context->handle()) {
148         qWarning("%s: '%s' requested for null context or context without handle.", __FUNCTION__, resource.constData());
149         return 0;
150     }
151     QWindowsGLContext *windowsContext = static_cast<QWindowsGLContext *>(context->handle());
152     if (resource == "renderingContext")
153         return windowsContext->renderingContext();
154
155     qWarning("%s: Invalid key '%s' requested.", __FUNCTION__, resource.constData());
156     return 0;
157 }
158 #endif // !QT_NO_OPENGL
159
160 /*!
161     \brief Creates a non-visible window handle for filtering messages.
162 */
163
164 void *QWindowsNativeInterface::createMessageWindow(const QString &classNameTemplate,
165                                                    const QString &windowName,
166                                                    void *eventProc) const
167 {
168     QWindowsContext *ctx = QWindowsContext::instance();
169     const HWND hwnd = ctx->createDummyWindow(classNameTemplate,
170                                              (wchar_t*)windowName.utf16(),
171                                              (WNDPROC)eventProc);
172     return hwnd;
173 }
174
175 /*!
176     \class QWindowsIntegration
177     \brief QPlatformIntegration implementation for Windows.
178     \internal
179     \ingroup qt-lighthouse-win
180 */
181
182 struct QWindowsIntegrationPrivate
183 {
184 #ifndef QT_NO_OPENGL
185     typedef QSharedPointer<QOpenGLStaticContext> QOpenGLStaticContextPtr;
186 #endif
187
188     QWindowsIntegrationPrivate();
189     ~QWindowsIntegrationPrivate();
190
191     QWindowsContext m_context;
192     QPlatformFontDatabase *m_fontDatabase;
193     QWindowsNativeInterface m_nativeInterface;
194 #ifndef QT_NO_CLIPBOARD
195     QWindowsClipboard m_clipboard;
196 #endif
197     QWindowsDrag m_drag;
198     QWindowsGuiEventDispatcher *m_eventDispatcher;
199 #ifndef QT_NO_OPENGL
200     QOpenGLStaticContextPtr m_staticOpenGLContext;
201 #endif
202     QWindowsInputContext m_inputContext;
203 #ifndef QT_NO_ACCESSIBILITY
204     QWindowsAccessibility m_accessibility;
205 #endif
206     QWindowsServices m_services;
207 };
208
209 QWindowsIntegrationPrivate::QWindowsIntegrationPrivate()
210     : m_fontDatabase(0), m_eventDispatcher(new QWindowsGuiEventDispatcher)
211 {
212 }
213
214 QWindowsIntegrationPrivate::~QWindowsIntegrationPrivate()
215 {
216     if (m_fontDatabase)
217         delete m_fontDatabase;
218 }
219
220 QWindowsIntegration::QWindowsIntegration() :
221     d(new QWindowsIntegrationPrivate)
222 {
223     QGuiApplicationPrivate::instance()->setEventDispatcher(d->m_eventDispatcher);
224 #ifndef QT_NO_CLIPBOARD
225     d->m_clipboard.registerViewer();
226 #endif
227     d->m_context.screenManager().handleScreenChanges();
228 }
229
230 QWindowsIntegration::~QWindowsIntegration()
231 {
232     if (QWindowsContext::verboseIntegration)
233         qDebug("%s", __FUNCTION__);
234 }
235
236 bool QWindowsIntegration::hasCapability(QPlatformIntegration::Capability cap) const
237 {
238     switch (cap) {
239     case ThreadedPixmaps:
240         return true;
241 #ifndef QT_NO_OPENGL
242     case OpenGL:
243         return true;
244     case ThreadedOpenGL:
245         return true;
246 #endif
247     default:
248         return QPlatformIntegration::hasCapability(cap);
249     }
250     return false;
251 }
252
253 QPlatformPixmap *QWindowsIntegration::createPlatformPixmap(QPlatformPixmap::PixelType type) const
254 {
255     return new QRasterPlatformPixmap(type);
256 }
257
258 QPlatformWindow *QWindowsIntegration::createPlatformWindow(QWindow *window) const
259 {
260     QWindowsWindow::WindowData requested;
261     requested.flags = window->windowFlags();
262     requested.geometry = window->geometry();
263     const QWindowsWindow::WindowData obtained
264             = QWindowsWindow::WindowData::create(window, requested, window->windowTitle());
265     if (QWindowsContext::verboseIntegration || QWindowsContext::verboseWindows)
266         qDebug().nospace()
267             << __FUNCTION__ << '<' << window << '\n'
268             << "    Requested: " << requested.geometry << "frame incl.: "
269             << QWindowsGeometryHint::positionIncludesFrame(window)
270             <<   " Flags="
271             << QWindowsWindow::debugWindowFlags(requested.flags) << '\n'
272             << "    Obtained : " << obtained.geometry << " Margins "
273             << obtained.frame  << " Flags="
274             << QWindowsWindow::debugWindowFlags(obtained.flags)
275             << " Handle=" << obtained.hwnd << '\n';
276     if (!obtained.hwnd)
277         return 0;
278     if (requested.flags != obtained.flags)
279         window->setWindowFlags(obtained.flags);
280     return new QWindowsWindow(window, obtained);
281 }
282
283 QPlatformBackingStore *QWindowsIntegration::createPlatformBackingStore(QWindow *window) const
284 {
285     if (QWindowsContext::verboseIntegration)
286         qDebug() << __FUNCTION__ << window;
287     return new QWindowsBackingStore(window);
288 }
289
290 #ifndef QT_NO_OPENGL
291 QPlatformOpenGLContext
292     *QWindowsIntegration::createPlatformOpenGLContext(QOpenGLContext *context) const
293 {
294     if (QWindowsContext::verboseIntegration)
295         qDebug() << __FUNCTION__ << context->format();
296     if (d->m_staticOpenGLContext.isNull())
297         d->m_staticOpenGLContext =
298             QSharedPointer<QOpenGLStaticContext>(QOpenGLStaticContext::create());
299     QScopedPointer<QWindowsGLContext> result(new QWindowsGLContext(d->m_staticOpenGLContext, context));
300     if (result->isValid())
301         return result.take();
302     return 0;
303 }
304 #endif // !QT_NO_OPENGL
305
306 /* Workaround for QTBUG-24205: In 'Auto', pick the FreeType engine for
307  * QML2 applications. */
308
309 enum FontDatabaseOption {
310     FontDatabaseFreeType,
311     FontDatabaseNative
312 };
313
314 static inline FontDatabaseOption fontDatabaseOption(const QObject &nativeInterface)
315 {
316     const QVariant argumentV = nativeInterface.property("fontengine");
317     if (argumentV.isValid()) {
318         const QString argument = argumentV.toString();
319         if (argument == QLatin1String("freetype"))
320             return FontDatabaseFreeType;
321         if (argument == QLatin1String("native"))
322             return FontDatabaseNative;
323     }
324     return FontDatabaseNative;
325 }
326
327 QPlatformFontDatabase *QWindowsIntegration::fontDatabase() const
328 {
329     if (!d->m_fontDatabase) {
330 #ifdef QT_NO_FREETYPE
331         d->m_fontDatabase = new QWindowsFontDatabase();
332 #else
333         FontDatabaseOption option = fontDatabaseOption(d->m_nativeInterface);
334         if (option == FontDatabaseFreeType) {
335             d->m_fontDatabase = new QWindowsFontDatabaseFT;
336         } else {
337             d->m_fontDatabase = new QWindowsFontDatabase;
338         }
339 #endif
340     }
341     return d->m_fontDatabase;
342 }
343
344 #ifdef SPI_GETKEYBOARDSPEED
345 static inline int keyBoardAutoRepeatRateMS()
346 {
347   DWORD time = 0;
348   if (SystemParametersInfo(SPI_GETKEYBOARDSPEED, 0, &time, 0))
349       return time ? 1000 / static_cast<int>(time) : 500;
350   return 30;
351 }
352 #endif
353
354 QVariant QWindowsIntegration::styleHint(QPlatformIntegration::StyleHint hint) const
355 {
356     switch (hint) {
357     case QPlatformIntegration::CursorFlashTime:
358         if (const unsigned timeMS = GetCaretBlinkTime())
359             return QVariant(int(timeMS));
360         break;
361 #ifdef SPI_GETKEYBOARDSPEED
362     case KeyboardAutoRepeatRate:
363         return QVariant(keyBoardAutoRepeatRateMS());
364 #endif
365     case QPlatformIntegration::StartDragTime:
366     case QPlatformIntegration::StartDragDistance:
367     case QPlatformIntegration::KeyboardInputInterval:
368     case QPlatformIntegration::ShowIsFullScreen:
369     case QPlatformIntegration::PasswordMaskDelay:
370         break; // Not implemented
371     case QPlatformIntegration::FontSmoothingGamma:
372         return QVariant(QWindowsFontDatabase::fontSmoothingGamma());
373     case QPlatformIntegration::MouseDoubleClickInterval:
374         if (const int ms = GetDoubleClickTime())
375             return QVariant(ms);
376         break;
377     }
378     return QPlatformIntegration::styleHint(hint);
379 }
380
381 Qt::KeyboardModifiers QWindowsIntegration::queryKeyboardModifiers() const
382 {
383     return QWindowsKeyMapper::queryKeyboardModifiers();
384 }
385
386 QPlatformNativeInterface *QWindowsIntegration::nativeInterface() const
387 {
388     return &d->m_nativeInterface;
389 }
390
391 #ifndef QT_NO_CLIPBOARD
392 QPlatformClipboard * QWindowsIntegration::clipboard() const
393 {
394     return &d->m_clipboard;
395 }
396 #endif // !QT_NO_CLIPBOARD
397
398 QPlatformDrag *QWindowsIntegration::drag() const
399 {
400     return &d->m_drag;
401 }
402
403 QPlatformInputContext * QWindowsIntegration::inputContext() const
404 {
405     return &d->m_inputContext;
406 }
407
408 #ifndef QT_NO_ACCESSIBILITY
409 QPlatformAccessibility *QWindowsIntegration::accessibility() const
410 {
411     return &d->m_accessibility;
412 }
413 #endif
414
415 QWindowsIntegration *QWindowsIntegration::instance()
416 {
417     return static_cast<QWindowsIntegration *>(QGuiApplicationPrivate::platformIntegration());
418 }
419
420 QAbstractEventDispatcher * QWindowsIntegration::guiThreadEventDispatcher() const
421 {
422     return d->m_eventDispatcher;
423 }
424
425 QStringList QWindowsIntegration::themeNames() const
426 {
427     return QStringList(QLatin1String(QWindowsTheme::name));
428 }
429
430 QPlatformTheme *QWindowsIntegration::createPlatformTheme(const QString &name) const
431 {
432     if (name == QLatin1String(QWindowsTheme::name))
433         return new QWindowsTheme;
434     return QPlatformIntegration::createPlatformTheme(name);
435 }
436
437 QPlatformServices *QWindowsIntegration::services() const
438 {
439     return &d->m_services;
440 }
441
442 QT_END_NAMESPACE
443
444 #include "qwindowsintegration.moc"