b4112999b6e57367cf0bee9a33f4c34507a66122
[profile/ivi/qtbase.git] / src / plugins / platforms / qnx / qqnxintegration.cpp
1 /***************************************************************************
2 **
3 ** Copyright (C) 2011 - 2012 Research In Motion
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 "qqnxintegration.h"
43 #include "qqnxeventthread.h"
44 #include "qqnxglbackingstore.h"
45 #include "qqnxglcontext.h"
46 #include "qqnxnativeinterface.h"
47 #include "qqnxnavigatoreventhandler.h"
48 #include "qqnxnavigatoreventnotifier.h"
49 #include "qqnxrasterbackingstore.h"
50 #include "qqnxscreen.h"
51 #include "qqnxscreeneventhandler.h"
52 #include "qqnxwindow.h"
53 #include "qqnxvirtualkeyboard.h"
54 #include "qqnxclipboard.h"
55 #include "qqnxglcontext.h"
56 #include "qqnxservices.h"
57
58 #if defined(QQnx_IMF)
59 #include "qqnxinputcontext_imf.h"
60 #else
61 #include "qqnxinputcontext_noimf.h"
62 #endif
63
64 #include "private/qgenericunixfontdatabase_p.h"
65 #include "private/qgenericunixeventdispatcher_p.h"
66
67 #include <QtGui/QPlatformWindow>
68 #include <QtGui/QWindowSystemInterface>
69 #include <QtGui/QOpenGLContext>
70
71 #include <QtCore/QDebug>
72 #include <QtCore/QHash>
73
74 #include <errno.h>
75
76 QT_BEGIN_NAMESPACE
77
78 QQnxWindowMapper QQnxIntegration::ms_windowMapper;
79 QMutex QQnxIntegration::ms_windowMapperMutex;
80
81 QQnxIntegration::QQnxIntegration()
82     : QPlatformIntegration()
83     , m_eventThread(0)
84     , m_navigatorEventHandler(new QQnxNavigatorEventHandler())
85     , m_navigatorEventNotifier(0)
86     , m_virtualKeyboard(0)
87     , m_inputContext(0)
88     , m_fontDatabase(new QGenericUnixFontDatabase())
89     , m_paintUsingOpenGL(false)
90     , m_eventDispatcher(createUnixEventDispatcher())
91     , m_nativeInterface(new QQnxNativeInterface())
92     , m_services(0)
93     , m_screenEventHandler(new QQnxScreenEventHandler())
94 #ifndef QT_NO_CLIPBOARD
95     , m_clipboard(0)
96 #endif
97 {
98 #if defined(QQNXINTEGRATION_DEBUG)
99     qDebug() << Q_FUNC_INFO;
100 #endif
101     // Open connection to QNX composition manager
102     errno = 0;
103     int result = screen_create_context(&m_screenContext, SCREEN_APPLICATION_CONTEXT);
104     if (result != 0) {
105         qFatal("QQnx: failed to connect to composition manager, errno=%d", errno);
106     }
107
108     // Create/start navigator event notifier
109     m_navigatorEventNotifier = new QQnxNavigatorEventNotifier(m_navigatorEventHandler);
110
111     // delay invocation of start() to the time the event loop is up and running
112     // needed to have the QThread internals of the main thread properly initialized
113     QMetaObject::invokeMethod(m_navigatorEventNotifier, "start", Qt::QueuedConnection);
114
115     // Create displays for all possible screens (which may not be attached)
116     createDisplays();
117
118     // Initialize global OpenGL resources
119     QQnxGLContext::initialize();
120
121     // Create/start event thread
122     m_eventThread = new QQnxEventThread(m_screenContext, m_screenEventHandler);
123     m_eventThread->start();
124
125     // Create/start the keyboard class.
126     m_virtualKeyboard = new QQnxVirtualKeyboard();
127
128     // delay invocation of start() to the time the event loop is up and running
129     // needed to have the QThread internals of the main thread properly initialized
130     QMetaObject::invokeMethod(m_virtualKeyboard, "start", Qt::QueuedConnection);
131
132     // TODO check if we need to do this for all screens or only the primary one
133     QObject::connect(m_virtualKeyboard, SIGNAL(heightChanged(int)),
134                      primaryDisplay(), SLOT(keyboardHeightChanged(int)));
135
136     // Set up the input context
137     m_inputContext = new QQnxInputContext(*m_virtualKeyboard);
138
139     // Create services handling class
140 #ifdef Q_OS_BLACKBERRY
141     m_services = new QQnxServices;
142 #endif
143 }
144
145 QQnxIntegration::~QQnxIntegration()
146 {
147 #if defined(QQNXINTEGRATION_DEBUG)
148     qDebug() << "QQnx: platform plugin shutdown begin";
149 #endif
150
151
152     delete m_nativeInterface;
153
154     // Destroy input context
155     delete m_inputContext;
156
157     // Destroy the keyboard class.
158     delete m_virtualKeyboard;
159
160 #ifndef QT_NO_CLIPBOARD
161     // Delete the clipboard
162     delete m_clipboard;
163 #endif
164
165     // Stop/destroy navigator event notifier
166     delete m_navigatorEventNotifier;
167     delete m_navigatorEventHandler;
168
169     // Stop/destroy event thread
170     delete m_eventThread;
171     delete m_screenEventHandler;
172
173     // Destroy all displays
174     destroyDisplays();
175
176     // Close connection to QNX composition manager
177     screen_destroy_context(m_screenContext);
178
179     // Cleanup global OpenGL resources
180     QQnxGLContext::shutdown();
181
182     // Destroy services class
183 #ifdef Q_OS_BLACKBERRY
184     delete m_services;
185 #endif
186
187 #if defined(QQNXINTEGRATION_DEBUG)
188     qDebug() << "QQnx: platform plugin shutdown end";
189 #endif
190 }
191
192 bool QQnxIntegration::hasCapability(QPlatformIntegration::Capability cap) const
193 {
194 #if defined(QQNXINTEGRATION_DEBUG)
195     qDebug() << Q_FUNC_INFO;
196 #endif
197     switch (cap) {
198     case ThreadedPixmaps: return true;
199 #if defined(QT_OPENGL_ES)
200     case OpenGL:
201         return true;
202 #endif
203     default: return QPlatformIntegration::hasCapability(cap);
204     }
205 }
206
207 QPlatformWindow *QQnxIntegration::createPlatformWindow(QWindow *window) const
208 {
209 #if defined(QQNXINTEGRATION_DEBUG)
210     qDebug() << Q_FUNC_INFO;
211 #endif
212     return new QQnxWindow(window, m_screenContext);
213 }
214
215 QPlatformBackingStore *QQnxIntegration::createPlatformBackingStore(QWindow *window) const
216 {
217 #if defined(QQNXINTEGRATION_DEBUG)
218     qDebug() << Q_FUNC_INFO;
219 #endif
220     if (paintUsingOpenGL())
221         return new QQnxGLBackingStore(window);
222     else
223         return new QQnxRasterBackingStore(window);
224 }
225
226 QPlatformOpenGLContext *QQnxIntegration::createPlatformOpenGLContext(QOpenGLContext *context) const
227 {
228 #if defined(QQNXINTEGRATION_DEBUG)
229     qDebug() << Q_FUNC_INFO;
230 #endif
231     return new QQnxGLContext(context);
232 }
233
234 QPlatformInputContext *QQnxIntegration::inputContext() const
235 {
236 #if defined(QQNXINTEGRATION_DEBUG)
237     qDebug() << Q_FUNC_INFO;
238 #endif
239     return m_inputContext;
240 }
241
242 void QQnxIntegration::moveToScreen(QWindow *window, int screen)
243 {
244 #if defined(QQNXINTEGRATION_DEBUG)
245     qDebug() << "QQnxIntegration::moveToScreen - w=" << window << ", s=" << screen;
246 #endif
247
248     // get platform window used by widget
249     QQnxWindow *platformWindow = static_cast<QQnxWindow *>(window->handle());
250
251     // lookup platform screen by index
252     QQnxScreen *platformScreen = m_screens.at(screen);
253
254     // move the platform window to the platform screen
255     platformWindow->setScreen(platformScreen);
256 }
257
258 QAbstractEventDispatcher *QQnxIntegration::guiThreadEventDispatcher() const
259 {
260 #if defined(QQNXINTEGRATION_DEBUG)
261     qDebug() << Q_FUNC_INFO;
262 #endif
263     return m_eventDispatcher;
264 }
265
266 QPlatformNativeInterface *QQnxIntegration::nativeInterface() const
267 {
268     return m_nativeInterface;
269 }
270
271 #ifndef QT_NO_CLIPBOARD
272 QPlatformClipboard *QQnxIntegration::clipboard() const
273 {
274 #if defined(QQNXINTEGRATION_DEBUG)
275     qDebug() << Q_FUNC_INFO;
276 #endif
277     if (!m_clipboard) {
278         m_clipboard = new QQnxClipboard;
279     }
280     return m_clipboard;
281 }
282 #endif
283
284 QVariant QQnxIntegration::styleHint(QPlatformIntegration::StyleHint hint) const
285 {
286 #if defined(QQNXINTEGRATION_DEBUG)
287     qDebug() << Q_FUNC_INFO;
288 #endif
289     if (hint == ShowIsFullScreen)
290         return true;
291
292     return QPlatformIntegration::styleHint(hint);
293 }
294
295 QPlatformServices * QQnxIntegration::services() const
296 {
297     return m_services;
298 }
299
300 QWindow *QQnxIntegration::window(screen_window_t qnxWindow)
301 {
302 #if defined(QQNXINTEGRATION_DEBUG)
303     qDebug() << Q_FUNC_INFO;
304 #endif
305     QMutexLocker locker(&ms_windowMapperMutex);
306     Q_UNUSED(locker);
307     return ms_windowMapper.value(qnxWindow, 0);
308 }
309
310 void QQnxIntegration::addWindow(screen_window_t qnxWindow, QWindow *window)
311 {
312 #if defined(QQNXINTEGRATION_DEBUG)
313     qDebug() << Q_FUNC_INFO;
314 #endif
315     QMutexLocker locker(&ms_windowMapperMutex);
316     Q_UNUSED(locker);
317     ms_windowMapper.insert(qnxWindow, window);
318 }
319
320 void QQnxIntegration::removeWindow(screen_window_t qnxWindow)
321 {
322 #if defined(QQNXINTEGRATION_DEBUG)
323     qDebug() << Q_FUNC_INFO;
324 #endif
325     QMutexLocker locker(&ms_windowMapperMutex);
326     Q_UNUSED(locker);
327     ms_windowMapper.remove(qnxWindow);
328 }
329
330 void QQnxIntegration::createDisplays()
331 {
332 #if defined(QQNXINTEGRATION_DEBUG)
333     qDebug() << Q_FUNC_INFO;
334 #endif
335     // Query number of displays
336     errno = 0;
337     int displayCount;
338     int result = screen_get_context_property_iv(m_screenContext, SCREEN_PROPERTY_DISPLAY_COUNT, &displayCount);
339     if (result != 0) {
340         qFatal("QQnxIntegration: failed to query display count, errno=%d", errno);
341     }
342
343     // Get all displays
344     errno = 0;
345     screen_display_t *displays = (screen_display_t *)alloca(sizeof(screen_display_t) * displayCount);
346     result = screen_get_context_property_pv(m_screenContext, SCREEN_PROPERTY_DISPLAYS, (void **)displays);
347     if (result != 0) {
348         qFatal("QQnxIntegration: failed to query displays, errno=%d", errno);
349     }
350
351     for (int i=0; i<displayCount; i++) {
352 #if defined(QQNXINTEGRATION_DEBUG)
353         qDebug() << "QQnxIntegration::Creating screen for display " << i;
354 #endif
355         QQnxScreen *screen = new QQnxScreen(m_screenContext, displays[i], i==0);
356         m_screens.append(screen);
357         screenAdded(screen);
358
359         QObject::connect(m_screenEventHandler, SIGNAL(newWindowCreated(void *)),
360                          screen, SLOT(newWindowCreated(void *)));
361         QObject::connect(m_screenEventHandler, SIGNAL(windowClosed(void *)),
362                          screen, SLOT(windowClosed(void *)));
363
364         QObject::connect(m_navigatorEventHandler, SIGNAL(rotationChanged(int)), screen, SLOT(setRotation(int)));
365     }
366 }
367
368 void QQnxIntegration::destroyDisplays()
369 {
370 #if defined(QQNXINTEGRATION_DEBUG)
371     qDebug() << Q_FUNC_INFO;
372 #endif
373     qDeleteAll(m_screens);
374     m_screens.clear();
375 }
376
377 QQnxScreen *QQnxIntegration::primaryDisplay() const
378 {
379     return m_screens.first();
380 }
381
382 QT_END_NAMESPACE