1 /***************************************************************************
3 ** Copyright (C) 2011 - 2012 Research In Motion
4 ** Contact: http://www.qt-project.org/
6 ** This file is part of the plugins of the Qt Toolkit.
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.
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.
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.
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.
40 ****************************************************************************/
42 #include "qqnxintegration.h"
43 #include "qqnxscreeneventthread.h"
44 #include "qqnxnativeinterface.h"
45 #include "qqnxrasterbackingstore.h"
46 #include "qqnxscreen.h"
47 #include "qqnxscreeneventhandler.h"
48 #include "qqnxwindow.h"
49 #include "qqnxnavigatoreventhandler.h"
50 #include "qqnxabstractnavigator.h"
51 #include "qqnxabstractvirtualkeyboard.h"
52 #include "qqnxservices.h"
54 #if defined(Q_OS_BLACKBERRY)
55 #include "qqnxbpseventfilter.h"
56 #include "qqnxnavigatorbps.h"
57 #include "qqnxtheme.h"
58 #include "qqnxvirtualkeyboardbps.h"
59 #elif defined(QQNX_PPS)
60 #include "qqnxnavigatorpps.h"
61 #include "qqnxvirtualkeyboardpps.h"
65 # include "qqnxnavigatoreventnotifier.h"
66 # include "qqnxclipboard.h"
68 # if defined(QQNX_IMF)
69 # include "qqnxinputcontext_imf.h"
71 # include "qqnxinputcontext_noimf.h"
75 #include "private/qgenericunixfontdatabase_p.h"
77 #if defined(Q_OS_BLACKBERRY)
78 #include "qqnxeventdispatcher_blackberry.h"
80 #include "private/qgenericunixeventdispatcher_p.h"
83 #include <qpa/qplatformwindow.h>
84 #include <QtGui/QWindowSystemInterface>
86 #if !defined(QT_NO_OPENGL)
87 #include "qqnxglbackingstore.h"
88 #include "qqnxglcontext.h"
90 #include <QtGui/QOpenGLContext>
93 #include <QtCore/QDebug>
94 #include <QtCore/QHash>
98 #ifdef QQNXINTEGRATION_DEBUG
99 #define qIntegrationDebug qDebug
101 #define qIntegrationDebug QT_NO_QDEBUG_MACRO
106 QQnxWindowMapper QQnxIntegration::ms_windowMapper;
107 QMutex QQnxIntegration::ms_windowMapperMutex;
109 QQnxIntegration::QQnxIntegration()
110 : QPlatformIntegration()
111 , m_screenEventThread(0)
112 , m_navigatorEventHandler(new QQnxNavigatorEventHandler())
113 , m_virtualKeyboard(0)
114 #if defined(QQNX_PPS)
115 , m_navigatorEventNotifier(0)
119 , m_fontDatabase(new QGenericUnixFontDatabase())
120 #if !defined(QT_NO_OPENGL)
121 , m_paintUsingOpenGL(false)
123 #if defined(Q_OS_BLACKBERRY)
124 , m_eventDispatcher(new QQnxEventDispatcherBlackberry())
125 , m_bpsEventFilter(0)
127 , m_eventDispatcher(createUnixEventDispatcher())
129 , m_nativeInterface(new QQnxNativeInterface())
130 , m_screenEventHandler(new QQnxScreenEventHandler())
131 #if !defined(QT_NO_CLIPBOARD)
135 qIntegrationDebug() << Q_FUNC_INFO;
136 // Open connection to QNX composition manager
138 int result = screen_create_context(&m_screenContext, SCREEN_APPLICATION_CONTEXT);
140 qFatal("QQnx: failed to connect to composition manager, errno=%d", errno);
143 // Not on BlackBerry, it has specialised event dispatcher which also handles navigator events
144 #if !defined(Q_OS_BLACKBERRY) && defined(QQNX_PPS)
145 // Create/start navigator event notifier
146 m_navigatorEventNotifier = new QQnxNavigatorEventNotifier(m_navigatorEventHandler);
148 // delay invocation of start() to the time the event loop is up and running
149 // needed to have the QThread internals of the main thread properly initialized
150 QMetaObject::invokeMethod(m_navigatorEventNotifier, "start", Qt::QueuedConnection);
153 #if !defined(QT_NO_OPENGL)
154 // Initialize global OpenGL resources
155 QQnxGLContext::initialize();
158 // Create/start event thread
159 #if defined(QQNX_SCREENEVENTTHREAD)
160 m_screenEventThread = new QQnxScreenEventThread(m_screenContext, m_screenEventHandler);
161 m_screenEventThread->start();
164 // Not on BlackBerry, it has specialised event dispatcher which also handles virtual keyboard events
165 #if !defined(Q_OS_BLACKBERRY) && defined(QQNX_PPS)
166 // Create/start the keyboard class.
167 m_virtualKeyboard = new QQnxVirtualKeyboardPps();
169 // delay invocation of start() to the time the event loop is up and running
170 // needed to have the QThread internals of the main thread properly initialized
171 QMetaObject::invokeMethod(m_virtualKeyboard, "start", Qt::QueuedConnection);
174 #if defined(Q_OS_BLACKBERRY)
175 m_navigator = new QQnxNavigatorBps();
176 #elif defined(QQNX_PPS)
177 m_navigator = new QQnxNavigatorPps();
180 // Create services handling class
182 m_services = new QQnxServices(m_navigator);
184 #if defined(Q_OS_BLACKBERRY)
185 QQnxVirtualKeyboardBps* virtualKeyboardBps = new QQnxVirtualKeyboardBps;
186 m_bpsEventFilter = new QQnxBpsEventFilter(m_navigatorEventHandler,
187 (m_screenEventThread ? 0 : m_screenEventHandler), virtualKeyboardBps);
188 m_bpsEventFilter->installOnEventDispatcher(m_eventDispatcher);
190 m_virtualKeyboard = virtualKeyboardBps;
193 // Create displays for all possible screens (which may not be attached). We have to do this
194 // *after* the call to m_bpsEventFilter->installOnEventDispatcher(m_eventDispatcher). The
195 // reason for this is that we have to be registered for NAVIGATOR events before we create the
196 // QQnxScreen objects, and hence the QQnxRootWindow's. It is when the NAVIGATOR service sees
197 // the window creation that it starts sending us messages which results in a race if we
198 // create the displays first.
201 #if !defined(QQNX_SCREENEVENTTHREAD) && defined(Q_OS_BLACKBERRY)
202 // Register for screen domain events with bps
203 Q_FOREACH (QQnxScreen *screen, m_screens)
204 m_bpsEventFilter->registerForScreenEvents(screen);
207 if (m_virtualKeyboard) {
208 // TODO check if we need to do this for all screens or only the primary one
209 QObject::connect(m_virtualKeyboard, SIGNAL(heightChanged(int)),
210 primaryDisplay(), SLOT(keyboardHeightChanged(int)));
212 #if defined(QQNX_PPS)
213 // Set up the input context
214 m_inputContext = new QQnxInputContext(*m_virtualKeyboard);
220 QQnxIntegration::~QQnxIntegration()
222 qIntegrationDebug() << Q_FUNC_INFO << "platform plugin shutdown begin";
223 delete m_nativeInterface;
225 #if defined(QQNX_PPS)
226 // Destroy input context
227 delete m_inputContext;
230 // Destroy the keyboard class.
231 delete m_virtualKeyboard;
233 #if !defined(QT_NO_CLIPBOARD)
234 // Delete the clipboard
238 // Stop/destroy navigator event notifier
239 #if defined(QQNX_PPS)
240 delete m_navigatorEventNotifier;
242 delete m_navigatorEventHandler;
244 #if defined(QQNX_SCREENEVENTTHREAD)
245 // Stop/destroy screen event thread
246 delete m_screenEventThread;
247 #elif defined(Q_OS_BLACKBERRY)
248 Q_FOREACH (QQnxScreen *screen, m_screens)
249 m_bpsEventFilter->unregisterForScreenEvents(screen);
252 #if defined(Q_OS_BLACKBERRY)
253 delete m_bpsEventFilter;
256 delete m_screenEventHandler;
258 // Destroy all displays
261 // Close connection to QNX composition manager
262 screen_destroy_context(m_screenContext);
264 #if !defined(QT_NO_OPENGL)
265 // Cleanup global OpenGL resources
266 QQnxGLContext::shutdown();
269 // Destroy services class
272 // Destroy navigator interface
275 qIntegrationDebug() << Q_FUNC_INFO << "platform plugin shutdown end";
278 bool QQnxIntegration::hasCapability(QPlatformIntegration::Capability cap) const
280 qIntegrationDebug() << Q_FUNC_INFO;
282 case ThreadedPixmaps: return true;
283 #if defined(QT_OPENGL_ES)
287 default: return QPlatformIntegration::hasCapability(cap);
291 QPlatformWindow *QQnxIntegration::createPlatformWindow(QWindow *window) const
293 qIntegrationDebug() << Q_FUNC_INFO;
294 return new QQnxWindow(window, m_screenContext);
297 QPlatformBackingStore *QQnxIntegration::createPlatformBackingStore(QWindow *window) const
299 qIntegrationDebug() << Q_FUNC_INFO;
300 #if !defined(QT_NO_OPENGL)
301 if (paintUsingOpenGL())
302 return new QQnxGLBackingStore(window);
305 return new QQnxRasterBackingStore(window);
308 #if !defined(QT_NO_OPENGL)
309 QPlatformOpenGLContext *QQnxIntegration::createPlatformOpenGLContext(QOpenGLContext *context) const
311 qIntegrationDebug() << Q_FUNC_INFO;
312 return new QQnxGLContext(context);
316 #if defined(QQNX_PPS)
317 QPlatformInputContext *QQnxIntegration::inputContext() const
319 qIntegrationDebug() << Q_FUNC_INFO;
320 return m_inputContext;
324 void QQnxIntegration::moveToScreen(QWindow *window, int screen)
326 qIntegrationDebug() << Q_FUNC_INFO << "w =" << window << ", s =" << screen;
328 // get platform window used by widget
329 QQnxWindow *platformWindow = static_cast<QQnxWindow *>(window->handle());
331 // lookup platform screen by index
332 QQnxScreen *platformScreen = m_screens.at(screen);
334 // move the platform window to the platform screen
335 platformWindow->setScreen(platformScreen);
338 QAbstractEventDispatcher *QQnxIntegration::guiThreadEventDispatcher() const
340 qIntegrationDebug() << Q_FUNC_INFO;
341 return m_eventDispatcher;
344 QPlatformNativeInterface *QQnxIntegration::nativeInterface() const
346 return m_nativeInterface;
349 #if !defined(QT_NO_CLIPBOARD)
350 QPlatformClipboard *QQnxIntegration::clipboard() const
352 qIntegrationDebug() << Q_FUNC_INFO;
354 #if defined(QQNX_PPS)
356 m_clipboard = new QQnxClipboard;
363 QVariant QQnxIntegration::styleHint(QPlatformIntegration::StyleHint hint) const
365 qIntegrationDebug() << Q_FUNC_INFO;
366 if (hint == ShowIsFullScreen)
369 return QPlatformIntegration::styleHint(hint);
372 QPlatformServices * QQnxIntegration::services() const
377 #if defined(Q_OS_BLACKBERRY)
378 QStringList QQnxIntegration::themeNames() const
380 return QStringList(QQnxTheme::name());
383 QPlatformTheme *QQnxIntegration::createPlatformTheme(const QString &name) const
385 qIntegrationDebug() << Q_FUNC_INFO << "name =" << name;
386 if (name == QQnxTheme::name())
387 return new QQnxTheme(m_fontDatabase, m_bpsEventFilter);
388 return QPlatformIntegration::createPlatformTheme(name);
392 QWindow *QQnxIntegration::window(screen_window_t qnxWindow)
394 qIntegrationDebug() << Q_FUNC_INFO;
395 QMutexLocker locker(&ms_windowMapperMutex);
397 return ms_windowMapper.value(qnxWindow, 0);
400 void QQnxIntegration::addWindow(screen_window_t qnxWindow, QWindow *window)
402 qIntegrationDebug() << Q_FUNC_INFO;
403 QMutexLocker locker(&ms_windowMapperMutex);
405 ms_windowMapper.insert(qnxWindow, window);
408 void QQnxIntegration::removeWindow(screen_window_t qnxWindow)
410 qIntegrationDebug() << Q_FUNC_INFO;
411 QMutexLocker locker(&ms_windowMapperMutex);
413 ms_windowMapper.remove(qnxWindow);
416 void QQnxIntegration::createDisplays()
418 qIntegrationDebug() << Q_FUNC_INFO;
419 // Query number of displays
422 int result = screen_get_context_property_iv(m_screenContext, SCREEN_PROPERTY_DISPLAY_COUNT, &displayCount);
424 qFatal("QQnxIntegration: failed to query display count, errno=%d", errno);
429 screen_display_t *displays = (screen_display_t *)alloca(sizeof(screen_display_t) * displayCount);
430 result = screen_get_context_property_pv(m_screenContext, SCREEN_PROPERTY_DISPLAYS, (void **)displays);
432 qFatal("QQnxIntegration: failed to query displays, errno=%d", errno);
435 for (int i=0; i<displayCount; i++) {
436 qIntegrationDebug() << Q_FUNC_INFO << "Creating screen for display" << i;
437 QQnxScreen *screen = new QQnxScreen(m_screenContext, displays[i], i==0);
438 m_screens.append(screen);
441 QObject::connect(m_screenEventHandler, SIGNAL(newWindowCreated(void *)),
442 screen, SLOT(newWindowCreated(void *)));
443 QObject::connect(m_screenEventHandler, SIGNAL(windowClosed(void *)),
444 screen, SLOT(windowClosed(void *)));
446 QObject::connect(m_navigatorEventHandler, SIGNAL(rotationChanged(int)), screen, SLOT(setRotation(int)));
447 QObject::connect(m_navigatorEventHandler, SIGNAL(windowGroupActivated(QByteArray)), screen, SLOT(activateWindowGroup(QByteArray)));
448 QObject::connect(m_navigatorEventHandler, SIGNAL(windowGroupDeactivated(QByteArray)), screen, SLOT(deactivateWindowGroup(QByteArray)));
452 void QQnxIntegration::destroyDisplays()
454 qIntegrationDebug() << Q_FUNC_INFO;
455 qDeleteAll(m_screens);
459 QQnxScreen *QQnxIntegration::primaryDisplay() const
461 return m_screens.first();