e0a11380d1a1eafed77e5d479b2bf07f081681d2
[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     \ingroup qt-lighthouse-win
90 */
91
92 class QWindowsNativeInterface : public QPlatformNativeInterface
93 {
94     Q_OBJECT
95 public:
96 #ifndef QT_NO_OPENGL
97     virtual void *nativeResourceForContext(const QByteArray &resource, QOpenGLContext *context);
98 #endif
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); }
103
104     Q_INVOKABLE void *createMessageWindow(const QString &classNameTemplate,
105                                           const QString &windowName,
106                                           void *eventProc) const;
107 };
108
109 void *QWindowsNativeInterface::nativeResourceForWindow(const QByteArray &resource, QWindow *window)
110 {
111     if (!window || !window->handle()) {
112         qWarning("%s: '%s' requested for null window or window without handle.", __FUNCTION__, resource.constData());
113         return 0;
114     }
115     QWindowsWindow *bw = static_cast<QWindowsWindow *>(window->handle());
116     if (resource == "handle")
117         return bw->handle();
118     if (window->surfaceType() == QWindow::RasterSurface) {
119         if (resource == "getDC")
120             return bw->getDC();
121         if (resource == "releaseDC") {
122             bw->releaseDC();
123             return 0;
124         }
125     }
126     qWarning("%s: Invalid key '%s' requested.", __FUNCTION__, resource.constData());
127     return 0;
128 }
129
130 void *QWindowsNativeInterface::nativeResourceForBackingStore(const QByteArray &resource, QBackingStore *bs)
131 {
132     if (!bs || !bs->handle()) {
133         qWarning("%s: '%s' requested for null backingstore or backingstore without handle.", __FUNCTION__, resource.constData());
134         return 0;
135     }
136     QWindowsBackingStore *wbs = static_cast<QWindowsBackingStore *>(bs->handle());
137     if (resource == "getDC")
138         return wbs->getDC();
139     qWarning("%s: Invalid key '%s' requested.", __FUNCTION__, resource.constData());
140     return 0;
141 }
142
143 #ifndef QT_NO_OPENGL
144 void *QWindowsNativeInterface::nativeResourceForContext(const QByteArray &resource, QOpenGLContext *context)
145 {
146     if (!context || !context->handle()) {
147         qWarning("%s: '%s' requested for null context or context without handle.", __FUNCTION__, resource.constData());
148         return 0;
149     }
150     QWindowsGLContext *windowsContext = static_cast<QWindowsGLContext *>(context->handle());
151     if (resource == "renderingContext")
152         return windowsContext->renderingContext();
153
154     qWarning("%s: Invalid key '%s' requested.", __FUNCTION__, resource.constData());
155     return 0;
156 }
157 #endif // !QT_NO_OPENGL
158
159 /*!
160     \brief Creates a non-visible window handle for filtering messages.
161 */
162
163 void *QWindowsNativeInterface::createMessageWindow(const QString &classNameTemplate,
164                                                    const QString &windowName,
165                                                    void *eventProc) const
166 {
167     QWindowsContext *ctx = QWindowsContext::instance();
168     const HWND hwnd = ctx->createDummyWindow(classNameTemplate,
169                                              (wchar_t*)windowName.utf16(),
170                                              (WNDPROC)eventProc);
171     return hwnd;
172 }
173
174 /*!
175     \class QWindowsIntegration
176     \brief QPlatformIntegration implementation for Windows.
177     \ingroup qt-lighthouse-win
178 */
179
180 struct QWindowsIntegrationPrivate
181 {
182 #ifndef QT_NO_OPENGL
183     typedef QSharedPointer<QOpenGLStaticContext> QOpenGLStaticContextPtr;
184 #endif
185
186     QWindowsIntegrationPrivate();
187     ~QWindowsIntegrationPrivate();
188
189     QWindowsContext m_context;
190     QPlatformFontDatabase *m_fontDatabase;
191     QWindowsNativeInterface m_nativeInterface;
192 #ifndef QT_NO_CLIPBOARD
193     QWindowsClipboard m_clipboard;
194 #endif
195     QWindowsDrag m_drag;
196     QWindowsGuiEventDispatcher *m_eventDispatcher;
197 #ifndef QT_NO_OPENGL
198     QOpenGLStaticContextPtr m_staticOpenGLContext;
199 #endif
200     QWindowsInputContext m_inputContext;
201 #ifndef QT_NO_ACCESSIBILITY
202     QWindowsAccessibility m_accessibility;
203 #endif
204     QWindowsServices m_services;
205 };
206
207 QWindowsIntegrationPrivate::QWindowsIntegrationPrivate()
208     : m_fontDatabase(0), m_eventDispatcher(new QWindowsGuiEventDispatcher)
209 {
210 }
211
212 QWindowsIntegrationPrivate::~QWindowsIntegrationPrivate()
213 {
214     if (m_fontDatabase)
215         delete m_fontDatabase;
216 }
217
218 QWindowsIntegration::QWindowsIntegration() :
219     d(new QWindowsIntegrationPrivate)
220 {
221     QGuiApplicationPrivate::instance()->setEventDispatcher(d->m_eventDispatcher);
222 #ifndef QT_NO_CLIPBOARD
223     d->m_clipboard.registerViewer();
224 #endif
225     d->m_context.screenManager().handleScreenChanges();
226 }
227
228 QWindowsIntegration::~QWindowsIntegration()
229 {
230     if (QWindowsContext::verboseIntegration)
231         qDebug("%s", __FUNCTION__);
232 }
233
234 bool QWindowsIntegration::hasCapability(QPlatformIntegration::Capability cap) const
235 {
236     switch (cap) {
237     case ThreadedPixmaps:
238         return true;
239 #ifndef QT_NO_OPENGL
240     case OpenGL:
241         return true;
242     case ThreadedOpenGL:
243         return true;
244 #endif
245     default:
246         return QPlatformIntegration::hasCapability(cap);
247     }
248     return false;
249 }
250
251 QPlatformPixmap *QWindowsIntegration::createPlatformPixmap(QPlatformPixmap::PixelType type) const
252 {
253     return new QRasterPlatformPixmap(type);
254 }
255
256 QPlatformWindow *QWindowsIntegration::createPlatformWindow(QWindow *window) const
257 {
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)
264         qDebug().nospace()
265             << __FUNCTION__ << '<' << window << '\n'
266             << "    Requested: " << requested.geometry << "frame incl.: "
267             << QWindowsGeometryHint::positionIncludesFrame(window)
268             <<   " Flags="
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';
274     if (!obtained.hwnd)
275         return 0;
276     if (requested.flags != obtained.flags)
277         window->setWindowFlags(obtained.flags);
278     return new QWindowsWindow(window, obtained);
279 }
280
281 QPlatformBackingStore *QWindowsIntegration::createPlatformBackingStore(QWindow *window) const
282 {
283     if (QWindowsContext::verboseIntegration)
284         qDebug() << __FUNCTION__ << window;
285     return new QWindowsBackingStore(window);
286 }
287
288 #ifndef QT_NO_OPENGL
289 QPlatformOpenGLContext
290     *QWindowsIntegration::createPlatformOpenGLContext(QOpenGLContext *context) const
291 {
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();
300     return 0;
301 }
302 #endif // !QT_NO_OPENGL
303
304 /* Workaround for QTBUG-24205: In 'Auto', pick the FreeType engine for
305  * QML2 applications. */
306
307 enum FontDatabaseOption {
308     FontDatabaseFreeType,
309     FontDatabaseNative
310 };
311
312 static inline FontDatabaseOption fontDatabaseOption(const QObject &nativeInterface)
313 {
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;
321     }
322     return FontDatabaseNative;
323 }
324
325 QPlatformFontDatabase *QWindowsIntegration::fontDatabase() const
326 {
327     if (!d->m_fontDatabase) {
328 #ifdef QT_NO_FREETYPE
329         d->m_fontDatabase = new QWindowsFontDatabase();
330 #else
331         FontDatabaseOption option = fontDatabaseOption(d->m_nativeInterface);
332         if (option == FontDatabaseFreeType) {
333             d->m_fontDatabase = new QWindowsFontDatabaseFT;
334         } else {
335             d->m_fontDatabase = new QWindowsFontDatabase;
336         }
337 #endif
338     }
339     return d->m_fontDatabase;
340 }
341
342 #ifdef SPI_GETKEYBOARDSPEED
343 static inline int keyBoardAutoRepeatRateMS()
344 {
345   DWORD time = 0;
346   if (SystemParametersInfo(SPI_GETKEYBOARDSPEED, 0, &time, 0))
347       return time ? 1000 / static_cast<int>(time) : 500;
348   return 30;
349 }
350 #endif
351
352 QVariant QWindowsIntegration::styleHint(QPlatformIntegration::StyleHint hint) const
353 {
354     switch (hint) {
355     case QPlatformIntegration::CursorFlashTime:
356         if (const unsigned timeMS = GetCaretBlinkTime())
357             return QVariant(int(timeMS));
358         break;
359 #ifdef SPI_GETKEYBOARDSPEED
360     case KeyboardAutoRepeatRate:
361         return QVariant(keyBoardAutoRepeatRateMS());
362 #endif
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())
373             return QVariant(ms);
374         break;
375     }
376     return QPlatformIntegration::styleHint(hint);
377 }
378
379 Qt::KeyboardModifiers QWindowsIntegration::queryKeyboardModifiers() const
380 {
381     return QWindowsKeyMapper::queryKeyboardModifiers();
382 }
383
384 QPlatformNativeInterface *QWindowsIntegration::nativeInterface() const
385 {
386     return &d->m_nativeInterface;
387 }
388
389 #ifndef QT_NO_CLIPBOARD
390 QPlatformClipboard * QWindowsIntegration::clipboard() const
391 {
392     return &d->m_clipboard;
393 }
394 #endif // !QT_NO_CLIPBOARD
395
396 QPlatformDrag *QWindowsIntegration::drag() const
397 {
398     return &d->m_drag;
399 }
400
401 QPlatformInputContext * QWindowsIntegration::inputContext() const
402 {
403     return &d->m_inputContext;
404 }
405
406 #ifndef QT_NO_ACCESSIBILITY
407 QPlatformAccessibility *QWindowsIntegration::accessibility() const
408 {
409     return &d->m_accessibility;
410 }
411 #endif
412
413 QWindowsIntegration *QWindowsIntegration::instance()
414 {
415     return static_cast<QWindowsIntegration *>(QGuiApplicationPrivate::platformIntegration());
416 }
417
418 QAbstractEventDispatcher * QWindowsIntegration::guiThreadEventDispatcher() const
419 {
420     return d->m_eventDispatcher;
421 }
422
423 QStringList QWindowsIntegration::themeNames() const
424 {
425     return QStringList(QLatin1String(QWindowsTheme::name));
426 }
427
428 QPlatformTheme *QWindowsIntegration::createPlatformTheme(const QString &name) const
429 {
430     if (name == QLatin1String(QWindowsTheme::name))
431         return new QWindowsTheme;
432     return QPlatformIntegration::createPlatformTheme(name);
433 }
434
435 QPlatformServices *QWindowsIntegration::services() const
436 {
437     return &d->m_services;
438 }
439
440 QT_END_NAMESPACE
441
442 #include "qwindowsintegration.moc"