QPlatformWindow: Add Window masks.
[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     case WindowMasks:
269         return true;
270     default:
271         return QPlatformIntegration::hasCapability(cap);
272     }
273     return false;
274 }
275
276 QPlatformPixmap *QWindowsIntegration::createPlatformPixmap(QPlatformPixmap::PixelType type) const
277 {
278     return new QRasterPlatformPixmap(type);
279 }
280
281 QPlatformWindow *QWindowsIntegration::createPlatformWindow(QWindow *window) const
282 {
283     QWindowsWindow::WindowData requested;
284     requested.flags = window->windowFlags();
285     requested.geometry = window->geometry();
286     const QWindowsWindow::WindowData obtained
287             = QWindowsWindow::WindowData::create(window, requested, window->windowTitle());
288     if (QWindowsContext::verboseIntegration || QWindowsContext::verboseWindows)
289         qDebug().nospace()
290             << __FUNCTION__ << '<' << window << '\n'
291             << "    Requested: " << requested.geometry << "frame incl.: "
292             << QWindowsGeometryHint::positionIncludesFrame(window)
293             <<   " Flags="
294             << QWindowsWindow::debugWindowFlags(requested.flags) << '\n'
295             << "    Obtained : " << obtained.geometry << " Margins "
296             << obtained.frame  << " Flags="
297             << QWindowsWindow::debugWindowFlags(obtained.flags)
298             << " Handle=" << obtained.hwnd << '\n';
299     if (!obtained.hwnd)
300         return 0;
301     if (requested.flags != obtained.flags)
302         window->setWindowFlags(obtained.flags);
303     return new QWindowsWindow(window, obtained);
304 }
305
306 QPlatformBackingStore *QWindowsIntegration::createPlatformBackingStore(QWindow *window) const
307 {
308     if (QWindowsContext::verboseIntegration)
309         qDebug() << __FUNCTION__ << window;
310     return new QWindowsBackingStore(window);
311 }
312
313 #ifndef QT_NO_OPENGL
314 QPlatformOpenGLContext
315     *QWindowsIntegration::createPlatformOpenGLContext(QOpenGLContext *context) const
316 {
317     if (QWindowsContext::verboseIntegration)
318         qDebug() << __FUNCTION__ << context->format();
319 #ifdef QT_OPENGL_ES_2
320     if (d->m_staticEGLContext.isNull()) {
321         QWindowsEGLStaticContext *staticContext = QWindowsEGLStaticContext::create();
322         if (!staticContext)
323             return 0;
324         d->m_staticEGLContext = QSharedPointer<QWindowsEGLStaticContext>(staticContext);
325     }
326     return new QWindowsEGLContext(d->m_staticEGLContext, context->format(), context->handle());
327 #else  // QT_OPENGL_ES_2
328     if (d->m_staticOpenGLContext.isNull())
329         d->m_staticOpenGLContext =
330             QSharedPointer<QOpenGLStaticContext>(QOpenGLStaticContext::create());
331     QScopedPointer<QWindowsGLContext> result(new QWindowsGLContext(d->m_staticOpenGLContext, context));
332     if (result->isValid())
333         return result.take();
334     return 0;
335 #endif // !QT_OPENGL_ES_2
336 }
337 #endif // !QT_NO_OPENGL
338
339 /* Workaround for QTBUG-24205: In 'Auto', pick the FreeType engine for
340  * QML2 applications. */
341
342 enum FontDatabaseOption {
343     FontDatabaseFreeType,
344     FontDatabaseNative
345 };
346
347 static inline FontDatabaseOption fontDatabaseOption(const QObject &nativeInterface)
348 {
349     const QVariant argumentV = nativeInterface.property("fontengine");
350     if (argumentV.isValid()) {
351         const QString argument = argumentV.toString();
352         if (argument == QLatin1String("freetype"))
353             return FontDatabaseFreeType;
354         if (argument == QLatin1String("native"))
355             return FontDatabaseNative;
356     }
357     return FontDatabaseNative;
358 }
359
360 QPlatformFontDatabase *QWindowsIntegration::fontDatabase() const
361 {
362     if (!d->m_fontDatabase) {
363 #ifdef QT_NO_FREETYPE
364         d->m_fontDatabase = new QWindowsFontDatabase();
365 #else
366         FontDatabaseOption option = fontDatabaseOption(d->m_nativeInterface);
367         if (option == FontDatabaseFreeType) {
368             d->m_fontDatabase = new QWindowsFontDatabaseFT;
369         } else {
370             d->m_fontDatabase = new QWindowsFontDatabase;
371         }
372 #endif
373     }
374     return d->m_fontDatabase;
375 }
376
377 #ifdef SPI_GETKEYBOARDSPEED
378 static inline int keyBoardAutoRepeatRateMS()
379 {
380   DWORD time = 0;
381   if (SystemParametersInfo(SPI_GETKEYBOARDSPEED, 0, &time, 0))
382       return time ? 1000 / static_cast<int>(time) : 500;
383   return 30;
384 }
385 #endif
386
387 QVariant QWindowsIntegration::styleHint(QPlatformIntegration::StyleHint hint) const
388 {
389     switch (hint) {
390     case QPlatformIntegration::CursorFlashTime:
391         if (const unsigned timeMS = GetCaretBlinkTime())
392             return QVariant(int(timeMS));
393         break;
394 #ifdef SPI_GETKEYBOARDSPEED
395     case KeyboardAutoRepeatRate:
396         return QVariant(keyBoardAutoRepeatRateMS());
397 #endif
398     case QPlatformIntegration::StartDragTime:
399     case QPlatformIntegration::StartDragDistance:
400     case QPlatformIntegration::KeyboardInputInterval:
401     case QPlatformIntegration::ShowIsFullScreen:
402     case QPlatformIntegration::PasswordMaskDelay:
403     case QPlatformIntegration::StartDragVelocity:
404         break; // Not implemented
405     case QPlatformIntegration::FontSmoothingGamma:
406         return QVariant(QWindowsFontDatabase::fontSmoothingGamma());
407     case QPlatformIntegration::MouseDoubleClickInterval:
408         if (const int ms = GetDoubleClickTime())
409             return QVariant(ms);
410         break;
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"