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 <qpa/qwindowsysteminterface.h>
86 #if !defined(QT_NO_OPENGL)
87 #include "qqnxglcontext.h"
88 #include <QtGui/QOpenGLContext>
91 #include <QtCore/QDebug>
92 #include <QtCore/QHash>
96 #ifdef QQNXINTEGRATION_DEBUG
97 #define qIntegrationDebug qDebug
99 #define qIntegrationDebug QT_NO_QDEBUG_MACRO
104 QQnxWindowMapper QQnxIntegration::ms_windowMapper;
105 QMutex QQnxIntegration::ms_windowMapperMutex;
107 QQnxIntegration::QQnxIntegration()
108 : QPlatformIntegration()
109 , m_screenEventThread(0)
110 , m_navigatorEventHandler(new QQnxNavigatorEventHandler())
111 , m_virtualKeyboard(0)
112 #if defined(QQNX_PPS)
113 , m_navigatorEventNotifier(0)
117 , m_fontDatabase(new QGenericUnixFontDatabase())
118 #if defined(Q_OS_BLACKBERRY)
119 , m_eventDispatcher(new QQnxEventDispatcherBlackberry())
120 , m_bpsEventFilter(0)
122 , m_eventDispatcher(createUnixEventDispatcher())
124 , m_nativeInterface(new QQnxNativeInterface())
125 , m_screenEventHandler(new QQnxScreenEventHandler())
126 #if !defined(QT_NO_CLIPBOARD)
130 qIntegrationDebug() << Q_FUNC_INFO;
131 // Open connection to QNX composition manager
133 int result = screen_create_context(&m_screenContext, SCREEN_APPLICATION_CONTEXT);
135 qFatal("QQnx: failed to connect to composition manager, errno=%d", errno);
138 // Not on BlackBerry, it has specialised event dispatcher which also handles navigator events
139 #if !defined(Q_OS_BLACKBERRY) && defined(QQNX_PPS)
140 // Create/start navigator event notifier
141 m_navigatorEventNotifier = new QQnxNavigatorEventNotifier(m_navigatorEventHandler);
143 // delay invocation of start() to the time the event loop is up and running
144 // needed to have the QThread internals of the main thread properly initialized
145 QMetaObject::invokeMethod(m_navigatorEventNotifier, "start", Qt::QueuedConnection);
148 #if !defined(QT_NO_OPENGL)
149 // Initialize global OpenGL resources
150 QQnxGLContext::initialize();
153 // Create/start event thread
154 #if defined(QQNX_SCREENEVENTTHREAD)
155 m_screenEventThread = new QQnxScreenEventThread(m_screenContext, m_screenEventHandler);
156 m_screenEventThread->start();
159 // Not on BlackBerry, it has specialised event dispatcher which also handles virtual keyboard events
160 #if !defined(Q_OS_BLACKBERRY) && defined(QQNX_PPS)
161 // Create/start the keyboard class.
162 m_virtualKeyboard = new QQnxVirtualKeyboardPps();
164 // delay invocation of start() to the time the event loop is up and running
165 // needed to have the QThread internals of the main thread properly initialized
166 QMetaObject::invokeMethod(m_virtualKeyboard, "start", Qt::QueuedConnection);
169 #if defined(Q_OS_BLACKBERRY)
170 m_navigator = new QQnxNavigatorBps();
171 #elif defined(QQNX_PPS)
172 m_navigator = new QQnxNavigatorPps();
175 // Create services handling class
177 m_services = new QQnxServices(m_navigator);
179 #if defined(Q_OS_BLACKBERRY)
180 QQnxVirtualKeyboardBps* virtualKeyboardBps = new QQnxVirtualKeyboardBps;
181 m_bpsEventFilter = new QQnxBpsEventFilter(m_navigatorEventHandler,
182 (m_screenEventThread ? 0 : m_screenEventHandler), virtualKeyboardBps);
183 m_bpsEventFilter->installOnEventDispatcher(m_eventDispatcher);
185 m_virtualKeyboard = virtualKeyboardBps;
188 // Create displays for all possible screens (which may not be attached). We have to do this
189 // *after* the call to m_bpsEventFilter->installOnEventDispatcher(m_eventDispatcher). The
190 // reason for this is that we have to be registered for NAVIGATOR events before we create the
191 // QQnxScreen objects, and hence the QQnxRootWindow's. It is when the NAVIGATOR service sees
192 // the window creation that it starts sending us messages which results in a race if we
193 // create the displays first.
196 #if !defined(QQNX_SCREENEVENTTHREAD) && defined(Q_OS_BLACKBERRY)
197 // Register for screen domain events with bps
198 Q_FOREACH (QQnxScreen *screen, m_screens)
199 m_bpsEventFilter->registerForScreenEvents(screen);
202 if (m_virtualKeyboard) {
203 // TODO check if we need to do this for all screens or only the primary one
204 QObject::connect(m_virtualKeyboard, SIGNAL(heightChanged(int)),
205 primaryDisplay(), SLOT(keyboardHeightChanged(int)));
207 #if defined(QQNX_PPS)
208 // Set up the input context
209 m_inputContext = new QQnxInputContext(*m_virtualKeyboard);
215 QQnxIntegration::~QQnxIntegration()
217 qIntegrationDebug() << Q_FUNC_INFO << "platform plugin shutdown begin";
218 delete m_nativeInterface;
220 #if defined(QQNX_PPS)
221 // Destroy input context
222 delete m_inputContext;
225 // Destroy the keyboard class.
226 delete m_virtualKeyboard;
228 #if !defined(QT_NO_CLIPBOARD)
229 // Delete the clipboard
233 // Stop/destroy navigator event notifier
234 #if defined(QQNX_PPS)
235 delete m_navigatorEventNotifier;
237 delete m_navigatorEventHandler;
239 #if defined(QQNX_SCREENEVENTTHREAD)
240 // Stop/destroy screen event thread
241 delete m_screenEventThread;
242 #elif defined(Q_OS_BLACKBERRY)
243 Q_FOREACH (QQnxScreen *screen, m_screens)
244 m_bpsEventFilter->unregisterForScreenEvents(screen);
247 #if defined(Q_OS_BLACKBERRY)
248 delete m_bpsEventFilter;
251 delete m_screenEventHandler;
253 // Destroy all displays
256 // Close connection to QNX composition manager
257 screen_destroy_context(m_screenContext);
259 #if !defined(QT_NO_OPENGL)
260 // Cleanup global OpenGL resources
261 QQnxGLContext::shutdown();
264 // Destroy services class
267 // Destroy navigator interface
270 qIntegrationDebug() << Q_FUNC_INFO << "platform plugin shutdown end";
273 bool QQnxIntegration::hasCapability(QPlatformIntegration::Capability cap) const
275 qIntegrationDebug() << Q_FUNC_INFO;
277 case ThreadedPixmaps:
279 #if defined(QT_OPENGL_ES)
282 case BufferQueueingOpenGL:
286 return QPlatformIntegration::hasCapability(cap);
290 QPlatformWindow *QQnxIntegration::createPlatformWindow(QWindow *window) const
292 qIntegrationDebug() << Q_FUNC_INFO;
293 return new QQnxWindow(window, m_screenContext);
296 QPlatformBackingStore *QQnxIntegration::createPlatformBackingStore(QWindow *window) const
298 qIntegrationDebug() << Q_FUNC_INFO;
299 return new QQnxRasterBackingStore(window);
302 #if !defined(QT_NO_OPENGL)
303 QPlatformOpenGLContext *QQnxIntegration::createPlatformOpenGLContext(QOpenGLContext *context) const
305 qIntegrationDebug() << Q_FUNC_INFO;
306 return new QQnxGLContext(context);
310 #if defined(QQNX_PPS)
311 QPlatformInputContext *QQnxIntegration::inputContext() const
313 qIntegrationDebug() << Q_FUNC_INFO;
314 return m_inputContext;
318 void QQnxIntegration::moveToScreen(QWindow *window, int screen)
320 qIntegrationDebug() << Q_FUNC_INFO << "w =" << window << ", s =" << screen;
322 // get platform window used by widget
323 QQnxWindow *platformWindow = static_cast<QQnxWindow *>(window->handle());
325 // lookup platform screen by index
326 QQnxScreen *platformScreen = m_screens.at(screen);
328 // move the platform window to the platform screen
329 platformWindow->setScreen(platformScreen);
332 QAbstractEventDispatcher *QQnxIntegration::guiThreadEventDispatcher() const
334 qIntegrationDebug() << Q_FUNC_INFO;
335 return m_eventDispatcher;
338 QPlatformNativeInterface *QQnxIntegration::nativeInterface() const
340 return m_nativeInterface;
343 #if !defined(QT_NO_CLIPBOARD)
344 QPlatformClipboard *QQnxIntegration::clipboard() const
346 qIntegrationDebug() << Q_FUNC_INFO;
348 #if defined(QQNX_PPS)
350 m_clipboard = new QQnxClipboard;
357 QVariant QQnxIntegration::styleHint(QPlatformIntegration::StyleHint hint) const
359 qIntegrationDebug() << Q_FUNC_INFO;
360 if (hint == ShowIsFullScreen)
363 return QPlatformIntegration::styleHint(hint);
366 QPlatformServices * QQnxIntegration::services() const
371 #if defined(Q_OS_BLACKBERRY)
372 QStringList QQnxIntegration::themeNames() const
374 return QStringList(QQnxTheme::name());
377 QPlatformTheme *QQnxIntegration::createPlatformTheme(const QString &name) const
379 qIntegrationDebug() << Q_FUNC_INFO << "name =" << name;
380 if (name == QQnxTheme::name())
381 return new QQnxTheme(m_fontDatabase, m_bpsEventFilter);
382 return QPlatformIntegration::createPlatformTheme(name);
386 QWindow *QQnxIntegration::window(screen_window_t qnxWindow)
388 qIntegrationDebug() << Q_FUNC_INFO;
389 QMutexLocker locker(&ms_windowMapperMutex);
391 return ms_windowMapper.value(qnxWindow, 0);
394 void QQnxIntegration::addWindow(screen_window_t qnxWindow, QWindow *window)
396 qIntegrationDebug() << Q_FUNC_INFO;
397 QMutexLocker locker(&ms_windowMapperMutex);
399 ms_windowMapper.insert(qnxWindow, window);
402 void QQnxIntegration::removeWindow(screen_window_t qnxWindow)
404 qIntegrationDebug() << Q_FUNC_INFO;
405 QMutexLocker locker(&ms_windowMapperMutex);
407 ms_windowMapper.remove(qnxWindow);
410 void QQnxIntegration::createDisplays()
412 qIntegrationDebug() << Q_FUNC_INFO;
413 // Query number of displays
416 int result = screen_get_context_property_iv(m_screenContext, SCREEN_PROPERTY_DISPLAY_COUNT, &displayCount);
418 qFatal("QQnxIntegration: failed to query display count, errno=%d", errno);
423 screen_display_t *displays = (screen_display_t *)alloca(sizeof(screen_display_t) * displayCount);
424 result = screen_get_context_property_pv(m_screenContext, SCREEN_PROPERTY_DISPLAYS, (void **)displays);
426 qFatal("QQnxIntegration: failed to query displays, errno=%d", errno);
429 for (int i=0; i<displayCount; i++) {
430 qIntegrationDebug() << Q_FUNC_INFO << "Creating screen for display" << i;
431 QQnxScreen *screen = new QQnxScreen(m_screenContext, displays[i], i==0);
432 m_screens.append(screen);
435 QObject::connect(m_screenEventHandler, SIGNAL(newWindowCreated(void*)),
436 screen, SLOT(newWindowCreated(void*)));
437 QObject::connect(m_screenEventHandler, SIGNAL(windowClosed(void*)),
438 screen, SLOT(windowClosed(void*)));
440 QObject::connect(m_navigatorEventHandler, SIGNAL(rotationChanged(int)), screen, SLOT(setRotation(int)));
441 QObject::connect(m_navigatorEventHandler, SIGNAL(windowGroupActivated(QByteArray)), screen, SLOT(activateWindowGroup(QByteArray)));
442 QObject::connect(m_navigatorEventHandler, SIGNAL(windowGroupDeactivated(QByteArray)), screen, SLOT(deactivateWindowGroup(QByteArray)));
446 void QQnxIntegration::destroyDisplays()
448 qIntegrationDebug() << Q_FUNC_INFO;
449 qDeleteAll(m_screens);
453 QQnxScreen *QQnxIntegration::primaryDisplay() const
455 return m_screens.first();