Revert "Move QWindowSystemInterface out of qpa."
[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 <qpa/qwindowsysteminterface.h>
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
106     Q_INVOKABLE void *createMessageWindow(const QString &classNameTemplate,
107                                           const QString &windowName,
108                                           void *eventProc) const;
109 };
110
111 void *QWindowsNativeInterface::nativeResourceForWindow(const QByteArray &resource, QWindow *window)
112 {
113     if (!window || !window->handle()) {
114         qWarning("%s: '%s' requested for null window or window without handle.", __FUNCTION__, resource.constData());
115         return 0;
116     }
117     QWindowsWindow *bw = static_cast<QWindowsWindow *>(window->handle());
118     if (resource == "handle")
119         return bw->handle();
120     if (window->surfaceType() == QWindow::RasterSurface) {
121         if (resource == "getDC")
122             return bw->getDC();
123         if (resource == "releaseDC") {
124             bw->releaseDC();
125             return 0;
126         }
127     }
128     qWarning("%s: Invalid key '%s' requested.", __FUNCTION__, resource.constData());
129     return 0;
130 }
131
132 void *QWindowsNativeInterface::nativeResourceForBackingStore(const QByteArray &resource, QBackingStore *bs)
133 {
134     if (!bs || !bs->handle()) {
135         qWarning("%s: '%s' requested for null backingstore or backingstore without handle.", __FUNCTION__, resource.constData());
136         return 0;
137     }
138     QWindowsBackingStore *wbs = static_cast<QWindowsBackingStore *>(bs->handle());
139     if (resource == "getDC")
140         return wbs->getDC();
141     qWarning("%s: Invalid key '%s' requested.", __FUNCTION__, resource.constData());
142     return 0;
143 }
144
145 #ifndef QT_NO_OPENGL
146 void *QWindowsNativeInterface::nativeResourceForContext(const QByteArray &resource, QOpenGLContext *context)
147 {
148     if (!context || !context->handle()) {
149         qWarning("%s: '%s' requested for null context or context without handle.", __FUNCTION__, resource.constData());
150         return 0;
151     }
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
165
166     qWarning("%s: Invalid key '%s' requested.", __FUNCTION__, resource.constData());
167     return 0;
168 }
169 #endif // !QT_NO_OPENGL
170
171 /*!
172     \brief Creates a non-visible window handle for filtering messages.
173 */
174
175 void *QWindowsNativeInterface::createMessageWindow(const QString &classNameTemplate,
176                                                    const QString &windowName,
177                                                    void *eventProc) const
178 {
179     QWindowsContext *ctx = QWindowsContext::instance();
180     const HWND hwnd = ctx->createDummyWindow(classNameTemplate,
181                                              (wchar_t*)windowName.utf16(),
182                                              (WNDPROC)eventProc);
183     return hwnd;
184 }
185
186 /*!
187     \class QWindowsIntegration
188     \brief QPlatformIntegration implementation for Windows.
189     \internal
190     \ingroup qt-lighthouse-win
191 */
192
193 struct QWindowsIntegrationPrivate
194 {
195 #if defined(QT_OPENGL_ES_2)
196     typedef QSharedPointer<QWindowsEGLStaticContext> QEGLStaticContextPtr;
197 #elif !defined(QT_NO_OPENGL)
198     typedef QSharedPointer<QOpenGLStaticContext> QOpenGLStaticContextPtr;
199 #endif
200
201     QWindowsIntegrationPrivate();
202     ~QWindowsIntegrationPrivate();
203
204     QWindowsContext m_context;
205     QPlatformFontDatabase *m_fontDatabase;
206     QWindowsNativeInterface m_nativeInterface;
207 #ifndef QT_NO_CLIPBOARD
208     QWindowsClipboard m_clipboard;
209 #endif
210     QWindowsDrag m_drag;
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;
216 #endif
217     QWindowsInputContext m_inputContext;
218 #ifndef QT_NO_ACCESSIBILITY
219     QWindowsAccessibility m_accessibility;
220 #endif
221     QWindowsServices m_services;
222 };
223
224 QWindowsIntegrationPrivate::QWindowsIntegrationPrivate()
225     : m_fontDatabase(0), m_eventDispatcher(new QWindowsGuiEventDispatcher)
226 {
227 }
228
229 QWindowsIntegrationPrivate::~QWindowsIntegrationPrivate()
230 {
231     if (m_fontDatabase)
232         delete m_fontDatabase;
233 }
234
235 QWindowsIntegration::QWindowsIntegration() :
236     d(new QWindowsIntegrationPrivate)
237 {
238     QGuiApplicationPrivate::instance()->setEventDispatcher(d->m_eventDispatcher);
239 #ifndef QT_NO_CLIPBOARD
240     d->m_clipboard.registerViewer();
241 #endif
242     d->m_context.screenManager().handleScreenChanges();
243 }
244
245 QWindowsIntegration::~QWindowsIntegration()
246 {
247     if (QWindowsContext::verboseIntegration)
248         qDebug("%s", __FUNCTION__);
249 }
250
251 bool QWindowsIntegration::hasCapability(QPlatformIntegration::Capability cap) const
252 {
253     switch (cap) {
254     case ThreadedPixmaps:
255         return true;
256 #ifndef QT_NO_OPENGL
257     case OpenGL:
258         return true;
259     case ThreadedOpenGL:
260 #  ifdef QT_OPENGL_ES_2
261         return QWindowsEGLContext::hasThreadedOpenGLCapability();
262 #  else
263         return true;
264 #  endif // QT_OPENGL_ES_2
265 #endif // !QT_NO_OPENGL
266     case WindowMasks:
267         return true;
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     case QPlatformIntegration::UseRtlExtensions:
410         return QVariant(d->m_context.useRTLExtensions());
411     }
412     return QPlatformIntegration::styleHint(hint);
413 }
414
415 Qt::KeyboardModifiers QWindowsIntegration::queryKeyboardModifiers() const
416 {
417     return QWindowsKeyMapper::queryKeyboardModifiers();
418 }
419
420 QPlatformNativeInterface *QWindowsIntegration::nativeInterface() const
421 {
422     return &d->m_nativeInterface;
423 }
424
425 #ifndef QT_NO_CLIPBOARD
426 QPlatformClipboard * QWindowsIntegration::clipboard() const
427 {
428     return &d->m_clipboard;
429 }
430 #endif // !QT_NO_CLIPBOARD
431
432 QPlatformDrag *QWindowsIntegration::drag() const
433 {
434     return &d->m_drag;
435 }
436
437 QPlatformInputContext * QWindowsIntegration::inputContext() const
438 {
439     return &d->m_inputContext;
440 }
441
442 #ifndef QT_NO_ACCESSIBILITY
443 QPlatformAccessibility *QWindowsIntegration::accessibility() const
444 {
445     return &d->m_accessibility;
446 }
447 #endif
448
449 QWindowsIntegration *QWindowsIntegration::instance()
450 {
451     return static_cast<QWindowsIntegration *>(QGuiApplicationPrivate::platformIntegration());
452 }
453
454 QAbstractEventDispatcher * QWindowsIntegration::guiThreadEventDispatcher() const
455 {
456     return d->m_eventDispatcher;
457 }
458
459 QStringList QWindowsIntegration::themeNames() const
460 {
461     return QStringList(QLatin1String(QWindowsTheme::name));
462 }
463
464 QPlatformTheme *QWindowsIntegration::createPlatformTheme(const QString &name) const
465 {
466     if (name == QLatin1String(QWindowsTheme::name))
467         return new QWindowsTheme;
468     return QPlatformIntegration::createPlatformTheme(name);
469 }
470
471 QPlatformServices *QWindowsIntegration::services() const
472 {
473     return &d->m_services;
474 }
475
476 QT_END_NAMESPACE
477
478 #include "qwindowsintegration.moc"