From b45c1e1c0e3dd838543c1e8d4725d9436367a16a Mon Sep 17 00:00:00 2001 From: Sami Nurmenniemi Date: Wed, 12 Dec 2018 13:45:16 +0200 Subject: Add possibility to configure QNX display order MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add environmental variable QT_QPA_QNX_DISPLAY_CONFIG for pointing to a file containing display order. Configuration file format is: { "displayOrder": [ 3, 1 ] } Task-number: QTBUG-66394 Change-Id: I8c20eb2b5cf35617d5a030213f5d4d68e62ace85 Reviewed-by: Kari Oikarinen Reviewed-by: Pasi Petäjäjärvi --- src/plugins/platforms/qnx/qqnxintegration.cpp | 114 +++++++++++++++++++++++++- src/plugins/platforms/qnx/qqnxintegration.h | 2 + 2 files changed, 112 insertions(+), 4 deletions(-) (limited to 'src/plugins') diff --git a/src/plugins/platforms/qnx/qqnxintegration.cpp b/src/plugins/platforms/qnx/qqnxintegration.cpp index 8c8521325c..db79780407 100644 --- a/src/plugins/platforms/qnx/qqnxintegration.cpp +++ b/src/plugins/platforms/qnx/qqnxintegration.cpp @@ -88,7 +88,10 @@ #include #include - +#include +#include +#include +#include #include #if defined(QQNXINTEGRATION_DEBUG) @@ -490,6 +493,108 @@ void QQnxIntegration::removeWindow(screen_window_t qnxWindow) m_windowMapper.remove(qnxWindow); } +/*! + Get display ID for given \a display + + Returns -1 for failure, otherwise returns display ID + */ +static int getIdOfDisplay(screen_display_t display) +{ + int displayId; + if (screen_get_display_property_iv(display, + SCREEN_PROPERTY_ID, + &displayId) == 0) { + return displayId; + } + return -1; +} + +/*! + Read JSON configuration file for the QNX display order + + Returns true if file was read successfully and fills \a requestedDisplays + */ +static bool getRequestedDisplays(QJsonArray &requestedDisplays) +{ + // Check if display configuration file is provided + QByteArray json = qgetenv("QT_QPA_QNX_DISPLAY_CONFIG"); + if (json.isEmpty()) + return false; + + // Check if configuration file exists + QFile file(QString::fromUtf8(json)); + if (!file.open(QFile::ReadOnly)) { + qWarning() << "Could not open config file" << json << "for reading"; + return false; + } + + // Read config file and check it's json + const QJsonDocument doc = QJsonDocument::fromJson(file.readAll()); + if (!doc.isObject()) { + qWarning() << "Invalid config file" << json + << "- no top-level JSON object"; + return false; + } + + // Read the requested display order + const QJsonObject object = doc.object(); + requestedDisplays = object.value(QLatin1String("displayOrder")).toArray(); + + return true; +} + +/*! + Match \a availableDisplays with display order defined in a json file + pointed to by QT_QPA_QNX_DISPLAY_CONFIG. Display order must use same + identifiers as defined for displays in graphics.conf. Number of + available displays must be specified in \a displayCount + + An example configuration is below: + \badcode + { + "displayOrder": [ 3, 1 ] + } + \endcode + + Returns ordered list of displays. If no order was specified, returns + displays in the same order as in the original list. +*/ +QList QQnxIntegration::sortDisplays(screen_display_t *availableDisplays, int displayCount) +{ + // Intermediate list for sorting + QList allDisplays; + for (int i = 0; i < displayCount; i++) + allDisplays.append(&availableDisplays[i]); + + // Read requested display order if available + QJsonArray requestedDisplays; + if (!getRequestedDisplays(requestedDisplays)) + return allDisplays; + + // Go through all the requested displays IDs + QList orderedDisplays; + for (const QJsonValue &value : qAsConst(requestedDisplays)) { + int requestedValue = value.toInt(); + + // Move all displays with matching ID from the intermediate list + // to the beginning of the ordered list + QMutableListIterator iter(allDisplays); + while (iter.hasNext()) { + screen_display_t *display = iter.next(); + if (getIdOfDisplay(*display) == requestedValue) { + orderedDisplays.append(display); + iter.remove(); + break; + } + } + } + + // Place all unordered displays to the end of list + orderedDisplays.append(allDisplays); + + return orderedDisplays; +} + void QQnxIntegration::createDisplays() { qIntegrationDebug(); @@ -508,15 +613,16 @@ void QQnxIntegration::createDisplays() screen_display_t *displays = (screen_display_t *)alloca(sizeof(screen_display_t) * displayCount); result = screen_get_context_property_pv(m_screenContext, SCREEN_PROPERTY_DISPLAYS, (void **)displays); + QList orderedDisplays = sortDisplays(displays, displayCount); Q_SCREEN_CRITICALERROR(result, "Failed to query displays"); // If it's primary, we create a QScreen for it even if it's not attached // since Qt will dereference QGuiApplication::primaryScreen() - createDisplay(displays[0], /*isPrimary=*/true); + createDisplay(*orderedDisplays[0], /*isPrimary=*/true); for (int i=1; i sortDisplays(screen_display_t *displays, + int displayCount); screen_context_t m_screenContext; QQnxScreenEventThread *m_screenEventThread; -- cgit v1.2.3