52950ecde5557ef3b2f00569a7172c5e0f67ad87
[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 #if defined(QT_OPENGL_ES_2)
47 #  include "qwindowseglcontext.h"
48 #  include <QtGui/QOpenGLContext>
49 #elif !defined(QT_NO_OPENGL)
50 #  include "qwindowsglcontext.h"
51 #endif
52 #include "qwindowsscreen.h"
53 #include "qwindowstheme.h"
54 #include "qwindowsservices.h"
55 #ifndef QT_NO_FREETYPE
56 #  include "qwindowsfontdatabase_ft.h"
57 #endif
58 #include "qwindowsfontdatabase.h"
59 #include "qwindowsguieventdispatcher.h"
60 #ifndef QT_NO_CLIPBOARD
61 #  include "qwindowsclipboard.h"
62 #endif
63 #include "qwindowsdrag.h"
64 #include "qwindowsinputcontext.h"
65 #include "qwindowskeymapper.h"
66 #  ifndef QT_NO_ACCESSIBILITY
67 #include "accessible/qwindowsaccessibility.h"
68 #endif
69
70 #include <qpa/qplatformnativeinterface.h>
71 #include <QtGui/QWindowSystemInterface>
72 #include <QtGui/QBackingStore>
73 #include <QtGui/private/qpixmap_raster_p.h>
74 #include <QtGui/private/qguiapplication_p.h>
75
76 #include <QtCore/private/qeventdispatcher_win_p.h>
77 #include <QtCore/QDebug>
78
79 QT_BEGIN_NAMESPACE
80
81 /*!
82     \class QWindowsNativeInterface
83     \brief Provides access to native handles.
84
85     Currently implemented keys
86     \list
87     \li handle (HWND)
88     \li getDC (DC)
89     \li releaseDC Releases the previously acquired DC and returns 0.
90     \endlist
91
92     \internal
93     \ingroup qt-lighthouse-win
94 */
95
96 class QWindowsNativeInterface : public QPlatformNativeInterface
97 {
98     Q_OBJECT
99 public:
100 #ifndef QT_NO_OPENGL
101     virtual void *nativeResourceForContext(const QByteArray &resource, QOpenGLContext *context);
102 #endif
103     virtual void *nativeResourceForWindow(const QByteArray &resource, QWindow *window);
104     virtual void *nativeResourceForBackingStore(const QByteArray &resource, QBackingStore *bs);
105     virtual EventFilter setEventFilter(const QByteArray &eventType, EventFilter filter)
106         { return QWindowsContext::instance()->setEventFilter(eventType, filter); }
107
108     Q_INVOKABLE void *createMessageWindow(const QString &classNameTemplate,
109                                           const QString &windowName,
110                                           void *eventProc) const;
111 };
112
113 void *QWindowsNativeInterface::nativeResourceForWindow(const QByteArray &resource, QWindow *window)
114 {
115     if (!window || !window->handle()) {
116         qWarning("%s: '%s' requested for null window or window without handle.", __FUNCTION__, resource.constData());
117         return 0;
118     }
119     QWindowsWindow *bw = static_cast<QWindowsWindow *>(window->handle());
120     if (resource == "handle")
121         return bw->handle();
122     if (window->surfaceType() == QWindow::RasterSurface) {
123         if (resource == "getDC")
124             return bw->getDC();
125         if (resource == "releaseDC") {
126             bw->releaseDC();
127             return 0;
128         }
129     }
130     qWarning("%s: Invalid key '%s' requested.", __FUNCTION__, resource.constData());
131     return 0;
132 }
133
134 void *QWindowsNativeInterface::nativeResourceForBackingStore(const QByteArray &resource, QBackingStore *bs)
135 {
136     if (!bs || !bs->handle()) {
137         qWarning("%s: '%s' requested for null backingstore or backingstore without handle.", __FUNCTION__, resource.constData());
138         return 0;
139     }
140     QWindowsBackingStore *wbs = static_cast<QWindowsBackingStore *>(bs->handle());
141     if (resource == "getDC")
142         return wbs->getDC();
143     qWarning("%s: Invalid key '%s' requested.", __FUNCTION__, resource.constData());
144     return 0;
145 }
146
147 #ifndef QT_NO_OPENGL
148 void *QWindowsNativeInterface::nativeResourceForContext(const QByteArray &resource, QOpenGLContext *context)
149 {
150     if (!context || !context->handle()) {
151         qWarning("%s: '%s' requested for null context or context without handle.", __FUNCTION__, resource.constData());
152         return 0;
153     }
154 #ifdef QT_OPENGL_ES_2
155     QWindowsEGLContext *windowsEglContext = static_cast<QWindowsEGLContext *>(context->handle());
156     if (resource == QByteArrayLiteral("eglDisplay"))
157         return windowsEglContext->eglDisplay();
158     if (resource == QByteArrayLiteral("eglContext"))
159         return windowsEglContext->eglContext();
160     if (resource == QByteArrayLiteral("eglConfig"))
161         return windowsEglContext->eglConfig();
162 #else // QT_OPENGL_ES_2
163     QWindowsGLContext *windowsContext = static_cast<QWindowsGLContext *>(context->handle());
164     if (resource == QByteArrayLiteral("renderingContext"))
165         return windowsContext->renderingContext();
166 #endif // !QT_OPENGL_ES_2
167
168     qWarning("%s: Invalid key '%s' requested.", __FUNCTION__, resource.constData());
169     return 0;
170 }
171 #endif // !QT_NO_OPENGL
172
173 /*!
174     \brief Creates a non-visible window handle for filtering messages.
175 */
176
177 void *QWindowsNativeInterface::createMessageWindow(const QString &classNameTemplate,
178                                                    const QString &windowName,
179                                                    void *eventProc) const
180 {
181     QWindowsContext *ctx = QWindowsContext::instance();
182     const HWND hwnd = ctx->createDummyWindow(classNameTemplate,
183                                              (wchar_t*)windowName.utf16(),
184                                              (WNDPROC)eventProc);
185     return hwnd;
186 }
187
188 /*!
189     \class QWindowsIntegration
190     \brief QPlatformIntegration implementation for Windows.
191     \internal
192     \ingroup qt-lighthouse-win
193 */
194
195 struct QWindowsIntegrationPrivate
196 {
197 #if defined(QT_OPENGL_ES_2)
198     typedef QSharedPointer<QWindowsEGLStaticContext> QEGLStaticContextPtr;
199 #elif !defined(QT_NO_OPENGL)
200     typedef QSharedPointer<QOpenGLStaticContext> QOpenGLStaticContextPtr;
201 #endif
202
203     QWindowsIntegrationPrivate();
204     ~QWindowsIntegrationPrivate();
205
206     QWindowsContext m_context;
207     QPlatformFontDatabase *m_fontDatabase;
208     QWindowsNativeInterface m_nativeInterface;
209 #ifndef QT_NO_CLIPBOARD
210     QWindowsClipboard m_clipboard;
211 #endif
212     QWindowsDrag m_drag;
213     QWindowsGuiEventDispatcher *m_eventDispatcher;
214 #if defined(QT_OPENGL_ES_2)
215     QEGLStaticContextPtr m_staticEGLContext;
216 #elif !defined(QT_NO_OPENGL)
217     QOpenGLStaticContextPtr m_staticOpenGLContext;
218 #endif
219     QWindowsInputContext m_inputContext;
220 #ifndef QT_NO_ACCESSIBILITY
221     QWindowsAccessibility m_accessibility;
222 #endif
223     QWindowsServices m_services;
224 };
225
226 QWindowsIntegrationPrivate::QWindowsIntegrationPrivate()
227     : m_fontDatabase(0), m_eventDispatcher(new QWindowsGuiEventDispatcher)
228 {
229 }
230
231 QWindowsIntegrationPrivate::~QWindowsIntegrationPrivate()
232 {
233     if (m_fontDatabase)
234         delete m_fontDatabase;
235 }
236
237 QWindowsIntegration::QWindowsIntegration() :
238     d(new QWindowsIntegrationPrivate)
239 {
240     QGuiApplicationPrivate::instance()->setEventDispatcher(d->m_eventDispatcher);
241 #ifndef QT_NO_CLIPBOARD
242     d->m_clipboard.registerViewer();
243 #endif
244     d->m_context.screenManager().handleScreenChanges();
245 }
246
247 QWindowsIntegration::~QWindowsIntegration()
248 {
249     if (QWindowsContext::verboseIntegration)
250         qDebug("%s", __FUNCTION__);
251 }
252
253 bool QWindowsIntegration::hasCapability(QPlatformIntegration::Capability cap) const
254 {
255     switch (cap) {
256     case ThreadedPixmaps:
257         return true;
258 #ifndef QT_NO_OPENGL
259     case OpenGL:
260         return true;
261     case ThreadedOpenGL:
262 #  ifdef QT_OPENGL_ES_2
263         return QWindowsEGLContext::hasThreadedOpenGLCapability();
264 #  else
265         return true;
266 #  endif // QT_OPENGL_ES_2
267 #endif // !QT_NO_OPENGL
268     default:
269         return QPlatformIntegration::hasCapability(cap);
270     }
271     return false;
272 }
273
274 QPlatformPixmap *QWindowsIntegration::createPlatformPixmap(QPlatformPixmap::PixelType type) const
275 {
276     return new QRasterPlatformPixmap(type);
277 }
278
279 QPlatformWindow *QWindowsIntegration::createPlatformWindow(QWindow *window) const
280 {
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)
287         qDebug().nospace()
288             << __FUNCTION__ << '<' << window << '\n'
289             << "    Requested: " << requested.geometry << "frame incl.: "
290             << QWindowsGeometryHint::positionIncludesFrame(window)
291             <<   " Flags="
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';
297     if (!obtained.hwnd)
298         return 0;
299     if (requested.flags != obtained.flags)
300         window->setWindowFlags(obtained.flags);
301     return new QWindowsWindow(window, obtained);
302 }
303
304 QPlatformBackingStore *QWindowsIntegration::createPlatformBackingStore(QWindow *window) const
305 {
306     if (QWindowsContext::verboseIntegration)
307         qDebug() << __FUNCTION__ << window;
308     return new QWindowsBackingStore(window);
309 }
310
311 #ifndef QT_NO_OPENGL
312 QPlatformOpenGLContext
313     *QWindowsIntegration::createPlatformOpenGLContext(QOpenGLContext *context) const
314 {
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();
320         if (!staticContext)
321             return 0;
322         d->m_staticEGLContext = QSharedPointer<QWindowsEGLStaticContext>(staticContext);
323     }
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();
332     return 0;
333 #endif // !QT_OPENGL_ES_2
334 }
335 #endif // !QT_NO_OPENGL
336
337 /* Workaround for QTBUG-24205: In 'Auto', pick the FreeType engine for
338  * QML2 applications. */
339
340 enum FontDatabaseOption {
341     FontDatabaseFreeType,
342     FontDatabaseNative
343 };
344
345 static inline FontDatabaseOption fontDatabaseOption(const QObject &nativeInterface)
346 {
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;
354     }
355     return FontDatabaseNative;
356 }
357
358 QPlatformFontDatabase *QWindowsIntegration::fontDatabase() const
359 {
360     if (!d->m_fontDatabase) {
361 #ifdef QT_NO_FREETYPE
362         d->m_fontDatabase = new QWindowsFontDatabase();
363 #else
364         FontDatabaseOption option = fontDatabaseOption(d->m_nativeInterface);
365         if (option == FontDatabaseFreeType) {
366             d->m_fontDatabase = new QWindowsFontDatabaseFT;
367         } else {
368             d->m_fontDatabase = new QWindowsFontDatabase;
369         }
370 #endif
371     }
372     return d->m_fontDatabase;
373 }
374
375 #ifdef SPI_GETKEYBOARDSPEED
376 static inline int keyBoardAutoRepeatRateMS()
377 {
378   DWORD time = 0;
379   if (SystemParametersInfo(SPI_GETKEYBOARDSPEED, 0, &time, 0))
380       return time ? 1000 / static_cast<int>(time) : 500;
381   return 30;
382 }
383 #endif
384
385 QVariant QWindowsIntegration::styleHint(QPlatformIntegration::StyleHint hint) const
386 {
387     switch (hint) {
388     case QPlatformIntegration::CursorFlashTime:
389         if (const unsigned timeMS = GetCaretBlinkTime())
390             return QVariant(int(timeMS));
391         break;
392 #ifdef SPI_GETKEYBOARDSPEED
393     case KeyboardAutoRepeatRate:
394         return QVariant(keyBoardAutoRepeatRateMS());
395 #endif
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())
407             return QVariant(ms);
408         break;
409     }
410     return QPlatformIntegration::styleHint(hint);
411 }
412
413 Qt::KeyboardModifiers QWindowsIntegration::queryKeyboardModifiers() const
414 {
415     return QWindowsKeyMapper::queryKeyboardModifiers();
416 }
417
418 QPlatformNativeInterface *QWindowsIntegration::nativeInterface() const
419 {
420     return &d->m_nativeInterface;
421 }
422
423 #ifndef QT_NO_CLIPBOARD
424 QPlatformClipboard * QWindowsIntegration::clipboard() const
425 {
426     return &d->m_clipboard;
427 }
428 #endif // !QT_NO_CLIPBOARD
429
430 QPlatformDrag *QWindowsIntegration::drag() const
431 {
432     return &d->m_drag;
433 }
434
435 QPlatformInputContext * QWindowsIntegration::inputContext() const
436 {
437     return &d->m_inputContext;
438 }
439
440 #ifndef QT_NO_ACCESSIBILITY
441 QPlatformAccessibility *QWindowsIntegration::accessibility() const
442 {
443     return &d->m_accessibility;
444 }
445 #endif
446
447 QWindowsIntegration *QWindowsIntegration::instance()
448 {
449     return static_cast<QWindowsIntegration *>(QGuiApplicationPrivate::platformIntegration());
450 }
451
452 QAbstractEventDispatcher * QWindowsIntegration::guiThreadEventDispatcher() const
453 {
454     return d->m_eventDispatcher;
455 }
456
457 QStringList QWindowsIntegration::themeNames() const
458 {
459     return QStringList(QLatin1String(QWindowsTheme::name));
460 }
461
462 QPlatformTheme *QWindowsIntegration::createPlatformTheme(const QString &name) const
463 {
464     if (name == QLatin1String(QWindowsTheme::name))
465         return new QWindowsTheme;
466     return QPlatformIntegration::createPlatformTheme(name);
467 }
468
469 QPlatformServices *QWindowsIntegration::services() const
470 {
471     return &d->m_services;
472 }
473
474 QT_END_NAMESPACE
475
476 #include "qwindowsintegration.moc"