Implement QSystemTrayIcon for Windows.
[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 #include "qwindowsglcontext.h"
47 #include "qwindowsscreen.h"
48 #include "qwindowstheme.h"
49 #include "qwindowsservices.h"
50 #ifndef QT_NO_FREETYPE
51 #include "qwindowsfontdatabase_ft.h"
52 #endif
53 #include "qwindowsfontdatabase.h"
54 #include "qwindowsguieventdispatcher.h"
55 #include "qwindowsclipboard.h"
56 #include "qwindowsdrag.h"
57 #include "qwindowsinputcontext.h"
58 #include "qwindowsaccessibility.h"
59
60 #include <QtGui/QPlatformNativeInterface>
61 #include <QtGui/QWindowSystemInterface>
62 #include <QtGui/QBackingStore>
63 #include <QtGui/private/qpixmap_raster_p.h>
64 #include <QtGui/private/qguiapplication_p.h>
65
66 #include <QtCore/private/qeventdispatcher_win_p.h>
67 #include <QtCore/QDebug>
68
69 QT_BEGIN_NAMESPACE
70
71 /*!
72     \class QWindowsNativeInterface
73     \brief Provides access to native handles.
74
75     Currently implemented keys
76     \list
77     \li handle (HWND)
78     \li getDC (DC)
79     \li releaseDC Releases the previously acquired DC and returns 0.
80     \endlist
81
82     \ingroup qt-lighthouse-win
83 */
84
85 class QWindowsNativeInterface : public QPlatformNativeInterface
86 {
87     Q_OBJECT
88 public:
89     virtual void *nativeResourceForContext(const QByteArray &resource, QOpenGLContext *context);
90     virtual void *nativeResourceForWindow(const QByteArray &resource, QWindow *window);
91     virtual void *nativeResourceForBackingStore(const QByteArray &resource, QBackingStore *bs);
92     virtual EventFilter setEventFilter(const QByteArray &eventType, EventFilter filter)
93         { return QWindowsContext::instance()->setEventFilter(eventType, filter); }
94
95     Q_INVOKABLE void *createMessageWindow(const QString &classNameTemplate,
96                                           const QString &windowName,
97                                           void *eventProc) const;
98 };
99
100 void *QWindowsNativeInterface::nativeResourceForWindow(const QByteArray &resource, QWindow *window)
101 {
102     if (!window || !window->handle()) {
103         qWarning("%s: '%s' requested for null window or window without handle.", __FUNCTION__, resource.constData());
104         return 0;
105     }
106     QWindowsWindow *bw = static_cast<QWindowsWindow *>(window->handle());
107     if (resource == "handle")
108         return bw->handle();
109     if (window->surfaceType() == QWindow::RasterSurface) {
110         if (resource == "getDC")
111             return bw->getDC();
112         if (resource == "releaseDC") {
113             bw->releaseDC();
114             return 0;
115         }
116     }
117     qWarning("%s: Invalid key '%s' requested.", __FUNCTION__, resource.constData());
118     return 0;
119 }
120
121 void *QWindowsNativeInterface::nativeResourceForBackingStore(const QByteArray &resource, QBackingStore *bs)
122 {
123     if (!bs || !bs->handle()) {
124         qWarning("%s: '%s' requested for null backingstore or backingstore without handle.", __FUNCTION__, resource.constData());
125         return 0;
126     }
127     QWindowsBackingStore *wbs = static_cast<QWindowsBackingStore *>(bs->handle());
128     if (resource == "getDC")
129         return wbs->getDC();
130     qWarning("%s: Invalid key '%s' requested.", __FUNCTION__, resource.constData());
131     return 0;
132 }
133
134 void *QWindowsNativeInterface::nativeResourceForContext(const QByteArray &resource, QOpenGLContext *context)
135 {
136     if (!context || !context->handle()) {
137         qWarning("%s: '%s' requested for null context or context without handle.", __FUNCTION__, resource.constData());
138         return 0;
139     }
140     QWindowsGLContext *windowsContext = static_cast<QWindowsGLContext *>(context->handle());
141     if (resource == "renderingContext")
142         return windowsContext->renderingContext();
143
144     qWarning("%s: Invalid key '%s' requested.", __FUNCTION__, resource.constData());
145     return 0;
146 }
147
148 /*!
149     \brief Creates a non-visible window handle for filtering messages.
150 */
151
152 void *QWindowsNativeInterface::createMessageWindow(const QString &classNameTemplate,
153                                                    const QString &windowName,
154                                                    void *eventProc) const
155 {
156     QWindowsContext *ctx = QWindowsContext::instance();
157     const HWND hwnd = ctx->createDummyWindow(classNameTemplate,
158                                              (wchar_t*)windowName.utf16(),
159                                              (WNDPROC)eventProc);
160     return hwnd;
161 }
162
163 /*!
164     \class QWindowsIntegration
165     \brief QPlatformIntegration implementation for Windows.
166     \ingroup qt-lighthouse-win
167 */
168
169 struct QWindowsIntegrationPrivate
170 {
171     typedef QSharedPointer<QOpenGLStaticContext> QOpenGLStaticContextPtr;
172
173     QWindowsIntegrationPrivate();
174     ~QWindowsIntegrationPrivate();
175
176     QWindowsContext m_context;
177     QPlatformFontDatabase *m_fontDatabase;
178     QWindowsNativeInterface m_nativeInterface;
179     QWindowsClipboard m_clipboard;
180     QWindowsDrag m_drag;
181     QWindowsGuiEventDispatcher *m_eventDispatcher;
182     QOpenGLStaticContextPtr m_staticOpenGLContext;
183     QWindowsInputContext m_inputContext;
184     QWindowsAccessibility m_accessibility;
185     QWindowsTheme m_theme;
186     QWindowsServices m_services;
187 };
188
189 QWindowsIntegrationPrivate::QWindowsIntegrationPrivate()
190     : m_fontDatabase(0), m_eventDispatcher(new QWindowsGuiEventDispatcher)
191 {
192 }
193
194 QWindowsIntegrationPrivate::~QWindowsIntegrationPrivate()
195 {
196     if (m_fontDatabase)
197         delete m_fontDatabase;
198 }
199
200 QWindowsIntegration::QWindowsIntegration() :
201     d(new QWindowsIntegrationPrivate)
202 {
203     QGuiApplicationPrivate::instance()->setEventDispatcher(d->m_eventDispatcher);
204     d->m_clipboard.registerViewer();
205     d->m_context.screenManager().handleScreenChanges();
206 }
207
208 QWindowsIntegration::~QWindowsIntegration()
209 {
210     if (QWindowsContext::verboseIntegration)
211         qDebug("%s", __FUNCTION__);
212 }
213
214 bool QWindowsIntegration::hasCapability(QPlatformIntegration::Capability cap) const
215 {
216     switch (cap) {
217     case ThreadedPixmaps:
218         return true;
219     case OpenGL:
220         return true;
221     case ThreadedOpenGL:
222         return true;
223     default:
224         return QPlatformIntegration::hasCapability(cap);
225     }
226     return false;
227 }
228
229 QPlatformPixmap *QWindowsIntegration::createPlatformPixmap(QPlatformPixmap::PixelType type) const
230 {
231     if (QWindowsContext::verboseIntegration)
232         qDebug() << __FUNCTION__ << type;
233     return new QRasterPlatformPixmap(type);
234 }
235
236 QPlatformWindow *QWindowsIntegration::createPlatformWindow(QWindow *window) const
237 {
238     QWindowsWindow::WindowData requested;
239     requested.flags = window->windowFlags();
240     requested.geometry = window->geometry();
241     const QWindowsWindow::WindowData obtained
242             = QWindowsWindow::WindowData::create(window, requested, window->windowTitle());
243     if (QWindowsContext::verboseIntegration || QWindowsContext::verboseWindows)
244         qDebug().nospace()
245             << __FUNCTION__ << ' ' << window << '\n'
246             << "    Requested: " << requested.geometry << " Flags="
247             << QWindowsWindow::debugWindowFlags(requested.flags) << '\n'
248             << "    Obtained : " << obtained.geometry << " Margins "
249             << obtained.frame  << " Flags="
250             << QWindowsWindow::debugWindowFlags(obtained.flags)
251             << " Handle=" << obtained.hwnd << '\n';
252     if (!obtained.hwnd)
253         return 0;
254     if (requested.flags != obtained.flags)
255         window->setWindowFlags(obtained.flags);
256     if (requested.geometry != obtained.geometry)
257         QWindowSystemInterface::handleGeometryChange(window, obtained.geometry);
258     return new QWindowsWindow(window, obtained);
259 }
260
261 QPlatformBackingStore *QWindowsIntegration::createPlatformBackingStore(QWindow *window) const
262 {
263     if (QWindowsContext::verboseIntegration)
264         qDebug() << __FUNCTION__ << window;
265     return new QWindowsBackingStore(window);
266 }
267
268 QPlatformOpenGLContext
269     *QWindowsIntegration::createPlatformOpenGLContext(QOpenGLContext *context) const
270 {
271     if (QWindowsContext::verboseIntegration)
272         qDebug() << __FUNCTION__ << context->format();
273     if (d->m_staticOpenGLContext.isNull())
274         d->m_staticOpenGLContext =
275             QSharedPointer<QOpenGLStaticContext>(QOpenGLStaticContext::create());
276     QScopedPointer<QWindowsGLContext> result(new QWindowsGLContext(d->m_staticOpenGLContext, context));
277     if (result->isValid())
278         return result.take();
279     return 0;
280 }
281
282 QPlatformFontDatabase *QWindowsIntegration::fontDatabase() const
283 {
284     if (!d->m_fontDatabase) {
285 #ifndef QT_NO_FREETYPE
286         if (d->m_nativeInterface.property("fontengine").toString() == QLatin1String("native"))
287             d->m_fontDatabase = new QWindowsFontDatabase();
288         else
289             d->m_fontDatabase = new QWindowsFontDatabaseFT();
290 #else
291         d->m_fontDatabase = new QWindowsFontDatabase();
292 #endif
293     }
294     return d->m_fontDatabase;
295 }
296
297 static inline int keyBoardAutoRepeatRateMS()
298 {
299   DWORD time = 0;
300   if (SystemParametersInfo(SPI_GETKEYBOARDSPEED, 0, &time, 0))
301       return time ? 1000 / static_cast<int>(time) : 500;
302   return 30;
303 }
304
305 QVariant QWindowsIntegration::styleHint(QPlatformIntegration::StyleHint hint) const
306 {
307     switch (hint) {
308     case QPlatformIntegration::CursorFlashTime:
309         if (const unsigned timeMS = GetCaretBlinkTime())
310             return QVariant(int(timeMS));
311         break;
312     case KeyboardAutoRepeatRate:
313         return QVariant(keyBoardAutoRepeatRateMS());
314     case QPlatformIntegration::StartDragTime:
315     case QPlatformIntegration::StartDragDistance:
316     case QPlatformIntegration::MouseDoubleClickInterval:
317     case QPlatformIntegration::KeyboardInputInterval:
318     case QPlatformIntegration::ShowIsFullScreen:
319         break; // Not implemented
320     }
321     return QPlatformIntegration::styleHint(hint);
322 }
323
324 QPlatformNativeInterface *QWindowsIntegration::nativeInterface() const
325 {
326     return &d->m_nativeInterface;
327 }
328
329 QPlatformClipboard * QWindowsIntegration::clipboard() const
330 {
331     return &d->m_clipboard;
332 }
333
334 QPlatformDrag *QWindowsIntegration::drag() const
335 {
336     return &d->m_drag;
337 }
338
339 QPlatformInputContext * QWindowsIntegration::inputContext() const
340 {
341     return &d->m_inputContext;
342 }
343
344 QPlatformAccessibility *QWindowsIntegration::accessibility() const
345 {
346     return &d->m_accessibility;
347 }
348
349 QWindowsIntegration *QWindowsIntegration::instance()
350 {
351     return static_cast<QWindowsIntegration *>(QGuiApplicationPrivate::platformIntegration());
352 }
353
354 QAbstractEventDispatcher * QWindowsIntegration::guiThreadEventDispatcher() const
355 {
356     return d->m_eventDispatcher;
357 }
358
359 QPlatformTheme *QWindowsIntegration::platformTheme() const
360 {
361     return &d->m_theme;
362 }
363
364 QPlatformServices *QWindowsIntegration::services() const
365 {
366     return &d->m_services;
367 }
368
369 QT_END_NAMESPACE
370
371 #include "qwindowsintegration.moc"