From 12aa50175268064b3da36473ec0196cbdb1bdf7f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Morten=20Johan=20S=C3=B8rvig?= Date: Thu, 14 Sep 2017 15:09:22 +0200 Subject: macOS: Fix OpenGL context sharing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit See code comments for problem and fix description. Task-number: QTBUG-63180 Change-Id: I6c6381f2c77c246bd975f66f9baa0165e32de777 Reviewed-by: Tor Arne Vestbø --- src/plugins/platforms/cocoa/qcocoaglcontext.mm | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) (limited to 'src/plugins') diff --git a/src/plugins/platforms/cocoa/qcocoaglcontext.mm b/src/plugins/platforms/cocoa/qcocoaglcontext.mm index 5ed81a7f1b..be5029b7e0 100644 --- a/src/plugins/platforms/cocoa/qcocoaglcontext.mm +++ b/src/plugins/platforms/cocoa/qcocoaglcontext.mm @@ -152,9 +152,32 @@ QCocoaGLContext::QCocoaGLContext(const QSurfaceFormat &format, QPlatformOpenGLCo QMacAutoReleasePool pool; // For the SG Canvas render thread + m_shareContext = share ? static_cast(share)->nsOpenGLContext() : nil; + + if (m_shareContext) { + // Allow sharing between 3.2 Core and 4.1 Core profile versions in + // cases where NSOpenGLContext creates a 4.1 context where a 3.2 + // context was requested. Due to the semantics of QSurfaceFormat + // this 4.1 version can find its way onto the format for the new + // context, even though it was at no point requested by the user. + GLint shareContextRequestedProfile; + [m_shareContext.pixelFormat getValues:&shareContextRequestedProfile + forAttribute:NSOpenGLPFAOpenGLProfile forVirtualScreen:0]; + auto shareContextActualProfile = share->format().version(); + + if (shareContextRequestedProfile == NSOpenGLProfileVersion3_2Core && + shareContextActualProfile >= qMakePair(4, 1)) { + + // There is a mismatch, downgrade requested format to make the + // NSOpenGLPFAOpenGLProfile attributes match. (NSOpenGLContext will + // fail to create a new context if there is a mismatch). + if (m_format.version() >= qMakePair(4, 1)) + m_format.setVersion(3, 2); + } + } + // create native context for the requested pixel format and share NSOpenGLPixelFormat *pixelFormat = createNSOpenGLPixelFormat(m_format); - m_shareContext = share ? static_cast(share)->nsOpenGLContext() : nil; m_context = [[NSOpenGLContext alloc] initWithFormat:pixelFormat shareContext:m_shareContext]; // retry without sharing on context creation failure. -- cgit v1.2.3 From a0871ad225bc0a7ceed67fa2eb5ed16e475ebd93 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Mon, 27 Nov 2017 11:40:12 +0100 Subject: iOS: Deliver all QWindowSystemInterface events synchronously On iOS we want all delivery of events from the system to be handled synchronously, as that's what the system expects. We don't need to add a delivery template argument to each function in QWindowSystemInterface that we want to delivery synchronously; that's only needed for functions that a platform normally sends asynch, but in some cases want to delivery synchronously. For always delivering events synchronously we just need to change the default delivery method. The only events affected by this are the screen changes, and window state change, which were not synchronous before, but should be. All other events were already synchronous, though either explicit delivery, of a flush. Change-Id: Ib20ca342d1c076be0fbcf018c83735a416769cfe Reviewed-by: Richard Moe Gustavsen --- src/plugins/platforms/ios/qiosapplicationstate.mm | 2 +- src/plugins/platforms/ios/qioseventdispatcher.mm | 2 ++ src/plugins/platforms/ios/qiostextresponder.mm | 1 - src/plugins/platforms/ios/quiview.mm | 14 +++++++------- 4 files changed, 10 insertions(+), 9 deletions(-) (limited to 'src/plugins') diff --git a/src/plugins/platforms/ios/qiosapplicationstate.mm b/src/plugins/platforms/ios/qiosapplicationstate.mm index 13e7e1150f..7c8e1f9927 100644 --- a/src/plugins/platforms/ios/qiosapplicationstate.mm +++ b/src/plugins/platforms/ios/qiosapplicationstate.mm @@ -75,7 +75,7 @@ static void handleApplicationStateChanged(UIApplicationState uiApplicationState) { Qt::ApplicationState state = qtApplicationState(uiApplicationState); qCDebug(lcQpaApplication) << "moved to" << state; - QWindowSystemInterface::handleApplicationStateChanged(state); + QWindowSystemInterface::handleApplicationStateChanged(state); } QT_BEGIN_NAMESPACE diff --git a/src/plugins/platforms/ios/qioseventdispatcher.mm b/src/plugins/platforms/ios/qioseventdispatcher.mm index f49f81912e..429b7d9591 100644 --- a/src/plugins/platforms/ios/qioseventdispatcher.mm +++ b/src/plugins/platforms/ios/qioseventdispatcher.mm @@ -422,6 +422,8 @@ QIOSEventDispatcher::QIOSEventDispatcher(QObject *parent) , m_processEventLevel(0) , m_runLoopExitObserver(this, &QIOSEventDispatcher::handleRunLoopExit, kCFRunLoopExit) { + // We want all delivery of events from the system to be handled synchronously + QWindowSystemInterface::setSynchronousWindowSystemEvents(true); } bool __attribute__((returns_twice)) QIOSEventDispatcher::processEvents(QEventLoop::ProcessEventsFlags flags) diff --git a/src/plugins/platforms/ios/qiostextresponder.mm b/src/plugins/platforms/ios/qiostextresponder.mm index 001985a128..33a0b6a42e 100644 --- a/src/plugins/platforms/ios/qiostextresponder.mm +++ b/src/plugins/platforms/ios/qiostextresponder.mm @@ -377,7 +377,6 @@ QScopedValueRollback rollback(m_inSendEventToFocusObject, true); QWindowSystemInterface::handleKeyEvent(qApp->focusWindow(), QEvent::KeyPress, key, modifiers); QWindowSystemInterface::handleKeyEvent(qApp->focusWindow(), QEvent::KeyRelease, key, modifiers); - QWindowSystemInterface::flushWindowSystemEvents(); } #ifndef QT_NO_SHORTCUT diff --git a/src/plugins/platforms/ios/quiview.mm b/src/plugins/platforms/ios/quiview.mm index bf26feac9f..a405fecee2 100644 --- a/src/plugins/platforms/ios/quiview.mm +++ b/src/plugins/platforms/ios/quiview.mm @@ -166,7 +166,7 @@ QWindow *window = m_qioswindow->window(); qCDebug(lcQpaWindow) << m_qioswindow->window() << "new geometry is" << actualGeometry; - QWindowSystemInterface::handleGeometryChange(window, actualGeometry, previousGeometry); + QWindowSystemInterface::handleGeometryChange(window, actualGeometry, previousGeometry); if (actualGeometry.size() != previousGeometry.size()) { // Trigger expose event on resize @@ -199,7 +199,7 @@ } qCDebug(lcQpaWindow) << m_qioswindow->window() << region << "isExposed" << m_qioswindow->isExposed(); - QWindowSystemInterface::handleExposeEvent(m_qioswindow->window(), region); + QWindowSystemInterface::handleExposeEvent(m_qioswindow->window(), region); } // ------------------------------------------------------------------------- @@ -230,7 +230,7 @@ } if (qGuiApp->focusWindow() != m_qioswindow->window()) - QWindowSystemInterface::handleWindowActivated(m_qioswindow->window()); + QWindowSystemInterface::handleWindowActivated(m_qioswindow->window()); else qImDebug() << m_qioswindow->window() << "already active, not sending window activation"; @@ -268,7 +268,7 @@ UIResponder *newResponder = FirstResponderCandidate::currentCandidate(); if ([self responderShouldTriggerWindowDeactivation:newResponder]) - QWindowSystemInterface::handleWindowActivated(0); + QWindowSystemInterface::handleWindowActivated(0); return YES; } @@ -359,7 +359,7 @@ - (void)sendTouchEventWithTimestamp:(ulong)timeStamp { QIOSIntegration *iosIntegration = QIOSIntegration::instance(); - QWindowSystemInterface::handleTouchEvent(m_qioswindow->window(), timeStamp, iosIntegration->touchDevice(), m_activeTouches.values()); + QWindowSystemInterface::handleTouchEvent(m_qioswindow->window(), timeStamp, iosIntegration->touchDevice(), m_activeTouches.values()); } - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event @@ -438,7 +438,7 @@ NSTimeInterval timestamp = event ? event.timestamp : [[NSProcessInfo processInfo] systemUptime]; QIOSIntegration *iosIntegration = static_cast(QGuiApplicationPrivate::platformIntegration()); - QWindowSystemInterface::handleTouchCancelEvent(m_qioswindow->window(), ulong(timestamp * 1000), iosIntegration->touchDevice()); + QWindowSystemInterface::handleTouchCancelEvent(m_qioswindow->window(), ulong(timestamp * 1000), iosIntegration->touchDevice()); } - (int)mapPressTypeToKey:(UIPress*)press @@ -466,7 +466,7 @@ int key = [self mapPressTypeToKey:press]; if (key == Qt::Key_unknown) continue; - if (QWindowSystemInterface::handleKeyEvent(m_qioswindow->window(), type, key, Qt::NoModifier)) + if (QWindowSystemInterface::handleKeyEvent(m_qioswindow->window(), type, key, Qt::NoModifier)) handled = true; } -- cgit v1.2.3 From 3acf5d61a14b70285625bc5276a842fc86f0c7af Mon Sep 17 00:00:00 2001 From: Joni Poikelin Date: Wed, 6 Sep 2017 14:01:39 +0300 Subject: Fix DB2 plugin building on Linux 64bit Task-number: QTBUG-59358 Change-Id: I2e7d52b31f354868c8c4435d8cabe3525d22ede2 Reviewed-by: Andy Shaw --- src/plugins/sqldrivers/db2/db2.pro | 2 ++ src/plugins/sqldrivers/db2/qsql_db2.cpp | 28 ++++++++++++++-------------- 2 files changed, 16 insertions(+), 14 deletions(-) (limited to 'src/plugins') diff --git a/src/plugins/sqldrivers/db2/db2.pro b/src/plugins/sqldrivers/db2/db2.pro index eef65fac66..b99fe91fe3 100644 --- a/src/plugins/sqldrivers/db2/db2.pro +++ b/src/plugins/sqldrivers/db2/db2.pro @@ -7,5 +7,7 @@ QMAKE_USE += db2 OTHER_FILES += db2.json +equals(QT_ARCH, x86_64): DEFINES += ODBC64 + PLUGIN_CLASS_NAME = QDB2DriverPlugin include(../qsqldriverbase.pri) diff --git a/src/plugins/sqldrivers/db2/qsql_db2.cpp b/src/plugins/sqldrivers/db2/qsql_db2.cpp index 27d0e7001a..839d80466f 100644 --- a/src/plugins/sqldrivers/db2/qsql_db2.cpp +++ b/src/plugins/sqldrivers/db2/qsql_db2.cpp @@ -268,7 +268,7 @@ static QSqlField qMakeFieldInfo(const QDB2ResultPrivate* d, int i) { SQLSMALLINT colNameLen; SQLSMALLINT colType; - SQLUINTEGER colSize; + SQLULEN colSize; SQLSMALLINT colScale; SQLSMALLINT nullable; SQLRETURN r = SQL_ERROR; @@ -304,7 +304,7 @@ static int qGetIntData(SQLHANDLE hStmt, int column, bool& isNull) { SQLINTEGER intbuf; isNull = false; - SQLINTEGER lengthIndicator = 0; + SQLLEN lengthIndicator = 0; SQLRETURN r = SQLGetData(hStmt, column + 1, SQL_C_SLONG, @@ -322,7 +322,7 @@ static double qGetDoubleData(SQLHANDLE hStmt, int column, bool& isNull) { SQLDOUBLE dblbuf; isNull = false; - SQLINTEGER lengthIndicator = 0; + SQLLEN lengthIndicator = 0; SQLRETURN r = SQLGetData(hStmt, column+1, SQL_C_DOUBLE, @@ -341,7 +341,7 @@ static SQLBIGINT qGetBigIntData(SQLHANDLE hStmt, int column, bool& isNull) { SQLBIGINT lngbuf = Q_INT64_C(0); isNull = false; - SQLINTEGER lengthIndicator = 0; + SQLLEN lengthIndicator = 0; SQLRETURN r = SQLGetData(hStmt, column+1, SQL_C_SBIGINT, @@ -358,7 +358,7 @@ static QString qGetStringData(SQLHANDLE hStmt, int column, int colSize, bool& is { QString fieldVal; SQLRETURN r = SQL_ERROR; - SQLINTEGER lengthIndicator = 0; + SQLLEN lengthIndicator = 0; if (colSize <= 0) colSize = 255; @@ -394,12 +394,12 @@ static QString qGetStringData(SQLHANDLE hStmt, int column, int colSize, bool& is return fieldVal; } -static QByteArray qGetBinaryData(SQLHANDLE hStmt, int column, SQLINTEGER& lengthIndicator, bool& isNull) +static QByteArray qGetBinaryData(SQLHANDLE hStmt, int column, SQLLEN& lengthIndicator, bool& isNull) { QByteArray fieldVal; SQLSMALLINT colNameLen; SQLSMALLINT colType; - SQLUINTEGER colSize; + SQLULEN colSize; SQLSMALLINT colScale; SQLSMALLINT nullable; SQLRETURN r = SQL_ERROR; @@ -633,9 +633,9 @@ bool QDB2Result::exec() { Q_D(QDB2Result); QList tmpStorage; // holds temporary ptrs - QVarLengthArray indicators(boundValues().count()); + QVarLengthArray indicators(boundValues().count()); - memset(indicators.data(), 0, indicators.size() * sizeof(SQLINTEGER)); + memset(indicators.data(), 0, indicators.size() * sizeof(SQLLEN)); setActive(false); setAt(QSql::BeforeFirstRow); SQLRETURN r; @@ -651,7 +651,7 @@ bool QDB2Result::exec() int i; for (i = 0; i < values.count(); ++i) { // bind parameters - only positional binding allowed - SQLINTEGER *ind = &indicators[i]; + SQLLEN *ind = &indicators[i]; if (values.at(i).isNull()) *ind = SQL_NULL_DATA; if (bindValueType(i) & QSql::Out) @@ -996,7 +996,7 @@ QVariant QDB2Result::data(int field) return QVariant(); } SQLRETURN r = 0; - SQLINTEGER lengthIndicator = 0; + SQLLEN lengthIndicator = 0; bool isNull = false; const QSqlField info = d->recInf.field(field); @@ -1109,7 +1109,7 @@ bool QDB2Result::isNull(int i) int QDB2Result::numRowsAffected() { Q_D(const QDB2Result); - SQLINTEGER affectedRowCount = 0; + SQLLEN affectedRowCount = 0; SQLRETURN r = SQLRowCount(d->hStmt, &affectedRowCount); if (r == SQL_SUCCESS || r == SQL_SUCCESS_WITH_INFO) return affectedRowCount; @@ -1238,7 +1238,7 @@ bool QDB2Driver::open(const QString& db, const QString& user, const QString& pas const QString opt(tmp.left(idx)); const QString val(tmp.mid(idx + 1).simplified()); - SQLUINTEGER v = 0; + SQLULEN v = 0; r = SQL_SUCCESS; if (opt == QLatin1String("SQL_ATTR_ACCESS_MODE")) { if (val == QLatin1String("SQL_MODE_READ_ONLY")) { @@ -1622,7 +1622,7 @@ bool QDB2Driver::rollbackTransaction() bool QDB2Driver::setAutoCommit(bool autoCommit) { Q_D(QDB2Driver); - SQLUINTEGER ac = autoCommit ? SQL_AUTOCOMMIT_ON : SQL_AUTOCOMMIT_OFF; + SQLULEN ac = autoCommit ? SQL_AUTOCOMMIT_ON : SQL_AUTOCOMMIT_OFF; SQLRETURN r = SQLSetConnectAttr(d->hDbc, SQL_ATTR_AUTOCOMMIT, reinterpret_cast(ac), -- cgit v1.2.3 From 81908abd5e62d3ee3e24c37801892ef500de2fc6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Tue, 28 Nov 2017 19:28:36 +0100 Subject: iOS: Update screen metrics (physical DPI) for the latest set of devices We were missing some recent iPads, and the iPhone 8 Plus and X. Change-Id: Ib65644a277a1cbd75ccb360b79b9ac8af935c741 Reviewed-by: Richard Moe Gustavsen --- src/plugins/platforms/ios/qiosscreen.mm | 32 +++++++++++++++++++------------- 1 file changed, 19 insertions(+), 13 deletions(-) (limited to 'src/plugins') diff --git a/src/plugins/platforms/ios/qiosscreen.mm b/src/plugins/platforms/ios/qiosscreen.mm index 3514bf63bb..deea4d86a0 100644 --- a/src/plugins/platforms/ios/qiosscreen.mm +++ b/src/plugins/platforms/ios/qiosscreen.mm @@ -181,12 +181,12 @@ QT_BEGIN_NAMESPACE /*! Returns the model identifier of the device. - - When running under the simulator, the identifier will not - match the simulated device, but will be x86_64 or i386. */ static QString deviceModelIdentifier() { +#if TARGET_OS_SIMULATOR + return QString::fromLocal8Bit(qgetenv("SIMULATOR_MODEL_IDENTIFIER")); +#else static const char key[] = "hw.machine"; size_t size; @@ -196,6 +196,7 @@ static QString deviceModelIdentifier() sysctlbyname(key, &value, &size, NULL, 0); return QString::fromLatin1(value); +#endif } QIOSScreen::QIOSScreen(UIScreen *screen) @@ -210,19 +211,24 @@ QIOSScreen::QIOSScreen(UIScreen *screen) // Based on https://en.wikipedia.org/wiki/List_of_iOS_devices#Display // iPhone (1st gen), 3G, 3GS, and iPod Touch (1st–3rd gen) are 18-bit devices - if (deviceIdentifier.contains(QRegularExpression("^(iPhone1,[12]|iPhone2,1|iPod[1-3],1)$"))) - m_depth = 18; - else - m_depth = 24; + static QRegularExpression lowBitDepthDevices("^(iPhone1,[12]|iPhone2,1|iPod[1-3],1)$"); + m_depth = deviceIdentifier.contains(lowBitDepthDevices) ? 18 : 24; + + static QRegularExpression iPhoneXModels("^iPhone(10,[36])$"); + static QRegularExpression iPhonePlusModels("^iPhone(7,1|8,2|9,[24]|10,[25])$"); + static QRegularExpression iPadMiniModels("^iPad(2,[567]|4,[4-9]|5,[12])$"); - if (deviceIdentifier.contains(QRegularExpression("^iPhone(7,1|8,2|9,2|9,4)$"))) { - // iPhone Plus models + if (deviceIdentifier.contains(iPhoneXModels)) { + m_physicalDpi = 458; + } else if (deviceIdentifier.contains(iPhonePlusModels)) { m_physicalDpi = 401; - } else if (deviceIdentifier.contains(QRegularExpression("^iPad(1,1|2,[1-4]|3,[1-6]|4,[1-3]|5,[3-4]|6,[7-8])$"))) { - // All iPads except the iPad Mini series - m_physicalDpi = 132 * devicePixelRatio(); + } else if (deviceIdentifier.startsWith("iPad")) { + if (deviceIdentifier.contains(iPadMiniModels)) + m_physicalDpi = 163 * devicePixelRatio(); + else + m_physicalDpi = 132 * devicePixelRatio(); } else { - // All non-Plus iPhones, and iPad Minis + // All normal iPhones, and iPods m_physicalDpi = 163 * devicePixelRatio(); } } else { -- cgit v1.2.3 From 038e473cfac43f80bd8d54bb6c6da5bf6391efa8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Tue, 28 Nov 2017 19:38:31 +0100 Subject: iOS: Don't treat AppleTV as an iDevice when resolving physical DPI Change-Id: I07ac92a7b2d8c65b7d70a4f2ed5f96f8f4d99ef0 Reviewed-by: Richard Moe Gustavsen --- src/plugins/platforms/ios/qiosscreen.mm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/plugins') diff --git a/src/plugins/platforms/ios/qiosscreen.mm b/src/plugins/platforms/ios/qiosscreen.mm index deea4d86a0..74e81dedf4 100644 --- a/src/plugins/platforms/ios/qiosscreen.mm +++ b/src/plugins/platforms/ios/qiosscreen.mm @@ -205,9 +205,9 @@ QIOSScreen::QIOSScreen(UIScreen *screen) , m_uiWindow(0) , m_orientationListener(0) { - if (screen == [UIScreen mainScreen]) { - QString deviceIdentifier = deviceModelIdentifier(); + QString deviceIdentifier = deviceModelIdentifier(); + if (screen == [UIScreen mainScreen] && !deviceIdentifier.startsWith("AppleTV")) { // Based on https://en.wikipedia.org/wiki/List_of_iOS_devices#Display // iPhone (1st gen), 3G, 3GS, and iPod Touch (1st–3rd gen) are 18-bit devices -- cgit v1.2.3 From e195620d7164f40050e0d9454f7dd94f1649dce2 Mon Sep 17 00:00:00 2001 From: Robert Szefner Date: Sat, 25 Nov 2017 19:04:48 +0100 Subject: QPSQL: Remove semicolon after Q_DECLARE_SQLDRIVER_PRIVATE The semicolon is unnecessary and QtCreator warns of it. Change-Id: I20f803d1ea0136080ff4dc4f7d9863fd8028992e Reviewed-by: Andy Shaw --- src/plugins/sqldrivers/psql/qsql_psql.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/plugins') diff --git a/src/plugins/sqldrivers/psql/qsql_psql.cpp b/src/plugins/sqldrivers/psql/qsql_psql.cpp index 8f7d261bdc..6ba32a0c71 100644 --- a/src/plugins/sqldrivers/psql/qsql_psql.cpp +++ b/src/plugins/sqldrivers/psql/qsql_psql.cpp @@ -229,7 +229,7 @@ class QPSQLResultPrivate : public QSqlResultPrivate { Q_DECLARE_PUBLIC(QPSQLResult) public: - Q_DECLARE_SQLDRIVER_PRIVATE(QPSQLDriver); + Q_DECLARE_SQLDRIVER_PRIVATE(QPSQLDriver) QPSQLResultPrivate(QPSQLResult *q, const QPSQLDriver *drv) : QSqlResultPrivate(q, drv), result(0), -- cgit v1.2.3 From 85eef0e5e05e84b1640a1887fe872e3adbc0ac5b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Wed, 29 Nov 2017 16:12:40 +0100 Subject: iOS: Improve logging during application startup Change-Id: I15c1980d7c532c94b34e612bb781c8ed5bf096a0 Reviewed-by: Jake Petroules --- src/plugins/platforms/ios/qioseventdispatcher.mm | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'src/plugins') diff --git a/src/plugins/platforms/ios/qioseventdispatcher.mm b/src/plugins/platforms/ios/qioseventdispatcher.mm index 429b7d9591..7194d5bed1 100644 --- a/src/plugins/platforms/ios/qioseventdispatcher.mm +++ b/src/plugins/platforms/ios/qioseventdispatcher.mm @@ -294,7 +294,7 @@ static bool rootLevelRunLoopIntegration() { [[NSNotificationCenter defaultCenter] addObserver:self - selector:@selector(applicationDidFinishLaunching) + selector:@selector(applicationDidFinishLaunching:) name:UIApplicationDidFinishLaunchingNotification object:nil]; @@ -320,8 +320,10 @@ static bool rootLevelRunLoopIntegration() # error "Unknown processor family" #endif -+ (void)applicationDidFinishLaunching ++ (void)applicationDidFinishLaunching:(NSNotification *)notification { + qCDebug(lcQpaApplication) << "Application launched with options" << notification.userInfo; + if (!isQtApplication()) return; @@ -329,7 +331,7 @@ static bool rootLevelRunLoopIntegration() // We schedule the main-redirection for the next run-loop pass, so that we // can return from this function and let UIApplicationMain finish its job. // This results in running Qt's application eventloop as a nested runloop. - qEventDispatcherDebug() << "Scheduling main() on next run-loop pass"; + qCDebug(lcQpaApplication) << "Scheduling main() on next run-loop pass"; CFRunLoopTimerRef userMainTimer = CFRunLoopTimerCreateWithHandler(kCFAllocatorDefault, CFAbsoluteTimeGetCurrent(), 0, 0, 0, ^(CFRunLoopTimerRef) { user_main_trampoline(); }); CFRunLoopAddTimer(CFRunLoopGetMain(), userMainTimer, kCFRunLoopCommonModes); @@ -339,7 +341,7 @@ static bool rootLevelRunLoopIntegration() switch (setjmp(processEventEnterJumpPoint)) { case kJumpPointSetSuccessfully: - qEventDispatcherDebug() << "Running main() on separate stack"; qIndent(); + qCDebug(lcQpaApplication) << "Running main() on separate stack"; qIndent(); // Redirect the stack pointer to the start of the reserved stack. This ensures // that when we longjmp out of the event dispatcher and continue execution, the @@ -358,7 +360,7 @@ static bool rootLevelRunLoopIntegration() case kJumpedFromEventDispatcherProcessEvents: // We've returned from the longjmp in the event dispatcher, // and the stack has been restored to its old self. - qUnIndent(); qEventDispatcherDebug() << "Returned from processEvents"; + qUnIndent(); qCDebug(lcQpaApplication) << "Returned from processEvents"; if (Q_UNLIKELY(debugStackUsage)) userMainStack.printUsage(); -- cgit v1.2.3 From da50a0b38ceb730ad3c30d600adfe4435a498550 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C5=82a=C5=BCej=20Szczygie=C5=82?= Date: Sun, 27 Aug 2017 16:22:08 +0200 Subject: xcb: Set executed drop action when drop is outside the application Task-number: QTBUG-62815 Change-Id: I13ee1a3a7e9515d827d29ada38bc0d396f4800d7 Reviewed-by: Shawn Rutledge --- src/plugins/platforms/xcb/qxcbdrag.cpp | 11 +++++++++++ src/plugins/platforms/xcb/qxcbdrag.h | 4 ++++ 2 files changed, 15 insertions(+) (limited to 'src/plugins') diff --git a/src/plugins/platforms/xcb/qxcbdrag.cpp b/src/plugins/platforms/xcb/qxcbdrag.cpp index 60d142157f..51d09d8927 100644 --- a/src/plugins/platforms/xcb/qxcbdrag.cpp +++ b/src/plugins/platforms/xcb/qxcbdrag.cpp @@ -170,6 +170,9 @@ void QXcbDrag::init() QXcbCursor::queryPointer(connection(), ¤t_virtual_desktop, 0); drag_types.clear(); + + dropped = false; + canceled = false; } QMimeData *QXcbDrag::platformDropData() @@ -225,6 +228,10 @@ void QXcbDrag::startDrag() void QXcbDrag::endDrag() { QBasicDrag::endDrag(); + if (!dropped && !canceled && canDrop()) { + // Set executed drop action when dropping outside application. + setExecutedDropAction(accepted_drop_action); + } initiatorWindow.clear(); } @@ -1026,6 +1033,8 @@ void QXcbDrag::handleDrop(QPlatformWindow *, const xcb_client_message_event_t *e // reset target_time = XCB_CURRENT_TIME; + + dropped = true; } @@ -1124,6 +1133,8 @@ void QXcbDrag::cancel() // remove canceled object currentDrag()->deleteLater(); + + canceled = true; } // find an ancestor with XdndAware on it diff --git a/src/plugins/platforms/xcb/qxcbdrag.h b/src/plugins/platforms/xcb/qxcbdrag.h index 2d152edf76..9e1ee46593 100644 --- a/src/plugins/platforms/xcb/qxcbdrag.h +++ b/src/plugins/platforms/xcb/qxcbdrag.h @@ -136,6 +136,10 @@ private: QRect source_sameanswer; bool waiting_for_status; + // helpers for setting executed drop action outside application + bool dropped; + bool canceled; + // top-level window we sent position to last. xcb_window_t current_target; // window to send events to (always valid if current_target) -- cgit v1.2.3 From dc4b4e9949e49da31efa1fe0f2a5cbb15656292d Mon Sep 17 00:00:00 2001 From: Timo Aarnipuro Date: Thu, 21 Sep 2017 12:09:05 +0300 Subject: Build integrityhid support only if it is available Change-Id: I6e0aa2f74516d4c0a1905b188f195834d395584b Reviewed-by: Oswald Buddenhagen --- src/plugins/platforms/integrity/integrity.pro | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) (limited to 'src/plugins') diff --git a/src/plugins/platforms/integrity/integrity.pro b/src/plugins/platforms/integrity/integrity.pro index 0fb256793d..54438707eb 100644 --- a/src/plugins/platforms/integrity/integrity.pro +++ b/src/plugins/platforms/integrity/integrity.pro @@ -8,13 +8,18 @@ QT += \ SOURCES = \ main.cpp \ qintegrityfbintegration.cpp \ - qintegrityfbscreen.cpp \ - qintegrityhidmanager.cpp + qintegrityfbscreen.cpp HEADERS = \ qintegrityfbintegration.h \ - qintegrityfbscreen.h \ - qintegrityhidmanager.h + qintegrityfbscreen.h + +qtConfig(integrityhid) { + SOURCES += \ + qintegrityhidmanager.cpp + HEADERS += \ + qintegrityhidmanager.h +} OTHER_FILES += integrity.json -- cgit v1.2.3 From 1a55c929332cacfc7e3934810fa1a4601f39846b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Fri, 24 Nov 2017 17:11:40 +0100 Subject: iOS: Compute screen available geometry based on safe area insets In addition to the (deprecated) applicationFrame property, we base the available geometry on the root view's safe area, which also takes into account system-reserved areas on iPhone X, and the screen's bezel in the case of tvOS. Change-Id: I252d960a0e486dd0c7e30843f88c0bf5684feb24 Reviewed-by: Jake Petroules --- src/plugins/platforms/ios/qiosscreen.mm | 29 ++++++++++++++++++++++++----- src/plugins/platforms/ios/quiview.h | 1 + src/plugins/platforms/ios/quiview.mm | 16 ++++++++++++++++ 3 files changed, 41 insertions(+), 5 deletions(-) (limited to 'src/plugins') diff --git a/src/plugins/platforms/ios/qiosscreen.mm b/src/plugins/platforms/ios/qiosscreen.mm index 74e81dedf4..1a7004c249 100644 --- a/src/plugins/platforms/ios/qiosscreen.mm +++ b/src/plugins/platforms/ios/qiosscreen.mm @@ -175,6 +175,21 @@ static QIOSScreen* qtPlatformScreenFor(UIScreen *uiScreen) @end +@interface UIScreen (Compatibility) +@property (nonatomic, readonly) CGRect qt_applicationFrame; +@end + +@implementation UIScreen (Compatibility) +- (CGRect)qt_applicationFrame +{ +#ifdef Q_OS_IOS + return self.applicationFrame; +#else + return self.bounds; +#endif +} +@end + // ------------------------------------------------------------------------- QT_BEGIN_NAMESPACE @@ -271,11 +286,15 @@ void QIOSScreen::updateProperties() QRect previousAvailableGeometry = m_availableGeometry; m_geometry = QRectF::fromCGRect(m_uiScreen.bounds).toRect(); -#ifdef Q_OS_TVOS - m_availableGeometry = m_geometry; -#else - m_availableGeometry = QRectF::fromCGRect(m_uiScreen.applicationFrame).toRect(); -#endif + + // The application frame doesn't take safe area insets into account, and + // the safe area insets are not available before the UIWindow is shown, + // and do not take split-view constraints into account, so we have to + // combine the two to get the correct available geometry. + QRect applicationFrame = QRectF::fromCGRect(m_uiScreen.qt_applicationFrame).toRect(); + UIEdgeInsets safeAreaInsets = m_uiWindow.qt_safeAreaInsets; + m_availableGeometry = m_geometry.adjusted(safeAreaInsets.left, safeAreaInsets.top, + -safeAreaInsets.right, -safeAreaInsets.bottom).intersected(applicationFrame); #ifndef Q_OS_TVOS if (m_uiScreen == [UIScreen mainScreen]) { diff --git a/src/plugins/platforms/ios/quiview.h b/src/plugins/platforms/ios/quiview.h index 1500f0b41c..1ce9007a35 100644 --- a/src/plugins/platforms/ios/quiview.h +++ b/src/plugins/platforms/ios/quiview.h @@ -77,5 +77,6 @@ QT_END_NAMESPACE - (QWindow *)qwindow; - (UIViewController *)viewController; - (QIOSViewController*)qtViewController; +@property (nonatomic, readonly) UIEdgeInsets qt_safeAreaInsets; @end diff --git a/src/plugins/platforms/ios/quiview.mm b/src/plugins/platforms/ios/quiview.mm index a405fecee2..79f9d6871a 100644 --- a/src/plugins/platforms/ios/quiview.mm +++ b/src/plugins/platforms/ios/quiview.mm @@ -545,6 +545,22 @@ return nil; } +- (UIEdgeInsets)qt_safeAreaInsets +{ +#if QT_DARWIN_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_NA, 110000, 110000, __WATCHOS_NA) + if (__builtin_available(iOS 11, tvOS 11, *)) + return self.safeAreaInsets; +#endif + + // Fallback for iOS < 11 + UIEdgeInsets safeAreaInsets = UIEdgeInsetsZero; + CGPoint topInset = [self convertPoint:CGPointMake(0, self.viewController.topLayoutGuide.length) fromView:nil]; + CGPoint bottomInset = [self convertPoint:CGPointMake(0, self.viewController.bottomLayoutGuide.length) fromView:nil]; + safeAreaInsets.top = topInset.y; + safeAreaInsets.bottom = bottomInset.y; + return safeAreaInsets; +} + @end #ifndef QT_NO_ACCESSIBILITY -- cgit v1.2.3 From 155f954d9941e9eee14d86ee7bc30411aea60dee Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Fri, 24 Nov 2017 08:49:35 +0100 Subject: Fix -Wclazy-connect-not-normalized in Windows code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit qwindowsxpstyle.cpp(289,35): warning: Signature is not normalized. Use void* instead of void * [-Wclazy-connect-not-normalized] qwindowsxpstyle.cpp(292,35): warning: Signature is not normalized. Use void* instead of void * [-Wclazy-connect-not-normalized] Change-Id: I773530452c0837c5066f9174c25ae37e57086e76 Reviewed-by: Sérgio Martins --- src/plugins/styles/windowsvista/qwindowsxpstyle.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/plugins') diff --git a/src/plugins/styles/windowsvista/qwindowsxpstyle.cpp b/src/plugins/styles/windowsvista/qwindowsxpstyle.cpp index 0a47ccf68a..4c982c14f4 100644 --- a/src/plugins/styles/windowsvista/qwindowsxpstyle.cpp +++ b/src/plugins/styles/windowsvista/qwindowsxpstyle.cpp @@ -286,10 +286,10 @@ static inline HWND createTreeViewHelperWindow() void *hwnd = 0; void *wndProc = reinterpret_cast(DefWindowProc); if (QMetaObject::invokeMethod(ni, "createMessageWindow", Qt::DirectConnection, - Q_RETURN_ARG(void *, hwnd), + Q_RETURN_ARG(void*, hwnd), Q_ARG(QString, QStringLiteral("QTreeViewThemeHelperWindowClass")), Q_ARG(QString, QStringLiteral("QTreeViewThemeHelperWindow")), - Q_ARG(void *, wndProc)) && hwnd) { + Q_ARG(void*, wndProc)) && hwnd) { return reinterpret_cast(hwnd); } } -- cgit v1.2.3 From 673762b02e4d112198501e91ab487b04a1ed3a39 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Fri, 24 Nov 2017 09:58:13 +0100 Subject: qwindowsmime.cpp: Fix clazy -Wclazy-container-anti-pattern qwindowsmime.cpp(1267,10): warning: allocating an unneeded temporary container [-Wclazy-container-anti-pattern] qwindowsmime.cpp(1274,14): warning: allocating an unneeded temporary container [-Wclazy-container-anti-pattern] qwindowsmime.cpp(1383,10): warning: allocating an unneeded temporary container [-Wclazy-container-anti-pattern] qwindowsmime.cpp(1429,16): warning: allocating an unneeded temporary container [-Wclazy-container-anti-pattern] qwindowsmime.cpp(1450,20): warning: allocating an unneeded temporary container [-Wclazy-container-anti-pattern] Change-Id: I9188a0478b4be0c5c8f064578bbe027e33b67b89 Reviewed-by: Andre de la Rocha Reviewed-by: Miguel Costa Reviewed-by: Oliver Wolff --- src/plugins/platforms/windows/qwindowsmime.cpp | 46 ++++++++++++-------------- 1 file changed, 21 insertions(+), 25 deletions(-) (limited to 'src/plugins') diff --git a/src/plugins/platforms/windows/qwindowsmime.cpp b/src/plugins/platforms/windows/qwindowsmime.cpp index b892f1610d..34e6041687 100644 --- a/src/plugins/platforms/windows/qwindowsmime.cpp +++ b/src/plugins/platforms/windows/qwindowsmime.cpp @@ -52,6 +52,7 @@ #include #include +#include QT_BEGIN_NAMESPACE @@ -1264,15 +1265,16 @@ bool QBuiltInMimes::convertFromMime(const FORMATETC &formatetc, const QMimeData QVector QBuiltInMimes::formatsForMime(const QString &mimeType, const QMimeData *mimeData) const { QVector formatetcs; - if (!outFormats.keys(mimeType).isEmpty() && mimeData->formats().contains(mimeType)) - formatetcs += setCf(outFormats.key(mimeType)); + const auto mit = std::find(outFormats.cbegin(), outFormats.cend(), mimeType); + if (mit != outFormats.cend() && mimeData->formats().contains(mimeType)) + formatetcs += setCf(mit.key()); return formatetcs; } bool QBuiltInMimes::canConvertToMime(const QString &mimeType, IDataObject *pDataObj) const { - return (!inFormats.keys(mimeType).isEmpty()) - && canGetData(inFormats.key(mimeType), pDataObj); + const auto mit = std::find(inFormats.cbegin(), inFormats.cend(), mimeType); + return mit != inFormats.cend() && canGetData(mit.key(), pDataObj); } QVariant QBuiltInMimes::convertToMime(const QString &mimeType, IDataObject *pDataObj, QVariant::Type preferredType) const @@ -1315,7 +1317,7 @@ public: QString mimeForFormat(const FORMATETC &formatetc) const override; private: - QMap formats; + mutable QMap formats; static QStringList ianaTypes; static QStringList excludeList; }; @@ -1380,15 +1382,13 @@ bool QLastResortMimes::convertFromMime(const FORMATETC &formatetc, const QMimeDa QVector QLastResortMimes::formatsForMime(const QString &mimeType, const QMimeData * /*mimeData*/) const { QVector formatetcs; - if (!formats.keys(mimeType).isEmpty()) { - formatetcs += setCf(formats.key(mimeType)); - } else if (!excludeList.contains(mimeType, Qt::CaseInsensitive)){ - // register any other available formats - int cf = QWindowsMime::registerMimeType(mimeType); - QLastResortMimes *that = const_cast(this); - that->formats.insert(cf, mimeType); - formatetcs += setCf(cf); - } + auto mit = std::find(formats.begin(), formats.end(), mimeType); + // register any other available formats + if (mit == formats.end() && !excludeList.contains(mimeType, Qt::CaseInsensitive)) + mit = formats.insert(QWindowsMime::registerMimeType(mimeType), mimeType); + if (mit != formats.end()) + formatetcs += setCf(mit.key()); + if (!formatetcs.isEmpty()) qCDebug(lcQpaMime) << __FUNCTION__ << mimeType << formatetcs; return formatetcs; @@ -1426,14 +1426,11 @@ bool QLastResortMimes::canConvertToMime(const QString &mimeType, IDataObject *pD QString clipFormat = customMimeType(mimeType); const UINT cf = RegisterClipboardFormat(reinterpret_cast (clipFormat.utf16())); return canGetData(int(cf), pDataObj); - } else if (formats.keys(mimeType).isEmpty()) { - // if it is not in there then register it and see if we can get it - int cf = QWindowsMime::registerMimeType(mimeType); - return canGetData(cf, pDataObj); - } else { - return canGetData(formats.key(mimeType), pDataObj); } - return false; + // if it is not in there then register it and see if we can get it + const auto mit = std::find(formats.cbegin(), formats.cend(), mimeType); + const int cf = mit != formats.cend() ? mit.key() : QWindowsMime::registerMimeType(mimeType); + return canGetData(cf, pDataObj); } QVariant QLastResortMimes::convertToMime(const QString &mimeType, IDataObject *pDataObj, QVariant::Type preferredType) const @@ -1447,11 +1444,10 @@ QVariant QLastResortMimes::convertToMime(const QString &mimeType, IDataObject *p QString clipFormat = customMimeType(mimeType, &lindex); const UINT cf = RegisterClipboardFormat(reinterpret_cast (clipFormat.utf16())); data = getData(int(cf), pDataObj, lindex); - } else if (formats.keys(mimeType).isEmpty()) { - int cf = QWindowsMime::registerMimeType(mimeType); - data = getData(cf, pDataObj); } else { - data = getData(formats.key(mimeType), pDataObj); + const auto mit = std::find(formats.cbegin(), formats.cend(), mimeType); + const int cf = mit != formats.cend() ? mit.key() : QWindowsMime::registerMimeType(mimeType); + data = getData(cf, pDataObj); } if (!data.isEmpty()) val = data; // it should be enough to return the data and let QMimeData do the rest. -- cgit v1.2.3 From f4498db196c19208236e97ddae448e0ec1a4be04 Mon Sep 17 00:00:00 2001 From: Kimmo Ollila Date: Wed, 15 Nov 2017 13:57:22 +0200 Subject: Add configure test for INTEGRITY EGLFS openWFD integration plugin Change-Id: I846f9e555df4f64097b5634707515d45c13a521c Reviewed-by: Laszlo Agocs Reviewed-by: Oswald Buddenhagen --- src/plugins/platforms/eglfs/deviceintegration/deviceintegration.pro | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/plugins') diff --git a/src/plugins/platforms/eglfs/deviceintegration/deviceintegration.pro b/src/plugins/platforms/eglfs/deviceintegration/deviceintegration.pro index 6d759938b5..2cddbe9beb 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/deviceintegration.pro +++ b/src/plugins/platforms/eglfs/deviceintegration/deviceintegration.pro @@ -8,7 +8,7 @@ qtConfig(eglfs_brcm): SUBDIRS += eglfs_brcm qtConfig(eglfs_mali): SUBDIRS += eglfs_mali qtConfig(eglfs_viv): SUBDIRS += eglfs_viv qtConfig(eglfs_viv_wl): SUBDIRS += eglfs_viv_wl - +qtConfig(eglfs_openwfd): SUBDIRS += eglfs_openwfd qtConfig(opengl): SUBDIRS += eglfs_emu eglfs_kms_egldevice.depends = eglfs_kms_support -- cgit v1.2.3 From de250dd22c698ae1eec4927c87314024c3523c70 Mon Sep 17 00:00:00 2001 From: Kimmo Ollila Date: Wed, 15 Nov 2017 13:03:36 +0200 Subject: Add EGLFS integration plugin for Qualcomm msm8996au board Change-Id: I5bed1fd690daa72492e7ec5f24e80198a2592986 Reviewed-by: Janne Koskinen Reviewed-by: Laszlo Agocs --- .../eglfs_openwfd/eglfs_openwfd.json | 3 + .../eglfs_openwfd/eglfs_openwfd.pro | 17 ++ .../eglfs_openwfd/qeglfsopenwfdintegration.cpp | 223 +++++++++++++++++++++ .../eglfs_openwfd/qeglfsopenwfdintegration.h | 69 +++++++ .../eglfs_openwfd/qeglfsopenwfdmain.cpp | 58 ++++++ 5 files changed, 370 insertions(+) create mode 100644 src/plugins/platforms/eglfs/deviceintegration/eglfs_openwfd/eglfs_openwfd.json create mode 100644 src/plugins/platforms/eglfs/deviceintegration/eglfs_openwfd/eglfs_openwfd.pro create mode 100644 src/plugins/platforms/eglfs/deviceintegration/eglfs_openwfd/qeglfsopenwfdintegration.cpp create mode 100644 src/plugins/platforms/eglfs/deviceintegration/eglfs_openwfd/qeglfsopenwfdintegration.h create mode 100644 src/plugins/platforms/eglfs/deviceintegration/eglfs_openwfd/qeglfsopenwfdmain.cpp (limited to 'src/plugins') diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_openwfd/eglfs_openwfd.json b/src/plugins/platforms/eglfs/deviceintegration/eglfs_openwfd/eglfs_openwfd.json new file mode 100644 index 0000000000..cf7cf6b887 --- /dev/null +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_openwfd/eglfs_openwfd.json @@ -0,0 +1,3 @@ +{ + "Keys": [ "eglfs_openwfd" ] +} diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_openwfd/eglfs_openwfd.pro b/src/plugins/platforms/eglfs/deviceintegration/eglfs_openwfd/eglfs_openwfd.pro new file mode 100644 index 0000000000..448b4cbe21 --- /dev/null +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_openwfd/eglfs_openwfd.pro @@ -0,0 +1,17 @@ +TARGET = qeglfs-openwfd-integration + +QT += core-private gui-private eglfsdeviceintegration-private + +INCLUDEPATH += $$PWD/../../api +CONFIG += egl + +SOURCES += $$PWD/qeglfsopenwfdmain.cpp \ + $$PWD/qeglfsopenwfdintegration.cpp + +HEADERS += $$PWD/qeglfsopenwfdintegration.h + +OTHER_FILES += $$PWD/eglfs_openwfd.json + +PLUGIN_TYPE = egldeviceintegrations +PLUGIN_CLASS_NAME = QEglFSOpenWFDIntegrationPlugin +load(qt_plugin) diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_openwfd/qeglfsopenwfdintegration.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_openwfd/qeglfsopenwfdintegration.cpp new file mode 100644 index 0000000000..bb176a69d2 --- /dev/null +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_openwfd/qeglfsopenwfdintegration.cpp @@ -0,0 +1,223 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qeglfsopenwfdintegration.h" + +#include "wfd.h" +#include "wfdext2.h" + +QT_BEGIN_NAMESPACE + +#define MAX_NUM_OF_WFD_BUFFERS 3 +#define MAX_NUM_OF_WFD_DEVICES 4 +#define MAX_NUM_OF_WFD_PIPELINES 4 +#define MAX_NUM_OF_WFD_PORT_MODES 64 +#define MAX_NUM_OF_WFD_PORTS 4 + +typedef struct wfd_buffer { + WFD_EGLImageType* image; + WFDSource source; +} wfd_buffer_t; + +typedef struct wfd_window { + WFDDevice dev; + WFDPort port; + WFDPipeline pipeline; + int numBuffers; + wfd_buffer_t buffers[MAX_NUM_OF_WFD_BUFFERS]; +} wfd_window_t; + +void QEglFSOpenWFDIntegration::platformInit() +{ + QEglFSDeviceIntegration::platformInit(); + + mNativeDisplay = EGL_DEFAULT_DISPLAY; + + // Get device list + WFDint numDevs = wfdEnumerateDevices(nullptr, 0, nullptr); + WFDint devIds[MAX_NUM_OF_WFD_DEVICES]; + + if (numDevs > 0) + wfdEnumerateDevices(devIds, numDevs, nullptr); + + // Create device + mDevice = wfdCreateDevice(WFD_DEFAULT_DEVICE_ID, nullptr); + + if (WFD_INVALID_HANDLE == mDevice) + qFatal( "Failed to create wfd device"); + + // Get port list + WFDint portIds[MAX_NUM_OF_WFD_PORTS]; + WFDint numPorts = wfdEnumeratePorts(mDevice, nullptr, 0, nullptr); + wfdEnumeratePorts(mDevice, portIds, numPorts, nullptr); + + // Create port + mPort = wfdCreatePort(mDevice, portIds[0], nullptr); + + if (WFD_INVALID_HANDLE == mPort) + qFatal("Failed to create wfd port"); + + // Get port modes + WFDint numPortModes = wfdGetPortModes(mDevice, mPort, nullptr, 0); + WFDPortMode portModes[MAX_NUM_OF_WFD_PORT_MODES]; + wfdGetPortModes(mDevice, mPort, portModes, numPortModes); + + // Get width and height + mScreenSize.setWidth(wfdGetPortModeAttribi(mDevice, mPort, portModes[0], WFD_PORT_MODE_WIDTH)); + mScreenSize.setHeight(wfdGetPortModeAttribi(mDevice, mPort, portModes[0], WFD_PORT_MODE_HEIGHT)); + + // Set port mode + wfdSetPortMode(mDevice, mPort, portModes[0]); + WFDErrorCode eError = wfdGetError(mDevice); + if (WFD_ERROR_NONE != eError) + qFatal("Failed to set wfd port mode"); + + // Power on + wfdSetPortAttribi(mDevice, mPort, WFD_PORT_POWER_MODE, WFD_POWER_MODE_ON); + eError = wfdGetError(mDevice); + if (WFD_ERROR_NONE != eError) + qFatal("Failed to power on wfd port"); +} + +QSize QEglFSOpenWFDIntegration::screenSize() const +{ + return mScreenSize; +} + +EGLNativeDisplayType QEglFSOpenWFDIntegration::platformDisplay() const +{ + return mNativeDisplay; +} + +EGLNativeWindowType QEglFSOpenWFDIntegration::createNativeWindow(QPlatformWindow *window, + const QSize &size, + const QSurfaceFormat &format) +{ + Q_UNUSED(window); + Q_UNUSED(format); + + // Get list of pipelines + WFDint numPipelines = wfdEnumeratePipelines(mDevice, nullptr, 0, nullptr); + + WFDint pipelineIds[MAX_NUM_OF_WFD_PIPELINES]; + wfdEnumeratePipelines(mDevice, pipelineIds, numPipelines, nullptr); + + WFDint testId = 0; + testId = pipelineIds[0]; + WFDPipeline pipeline = wfdCreatePipeline(mDevice, testId, nullptr); + if (WFD_INVALID_HANDLE == pipeline) + qFatal("Failed to create wfd pipeline"); + + wfdSetPipelineAttribi(mDevice, pipeline, WFD_PIPELINE_TRANSPARENCY_ENABLE, + (WFD_TRANSPARENCY_SOURCE_ALPHA|WFD_TRANSPARENCY_GLOBAL_ALPHA)); + + WFDErrorCode eError = wfdGetError(mDevice); + if (WFD_ERROR_NONE != eError) + qFatal("Failed to set WFD_PIPELINE_TRANSPARENCY_ENABLE"); + + wfdSetPipelineAttribi(mDevice, pipeline, WFD_PIPELINE_GLOBAL_ALPHA, 255); + eError = wfdGetError(mDevice); + if (WFD_ERROR_NONE != eError) + qFatal("Failed to set WFD_PIPELINE_GLOBAL_ALPHA"); + + wfdBindPipelineToPort(mDevice, mPort, pipeline); + eError = wfdGetError(mDevice); + if (WFD_ERROR_NONE != eError) + qFatal("Failed to bind port to pipeline"); + + // Create buffers + WFDSource source[MAX_NUM_OF_WFD_BUFFERS] = {WFD_INVALID_HANDLE, WFD_INVALID_HANDLE, + WFD_INVALID_HANDLE}; + WFDEGLImage eglImageHandles[MAX_NUM_OF_WFD_BUFFERS]; + WFD_EGLImageType* wfdEglImages[MAX_NUM_OF_WFD_BUFFERS]; + + for (int i = 0; i < MAX_NUM_OF_WFD_BUFFERS; i++) { + wfdCreateWFDEGLImages(mDevice, mScreenSize.width(), mScreenSize.height(), + WFD_FORMAT_RGBA8888, WFD_USAGE_OPENGL_ES2 | WFD_USAGE_DISPLAY, + 1, &(eglImageHandles[i]), 0); + + wfdEglImages[i] = (WFD_EGLImageType *)(eglImageHandles[i]); + if (WFD_INVALID_HANDLE == wfdEglImages[i]) + qFatal("Failed to create WDFEGLImages"); + + source[i] = wfdCreateSourceFromImage(mDevice, pipeline, eglImageHandles[i], nullptr); + if (WFD_INVALID_HANDLE == source[i]) + qFatal("Failed to create source from EGLImage"); + } + + // Commit port + wfdDeviceCommit(mDevice, WFD_COMMIT_ENTIRE_PORT, mPort); + eError = wfdGetError(mDevice); + if (WFD_ERROR_NONE != eError) + qFatal("Failed to commit port"); + + // Create native window + wfd_window_t* nativeWindow = (wfd_window_t*)malloc(sizeof(wfd_window_t)); + if (nullptr == nativeWindow) + qFatal("Failed to allocate memory for native window"); + + nativeWindow->dev = mDevice; + nativeWindow->port = mPort; + nativeWindow->pipeline = pipeline; + nativeWindow->numBuffers = MAX_NUM_OF_WFD_BUFFERS; + + for (int i = 0; i < MAX_NUM_OF_WFD_BUFFERS; i++) { + nativeWindow->buffers[i].image = wfdEglImages[i]; + nativeWindow->buffers[i].source = source[i]; + } + + return (EGLNativeWindowType)nativeWindow; +} + +QSurfaceFormat QEglFSOpenWFDIntegration::surfaceFormatFor(const QSurfaceFormat &inputFormat) const +{ + QSurfaceFormat format; + format.setRedBufferSize(8); + format.setGreenBufferSize(8); + format.setBlueBufferSize(8); + format.setAlphaBufferSize(8); + return format; +} + +void QEglFSOpenWFDIntegration::destroyNativeWindow(EGLNativeWindowType window) +{ + free((void*)window); +} + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_openwfd/qeglfsopenwfdintegration.h b/src/plugins/platforms/eglfs/deviceintegration/eglfs_openwfd/qeglfsopenwfdintegration.h new file mode 100644 index 0000000000..189ddd4d7a --- /dev/null +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_openwfd/qeglfsopenwfdintegration.h @@ -0,0 +1,69 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QEGLFSOPENWFDINTEGRATION_H +#define QEGLFSOPENWFDINTEGRATION_H + +#include "private/qeglfsdeviceintegration_p.h" +#define WFD_WFDEXT_PROTOTYPES +#include "wfd.h" +#include "wfdext2.h" + +QT_BEGIN_NAMESPACE + +class QEglFSOpenWFDIntegration : public QEglFSDeviceIntegration +{ +public: + void platformInit() override; + QSize screenSize() const override; + EGLNativeWindowType createNativeWindow(QPlatformWindow *window, const QSize &size, const QSurfaceFormat &format) override; + void destroyNativeWindow(EGLNativeWindowType window) override; + EGLNativeDisplayType platformDisplay() const override; + virtual QSurfaceFormat surfaceFormatFor(const QSurfaceFormat &inputFormat) const; + +private: + QSize mScreenSize; + EGLNativeDisplayType mNativeDisplay; + WFDDevice mDevice; + WFDPort mPort; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_openwfd/qeglfsopenwfdmain.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_openwfd/qeglfsopenwfdmain.cpp new file mode 100644 index 0000000000..1d6132b55e --- /dev/null +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_openwfd/qeglfsopenwfdmain.cpp @@ -0,0 +1,58 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "private/qeglfsdeviceintegration_p.h" +#include "qeglfsopenwfdintegration.h" + +QT_BEGIN_NAMESPACE + +class QEglFSOpenWFDIntegrationPlugin : public QEglFSDeviceIntegrationPlugin +{ + Q_OBJECT + Q_PLUGIN_METADATA(IID QEglFSDeviceIntegrationFactoryInterface_iid FILE "eglfs_openwfd.json") + +public: + QEglFSDeviceIntegration *create() override { + return new QEglFSOpenWFDIntegration; + } +}; + +QT_END_NAMESPACE + +#include "qeglfsopenwfdmain.moc" -- cgit v1.2.3 From 11a2e0aa2dd921e16cbc80479dd3667dc62ff18a Mon Sep 17 00:00:00 2001 From: Andy Shaw Date: Mon, 25 Sep 2017 13:43:05 +0200 Subject: Cocoa: Ensure menus for a dialog's menubar are validated correctly MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Although the items were enabled for a dialog's menubar they were not appearing as such because Cocoa will query the menu item's target to see if it has a worksWhenModal selector. Therefore to ensure that the menu item will be enabled, we need to add this selector to our delegate and return YES from it when the window for the menubar is the dialog. Task-number: QTBUG-44584 Change-Id: Ic62dc027d563069d2f5c2b7bf9810184bd76de39 Reviewed-by: Morten Johan Sørvig Reviewed-by: Gabriel de Dietrich --- src/plugins/platforms/cocoa/qcocoamenu.mm | 12 ++++++++++++ src/plugins/platforms/cocoa/qcocoamenubar.h | 1 + src/plugins/platforms/cocoa/qcocoamenubar.mm | 5 +++++ 3 files changed, 18 insertions(+) (limited to 'src/plugins') diff --git a/src/plugins/platforms/cocoa/qcocoamenu.mm b/src/plugins/platforms/cocoa/qcocoamenu.mm index a54284dbae..1345295ef5 100644 --- a/src/plugins/platforms/cocoa/qcocoamenu.mm +++ b/src/plugins/platforms/cocoa/qcocoamenu.mm @@ -253,6 +253,18 @@ QT_NAMESPACE_ALIAS_OBJC_CLASS(QCocoaMenuDelegate); return nil; } +// Cocoa will query the menu item's target for the worksWhenModal selector. +// So we need to implement this to allow the items to be handled correctly +// when a modal dialog is visible. +- (BOOL)worksWhenModal +{ + if (!QGuiApplication::modalWindow()) + return YES; + if (auto *mb = qobject_cast(m_menu->menuParent())) + return QGuiApplication::modalWindow()->handle() == mb->cocoaWindow() ? YES : NO; + return YES; +} + @end QT_BEGIN_NAMESPACE diff --git a/src/plugins/platforms/cocoa/qcocoamenubar.h b/src/plugins/platforms/cocoa/qcocoamenubar.h index a4ee531e91..a259147247 100644 --- a/src/plugins/platforms/cocoa/qcocoamenubar.h +++ b/src/plugins/platforms/cocoa/qcocoamenubar.h @@ -71,6 +71,7 @@ public: QList merged() const; NSMenuItem *itemForRole(QPlatformMenuItem::MenuRole r); + QCocoaWindow *cocoaWindow() const; void syncMenu_helper(QPlatformMenu *menu, bool menubarUpdate); diff --git a/src/plugins/platforms/cocoa/qcocoamenubar.mm b/src/plugins/platforms/cocoa/qcocoamenubar.mm index a4cd465dae..cf9553bcf7 100644 --- a/src/plugins/platforms/cocoa/qcocoamenubar.mm +++ b/src/plugins/platforms/cocoa/qcocoamenubar.mm @@ -452,5 +452,10 @@ NSMenuItem *QCocoaMenuBar::itemForRole(QPlatformMenuItem::MenuRole r) return Q_NULLPTR; } +QCocoaWindow *QCocoaMenuBar::cocoaWindow() const +{ + return m_window.data(); +} + QT_END_NAMESPACE -- cgit v1.2.3 From 29104c85db53e7c0c0aaf3fe78f84b737fce4886 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Morten=20Johan=20S=C3=B8rvig?= Date: Fri, 17 Nov 2017 12:28:55 +0100 Subject: =?UTF-8?q?Cocoa:=20Disable=20=E2=80=9CHide=E2=80=9D=20menu=20item?= =?UTF-8?q?=20on=20open=20popups?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Follow native behavior and disable ⌘H and the “Hide” menu item if there are any open popup windows. Task-number: QTBUG-58727 Change-Id: Iad38cc5cce29e0081613417c53b154ae0f05857e Reviewed-by: Morten Johan Sørvig --- src/plugins/platforms/cocoa/qcocoamenuloader.mm | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'src/plugins') diff --git a/src/plugins/platforms/cocoa/qcocoamenuloader.mm b/src/plugins/platforms/cocoa/qcocoamenuloader.mm index 0d9bb5009d..b986833f6d 100644 --- a/src/plugins/platforms/cocoa/qcocoamenuloader.mm +++ b/src/plugins/platforms/cocoa/qcocoamenuloader.mm @@ -43,6 +43,7 @@ #include "qcocoahelpers.h" #include "qcocoamenubar.h" #include "qcocoamenuitem.h" +#include "qcocoaintegration.h" #include #include @@ -343,10 +344,13 @@ - (BOOL)validateMenuItem:(NSMenuItem*)menuItem { - if ([menuItem action] == @selector(hide:) - || [menuItem action] == @selector(hideOtherApplications:) + if ([menuItem action] == @selector(hideOtherApplications:) || [menuItem action] == @selector(unhideAllApplications:)) { return [NSApp validateMenuItem:menuItem]; + } else if ([menuItem action] == @selector(hide:)) { + if (QCocoaIntegration::instance()->activePopupWindow()) + return NO; + return [NSApp validateMenuItem:menuItem]; } else if ([menuItem tag]) { QCocoaMenuItem *cocoaItem = reinterpret_cast([menuItem tag]); return cocoaItem->isEnabled(); -- cgit v1.2.3 From bcd0e43eb98885f0562efddee45b11ca7ec1d546 Mon Sep 17 00:00:00 2001 From: Gatis Paeglis Date: Mon, 4 Dec 2017 16:00:16 +0100 Subject: xcb: fix regression with missing XI_PropertyEvent Wacom stylus proximity detection had stopped working: it was not detecting which type of tool is in use, so all stylus types acted as a generic drawing stylus. Selecting XI_PropertyEvent on a root window fixes the problem. There is nothing in the XI2 specification that says that this property would not be supported on non-root windows. Possibly it is bug in the X server. Anyways, selecting XI_PropertyEvent on a root window in this case actually is better. Property event contains a global state information, there is nothing window specific in it, so there is no need to select it for every native sub-window. It is worth noting that XI_HierarchyChanged also seems to work only when selected on the root window (according to my testing results). And on XI2 author's blog post about XI_HierarchyChanged it says [1]: "These events are sent to all windows, so it doesn't really matter where you register. The traditional approach is to register on the root window." This kind of further confirms that it might be bug in X Server's implementation. [1] http://who-t.blogspot.no/2009/06/xi2-recipies-part-2.html Task-number: QTBUG-64911 Change-Id: I8582675bf835239932e23f4596966dc167495e30 Reviewed-by: Shawn Rutledge --- src/plugins/platforms/xcb/qxcbconnection_xi2.cpp | 30 ++++++++++++++---------- 1 file changed, 18 insertions(+), 12 deletions(-) (limited to 'src/plugins') diff --git a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp index f90f189146..ce6dd7c035 100644 --- a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp +++ b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp @@ -100,6 +100,7 @@ void QXcbConnection::xi2SelectStateEvents() XIEventMask xiEventMask; bitMask = XI_HierarchyChangedMask; bitMask |= XI_DeviceChangedMask; + bitMask |= XI_PropertyEventMask; xiEventMask.deviceid = XIAllDevices; xiEventMask.mask_len = sizeof(bitMask); xiEventMask.mask = xiBitMask; @@ -121,7 +122,6 @@ void QXcbConnection::xi2SelectDeviceEvents(xcb_window_t window) // core enter/leave events will be ignored in this case. bitMask |= XI_EnterMask; bitMask |= XI_LeaveMask; - bitMask |= XI_PropertyEventMask; #ifdef XCB_USE_XINPUT22 if (isAtLeastXI22()) { bitMask |= XI_TouchBeginMask; @@ -378,24 +378,25 @@ void QXcbConnection::xi2SelectDeviceEventsCompatibility(xcb_window_t window) unsigned int mask = 0; unsigned char *bitMask = reinterpret_cast(&mask); - mask |= XI_PropertyEventMask; + Display *dpy = static_cast(m_xlib_display); + #ifdef XCB_USE_XINPUT22 if (isAtLeastXI22()) { mask |= XI_TouchBeginMask; mask |= XI_TouchUpdateMask; mask |= XI_TouchEndMask; + + XIEventMask xiMask; + xiMask.mask_len = sizeof(mask); + xiMask.mask = bitMask; + xiMask.deviceid = XIAllMasterDevices; + Status result = XISelectEvents(dpy, window, &xiMask, 1); + if (result == Success) + QWindowSystemInterfacePrivate::TabletEvent::setPlatformSynthesizesMouse(false); + else + qCDebug(lcQpaXInput, "failed to select events, window %x, result %d", window, result); } #endif - XIEventMask xiMask; - xiMask.mask_len = sizeof(mask); - xiMask.mask = bitMask; - xiMask.deviceid = XIAllMasterDevices; - Display *dpy = static_cast(m_xlib_display); - Status result = XISelectEvents(dpy, window, &xiMask, 1); - if (result == Success) - QWindowSystemInterfacePrivate::TabletEvent::setPlatformSynthesizesMouse(false); - else - qCDebug(lcQpaXInput, "failed to select events, window %x, result %d", window, result); mask = XI_ButtonPressMask; mask |= XI_ButtonReleaseMask; @@ -434,6 +435,11 @@ void QXcbConnection::xi2SelectDeviceEventsCompatibility(xcb_window_t window) XISelectEvents(dpy, window, xiEventMask.data(), i); } #endif + +#if !QT_CONFIG(tabletevent) && !defined(XCB_USE_XINPUT21) + Q_UNUSED(bitMask); + Q_UNUSED(dpy); +#endif } QXcbConnection::TouchDeviceData *QXcbConnection::touchDeviceForId(int id) -- cgit v1.2.3 From ff7dbda3b0eaedf857de3913c2be2f880909ee82 Mon Sep 17 00:00:00 2001 From: Dongmei Wang Date: Fri, 18 Aug 2017 11:32:25 -0700 Subject: xcb_qpa_lib: Fix "undefined reference to `dlsym'" error Change-Id: I37515542571ef37f4361e72b8db4547ff1e1b86a Reviewed-by: Oswald Buddenhagen --- src/plugins/platforms/xcb/xcb_qpa_lib.pro | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/plugins') diff --git a/src/plugins/platforms/xcb/xcb_qpa_lib.pro b/src/plugins/platforms/xcb/xcb_qpa_lib.pro index 284711075e..55007b43a7 100644 --- a/src/plugins/platforms/xcb/xcb_qpa_lib.pro +++ b/src/plugins/platforms/xcb/xcb_qpa_lib.pro @@ -85,4 +85,6 @@ include(gl_integrations/gl_integrations.pri) QMAKE_USE += xkbcommon } +qtConfig(dlopen): QMAKE_USE += libdl + load(qt_module) -- cgit v1.2.3 From 87efdd8c7f997e16ff5a35a44dce9b967d23f09b Mon Sep 17 00:00:00 2001 From: Andy Shaw Date: Tue, 5 Dec 2017 13:45:13 +0100 Subject: Android: Reserve space for the QVarLengthArray, so we can use append MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When the QVarLengthArray was initialized with a size then append would add to the end of that. Therefore we need to use reserve to get the desired effect. Task-number: QTBUG-64905 Change-Id: Ia1ebeb26cd31bc5e92bd7f81079506a266b845bf Reviewed-by: Jan Arve Sæther --- src/plugins/platforms/android/androidjniaccessibility.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/plugins') diff --git a/src/plugins/platforms/android/androidjniaccessibility.cpp b/src/plugins/platforms/android/androidjniaccessibility.cpp index a3bc58bb89..309e41bfd6 100644 --- a/src/plugins/platforms/android/androidjniaccessibility.cpp +++ b/src/plugins/platforms/android/androidjniaccessibility.cpp @@ -106,7 +106,8 @@ namespace QtAndroidAccessibility QAccessibleInterface *iface = interfaceFromId(objectId); if (iface && iface->isValid()) { const int childCount = iface->childCount(); - QVarLengthArray ifaceIdArray(childCount); + QVarLengthArray ifaceIdArray; + ifaceIdArray.reserve(childCount); for (int i = 0; i < childCount; ++i) { QAccessibleInterface *child = iface->child(i); if (child && child->isValid()) -- cgit v1.2.3 From 58a409c6dce920feb5c746a9319d0e0f1d02a233 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Tue, 5 Dec 2017 19:30:12 +0100 Subject: iOS: Implement QPlatformScreen::name for easier debugging Change-Id: I077bec93fe2086c38ebe986b322977a50a1ab27d Reviewed-by: Richard Moe Gustavsen --- src/plugins/platforms/ios/qiosscreen.h | 2 ++ src/plugins/platforms/ios/qiosscreen.mm | 10 ++++++++++ 2 files changed, 12 insertions(+) (limited to 'src/plugins') diff --git a/src/plugins/platforms/ios/qiosscreen.h b/src/plugins/platforms/ios/qiosscreen.h index 9fcce42825..7f10b08492 100644 --- a/src/plugins/platforms/ios/qiosscreen.h +++ b/src/plugins/platforms/ios/qiosscreen.h @@ -56,6 +56,8 @@ public: QIOSScreen(UIScreen *screen); ~QIOSScreen(); + QString name() const override; + QRect geometry() const Q_DECL_OVERRIDE; QRect availableGeometry() const Q_DECL_OVERRIDE; int depth() const Q_DECL_OVERRIDE; diff --git a/src/plugins/platforms/ios/qiosscreen.mm b/src/plugins/platforms/ios/qiosscreen.mm index 1a7004c249..67970ba59e 100644 --- a/src/plugins/platforms/ios/qiosscreen.mm +++ b/src/plugins/platforms/ios/qiosscreen.mm @@ -280,6 +280,16 @@ QIOSScreen::~QIOSScreen() [m_uiWindow release]; } +QString QIOSScreen::name() const +{ + if (m_uiScreen == [UIScreen mainScreen]) { + return QString::fromNSString([UIDevice currentDevice].model) + + QLatin1String(" built-in display"); + } else { + return QLatin1String("External display"); + } +} + void QIOSScreen::updateProperties() { QRect previousGeometry = m_geometry; -- cgit v1.2.3 From 77942a1bdf9fe22d8f076e59ce19fe9a9d7870d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Tue, 5 Dec 2017 18:09:50 +0100 Subject: iOS: Try to detect and deal with delayed touch delivery due to gestures A UIGestureRecognizer may have its delaysTouchesBegan or delaysTouchesEnded properties set, which causes iOS to not deliver touch events to the view until the recognizer has failed recognition of its gesture. In that case, the touch event is not delivered via [UIWindow sendEvent:] as usual, but via _UIGestureEnvironmentSortAndSendDelayedTouches. The latter function is apparently not reentrant, as opening a native alert dialog in response to the touch delivery will result in the dialogs's buttons to stop working, probably because they themselves use gestures. Unfortunately iOS maintains two internal gesture recognizers on iPad, of type _UISystemGestureGateGestureRecognizer, probably related to the swipe-from-bottom gesture used for multitasking. Without any workaround, these two recognizers will result in any tap on the bottom part of the screen to be delivered delayed, which may introduce stuck alert dialogs as described above. UITouch has a gestureRecognizers property, but unfortunately this property does not give us any information in the cases where we need it, so we have to use an heuristic involving a UIWindow subclass to detect the case where event delivery is delayed. As there is no way to prevent the user from recursing into an event loop when delivering the event, our only hope is to deliver the event asynchronously. Task-number: QTBUG-64577 Change-Id: I11d9caa8c4542dc80426a9e58ea555914bed433e Reviewed-by: Richard Moe Gustavsen --- src/plugins/platforms/ios/qiosscreen.h | 4 ++++ src/plugins/platforms/ios/qiosscreen.mm | 22 +++++++++++++++++++++- src/plugins/platforms/ios/quiview.mm | 17 ++++++++++++++++- 3 files changed, 41 insertions(+), 2 deletions(-) (limited to 'src/plugins') diff --git a/src/plugins/platforms/ios/qiosscreen.h b/src/plugins/platforms/ios/qiosscreen.h index 7f10b08492..d63fa29ec3 100644 --- a/src/plugins/platforms/ios/qiosscreen.h +++ b/src/plugins/platforms/ios/qiosscreen.h @@ -46,6 +46,10 @@ @class QIOSOrientationListener; +@interface QUIWindow : UIWindow +@property (nonatomic, readonly) BOOL sendingEvent; +@end + QT_BEGIN_NAMESPACE class QIOSScreen : public QObject, public QPlatformScreen diff --git a/src/plugins/platforms/ios/qiosscreen.mm b/src/plugins/platforms/ios/qiosscreen.mm index 67970ba59e..0d3826fc4c 100644 --- a/src/plugins/platforms/ios/qiosscreen.mm +++ b/src/plugins/platforms/ios/qiosscreen.mm @@ -192,6 +192,26 @@ static QIOSScreen* qtPlatformScreenFor(UIScreen *uiScreen) // ------------------------------------------------------------------------- +@implementation QUIWindow + +- (id)initWithFrame:(CGRect)frame +{ + if ((self = [super initWithFrame:frame])) + self->_sendingEvent = NO; + + return self; +} + +- (void)sendEvent:(UIEvent *)event +{ + QScopedValueRollback(self->_sendingEvent, YES); + [super sendEvent:event]; +} + +@end + +// ------------------------------------------------------------------------- + QT_BEGIN_NAMESPACE /*! @@ -261,7 +281,7 @@ QIOSScreen::QIOSScreen(UIScreen *screen) if (!m_uiWindow) { // Create a window and associated view-controller that we can use - m_uiWindow = [[UIWindow alloc] initWithFrame:[m_uiScreen bounds]]; + m_uiWindow = [[QUIWindow alloc] initWithFrame:[m_uiScreen bounds]]; m_uiWindow.rootViewController = [[[QIOSViewController alloc] initWithQIOSScreen:this] autorelease]; } diff --git a/src/plugins/platforms/ios/quiview.mm b/src/plugins/platforms/ios/quiview.mm index 79f9d6871a..1dbacad6e7 100644 --- a/src/plugins/platforms/ios/quiview.mm +++ b/src/plugins/platforms/ios/quiview.mm @@ -43,6 +43,7 @@ #include "qiosintegration.h" #include "qiosviewcontroller.h" #include "qiostextresponder.h" +#include "qiosscreen.h" #include "qioswindow.h" #ifndef Q_OS_TVOS #include "qiosmenu.h" @@ -359,7 +360,21 @@ - (void)sendTouchEventWithTimestamp:(ulong)timeStamp { QIOSIntegration *iosIntegration = QIOSIntegration::instance(); - QWindowSystemInterface::handleTouchEvent(m_qioswindow->window(), timeStamp, iosIntegration->touchDevice(), m_activeTouches.values()); + if (!static_cast(self.window).sendingEvent) { + // The event is likely delivered as part of delayed touch delivery, via + // _UIGestureEnvironmentSortAndSendDelayedTouches, due to one of the two + // _UISystemGestureGateGestureRecognizer instances on the top level window + // having its delaysTouchesBegan set to YES. During this delivery, it's not + // safe to spin up a recursive event loop, as our calling function is not + // reentrant, so any gestures used by the recursive code, e.g. a native + // alert dialog, will fail to recognize. To be on the safe side, we deliver + // the event asynchronously. + QWindowSystemInterface::handleTouchEvent( + m_qioswindow->window(), timeStamp, iosIntegration->touchDevice(), m_activeTouches.values()); + } else { + QWindowSystemInterface::handleTouchEvent( + m_qioswindow->window(), timeStamp, iosIntegration->touchDevice(), m_activeTouches.values()); + } } - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event -- cgit v1.2.3 From e37c9d5d5f4ba9874808a4e565c36b2953eb96da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Mon, 4 Dec 2017 14:41:36 +0100 Subject: iOS: Harden application state change logic Make sure we catch application state changes as early as possible, and deal properly with any changes delivered before we have an app to send them to. Change-Id: I6d0ea0398f9fab88fc182342769b075cb144227f Reviewed-by: Richard Moe Gustavsen --- src/plugins/platforms/ios/qiosapplicationstate.h | 18 ++-- src/plugins/platforms/ios/qiosapplicationstate.mm | 110 ++++++++++------------ src/plugins/platforms/ios/qiosintegration.h | 3 +- 3 files changed, 65 insertions(+), 66 deletions(-) (limited to 'src/plugins') diff --git a/src/plugins/platforms/ios/qiosapplicationstate.h b/src/plugins/platforms/ios/qiosapplicationstate.h index 1c77b26da1..a68147a72a 100644 --- a/src/plugins/platforms/ios/qiosapplicationstate.h +++ b/src/plugins/platforms/ios/qiosapplicationstate.h @@ -40,20 +40,24 @@ #ifndef QIOSAPPLICATIONSTATE_H #define QIOSAPPLICATIONSTATE_H -#include -#include +#include -Q_FORWARD_DECLARE_OBJC_CLASS(NSObject); +#include QT_BEGIN_NAMESPACE -class QIOSApplicationState +class QIOSApplicationState : public QObject { + Q_OBJECT public: QIOSApplicationState(); - ~QIOSApplicationState(); -private: - QVector m_observers; + + static void handleApplicationStateChanged(UIApplicationState state, const QString &reason); + static Qt::ApplicationState toQtApplicationState(UIApplicationState state); + +Q_SIGNALS: + void applicationStateWillChange(Qt::ApplicationState); + void applicationStateDidChange(Qt::ApplicationState); }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/ios/qiosapplicationstate.mm b/src/plugins/platforms/ios/qiosapplicationstate.mm index 7c8e1f9927..fed09999b5 100644 --- a/src/plugins/platforms/ios/qiosapplicationstate.mm +++ b/src/plugins/platforms/ios/qiosapplicationstate.mm @@ -40,82 +40,76 @@ #include "qiosapplicationstate.h" #include "qiosglobal.h" +#include "qiosintegration.h" #include #include #include -#import +QT_BEGIN_NAMESPACE -static Qt::ApplicationState qtApplicationState(UIApplicationState uiApplicationState) +static void qRegisterApplicationStateNotifications() { - switch (uiApplicationState) { - case UIApplicationStateActive: - // The application is visible in front, and receiving events - return Qt::ApplicationActive; - case UIApplicationStateInactive: - // The app is running in the foreground but is not receiving events. This - // typically happens while transitioning to/from active/background, like - // upon app launch or when receiving incoming calls. - return Qt::ApplicationInactive; - case UIApplicationStateBackground: - // Normally the app would enter this state briefly before it gets - // suspeded (you have five seconds, according to Apple). - // You can request more time and start a background task, which would - // normally map closer to Qt::ApplicationHidden. But since we have no - // API for doing that yet, we handle this state as "about to be suspended". - // Note: A screen-shot for the SpringBoard will also be taken after this - // call returns. - return Qt::ApplicationSuspended; + NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter]; + NSOperationQueue *mainQueue = [NSOperationQueue mainQueue]; + + // Map between notifications and corresponding application state. Note that + // there's no separate notification for moving to UIApplicationStateInactive, + // so we use UIApplicationWillResignActiveNotification as an intermediate. + static QMap notifications { + { UIApplicationDidBecomeActiveNotification, UIApplicationStateActive }, + { UIApplicationWillResignActiveNotification, UIApplicationStateInactive }, + { UIApplicationDidEnterBackgroundNotification, UIApplicationStateBackground }, + }; + + for (auto i = notifications.constBegin(); i != notifications.constEnd(); ++i) { + [notificationCenter addObserverForName:i.key() object:nil queue:mainQueue + usingBlock:^void(NSNotification *notification) { + NSRange nameRange = NSMakeRange(2, notification.name.length - 14); + QString reason = QString::fromNSString([notification.name substringWithRange:nameRange]); + QIOSApplicationState::handleApplicationStateChanged(i.value(), reason); + }]; } -} -static void handleApplicationStateChanged(UIApplicationState uiApplicationState) -{ - Qt::ApplicationState state = qtApplicationState(uiApplicationState); - qCDebug(lcQpaApplication) << "moved to" << state; - QWindowSystemInterface::handleApplicationStateChanged(state); + // Initialize correct startup state, which may not be the Qt default (inactive) + UIApplicationState startupState = [UIApplication sharedApplication].applicationState; + QIOSApplicationState::handleApplicationStateChanged(startupState, QLatin1String("Application loaded")); } - -QT_BEGIN_NAMESPACE +Q_CONSTRUCTOR_FUNCTION(qRegisterApplicationStateNotifications) QIOSApplicationState::QIOSApplicationState() { - NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter]; - - m_observers.push_back([notificationCenter addObserverForName:UIApplicationDidBecomeActiveNotification - object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *) { - handleApplicationStateChanged(UIApplicationStateActive); - } - ]); - - m_observers.push_back([notificationCenter addObserverForName:UIApplicationWillResignActiveNotification - object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *) { - // Note: UIApplication is still UIApplicationStateActive at this point, - // but since there is no separate notification for the inactive state, - // we report UIApplicationStateInactive now. - handleApplicationStateChanged(UIApplicationStateInactive); - } - ]); - - m_observers.push_back([notificationCenter addObserverForName:UIApplicationDidEnterBackgroundNotification - object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *) { - handleApplicationStateChanged(UIApplicationStateBackground); - } - ]); - - // Initialize correct startup state, which may not be the Qt default (inactive) UIApplicationState startupState = [UIApplication sharedApplication].applicationState; - QGuiApplicationPrivate::applicationState = qtApplicationState(startupState); + QIOSApplicationState::handleApplicationStateChanged(startupState, QLatin1String("Application launched")); } -QIOSApplicationState::~QIOSApplicationState() +void QIOSApplicationState::handleApplicationStateChanged(UIApplicationState uiState, const QString &reason) { - NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter]; - foreach (const NSObject* observer, m_observers) - [notificationCenter removeObserver:observer]; + Qt::ApplicationState state = toQtApplicationState(uiState); + qCDebug(lcQpaApplication) << qPrintable(reason) + << "- moving from" << QGuiApplication::applicationState() << "to" << state; + + if (QIOSIntegration *integration = QIOSIntegration::instance()) { + emit integration->applicationState.applicationStateWillChange(state); + QWindowSystemInterface::handleApplicationStateChanged(state); + emit integration->applicationState.applicationStateDidChange(state); + qCDebug(lcQpaApplication) << "done moving to" << state; + } else { + qCDebug(lcQpaApplication) << "no platform integration yet, setting state directly"; + QGuiApplicationPrivate::applicationState = state; + } } -QT_END_NAMESPACE +Qt::ApplicationState QIOSApplicationState::toQtApplicationState(UIApplicationState state) +{ + switch (state) { + case UIApplicationStateActive: return Qt::ApplicationActive; + case UIApplicationStateInactive: return Qt::ApplicationInactive; + case UIApplicationStateBackground: return Qt::ApplicationSuspended; + } +} +#include "moc_qiosapplicationstate.cpp" + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/ios/qiosintegration.h b/src/plugins/platforms/ios/qiosintegration.h index 54c1a1dcb7..1d53734096 100644 --- a/src/plugins/platforms/ios/qiosintegration.h +++ b/src/plugins/platforms/ios/qiosintegration.h @@ -109,6 +109,8 @@ public: QFactoryLoader *optionalPlugins() { return m_optionalPlugins; } + QIOSApplicationState applicationState; + private: QPlatformFontDatabase *m_fontDatabase; #ifndef Q_OS_TVOS @@ -116,7 +118,6 @@ private: #endif QPlatformInputContext *m_inputContext; QTouchDevice *m_touchDevice; - QIOSApplicationState m_applicationState; QIOSServices *m_platformServices; mutable QPlatformAccessibility *m_accessibility; QFactoryLoader *m_optionalPlugins; -- cgit v1.2.3 From 933497bace2ddfd9920100ccf155658cd2030c7c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Thu, 30 Nov 2017 16:46:41 +0100 Subject: iOS: Ignore view layouts while in the background Despite the OpenGL ES Programming Guide telling us to avoid all use of OpenGL while in the background, iOS will perform its view snapshotting for the app switcher after the application has been backgrounded; once for each orientation. Presumably the expectation is that no rendering needs to be done to provide an alternate orientation snapshot, just relayouting of views. But in our case, or any non-stretchable content case such as a OpenGL based game, this is not true. Instead of continuing layout, which will send potentially expensive geometry changes (with isExposed false, since we're in the background), we short-circuit the snapshotting. iOS will still use the latest rendered frame to create the application switcher thumbnail, but it will be based on the last active orientation of the application. To ensure that we pick up the right geometry when rotating the device while the app is in the background, we treat applicationWillEnterForeground as Qt::ApplicationInactive, which matches the recommendations of the OpenGL ES Programming Guide to "re-create any objects and restart your animation timers". Change-Id: Ia9c27f85f996ecf30284c825b43447aa7099224e Reviewed-by: Richard Moe Gustavsen --- src/plugins/platforms/ios/qiosapplicationstate.mm | 1 + src/plugins/platforms/ios/qiosviewcontroller.mm | 20 ++++++++++++++++++++ 2 files changed, 21 insertions(+) (limited to 'src/plugins') diff --git a/src/plugins/platforms/ios/qiosapplicationstate.mm b/src/plugins/platforms/ios/qiosapplicationstate.mm index fed09999b5..3407aebf8f 100644 --- a/src/plugins/platforms/ios/qiosapplicationstate.mm +++ b/src/plugins/platforms/ios/qiosapplicationstate.mm @@ -58,6 +58,7 @@ static void qRegisterApplicationStateNotifications() // there's no separate notification for moving to UIApplicationStateInactive, // so we use UIApplicationWillResignActiveNotification as an intermediate. static QMap notifications { + { UIApplicationWillEnterForegroundNotification, UIApplicationStateInactive }, { UIApplicationDidBecomeActiveNotification, UIApplicationStateActive }, { UIApplicationWillResignActiveNotification, UIApplicationStateInactive }, { UIApplicationDidEnterBackgroundNotification, UIApplicationStateBackground }, diff --git a/src/plugins/platforms/ios/qiosviewcontroller.mm b/src/plugins/platforms/ios/qiosviewcontroller.mm index c47b6d68b1..a9fdfaf9f1 100644 --- a/src/plugins/platforms/ios/qiosviewcontroller.mm +++ b/src/plugins/platforms/ios/qiosviewcontroller.mm @@ -157,6 +157,26 @@ - (void)layoutSubviews { + if (QGuiApplication::applicationState() == Qt::ApplicationSuspended) { + // Despite the OpenGL ES Programming Guide telling us to avoid all + // use of OpenGL while in the background, iOS will perform its view + // snapshotting for the app switcher after the application has been + // backgrounded; once for each orientation. Presumably the expectation + // is that no rendering needs to be done to provide an alternate + // orientation snapshot, just relayouting of views. But in our case, + // or any non-stretchable content case such as a OpenGL based game, + // this is not true. Instead of continuing layout, which will send + // potentially expensive geometry changes (with isExposed false, + // since we're in the background), we short-circuit the snapshotting + // here. iOS will still use the latest rendered frame to create the + // application switcher thumbnail, but it will be based on the last + // active orientation of the application. + QIOSScreen *screen = self.qtViewController->m_screen; + qCDebug(lcQpaWindow) << "ignoring layout of subviews while suspended," + << "likely system snapshot of" << screen->screen()->primaryOrientation(); + return; + } + for (int i = int(self.subviews.count) - 1; i >= 0; --i) { UIView *view = static_cast([self.subviews objectAtIndex:i]); if (![view isKindOfClass:[QUIView class]]) -- cgit v1.2.3 From a73de7ce2dde1128a14e968bcdd6c17b3d2d17f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Mon, 20 Nov 2017 12:04:50 +0100 Subject: iOS: Harden logic for when it's safe to use the graphics hardware To fix QTBUG-52493 we tied the exposed state of a window to the application being in the foreground. This has the result of a visible flash of black between hiding the launch screen and showing the first frame of the application, as the application is still waiting for UIApplicationStateActive to begin rendering, which happens after iOS hides the launch screen. According to the iOS OpenGL ES Programming Guide, it should be safe to render GL in UIApplicationStateInactive as well, and even in UIApplicationStateBackground, as long as the rendering finishes before the UIApplicationDidEnterBackgroundNotification returns. To ensure that we catch any bugs in this area, checks have been added that verify that no rendering happens while in the background state. Task-number: QTBUG-63229 Task-number: QTBUG-52493 Task-number: QTBUG-55205 Change-Id: Ib42bedbeddd7479ab0fb5e5b7de9f5805658e111 Reviewed-by: Richard Moe Gustavsen --- src/plugins/platforms/ios/qioscontext.h | 1 + src/plugins/platforms/ios/qioscontext.mm | 66 +++++++++++++++++++++++++++----- src/plugins/platforms/ios/qioswindow.mm | 2 +- 3 files changed, 59 insertions(+), 10 deletions(-) (limited to 'src/plugins') diff --git a/src/plugins/platforms/ios/qioscontext.h b/src/plugins/platforms/ios/qioscontext.h index 5b7917f7b4..ce50eff1d9 100644 --- a/src/plugins/platforms/ios/qioscontext.h +++ b/src/plugins/platforms/ios/qioscontext.h @@ -87,6 +87,7 @@ private: bool isComplete; }; + static bool verifyGraphicsHardwareAvailability(); static void deleteBuffers(const FramebufferObject &framebufferObject); FramebufferObject &backingFramebufferObjectFor(QPlatformSurface *) const; diff --git a/src/plugins/platforms/ios/qioscontext.mm b/src/plugins/platforms/ios/qioscontext.mm index 6a6cbb4324..03643c19a9 100644 --- a/src/plugins/platforms/ios/qioscontext.mm +++ b/src/plugins/platforms/ios/qioscontext.mm @@ -38,10 +38,13 @@ ****************************************************************************/ #include "qioscontext.h" + +#include "qiosintegration.h" #include "qioswindow.h" #include +#include #include #import @@ -136,6 +139,9 @@ bool QIOSContext::makeCurrent(QPlatformSurface *surface) { Q_ASSERT_IS_GL_SURFACE(surface); + if (!verifyGraphicsHardwareAvailability()) + return false; + [EAGLContext setCurrentContext:m_eaglContext]; // For offscreen surfaces we don't prepare a default FBO @@ -214,18 +220,12 @@ void QIOSContext::swapBuffers(QPlatformSurface *surface) { Q_ASSERT_IS_GL_SURFACE(surface); + if (!verifyGraphicsHardwareAvailability()) + return; + if (surface->surface()->surfaceClass() == QSurface::Offscreen) return; // Nothing to do - // When using threaded rendering, the render-thread may not have picked up - // yet on the fact that a window is no longer exposed, and will try to swap - // a non-exposed window. This may in some cases result in crashes, e.g. when - // iOS is suspending an application, so we have an extra guard here. - if (!static_cast(surface)->isExposed()) { - qCDebug(lcQpaGLContext, "Detected swapBuffers on a non-exposed window, skipping flush"); - return; - } - FramebufferObject &framebufferObject = backingFramebufferObjectFor(surface); Q_ASSERT_X(framebufferObject.isComplete, "QIOSContext", "swapBuffers on incomplete FBO"); @@ -287,6 +287,54 @@ bool QIOSContext::needsRenderbufferResize(QPlatformSurface *surface) const return false; } +bool QIOSContext::verifyGraphicsHardwareAvailability() +{ + // Per the iOS OpenGL ES Programming Guide, background apps may not execute commands on the + // graphics hardware. Specifically: "In your app delegate’s applicationDidEnterBackground: + // method, your app may want to delete some of its OpenGL ES objects to make memory and + // resources available to the foreground app. Call the glFinish function to ensure that + // the resources are removed immediately. After your app exits its applicationDidEnterBackground: + // method, it must not make any new OpenGL ES calls. If it makes an OpenGL ES call, it is + // terminated by iOS.". + static bool applicationBackgrounded = QGuiApplication::applicationState() == Qt::ApplicationSuspended; + + static dispatch_once_t onceToken = 0; + dispatch_once(&onceToken, ^{ + QIOSApplicationState *applicationState = &QIOSIntegration::instance()->applicationState; + connect(applicationState, &QIOSApplicationState::applicationStateWillChange, [](Qt::ApplicationState state) { + if (applicationBackgrounded && state != Qt::ApplicationSuspended) { + qCDebug(lcQpaGLContext) << "app no longer backgrounded, rendering enabled"; + applicationBackgrounded = false; + } + }); + connect(applicationState, &QIOSApplicationState::applicationStateDidChange, [](Qt::ApplicationState state) { + if (state != Qt::ApplicationSuspended) + return; + + qCDebug(lcQpaGLContext) << "app backgrounded, rendering disabled"; + applicationBackgrounded = true; + + // By the time we receive this signal the application has moved into + // Qt::ApplactionStateSuspended, and all windows have been obscured, + // which should stop all rendering. If there's still an active GL context, + // we follow Apple's advice and call glFinish before making it inactive. + if (QOpenGLContext *currentContext = QOpenGLContext::currentContext()) { + qCWarning(lcQpaGLContext) << "explicitly glFinishing and deactivating" << currentContext; + glFinish(); + currentContext->doneCurrent(); + } + }); + }); + + if (applicationBackgrounded) { + static const char warning[] = "OpenGL ES calls are not allowed while an application is backgrounded"; + Q_ASSERT_X(!applicationBackgrounded, "QIOSContext", warning); + qCWarning(lcQpaGLContext, warning); + } + + return !applicationBackgrounded; +} + void QIOSContext::windowDestroyed(QObject *object) { QIOSWindow *window = static_cast(object); diff --git a/src/plugins/platforms/ios/qioswindow.mm b/src/plugins/platforms/ios/qioswindow.mm index fb161febda..e934cb90fa 100644 --- a/src/plugins/platforms/ios/qioswindow.mm +++ b/src/plugins/platforms/ios/qioswindow.mm @@ -225,7 +225,7 @@ void QIOSWindow::applyGeometry(const QRect &rect) bool QIOSWindow::isExposed() const { - return qApp->applicationState() >= Qt::ApplicationActive + return qApp->applicationState() != Qt::ApplicationSuspended && window()->isVisible() && !window()->geometry().isEmpty(); } -- cgit v1.2.3 From 79d78d814acad4e183e281aea9b131f396abe3fb Mon Sep 17 00:00:00 2001 From: Gatis Paeglis Date: Thu, 7 Dec 2017 11:49:49 +0100 Subject: xcb: verify if xrandr present before using xcb_randr* APIs Not doing so might break the connection. We have had similar issues before, e.g. QTBUG-45312. Change-Id: I95f15d24773fc92b052578bd72d1ba264d0a5f63 Reviewed-by: Laszlo Agocs Reviewed-by: Uli Schlachter --- src/plugins/platforms/xcb/qxcbscreen.cpp | 35 +++++++++++++++++++++----------- 1 file changed, 23 insertions(+), 12 deletions(-) (limited to 'src/plugins') diff --git a/src/plugins/platforms/xcb/qxcbscreen.cpp b/src/plugins/platforms/xcb/qxcbscreen.cpp index ec0f9ba561..67c96b2d80 100644 --- a/src/plugins/platforms/xcb/qxcbscreen.cpp +++ b/src/plugins/platforms/xcb/qxcbscreen.cpp @@ -446,17 +446,24 @@ QXcbScreen::QXcbScreen(QXcbConnection *connection, QXcbVirtualDesktop *virtualDe m_cursor = new QXcbCursor(connection, this); - // Parse EDID - if (m_edid.parse(getEdid())) - qCDebug(lcQpaScreen, "EDID data for output \"%s\": identifier '%s', manufacturer '%s', model '%s', serial '%s', physical size: %.2fx%.2f", - name().toLatin1().constData(), - m_edid.identifier.toLatin1().constData(), - m_edid.manufacturer.toLatin1().constData(), - m_edid.model.toLatin1().constData(), - m_edid.serialNumber.toLatin1().constData(), - m_edid.physicalSize.width(), m_edid.physicalSize.height()); - else - qCDebug(lcQpaScreen) << "Failed to parse EDID data for output" << name(); // keep this debug, not warning + if (connection->hasXRandr()) { // Parse EDID + QByteArray edid = getEdid(); + if (m_edid.parse(edid)) { + qCDebug(lcQpaScreen, "EDID data for output \"%s\": identifier '%s', manufacturer '%s'," + "model '%s', serial '%s', physical size: %.2fx%.2f", + name().toLatin1().constData(), + m_edid.identifier.toLatin1().constData(), + m_edid.manufacturer.toLatin1().constData(), + m_edid.model.toLatin1().constData(), + m_edid.serialNumber.toLatin1().constData(), + m_edid.physicalSize.width(), m_edid.physicalSize.height()); + } else { + // This property is defined by the xrandr spec. Parsing failure indicates a valid error, + // but keep this as debug, for details see 4f515815efc318ddc909a0399b71b8a684962f38. + qCDebug(lcQpaScreen) << "Failed to parse EDID data for output" << name() << + "edid data: " << edid; + } + } } QXcbScreen::~QXcbScreen() @@ -899,9 +906,13 @@ QByteArray QXcbScreen::getOutputProperty(xcb_atom_t atom) const QByteArray QXcbScreen::getEdid() const { + QByteArray result; + if (!connection()->hasXRandr()) + return result; + // Try a bunch of atoms xcb_atom_t atom = connection()->internAtom("EDID"); - QByteArray result = getOutputProperty(atom); + result = getOutputProperty(atom); if (result.isEmpty()) { atom = connection()->internAtom("EDID_DATA"); result = getOutputProperty(atom); -- cgit v1.2.3 From fefd9de52aaaae58d3c0150cbd19f0e403ba92ce Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Mon, 11 Dec 2017 10:17:59 +0100 Subject: Windows QPA: Emulate aboutToHide(), aboutToShow() signals of QPlatformMenu Wrap the call to TrackPopupMenu accordingly. Complements 7849aa6e96aa923fca5523afc8cf88edcc0bcf90. Task-number: QTBUG-64628 Change-Id: Ia370e566266e96ab690ce5ed41d06dea7cafd4e4 Reviewed-by: J-P Nurmi Reviewed-by: Oliver Wolff --- src/plugins/platforms/windows/qwindowsmenu.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'src/plugins') diff --git a/src/plugins/platforms/windows/qwindowsmenu.cpp b/src/plugins/platforms/windows/qwindowsmenu.cpp index 4e1997c4f8..72f11d54b4 100644 --- a/src/plugins/platforms/windows/qwindowsmenu.cpp +++ b/src/plugins/platforms/windows/qwindowsmenu.cpp @@ -686,9 +686,16 @@ void QWindowsPopupMenu::showPopup(const QWindow *parentWindow, const QRect &targ bool QWindowsPopupMenu::trackPopupMenu(HWND windowHandle, int x, int y) { lastShownPopupMenu = this; - return TrackPopupMenu(menuHandle(), + // Emulate Show()/Hide() signals. Could be implemented by catching the + // WM_EXITMENULOOP, WM_ENTERMENULOOP messages; but they do not carry + // information telling which menu was opened. + emit aboutToShow(); + const bool result = + TrackPopupMenu(menuHandle(), QGuiApplication::layoutDirection() == Qt::RightToLeft ? UINT(TPM_RIGHTALIGN) : UINT(0), x, y, 0, windowHandle, nullptr) == TRUE; + emit aboutToHide(); + return result; } bool QWindowsPopupMenu::notifyTriggered(uint id) -- cgit v1.2.3 From 3d720f38faec4c1c600e128d5d8da5a4435ec1ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Tue, 5 Dec 2017 00:22:05 +0100 Subject: iOS: Implement QIOSScreen::refreshRate to account for 120Hz displays Task-number: QTBUG-64968 Change-Id: If96f6cde8f2fc6d91beb842d82a881fe057260b5 Reviewed-by: Jake Petroules --- src/plugins/platforms/ios/qiosscreen.h | 1 + src/plugins/platforms/ios/qiosscreen.mm | 10 ++++++++++ 2 files changed, 11 insertions(+) (limited to 'src/plugins') diff --git a/src/plugins/platforms/ios/qiosscreen.h b/src/plugins/platforms/ios/qiosscreen.h index d63fa29ec3..be0f301710 100644 --- a/src/plugins/platforms/ios/qiosscreen.h +++ b/src/plugins/platforms/ios/qiosscreen.h @@ -69,6 +69,7 @@ public: QSizeF physicalSize() const Q_DECL_OVERRIDE; QDpi logicalDpi() const Q_DECL_OVERRIDE; qreal devicePixelRatio() const Q_DECL_OVERRIDE; + qreal refreshRate() const override; Qt::ScreenOrientation nativeOrientation() const Q_DECL_OVERRIDE; Qt::ScreenOrientation orientation() const Q_DECL_OVERRIDE; diff --git a/src/plugins/platforms/ios/qiosscreen.mm b/src/plugins/platforms/ios/qiosscreen.mm index 0d3826fc4c..521495b42f 100644 --- a/src/plugins/platforms/ios/qiosscreen.mm +++ b/src/plugins/platforms/ios/qiosscreen.mm @@ -459,6 +459,16 @@ qreal QIOSScreen::devicePixelRatio() const return [m_uiScreen scale]; } +qreal QIOSScreen::refreshRate() const +{ +#if QT_DARWIN_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_NA, 100300, 110000, __WATCHOS_NA) + if (__builtin_available(iOS 10.3, tvOS 11, *)) + return m_uiScreen.maximumFramesPerSecond; +#endif + + return 60.0; +} + Qt::ScreenOrientation QIOSScreen::nativeOrientation() const { CGRect nativeBounds = -- cgit v1.2.3 From b0f142e3533599466f15f1303b063ee35b18e4e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Fri, 8 Dec 2017 02:06:31 +0100 Subject: iOS: Ensure that the cursor rect doesn't trigger an inverted scroll If the cursor is at the top of the screen, it may end up with a cursor rect that extends beyond the screen after we pad it. We need to make sure it's constrained by the screen geometry before checking if it's within the available geometry. Task-number: QTBUG-65041 Change-Id: I115f49d359b3c2e10219a6b8aa5ad051f44256a7 Reviewed-by: Richard Moe Gustavsen --- src/plugins/platforms/ios/qiosinputcontext.mm | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) (limited to 'src/plugins') diff --git a/src/plugins/platforms/ios/qiosinputcontext.mm b/src/plugins/platforms/ios/qiosinputcontext.mm index 237077400b..050c592aca 100644 --- a/src/plugins/platforms/ios/qiosinputcontext.mm +++ b/src/plugins/platforms/ios/qiosinputcontext.mm @@ -500,23 +500,25 @@ void QIOSInputContext::scrollToCursor() QWindow *focusWindow = qApp->focusWindow(); QRect cursorRect = qApp->inputMethod()->cursorRectangle().translated(focusWindow->geometry().topLeft()).toRect(); - if (cursorRect.isNull()) { - scroll(0); - return; - } - - // Add some padding so that the cusor does not end up directly above the keyboard - static const int kCursorRectPadding = 20; - cursorRect.adjust(0, -kCursorRectPadding, 0, kCursorRectPadding); // We explicitly ask for the geometry of the screen instead of the availableGeometry, - // as we hide the statusbar when scrolling the screen, so the available geometry will + // as we hide the status bar when scrolling the screen, so the available geometry will // include the space taken by the status bar at the moment. QRect screenGeometry = focusWindow->screen()->geometry(); + + if (!cursorRect.isNull()) { + // Add some padding so that the cursor does not end up directly above the keyboard + static const int kCursorRectPadding = 20; + cursorRect.adjust(0, -kCursorRectPadding, 0, kCursorRectPadding); + + // Make sure the cursor rect is still within the screen geometry after padding + cursorRect &= screenGeometry; + } + QRect keyboardGeometry = QRectF::fromCGRect(m_keyboardState.keyboardEndRect).toRect(); QRect availableGeometry = (QRegion(screenGeometry) - keyboardGeometry).boundingRect(); - if (!availableGeometry.contains(cursorRect, true)) { + if (!cursorRect.isNull() && !availableGeometry.contains(cursorRect)) { qImDebug() << "cursor rect" << cursorRect << "not fully within" << availableGeometry; int scrollToCenter = -(availableGeometry.center() - cursorRect.center()).y(); int scrollToBottom = focusWindow->screen()->geometry().bottom() - availableGeometry.bottom(); @@ -528,6 +530,8 @@ void QIOSInputContext::scrollToCursor() void QIOSInputContext::scroll(int y) { + Q_ASSERT(y >= 0); + UIView *rootView = scrollableRootView(); if (!rootView) return; -- cgit v1.2.3 From 495833b7965330cc1db5fdce0a3c86f7ec15e836 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Mon, 11 Dec 2017 15:50:21 +0100 Subject: [ChangeLog][QPA][eglfs] Fix crash when using cursors and multiple GL contexts The hash from QOpenGLContext* to cursor texture/shader data can accumulate dangling pointers if the program uses multiple contexts on the same screen. This is fixed by moving the cursor data into the platform context. The code for deleting the texture and shader program is omitted as it is tied to the life time of the context and the GL context deletes its resources automatically upon destruction. Task-number: QTBUG-65119 Change-Id: Ic3b8e5669d14949af811bdf047e7d47000216180 Reviewed-by: Laszlo Agocs --- src/plugins/platforms/eglfs/api/qeglfscontext_p.h | 3 +++ src/plugins/platforms/eglfs/api/qeglfscursor.cpp | 15 ++++----------- src/plugins/platforms/eglfs/api/qeglfscursor_p.h | 22 ++++++++++------------ 3 files changed, 17 insertions(+), 23 deletions(-) (limited to 'src/plugins') diff --git a/src/plugins/platforms/eglfs/api/qeglfscontext_p.h b/src/plugins/platforms/eglfs/api/qeglfscontext_p.h index 96f7f01381..af8725b6b3 100644 --- a/src/plugins/platforms/eglfs/api/qeglfscontext_p.h +++ b/src/plugins/platforms/eglfs/api/qeglfscontext_p.h @@ -52,6 +52,7 @@ // #include "qeglfsglobal_p.h" +#include "qeglfscursor_p.h" #include #include @@ -68,6 +69,8 @@ public: void runGLChecks() override; void swapBuffers(QPlatformSurface *surface) override; + QEglFSCursorData cursorData; + private: EGLNativeWindowType m_tempWindow; }; diff --git a/src/plugins/platforms/eglfs/api/qeglfscursor.cpp b/src/plugins/platforms/eglfs/api/qeglfscursor.cpp index f46206cab5..22319fcc66 100644 --- a/src/plugins/platforms/eglfs/api/qeglfscursor.cpp +++ b/src/plugins/platforms/eglfs/api/qeglfscursor.cpp @@ -40,10 +40,10 @@ #include "qeglfscursor_p.h" #include "qeglfsintegration_p.h" #include "qeglfsscreen_p.h" +#include "qeglfscontext_p.h" #include #include -#include #include #include #include @@ -115,13 +115,6 @@ void QEglFSCursorDeviceListener::onDeviceListChanged(QInputDeviceManager::Device void QEglFSCursor::resetResources() { - if (QOpenGLContext *ctx = QOpenGLContext::currentContext()) { - GraphicsContextData &gfx(m_gfx[ctx]); - delete gfx.program; - glDeleteTextures(1, &gfx.customCursorTexture); - glDeleteTextures(1, &gfx.atlasTexture); - gfx = GraphicsContextData(); - } m_cursor.customCursorPending = !m_cursor.customCursorImage.isNull(); } @@ -144,8 +137,8 @@ void QEglFSCursor::createShaderPrograms() " gl_FragColor = texture2D(texture, textureCoord).bgra;\n" "}\n"; - GraphicsContextData &gfx(m_gfx[QOpenGLContext::currentContext()]); - gfx.program = new QOpenGLShaderProgram; + QEglFSCursorData &gfx = static_cast(QOpenGLContext::currentContext()->handle())->cursorData; + gfx.program.reset(new QOpenGLShaderProgram); gfx.program->addCacheableShaderFromSourceCode(QOpenGLShader::Vertex, textureVertexProgram); gfx.program->addCacheableShaderFromSourceCode(QOpenGLShader::Fragment, textureFragmentProgram); gfx.program->bindAttributeLocation("vertexCoordEntry", 0); @@ -475,7 +468,7 @@ void QEglFSCursor::draw(const QRectF &r) { StateSaver stateSaver; - GraphicsContextData &gfx(m_gfx[QOpenGLContext::currentContext()]); + QEglFSCursorData &gfx = static_cast(QOpenGLContext::currentContext()->handle())->cursorData; if (!gfx.program) { // one time initialization initializeOpenGLFunctions(); diff --git a/src/plugins/platforms/eglfs/api/qeglfscursor_p.h b/src/plugins/platforms/eglfs/api/qeglfscursor_p.h index aaeb83cb99..89c2e89f58 100644 --- a/src/plugins/platforms/eglfs/api/qeglfscursor_p.h +++ b/src/plugins/platforms/eglfs/api/qeglfscursor_p.h @@ -56,6 +56,7 @@ #include #include #include +#include #include QT_BEGIN_NAMESPACE @@ -81,6 +82,15 @@ private: #if QT_CONFIG(opengl) +struct QEglFSCursorData { + QScopedPointer program; + int textureEntry = 0; + int matEntry = 0; + uint customCursorTexture = 0; + uint atlasTexture = 0; + qint64 customCursorKey = 0; +}; + class Q_EGLFS_EXPORT QEglFSCursor : public QPlatformCursor , protected QOpenGLFunctions { @@ -143,18 +153,6 @@ private: QEglFSCursorDeviceListener *m_deviceListener; bool m_updateRequested; QMatrix4x4 m_rotationMatrix; - - struct GraphicsContextData { - GraphicsContextData() : program(nullptr), textureEntry(0), matEntry(0), - customCursorTexture(0), atlasTexture(0), customCursorKey(0) { } - QOpenGLShaderProgram *program; - int textureEntry; - int matEntry; - uint customCursorTexture; - uint atlasTexture; - qint64 customCursorKey; - }; - QHash m_gfx; }; #endif // QT_CONFIG(opengl) -- cgit v1.2.3 From 280b8b79c0f8a75bf580c76cf61b43061b842aaa Mon Sep 17 00:00:00 2001 From: BogDan Vatra Date: Tue, 28 Nov 2017 14:56:02 +0200 Subject: Allow the users to disable the text handles The user can set QT_QPA_NO_TEXT_HANDLES to 1 to disable the text handles. Change-Id: I974af4d79c86259288035fe20b6a9d0c6d047af8 Reviewed-by: J-P Nurmi --- src/plugins/platforms/android/qandroidinputcontext.cpp | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src/plugins') diff --git a/src/plugins/platforms/android/qandroidinputcontext.cpp b/src/plugins/platforms/android/qandroidinputcontext.cpp index 7fa809f3f8..ccc7f06b6b 100644 --- a/src/plugins/platforms/android/qandroidinputcontext.cpp +++ b/src/plugins/platforms/android/qandroidinputcontext.cpp @@ -526,6 +526,10 @@ void QAndroidInputContext::updateCursorPosition() void QAndroidInputContext::updateSelectionHandles() { + static bool noHandles = qEnvironmentVariableIntValue("QT_QPA_NO_TEXT_HANDLES"); + if (noHandles) + return; + auto im = qGuiApp->inputMethod(); if (!m_focusObject || (m_cursorHandleShown == CursorHandleNotShown)) { // Hide the handles -- cgit v1.2.3 From 141bca90e16073086124e542cdb0b91556fe06c5 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Wed, 6 Dec 2017 10:20:52 +0100 Subject: Windows QPA: Fix handling of override cursors Override cursors were not restored when nested or in a dual monitor setups. The default cursor stored in QWindowsCursor::m_overriddenCursor was clobbered by subsequent calls to QWindowsCursor::setOverrideCursor(). This caused for example the wait cursor to remain active when switching to Help Mode in Qt Creator. Add a check preventing that. Make the variable static so that it is shared between the cursors of multiple screens. Amends b05d1c2ebfebf0f427a92668c0a7b177d0952012. Task-number: QTBUG-65001 Change-Id: Iead5804d317f73dedd78d22c1c85c62b5349ab83 Reviewed-by: Oliver Wolff --- src/plugins/platforms/windows/qwindowscursor.cpp | 6 +++++- src/plugins/platforms/windows/qwindowscursor.h | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) (limited to 'src/plugins') diff --git a/src/plugins/platforms/windows/qwindowscursor.cpp b/src/plugins/platforms/windows/qwindowscursor.cpp index e7ba08b719..1da7de7451 100644 --- a/src/plugins/platforms/windows/qwindowscursor.cpp +++ b/src/plugins/platforms/windows/qwindowscursor.cpp @@ -548,6 +548,8 @@ CursorHandlePtr QWindowsCursor::standardWindowCursor(Qt::CursorShape shape) return it != m_standardCursorCache.end() ? it.value() : CursorHandlePtr(new CursorHandle); } +HCURSOR QWindowsCursor::m_overriddenCursor = nullptr; + /*! \brief Return cached pixmap cursor or create new one. */ @@ -623,7 +625,9 @@ void QWindowsCursor::setOverrideCursor(const QCursor &cursor) { const CursorHandlePtr wcursor = cursorHandle(cursor); if (wcursor->handle()) { - m_overriddenCursor = SetCursor(wcursor->handle()); + const HCURSOR previousCursor = SetCursor(wcursor->handle()); + if (m_overriddenCursor == nullptr) + m_overriddenCursor = previousCursor; } else { qWarning("%s: Unable to obtain system cursor for %d", __FUNCTION__, cursor.shape()); diff --git a/src/plugins/platforms/windows/qwindowscursor.h b/src/plugins/platforms/windows/qwindowscursor.h index 9aa9523ac8..28c7e88a6e 100644 --- a/src/plugins/platforms/windows/qwindowscursor.h +++ b/src/plugins/platforms/windows/qwindowscursor.h @@ -141,7 +141,7 @@ private: mutable QPixmap m_linkDragCursor; mutable QPixmap m_ignoreDragCursor; - HCURSOR m_overriddenCursor = nullptr; + static HCURSOR m_overriddenCursor; }; QT_END_NAMESPACE -- cgit v1.2.3 From 4a4efd5693d42a0d5ece0fb166357b0255cb205d Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Fri, 24 Nov 2017 08:46:18 +0100 Subject: qwindowsopengltester.cpp: Fix -Wclazy-strict-iterators Change-Id: Id22096197aa5bf406ea1f072e8b5ca2a90578eec Reviewed-by: Oliver Wolff --- src/plugins/platforms/windows/qwindowsopengltester.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/plugins') diff --git a/src/plugins/platforms/windows/qwindowsopengltester.cpp b/src/plugins/platforms/windows/qwindowsopengltester.cpp index 5283d6b260..a511cc6164 100644 --- a/src/plugins/platforms/windows/qwindowsopengltester.cpp +++ b/src/plugins/platforms/windows/qwindowsopengltester.cpp @@ -214,7 +214,7 @@ QWindowsOpenGLTester::Renderers QWindowsOpenGLTester::detectSupportedRenderers(c #else QOpenGLConfig::Gpu qgpu = QOpenGLConfig::Gpu::fromDevice(gpu.vendorId, gpu.deviceId, gpu.driverVersion, gpu.description); SupportedRenderersCache *srCache = supportedRenderersCache(); - SupportedRenderersCache::const_iterator it = srCache->find(qgpu); + SupportedRenderersCache::const_iterator it = srCache->constFind(qgpu); if (it != srCache->cend()) return *it; -- cgit v1.2.3 From ba44cdae38406c429c7fb43863a6883bd0f79cf5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Fri, 1 Dec 2017 19:03:05 +0100 Subject: Teach QPlatformWindow about safe area margins and implement for iOS The safe area margins of a window represent the area that is safe to place content within, without intersecting areas of the screen where system UI is placed, or where a screen bezel may cover the content. QWidget will incorporate the safe area margins into its contents margins, so that they are are never smaller than the safe area margins. This can be disabled by unsetting the Qt::WA_ContentsMarginsRespectsSafeArea widget attribute, which is set by default. QLayouts will automatically use the contents area of a widget for their layout, unless the Qt::WA_LayoutOnEntireRect attribute has been set. This can be used, along with a contents margin of 0 on the actual layout, to allow e.g. a background image to underlay the status bar and other system areas on an iOS device, while still allowing child widgets of that background to be inset based on the safe area. [ChangeLog][iOS/tvOS] Qt will now take the safe area margins of the device into account when computing layouts for QtWidgets. Change-Id: Ife3827ab663f0625c1451e75b14fb8eeffb00754 Reviewed-by: Richard Moe Gustavsen --- src/plugins/platforms/ios/qioswindow.h | 2 ++ src/plugins/platforms/ios/qioswindow.mm | 7 ++++++ src/plugins/platforms/ios/quiview.mm | 39 +++++++++++++++++++++++++++++++++ 3 files changed, 48 insertions(+) (limited to 'src/plugins') diff --git a/src/plugins/platforms/ios/qioswindow.h b/src/plugins/platforms/ios/qioswindow.h index 81fad420f6..85c60f61df 100644 --- a/src/plugins/platforms/ios/qioswindow.h +++ b/src/plugins/platforms/ios/qioswindow.h @@ -71,6 +71,8 @@ public: bool isExposed() const Q_DECL_OVERRIDE; void propagateSizeHints() Q_DECL_OVERRIDE {} + QMargins safeAreaMargins() const override; + void raise() Q_DECL_OVERRIDE{ raiseOrLower(true); } void lower() Q_DECL_OVERRIDE { raiseOrLower(false); } diff --git a/src/plugins/platforms/ios/qioswindow.mm b/src/plugins/platforms/ios/qioswindow.mm index e934cb90fa..4ce73d7b5d 100644 --- a/src/plugins/platforms/ios/qioswindow.mm +++ b/src/plugins/platforms/ios/qioswindow.mm @@ -223,6 +223,13 @@ void QIOSWindow::applyGeometry(const QRect &rect) [m_view layoutIfNeeded]; } +QMargins QIOSWindow::safeAreaMargins() const +{ + UIEdgeInsets safeAreaInsets = m_view.qt_safeAreaInsets; + return QMargins(safeAreaInsets.left, safeAreaInsets.top, + safeAreaInsets.right, safeAreaInsets.bottom); +} + bool QIOSWindow::isExposed() const { return qApp->applicationState() != Qt::ApplicationSuspended diff --git a/src/plugins/platforms/ios/quiview.mm b/src/plugins/platforms/ios/quiview.mm index 1dbacad6e7..ed8af8e290 100644 --- a/src/plugins/platforms/ios/quiview.mm +++ b/src/plugins/platforms/ios/quiview.mm @@ -56,6 +56,24 @@ @implementation QUIView ++ (void)load +{ + if (QOperatingSystemVersion::current() < QOperatingSystemVersion(QOperatingSystemVersion::IOS, 11)) { + // iOS 11 handles this though [UIView safeAreaInsetsDidChange], but there's no signal for + // the corresponding top and bottom layout guides that we use on earlier versions. Note + // that we use the _will_ change version of the notification, because we want to react + // to the change as early was possible. But since the top and bottom layout guides have + // not been updated at this point we use asynchronous delivery of the event, so that the + // event is processed by QtGui just after iOS has updated the layout margins. + [[NSNotificationCenter defaultCenter] addObserverForName:UIApplicationWillChangeStatusBarFrameNotification + object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *) { + for (QWindow *window : QGuiApplication::allWindows()) + QWindowSystemInterface::handleSafeAreaMarginsChanged(window); + } + ]; + } +} + + (Class)layerClass { return [CAEAGLLayer class]; @@ -100,6 +118,22 @@ self.layer.borderColor = colorWithBrightness(1.0); self.layer.borderWidth = 1.0; } + +#if QT_DARWIN_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_NA, 110000, 110000, __WATCHOS_NA) + if (qEnvironmentVariableIsSet("QT_IOS_DEBUG_WINDOW_SAFE_AREAS")) { + if (__builtin_available(iOS 11, tvOS 11, *)) { + UIView *safeAreaOverlay = [[UIView alloc] initWithFrame:CGRectZero]; + [safeAreaOverlay setBackgroundColor:[UIColor colorWithRed:0.3 green:0.7 blue:0.9 alpha:0.3]]; + [self addSubview:safeAreaOverlay]; + + safeAreaOverlay.translatesAutoresizingMaskIntoConstraints = NO; + [safeAreaOverlay.topAnchor constraintEqualToAnchor:self.safeAreaLayoutGuide.topAnchor].active = YES; + [safeAreaOverlay.leftAnchor constraintEqualToAnchor:self.safeAreaLayoutGuide.leftAnchor].active = YES; + [safeAreaOverlay.rightAnchor constraintEqualToAnchor:self.safeAreaLayoutGuide.rightAnchor].active = YES; + [safeAreaOverlay.bottomAnchor constraintEqualToAnchor:self.safeAreaLayoutGuide.bottomAnchor].active = YES; + } + } +#endif } return self; @@ -203,6 +237,11 @@ QWindowSystemInterface::handleExposeEvent(m_qioswindow->window(), region); } +- (void)safeAreaInsetsDidChange +{ + QWindowSystemInterface::handleSafeAreaMarginsChanged(m_qioswindow->window()); +} + // ------------------------------------------------------------------------- - (BOOL)canBecomeFirstResponder -- cgit v1.2.3 From 9dc7904556a261e9373bebc9060de62fcdab52a3 Mon Sep 17 00:00:00 2001 From: Gatis Paeglis Date: Mon, 11 Dec 2017 09:55:53 +0100 Subject: xcb: update libXi version requirement in the README file ... from 1.7.4 to 1.7.5 (released Sep, 2015). Some more locking issues were fixed after 1.7.4. Testing for a prolonged period of time has showed that 1.7.5 does not cause a system lock-up. [ChangeLog][Platform Specific Changes][X11 / XCB] Minimal libXi version requirement has been updated from 1.7.4 to 1.7.5. This is because XIAllowTouchEvents is known to deadlock with libXi 1.7.4 and earlier. When touch events are never received, this is not an issue. Plain mouse / keyboard systems are not affected. Task-number: QTBUG-62224 Change-Id: Ie70264b9af0390df33c417f660350d4bce48c6d3 Reviewed-by: Laszlo Agocs --- src/plugins/platforms/xcb/README | 3 +-- src/plugins/platforms/xcb/qxcbconnection_xi2.cpp | 5 +++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'src/plugins') diff --git a/src/plugins/platforms/xcb/README b/src/plugins/platforms/xcb/README index 5efc9b7f99..8308db46dc 100644 --- a/src/plugins/platforms/xcb/README +++ b/src/plugins/platforms/xcb/README @@ -25,9 +25,8 @@ This should allow for binaries that are portable across most modern Linux distri PACKAGE VERSION REQUIREMENTS When using touch input via XInput 2.2 or higher, there is a potential issue on systems that ship with -a libXi older than 1.7.4. This is because XIAllowTouchEvents can deadlock with libXi 1.7.3 and earlier. +a libXi older than 1.7.5. This is because XIAllowTouchEvents can deadlock with libXi 1.7.4 and earlier. When touch events are never received, this is not an issue, so plain mouse/keyboard systems are not affected. -See http://lists.x.org/archives/xorg-devel/2014-July/043059.html for details on the libXi patch. Qt versions before 5.8 attempted to recognize this scenario based on the pkg-config package version and skip the call. This has been removed starting from 5.8 since relying on pkg-config package versions is unsafe given that Qt must also support systems with limited or incomplete pkg-config setups. diff --git a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp index 26a9ba8d26..d1d97affe8 100644 --- a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp +++ b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp @@ -700,8 +700,9 @@ void QXcbConnection::xi2ProcessTouch(void *xiDevEvent, QXcbWindow *platformWindo // Touches must be accepted when we are grabbing touch events. Otherwise the entire sequence // will get replayed when the grab ends. if (m_xiGrab) { - // XIAllowTouchEvents deadlocks with libXi < 1.7.4 (this has nothing to do with the XI2 versions like 2.2) - // http://lists.x.org/archives/xorg-devel/2014-July/043059.html + // Note that XIAllowTouchEvents is known to deadlock with older libXi versions, + // for details see qtbase/src/plugins/platforms/xcb/README. This has nothing to + // do with the XInput protocol version, but is a bug in libXi implementation instead. XIAllowTouchEvents(static_cast(m_xlib_display), xiDeviceEvent->deviceid, xiDeviceEvent->detail, xiDeviceEvent->event, XIAcceptTouch); } -- cgit v1.2.3 From e739e984c3006ed2e88ef8f087455116cf9c4ebb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Morten=20Johan=20S=C3=B8rvig?= Date: Mon, 7 Aug 2017 19:54:41 +0200 Subject: macOS: Make retina OpenGL work on VMware MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Qt requests full resolution OpenGL surfaces by default. However, when running as a VMware guest it looks like the OS silently creates low-resolution surfaces. This is not possible to detect using the standard NSWindow APIs for converting to backing coordinates or for reading the backing scale factor. The result of this is that Qt will incorrectly display one quarter of the window content only. Fall back to detecting if the OpenGL renderer is the Apple software renderer, which it will be on VMware. Cancel the high-resolution surface request if this is the case. This needs to be done while we have a valid OpenGL context. Task-number: QTBUG-62357 Change-Id: I33bf12b3bb0408249e6d66e0a8ca86b044bea781 Reviewed-by: Tor Arne Vestbø --- src/plugins/platforms/cocoa/qcocoaglcontext.h | 1 + src/plugins/platforms/cocoa/qcocoaglcontext.mm | 19 ++++++++++++++++++- src/plugins/platforms/cocoa/qcocoawindow.mm | 1 + 3 files changed, 20 insertions(+), 1 deletion(-) (limited to 'src/plugins') diff --git a/src/plugins/platforms/cocoa/qcocoaglcontext.h b/src/plugins/platforms/cocoa/qcocoaglcontext.h index 1a66cec0e3..732b50d29e 100644 --- a/src/plugins/platforms/cocoa/qcocoaglcontext.h +++ b/src/plugins/platforms/cocoa/qcocoaglcontext.h @@ -84,6 +84,7 @@ private: NSOpenGLContext *m_shareContext; QSurfaceFormat m_format; QPointer m_currentWindow; + bool m_didCheckForSoftwareContext; }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/cocoa/qcocoaglcontext.mm b/src/plugins/platforms/cocoa/qcocoaglcontext.mm index be5029b7e0..b656025ec7 100644 --- a/src/plugins/platforms/cocoa/qcocoaglcontext.mm +++ b/src/plugins/platforms/cocoa/qcocoaglcontext.mm @@ -121,7 +121,8 @@ QCocoaGLContext::QCocoaGLContext(const QSurfaceFormat &format, QPlatformOpenGLCo const QVariant &nativeHandle) : m_context(nil), m_shareContext(nil), - m_format(format) + m_format(format), + m_didCheckForSoftwareContext(false) { if (!nativeHandle.isNull()) { if (!nativeHandle.canConvert()) { @@ -262,6 +263,22 @@ bool QCocoaGLContext::makeCurrent(QPlatformSurface *surface) QWindow *window = static_cast(surface)->window(); setActiveWindow(window); + + // Disable high-resolution surfaces when using the software renderer, which has the + // problem that the system silently falls back to a to using a low-resolution buffer + // when a high-resolution buffer is requested. This is not detectable using the NSWindow + // convertSizeToBacking and backingScaleFactor APIs. A typical result of this is that Qt + // will display a quarter of the window content when running in a virtual machine. + if (!m_didCheckForSoftwareContext) { + m_didCheckForSoftwareContext = true; + + const GLubyte* renderer = glGetString(GL_RENDERER); + if (qstrcmp((const char *)renderer, "Apple Software Renderer") == 0) { + NSView *view = static_cast(surface)->m_view; + [view setWantsBestResolutionOpenGLSurface:NO]; + } + } + update(); return true; } diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm index d1f19f2de9..e86cc2d955 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.mm +++ b/src/plugins/platforms/cocoa/qcocoawindow.mm @@ -198,6 +198,7 @@ void QCocoaWindow::initialize() BOOL enable = qt_mac_resolveOption(YES, window(), "_q_mac_wantsBestResolutionOpenGLSurface", "QT_MAC_WANTS_BEST_RESOLUTION_OPENGL_SURFACE"); [m_view setWantsBestResolutionOpenGLSurface:enable]; + // See also QCocoaGLContext::makeCurrent for software renderer workarounds. } BOOL enable = qt_mac_resolveOption(NO, window(), "_q_mac_wantsLayer", "QT_MAC_WANTS_LAYER"); -- cgit v1.2.3 From 034e92b0f4f49432e170184fb84e29c315d3f279 Mon Sep 17 00:00:00 2001 From: Johan Klokkhammer Helsing Date: Thu, 14 Dec 2017 13:15:05 +0100 Subject: Android: Set correct input hints when queried through getCursorCapsMode getCursorCapsMode() now matches the Java implementation in QtActivityDelegate.showSoftwareKeyboard() which is given to the Android keyboard on InputConnection creation. The reason we only saw this bug with some Android keyboards was that many keyboards never call getCursorCapsMode and just rely on the initial hints. Task-number: QTBUG-51865 Change-Id: I2aae024d9c77ea14e087e3f51a413d15a684179c Reviewed-by: Paul Olav Tvete Reviewed-by: Christian Stromme --- src/plugins/platforms/android/qandroidinputcontext.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/plugins') diff --git a/src/plugins/platforms/android/qandroidinputcontext.cpp b/src/plugins/platforms/android/qandroidinputcontext.cpp index ccc7f06b6b..fe4c5be4cb 100644 --- a/src/plugins/platforms/android/qandroidinputcontext.cpp +++ b/src/plugins/platforms/android/qandroidinputcontext.cpp @@ -847,11 +847,11 @@ jint QAndroidInputContext::getCursorCapsMode(jint /*reqModes*/) const uint qtInputMethodHints = query->value(Qt::ImHints).toUInt(); - if (qtInputMethodHints & Qt::ImhPreferUppercase) - res = CAP_MODE_SENTENCES; + if (!(qtInputMethodHints & Qt::ImhLowercaseOnly) && !(qtInputMethodHints & Qt::ImhNoAutoUppercase)) + res |= CAP_MODE_SENTENCES; if (qtInputMethodHints & Qt::ImhUppercaseOnly) - res = CAP_MODE_CHARACTERS; + res |= CAP_MODE_CHARACTERS; return res; } -- cgit v1.2.3 From dffa01a438f971089f6609bc8c2406ca19fba724 Mon Sep 17 00:00:00 2001 From: Timo Aarnipuro Date: Tue, 21 Nov 2017 13:09:09 +0200 Subject: Add EGLFS integration plugin for Salvator-X on INTEGRITY Multivisor This plugin uses the Renesas RISP Window Manager. Change-Id: If813c46ab8d39e966c0a969610841867885dd473 Reviewed-by: Laszlo Agocs --- .../eglfs/deviceintegration/deviceintegration.pro | 1 + .../deviceintegration/eglfs_rcar/eglfs_rcar.json | 3 + .../deviceintegration/eglfs_rcar/eglfs_rcar.pro | 19 +++ .../eglfs_rcar/qeglfsrcarintegration.cpp | 159 +++++++++++++++++++++ .../eglfs_rcar/qeglfsrcarintegration.h | 66 +++++++++ .../eglfs_rcar/qeglfsrcarmain.cpp | 57 ++++++++ 6 files changed, 305 insertions(+) create mode 100644 src/plugins/platforms/eglfs/deviceintegration/eglfs_rcar/eglfs_rcar.json create mode 100644 src/plugins/platforms/eglfs/deviceintegration/eglfs_rcar/eglfs_rcar.pro create mode 100644 src/plugins/platforms/eglfs/deviceintegration/eglfs_rcar/qeglfsrcarintegration.cpp create mode 100644 src/plugins/platforms/eglfs/deviceintegration/eglfs_rcar/qeglfsrcarintegration.h create mode 100644 src/plugins/platforms/eglfs/deviceintegration/eglfs_rcar/qeglfsrcarmain.cpp (limited to 'src/plugins') diff --git a/src/plugins/platforms/eglfs/deviceintegration/deviceintegration.pro b/src/plugins/platforms/eglfs/deviceintegration/deviceintegration.pro index 2cddbe9beb..92ee83fd8f 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/deviceintegration.pro +++ b/src/plugins/platforms/eglfs/deviceintegration/deviceintegration.pro @@ -7,6 +7,7 @@ qtConfig(eglfs_egldevice): SUBDIRS *= eglfs_kms_support eglfs_kms_egldevice qtConfig(eglfs_brcm): SUBDIRS += eglfs_brcm qtConfig(eglfs_mali): SUBDIRS += eglfs_mali qtConfig(eglfs_viv): SUBDIRS += eglfs_viv +qtConfig(eglfs_rcar): SUBDIRS += eglfs_rcar qtConfig(eglfs_viv_wl): SUBDIRS += eglfs_viv_wl qtConfig(eglfs_openwfd): SUBDIRS += eglfs_openwfd qtConfig(opengl): SUBDIRS += eglfs_emu diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_rcar/eglfs_rcar.json b/src/plugins/platforms/eglfs/deviceintegration/eglfs_rcar/eglfs_rcar.json new file mode 100644 index 0000000000..77b3083eef --- /dev/null +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_rcar/eglfs_rcar.json @@ -0,0 +1,3 @@ +{ + "Keys": [ "eglfs_rcar" ] +} diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_rcar/eglfs_rcar.pro b/src/plugins/platforms/eglfs/deviceintegration/eglfs_rcar/eglfs_rcar.pro new file mode 100644 index 0000000000..04236449a0 --- /dev/null +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_rcar/eglfs_rcar.pro @@ -0,0 +1,19 @@ +TARGET = qeglfs-rcar-integration + +QT += core-private gui-private eglfsdeviceintegration-private + +INCLUDEPATH += $$PWD/../../api +CONFIG += egl +DEFINES += LINUX=1 EGL_API_FB=1 +QMAKE_LFLAGS += $$QMAKE_LFLAGS_NOUNDEF + +SOURCES += $$PWD/qeglfsrcarmain.cpp \ + $$PWD/qeglfsrcarintegration.cpp + +HEADERS += $$PWD/qeglfsrcarintegration.h + +OTHER_FILES += $$PWD/eglfs_rcar.json + +PLUGIN_TYPE = egldeviceintegrations +PLUGIN_CLASS_NAME = QEglFSRcarIntegrationPlugin +load(qt_plugin) diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_rcar/qeglfsrcarintegration.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_rcar/qeglfsrcarintegration.cpp new file mode 100644 index 0000000000..98cf1d3bfb --- /dev/null +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_rcar/qeglfsrcarintegration.cpp @@ -0,0 +1,159 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include +#include +#include "INTEGRITY.h" +#include "qeglfsrcarintegration.h" + +#define RCAR_DEFAULT_DISPLAY 1 +#define RCAR_DEFAULT_WM_LAYER 2 + +extern "C" unsigned long PVRGrfxServerInit(void); + +QT_BEGIN_NAMESPACE + +void QEglFSRcarIntegration::platformInit() +{ + QEglFSDeviceIntegration::platformInit(); + + PVRGrfxServerInit(); + + mScreenSize = q_screenSizeFromFb(0); + mNativeDisplay = (NativeDisplayType)EGL_DEFAULT_DISPLAY; +} + +QSize QEglFSRcarIntegration::screenSize() const +{ + return mScreenSize; +} + +EGLNativeDisplayType QEglFSRcarIntegration::platformDisplay() const +{ + return mNativeDisplay; +} + +static r_wm_WinColorFmt_t getWMColorFormat(const QSurfaceFormat &format) +{ + const int a = format.alphaBufferSize(); + const int r = format.redBufferSize(); + const int g = format.greenBufferSize(); + const int b = format.blueBufferSize(); + + switch (r) { + case 4: + if (g == 4 && b == 4 && a == 4) + return R_WM_COLORFMT_ARGB4444; + break; + case 5: + if (g == 6 && b == 5 && a == 0) + return R_WM_COLORFMT_RGB565; + else if (g == 5 && b == 5 && a == 1) + return R_WM_COLORFMT_ARGB1555; + break; + case 8: + if (g == 8 && b == 8 && a == 0) + return R_WM_COLORFMT_RGB0888; + else if (g == 8 && b == 8 && a == 8) + return R_WM_COLORFMT_ARGB8888; + break; + } + + qFatal("Unsupported color format: R:%d G:%d B:%d A:%d", r, g, b, a); + return R_WM_COLORFMT_LAST; +} + +EGLNativeWindowType QEglFSRcarIntegration::createNativeWindow(QPlatformWindow *window, const QSize &size, const QSurfaceFormat &format) +{ + bool ok; + + mNativeDisplayID = qEnvironmentVariableIntValue("QT_QPA_WM_DISP_ID", &ok); + if (!ok) + mNativeDisplayID = RCAR_DEFAULT_DISPLAY; + + r_wm_Error_t wm_err = R_WM_DevInit(mNativeDisplayID); + if (wm_err != R_WM_ERR_OK) + qFatal("Failed to init WM Dev: %d, error: %d", mNativeDisplayID, wm_err); + + mNativeWindow = (EGLNativeWindowTypeREL*)malloc(sizeof(EGLNativeWindowTypeREL)); + memset(mNativeWindow, 0, sizeof(EGLNativeWindowTypeREL)); + + mNativeWindow->ColorFmt = getWMColorFormat(format); + mNativeWindow->PosX = 0; + mNativeWindow->PosY = 0; + mNativeWindow->PosZ = qEnvironmentVariableIntValue("QT_QPA_WM_LAYER", &ok); + if (!ok) + mNativeWindow->PosZ = RCAR_DEFAULT_WM_LAYER; + mNativeWindow->Pitch = size.width(); + mNativeWindow->Width = size.width(); + mNativeWindow->Height = size.height(); + mNativeWindow->Alpha = format.alphaBufferSize(); + + if (format.swapBehavior() == QSurfaceFormat::DefaultSwapBehavior) + mNativeWindow->Surface.BufNum = 3; + else + mNativeWindow->Surface.BufNum = format.swapBehavior(); + + mNativeWindow->Surface.Type = R_WM_SURFACE_FB; + mNativeWindow->Surface.BufMode = R_WM_WINBUF_ALLOC_INTERNAL; + + wm_err = R_WM_WindowCreate(mNativeDisplayID, mNativeWindow); + if (wm_err != R_WM_ERR_OK) + qFatal("Failed to create window layer: %d", wm_err); + wm_err = R_WM_DevEventRegister(mNativeDisplayID, R_WM_EVENT_VBLANK, 0); + if (wm_err != R_WM_ERR_OK) + qFatal("Failed to Register vsync event: %d", wm_err); + wm_err = R_WM_WindowEnable(mNativeDisplayID, mNativeWindow); + if (wm_err != R_WM_ERR_OK) + qFatal("Failed to Enable window surface: %d", wm_err); + + return static_cast(mNativeWindow); +} + +void QEglFSRcarIntegration::destroyNativeWindow(EGLNativeWindowType window) +{ + R_WM_WindowDisable(mNativeDisplayID, mNativeWindow); + usleep(100000); //Needed to allow Window Manager make the window transparent + R_WM_WindowDelete(mNativeDisplayID, mNativeWindow); + R_WM_DevDeinit(mNativeDisplayID); + free(mNativeWindow); +} + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_rcar/qeglfsrcarintegration.h b/src/plugins/platforms/eglfs/deviceintegration/eglfs_rcar/qeglfsrcarintegration.h new file mode 100644 index 0000000000..08911594f9 --- /dev/null +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_rcar/qeglfsrcarintegration.h @@ -0,0 +1,66 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QEGLFSVIVINTEGRATION_H +#define QEGLFSVIVINTEGRATION_H + +#include "private/qeglfsdeviceintegration_p.h" +#include "EGL/eglext_REL.h" + +QT_BEGIN_NAMESPACE + +class QEglFSRcarIntegration : public QEglFSDeviceIntegration +{ +public: + void platformInit() override; + QSize screenSize() const override; + EGLNativeWindowType createNativeWindow(QPlatformWindow *window, const QSize &size, const QSurfaceFormat &format) override; + void destroyNativeWindow(EGLNativeWindowType window) override; + EGLNativeDisplayType platformDisplay() const override; + +private: + QSize mScreenSize; + EGLNativeDisplayType mNativeDisplay; + EGLNativeWindowTypeREL *mNativeWindow; + int mNativeDisplayID; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_rcar/qeglfsrcarmain.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_rcar/qeglfsrcarmain.cpp new file mode 100644 index 0000000000..6cf3e1387d --- /dev/null +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_rcar/qeglfsrcarmain.cpp @@ -0,0 +1,57 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "INTEGRITY.h" +#include "private/qeglfsdeviceintegration_p.h" +#include "qeglfsrcarintegration.h" + +QT_BEGIN_NAMESPACE + +class QEglFSRcarIntegrationPlugin : public QEglFSDeviceIntegrationPlugin +{ + Q_OBJECT + Q_PLUGIN_METADATA(IID QEglFSDeviceIntegrationFactoryInterface_iid FILE "eglfs_rcar.json") + +public: + QEglFSDeviceIntegration *create() override { return new QEglFSRcarIntegration; } +}; + +QT_END_NAMESPACE + +#include "qeglfsrcarmain.moc" -- cgit v1.2.3 From c10f2aaeb77c3da609be0f7d88ed6641a256953d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Morten=20Johan=20S=C3=B8rvig?= Date: Mon, 11 Dec 2017 10:18:44 +0100 Subject: Disable WiFi bearer plugins on macOS and Windows Scanning for WiFi networks is causing network disruptions in the form of higher latency, sometimes globally for all running applications. In practice, the default configuration selection algorithm in QNetworkConfigurationManager prefers configurations from the generic bearer plugin, due to the way the plugins are ordered. Removing the platform WiFi bearers should have no effect on default network configuration selection. Task-number: QTBUG-40332 Change-Id: I778281c41a1aaec1949c220a9266677bd788a57a Reviewed-by: Timur Pocheptsov --- src/plugins/bearer/bearer.pro | 5 ----- 1 file changed, 5 deletions(-) (limited to 'src/plugins') diff --git a/src/plugins/bearer/bearer.pro b/src/plugins/bearer/bearer.pro index b362722b28..824fd0388f 100644 --- a/src/plugins/bearer/bearer.pro +++ b/src/plugins/bearer/bearer.pro @@ -6,11 +6,6 @@ QT_FOR_CONFIG += network-private SUBDIRS += connman networkmanager } -#win32:SUBDIRS += nla -win32:SUBDIRS += generic -win32:!winrt: SUBDIRS += nativewifi -darwin:qtConfig(corewlan): SUBDIRS += corewlan -mac:SUBDIRS += generic android:SUBDIRS += android isEmpty(SUBDIRS):SUBDIRS = generic -- cgit v1.2.3 From bcef582b6f0f851b0d3985decc92eefb820ddf46 Mon Sep 17 00:00:00 2001 From: Lorn Potter Date: Wed, 8 Nov 2017 11:30:01 +1000 Subject: Fix scan reply dbus signature in connman bearer backend Task-number: QTBUG-57844 Change-Id: I1f3035f32d213ec6da95650a946c17c64becf549 Reviewed-by: Sami Nurmenniemi Reviewed-by: Lorn Potter --- src/plugins/bearer/connman/qconnmanservice_linux.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/plugins') diff --git a/src/plugins/bearer/connman/qconnmanservice_linux.cpp b/src/plugins/bearer/connman/qconnmanservice_linux.cpp index 55eec57270..7c9db4640b 100644 --- a/src/plugins/bearer/connman/qconnmanservice_linux.cpp +++ b/src/plugins/bearer/connman/qconnmanservice_linux.cpp @@ -506,7 +506,7 @@ void QConnmanTechnologyInterface::scan() void QConnmanTechnologyInterface::scanReply(QDBusPendingCallWatcher *call) { - QDBusPendingReply props_reply = *call; + QDBusPendingReply<> props_reply = *call; if (props_reply.isError()) { qDebug() << props_reply.error().message(); } -- cgit v1.2.3 From d04187b6a17c16cc455a330fd3e3350016dcc889 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Tue, 12 Dec 2017 09:23:04 +0100 Subject: Windows QPA: Check validity of device when handling tablet leave Huion GT-191 has been observed to send spurious leave events. Amends 127483b5e30de6c1905ea3280dd45a0b7d6a3813. Task-number: QTBUG-65120 Change-Id: I5dfa003a71be137a7b40cc9c27d7cf2cada6922d Reviewed-by: Shawn Rutledge Reviewed-by: Oliver Wolff --- src/plugins/platforms/windows/qwindowstabletsupport.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/plugins') diff --git a/src/plugins/platforms/windows/qwindowstabletsupport.cpp b/src/plugins/platforms/windows/qwindowstabletsupport.cpp index fba4e8f386..5fdc664603 100644 --- a/src/plugins/platforms/windows/qwindowstabletsupport.cpp +++ b/src/plugins/platforms/windows/qwindowstabletsupport.cpp @@ -355,6 +355,8 @@ bool QWindowsTabletSupport::translateTabletProximityEvent(WPARAM /* wParam */, L if (!LOWORD(lParam)) { qCDebug(lcQpaTablet) << "leave proximity for device #" << m_currentDevice; + if (m_currentDevice < 0 || m_currentDevice >= m_devices.size()) // QTBUG-65120, spurious leave observed + return false; if (totalPacks > 0) { QWindowSystemInterface::handleTabletLeaveProximityEvent(proximityBuffer[0].pkTime, m_devices.at(m_currentDevice).currentDevice, -- cgit v1.2.3 From 3af9d774316ef0edf65acb478871d89231b930f2 Mon Sep 17 00:00:00 2001 From: Karim Pinter Date: Fri, 15 Dec 2017 12:56:47 +0200 Subject: Fix pps and imf support for QNX builds Change from config to feature in the json and pro files. Change-Id: I58ddac3c4ad739253bae010f1d5023fc1d481047 Reviewed-by: Oswald Buddenhagen --- src/plugins/platforms/qnx/qnx.pro | 20 +++++++++--------- src/plugins/platforms/qnx/qqnxintegration.cpp | 29 +++++++++++++-------------- src/plugins/platforms/qnx/qqnxintegration.h | 8 ++++---- 3 files changed, 28 insertions(+), 29 deletions(-) (limited to 'src/plugins') diff --git a/src/plugins/platforms/qnx/qnx.pro b/src/plugins/platforms/qnx/qnx.pro index 34be6d582e..15d33200e5 100644 --- a/src/plugins/platforms/qnx/qnx.pro +++ b/src/plugins/platforms/qnx/qnx.pro @@ -81,26 +81,26 @@ qtConfig(opengles2) { QMAKE_USE += opengl_es2 egl } -CONFIG(qqnx_pps) { - DEFINES += QQNX_PPS - - SOURCES += qqnxclipboard.cpp \ - qqnxbuttoneventnotifier.cpp \ +qtConfig(qqnx_pps) { + SOURCES += qqnxbuttoneventnotifier.cpp \ qqnxnavigatorpps.cpp \ qqnxnavigatoreventnotifier.cpp \ qqnxvirtualkeyboardpps.cpp - HEADERS += qqnxclipboard.h \ - qqnxbuttoneventnotifier.h \ + HEADERS += qqnxbuttoneventnotifier.h \ qqnxnavigatorpps.h \ qqnxnavigatoreventnotifier.h \ qqnxvirtualkeyboardpps.h QMAKE_USE += pps - !contains(DEFINES, QT_NO_CLIPBOARD): LIBS += -lclipboard - CONFIG(qqnx_imf) { - DEFINES += QQNX_IMF + qtConfig(clipboard) { + SOURCES += qqnxclipboard.cpp + HEADERS += qqnxclipboard.h + LIBS += -lclipboard + } + + qtConfig(qqnx_imf) { HEADERS += qqnxinputcontext_imf.h SOURCES += qqnxinputcontext_imf.cpp } else { diff --git a/src/plugins/platforms/qnx/qqnxintegration.cpp b/src/plugins/platforms/qnx/qqnxintegration.cpp index eee0581709..072510e052 100644 --- a/src/plugins/platforms/qnx/qqnxintegration.cpp +++ b/src/plugins/platforms/qnx/qqnxintegration.cpp @@ -56,17 +56,16 @@ #include "qqnxeglwindow.h" #endif -#if defined(QQNX_PPS) +#if QT_CONFIG(qqnx_pps) #include "qqnxnavigatorpps.h" #include "qqnxnavigatoreventnotifier.h" #include "qqnxvirtualkeyboardpps.h" #endif -#if defined(QQNX_PPS) +#if QT_CONFIG(qqnx_pps) # include "qqnxbuttoneventnotifier.h" # include "qqnxclipboard.h" - -# if defined(QQNX_IMF) +# if QT_CONFIG(qqnx_imf) # include "qqnxinputcontext_imf.h" # else # include "qqnxinputcontext_noimf.h" @@ -126,7 +125,7 @@ QQnxIntegration::QQnxIntegration(const QStringList ¶mList) , m_screenEventThread(0) , m_navigatorEventHandler(new QQnxNavigatorEventHandler()) , m_virtualKeyboard(0) -#if defined(QQNX_PPS) +#if QT_CONFIG(qqnx_pps) , m_navigatorEventNotifier(0) , m_inputContext(0) , m_buttonsNotifier(new QQnxButtonEventNotifier()) @@ -150,7 +149,7 @@ QQnxIntegration::QQnxIntegration(const QStringList ¶mList) Q_SCREEN_CRITICALERROR(screen_create_context(&ms_screenContext, SCREEN_APPLICATION_CONTEXT), "Failed to create screen context"); -#if defined(QQNX_PPS) +#if QT_CONFIG(qqnx_pps) // Create/start navigator event notifier m_navigatorEventNotifier = new QQnxNavigatorEventNotifier(m_navigatorEventHandler); @@ -168,7 +167,7 @@ QQnxIntegration::QQnxIntegration(const QStringList ¶mList) m_screenEventThread = new QQnxScreenEventThread(ms_screenContext, m_screenEventHandler); m_screenEventThread->start(); -#if defined(QQNX_PPS) +#if QT_CONFIG(qqnx_pps) // Create/start the keyboard class. m_virtualKeyboard = new QQnxVirtualKeyboardPps(); @@ -177,7 +176,7 @@ QQnxIntegration::QQnxIntegration(const QStringList ¶mList) QMetaObject::invokeMethod(m_virtualKeyboard, "start", Qt::QueuedConnection); #endif -#if defined(QQNX_PPS) +#if QT_CONFIG(qqnx_pps) m_navigator = new QQnxNavigatorPps(); #endif @@ -192,16 +191,16 @@ QQnxIntegration::QQnxIntegration(const QStringList ¶mList) QObject::connect(m_virtualKeyboard, SIGNAL(heightChanged(int)), primaryDisplay(), SLOT(keyboardHeightChanged(int))); -#if defined(QQNX_PPS) +#if QT_CONFIG(qqnx_pps) // Set up the input context m_inputContext = new QQnxInputContext(this, *m_virtualKeyboard); -#if defined(QQNX_IMF) +#if QT_CONFIG(qqnx_imf) m_screenEventHandler->addScreenEventFilter(m_inputContext); #endif #endif } -#if defined(QQNX_PPS) +#if QT_CONFIG(qqnx_pps) // delay invocation of start() to the time the event loop is up and running // needed to have the QThread internals of the main thread properly initialized QMetaObject::invokeMethod(m_buttonsNotifier, "start", Qt::QueuedConnection); @@ -224,7 +223,7 @@ QQnxIntegration::~QQnxIntegration() #endif // Stop/destroy navigator event notifier -#if defined(QQNX_PPS) +#if QT_CONFIG(qqnx_pps) delete m_navigatorEventNotifier; #endif delete m_navigatorEventHandler; @@ -248,7 +247,7 @@ QQnxIntegration::~QQnxIntegration() QQnxGLContext::shutdownContext(); #endif -#if defined(QQNX_PPS) +#if QT_CONFIG(qqnx_pps) // Destroy the hardware button notifier delete m_buttonsNotifier; @@ -318,7 +317,7 @@ QPlatformOpenGLContext *QQnxIntegration::createPlatformOpenGLContext(QOpenGLCont } #endif -#if defined(QQNX_PPS) +#if QT_CONFIG(qqnx_pps) QPlatformInputContext *QQnxIntegration::inputContext() const { qIntegrationDebug(); @@ -361,7 +360,7 @@ QPlatformClipboard *QQnxIntegration::clipboard() const { qIntegrationDebug(); -#if defined(QQNX_PPS) +#if QT_CONFIG(qqnx_pps) if (!m_clipboard) m_clipboard = new QQnxClipboard; #endif diff --git a/src/plugins/platforms/qnx/qqnxintegration.h b/src/plugins/platforms/qnx/qqnxintegration.h index b2008baa0c..d1ebb1d4bf 100644 --- a/src/plugins/platforms/qnx/qqnxintegration.h +++ b/src/plugins/platforms/qnx/qqnxintegration.h @@ -41,7 +41,7 @@ #define QQNXINTEGRATION_H #include - +#include #include #include @@ -61,7 +61,7 @@ class QQnxServices; class QSimpleDrag; -#if defined(QQNX_PPS) +#if QT_CONFIG(qqnx_pps) class QQnxInputContext; class QQnxNavigatorEventNotifier; class QQnxButtonEventNotifier; @@ -96,7 +96,7 @@ public: QPlatformOpenGLContext *createPlatformOpenGLContext(QOpenGLContext *context) const override; #endif -#if defined(QQNX_PPS) +#if QT_CONFIG(qqnx_pps) QPlatformInputContext *inputContext() const override; #endif @@ -143,7 +143,7 @@ private: QQnxScreenEventThread *m_screenEventThread; QQnxNavigatorEventHandler *m_navigatorEventHandler; QQnxAbstractVirtualKeyboard *m_virtualKeyboard; -#if defined(QQNX_PPS) +#if QT_CONFIG(qqnx_pps) QQnxNavigatorEventNotifier *m_navigatorEventNotifier; QQnxInputContext *m_inputContext; QQnxButtonEventNotifier *m_buttonsNotifier; -- cgit v1.2.3 From 117148c381316c046b99a4ce40ab668fb7c79f11 Mon Sep 17 00:00:00 2001 From: Gabriel de Dietrich Date: Wed, 20 Dec 2017 10:34:56 -0800 Subject: QMacStyle: Bring back submenu indicator MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This one fell off the truck while we were removing HITheme calls. We add it back by simply rendering a BLACK RIGHT-POINTING TRIANGLE character. We also fix smaller issues, such as not displaying any shortcut related to a submenu action — this is simply not a thing. The spacing between the menu item's text and the submenu indicator has also been slightly improved. Change-Id: I6c768a5506a5eb9528b0dd76acd52b561266d67b Task-number: QTBUG-64405 Reviewed-by: Jake Petroules --- src/plugins/styles/mac/qmacstyle_mac.mm | 53 +++++++++++++++++++++------------ 1 file changed, 34 insertions(+), 19 deletions(-) (limited to 'src/plugins') diff --git a/src/plugins/styles/mac/qmacstyle_mac.mm b/src/plugins/styles/mac/qmacstyle_mac.mm index c6ae7c1b79..386e944e42 100644 --- a/src/plugins/styles/mac/qmacstyle_mac.mm +++ b/src/plugins/styles/mac/qmacstyle_mac.mm @@ -4187,7 +4187,6 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter break; } - const int tabwidth = mi->tabWidth; const int maxpmw = mi->maxIconWidth; const bool enabled = mi->state & State_Enabled; @@ -4245,21 +4244,37 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter } QString s = mi->text; - if (!s.isEmpty()) { - int t = s.indexOf(QLatin1Char('\t')); - int text_flags = Qt::AlignRight | Qt::AlignVCenter | Qt::TextHideMnemonic - | Qt::TextSingleLine | Qt::AlignAbsolute; - int yPos = mi->rect.y(); - if (widgetSize == QStyleHelper::SizeMini) - yPos += 1; - p->save(); - if (t >= 0) { - p->setFont(qt_app_fonts_hash()->value("QMenuItem", p->font())); - int xp = mi->rect.right() - tabwidth - macRightBorder - macItemHMargin - macItemFrame + 1; - p->drawText(xp, yPos, tabwidth, mi->rect.height(), text_flags, s.mid(t + 1)); - s = s.left(t); - } + const auto text_flags = Qt::AlignVCenter | Qt::TextHideMnemonic + | Qt::TextSingleLine | Qt::AlignAbsolute; + int yPos = mi->rect.y(); + if (widgetSize == QStyleHelper::SizeMini) + yPos += 1; + + const bool isSubMenu = mi->menuItemType == QStyleOptionMenuItem::SubMenu; + const int tabwidth = isSubMenu ? 9 : mi->tabWidth; + + QString rightMarginText; + if (isSubMenu) + rightMarginText = QStringLiteral("\u25b6\ufe0e"); // U+25B6 U+FE0E: BLACK RIGHT-POINTING TRIANGLE + + // If present, save and remove embedded shorcut from text + const int tabIndex = s.indexOf(QLatin1Char('\t')); + if (tabIndex >= 0) { + if (!isSubMenu) // ... but ignore it if it's a submenu. + rightMarginText = s.mid(tabIndex + 1); + s = s.left(tabIndex); + } + p->save(); + if (!rightMarginText.isEmpty()) { + p->setFont(qt_app_fonts_hash()->value("QMenuItem", p->font())); + int xp = mi->rect.right() - tabwidth - macRightBorder + 2; + if (!isSubMenu) + xp -= macItemHMargin + macItemFrame + 3; // Adjust for shortcut + p->drawText(xp, yPos, tabwidth, mi->rect.height(), text_flags | Qt::AlignRight, rightMarginText); + } + + if (!s.isEmpty()) { const int xm = macItemFrame + maxpmw + macItemHMargin; QFont myFont = mi->font; // myFont may not have any "hard" flags set. We override @@ -4270,9 +4285,9 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter myFont.setPointSizeF(QFontInfo(mi->font).pointSizeF()); p->setFont(myFont); p->drawText(xpos, yPos, mi->rect.width() - xm - tabwidth + 1, - mi->rect.height(), text_flags ^ Qt::AlignRight, s); - p->restore(); + mi->rect.height(), text_flags, s); } + p->restore(); } break; case CE_MenuBarItem: @@ -6364,8 +6379,8 @@ QSize QMacStyle::sizeFromContents(ContentsType ct, const QStyleOption *opt, } if (mi->text.contains(QLatin1Char('\t'))) w += 12; - if (mi->menuItemType == QStyleOptionMenuItem::SubMenu) - w += 20; + else if (mi->menuItemType == QStyleOptionMenuItem::SubMenu) + w += 35; // Not quite exactly as it seems to depend on other factors if (maxpmw) w += maxpmw + 6; // add space for a check. All items have place for a check too. -- cgit v1.2.3 From e3c79b4356ca0d777663e7c4ad673dcb428b76b0 Mon Sep 17 00:00:00 2001 From: Gabriel de Dietrich Date: Wed, 20 Dec 2017 16:47:01 -0800 Subject: QMacStyle: Use light color on expanding scrollbar Change-Id: I4e9c870c8acaaa690f530f847c9927d61a508a94 Reviewed-by: Jake Petroules --- src/plugins/styles/mac/qmacstyle_mac.mm | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'src/plugins') diff --git a/src/plugins/styles/mac/qmacstyle_mac.mm b/src/plugins/styles/mac/qmacstyle_mac.mm index 386e944e42..ad2ca4a02e 100644 --- a/src/plugins/styles/mac/qmacstyle_mac.mm +++ b/src/plugins/styles/mac/qmacstyle_mac.mm @@ -5174,11 +5174,11 @@ void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex const auto cw = QMacStylePrivate::CocoaControl(controlType, cocoaSize); NSScroller *scroller = static_cast(d->cocoaControl(cw)); + const QColor bgColor = QStyleHelper::backgroundColor(opt->palette, widget); + const bool hasDarkBg = bgColor.red() < 128 && bgColor.green() < 128 && bgColor.blue() < 128; if (isTransient) { // macOS behavior: as soon as one color channel is >= 128, // the background is considered bright, scroller is dark. - const QColor bgColor = QStyleHelper::backgroundColor(opt->palette, widget); - const bool hasDarkBg = bgColor.red() < 128 && bgColor.green() < 128 && bgColor.blue() < 128; scroller.knobStyle = hasDarkBg? NSScrollerKnobStyleLight : NSScrollerKnobStyleDark; } else { scroller.knobStyle = NSScrollerKnobStyleDefault; @@ -5228,7 +5228,8 @@ void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex QCFType knobPath = CGPathCreateWithRoundedRect(knobRect, knobRadius, knobRadius, nullptr); CGContextAddPath(cg, knobPath); CGContextSetAlpha(cg, 0.5); - CGContextSetFillColorWithColor(cg, NSColor.blackColor.CGColor); + CGColorRef knobColor = hasDarkBg ? NSColor.whiteColor.CGColor : NSColor.blackColor.CGColor; + CGContextSetFillColorWithColor(cg, knobColor); CGContextFillPath(cg); } else { [scroller drawKnob]; -- cgit v1.2.3 From c5a3022b041f19c3bc2dd2204c9f9b334c7f986f Mon Sep 17 00:00:00 2001 From: Gabriel de Dietrich Date: Wed, 20 Dec 2017 17:14:18 -0800 Subject: QMacStyle: Minimize size of scrollbar transparency layer Instead of allocating the full backing store size for the transparency layer, we make sure we only allocate exactly as much as needed by the scrollbar. Change-Id: I55c3172fe3dd2a1f3fd46828463497f9f35cb1ae Reviewed-by: Jake Petroules --- src/plugins/styles/mac/qmacstyle_mac.mm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/plugins') diff --git a/src/plugins/styles/mac/qmacstyle_mac.mm b/src/plugins/styles/mac/qmacstyle_mac.mm index ad2ca4a02e..db02ab1fe9 100644 --- a/src/plugins/styles/mac/qmacstyle_mac.mm +++ b/src/plugins/styles/mac/qmacstyle_mac.mm @@ -5190,7 +5190,7 @@ void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex break; if (isTransient) { - CGContextBeginTransparencyLayer(cg, NULL); + CGContextBeginTransparencyLayerWithRect(cg, scroller.frame, nullptr); CGContextSetAlpha(cg, opacity); } -- cgit v1.2.3 From 44ef95a885f440a33e79ff3f9a79d4bb6d408dda Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Tue, 19 Dec 2017 19:58:29 +0100 Subject: iOS: Don't send all touch events async Commit 77942a1bdf9 introduced the QScopedValueRollback, but without assigning it to a local temporary, so the value was rolled back immediately, resulting in always sending touch events async. Change-Id: Ic7f65c3d38c46813ff06694e883dae3df138b9d4 Reviewed-by: Jake Petroules --- src/plugins/platforms/ios/qiosscreen.mm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/plugins') diff --git a/src/plugins/platforms/ios/qiosscreen.mm b/src/plugins/platforms/ios/qiosscreen.mm index 521495b42f..5717483a81 100644 --- a/src/plugins/platforms/ios/qiosscreen.mm +++ b/src/plugins/platforms/ios/qiosscreen.mm @@ -204,7 +204,7 @@ static QIOSScreen* qtPlatformScreenFor(UIScreen *uiScreen) - (void)sendEvent:(UIEvent *)event { - QScopedValueRollback(self->_sendingEvent, YES); + QScopedValueRollback sendingEvent(self->_sendingEvent, YES); [super sendEvent:event]; } -- cgit v1.2.3 From 52b85212a2ec8ec5bf187f6cd00b669a45bcf0bd Mon Sep 17 00:00:00 2001 From: Andy Shaw Date: Thu, 7 Dec 2017 16:01:48 +0100 Subject: sqlite: Check that there are values to be set when binding If the values vector is empty then we know already that the paramCount will still be invalid, so we should just accept that and not check the reused named placeholders. Task-number: QTBUG-64923 Change-Id: Ifaa755540c4574f1f76d3f9f129bf0f66b837b70 Reviewed-by: Edward Welbourne --- src/plugins/sqldrivers/sqlite/qsql_sqlite.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/plugins') diff --git a/src/plugins/sqldrivers/sqlite/qsql_sqlite.cpp b/src/plugins/sqldrivers/sqlite/qsql_sqlite.cpp index e9f5ee9508..67dd1a6ee5 100644 --- a/src/plugins/sqldrivers/sqlite/qsql_sqlite.cpp +++ b/src/plugins/sqldrivers/sqlite/qsql_sqlite.cpp @@ -467,7 +467,7 @@ bool QSQLiteResult::exec() #if (SQLITE_VERSION_NUMBER >= 3003011) // In the case of the reuse of a named placeholder - if (!paramCountIsValid) { + if (paramCount < values.count()) { const auto countIndexes = [](int counter, const QList& indexList) { return counter + indexList.length(); }; -- cgit v1.2.3