1 /***************************************************************************
2 **
3 ** Copyright (C) 2013 BlackBerry Limited. All rights reserved.
4 ** Contact: https://www.qt.io/licensing/
5 **
6 ** This file is part of the plugins of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see https://www.qt.io/terms-conditions. For further
15 ** information use the contact form at https://www.qt.io/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 3 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL3 included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 3 requirements
23 ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24 **
25 ** GNU General Public License Usage
26 ** Alternatively, this file may be used under the terms of the GNU
27 ** General Public License version 2.0 or (at your option) the GNU General
28 ** Public license version 3 or any later version approved by the KDE Free
29 ** Qt Foundation. The licenses are as published by the Free Software
30 ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31 ** included in the packaging of this file. Please review the following
32 ** information to ensure the GNU General Public License requirements will
33 ** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34 ** https://www.gnu.org/licenses/gpl-3.0.html.
35 **
36 ** $QT_END_LICENSE$
37 **
38 ****************************************************************************/
39
40 #include "qqnxglobal.h"
41
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"
53
54 #include "qqnxforeignwindow.h"
55 #include "qqnxrasterwindow.h"
56 #if !defined(QT_NO_OPENGL)
57 #include "qqnxeglwindow.h"
58 #endif
59
60 #if QT_CONFIG(qqnx_pps)
61 #include "qqnxnavigatorpps.h"
62 #include "qqnxnavigatoreventnotifier.h"
63 #include "qqnxvirtualkeyboardpps.h"
64 #endif
65
66 #if QT_CONFIG(qqnx_pps)
67 # include "qqnxbuttoneventnotifier.h"
68 # include "qqnxclipboard.h"
69 # if QT_CONFIG(qqnx_imf)
70 # include "qqnxinputcontext_imf.h"
71 # else
72 # include "qqnxinputcontext_noimf.h"
73 # endif
74 #endif
75
76 #include <qpa/qplatforminputcontextfactory_p.h>
77 #include <qpa/qplatforminputcontext.h>
78
79 #include "private/qgenericunixfontdatabase_p.h"
80 #include "private/qgenericunixeventdispatcher_p.h"
81
82 #include <qpa/qplatformwindow.h>
83 #include <qpa/qwindowsysteminterface.h>
84
85 #include <QtGui/private/qguiapplication_p.h>
86
87 #if !defined(QT_NO_OPENGL)
88 #include "qqnxglcontext.h"
89 #include <QtGui/QOpenGLContext>
90 #endif
91
92 #include <private/qsimpledrag_p.h>
93
94 #include <QtCore/QDebug>
95 #include <QtCore/QJsonDocument>
96 #include <QtCore/QJsonObject>
97 #include <QtCore/QJsonArray>
98 #include <QtCore/QFile>
99 #include <errno.h>
100
101 #if defined(QQNXINTEGRATION_DEBUG)
102 #define qIntegrationDebug qDebug
103 #else
104 #define qIntegrationDebug QT_NO_QDEBUG_MACRO
105 #endif
106
107 QT_BEGIN_NAMESPACE
108
109 QQnxIntegration *QQnxIntegration::ms_instance;
110
parseOptions(const QStringList & paramList)111 static inline QQnxIntegration::Options parseOptions(const QStringList ¶mList)
112 {
113 QQnxIntegration::Options options = QQnxIntegration::NoOptions;
114 if (!paramList.contains(QLatin1String("no-fullscreen"))) {
115 options |= QQnxIntegration::FullScreenApplication;
116 }
117
118 if (paramList.contains(QLatin1String("flush-screen-context"))) {
119 options |= QQnxIntegration::AlwaysFlushScreenContext;
120 }
121
122 if (paramList.contains(QLatin1String("rootwindow"))) {
123 options |= QQnxIntegration::RootWindow;
124 }
125
126 if (!paramList.contains(QLatin1String("disable-EGL_KHR_surfaceless_context"))) {
127 options |= QQnxIntegration::SurfacelessEGLContext;
128 }
129
130 return options;
131 }
132
getContextCapabilities(const QStringList & paramList)133 static inline int getContextCapabilities(const QStringList ¶mList)
134 {
135 QString contextCapabilitiesPrefix = QStringLiteral("screen-context-capabilities=");
136 int contextCapabilities = SCREEN_APPLICATION_CONTEXT;
137 for (const QString ¶m : paramList) {
138 if (param.startsWith(contextCapabilitiesPrefix)) {
139 QStringRef value = param.midRef(contextCapabilitiesPrefix.length());
140 bool ok = false;
141 contextCapabilities = value.toInt(&ok, 0);
142 if (!ok)
143 contextCapabilities = SCREEN_APPLICATION_CONTEXT;
144 }
145 }
146 return contextCapabilities;
147 }
148
QQnxIntegration(const QStringList & paramList)149 QQnxIntegration::QQnxIntegration(const QStringList ¶mList)
150 : QPlatformIntegration()
151 , m_screenContextId(256, 0)
152 , m_screenEventThread(0)
153 , m_navigatorEventHandler(new QQnxNavigatorEventHandler())
154 , m_virtualKeyboard(0)
155 #if QT_CONFIG(qqnx_pps)
156 , m_navigatorEventNotifier(0)
157 , m_inputContext(0)
158 , m_buttonsNotifier(new QQnxButtonEventNotifier())
159 #endif
160 , m_qpaInputContext(0)
161 , m_services(0)
162 , m_fontDatabase(new QGenericUnixFontDatabase())
163 , m_eventDispatcher(createUnixEventDispatcher())
164 , m_nativeInterface(new QQnxNativeInterface(this))
165 , m_screenEventHandler(new QQnxScreenEventHandler(this))
166 #if !defined(QT_NO_CLIPBOARD)
167 , m_clipboard(0)
168 #endif
169 , m_navigator(0)
170 #if QT_CONFIG(draganddrop)
171 , m_drag(new QSimpleDrag())
172 #endif
173 #if QT_CONFIG(opengl)
174 , m_eglDisplay(EGL_NO_DISPLAY)
175 #endif
176 {
177 ms_instance = this;
178 m_options = parseOptions(paramList);
179 qIntegrationDebug();
180
181 // Open connection to QNX composition manager
182 if (screen_create_context(&m_screenContext, getContextCapabilities(paramList))) {
183 qFatal("%s - Screen: Failed to create screen context - Error: %s (%i)",
184 Q_FUNC_INFO, strerror(errno), errno);
185 }
186 screen_get_context_property_cv(m_screenContext,
187 SCREEN_PROPERTY_ID,
188 m_screenContextId.size(),
189 m_screenContextId.data());
190 m_screenContextId.resize(strlen(m_screenContextId.constData()));
191
192 #if QT_CONFIG(qqnx_pps)
193 // Create/start navigator event notifier
194 m_navigatorEventNotifier = new QQnxNavigatorEventNotifier(m_navigatorEventHandler);
195
196 // delay invocation of start() to the time the event loop is up and running
197 // needed to have the QThread internals of the main thread properly initialized
198 QMetaObject::invokeMethod(m_navigatorEventNotifier, "start", Qt::QueuedConnection);
199 #endif
200
201 #if QT_CONFIG(opengl)
202 createEglDisplay();
203 #endif
204
205 // Create/start event thread
206 m_screenEventThread = new QQnxScreenEventThread(m_screenContext);
207 m_screenEventHandler->setScreenEventThread(m_screenEventThread);
208 m_screenEventThread->start();
209
210 m_qpaInputContext = QPlatformInputContextFactory::create();
211
212 #if QT_CONFIG(qqnx_pps)
213 if (!m_qpaInputContext) {
214 // Create/start the keyboard class.
215 m_virtualKeyboard = new QQnxVirtualKeyboardPps();
216
217 // delay invocation of start() to the time the event loop is up and running
218 // needed to have the QThread internals of the main thread properly initialized
219 QMetaObject::invokeMethod(m_virtualKeyboard, "start", Qt::QueuedConnection);
220 }
221 #endif
222
223 #if QT_CONFIG(qqnx_pps)
224 m_navigator = new QQnxNavigatorPps();
225 #endif
226
227 // Create services handling class
228 if (m_navigator)
229 m_services = new QQnxServices(m_navigator);
230
231 createDisplays();
232
233 if (m_virtualKeyboard) {
234 // TODO check if we need to do this for all screens or only the primary one
235 QObject::connect(m_virtualKeyboard, SIGNAL(heightChanged(int)),
236 primaryDisplay(), SLOT(keyboardHeightChanged(int)));
237
238 #if QT_CONFIG(qqnx_pps)
239 // Set up the input context
240 m_inputContext = new QQnxInputContext(this, *m_virtualKeyboard);
241 #if QT_CONFIG(qqnx_imf)
242 m_screenEventHandler->addScreenEventFilter(m_inputContext);
243 #endif
244 #endif
245 }
246
247 #if QT_CONFIG(qqnx_pps)
248 // delay invocation of start() to the time the event loop is up and running
249 // needed to have the QThread internals of the main thread properly initialized
250 QMetaObject::invokeMethod(m_buttonsNotifier, "start", Qt::QueuedConnection);
251 #endif
252 }
253
~QQnxIntegration()254 QQnxIntegration::~QQnxIntegration()
255 {
256 qIntegrationDebug("platform plugin shutdown begin");
257 delete m_nativeInterface;
258
259 #if QT_CONFIG(draganddrop)
260 // Destroy the drag object
261 delete m_drag;
262 #endif
263
264 #if !defined(QT_NO_CLIPBOARD)
265 // Delete the clipboard
266 delete m_clipboard;
267 #endif
268
269 // Stop/destroy navigator event notifier
270 #if QT_CONFIG(qqnx_pps)
271 delete m_navigatorEventNotifier;
272 #endif
273 delete m_navigatorEventHandler;
274
275 // Stop/destroy screen event thread
276 delete m_screenEventThread;
277
278 // In case the event-dispatcher was never transferred to QCoreApplication
279 delete m_eventDispatcher;
280
281 delete m_screenEventHandler;
282
283 // Destroy all displays
284 destroyDisplays();
285
286 // Close connection to QNX composition manager
287 screen_destroy_context(m_screenContext);
288
289 #if QT_CONFIG(opengl)
290 destroyEglDisplay();
291 #endif
292
293 #if QT_CONFIG(qqnx_pps)
294 // Destroy the hardware button notifier
295 delete m_buttonsNotifier;
296
297 // Destroy input context
298 delete m_inputContext;
299 #endif
300 delete m_qpaInputContext;
301
302 // Destroy the keyboard class.
303 delete m_virtualKeyboard;
304
305 // Destroy services class
306 delete m_services;
307
308 // Destroy navigator interface
309 delete m_navigator;
310
311 ms_instance = nullptr;
312
313 qIntegrationDebug("platform plugin shutdown end");
314 }
315
hasCapability(QPlatformIntegration::Capability cap) const316 bool QQnxIntegration::hasCapability(QPlatformIntegration::Capability cap) const
317 {
318 qIntegrationDebug();
319 switch (cap) {
320 case MultipleWindows:
321 case ForeignWindows:
322 case ThreadedPixmaps:
323 return true;
324 #if !defined(QT_NO_OPENGL)
325 case OpenGL:
326 case ThreadedOpenGL:
327 case BufferQueueingOpenGL:
328 return true;
329 #endif
330 default:
331 return QPlatformIntegration::hasCapability(cap);
332 }
333 }
334
createForeignWindow(QWindow * window,WId nativeHandle) const335 QPlatformWindow *QQnxIntegration::createForeignWindow(QWindow *window, WId nativeHandle) const
336 {
337 screen_window_t screenWindow = reinterpret_cast<screen_window_t>(nativeHandle);
338 if (this->window(screenWindow)) {
339 qWarning() << "QWindow already created for foreign window"
340 << screenWindow;
341 return nullptr;
342 }
343
344 return new QQnxForeignWindow(window, m_screenContext, screenWindow);
345 }
346
createPlatformWindow(QWindow * window) const347 QPlatformWindow *QQnxIntegration::createPlatformWindow(QWindow *window) const
348 {
349 qIntegrationDebug();
350 QSurface::SurfaceType surfaceType = window->surfaceType();
351 const bool needRootWindow = options() & RootWindow;
352 switch (surfaceType) {
353 case QSurface::RasterSurface:
354 return new QQnxRasterWindow(window, m_screenContext, needRootWindow);
355 #if !defined(QT_NO_OPENGL)
356 case QSurface::OpenGLSurface:
357 return new QQnxEglWindow(window, m_screenContext, needRootWindow);
358 #endif
359 default:
360 qFatal("QQnxWindow: unsupported window API");
361 }
362 return 0;
363 }
364
createPlatformBackingStore(QWindow * window) const365 QPlatformBackingStore *QQnxIntegration::createPlatformBackingStore(QWindow *window) const
366 {
367 qIntegrationDebug();
368 return new QQnxRasterBackingStore(window);
369 }
370
371 #if !defined(QT_NO_OPENGL)
createPlatformOpenGLContext(QOpenGLContext * context) const372 QPlatformOpenGLContext *QQnxIntegration::createPlatformOpenGLContext(QOpenGLContext *context) const
373 {
374 qIntegrationDebug();
375
376 // Get color channel sizes from window format
377 QSurfaceFormat format = context->format();
378 int alphaSize = format.alphaBufferSize();
379 int redSize = format.redBufferSize();
380 int greenSize = format.greenBufferSize();
381 int blueSize = format.blueBufferSize();
382
383 // Check if all channels are don't care
384 if (alphaSize == -1 && redSize == -1 && greenSize == -1 && blueSize == -1) {
385 // Set color channels based on depth of window's screen
386 QQnxScreen *screen = static_cast<QQnxScreen*>(context->screen()->handle());
387 int depth = screen->depth();
388 if (depth == 32) {
389 // SCREEN_FORMAT_RGBA8888
390 alphaSize = 8;
391 redSize = 8;
392 greenSize = 8;
393 blueSize = 8;
394 } else {
395 // SCREEN_FORMAT_RGB565
396 alphaSize = 0;
397 redSize = 5;
398 greenSize = 6;
399 blueSize = 5;
400 }
401 } else {
402 // Choose best match based on supported pixel formats
403 if (alphaSize <= 0 && redSize <= 5 && greenSize <= 6 && blueSize <= 5) {
404 // SCREEN_FORMAT_RGB565
405 alphaSize = 0;
406 redSize = 5;
407 greenSize = 6;
408 blueSize = 5;
409 } else {
410 // SCREEN_FORMAT_RGBA8888
411 alphaSize = 8;
412 redSize = 8;
413 greenSize = 8;
414 blueSize = 8;
415 }
416 }
417
418 // Update color channel sizes in window format
419 format.setAlphaBufferSize(alphaSize);
420 format.setRedBufferSize(redSize);
421 format.setGreenBufferSize(greenSize);
422 format.setBlueBufferSize(blueSize);
423 context->setFormat(format);
424
425 QQnxGLContext *ctx = new QQnxGLContext(context->format(), context->shareHandle());
426 return ctx;
427 }
428 #endif
429
inputContext() const430 QPlatformInputContext *QQnxIntegration::inputContext() const
431 {
432 qIntegrationDebug();
433 if (m_qpaInputContext)
434 return m_qpaInputContext;
435 return m_inputContext;
436 }
437
moveToScreen(QWindow * window,int screen)438 void QQnxIntegration::moveToScreen(QWindow *window, int screen)
439 {
440 qIntegrationDebug() << "w =" << window << ", s =" << screen;
441
442 // get platform window used by widget
443 QQnxWindow *platformWindow = static_cast<QQnxWindow *>(window->handle());
444
445 // lookup platform screen by index
446 QQnxScreen *platformScreen = m_screens.at(screen);
447
448 // move the platform window to the platform screen
449 platformWindow->setScreen(platformScreen);
450 }
451
createEventDispatcher() const452 QAbstractEventDispatcher *QQnxIntegration::createEventDispatcher() const
453 {
454 qIntegrationDebug();
455
456 // We transfer ownersip of the event-dispatcher to QtCoreApplication
457 QAbstractEventDispatcher *eventDispatcher = m_eventDispatcher;
458 m_eventDispatcher = 0;
459
460 return eventDispatcher;
461 }
462
nativeInterface() const463 QPlatformNativeInterface *QQnxIntegration::nativeInterface() const
464 {
465 return m_nativeInterface;
466 }
467
468 #if !defined(QT_NO_CLIPBOARD)
clipboard() const469 QPlatformClipboard *QQnxIntegration::clipboard() const
470 {
471 qIntegrationDebug();
472
473 #if QT_CONFIG(qqnx_pps)
474 if (!m_clipboard)
475 m_clipboard = new QQnxClipboard;
476 #endif
477 return m_clipboard;
478 }
479 #endif
480
481 #if QT_CONFIG(draganddrop)
drag() const482 QPlatformDrag *QQnxIntegration::drag() const
483 {
484 return m_drag;
485 }
486 #endif
487
styleHint(QPlatformIntegration::StyleHint hint) const488 QVariant QQnxIntegration::styleHint(QPlatformIntegration::StyleHint hint) const
489 {
490 qIntegrationDebug();
491 if ((hint == ShowIsFullScreen) && (m_options & FullScreenApplication))
492 return true;
493
494 return QPlatformIntegration::styleHint(hint);
495 }
496
services() const497 QPlatformServices * QQnxIntegration::services() const
498 {
499 return m_services;
500 }
501
window(screen_window_t qnxWindow) const502 QWindow *QQnxIntegration::window(screen_window_t qnxWindow) const
503 {
504 qIntegrationDebug();
505 QMutexLocker locker(&m_windowMapperMutex);
506 Q_UNUSED(locker);
507 return m_windowMapper.value(qnxWindow, 0);
508 }
509
addWindow(screen_window_t qnxWindow,QWindow * window)510 void QQnxIntegration::addWindow(screen_window_t qnxWindow, QWindow *window)
511 {
512 qIntegrationDebug();
513 QMutexLocker locker(&m_windowMapperMutex);
514 Q_UNUSED(locker);
515 m_windowMapper.insert(qnxWindow, window);
516 }
517
removeWindow(screen_window_t qnxWindow)518 void QQnxIntegration::removeWindow(screen_window_t qnxWindow)
519 {
520 qIntegrationDebug();
521 QMutexLocker locker(&m_windowMapperMutex);
522 Q_UNUSED(locker);
523 m_windowMapper.remove(qnxWindow);
524 }
525
526 /*!
527 Get display ID for given \a display
528
529 Returns -1 for failure, otherwise returns display ID
530 */
getIdOfDisplay(screen_display_t display)531 static int getIdOfDisplay(screen_display_t display)
532 {
533 int displayId;
534 if (screen_get_display_property_iv(display,
535 SCREEN_PROPERTY_ID,
536 &displayId) == 0) {
537 return displayId;
538 }
539 return -1;
540 }
541
542 /*!
543 Read JSON configuration file for the QNX display order
544
545 Returns true if file was read successfully and fills \a requestedDisplays
546 */
getRequestedDisplays(QJsonArray & requestedDisplays)547 static bool getRequestedDisplays(QJsonArray &requestedDisplays)
548 {
549 // Check if display configuration file is provided
550 QByteArray json = qgetenv("QT_QPA_QNX_DISPLAY_CONFIG");
551 if (json.isEmpty())
552 return false;
553
554 // Check if configuration file exists
555 QFile file(QString::fromUtf8(json));
556 if (!file.open(QFile::ReadOnly)) {
557 qWarning() << "Could not open config file" << json << "for reading";
558 return false;
559 }
560
561 // Read config file and check it's json
562 const QJsonDocument doc = QJsonDocument::fromJson(file.readAll());
563 if (!doc.isObject()) {
564 qWarning() << "Invalid config file" << json
565 << "- no top-level JSON object";
566 return false;
567 }
568
569 // Read the requested display order
570 const QJsonObject object = doc.object();
571 requestedDisplays = object.value(QLatin1String("displayOrder")).toArray();
572
573 return true;
574 }
575
576 /*!
577 Match \a availableDisplays with display order defined in a json file
578 pointed to by QT_QPA_QNX_DISPLAY_CONFIG. Display order must use same
579 identifiers as defined for displays in graphics.conf. Number of
580 available displays must be specified in \a displayCount
581
582 An example configuration is below:
583 \badcode
584 {
585 "displayOrder": [ 3, 1 ]
586 }
587 \endcode
588
589 Returns ordered list of displays. If no order was specified, returns
590 displays in the same order as in the original list.
591 */
sortDisplays(screen_display_t * availableDisplays,int displayCount)592 QList<screen_display_t *> QQnxIntegration::sortDisplays(screen_display_t *availableDisplays, int displayCount)
593 {
594 // Intermediate list for sorting
595 QList<screen_display_t *> allDisplays;
596 for (int i = 0; i < displayCount; i++)
597 allDisplays.append(&availableDisplays[i]);
598
599 // Read requested display order if available
600 QJsonArray requestedDisplays;
601 if (!getRequestedDisplays(requestedDisplays))
602 return allDisplays;
603
604 // Go through all the requested displays IDs
605 QList<screen_display_t *> orderedDisplays;
606 for (const QJsonValue &value : qAsConst(requestedDisplays)) {
607 int requestedValue = value.toInt();
608
609 // Move all displays with matching ID from the intermediate list
610 // to the beginning of the ordered list
611 for (auto it = allDisplays.begin(), end = allDisplays.end(); it != end; ++it) {
612 screen_display_t *display = *it;
613 if (getIdOfDisplay(*display) == requestedValue) {
614 orderedDisplays.append(display);
615 allDisplays.erase(it);
616 break;
617 }
618 }
619 }
620
621 // Place all unordered displays to the end of list
622 orderedDisplays.append(allDisplays);
623
624 return orderedDisplays;
625 }
626
createDisplays()627 void QQnxIntegration::createDisplays()
628 {
629 qIntegrationDebug();
630 // Query number of displays
631 int displayCount = 0;
632 int result = screen_get_context_property_iv(m_screenContext, SCREEN_PROPERTY_DISPLAY_COUNT,
633 &displayCount);
634 Q_SCREEN_CRITICALERROR(result, "Failed to query display count");
635
636 if (Q_UNLIKELY(displayCount < 1)) {
637 // Never happens, even if there's no display, libscreen returns 1
638 qFatal("QQnxIntegration: displayCount=%d", displayCount);
639 }
640
641 // Get all displays
642 screen_display_t *displays = (screen_display_t *)alloca(sizeof(screen_display_t) * displayCount);
643 result = screen_get_context_property_pv(m_screenContext, SCREEN_PROPERTY_DISPLAYS,
644 (void **)displays);
645 QList<screen_display_t *> orderedDisplays = sortDisplays(displays, displayCount);
646 Q_SCREEN_CRITICALERROR(result, "Failed to query displays");
647
648 // If it's primary, we create a QScreen for it even if it's not attached
649 // since Qt will dereference QGuiApplication::primaryScreen()
650 createDisplay(*orderedDisplays[0], /*isPrimary=*/true);
651
652 for (int i=1; i<displayCount; i++) {
653 int isAttached = 1;
654 result = screen_get_display_property_iv(*orderedDisplays[i], SCREEN_PROPERTY_ATTACHED,
655 &isAttached);
656 Q_SCREEN_CHECKERROR(result, "Failed to query display attachment");
657
658 if (!isAttached) {
659 qIntegrationDebug("Skipping non-attached display %d", i);
660 continue;
661 }
662
663 qIntegrationDebug("Creating screen for display %d", i);
664 createDisplay(*orderedDisplays[i], /*isPrimary=*/false);
665 } // of displays iteration
666 }
667
createDisplay(screen_display_t display,bool isPrimary)668 void QQnxIntegration::createDisplay(screen_display_t display, bool isPrimary)
669 {
670 QQnxScreen *screen = new QQnxScreen(m_screenContext, display, isPrimary);
671 m_screens.append(screen);
672 QWindowSystemInterface::handleScreenAdded(screen);
673 screen->adjustOrientation();
674
675 QObject::connect(m_screenEventHandler, SIGNAL(newWindowCreated(void*)),
676 screen, SLOT(newWindowCreated(void*)));
677 QObject::connect(m_screenEventHandler, SIGNAL(windowClosed(void*)),
678 screen, SLOT(windowClosed(void*)));
679
680 QObject::connect(m_navigatorEventHandler, SIGNAL(rotationChanged(int)), screen, SLOT(setRotation(int)));
681 QObject::connect(m_navigatorEventHandler, SIGNAL(windowGroupActivated(QByteArray)), screen, SLOT(activateWindowGroup(QByteArray)));
682 QObject::connect(m_navigatorEventHandler, SIGNAL(windowGroupDeactivated(QByteArray)), screen, SLOT(deactivateWindowGroup(QByteArray)));
683 QObject::connect(m_navigatorEventHandler, SIGNAL(windowGroupStateChanged(QByteArray,Qt::WindowState)),
684 screen, SLOT(windowGroupStateChanged(QByteArray,Qt::WindowState)));
685 }
686
removeDisplay(QQnxScreen * screen)687 void QQnxIntegration::removeDisplay(QQnxScreen *screen)
688 {
689 Q_CHECK_PTR(screen);
690 Q_ASSERT(m_screens.contains(screen));
691 m_screens.removeAll(screen);
692 QWindowSystemInterface::handleScreenRemoved(screen);
693 }
694
destroyDisplays()695 void QQnxIntegration::destroyDisplays()
696 {
697 qIntegrationDebug();
698 Q_FOREACH (QQnxScreen *screen, m_screens) {
699 QWindowSystemInterface::handleScreenRemoved(screen);
700 }
701 m_screens.clear();
702 }
703
screenForNative(screen_display_t qnxScreen) const704 QQnxScreen *QQnxIntegration::screenForNative(screen_display_t qnxScreen) const
705 {
706 Q_FOREACH (QQnxScreen *screen, m_screens) {
707 if (screen->nativeDisplay() == qnxScreen)
708 return screen;
709 }
710
711 return 0;
712 }
713
primaryDisplay() const714 QQnxScreen *QQnxIntegration::primaryDisplay() const
715 {
716 return m_screens.first();
717 }
718
options() const719 QQnxIntegration::Options QQnxIntegration::options() const
720 {
721 return m_options;
722 }
723
screenContext()724 screen_context_t QQnxIntegration::screenContext()
725 {
726 return m_screenContext;
727 }
728
screenContextId()729 QByteArray QQnxIntegration::screenContextId()
730 {
731 return m_screenContextId;
732 }
733
navigatorEventHandler()734 QQnxNavigatorEventHandler *QQnxIntegration::navigatorEventHandler()
735 {
736 return m_navigatorEventHandler;
737 }
738
supportsNavigatorEvents() const739 bool QQnxIntegration::supportsNavigatorEvents() const
740 {
741 // If QQNX_PPS is defined then we have navigator
742 return m_navigator != 0;
743 }
744
745 #if QT_CONFIG(opengl)
createEglDisplay()746 void QQnxIntegration::createEglDisplay()
747 {
748 qIntegrationDebug();
749
750 // Initialize connection to EGL
751 m_eglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
752 if (Q_UNLIKELY(m_eglDisplay == EGL_NO_DISPLAY))
753 qFatal("QQnxiIntegration: failed to obtain EGL display: %x", eglGetError());
754
755 EGLBoolean eglResult = eglInitialize(m_eglDisplay, 0, 0);
756 if (Q_UNLIKELY(eglResult != EGL_TRUE))
757 qFatal("QQnxIntegration: failed to initialize EGL display, err=%d", eglGetError());
758 }
759
destroyEglDisplay()760 void QQnxIntegration::destroyEglDisplay()
761 {
762 qIntegrationDebug();
763
764 // Close connection to EGL
765 eglTerminate(m_eglDisplay);
766 }
767 #endif
768
769 QT_END_NAMESPACE
770