From f72152381b37740e65f174e175306d21c7616549 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Tue, 13 Oct 2015 21:48:08 +0200 Subject: tst_QStringBuilder: add a check for self-assignment Change-Id: I78094146bf534163af12d6e265276d987d5ce994 Reviewed-by: Olivier Goffart (Woboq GmbH) --- .../corelib/tools/qstringbuilder/qstringbuilder1/stringbuilder.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tests/auto/corelib/tools/qstringbuilder/qstringbuilder1/stringbuilder.cpp b/tests/auto/corelib/tools/qstringbuilder/qstringbuilder1/stringbuilder.cpp index e3b25c4c81..777fd5392c 100644 --- a/tests/auto/corelib/tools/qstringbuilder/qstringbuilder1/stringbuilder.cpp +++ b/tests/auto/corelib/tools/qstringbuilder/qstringbuilder1/stringbuilder.cpp @@ -93,6 +93,11 @@ void runScenario() r = special + string; QCOMPARE(r, QString(special P string)); + // self-assignment: + r = stringref.toString(); + r = achar + r; + QCOMPARE(r, QString(achar P stringref)); + #ifdef Q_COMPILER_UNICODE_STRINGS r = QStringLiteral(UNICODE_LITERAL); r = r Q QStringLiteral(UNICODE_LITERAL); -- cgit v1.2.3 From 2b09d371eb7d9f3e903603a94efdafa1e650a85b Mon Sep 17 00:00:00 2001 From: Rolland Dudemaine Date: Thu, 24 Mar 2016 11:02:27 +0100 Subject: Resolve build failure in network stress tests. strncmp() needs 3 arguments, not 2. Change-Id: Ia7077108a533321d5218cc35fd78ada8863f8200 Reviewed-by: Oswald Buddenhagen --- .../manual/network_remote_stresstest/tst_network_remote_stresstest.cpp | 2 +- tests/manual/network_stresstest/tst_network_stresstest.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/manual/network_remote_stresstest/tst_network_remote_stresstest.cpp b/tests/manual/network_remote_stresstest/tst_network_remote_stresstest.cpp index 486c5179b7..6767c8b153 100644 --- a/tests/manual/network_remote_stresstest/tst_network_remote_stresstest.cpp +++ b/tests/manual/network_remote_stresstest/tst_network_remote_stresstest.cpp @@ -144,7 +144,7 @@ void tst_NetworkRemoteStressTest::init() { // clear the internal cache #ifndef QT_BUILD_INTERNAL - if (strncmp(QTest::currentTestFunction(), "nam") == 0) + if (strncmp(QTest::currentTestFunction(), "nam", 3) == 0) QSKIP("QNetworkAccessManager tests disabled"); #endif } diff --git a/tests/manual/network_stresstest/tst_network_stresstest.cpp b/tests/manual/network_stresstest/tst_network_stresstest.cpp index 72233bf938..ab9481534e 100644 --- a/tests/manual/network_stresstest/tst_network_stresstest.cpp +++ b/tests/manual/network_stresstest/tst_network_stresstest.cpp @@ -135,7 +135,7 @@ void tst_NetworkStressTest::init() { // clear the internal cache #ifndef QT_BUILD_INTERNAL - if (strncmp(QTest::currentTestFunction(), "nam") == 0) + if (strncmp(QTest::currentTestFunction(), "nam", 3) == 0) QSKIP("QNetworkAccessManager tests disabled"); #endif } -- cgit v1.2.3 From 5b17fb14282822de36efd924abff8e3555e2491f Mon Sep 17 00:00:00 2001 From: Andy Shaw Date: Thu, 17 Mar 2016 10:01:25 +0100 Subject: Doc: Make the replacement functions for obsoleted functions explicit MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: I3a4bd3b4fcfd253b63fe342da6e398a4aeaf6825 Reviewed-by: Topi Reiniö --- src/corelib/tools/qstring.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp index cdf37cca07..10d3441d2c 100644 --- a/src/corelib/tools/qstring.cpp +++ b/src/corelib/tools/qstring.cpp @@ -5820,7 +5820,9 @@ QString QString::toUpper_helper(QString &str) } /*! - \obsolete Use asprintf(), arg() or QTextStream instead. + \obsolete + + Use asprintf(), arg() or QTextStream instead. */ QString &QString::sprintf(const char *cformat, ...) { @@ -5876,7 +5878,9 @@ QString QString::asprintf(const char *cformat, ...) } /*! - \obsolete Use vasprintf(), arg() or QTextStream instead. + \obsolete + + Use vasprintf(), arg() or QTextStream instead. */ QString &QString::vsprintf(const char *cformat, va_list ap) { @@ -10487,7 +10491,7 @@ float QStringRef::toFloat(bool *ok) const \obsolete \fn QString Qt::escape(const QString &plain) - \sa QString::toHtmlEscaped() + Use QString::toHtmlEscaped() instead. */ /*! -- cgit v1.2.3 From 7d1e6ca1998f6fd26795b1f9e408ccd7c7c0b558 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20L=C3=B6sch?= Date: Thu, 31 Mar 2016 15:09:20 +0200 Subject: Limit URLs for proxy auto config to 2083 chars On Windows only URLs up to 2083 characters are supported, so longer URLs are truncated. Task-number: QTBUG-52271 Change-Id: I625e4d089df4d977d39e61e5831611e04260e729 Reviewed-by: Markus Goetz (Woboq GmbH) --- src/network/kernel/qnetworkproxy_win.cpp | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/network/kernel/qnetworkproxy_win.cpp b/src/network/kernel/qnetworkproxy_win.cpp index 9e571bfe7f..15ef7d7cee 100644 --- a/src/network/kernel/qnetworkproxy_win.cpp +++ b/src/network/kernel/qnetworkproxy_win.cpp @@ -41,6 +41,7 @@ #include #include #include +#include #include #include @@ -590,8 +591,16 @@ QList QNetworkProxyFactory::systemProxyForQuery(const QNetworkPro url.setScheme(QLatin1String("https")); } + QString urlQueryString = url.toString(); + if (urlQueryString.size() > 2083) { + // calls to WinHttpGetProxyForUrl with urls longer than 2083 characters + // fail with error code ERROR_INVALID_PARAMETER(87), so we truncate it + qWarning("Proxy query URL too long for windows API, try with truncated URL"); + urlQueryString = url.toString().left(2083); + } + bool getProxySucceeded = ptrWinHttpGetProxyForUrl(sp->hHttpSession, - (LPCWSTR)url.toString().utf16(), + (LPCWSTR)urlQueryString.utf16(), &sp->autoProxyOptions, &proxyInfo); DWORD getProxyError = GetLastError(); @@ -608,7 +617,7 @@ QList QNetworkProxyFactory::systemProxyForQuery(const QNetworkPro sp->autoProxyOptions.dwFlags = WINHTTP_AUTOPROXY_CONFIG_URL; sp->autoProxyOptions.lpszAutoConfigUrl = (LPCWSTR)sp->autoConfigUrl.utf16(); getProxySucceeded = ptrWinHttpGetProxyForUrl(sp->hHttpSession, - (LPCWSTR)url.toString().utf16(), + (LPCWSTR)urlQueryString.utf16(), &sp->autoProxyOptions, &proxyInfo); getProxyError = GetLastError(); @@ -621,7 +630,7 @@ QList QNetworkProxyFactory::systemProxyForQuery(const QNetworkPro // But now we've to enable it (http://msdn.microsoft.com/en-us/library/aa383153%28v=VS.85%29.aspx) sp->autoProxyOptions.fAutoLogonIfChallenged = TRUE; getProxySucceeded = ptrWinHttpGetProxyForUrl(sp->hHttpSession, - (LPCWSTR)url.toString().utf16(), + (LPCWSTR)urlQueryString.utf16(), &sp->autoProxyOptions, &proxyInfo); getProxyError = GetLastError(); -- cgit v1.2.3 From 684ae5f7fecf005b4086e512332028eea737fa64 Mon Sep 17 00:00:00 2001 From: Joni Poikelin Date: Thu, 7 Apr 2016 08:02:52 +0300 Subject: Fix compiling examples with -no-sm There is access to session manager functions which are not present when building with -no-sm. Change-Id: I1c92b4a70f7adb56816877930fb9f55b04ff8940 Reviewed-by: Andy Shaw --- examples/widgets/mainwindows/application/mainwindow.cpp | 5 ++++- examples/widgets/mainwindows/application/mainwindow.h | 2 ++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/examples/widgets/mainwindows/application/mainwindow.cpp b/examples/widgets/mainwindows/application/mainwindow.cpp index 861b908189..7d97cfd7f0 100644 --- a/examples/widgets/mainwindows/application/mainwindow.cpp +++ b/examples/widgets/mainwindows/application/mainwindow.cpp @@ -59,9 +59,11 @@ MainWindow::MainWindow() connect(textEdit->document(), &QTextDocument::contentsChanged, this, &MainWindow::documentWasModified); +#ifndef QT_NO_SESSIONMANAGER QGuiApplication::setFallbackSessionManagementEnabled(false); connect(qApp, &QGuiApplication::commitDataRequest, this, &MainWindow::commitData); +#endif setCurrentFile(QString()); setUnifiedTitleAndToolBarOnMac(true); @@ -387,7 +389,7 @@ QString MainWindow::strippedName(const QString &fullFileName) return QFileInfo(fullFileName).fileName(); } //! [49] - +#ifndef QT_NO_SESSIONMANAGER void MainWindow::commitData(QSessionManager &manager) { if (manager.allowsInteraction()) { @@ -399,3 +401,4 @@ void MainWindow::commitData(QSessionManager &manager) save(); } } +#endif diff --git a/examples/widgets/mainwindows/application/mainwindow.h b/examples/widgets/mainwindows/application/mainwindow.h index 9712604125..690e8ebc32 100644 --- a/examples/widgets/mainwindows/application/mainwindow.h +++ b/examples/widgets/mainwindows/application/mainwindow.h @@ -70,7 +70,9 @@ private slots: bool saveAs(); void about(); void documentWasModified(); +#ifndef QT_NO_SESSIONMANAGER void commitData(QSessionManager &); +#endif private: void createActions(); -- cgit v1.2.3 From 34e0e908c896126138a95abdeba7456499d0fb68 Mon Sep 17 00:00:00 2001 From: Maurice Kalinowski Date: Thu, 17 Mar 2016 10:29:43 +0100 Subject: winrt: Add capabilities as specified by modules So far no capabilities (but internetClient for Windows 10) were added by default, which forced developers to always manually edit the WINRT_MANIFEST.capabilities(_device) property. This allowed to leave out non-required capabilities and keep the created manifest clean, examples being microphone for multimedia. However, this also breaks first user experience as deeper knowledge about this topic is required. Furthermore this is inconsistent with other platforms like Android, where all capabilities are set by default and developers need to edit the manifest manually in any case. With this change, modules can define the capability set to enable all features in the module. If developers want to disable some again, they need to adapt the generated manifest. From our experience this needs to be done in any case, latest at publishing stage when the store manipulates the manifest. Task-number: QTBUG-38802 Change-Id: I6d522268ee0afbfa00a30dbdd5e6ec9f415bebf3 Reviewed-by: Oswald Buddenhagen --- mkspecs/common/winrt_winphone/qmake.conf | 5 ++++- mkspecs/features/qt.prf | 9 +++++++++ mkspecs/features/qt_module_pris.prf | 4 ++++ mkspecs/features/winrt/package_manifest.prf | 11 ++++++++++- src/network/network.pro | 4 ++++ 5 files changed, 31 insertions(+), 2 deletions(-) diff --git a/mkspecs/common/winrt_winphone/qmake.conf b/mkspecs/common/winrt_winphone/qmake.conf index a9450b0c32..b5e0c7cc71 100644 --- a/mkspecs/common/winrt_winphone/qmake.conf +++ b/mkspecs/common/winrt_winphone/qmake.conf @@ -9,7 +9,7 @@ include(../angle.conf) MAKEFILE_GENERATOR = MSBUILD QMAKE_COMPILER = msvc QMAKE_PLATFORM = winrt win32 -CONFIG += incremental flat precompile_header autogen_precompile_source debug_and_release debug_and_release_target package_manifest rtti +CONFIG = package_manifest $$CONFIG incremental flat precompile_header autogen_precompile_source debug_and_release debug_and_release_target rtti DEFINES += UNICODE WIN32 QT_LARGEFILE_SUPPORT Q_BYTE_ORDER=Q_LITTLE_ENDIAN \ QT_NO_PRINTER QT_NO_PRINTDIALOG # TODO: Remove when printing is re-enabled @@ -95,6 +95,9 @@ VCSOLUTION_EXTENSION = .sln VCPROJ_KEYWORD = Qt4VSv1.0 WINRT_ASSETS_PATH = $$PWD/assets +WINRT_MANIFEST.capabilities = defaults +WINRT_MANIFEST.capabilities_device = defaults + include(../msvc-base.conf) unset(MSC_VER) diff --git a/mkspecs/features/qt.prf b/mkspecs/features/qt.prf index 5cc176c2ae..75b84ff6aa 100644 --- a/mkspecs/features/qt.prf +++ b/mkspecs/features/qt.prf @@ -141,6 +141,15 @@ for(ever) { } } } + # Add capabilities as defined by modules used in the project + winrt { + MODULE_WINRT_CAPABILITIES = $$eval(QT.$${QTLIB}.winrt_capabilities) + !isEmpty(MODULE_WINRT_CAPABILITIES): \ + WINRT_MANIFEST.capabilities_default += $$MODULE_WINRT_CAPABILITIES + MODULE_WINRT_CAPABILITIES_DEVICE = $$eval(QT.$${QTLIB}.winrt_capabilities_device) + !isEmpty(MODULE_WINRT_CAPABILITIES_DEVICE): \ + WINRT_MANIFEST.capabilities_device_default += $$MODULE_WINRT_CAPABILITIES_DEVICE + } } !isEmpty(BAD_QT):error("Unknown module(s) in QT$$var_sfx: $$replace(BAD_QT, _private$, -private)") diff --git a/mkspecs/features/qt_module_pris.prf b/mkspecs/features/qt_module_pris.prf index 9c45350543..4dd9e25f9f 100644 --- a/mkspecs/features/qt_module_pris.prf +++ b/mkspecs/features/qt_module_pris.prf @@ -104,6 +104,9 @@ MODULE_FWD_PRI = $$mod_work_pfx/qt_lib_$${MODULE_ID}.pri "QT.$${MODULE_ID}.DEFINES = $$val_escape(MODULE_DEFINES)" \ "" \ "QT_MODULES += $$MODULE" + winrt: MODULE_PRI_CONT += \ + "QT.$${MODULE_ID}.winrt_capabilities =$$join(MODULE_WINRT_CAPABILITIES, " ", " ")" \ + "QT.$${MODULE_ID}.winrt_capabilities_device =$$join(MODULE_WINRT_CAPABILITIES_DEVICE, " ", " ")" write_file($$MODULE_PRI, MODULE_PRI_CONT)|error("Aborting.") !internal_module:!no_private_module { module_build_type += internal_module @@ -186,6 +189,7 @@ MODULE_FWD_PRI = $$mod_work_pfx/qt_lib_$${MODULE_ID}.pri for(var, $$list(VERSION MAJOR_VERSION MINOR_VERSION PATCH_VERSION \ name module depends run_depends plugin_types module_config CONFIG DEFINES \ priority includes bins libs frameworks libexecs plugins imports qml \ + winrt_capabilities winrt_capabilities_device \ )):defined(QT.$${mod}.$$var, var):cache(QT.$${mod}.$$var, transient) } cache(QT_MODULES, transient) diff --git a/mkspecs/features/winrt/package_manifest.prf b/mkspecs/features/winrt/package_manifest.prf index 3520fcdf93..291ebec6e9 100644 --- a/mkspecs/features/winrt/package_manifest.prf +++ b/mkspecs/features/winrt/package_manifest.prf @@ -112,10 +112,19 @@ # capability anymore and is assumed to be standard. *-msvc2015: WINRT_MANIFEST.capabilities += internetClient + contains(WINRT_MANIFEST.capabilities, defaults) { + WINRT_MANIFEST.capabilities -= defaults + WINRT_MANIFEST.capabilities += $$WINRT_MANIFEST.capabilities_default + } + + contains(WINRT_MANIFEST.capabilities_device, defaults) { + WINRT_MANIFEST.capabilities_device -= defaults + WINRT_MANIFEST.capabilities_device += $$WINRT_MANIFEST.capabilities_device_default + } + # Capabilities are given as a string list and may change with the configuration (network, sensors, etc.) WINRT_MANIFEST.capabilities = $$unique(WINRT_MANIFEST.capabilities) WINRT_MANIFEST.capabilities_device = $$unique(WINRT_MANIFEST.capabilities_device) - !isEmpty(WINRT_MANIFEST.capabilities)|!isEmpty(WINRT_MANIFEST.capabilities_device) { MANIFEST_CAPABILITIES += "" for(CAPABILITY, WINRT_MANIFEST.capabilities): \ diff --git a/src/network/network.pro b/src/network/network.pro index cdea190222..fed14616af 100644 --- a/src/network/network.pro +++ b/src/network/network.pro @@ -32,6 +32,10 @@ MODULE_PLUGIN_TYPES = \ ANDROID_PERMISSIONS += \ android.permission.ACCESS_NETWORK_STATE +MODULE_WINRT_CAPABILITIES = \ + internetClient \ + internetClientServer + MODULE_PLUGIN_TYPES = \ bearer load(qt_module) -- cgit v1.2.3 From fe4fad790ed187bf1d8c5bf61066fe00823fbe7e Mon Sep 17 00:00:00 2001 From: Oliver Wolff Date: Tue, 22 Mar 2016 15:50:44 +0100 Subject: winrt: Fix QKeyEvent::isAutoRepeat When keeping a key pressed CorePhysicalKeyStatus' RepeatCount stays 1 while WasKeyDown changes from false to true. Thus WasKeyDown should be used to determine the auto repeat status of the key event. Task-number: QTBUG-52055 Change-Id: I7cde6b92473bd5335e85418c2b92cfe8f338975c Reviewed-by: Maurice Kalinowski --- src/plugins/platforms/winrt/qwinrtscreen.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/plugins/platforms/winrt/qwinrtscreen.cpp b/src/plugins/platforms/winrt/qwinrtscreen.cpp index 47e68ae0af..e4f7709146 100644 --- a/src/plugins/platforms/winrt/qwinrtscreen.cpp +++ b/src/plugins/platforms/winrt/qwinrtscreen.cpp @@ -885,7 +885,7 @@ HRESULT QWinRTScreen::onKeyDown(ABI::Windows::UI::Core::ICoreWindow *, ABI::Wind virtualKey, 0, QString(), - status.RepeatCount > 1, + status.WasKeyDown, !status.RepeatCount ? 1 : status.RepeatCount, false); return S_OK; @@ -912,7 +912,7 @@ HRESULT QWinRTScreen::onKeyUp(ABI::Windows::UI::Core::ICoreWindow *, ABI::Window virtualKey, 0, info.text, - status.RepeatCount > 1, + status.WasKeyDown, !status.RepeatCount ? 1 : status.RepeatCount, false); return S_OK; @@ -945,7 +945,7 @@ HRESULT QWinRTScreen::onCharacterReceived(ICoreWindow *, ICharacterReceivedEvent virtualKey, 0, text, - status.RepeatCount > 1, + status.WasKeyDown, !status.RepeatCount ? 1 : status.RepeatCount, false); d->activeKeys.insert(key, KeyInfo(text, virtualKey)); -- cgit v1.2.3 From a064bcf883f4552af3c81756dceda7c53cb8b061 Mon Sep 17 00:00:00 2001 From: Oliver Wolff Date: Wed, 23 Mar 2016 10:25:17 +0100 Subject: winrt: mimic desktop Window's "QKeyEvent::isAutoRepeat" behavior We should mimic desktop Qt's behavior as close as possible. That means, that a key release event is triggered between auto generated press events for most keys. For some keys like modifiers, caps lock, scroll lock etc. there are no auto repeated events if the key is held down. The "last" release event after having held the key and several events are triggered does not have the isAutoRepeat flag set so we should not have that flag in this case either. Task-number: QTBUG-52055 Change-Id: I001a73416c4b2072d307ee5d87c7cb8406c9575f Reviewed-by: Maurice Kalinowski --- src/plugins/platforms/winrt/qwinrtscreen.cpp | 46 +++++++++++++++++++++++++--- 1 file changed, 42 insertions(+), 4 deletions(-) diff --git a/src/plugins/platforms/winrt/qwinrtscreen.cpp b/src/plugins/platforms/winrt/qwinrtscreen.cpp index e4f7709146..fbf6393d90 100644 --- a/src/plugins/platforms/winrt/qwinrtscreen.cpp +++ b/src/plugins/platforms/winrt/qwinrtscreen.cpp @@ -416,6 +416,23 @@ static inline Qt::Key qKeyFromVirtual(VirtualKey key) } } +// Some keys like modifiers, caps lock etc. should not be automatically repeated if the key is held down +static inline bool shouldAutoRepeat(Qt::Key key) +{ + switch (key) { + case Qt::Key_Shift: + case Qt::Key_Control: + case Qt::Key_Alt: + case Qt::Key_Meta: + case Qt::Key_CapsLock: + case Qt::Key_NumLock: + case Qt::Key_ScrollLock: + return false; + default: + return true; + } +} + static inline Qt::Key qKeyFromCode(quint32 code, int mods) { if (code >= 'a' && code <= 'z') @@ -870,12 +887,33 @@ HRESULT QWinRTScreen::onKeyDown(ABI::Windows::UI::Core::ICoreWindow *, ABI::Wind Q_ASSERT_SUCCEEDED(hr); Qt::Key key = qKeyFromVirtual(virtualKey); - // Defer character key presses to onCharacterReceived - if (key == Qt::Key_unknown || (key >= Qt::Key_Space && key <= Qt::Key_ydiaeresis)) { + + const bool wasPressed = d->activeKeys.contains(key); + if (wasPressed) { + if (!shouldAutoRepeat(key)) + return S_OK; + + // If the key was pressed before trigger a key release before the next key press + QWindowSystemInterface::handleExtendedKeyEvent( + topWindow(), + QEvent::KeyRelease, + key, + keyboardModifiers(), + !status.ScanCode ? -1 : status.ScanCode, + virtualKey, + 0, + QString(), + status.WasKeyDown, + !status.RepeatCount ? 1 : status.RepeatCount, + false); + } else { d->activeKeys.insert(key, KeyInfo(virtualKey)); - return S_OK; } + // Defer character key presses to onCharacterReceived + if (key == Qt::Key_unknown || (key >= Qt::Key_Space && key <= Qt::Key_ydiaeresis)) + return S_OK; + QWindowSystemInterface::handleExtendedKeyEvent( topWindow(), QEvent::KeyPress, @@ -912,7 +950,7 @@ HRESULT QWinRTScreen::onKeyUp(ABI::Windows::UI::Core::ICoreWindow *, ABI::Window virtualKey, 0, info.text, - status.WasKeyDown, + false, // The final key release does not have autoRepeat set on Windows !status.RepeatCount ? 1 : status.RepeatCount, false); return S_OK; -- cgit v1.2.3 From f6eadcd60178b1a16224d557b8945020164eba7d Mon Sep 17 00:00:00 2001 From: BogDan Vatra Date: Fri, 1 Apr 2016 09:36:49 +0300 Subject: Hide the navigation bar only on Android API-19+ Hiding navigation bar only on Android pre API-19 is useless because the navigation bar appears every time when the user touches the application window. [ChangeLog][Android] Hide the navigation bar only on Android API-19+ Change-Id: I085d691a0170cf10dd9970e009c34c6afc961bc6 Reviewed-by: Christian Stromme --- .../org/qtproject/qt5/android/QtActivityDelegate.java | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java b/src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java index 4cce86e8bb..21a9d498df 100644 --- a/src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java +++ b/src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java @@ -139,17 +139,13 @@ public class QtActivityDelegate m_activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN); m_activity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN); try { - if (Build.VERSION.SDK_INT >= 14) { + if (Build.VERSION.SDK_INT >= 19) { int flags = View.class.getDeclaredField("SYSTEM_UI_FLAG_HIDE_NAVIGATION").getInt(null); - if (Build.VERSION.SDK_INT >= 16) { - flags |= View.class.getDeclaredField("SYSTEM_UI_FLAG_LAYOUT_STABLE").getInt(null); - flags |= View.class.getDeclaredField("SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION").getInt(null); - flags |= View.class.getDeclaredField("SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN").getInt(null); - flags |= View.class.getDeclaredField("SYSTEM_UI_FLAG_FULLSCREEN").getInt(null); - - if (Build.VERSION.SDK_INT >= 19) - flags |= View.class.getDeclaredField("SYSTEM_UI_FLAG_IMMERSIVE_STICKY").getInt(null); - } + flags |= View.class.getDeclaredField("SYSTEM_UI_FLAG_LAYOUT_STABLE").getInt(null); + flags |= View.class.getDeclaredField("SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION").getInt(null); + flags |= View.class.getDeclaredField("SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN").getInt(null); + flags |= View.class.getDeclaredField("SYSTEM_UI_FLAG_FULLSCREEN").getInt(null); + flags |= View.class.getDeclaredField("SYSTEM_UI_FLAG_IMMERSIVE_STICKY").getInt(null); Method m = View.class.getMethod("setSystemUiVisibility", int.class); m.invoke(m_activity.getWindow().getDecorView(), flags | View.INVISIBLE); } -- cgit v1.2.3 From 24914b1acbfc5e45768dd1465b9e3f3e61185829 Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Fri, 18 Mar 2016 15:49:58 +0100 Subject: Qt Quick: Fix bug for selections with line wraps and breaks This fixes yet another bug where the selection spans both line wraps and explicit line breaks. Offsetting the log clusters by the text position in 342c909b340cb1bfbb95480fc79dcea21a470c83 was not entirely correct, because in some cases the script item will refer to a specific part of the string, as indicated by si.position, while iterator.itemStart is in the context of the full string. In this case, the log cluster array pointer we use refers to the script item's part of the array, i.e. it is already offset by si.position. Therefore, we must offset the logClusters pointer by the text position *relative* to the current script item. Previously we would actually offset by si.position twice in cases where si.position != 0. We want the text range to refer to the full string, though, so it can be compared to other text ranges later. However, in some cases when we are requesting only part of a script item, then iterator.itemStart does not correspond to relativeFrom, so in order for the text range search to work, we must pass in the text positions we are using [relativeFrom, relativeTo], though offset by si.position so that it refers to the full string and not just the part addressed by the script item. Task-number: QTBUG-51759 Change-Id: Ib69856d6d3bc1dd501db94c9d295623f436d122c Reviewed-by: Konstantin Ritt Reviewed-by: Simon Hausmann --- src/gui/text/qtextlayout.cpp | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/src/gui/text/qtextlayout.cpp b/src/gui/text/qtextlayout.cpp index bc9c452ff7..aca475a581 100644 --- a/src/gui/text/qtextlayout.cpp +++ b/src/gui/text/qtextlayout.cpp @@ -2141,7 +2141,6 @@ static QGlyphRun glyphRunWithInfo(QFontEngine *fontEngine, QGlyphRunPrivate *d = QGlyphRunPrivate::get(glyphRun); int rangeStart = textPosition; - logClusters += textPosition; while (*logClusters != glyphsStart && rangeStart < textPosition + textLength) { ++logClusters; ++rangeStart; @@ -2350,9 +2349,9 @@ QList QTextLine::glyphRuns(int from, int length) const width, glyphsStart + start, glyphsStart + end, - logClusters, - iterator.itemStart, - iterator.itemLength)); + logClusters + relativeFrom, + relativeFrom + si.position, + relativeTo - relativeFrom + 1)); for (int i = 0; i < subLayout.numGlyphs; ++i) { QFixed justification = QFixed::fromFixed(subLayout.justifications[i].space_18d6); pos.rx() += (subLayout.advances[i] + justification).toReal(); @@ -2380,9 +2379,9 @@ QList QTextLine::glyphRuns(int from, int length) const width, glyphsStart + start, glyphsStart + end, - logClusters, - iterator.itemStart, - iterator.itemLength); + logClusters + relativeFrom, + relativeFrom + si.position, + relativeTo - relativeFrom + 1); if (!glyphRun.isEmpty()) glyphRuns.append(glyphRun); } else { @@ -2396,9 +2395,9 @@ QList QTextLine::glyphRuns(int from, int length) const width, glyphsStart, glyphsEnd, - logClusters, - iterator.itemStart, - iterator.itemLength); + logClusters + relativeFrom, + relativeFrom + si.position, + relativeTo - relativeFrom + 1); if (!glyphRun.isEmpty()) glyphRuns.append(glyphRun); } -- cgit v1.2.3 From 161fbfda70700c593dc4ce9952a572ae914c7398 Mon Sep 17 00:00:00 2001 From: Frederik Gladhorn Date: Thu, 7 Apr 2016 12:49:17 +0200 Subject: Improve gdb backtrace handling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Long backtraces would get cut off in the terminal, this is especially bothersome when having lots of threads. Make sure that the output is complet by setting height=0 for gdb. The gdb manual states: "If you specify a height of either unlimited or zero lines, gdb does not pause during output no matter how long the output is. This is useful if output is to a file or to an editor buffer." Change-Id: I282054bc9e205d67d3076e37d5c928475803b22d Reviewed-by: Simon Hausmann Reviewed-by: Friedemann Kleint Reviewed-by: Jędrzej Nowacki --- src/testlib/qtestcase.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/testlib/qtestcase.cpp b/src/testlib/qtestcase.cpp index 339db2246e..8de631094d 100644 --- a/src/testlib/qtestcase.cpp +++ b/src/testlib/qtestcase.cpp @@ -114,6 +114,7 @@ static void stackTrace() char cmd[512]; qsnprintf(cmd, 512, "gdb --pid %d 2>/dev/null < Date: Mon, 4 Apr 2016 18:36:53 +0200 Subject: remove bogus no_cxx_module conditional this flag specifies that the plugin does not track a qt module. this is entirely unrelated to whether the plugin should be versioned. amends f54a3d783. Change-Id: Ibd3e9bedf488dc58e6354ccf7dd33d974e5f52c2 Reviewed-by: Joerg Bornemann --- mkspecs/features/qml_plugin.prf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mkspecs/features/qml_plugin.prf b/mkspecs/features/qml_plugin.prf index daedeca3a0..20b8eb4d53 100644 --- a/mkspecs/features/qml_plugin.prf +++ b/mkspecs/features/qml_plugin.prf @@ -27,7 +27,7 @@ CONFIG += relative_qt_rpath # Qt's QML plugins should be relocatable } isEmpty(TARGETPATH): TARGETPATH = $$eval(QT.$${CXX_MODULE}.name) -!no_cxx_module:win32:CONFIG(shared, static|shared) { +win32:CONFIG(shared, static|shared) { # Embed a VERSIONINFO resource into the plugin's DLL. isEmpty(VERSION): VERSION = $$MODULE_VERSION CONFIG += skip_target_version_ext -- cgit v1.2.3 From b2c0e5af186201979f47a306e017eb8979248f00 Mon Sep 17 00:00:00 2001 From: BogDan Vatra Date: Mon, 28 Mar 2016 13:37:22 +0300 Subject: By default use native menu bar Task-number: QTBUG-52010 Change-Id: I8f5feacc41719b1c084ec5a8763e597c1dab716c Reviewed-by: Eskil Abrahamsen Blomfeldt --- src/plugins/platforms/android/qandroidplatformtheme.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/plugins/platforms/android/qandroidplatformtheme.cpp b/src/plugins/platforms/android/qandroidplatformtheme.cpp index d53d678bcf..9350a15721 100644 --- a/src/plugins/platforms/android/qandroidplatformtheme.cpp +++ b/src/plugins/platforms/android/qandroidplatformtheme.cpp @@ -362,6 +362,9 @@ QAndroidPlatformTheme::QAndroidPlatformTheme(QAndroidPlatformNativeInterface *an // default in case the style has not set a font m_systemFont = QFont(QLatin1String("Roboto"), 14.0 * 100 / 72); // keep default size the same after changing from 100 dpi to 72 dpi + + // by default use native menu bar + QCoreApplication::setAttribute(Qt::AA_DontUseNativeMenuBar, false); } QPlatformMenuBar *QAndroidPlatformTheme::createPlatformMenuBar() const -- cgit v1.2.3 From ee22fe13cda74c5ef5ee7b6db1b75d2837e43672 Mon Sep 17 00:00:00 2001 From: Edward Welbourne Date: Mon, 18 Jan 2016 13:00:32 +0100 Subject: QDateTimeParser::parse(): improve readability A switch (was inconsistent about whether enum members need casts and) made it less obvious, rather than more, what was going on; so changed it to a nested if. Change-Id: I9af322d9dd17aa08cac5003eff2c8eaa73b50d45 Reviewed-by: Marc Mutz --- src/corelib/tools/qdatetimeparser.cpp | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/src/corelib/tools/qdatetimeparser.cpp b/src/corelib/tools/qdatetimeparser.cpp index 8e3eaf7074..cc09992b88 100644 --- a/src/corelib/tools/qdatetimeparser.cpp +++ b/src/corelib/tools/qdatetimeparser.cpp @@ -977,22 +977,17 @@ QDateTimeParser::StateNode QDateTimeParser::parse(QString &input, int &cursorPos if (state != Invalid) { if (parserType != QVariant::Time) { - if (year % 100 != year2digits) { - switch (isSet & (YearSection2Digits|YearSection)) { - case YearSection2Digits: + if (year % 100 != year2digits && (isSet & YearSection2Digits)) { + if (!(isSet & YearSection)) { year = (year / 100) * 100; year += year2digits; - break; - case ((uint)YearSection2Digits|(uint)YearSection): { + } else { conflicts = true; const SectionNode &sn = sectionNode(currentSectionIndex); if (sn.type == YearSection2Digits) { year = (year / 100) * 100; year += year2digits; } - break; } - default: - break; } } -- cgit v1.2.3 From c671e66802b75b511ad85347c70f6193134d81ca Mon Sep 17 00:00:00 2001 From: Edward Welbourne Date: Mon, 18 Jan 2016 17:14:17 +0100 Subject: QDateTimeParser: mediate QLocale's meddling via a setter. The former has (for now) nothing private, so QLocale got away with setting its .defaultLocale explicitly; provide a setter method by which it can do that, to allow scope for later encapsulation. Change-Id: I77fc5fc8f868fc7cf8d51eb1c5d18926c61cbf78 Reviewed-by: Marc Mutz --- src/corelib/tools/qdatetimeparser_p.h | 1 + src/corelib/tools/qlocale.cpp | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/corelib/tools/qdatetimeparser_p.h b/src/corelib/tools/qdatetimeparser_p.h index 257cb6e2cc..d6c4d615db 100644 --- a/src/corelib/tools/qdatetimeparser_p.h +++ b/src/corelib/tools/qdatetimeparser_p.h @@ -218,6 +218,7 @@ public: FieldInfo fieldInfo(int index) const; + void setDefaultLocale(const QLocale &loc) { defaultLocale = loc; } virtual QDateTime getMinimum() const; virtual QDateTime getMaximum() const; virtual int cursorPosition() const { return -1; } diff --git a/src/corelib/tools/qlocale.cpp b/src/corelib/tools/qlocale.cpp index 890a8fb95d..72a6668bd3 100644 --- a/src/corelib/tools/qlocale.cpp +++ b/src/corelib/tools/qlocale.cpp @@ -1834,7 +1834,7 @@ QTime QLocale::toTime(const QString &string, const QString &format) const QTime time; #ifndef QT_BOOTSTRAPPED QDateTimeParser dt(QVariant::Time, QDateTimeParser::FromString); - dt.defaultLocale = *this; + dt.setDefaultLocale(*this); if (dt.parseFormat(format)) dt.fromString(string, 0, &time); #else @@ -1865,7 +1865,7 @@ QDate QLocale::toDate(const QString &string, const QString &format) const QDate date; #ifndef QT_BOOTSTRAPPED QDateTimeParser dt(QVariant::Date, QDateTimeParser::FromString); - dt.defaultLocale = *this; + dt.setDefaultLocale(*this); if (dt.parseFormat(format)) dt.fromString(string, &date, 0); #else @@ -1898,7 +1898,7 @@ QDateTime QLocale::toDateTime(const QString &string, const QString &format) cons QDate date; QDateTimeParser dt(QVariant::DateTime, QDateTimeParser::FromString); - dt.defaultLocale = *this; + dt.setDefaultLocale(*this); if (dt.parseFormat(format) && dt.fromString(string, &date, &time)) return QDateTime(date, time); #else -- cgit v1.2.3 From fd5720af2cb1e641c433c73fd977c8ba9d278305 Mon Sep 17 00:00:00 2001 From: Edward Welbourne Date: Wed, 20 Jan 2016 09:42:34 +0100 Subject: QDateTimeParser: new Section mask values simplify code. Various |s of existing section flags were used repeatedly; naming these masks makes the relevant code easier to read. In QDateTimeEdit, add a comment to make clear that its Section enum is based on QDTP's. Change-Id: Ifd8364cd396a6d0d5ed7ae7dc4d31690f77edd30 Reviewed-by: Marc Mutz --- src/corelib/tools/qdatetimeparser.cpp | 18 +++++++++++------- src/corelib/tools/qdatetimeparser_p.h | 12 +++++++++--- src/widgets/widgets/qdatetimeedit.cpp | 12 ++++++------ src/widgets/widgets/qdatetimeedit.h | 2 +- 4 files changed, 27 insertions(+), 17 deletions(-) diff --git a/src/corelib/tools/qdatetimeparser.cpp b/src/corelib/tools/qdatetimeparser.cpp index cc09992b88..180f76bcc1 100644 --- a/src/corelib/tools/qdatetimeparser.cpp +++ b/src/corelib/tools/qdatetimeparser.cpp @@ -159,7 +159,7 @@ bool QDateTimeParser::setDigit(QDateTime &v, int index, int newVal) const break; } - if (!(node.type & (DaySection|DayOfWeekSectionShort|DayOfWeekSectionLong))) { + if (!(node.type & DaySectionMask)) { if (day < cachedDay) day = cachedDay; const int max = QDate(year, month, 1).daysInMonth(); @@ -625,6 +625,10 @@ int QDateTimeParser::sectionMaxSize(Section s, int count) const case Internal: case TimeSectionMask: case DateSectionMask: + case HourSectionMask: + case YearSectionMask: + case DayOfWeekSectionMask: + case DaySectionMask: qWarning("QDateTimeParser::sectionMaxSize: Invalid section %s", SectionNode::name(s).toLatin1().constData()); @@ -993,12 +997,11 @@ QDateTimeParser::StateNode QDateTimeParser::parse(QString &input, int &cursorPos const QDate date(year, month, day); const int diff = dayofweek - date.dayOfWeek(); - if (diff != 0 && state == Acceptable - && isSet & (DayOfWeekSectionShort | DayOfWeekSectionLong)) { + if (diff != 0 && state == Acceptable && isSet & DayOfWeekSectionMask) { if (isSet & DaySection) conflicts = true; const SectionNode &sn = sectionNode(currentSectionIndex); - if (sn.type & (DayOfWeekSectionShort|DayOfWeekSectionLong) || currentSectionIndex == -1) { + if (sn.type & DayOfWeekSectionMask || currentSectionIndex == -1) { // dayofweek should be preferred day += diff; if (day <= 0) { @@ -1010,8 +1013,9 @@ QDateTimeParser::StateNode QDateTimeParser::parse(QString &input, int &cursorPos << diff << QDate(year, month, day).dayOfWeek(); } } + bool needfixday = false; - if (sectionType(currentSectionIndex) & (DaySection|DayOfWeekSectionShort|DayOfWeekSectionLong)) { + if (sectionType(currentSectionIndex) & DaySectionMask) { cachedDay = day; } else if (cachedDay > day) { day = cachedDay; @@ -1039,7 +1043,7 @@ QDateTimeParser::StateNode QDateTimeParser::parse(QString &input, int &cursorPos const SectionNode sn = sectionNode(i); if (sn.type & DaySection) { input.replace(sectionPos(sn), sectionSize(i), loc.toString(day)); - } else if (sn.type & (DayOfWeekSectionShort | DayOfWeekSectionLong)) { + } else if (sn.type & DayOfWeekSectionMask) { const int dayOfWeek = QDate(year, month, day).dayOfWeek(); const QLocale::FormatType dayFormat = (sn.type == DayOfWeekSectionShort @@ -1296,7 +1300,7 @@ int QDateTimeParser::findDay(const QString &str1, int startDay, int sectionIndex int bestCount = 0; if (!str1.isEmpty()) { const SectionNode &sn = sectionNode(sectionIndex); - if (!(sn.type & (DaySection|DayOfWeekSectionShort|DayOfWeekSectionLong))) { + if (!(sn.type & DaySectionMask)) { qWarning("QDateTimeParser::findDay Internal error"); return -1; } diff --git a/src/corelib/tools/qdatetimeparser_p.h b/src/corelib/tools/qdatetimeparser_p.h index d6c4d615db..90c6a8acba 100644 --- a/src/corelib/tools/qdatetimeparser_p.h +++ b/src/corelib/tools/qdatetimeparser_p.h @@ -114,14 +114,20 @@ public: MinuteSection = 0x00008, Hour12Section = 0x00010, Hour24Section = 0x00020, - TimeSectionMask = (AmPmSection|MSecSection|SecondSection|MinuteSection|Hour12Section|Hour24Section), + HourSectionMask = (Hour12Section | Hour24Section), + TimeSectionMask = (MSecSection | SecondSection | MinuteSection | + HourSectionMask | AmPmSection), + DaySection = 0x00100, MonthSection = 0x00200, YearSection = 0x00400, YearSection2Digits = 0x00800, + YearSectionMask = YearSection | YearSection2Digits, DayOfWeekSectionShort = 0x01000, DayOfWeekSectionLong = 0x02000, - DateSectionMask = (DaySection|MonthSection|YearSection|YearSection2Digits|DayOfWeekSectionShort|DayOfWeekSectionLong), + DayOfWeekSectionMask = DayOfWeekSectionShort | DayOfWeekSectionLong, + DaySectionMask = DaySection | DayOfWeekSectionMask, + DateSectionMask = DaySectionMask | MonthSection | YearSectionMask, Internal = 0x10000, FirstSection = 0x20000 | Internal, @@ -132,7 +138,7 @@ public: FirstSectionIndex = -2, LastSectionIndex = -3, CalendarPopupIndex = -4 - }; // duplicated from qdatetimeedit.h + }; // extending qdatetimeedit.h's equivalent Q_DECLARE_FLAGS(Sections, Section) struct Q_CORE_EXPORT SectionNode { diff --git a/src/widgets/widgets/qdatetimeedit.cpp b/src/widgets/widgets/qdatetimeedit.cpp index 8ee32a2a8b..eb001bade4 100644 --- a/src/widgets/widgets/qdatetimeedit.cpp +++ b/src/widgets/widgets/qdatetimeedit.cpp @@ -2047,7 +2047,7 @@ QDateTime QDateTimeEditPrivate::stepBy(int sectionIndex, int steps, bool test) c // doesn't mean that we hit the floor in the other if (steps > 0) { setDigit(v, sectionIndex, min); - if (!(sn.type & (DaySection|DayOfWeekSectionShort|DayOfWeekSectionLong)) && sections & DateSectionMask) { + if (!(sn.type & DaySectionMask) && sections & DateSectionMask) { const int daysInMonth = v.date().daysInMonth(); if (v.date().day() < oldDay && v.date().day() < daysInMonth) { const int adds = qMin(oldDay, daysInMonth); @@ -2062,7 +2062,7 @@ QDateTime QDateTimeEditPrivate::stepBy(int sectionIndex, int steps, bool test) c } } else { setDigit(v, sectionIndex, max); - if (!(sn.type & (DaySection|DayOfWeekSectionShort|DayOfWeekSectionLong)) && sections & DateSectionMask) { + if (!(sn.type & DaySectionMask) && sections & DateSectionMask) { const int daysInMonth = v.date().daysInMonth(); if (v.date().day() < oldDay && v.date().day() < daysInMonth) { const int adds = qMin(oldDay, daysInMonth); @@ -2080,7 +2080,7 @@ QDateTime QDateTimeEditPrivate::stepBy(int sectionIndex, int steps, bool test) c setDigit(v, sectionIndex, (steps > 0 ? localmax : localmin)); } } - if (!test && oldDay != v.date().day() && !(sn.type & (DaySection|DayOfWeekSectionShort|DayOfWeekSectionLong))) { + if (!test && oldDay != v.date().day() && !(sn.type & DaySectionMask)) { // this should not happen when called from stepEnabled cachedDay = qMax(oldDay, cachedDay); } @@ -2272,15 +2272,15 @@ QDateTimeEdit::Sections QDateTimeEditPrivate::convertSections(QDateTimeParser::S ret |= QDateTimeEdit::SecondSection; if (s & QDateTimeParser::MinuteSection) ret |= QDateTimeEdit::MinuteSection; - if (s & (QDateTimeParser::Hour24Section|QDateTimeParser::Hour12Section)) + if (s & (QDateTimeParser::HourSectionMask)) ret |= QDateTimeEdit::HourSection; if (s & QDateTimeParser::AmPmSection) ret |= QDateTimeEdit::AmPmSection; - if (s & (QDateTimeParser::DaySection|QDateTimeParser::DayOfWeekSectionShort|QDateTimeParser::DayOfWeekSectionLong)) + if (s & (QDateTimeParser::DaySectionMask)) ret |= QDateTimeEdit::DaySection; if (s & QDateTimeParser::MonthSection) ret |= QDateTimeEdit::MonthSection; - if (s & (QDateTimeParser::YearSection|QDateTimeParser::YearSection2Digits)) + if (s & (QDateTimeParser::YearSectionMask)) ret |= QDateTimeEdit::YearSection; return ret; diff --git a/src/widgets/widgets/qdatetimeedit.h b/src/widgets/widgets/qdatetimeedit.h index 829ce205be..031cc0bbb4 100644 --- a/src/widgets/widgets/qdatetimeedit.h +++ b/src/widgets/widgets/qdatetimeedit.h @@ -69,7 +69,7 @@ class Q_WIDGETS_EXPORT QDateTimeEdit : public QAbstractSpinBox Q_PROPERTY(int sectionCount READ sectionCount) Q_PROPERTY(Qt::TimeSpec timeSpec READ timeSpec WRITE setTimeSpec) public: - enum Section { + enum Section { // a sub-type of QDateTimeParser's like-named enum. NoSection = 0x0000, AmPmSection = 0x0001, MSecSection = 0x0002, -- cgit v1.2.3 From 2996560bf80d037b7bb6d541cdabd7816a8d3325 Mon Sep 17 00:00:00 2001 From: Edward Welbourne Date: Wed, 6 Apr 2016 17:53:58 +0200 Subject: QDateTimeEditPrivate: make clear which overrides are for which base. The class does multiple inheritance and over-rides virtuals from both bases; it also declared the over-rides virtual rather than declaring them to be over-rides; so deploy Q_DECL_OVERRIDE and, while changing those lines, move them all together and document which belong to which base. Change-Id: Ica3958d6d24124a537983e7e94fce642284f1f24 Reviewed-by: Marc Mutz --- src/widgets/widgets/qdatetimeedit_p.h | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/src/widgets/widgets/qdatetimeedit_p.h b/src/widgets/widgets/qdatetimeedit_p.h index 4a6014000b..5772647a1a 100644 --- a/src/widgets/widgets/qdatetimeedit_p.h +++ b/src/widgets/widgets/qdatetimeedit_p.h @@ -75,14 +75,25 @@ public: void emitSignals(EmitPolicy ep, const QVariant &old); QString textFromValue(const QVariant &f) const; QVariant valueFromText(const QString &f) const; - virtual void _q_editorCursorPositionChanged(int oldpos, int newpos); - virtual void interpret(EmitPolicy ep); - virtual void clearCache() const; QDateTime validateAndInterpret(QString &input, int &, QValidator::State &state, bool fixup = false) const; void clearSection(int index); - virtual QString displayText() const { return edit->text(); } // this is from QDateTimeParser + + // Override QAbstractSpinBoxPrivate: + void _q_editorCursorPositionChanged(int oldpos, int newpos) Q_DECL_OVERRIDE; + void interpret(EmitPolicy ep) Q_DECL_OVERRIDE; + void clearCache() const Q_DECL_OVERRIDE; + QStyle::SubControl newHoverControl(const QPoint &pos) Q_DECL_OVERRIDE; + void updateEditFieldGeometry() Q_DECL_OVERRIDE; + QVariant getZeroVariant() const Q_DECL_OVERRIDE; + void setRange(const QVariant &min, const QVariant &max) Q_DECL_OVERRIDE; + + // Override QDateTimePraser: + QString displayText() const Q_DECL_OVERRIDE { return edit->text(); } + QDateTime getMinimum() const Q_DECL_OVERRIDE { return minimum.toDateTime(); } + QDateTime getMaximum() const Q_DECL_OVERRIDE { return maximum.toDateTime(); } + QLocale locale() const Q_DECL_OVERRIDE { return q_func()->locale(); } int absoluteIndex(QDateTimeEdit::Section s, int index) const; int absoluteIndex(const SectionNode &s) const; @@ -96,18 +107,10 @@ public: void updateCache(const QVariant &val, const QString &str) const; void updateTimeSpec(); - virtual QDateTime getMinimum() const { return minimum.toDateTime(); } - virtual QDateTime getMaximum() const { return maximum.toDateTime(); } - virtual QLocale locale() const { return q_func()->locale(); } QString valueToText(const QVariant &var) const { return textFromValue(var); } QString getAmPmText(AmPm ap, Case cs) const; int cursorPosition() const { return edit ? edit->cursorPosition() : -1; } - virtual QStyle::SubControl newHoverControl(const QPoint &pos); - virtual void updateEditFieldGeometry(); - virtual QVariant getZeroVariant() const; - virtual void setRange(const QVariant &min, const QVariant &max); - void _q_resetButton(); void updateArrow(QStyle::StateFlag state); bool calendarPopupEnabled() const; -- cgit v1.2.3 From 4ac0686a6ba0d7512585dedd0561ed56240a8ccc Mon Sep 17 00:00:00 2001 From: Edward Welbourne Date: Wed, 27 Jan 2016 14:31:37 +0100 Subject: Remove QDateTimeEditPrivate's duplication of QDateTimeParser code. Both constructors set up the first, last and none members. QDateTimeEditPrivate wants first.pos = 0, different to its base, so keep that, but the rest merely duplicated. Change-Id: Ice22e0495112dc3427eb35b5b73420f42d7dafc1 Reviewed-by: Marc Mutz --- src/widgets/widgets/qdatetimeedit.cpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/widgets/widgets/qdatetimeedit.cpp b/src/widgets/widgets/qdatetimeedit.cpp index eb001bade4..960f84c13a 100644 --- a/src/widgets/widgets/qdatetimeedit.cpp +++ b/src/widgets/widgets/qdatetimeedit.cpp @@ -1668,12 +1668,7 @@ QDateTimeEditPrivate::QDateTimeEditPrivate() cachedDay = -1; currentSectionIndex = FirstSectionIndex; - first.type = FirstSection; - last.type = LastSection; - none.type = NoSection; first.pos = 0; - last.pos = -1; - none.pos = -1; sections = 0; calendarPopup = false; minimum = QDATETIMEEDIT_COMPAT_DATETIME_MIN; -- cgit v1.2.3 From 3c08035b7b29e48e749a92cbdf05432a57f4108d Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Wed, 6 Jan 2016 14:47:00 +0100 Subject: QScreen manual test: add MouseMonitor to test multi-screen scenarios MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - QMouseEvent::screenPos() should be global desktop position - QDesktopWidget::screenNumber() should tell the correct screen - QGuiApplication::topLevelAt(screenPos) should find the window where the mouse is clicked Change-Id: I9a63ab3ee1944b7246551d0f3d5e37f0d2aa5457 Reviewed-by: Błażej Szczygieł Reviewed-by: Friedemann Kleint --- tests/manual/qscreen/main.cpp | 67 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) diff --git a/tests/manual/qscreen/main.cpp b/tests/manual/qscreen/main.cpp index 298996a59b..13d4145a68 100644 --- a/tests/manual/qscreen/main.cpp +++ b/tests/manual/qscreen/main.cpp @@ -45,6 +45,61 @@ #include #include #include +#include +#include +#include + + +class MouseMonitor : public QLabel { + Q_OBJECT +public: + MouseMonitor() : m_grabbed(false) { + setMinimumSize(540, 240); + setAlignment(Qt::AlignCenter); + setMouseTracking(true); + setWindowTitle(QLatin1String("Mouse Monitor")); + updateText(); + } + + void updateText() { + QString txt = m_grabbed ? + QLatin1String("Left-click to test QGuiApplication::topLevelAt(click pos)\nRight-click to ungrab\n") : + QLatin1String("Left-click to grab mouse\n"); + if (!m_cursorPos.isNull()) { + txt += QString(QLatin1String("Current mouse position: %1, %2 on screen %3\n")) + .arg(m_cursorPos.x()).arg(m_cursorPos.y()).arg(QApplication::desktop()->screenNumber(m_cursorPos)); + if (QGuiApplication::mouseButtons() & Qt::LeftButton) { + QWindow *win = QGuiApplication::topLevelAt(m_cursorPos); + txt += QString(QLatin1String("Top-level window found? %1\n")) + .arg(win ? (win->title().isEmpty() ? "no title" : win->title()) : "none"); + } + } + setText(txt); + } + +protected: + void mouseMoveEvent(QMouseEvent *ev) Q_DECL_OVERRIDE { + m_cursorPos = ev->screenPos().toPoint(); + updateText(); + } + + void mousePressEvent(QMouseEvent *ev) Q_DECL_OVERRIDE { + m_cursorPos = ev->screenPos().toPoint(); + qDebug() << "top level @" << m_cursorPos << ":" << QGuiApplication::topLevelAt(m_cursorPos); + updateText(); + if (!m_grabbed) { + grabMouse(Qt::CrossCursor); + m_grabbed = true; + } else if (ev->button() == Qt::RightButton) { + setVisible(false); + deleteLater(); + } + } + +private: + QPoint m_cursorPos; + bool m_grabbed; +}; class ScreenPropertyWatcher : public PropertyWatcher { @@ -101,6 +156,7 @@ public: protected: bool event(QEvent *event) Q_DECL_OVERRIDE; + void startMouseMonitor(); private: const QString m_annotation; @@ -124,6 +180,11 @@ ScreenWatcherMainWindow::ScreenWatcherMainWindow(QScreen *screen) a = fileMenu->addAction(QLatin1String("Quit")); a->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_Q)); connect(a, SIGNAL(triggered()), qApp, SLOT(quit())); + + QMenu *toolsMenu = menuBar()->addMenu(QLatin1String("&Tools")); + a = toolsMenu->addAction(QLatin1String("Mouse Monitor")); + a->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_M)); + connect(a, &QAction::triggered, this, &ScreenWatcherMainWindow::startMouseMonitor); } static inline QString msgScreenChange(const QWidget *w, const QScreen *oldScreen, const QScreen *newScreen) @@ -159,6 +220,12 @@ bool ScreenWatcherMainWindow::event(QEvent *event) return QMainWindow::event(event); } +void ScreenWatcherMainWindow::startMouseMonitor() +{ + MouseMonitor *mm = new MouseMonitor(); + mm->show(); +} + void screenAdded(QScreen* screen) { screen->setOrientationUpdateMask((Qt::ScreenOrientations)0x0F); -- cgit v1.2.3 From 8e103902def83af0a074b81c9d527d8147def162 Mon Sep 17 00:00:00 2001 From: Liang Qi Date: Wed, 6 Apr 2016 14:29:15 +0200 Subject: tests: fix tst_QFontComboBox on OS X MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit After 909d3f5c7, private families will not be shown in user interface. Task-number: QTBUG-41318 Change-Id: I15ae77cacd2a27c9db4b1a8ffbb582416258988c Reviewed-by: Morten Johan Sørvig --- tests/auto/widgets/widgets/qfontcombobox/BLACKLIST | 6 ------ .../widgets/qfontcombobox/tst_qfontcombobox.cpp | 20 +++++++++++++++----- 2 files changed, 15 insertions(+), 11 deletions(-) delete mode 100644 tests/auto/widgets/widgets/qfontcombobox/BLACKLIST diff --git a/tests/auto/widgets/widgets/qfontcombobox/BLACKLIST b/tests/auto/widgets/widgets/qfontcombobox/BLACKLIST deleted file mode 100644 index 8bd4caad31..0000000000 --- a/tests/auto/widgets/widgets/qfontcombobox/BLACKLIST +++ /dev/null @@ -1,6 +0,0 @@ -[currentFont] -osx -[fontFilters] -osx -[writingSystem] -osx diff --git a/tests/auto/widgets/widgets/qfontcombobox/tst_qfontcombobox.cpp b/tests/auto/widgets/widgets/qfontcombobox/tst_qfontcombobox.cpp index 5d6fdf2851..10e447c417 100644 --- a/tests/auto/widgets/widgets/qfontcombobox/tst_qfontcombobox.cpp +++ b/tests/auto/widgets/widgets/qfontcombobox/tst_qfontcombobox.cpp @@ -113,18 +113,21 @@ void tst_QFontComboBox::qfontcombobox() void tst_QFontComboBox::currentFont_data() { QTest::addColumn("currentFont"); + QFontDatabase db; // Normalize the names QFont defaultFont; QFontInfo fi(defaultFont); defaultFont = QFont(fi.family()); // make sure we have a real font name and not something like 'Sans Serif'. - QTest::newRow("default") << defaultFont; + if (!db.isPrivateFamily(defaultFont.family())) + QTest::newRow("default") << defaultFont; defaultFont.setPointSize(defaultFont.pointSize() + 10); - QTest::newRow("default2") << defaultFont; - QFontDatabase db; + if (!db.isPrivateFamily(defaultFont.family())) + QTest::newRow("default2") << defaultFont; QStringList list = db.families(); for (int i = 0; i < list.count(); ++i) { QFont f = QFont(QFontInfo(QFont(list.at(i))).family()); - QTest::newRow(qPrintable(list.at(i))) << f; + if (!db.isPrivateFamily(f.family())) + QTest::newRow(qPrintable(list.at(i))) << f; } } @@ -201,6 +204,8 @@ void tst_QFontComboBox::fontFilters() fontFilters &= ~spacingMask; for (int i = 0; i < list.count(); ++i) { + if (db.isPrivateFamily(list[i])) + continue; if (fontFilters & QFontComboBox::ScalableFonts) { if (!db.isSmoothlyScalable(list[i])) continue; @@ -265,7 +270,12 @@ void tst_QFontComboBox::writingSystem() QFontDatabase db; QStringList list = db.families(writingSystem); - QCOMPARE(box.model()->rowCount(), list.count()); + int c = list.count(); + for (int i = 0; i < list.count(); ++i) { + if (db.isPrivateFamily(list[i])) + c--; + } + QCOMPARE(box.model()->rowCount(), c); if (list.count() == 0) QCOMPARE(box.currentFont(), QFont()); -- cgit v1.2.3 From f39e542eb859f5f88c65a1b97bdf2f4256c68ec0 Mon Sep 17 00:00:00 2001 From: Alexander Grishkov Date: Tue, 15 Mar 2016 22:54:20 +0300 Subject: Fix parsing of IPv4 addresses with certain symbols Add some extra checks to the parser to make sure that addresses like "300-05" aren't interpreted as valid IPv4 addresses. Change-Id: I12475eebc9452e060779bb05e2b4ad9512a28281 Reviewed-by: Thiago Macieira Reviewed-by: Oswald Buddenhagen --- src/corelib/io/qipaddress.cpp | 3 +++ tests/auto/corelib/io/qipaddress/tst_qipaddress.cpp | 8 ++++++++ 2 files changed, 11 insertions(+) diff --git a/src/corelib/io/qipaddress.cpp b/src/corelib/io/qipaddress.cpp index ef0ca0269e..47cbbe066a 100644 --- a/src/corelib/io/qipaddress.cpp +++ b/src/corelib/io/qipaddress.cpp @@ -111,6 +111,9 @@ static bool parseIp4Internal(IPv4Address &address, const char *ptr, bool acceptL return false; else if (dotCount == 3 || *endptr == '\0') return true; + if (*endptr != '.') + return false; + ++dotCount; ptr = endptr + 1; } diff --git a/tests/auto/corelib/io/qipaddress/tst_qipaddress.cpp b/tests/auto/corelib/io/qipaddress/tst_qipaddress.cpp index 3e16d3b871..0addd89ebf 100644 --- a/tests/auto/corelib/io/qipaddress/tst_qipaddress.cpp +++ b/tests/auto/corelib/io/qipaddress/tst_qipaddress.cpp @@ -186,6 +186,7 @@ void tst_QIpAddress::invalidParseIp4_data() QTest::newRow("..") << ".."; QTest::newRow("...") << "..."; QTest::newRow("....") << "...."; + QTest::newRow(".1.2.3") << ".1.2.3"; QTest::newRow("1.") << "1."; QTest::newRow("1.2.") << "1.2."; QTest::newRow("1.2.3.") << "1.2.3."; @@ -214,9 +215,15 @@ void tst_QIpAddress::invalidParseIp4_data() QTest::newRow("-1.1") << "-1.1"; QTest::newRow("1.-1") << "1.-1"; QTest::newRow("1.1.1.-1") << "1.1.1.-1"; + QTest::newRow("300-05") << "300-05"; + QTest::newRow("127.-1") << "127.-1"; + QTest::newRow("-127-10") << "-127-10"; + QTest::newRow("198.-16") << "198-16"; + QTest::newRow("-127.-0.") << "-127.-0."; // letters QTest::newRow("abc") << "abc"; + QTest::newRow("localhost") << "localhost"; QTest::newRow("1.2.3a.4") << "1.2.3a.4"; QTest::newRow("a.2.3.4") << "a.2.3.4"; QTest::newRow("1.2.3.4a") << "1.2.3.4a"; @@ -249,6 +256,7 @@ void tst_QIpAddress::ip4ToString_data() QTest::newRow("0.0.0.0") << 0u << "0.0.0.0"; QTest::newRow("1.2.3.4") << 0x01020304u << "1.2.3.4"; + QTest::newRow("127.0.0.1") << 0x7f000001u << "127.0.0.1"; QTest::newRow("111.222.33.44") << 0x6fde212cu << "111.222.33.44"; QTest::newRow("255.255.255.255") << 0xffffffffu << "255.255.255.255"; } -- cgit v1.2.3 From b0bfe8de68a27de34b9493e7d5263cad1e5823c9 Mon Sep 17 00:00:00 2001 From: Weng Xuetian Date: Tue, 29 Mar 2016 15:24:01 -0700 Subject: Delete the dangling generic engine object. Change-Id: I7d7531f1a678bf186e3a992091344fff64721dec Reviewed-by: Marc Mutz Reviewed-by: Lorn Potter --- src/network/bearer/qnetworkconfigmanager_p.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/network/bearer/qnetworkconfigmanager_p.cpp b/src/network/bearer/qnetworkconfigmanager_p.cpp index 71e435b771..ccda9dd509 100644 --- a/src/network/bearer/qnetworkconfigmanager_p.cpp +++ b/src/network/bearer/qnetworkconfigmanager_p.cpp @@ -418,6 +418,8 @@ void QNetworkConfigurationManagerPrivate::updateConfigurations() if (generic) { if (!envOK || skipGeneric <= 0) sessionEngines.append(generic); + else + delete generic; } #endif // QT_NO_LIBRARY } -- cgit v1.2.3 From b77ef8a7e6e4104067d52824e29eadc8c66f5929 Mon Sep 17 00:00:00 2001 From: Weng Xuetian Date: Sat, 5 Mar 2016 12:23:21 -0800 Subject: QtDBus: clean up signal hooks and object tree in closeConnection If a QObject is added or passed as receiver to QDBusConnection::connect() and it is managed by Q_GLOBAL_STATIC or similar mechanism, it is possible that when that its destructor is called after the dbus daemon thread ends. In that case, QObject::destroyed connected via Qt::BlockingQueuedConnection to QDBusConnectionPrivate will cause dead lock since the thread is no longer processing events. Task-number: QTBUG-51648 Change-Id: I1a1810a6d6d0234af0269d5f3fc1f54101bf1547 Reviewed-by: Thiago Macieira --- src/dbus/qdbusconnection_p.h | 1 + src/dbus/qdbusintegrator.cpp | 26 +++++++++++++++++++++++++- 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/src/dbus/qdbusconnection_p.h b/src/dbus/qdbusconnection_p.h index c77daf7ee1..565eb832f2 100644 --- a/src/dbus/qdbusconnection_p.h +++ b/src/dbus/qdbusconnection_p.h @@ -254,6 +254,7 @@ private: const QVector &metaTypes, int slotIdx); SignalHookHash::Iterator removeSignalHookNoLock(SignalHookHash::Iterator it); + void disconnectObjectTree(ObjectTreeNode &node); bool isServiceRegisteredByThread(const QString &serviceName); diff --git a/src/dbus/qdbusintegrator.cpp b/src/dbus/qdbusintegrator.cpp index 478a2c4a05..3be775db82 100644 --- a/src/dbus/qdbusintegrator.cpp +++ b/src/dbus/qdbusintegrator.cpp @@ -1050,7 +1050,6 @@ QDBusConnectionPrivate::~QDBusConnectionPrivate() qPrintable(name)); closeConnection(); - rootNode.children.clear(); // free resources qDeleteAll(cachedMetaObjects); if (mode == ClientMode || mode == PeerMode) { @@ -1072,6 +1071,19 @@ QDBusConnectionPrivate::~QDBusConnectionPrivate() } } +void QDBusConnectionPrivate::disconnectObjectTree(QDBusConnectionPrivate::ObjectTreeNode &haystack) +{ + QDBusConnectionPrivate::ObjectTreeNode::DataList::Iterator it = haystack.children.begin(); + + while (it != haystack.children.end()) { + disconnectObjectTree(*it); + it++; + } + + if (haystack.obj) + haystack.obj->disconnect(this); +} + void QDBusConnectionPrivate::closeConnection() { QDBusWriteLocker locker(CloseConnectionAction, this); @@ -1095,6 +1107,18 @@ void QDBusConnectionPrivate::closeConnection() } qDeleteAll(pendingCalls); + + // Disconnect all signals from signal hooks and from the object tree to + // avoid QObject::destroyed being sent to dbus daemon thread which has + // already quit. + SignalHookHash::iterator sit = signalHooks.begin(); + while (sit != signalHooks.end()) { + sit.value().obj->disconnect(this); + sit++; + } + + disconnectObjectTree(rootNode); + rootNode.children.clear(); // free resources } void QDBusConnectionPrivate::checkThread() -- cgit v1.2.3 From 53d5811b0c432b845e453dfbef3f4237a1a71877 Mon Sep 17 00:00:00 2001 From: Timur Pocheptsov Date: Mon, 26 Oct 2015 14:19:23 +0100 Subject: rcc compiler with -list on Windows (newline symbols) Suppress '\n' -> '\r\n' replacement done by QIODevice, on Windows fwrite to stdout will end up in such replacement, no need in \r\r\n (reported as a bug in QtQuickCompiler originally).) Task-number: QTRD-3497 Change-Id: I61010831b49e41b3e4fa6626054f9fb53c63bb8a Reviewed-by: hjk --- src/tools/rcc/main.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/tools/rcc/main.cpp b/src/tools/rcc/main.cpp index d8d5728414..30975cc17e 100644 --- a/src/tools/rcc/main.cpp +++ b/src/tools/rcc/main.cpp @@ -255,6 +255,11 @@ int runRcc(int argc, char *argv[]) // Make sure fwrite to stdout doesn't do LF->CRLF if (library.format() == RCCResourceLibrary::Binary) _setmode(_fileno(stdout), _O_BINARY); + // Make sure QIODevice does not do LF->CRLF, + // otherwise we'll end up in CRCRLF instead of + // CRLF. + if (list) + mode &= ~QIODevice::Text; #endif // Q_OS_WIN // using this overload close() only flushes. out.open(stdout, mode); -- cgit v1.2.3 From a8f98959ef6881d571fa35201cd6721067a3204b Mon Sep 17 00:00:00 2001 From: Donald Carr Date: Thu, 24 Mar 2016 18:37:57 -0700 Subject: Make CFLAGS/CXXFLAGS behave consistently in config.tests The journald test was failing as sysroot was not being passed to the compiler in the compile test. This is due to the fact we were explicitly defining sysroot in the CXXFLAGS and not in CFLAGS. Change-Id: I4b4bda71f9aabc8e420e0e89ff3cc8fa3bbca201 Reviewed-by: Oswald Buddenhagen --- config.tests/unix/compile.test | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/config.tests/unix/compile.test b/config.tests/unix/compile.test index 65bc874617..b94e3d7ab0 100755 --- a/config.tests/unix/compile.test +++ b/config.tests/unix/compile.test @@ -13,6 +13,7 @@ DESCRIPTION=$7 shift 7 LFLAGS="$SYSROOT_FLAG" INCLUDEPATH="" +CFLAGS="$SYSROOT_FLAG" CXXFLAGS="$SYSROOT_FLAG" MAC_ARCH_CXXFLAGS="" MAC_ARCH_LFLAGS="" @@ -28,12 +29,14 @@ while [ "$#" -gt 0 ]; do shift ;; -arch) + MAC_ARCH_CFLAGS="$MAC_ARCH_CFLAGS -arch $2" MAC_ARCH_CXXFLAGS="$MAC_ARCH_CXXFLAGS -arch $2" MAC_ARCH_LFLAGS="$MAC_ARCH_LFLAGS -arch $2" shift ;; -F*|-m*|-x*) LFLAGS="$LFLAGS \"$PARAM\"" + CFLAGS="$CFLAGS \"$PARAM\"" CXXFLAGS="$CXXFLAGS \"$PARAM\"" ;; -L*|-l*|-pthread) @@ -44,10 +47,12 @@ while [ "$#" -gt 0 ]; do INCLUDEPATH="$INCLUDEPATH \"$INC\"" ;; -f*|-D*) + CFLAGS="$CFLAGS \"$PARAM\"" CXXFLAGS="$CXXFLAGS \"$PARAM\"" ;; -Qoption) # Two-argument form for the Sun Compiler + CFLAGS="$CFLAGS $PARAM \"$2\"" CXXFLAGS="$CXXFLAGS $PARAM \"$2\"" shift ;; @@ -67,7 +72,7 @@ test -r Makefile && $MAKE distclean >/dev/null 2>&1 # Make sure output from possible previous tests is gone rm -f "$EXE" "${EXE}.exe" -set -- "$OUTDIR/bin/qmake" -nocache -spec "$QMKSPEC" "CONFIG+=$QMAKE_CONFIG" "CONFIG+=android_app" "CONFIG-=debug_and_release app_bundle lib_bundle" "LIBS+=$LFLAGS" "LIBS+=$MAC_ARCH_LFLAGS" "INCLUDEPATH*=$INCLUDEPATH" "QMAKE_CXXFLAGS*=$CXXFLAGS" "QMAKE_CXXFLAGS+=$MAC_ARCH_CXXFLAGS" "$SRCDIR/$TEST/$EXE.pro" -o "$OUTDIR/$TEST/Makefile" +set -- "$OUTDIR/bin/qmake" -nocache -spec "$QMKSPEC" "CONFIG+=$QMAKE_CONFIG" "CONFIG+=android_app" "CONFIG-=debug_and_release app_bundle lib_bundle" "LIBS+=$LFLAGS" "LIBS+=$MAC_ARCH_LFLAGS" "INCLUDEPATH*=$INCLUDEPATH" "QMAKE_CFLAGS*=$CFLAGS" "QMAKE_CFLAGS+=$MAC_ARCH_CFLAGS" "QMAKE_CXXFLAGS*=$CXXFLAGS" "QMAKE_CXXFLAGS+=$MAC_ARCH_CXXFLAGS" "$SRCDIR/$TEST/$EXE.pro" -o "$OUTDIR/$TEST/Makefile" if [ "$VERBOSE" = "yes" ]; then OUTDIR=$OUTDIR "$@" && $MAKE && SUCCESS=yes else -- cgit v1.2.3 From 2693ca59e197651c05934daaf2b29e7386746140 Mon Sep 17 00:00:00 2001 From: Donald Carr Date: Wed, 30 Mar 2016 10:35:51 -0700 Subject: Adjust egl config.test to pass sysrooted libs We should really start using -L=/foo and -I=/foo inside of sysroots, this test was preventing us from doing so (while arguably buying us nothing). Change-Id: If6e67631c585493871231e5d8a9354fa72e07343 Reviewed-by: Laszlo Agocs Reviewed-by: Oswald Buddenhagen --- config.tests/qpa/egl-x11/egl-x11.pro | 2 +- config.tests/qpa/egl/egl.pro | 2 +- config.tests/qpa/eglfs-brcm/eglfs-brcm.pro | 2 +- config.tests/qpa/eglfs-egldevice/eglfs-egldevice.pro | 2 +- config.tests/unix/opengles2/opengles2.pro | 2 +- config.tests/unix/opengles3/opengles3.pro | 2 +- config.tests/unix/opengles31/opengles31.pro | 2 +- mkspecs/features/egl.prf | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/config.tests/qpa/egl-x11/egl-x11.pro b/config.tests/qpa/egl-x11/egl-x11.pro index c4e94ca40c..aceb03dd78 100644 --- a/config.tests/qpa/egl-x11/egl-x11.pro +++ b/config.tests/qpa/egl-x11/egl-x11.pro @@ -1,7 +1,7 @@ SOURCES = egl-x11.cpp for(p, QMAKE_LIBDIR_EGL) { - exists($$p):LIBS += -L$$p + LIBS += -L$$p } !isEmpty(QMAKE_INCDIR_EGL): INCLUDEPATH += $$QMAKE_INCDIR_EGL diff --git a/config.tests/qpa/egl/egl.pro b/config.tests/qpa/egl/egl.pro index f04d053543..b5396dab15 100644 --- a/config.tests/qpa/egl/egl.pro +++ b/config.tests/qpa/egl/egl.pro @@ -1,7 +1,7 @@ SOURCES = egl.cpp for(p, QMAKE_LIBDIR_EGL) { - exists($$p):LIBS += -L$$p + LIBS += -L$$p } !isEmpty(QMAKE_INCDIR_EGL): INCLUDEPATH += $$QMAKE_INCDIR_EGL diff --git a/config.tests/qpa/eglfs-brcm/eglfs-brcm.pro b/config.tests/qpa/eglfs-brcm/eglfs-brcm.pro index ce16a3a391..d8b1c3ec7e 100644 --- a/config.tests/qpa/eglfs-brcm/eglfs-brcm.pro +++ b/config.tests/qpa/eglfs-brcm/eglfs-brcm.pro @@ -5,7 +5,7 @@ CONFIG -= qt INCLUDEPATH += $$QMAKE_INCDIR_EGL for(p, QMAKE_LIBDIR_EGL) { - exists($$p):LIBS += -L$$p + LIBS += -L$$p } LIBS += -lEGL -lGLESv2 -lbcm_host diff --git a/config.tests/qpa/eglfs-egldevice/eglfs-egldevice.pro b/config.tests/qpa/eglfs-egldevice/eglfs-egldevice.pro index 87214abc7a..521a911219 100644 --- a/config.tests/qpa/eglfs-egldevice/eglfs-egldevice.pro +++ b/config.tests/qpa/eglfs-egldevice/eglfs-egldevice.pro @@ -1,7 +1,7 @@ SOURCES = eglfs-egldevice.cpp for(p, QMAKE_LIBDIR_EGL) { - exists($$p):LIBS += -L$$p + LIBS += -L$$p } INCLUDEPATH += $$QMAKE_INCDIR_EGL diff --git a/config.tests/unix/opengles2/opengles2.pro b/config.tests/unix/opengles2/opengles2.pro index c4d76895a8..da30b453c6 100644 --- a/config.tests/unix/opengles2/opengles2.pro +++ b/config.tests/unix/opengles2/opengles2.pro @@ -2,7 +2,7 @@ SOURCES = opengles2.cpp INCLUDEPATH += $$QMAKE_INCDIR_OPENGL_ES2 for(p, QMAKE_LIBDIR_OPENGL_ES2) { - exists($$p):LIBS += -L$$p + LIBS += -L$$p } CONFIG -= qt diff --git a/config.tests/unix/opengles3/opengles3.pro b/config.tests/unix/opengles3/opengles3.pro index 6942b57327..720985f14d 100644 --- a/config.tests/unix/opengles3/opengles3.pro +++ b/config.tests/unix/opengles3/opengles3.pro @@ -6,7 +6,7 @@ SOURCES = opengles3.cpp INCLUDEPATH += $$QMAKE_INCDIR_OPENGL_ES2 for(p, QMAKE_LIBDIR_OPENGL_ES2) { - exists($$p):LIBS += -L$$p + LIBS += -L$$p } CONFIG -= qt diff --git a/config.tests/unix/opengles31/opengles31.pro b/config.tests/unix/opengles31/opengles31.pro index 1df9cedfcd..225180e1c6 100644 --- a/config.tests/unix/opengles31/opengles31.pro +++ b/config.tests/unix/opengles31/opengles31.pro @@ -6,7 +6,7 @@ SOURCES = opengles31.cpp INCLUDEPATH += $$QMAKE_INCDIR_OPENGL_ES2 for(p, QMAKE_LIBDIR_OPENGL_ES2) { - exists($$p):LIBS += -L$$p + LIBS += -L$$p } CONFIG -= qt diff --git a/mkspecs/features/egl.prf b/mkspecs/features/egl.prf index c3bdd9fdf4..9fa0c9e219 100644 --- a/mkspecs/features/egl.prf +++ b/mkspecs/features/egl.prf @@ -4,5 +4,5 @@ QMAKE_CFLAGS += $$QMAKE_CFLAGS_EGL QMAKE_CXXFLAGS += $$QMAKE_CFLAGS_EGL LIBS += $$QMAKE_LFLAGS_EGL for(p, QMAKE_LIBDIR_EGL) { - exists($$p): LIBS_PRIVATE += -L$$p + LIBS_PRIVATE += -L$$p } -- cgit v1.2.3 From 01d43cece85456ae69810ea3bdaf4b0e164e1542 Mon Sep 17 00:00:00 2001 From: Donald Carr Date: Thu, 31 Mar 2016 09:54:55 -0700 Subject: Introduce RPI3 aarch32 mkspec Change-Id: Ia76f7f5b1793a16ac17285d19429f70d722675cf Reviewed-by: Laszlo Agocs --- mkspecs/devices/linux-rpi3-g++/qmake.conf | 41 ++++++++++++++++++++++++++ mkspecs/devices/linux-rpi3-g++/qplatformdefs.h | 34 +++++++++++++++++++++ 2 files changed, 75 insertions(+) create mode 100644 mkspecs/devices/linux-rpi3-g++/qmake.conf create mode 100644 mkspecs/devices/linux-rpi3-g++/qplatformdefs.h diff --git a/mkspecs/devices/linux-rpi3-g++/qmake.conf b/mkspecs/devices/linux-rpi3-g++/qmake.conf new file mode 100644 index 0000000000..600d3e7dc1 --- /dev/null +++ b/mkspecs/devices/linux-rpi3-g++/qmake.conf @@ -0,0 +1,41 @@ +# qmake configuration for the Raspberry Pi 3 + +include(../common/linux_device_pre.conf) + +# I consider it a bug that this is required, but our EGL config.test _requires_ it +QMAKE_LFLAGS += -Wl,-rpath-link,$$[QT_SYSROOT]/opt/vc/lib + +VC_LIBRARY_PATH = /opt/vc/lib +VC_INCLUDE_PATH = =/opt/vc/include + +# terrible, they do not appear to resolve "=" in rpath! +VC_LINK_LINE = -L=$${VC_LIBRARY_PATH} -Wl,-rpath-link,$$[QT_SYSROOT]$${VC_LIBRARY_PATH} + +QMAKE_LIBDIR_OPENGL_ES2 = =$${VC_LIBRARY_PATH} +QMAKE_LIBDIR_EGL = $$QMAKE_LIBDIR_OPENGL_ES2 +QMAKE_LIBDIR_OPENVG = $$QMAKE_LIBDIR_OPENGL_ES2 + +QMAKE_INCDIR_EGL = \ + $${VC_INCLUDE_PATH} \ + $${VC_INCLUDE_PATH}/interface/vcos/pthreads \ + $${VC_INCLUDE_PATH}/interface/vmcs_host/linux + +QMAKE_INCDIR_OPENGL_ES2 = $${QMAKE_INCDIR_EGL} + +QMAKE_LIBS_OPENGL_ES2 = $${VC_LINK_LINE} -lGLESv2 + +# The official opt vc EGL references GLESv2 symbols: need to link it +QMAKE_LIBS_EGL = $${VC_LINK_LINE} -lEGL -lGLESv2 + +# We deliberately override the existing Qt CFLAGS as they might be problematic +QMAKE_CFLAGS = -march=armv8-a+crc -mtune=cortex-a53 -mfpu=crypto-neon-fp-armv8 -pipe -Os -mthumb +QMAKE_CXXFLAGS = $$QMAKE_CFLAGS -std=c++1z + +DISTRO_OPTS += hard-float +DISTRO_OPTS += deb-multi-arch + +EGLFS_DEVICE_INTEGRATION= eglfs_brcm + +include(../common/linux_arm_device_post.conf) + +load(qt_config) diff --git a/mkspecs/devices/linux-rpi3-g++/qplatformdefs.h b/mkspecs/devices/linux-rpi3-g++/qplatformdefs.h new file mode 100644 index 0000000000..5ae49b35dd --- /dev/null +++ b/mkspecs/devices/linux-rpi3-g++/qplatformdefs.h @@ -0,0 +1,34 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the qmake spec of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL21$ +** 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 http://www.qt.io/terms-conditions. For further +** information use the contact form at http://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 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "../../linux-g++/qplatformdefs.h" -- cgit v1.2.3 From 57ecc00978115ec919d78be622c08d95f141032e Mon Sep 17 00:00:00 2001 From: Jake Petroules Date: Thu, 7 Apr 2016 11:43:00 -0700 Subject: Note the introductory version of network redirection related enums. These were missed in d815de8c26ccee33713e37a0fec2982755dcfe1f which originally added these values. Change-Id: I69618c90e71f7cc01eef3db477427759e62f626b Reviewed-by: Allan Sandfeld Jensen Reviewed-by: Mandeep Sandhu --- src/network/access/qnetworkreply.cpp | 2 ++ src/network/access/qnetworkrequest.cpp | 1 + 2 files changed, 3 insertions(+) diff --git a/src/network/access/qnetworkreply.cpp b/src/network/access/qnetworkreply.cpp index 26f7034c09..a7565560ac 100644 --- a/src/network/access/qnetworkreply.cpp +++ b/src/network/access/qnetworkreply.cpp @@ -135,10 +135,12 @@ QNetworkReplyPrivate::QNetworkReplyPrivate() \value TooManyRedirectsError while following redirects, the maximum limit was reached. The limit is by default set to 50 or as set by QNetworkRequest::setMaxRedirectsAllowed(). + (This value was introduced in 5.6.) \value InsecureRedirectError while following redirects, the network access API detected a redirect from a encrypted protocol (https) to an unencrypted one (http). + (This value was introduced in 5.6.) \value ProxyConnectionRefusedError the connection to the proxy server was refused (the proxy server is not accepting requests) diff --git a/src/network/access/qnetworkrequest.cpp b/src/network/access/qnetworkrequest.cpp index f5010198f3..2a62cb5f39 100644 --- a/src/network/access/qnetworkrequest.cpp +++ b/src/network/access/qnetworkrequest.cpp @@ -263,6 +263,7 @@ QT_BEGIN_NAMESPACE Indicates whether the Network Access API should automatically follow a HTTP redirect response or not. Currently redirects that are insecure, that is redirecting from "https" to "http" protocol, are not allowed. + (This value was introduced in 5.6.) \value User Special type. Additional information can be passed in -- cgit v1.2.3 From 8c427e5bdfcb54e19d10646d9ff45674077253c9 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Tue, 23 Feb 2016 16:18:05 -0800 Subject: Autotest: confirm that QHostAddress obeys RFC 5952 recommendations Change-Id: I0c94a5c2846b48c8aea7ffff1435b8a7ccbd4d9e Reviewed-by: Richard J. Moore Reviewed-by: Edward Welbourne --- .../network/kernel/qhostaddress/tst_qhostaddress.cpp | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/tests/auto/network/kernel/qhostaddress/tst_qhostaddress.cpp b/tests/auto/network/kernel/qhostaddress/tst_qhostaddress.cpp index 8069865d93..4d2d5fc67d 100644 --- a/tests/auto/network/kernel/qhostaddress/tst_qhostaddress.cpp +++ b/tests/auto/network/kernel/qhostaddress/tst_qhostaddress.cpp @@ -159,8 +159,16 @@ void tst_QHostAddress::setAddress_QString_data() QTest::newRow("ip4_06") << QString("123.0.0") << true << QString("123.0.0.0") << 4; // for the format of IPv6 addresses see also RFC 5952 - QTest::newRow("ip6_00") << QString("FEDC:BA98:7654:3210:FEDC:BA98:7654:3210") << true << QString("fedc:ba98:7654:3210:fedc:ba98:7654:3210") << 6; - QTest::newRow("ip6_01") << QString("1080:0000:0000:0000:0008:0800:200C:417A") << true << QString("1080::8:800:200c:417a") << 6; + // rule 4.1: Leading zeros MUST be suppressed + // rule 4.2.1: Shorten as Much as Possible + // rule 4.2.2: The symbol "::" MUST NOT be used to shorten just one 16-bit 0 field. + // rule 4.2.3: the longest run of consecutive 16-bit 0 fields MUST be shortened + // When the length of the consecutive 16-bit 0 fields, the first sequence + // of zero bits MUST be shortened + // rule 4.3: The characters "a", "b", "c", "d", "e", and "f" in an IPv6 address + // MUST be represented in lowercase + QTest::newRow("ip6_00") << QString("FEDC:BA98:7654:3210:FEDC:BA98:7654:3210") << true << QString("fedc:ba98:7654:3210:fedc:ba98:7654:3210") << 6; // 4.3 + QTest::newRow("ip6_01") << QString("1080:0000:0000:0000:0008:0800:200C:417A") << true << QString("1080::8:800:200c:417a") << 6; // 4.1, 4.2.1 QTest::newRow("ip6_02") << QString("1080:0:0:0:8:800:200C:417A") << true << QString("1080::8:800:200c:417a") << 6; QTest::newRow("ip6_03") << QString("1080::8:800:200C:417A") << true << QString("1080::8:800:200c:417a") << 6; QTest::newRow("ip6_04") << QString("FF01::43") << true << QString("ff01::43") << 6; @@ -173,10 +181,11 @@ void tst_QHostAddress::setAddress_QString_data() QTest::newRow("ip6_11") << QString("::FFFF:129.144.52.38") << true << QString("::ffff:129.144.52.38") << 6; QTest::newRow("ip6_12") << QString("1::FFFF:129.144.52.38") << true << QString("1::ffff:8190:3426") << 6; QTest::newRow("ip6_13") << QString("A:B::D:E") << true << QString("a:b::d:e") << 6; - QTest::newRow("ip6_14") << QString("1080:0:1:0:8:800:200C:417A") << true << QString("1080:0:1:0:8:800:200c:417a") << 6; + QTest::newRow("ip6_14") << QString("1080:0:1:0:8:800:200C:417A") << true << QString("1080:0:1:0:8:800:200c:417a") << 6; // 4.2.2 QTest::newRow("ip6_15") << QString("1080:0:1:0:8:800:200C:0") << true << QString("1080:0:1:0:8:800:200c:0") << 6; QTest::newRow("ip6_16") << QString("1080:0:1:0:8:800:0:0") << true << QString("1080:0:1:0:8:800::") << 6; - QTest::newRow("ip6_17") << QString("1080:0:0:0:8:800:0:0") << true << QString("1080::8:800:0:0") << 6; + QTest::newRow("ip6_17a") << QString("1080:0:0:8:800:0:0:0") << true << QString("1080:0:0:8:800::") << 6; // 4.2.3a + QTest::newRow("ip6_17b") << QString("1080:0:0:0:8:0:0:0") << true << QString("1080::8:0:0:0") << 6; // 4.2.3b QTest::newRow("ip6_18") << QString("0:1:1:1:8:800:0:0") << true << QString("0:1:1:1:8:800::") << 6; QTest::newRow("ip6_19") << QString("0:1:1:1:8:800:0:1") << true << QString("0:1:1:1:8:800:0:1") << 6; -- cgit v1.2.3 From b6eea89b67e0d3bb4f8f888fff21257eff0b65a5 Mon Sep 17 00:00:00 2001 From: David Faure Date: Sun, 3 Apr 2016 18:36:52 +0200 Subject: Fix crash when using QLockFile in a global destructor (for instance any global object which writes out to a config file in the destructor). If the global cache isn't available anymore, don't use it. Change-Id: I851a6e394d0b073aebf3ffd88b1966d424bfb92e Reviewed-by: Olivier Goffart (Woboq GmbH) --- src/corelib/io/qlockfile_unix.cpp | 2 ++ tests/auto/corelib/io/qlockfile/tst_qlockfile.cpp | 10 ++++++++++ 2 files changed, 12 insertions(+) diff --git a/src/corelib/io/qlockfile_unix.cpp b/src/corelib/io/qlockfile_unix.cpp index 623968b869..bcef84206e 100644 --- a/src/corelib/io/qlockfile_unix.cpp +++ b/src/corelib/io/qlockfile_unix.cpp @@ -136,6 +136,8 @@ static QBasicMutex fcntlLock; static bool fcntlWorksAfterFlock(const QString &fn) { QMutexLocker lock(&fcntlLock); + if (fcntlOK.isDestroyed()) + return QLockFilePrivate::checkFcntlWorksAfterFlock(fn); bool *worksPtr = fcntlOK->object(fn); if (!worksPtr) { worksPtr = new bool(QLockFilePrivate::checkFcntlWorksAfterFlock(fn)); diff --git a/tests/auto/corelib/io/qlockfile/tst_qlockfile.cpp b/tests/auto/corelib/io/qlockfile/tst_qlockfile.cpp index 21c5696d1d..4884c126d4 100644 --- a/tests/auto/corelib/io/qlockfile/tst_qlockfile.cpp +++ b/tests/auto/corelib/io/qlockfile/tst_qlockfile.cpp @@ -546,5 +546,15 @@ bool tst_QLockFile::overwritePidInLockFile(const QString &filePath, qint64 pid) return f.write(buf) == buf.size(); } +struct LockFileUsageInGlobalDtor +{ + ~LockFileUsageInGlobalDtor() { + QLockFile lockFile(QDir::currentPath() + "/lastlock"); + QVERIFY(lockFile.lock()); + QVERIFY(lockFile.isLocked()); + } +}; +LockFileUsageInGlobalDtor s_instance; + QTEST_MAIN(tst_QLockFile) #include "tst_qlockfile.moc" -- cgit v1.2.3 From 8686ff0d9c09af255a16d03a1f5a2f794c631424 Mon Sep 17 00:00:00 2001 From: David Faure Date: Sun, 27 Mar 2016 22:32:19 +0200 Subject: Doc: clarify redirection handling in QNetworkRequest The text for RedirectionTargetAttribute said the app has to handle redirections, and only said that this attribute wouldn't be set if FollowRedirectsAttribute is set, which was a bit confusing to read, before reading what exactly FollowRedirectsAttribute does. It does more than removing the other attribute, it actually follows the redirection... Change-Id: Idc634996e7b521ba05c05ca52438e47f1a411c85 Reviewed-by: Mandeep Sandhu Reviewed-by: Allan Sandfeld Jensen --- src/network/access/qnetworkrequest.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/network/access/qnetworkrequest.cpp b/src/network/access/qnetworkrequest.cpp index 2a62cb5f39..29a7c2c46d 100644 --- a/src/network/access/qnetworkrequest.cpp +++ b/src/network/access/qnetworkrequest.cpp @@ -138,11 +138,12 @@ QT_BEGIN_NAMESPACE Replies only, type: QMetaType::QUrl (no default) If present, it indicates that the server is redirecting the request to a different URL. The Network Access API does not by - default follow redirections: it's up to the application to + default follow redirections: the application can determine if the requested redirection should be allowed, - according to its security policies. However, if - QNetworkRequest::FollowRedirectsAttribute is set, then this attribute - will not be present in the reply. + according to its security policies, or it can set + QNetworkRequest::FollowRedirectsAttribute to true (in which case + the redirection will be followed and this attribute will not + be present in the reply). The returned URL might be relative. Use QUrl::resolved() to create an absolute URL out of it. -- cgit v1.2.3 From 093eec6fedd46d4065056376c5d9b56deb249fae Mon Sep 17 00:00:00 2001 From: Andreas Holzammer Date: Thu, 24 Mar 2016 16:22:33 +0100 Subject: wince: Fix intrinsics for X86 platforms when SSE2 is enabled SSE2 can use intrinsics, which are supported by WEC2013, but for WEC7 they need to be defined. Change-Id: I261f3db4db7abcb0b59598cef9cbad404635c3ec Reviewed-by: Friedemann Kleint Reviewed-by: Gunnar Roth Reviewed-by: Kevin Funk Reviewed-by: Lars Knoll --- src/corelib/tools/qsimd_p.h | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/corelib/tools/qsimd_p.h b/src/corelib/tools/qsimd_p.h index 8171184ad2..ca53908cf5 100644 --- a/src/corelib/tools/qsimd_p.h +++ b/src/corelib/tools/qsimd_p.h @@ -432,7 +432,13 @@ static inline quint64 qCpuFeatures() #ifdef Q_PROCESSOR_X86 // Bit scan functions for x86 -# if defined(Q_CC_MSVC) && !defined(Q_OS_WINCE) +# if defined(Q_CC_MSVC) +# if defined _WIN32_WCE && _WIN32_WCE < 0x800 +extern "C" unsigned char _BitScanForward(unsigned long* Index, unsigned long Mask); +extern "C" unsigned char _BitScanReverse(unsigned long* Index, unsigned long Mask); +# pragma intrinsic(_BitScanForward) +# pragma intrinsic(_BitScanReverse) +# endif // MSVC calls it _BitScanReverse and returns the carry flag, which we don't need static __forceinline unsigned long _bit_scan_reverse(uint val) { -- cgit v1.2.3 From 0328eec6a4efd52a8b75fa25b65e4cb3c28b96b3 Mon Sep 17 00:00:00 2001 From: Mitch Curtis Date: Sun, 10 Apr 2016 12:11:53 +0200 Subject: Improve grammar in QUndoStack::beginMacro() documentation Change-Id: I4e27014a9a39abc03cee25f9753a46225efa43b9 Reviewed-by: Venugopal Shivashankar --- src/widgets/util/qundostack.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/widgets/util/qundostack.cpp b/src/widgets/util/qundostack.cpp index 5163783b0b..5bcfa57b37 100644 --- a/src/widgets/util/qundostack.cpp +++ b/src/widgets/util/qundostack.cpp @@ -924,7 +924,7 @@ QAction *QUndoStack::createRedoAction(QObject *parent, const QString &prefix) co Calls to beginMacro() and endMacro() may be nested, but every call to beginMacro() must have a matching call to endMacro(). - While a macro is composed, the stack is disabled. This means that: + While a macro is being composed, the stack is disabled. This means that: \list \li indexChanged() and cleanChanged() are not emitted, \li canUndo() and canRedo() return false, -- cgit v1.2.3 From 7b4c02d527c448a3c8b3e9fa771e42f8bd7778ff Mon Sep 17 00:00:00 2001 From: Joerg Bornemann Date: Fri, 8 Apr 2016 17:21:07 +0200 Subject: Fix finding a helper executable in tst_QLocalSocket Use QFINDTESTDATA to find the socketprocess helper executable. Now tst_QLocalSocket::processConnection() passes when started from Qt Creator without adjusting the working directory. Change-Id: I97ca3334a381b3cd646647487529bcd90b969528 Reviewed-by: Thiago Macieira --- tests/auto/network/socket/qlocalsocket/tst_qlocalsocket.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/auto/network/socket/qlocalsocket/tst_qlocalsocket.cpp b/tests/auto/network/socket/qlocalsocket/tst_qlocalsocket.cpp index a96c88874e..99f40ca215 100644 --- a/tests/auto/network/socket/qlocalsocket/tst_qlocalsocket.cpp +++ b/tests/auto/network/socket/qlocalsocket/tst_qlocalsocket.cpp @@ -847,7 +847,8 @@ void tst_QLocalSocket::processConnection() const QString exeSuffix; #endif - QString socketProcess = QStringLiteral("socketprocess/socketprocess") + exeSuffix; + const QString socketProcess + = QFINDTESTDATA(QStringLiteral("socketprocess/socketprocess") + exeSuffix); QVERIFY(QFile::exists(socketProcess)); QFETCH(int, processes); -- cgit v1.2.3 From 045e417eff0a0efabd15d22361af7e6dff5f44f4 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Sun, 3 Apr 2016 13:02:47 +0200 Subject: [doc] QElapsedTimer: mention more clearly which functions cause undefined behavior Change-Id: Ic7ab0d81689e2cc78f39f5f32beaea74ca10ce38 Reviewed-by: Giuseppe D'Angelo Reviewed-by: Friedemann Kleint Reviewed-by: Olivier Goffart (Woboq GmbH) Reviewed-by: Thiago Macieira --- src/corelib/tools/qelapsedtimer_generic.cpp | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/src/corelib/tools/qelapsedtimer_generic.cpp b/src/corelib/tools/qelapsedtimer_generic.cpp index 210d372e15..8679aec810 100644 --- a/src/corelib/tools/qelapsedtimer_generic.cpp +++ b/src/corelib/tools/qelapsedtimer_generic.cpp @@ -79,7 +79,8 @@ void QElapsedTimer::start() Q_DECL_NOTHROW and then starting the timer again with start(), but it does so in one single operation, avoiding the need to obtain the clock value twice. - Restarting the timer makes it valid again. + Calling this function on a QElapsedTimer that is invalid + results in undefined behavior. The following example illustrates how to use this function to calibrate a parameter to a slow operation (for example, an iteration count) so that @@ -87,7 +88,7 @@ void QElapsedTimer::start() Q_DECL_NOTHROW \snippet qelapsedtimer/main.cpp 3 - \sa start(), invalidate(), elapsed() + \sa start(), invalidate(), elapsed(), isValid() */ qint64 QElapsedTimer::restart() Q_DECL_NOTHROW { @@ -100,8 +101,10 @@ qint64 QElapsedTimer::restart() Q_DECL_NOTHROW /*! \since 4.8 Returns the number of nanoseconds since this QElapsedTimer was last - started. Calling this function in a QElapsedTimer that was invalidated - will result in undefined results. + started. + + Calling this function on a QElapsedTimer that is invalid + results in undefined behavior. On platforms that do not provide nanosecond resolution, the value returned will be the best estimate available. @@ -115,10 +118,12 @@ qint64 QElapsedTimer::nsecsElapsed() const Q_DECL_NOTHROW /*! Returns the number of milliseconds since this QElapsedTimer was last - started. Calling this function in a QElapsedTimer that was invalidated - will result in undefined results. + started. - \sa start(), restart(), hasExpired(), invalidate() + Calling this function on a QElapsedTimer that is invalid + results in undefined behavior. + + \sa start(), restart(), hasExpired(), isValid(), invalidate() */ qint64 QElapsedTimer::elapsed() const Q_DECL_NOTHROW { @@ -166,7 +171,8 @@ qint64 QElapsedTimer::msecsTo(const QElapsedTimer &other) const Q_DECL_NOTHROW \a other was started before this object, the returned value will be negative. If it was started later, the returned value will be positive. - The return value is undefined if this object or \a other were invalidated. + Calling this function on or with a QElapsedTimer that is invalid + results in undefined behavior. \sa msecsTo(), elapsed() */ -- cgit v1.2.3 From af32319803847dd97a4df7a6fc6100e193403fb2 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Mon, 11 Apr 2016 10:09:21 +0200 Subject: QTreeView: re-use cached values in rowsInserted() The parentRowCount and the delta were already calculated a few lines up, so don't recalculate them here. This improves performance (rowCount() is a virtual function), as well as readability (delta is more readable than end - begin + 1). Change-Id: Iabe88852a61f7ef52139e1ba446e9d3f87d6bd04 Reviewed-by: Friedemann Kleint --- src/widgets/itemviews/qtreeview.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/widgets/itemviews/qtreeview.cpp b/src/widgets/itemviews/qtreeview.cpp index e6a6b2a447..135c417f15 100644 --- a/src/widgets/itemviews/qtreeview.cpp +++ b/src/widgets/itemviews/qtreeview.cpp @@ -2568,7 +2568,7 @@ void QTreeView::rowsInserted(const QModelIndex &parent, int start, int end) if (((parentItem != -1) && d->viewItems.at(parentItem).expanded) || (parent == d->root)) { d->doDelayedItemsLayout(); - } else if (parentItem != -1 && (d->model->rowCount(parent) == end - start + 1)) { + } else if (parentItem != -1 && parentRowCount == delta) { // the parent just went from 0 children to more. update to re-paint the decoration d->viewItems[parentItem].hasChildren = true; viewport()->update(); -- cgit v1.2.3 From 09487deeaea584b2abcc2b1049df2a8542bc113e Mon Sep 17 00:00:00 2001 From: Oliver Wolff Date: Fri, 1 Apr 2016 13:42:32 +0200 Subject: WinRT: Enable broadcasts The CanBroadcast flag for QNetworkInterface indicates the ability to work in broadcast mode. As WinRT natively supports udp broadcasts and they work out of the box this flag should be set there. Task-number: QTBUG-49026 Change-Id: I6623014287fe63dc1c353a6de265ebdf9114d013 Reviewed-by: Maurice Kalinowski --- src/network/kernel/qnetworkinterface_winrt.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/network/kernel/qnetworkinterface_winrt.cpp b/src/network/kernel/qnetworkinterface_winrt.cpp index 1945b2427f..d0a22e9a16 100644 --- a/src/network/kernel/qnetworkinterface_winrt.cpp +++ b/src/network/kernel/qnetworkinterface_winrt.cpp @@ -73,6 +73,7 @@ static QNetworkInterfacePrivate *interfaceFromProfile(IConnectionProfile *profil Q_ASSERT_SUCCEEDED(hr); if (connectivityLevel != NetworkConnectivityLevel_None) iface->flags = QNetworkInterface::IsUp | QNetworkInterface::IsRunning; + iface->flags |= QNetworkInterface::CanBroadcast; ComPtr adapter; hr = profile->get_NetworkAdapter(&adapter); -- cgit v1.2.3 From 14399b427cdb7662cbca6aa89443521301507b41 Mon Sep 17 00:00:00 2001 From: Oliver Wolff Date: Wed, 6 Apr 2016 10:42:05 +0200 Subject: winrt: fix callbacks by moving them to the xaml thread Change-Id: I7b4f007107e21c02646140acd5ebe5745ca79bce Reviewed-by: Maurice Kalinowski --- src/network/socket/qnativesocketengine_winrt.cpp | 118 +++++++++++++---------- 1 file changed, 67 insertions(+), 51 deletions(-) diff --git a/src/network/socket/qnativesocketengine_winrt.cpp b/src/network/socket/qnativesocketengine_winrt.cpp index 35b7d5474b..d1ebd19cca 100644 --- a/src/network/socket/qnativesocketengine_winrt.cpp +++ b/src/network/socket/qnativesocketengine_winrt.cpp @@ -298,8 +298,10 @@ bool QNativeSocketEngine::connectToHostByName(const QString &name, quint16 port) Q_ASSERT_SUCCEEDED(hr); d->socketState = QAbstractSocket::ConnectingState; - hr = d->connectOp->put_Completed(Callback( + hr = QEventDispatcherWinRT::runOnXamlThread([d]() { + return d->connectOp->put_Completed(Callback( d, &QNativeSocketEnginePrivate::handleConnectToHost).Get()); + }); Q_ASSERT_SUCCEEDED(hr); return d->socketState == QAbstractSocket::ConnectedState; @@ -309,50 +311,53 @@ bool QNativeSocketEngine::bind(const QHostAddress &address, quint16 port) { Q_D(QNativeSocketEngine); HRESULT hr; - ComPtr hostAddress; + hr = QEventDispatcherWinRT::runOnXamlThread([address, d, port, this]() { + HRESULT hr; + ComPtr hostAddress; - if (address != QHostAddress::Any && address != QHostAddress::AnyIPv4 && address != QHostAddress::AnyIPv6) { - ComPtr hostNameFactory; - hr = GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Networking_HostName).Get(), - &hostNameFactory); - Q_ASSERT_SUCCEEDED(hr); - const QString addressString = address.toString(); - HStringReference addressRef(reinterpret_cast(addressString.utf16())); - hr = hostNameFactory->CreateHostName(addressRef.Get(), &hostAddress); - RETURN_FALSE_IF_FAILED("QNativeSocketEngine::bind: Could not create hostname."); - } + if (address != QHostAddress::Any && address != QHostAddress::AnyIPv4 && address != QHostAddress::AnyIPv6) { + ComPtr hostNameFactory; + hr = GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Networking_HostName).Get(), + &hostNameFactory); + RETURN_HR_IF_FAILED("QNativeSocketEngine::bind: Could not obtain hostname factory"); + const QString addressString = address.toString(); + HStringReference addressRef(reinterpret_cast(addressString.utf16())); + hr = hostNameFactory->CreateHostName(addressRef.Get(), &hostAddress); + RETURN_HR_IF_FAILED("QNativeSocketEngine::bind: Could not create hostname."); + } - QString portQString = port ? QString::number(port) : QString(); - HStringReference portString(reinterpret_cast(portQString.utf16())); + QString portQString = port ? QString::number(port) : QString(); + HStringReference portString(reinterpret_cast(portQString.utf16())); - ComPtr op; - if (d->socketType == QAbstractSocket::TcpSocket) { - if (!d->tcpListener) { - hr = RoActivateInstance(HString::MakeReference(RuntimeClass_Windows_Networking_Sockets_StreamSocketListener).Get(), - &d->tcpListener); - Q_ASSERT_SUCCEEDED(hr); - } + ComPtr op; + if (d->socketType == QAbstractSocket::TcpSocket) { + if (!d->tcpListener) { + hr = RoActivateInstance(HString::MakeReference(RuntimeClass_Windows_Networking_Sockets_StreamSocketListener).Get(), + &d->tcpListener); + RETURN_HR_IF_FAILED("QNativeSocketEngine::bind: Could not create tcp listener"); + } - hr = QEventDispatcherWinRT::runOnXamlThread([d]() { - return d->tcpListener->add_ConnectionReceived( + hr = d->tcpListener->add_ConnectionReceived( Callback(d, &QNativeSocketEnginePrivate::handleClientConnection).Get(), &d->connectionToken); - }); - Q_ASSERT_SUCCEEDED(hr); - hr = d->tcpListener->BindEndpointAsync(hostAddress.Get(), portString.Get(), &op); - } else if (d->socketType == QAbstractSocket::UdpSocket) { - hr = d->udpSocket()->BindEndpointAsync(hostAddress.Get(), portString.Get(), &op); - } - if (hr == E_ACCESSDENIED) { - qErrnoWarning(hr, "Unable to bind socket (%s:%hu/%s). Please check your manifest capabilities.", - qPrintable(address.toString()), port, socketDescription(this).constData()); - return false; - } - Q_ASSERT_SUCCEEDED(hr); + RETURN_HR_IF_FAILED("QNativeSocketEngine::bind: Could not register client connection callback"); + hr = d->tcpListener->BindEndpointAsync(hostAddress.Get(), portString.Get(), &op); + } else if (d->socketType == QAbstractSocket::UdpSocket) { + hr = d->udpSocket()->BindEndpointAsync(hostAddress.Get(), portString.Get(), &op); + } + if (hr == E_ACCESSDENIED) { + qErrnoWarning(hr, "Unable to bind socket (%s:%hu/%s). Please check your manifest capabilities.", + qPrintable(address.toString()), port, socketDescription(this).constData()); + return hr; + } + RETURN_HR_IF_FAILED("QNativeSocketEngine::bind: Unable to bind socket"); - hr = op->put_Completed(Callback(d, &QNativeSocketEnginePrivate::handleBindCompleted).Get()); - Q_ASSERT_SUCCEEDED(hr); - hr = QWinRTFunctions::await(op); + hr = op->put_Completed(Callback(d, &QNativeSocketEnginePrivate::handleBindCompleted).Get()); + RETURN_HR_IF_FAILED("QNativeSocketEngine::bind: Could not register bind callback"); + hr = QWinRTFunctions::await(op); + RETURN_HR_IF_FAILED("QNativeSocketEngine::bind: Could not wait for bind to finish"); + return S_OK; + }); Q_ASSERT_SUCCEEDED(hr); d->socketState = QAbstractSocket::BoundState; @@ -404,7 +409,9 @@ int QNativeSocketEngine::accept() socketDescription(this).constData()); return -1; } - hr = op->put_Completed(Callback(d, &QNativeSocketEnginePrivate::handleReadyRead).Get()); + hr = QEventDispatcherWinRT::runOnXamlThread([d, op]() { + return op->put_Completed(Callback(d, &QNativeSocketEnginePrivate::handleReadyRead).Get()); + }); if (FAILED(hr)) { qErrnoWarning(hr, "accept(): Failed to set socket read callback (%s).", socketDescription(this).constData()); @@ -774,18 +781,22 @@ void QNativeSocketEngine::establishRead() Q_D(QNativeSocketEngine); HRESULT hr; - ComPtr stream; - hr = d->tcpSocket()->get_InputStream(&stream); - RETURN_VOID_IF_FAILED("Failed to get socket input stream"); + hr = QEventDispatcherWinRT::runOnXamlThread([d]() { + ComPtr stream; + HRESULT hr = d->tcpSocket()->get_InputStream(&stream); + RETURN_HR_IF_FAILED("QNativeSocketEngine::establishRead: Failed to get socket input stream"); - ComPtr buffer; - hr = g->bufferFactory->Create(READ_BUFFER_SIZE, &buffer); - Q_ASSERT_SUCCEEDED(hr); + ComPtr buffer; + hr = g->bufferFactory->Create(READ_BUFFER_SIZE, &buffer); + RETURN_HR_IF_FAILED("QNativeSocketEngine::establishRead: Failed to create buffer"); - ComPtr op; - hr = stream->ReadAsync(buffer.Get(), READ_BUFFER_SIZE, InputStreamOptions_Partial, &op); - RETURN_VOID_IF_FAILED("Failed to initiate socket read"); - hr = op->put_Completed(Callback(d, &QNativeSocketEnginePrivate::handleReadyRead).Get()); + ComPtr op; + hr = stream->ReadAsync(buffer.Get(), READ_BUFFER_SIZE, InputStreamOptions_Partial, &op); + RETURN_HR_IF_FAILED("QNativeSocketEngine::establishRead: Failed to initiate socket read"); + hr = op->put_Completed(Callback(d, &QNativeSocketEnginePrivate::handleReadyRead).Get()); + RETURN_HR_IF_FAILED("QNativeSocketEngine::establishRead: Failed to register read callback"); + return S_OK; + }); Q_ASSERT_SUCCEEDED(hr); } @@ -807,7 +818,10 @@ bool QNativeSocketEnginePrivate::createNewSocket(QAbstractSocket::SocketType soc hr = RoActivateInstance(HString::MakeReference(RuntimeClass_Windows_Networking_Sockets_DatagramSocket).Get(), &socket); Q_ASSERT_SUCCEEDED(hr); socketDescriptor = qintptr(socket.Detach()); - hr = udpSocket()->add_MessageReceived(Callback(this, &QNativeSocketEnginePrivate::handleNewDatagram).Get(), &connectionToken); + hr = QEventDispatcherWinRT::runOnXamlThread([this]() { + HRESULT hr = udpSocket()->add_MessageReceived(Callback(this, &QNativeSocketEnginePrivate::handleNewDatagram).Get(), &connectionToken); + return hr; + }); Q_ASSERT_SUCCEEDED(hr); break; } @@ -1297,7 +1311,9 @@ HRESULT QNativeSocketEnginePrivate::handleReadyRead(IAsyncBufferOperation *async socketDescription(q).constData()); return S_OK; } - hr = op->put_Completed(Callback(this, &QNativeSocketEnginePrivate::handleReadyRead).Get()); + hr = QEventDispatcherWinRT::runOnXamlThread([op, this]() { + return op->put_Completed(Callback(this, &QNativeSocketEnginePrivate::handleReadyRead).Get()); + }); if (FAILED(hr)) { qErrnoWarning(hr, "handleReadyRead(): Failed to set socket read callback (%s).", socketDescription(q).constData()); -- cgit v1.2.3 From cd17321213917607fe8804f90698ff94301aa3fc Mon Sep 17 00:00:00 2001 From: Oliver Wolff Date: Wed, 6 Apr 2016 10:46:00 +0200 Subject: winrt: Use correct socket error on socket close Change-Id: I6d39b091e48a911534cb79d42d33d16041261cfb Reviewed-by: Maurice Kalinowski --- src/network/socket/qnativesocketengine_winrt.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/network/socket/qnativesocketengine_winrt.cpp b/src/network/socket/qnativesocketengine_winrt.cpp index d1ebd19cca..0ff76adecf 100644 --- a/src/network/socket/qnativesocketengine_winrt.cpp +++ b/src/network/socket/qnativesocketengine_winrt.cpp @@ -1246,7 +1246,7 @@ HRESULT QNativeSocketEnginePrivate::handleReadyRead(IAsyncBufferOperation *async // that the connection was closed. The socket cannot be closed here, as the subsequent read // might fail then. if (status == Error || status == Canceled) { - setError(QAbstractSocket::NetworkError, RemoteHostClosedErrorString); + setError(QAbstractSocket::RemoteHostClosedError, RemoteHostClosedErrorString); socketState = QAbstractSocket::UnconnectedState; if (notifyOnRead) emit q->readReady(); @@ -1265,7 +1265,7 @@ HRESULT QNativeSocketEnginePrivate::handleReadyRead(IAsyncBufferOperation *async // the closing of the socket won't be communicated to the caller. So only the error is set. The // actual socket close happens inside of read. if (!bufferLength) { - setError(QAbstractSocket::NetworkError, RemoteHostClosedErrorString); + setError(QAbstractSocket::RemoteHostClosedError, RemoteHostClosedErrorString); socketState = QAbstractSocket::UnconnectedState; if (notifyOnRead) emit q->readReady(); -- cgit v1.2.3 From e108db5a9ae9ef4495f09630b8d2f0feb1534550 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Mon, 11 Apr 2016 13:30:42 +0200 Subject: QTestlib: Document newly added enumeration value KeyAction:Shortcut. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Amends change 0e342fce4c665d72a50147c4f4b30ea08cc6c87b, fixing a qdoc warning: qtbase/src/testlib/qtestcase.qdoc:524: warning: Undocumented enum item 'Shortcut' in QTest::KeyAction Change-Id: I7a7116bd5ff160c4a13f2fb0f9512f0d71385a4b Reviewed-by: Leena Miettinen Reviewed-by: Tor Arne Vestbø --- src/testlib/qtestcase.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/testlib/qtestcase.cpp b/src/testlib/qtestcase.cpp index 8de631094d..4643013371 100644 --- a/src/testlib/qtestcase.cpp +++ b/src/testlib/qtestcase.cpp @@ -645,6 +645,7 @@ static void stackTrace() \value Press The key is pressed. \value Release The key is released. \value Click The key is clicked (pressed and released). + \value Shortcut A shortcut is activated. This value has been added in Qt 5.6. */ /*! \enum QTest::MouseAction -- cgit v1.2.3 From f156c33c2739d84b97cdedf6ae9568b9cea728d5 Mon Sep 17 00:00:00 2001 From: Dmitry Shachnev Date: Fri, 1 Apr 2016 21:28:00 +0200 Subject: dbustray: Implement better detection of indicator-application We need to do the icon cache trick all desktops using indicator-application, these are not limited to Unity. For example, the default Xubuntu and Lubuntu desktops use indicator-application too. Without this, tray icons will be improperly shown on these desktops. Change-Id: Id397bbe9b594152d7c3a29c36c853e928af7dde4 Reviewed-by: Shawn Rutledge --- src/corelib/io/qlockfile_p.h | 3 ++- src/platformsupport/dbustray/qdbustrayicon.cpp | 18 ++++++++++++++++-- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/src/corelib/io/qlockfile_p.h b/src/corelib/io/qlockfile_p.h index 48b642abd0..468b4c0d29 100644 --- a/src/corelib/io/qlockfile_p.h +++ b/src/corelib/io/qlockfile_p.h @@ -75,7 +75,8 @@ public: // Returns \c true if the lock belongs to dead PID, or is old. // The attempt to delete it will tell us if it was really stale or not, though. bool isApparentlyStale() const; - static QString processNameByPid(qint64 pid); + // used in dbusmenu + Q_CORE_EXPORT static QString processNameByPid(qint64 pid); #ifdef Q_OS_UNIX static int checkFcntlWorksAfterFlock(const QString &fn); diff --git a/src/platformsupport/dbustray/qdbustrayicon.cpp b/src/platformsupport/dbustray/qdbustrayicon.cpp index 87083c8a55..7dbdb3a35b 100644 --- a/src/platformsupport/dbustray/qdbustrayicon.cpp +++ b/src/platformsupport/dbustray/qdbustrayicon.cpp @@ -47,13 +47,19 @@ #include #include #include +#include +#include #include +// Defined in Windows headers which get included by qlockfile_p.h +#undef interface + QT_BEGIN_NAMESPACE Q_LOGGING_CATEGORY(qLcTray, "qt.qpa.tray") static const QString KDEItemFormat = QStringLiteral("org.kde.StatusNotifierItem-%1-%2"); +static const QString KDEWatcherService = QStringLiteral("org.kde.StatusNotifierWatcher"); static const QString TempFileTemplate = QDir::tempPath() + QStringLiteral("/qt-trayicon-XXXXXX.png"); static const QString XdgNotificationService = QStringLiteral("org.freedesktop.Notifications"); static const QString XdgNotificationPath = QStringLiteral("/org/freedesktop/Notifications"); @@ -136,9 +142,17 @@ void QDBusTrayIcon::setStatus(const QString &status) QTemporaryFile *QDBusTrayIcon::tempIcon(const QIcon &icon) { - // Hack for Unity, which doesn't handle icons sent across D-Bus: + // Hack for indicator-application, which doesn't handle icons sent across D-Bus: // save the icon to a temp file and set the icon name to that filename. - static bool necessary = (QGuiApplicationPrivate::platformIntegration()->services()->desktopEnvironment().split(':').contains("UNITY")); + static bool necessity_checked = false; + static bool necessary = false; + if (!necessity_checked) { + QDBusConnection session = QDBusConnection::sessionBus(); + uint pid = session.interface()->servicePid(KDEWatcherService).value(); + QString processName = QLockFilePrivate::processNameByPid(pid); + necessary = processName.endsWith(QStringLiteral("indicator-application-service")); + necessity_checked = true; + } if (!necessary) return Q_NULLPTR; QTemporaryFile *ret = new QTemporaryFile(TempFileTemplate, this); -- cgit v1.2.3 From 3f73ecd59aea46d6ddd8d5dc1e7d4ace6307bafa Mon Sep 17 00:00:00 2001 From: Elena Zaretskaya Date: Sat, 9 Apr 2016 00:36:34 +0400 Subject: Fix 2 cursors under EGLFS_KMS Don't create hwcursor if it is disabled in QT_QPA_EGLFS_KMS_CONFIG. Task-number: QTBUG-52403 Change-Id: I4e6f45d5b773dc2d50cd012179cd23452d910537 Reviewed-by: Laszlo Agocs --- .../platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsdevice.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsdevice.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsdevice.cpp index c29d64c06d..8ba0a5cdd0 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsdevice.cpp +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsdevice.cpp @@ -417,7 +417,7 @@ void QEglFSKmsDevice::createScreens() Q_FOREACH (QPlatformScreen *screen, siblings) static_cast(screen)->setVirtualSiblings(siblings); - if (primaryScreen) + if (primaryScreen && m_integration->hwCursor()) m_globalCursor = new QEglFSKmsCursor(primaryScreen); } } -- cgit v1.2.3 From 0a1c8cc6686cb80cb5c35509c9eaa1fe9e27c495 Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Mon, 21 Mar 2016 11:38:05 +0100 Subject: Android: Support build with latest available SDK version To make custom builds of Qt possible, we no longer require the minimum SDK platform to be present on the system. Instead we will look for any version higher than the minimum requirement if the minimum is not available. If the minimum required platform is available, then it will still be preferred. Change-Id: I3e804af89aba36e27a7da1e46a25c0c5798aeaf2 Reviewed-by: BogDan Vatra Reviewed-by: Oswald Buddenhagen --- mkspecs/features/java.prf | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/mkspecs/features/java.prf b/mkspecs/features/java.prf index 54dced2865..6b9bbd3409 100644 --- a/mkspecs/features/java.prf +++ b/mkspecs/features/java.prf @@ -6,7 +6,18 @@ android { ANDROID_JAR_FILE = $$ANDROID_SDK_ROOT/platforms/$$API_VERSION_TO_USE/android.jar !exists($$ANDROID_JAR_FILE) { - error("The Path $$ANDROID_JAR_FILE does not exist. Make sure the ANDROID_SDK_ROOT and ANDROID_API_VERSION environment variables are correctly set.") + ANDROID_API_VERSION = $$section(API_VERSION_TO_USE, -, 1, 1) # Get version number from android-XY to ensure numeric comparison + ANDROID_API_VERSIONS = $$files($$ANDROID_SDK_ROOT/platforms/*) + for (VERSION, ANDROID_API_VERSIONS) { + BASENAME = $$basename(VERSION) + BASENAME = $$section(BASENAME, -, 1, 1) + greaterThan(BASENAME, $$ANDROID_API_VERSION): ANDROID_API_VERSION = $$BASENAME + } + API_VERSION_TO_USE = android-$$ANDROID_API_VERSION + ANDROID_JAR_FILE = $$ANDROID_SDK_ROOT/platforms/$$API_VERSION_TO_USE/android.jar + } + !exists($$ANDROID_JAR_FILE) { + error("No suitable Android SDK platform found. Minimum version is $${API_VERSION_TO_USE}.") } JAVACLASSPATH += $$ANDROID_JAR_FILE -- cgit v1.2.3 From 838fd4039e6ac48761cf1064d94b735902b014ac Mon Sep 17 00:00:00 2001 From: Jake Petroules Date: Wed, 6 Apr 2016 20:36:45 -0700 Subject: Fix bugs in accuracy of target path calculation in resolve_target. Incidentally, this introduces QMAKE_RESOLVED_BUNDLE, which can be used to determine the path of the bundle wrapper itself as well as the executable target. This is necessary for a subsequent patch adding support for -separate-debug-info on Apple platforms. Change-Id: Ia11430026b8e3f171e5db6677b190b8356832805 Reviewed-by: Oswald Buddenhagen --- mkspecs/features/resolve_target.prf | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/mkspecs/features/resolve_target.prf b/mkspecs/features/resolve_target.prf index d6460c1d9d..5c3a46e117 100644 --- a/mkspecs/features/resolve_target.prf +++ b/mkspecs/features/resolve_target.prf @@ -33,7 +33,18 @@ win32 { mac { equals(TEMPLATE, lib) { lib_bundle { - QMAKE_RESOLVED_TARGET = $${QMAKE_RESOLVED_TARGET}$${TARGET}.framework/$${TARGET} + !isEmpty(QMAKE_FRAMEWORK_BUNDLE_NAME): \ + framework_target = $$QMAKE_FRAMEWORK_BUNDLE_NAME + else: \ + framework_target = $$TARGET + QMAKE_RESOLVED_BUNDLE = $${QMAKE_RESOLVED_TARGET}$${framework_target}.framework + !shallow_bundle { + TEMP_VERSION = $$section(VERSION, ., 0, 0) + isEmpty(TEMP_VERSION):TEMP_VERSION = A + QMAKE_RESOLVED_TARGET = $${QMAKE_RESOLVED_BUNDLE}/Versions/$${TEMP_VERSION}/$${TARGET} + } else { + QMAKE_RESOLVED_TARGET = $${QMAKE_RESOLVED_BUNDLE}/$${TARGET} + } } else { QMAKE_RESOLVED_TARGET = $${QMAKE_RESOLVED_TARGET}$${LIBPREFIX}$${TARGET} !plugin { @@ -46,7 +57,15 @@ win32 { } } else { app_bundle { - QMAKE_RESOLVED_TARGET = $${QMAKE_RESOLVED_TARGET}$${TARGET}.app/Contents/MacOS/$${TARGET} + !isEmpty(QMAKE_APPLICATION_BUNDLE_NAME): \ + app_target = $$QMAKE_APPLICATION_BUNDLE_NAME + else: \ + app_target = $$TARGET + QMAKE_RESOLVED_BUNDLE = $${QMAKE_RESOLVED_TARGET}$${app_target}.app + !shallow_bundle: \ + QMAKE_RESOLVED_TARGET = $${QMAKE_RESOLVED_BUNDLE}/Contents/MacOS/$${TARGET} + else: \ + QMAKE_RESOLVED_TARGET = $${QMAKE_RESOLVED_BUNDLE}/$${TARGET} } else { QMAKE_RESOLVED_TARGET = $${QMAKE_RESOLVED_TARGET}$${TARGET} } -- cgit v1.2.3 From 7fb740f5186e90d9470c4245c9e9072cea3fd3d8 Mon Sep 17 00:00:00 2001 From: Jake Petroules Date: Fri, 8 Apr 2016 16:50:29 -0700 Subject: Don't indicate which versions of OS X are supported in QSysInfo docs. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is not done for other platforms (iOS or Windows) and eliminates a maintenance burden and potential of inconsistencies with other parts of the documentation (as illustrated by the fact that this page indicates the wrong minimum supported version). The Supported Platforms page will be the authoritative (and only) source of which particular versions of a given operating system are supported. Change-Id: I5a31f68965265f2dcd6515b1fa9385a9e9078274 Reviewed-by: Topi Reiniö Reviewed-by: Morten Johan Sørvig --- src/corelib/global/qglobal.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/corelib/global/qglobal.cpp b/src/corelib/global/qglobal.cpp index e8c50dff2b..461b0f383d 100644 --- a/src/corelib/global/qglobal.cpp +++ b/src/corelib/global/qglobal.cpp @@ -1121,13 +1121,13 @@ bool qSharedBuild() Q_DECL_NOTHROW QSysInfo::MacintoshVersion variable gives the version of the system on which the application is run. - \value MV_9 Mac OS 9 (unsupported) - \value MV_10_0 Mac OS X 10.0 (unsupported) - \value MV_10_1 Mac OS X 10.1 (unsupported) - \value MV_10_2 Mac OS X 10.2 (unsupported) - \value MV_10_3 Mac OS X 10.3 (unsupported) - \value MV_10_4 Mac OS X 10.4 (unsupported) - \value MV_10_5 Mac OS X 10.5 (unsupported) + \value MV_9 Mac OS 9 + \value MV_10_0 Mac OS X 10.0 + \value MV_10_1 Mac OS X 10.1 + \value MV_10_2 Mac OS X 10.2 + \value MV_10_3 Mac OS X 10.3 + \value MV_10_4 Mac OS X 10.4 + \value MV_10_5 Mac OS X 10.5 \value MV_10_6 Mac OS X 10.6 \value MV_10_7 Mac OS X 10.7 \value MV_10_8 OS X 10.8 -- cgit v1.2.3 From 5f41d344e9d66434be13a9644b4da08dd01974a9 Mon Sep 17 00:00:00 2001 From: Gabriel de Dietrich Date: Wed, 6 Apr 2016 16:09:25 -0700 Subject: QNSView: Disable focus ring MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Not only we don't need Cocoa to display it for us, but it also seems to take a lot of time after the call to -[NSView setNeedsDisplayInRect:]. While resizing a large and busy widgets window, we can decrease the relative time spent in -[QNSView flushBackingStore:region: offset:] from over 15% down to around 3%. Change-Id: I2a8d51be28b77c4c3da2588d9a14e461e7910167 Reviewed-by: Timur Pocheptsov Reviewed-by: Morten Johan Sørvig --- src/plugins/platforms/cocoa/qnsview.mm | 1 + 1 file changed, 1 insertion(+) diff --git a/src/plugins/platforms/cocoa/qnsview.mm b/src/plugins/platforms/cocoa/qnsview.mm index 90a7004938..7e9b9aa839 100644 --- a/src/plugins/platforms/cocoa/qnsview.mm +++ b/src/plugins/platforms/cocoa/qnsview.mm @@ -164,6 +164,7 @@ static NSString *_q_NSWindowDidChangeOcclusionStateNotification = nil; } m_isMenuView = false; + self.focusRingType = NSFocusRingTypeNone; } return self; } -- cgit v1.2.3 From 0f7171f290f0d137b4034c617d4c1fd169079209 Mon Sep 17 00:00:00 2001 From: Jesus Fernandez Date: Mon, 11 Apr 2016 10:55:30 +0200 Subject: Better error message when trying to load an invalid resource Before this change QFile::errorString function was returning an "Unknown error". Now it will return the typical ENOENT string. Task-number: QTBUG-45259 Change-Id: Ib7634f1aa5d91f77151cf92c58d3956e20a4cc6b Reviewed-by: hjk --- src/corelib/io/qresource.cpp | 6 ++++-- tests/auto/corelib/io/qfile/tst_qfile.cpp | 4 ++++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/corelib/io/qresource.cpp b/src/corelib/io/qresource.cpp index 0674ef34e0..c584933b97 100644 --- a/src/corelib/io/qresource.cpp +++ b/src/corelib/io/qresource.cpp @@ -1252,8 +1252,10 @@ bool QResourceFileEngine::open(QIODevice::OpenMode flags) } if(flags & QIODevice::WriteOnly) return false; - if(!d->resource.isValid()) - return false; + if (!d->resource.isValid()) { + d->errorString = qt_error_string(ENOENT); + return false; + } return true; } diff --git a/tests/auto/corelib/io/qfile/tst_qfile.cpp b/tests/auto/corelib/io/qfile/tst_qfile.cpp index 1c695a1113..b1e383dda1 100644 --- a/tests/auto/corelib/io/qfile/tst_qfile.cpp +++ b/tests/auto/corelib/io/qfile/tst_qfile.cpp @@ -543,6 +543,10 @@ void tst_QFile::open_data() << false << QFile::OpenError; QTest::newRow("noreadfile") << QString::fromLatin1(noReadFile) << int(QIODevice::ReadOnly) << false << QFile::OpenError; + QTest::newRow("resource_file") << QString::fromLatin1(":/does/not/exist") + << int(QIODevice::ReadOnly) + << false + << QFile::OpenError; #if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT) //opening devices requires administrative privileges (and elevation). HANDLE hTest = CreateFile(_T("\\\\.\\PhysicalDrive0"), GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); -- cgit v1.2.3 From 51f040866b3a50e2e8de180a157f51f261531eb0 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Tue, 12 Apr 2016 13:47:08 +0200 Subject: remove empty dylib.prf it doesn't appear to be referenced in any way, either. Change-Id: Ifd30b435e3e628cd5e48ae24e9aef01c662d6d61 Reviewed-by: Joerg Bornemann --- mkspecs/features/unix/dylib.prf | 1 - 1 file changed, 1 deletion(-) delete mode 100644 mkspecs/features/unix/dylib.prf diff --git a/mkspecs/features/unix/dylib.prf b/mkspecs/features/unix/dylib.prf deleted file mode 100644 index 8b13789179..0000000000 --- a/mkspecs/features/unix/dylib.prf +++ /dev/null @@ -1 +0,0 @@ - -- cgit v1.2.3 From 949aaffb4fda892f39ae488496db2270a65cb1c1 Mon Sep 17 00:00:00 2001 From: Edward Welbourne Date: Tue, 15 Mar 2016 15:50:37 +0100 Subject: tst_QNetworkReply: fix mis-guided use of QSKIP(). QSKIP() causes the whole test to be skipped, where this work-around for a known quirk of the test server only requires skipping a single Q_COMPARE(); the rest of the test passes fine without it. Change-Id: Ie4612bd428f4cb4b342fad908cc2784fbadf069c Reviewed-by: Timur Pocheptsov --- tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp b/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp index ce56dcacba..088b721a89 100644 --- a/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp +++ b/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp @@ -6814,9 +6814,9 @@ void tst_QNetworkReply::authenticationCacheAfterCancel() QTestEventLoop::instance().enterLoop(10); QVERIFY(!QTestEventLoop::instance().timeout()); - if (reply->error() == QNetworkReply::HostNotFoundError) - QSKIP("skip because of quirk in the old test server"); - QCOMPARE(reply->error(), QNetworkReply::ProxyAuthenticationRequiredError); + // Work round known quirk in the old test server: + if (reply->error() != QNetworkReply::HostNotFoundError) + QCOMPARE(reply->error(), QNetworkReply::ProxyAuthenticationRequiredError); QCOMPARE(authSpy.count(), 0); QVERIFY(proxyAuthSpy.count() > 0); proxyAuthSpy.clear(); -- cgit v1.2.3 From 541c9d4d2acd045459c3e75eee80c63b36af9ed0 Mon Sep 17 00:00:00 2001 From: Edward Welbourne Date: Tue, 15 Mar 2016 17:00:29 +0100 Subject: tst_QNetworkReply: Commentary fixes on test server workarounds. Follow-up to commit 6fd205d5: document which version of danted shall make one work-around redundant, document that another work-around is still needed even with that v1.1.19; and remove a comment that referred back to an XFAIL that commit 6fd205d5 removed. Change-Id: I270b662528127c82184bff20b3cecea4f0c41b41 Reviewed-by: Timur Pocheptsov --- tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp b/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp index 088b721a89..02aca3d6c1 100644 --- a/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp +++ b/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp @@ -6814,19 +6814,19 @@ void tst_QNetworkReply::authenticationCacheAfterCancel() QTestEventLoop::instance().enterLoop(10); QVERIFY(!QTestEventLoop::instance().timeout()); - // Work round known quirk in the old test server: + // Work round known quirk in the old test server (danted -v < v1.1.19): if (reply->error() != QNetworkReply::HostNotFoundError) QCOMPARE(reply->error(), QNetworkReply::ProxyAuthenticationRequiredError); QCOMPARE(authSpy.count(), 0); QVERIFY(proxyAuthSpy.count() > 0); proxyAuthSpy.clear(); - //QTBUG-23136 workaround + // QTBUG-23136 workaround (needed even with danted v1.1.19): if (proxy.port() == 1081) { #ifdef QT_BUILD_INTERNAL QNetworkAccessManagerPrivate::clearCache(&manager); #else - return; //XFAIL result above + return; #endif } -- cgit v1.2.3 From c327fb79e1a50c825a945e97f2c66d07a1c6d225 Mon Sep 17 00:00:00 2001 From: Allan Sandfeld Jensen Date: Tue, 12 Apr 2016 10:12:09 +0200 Subject: Use QTransform instead of doing transforms manually Minor cleanup of QOutlineMapper to take advantage of QTransform. Change-Id: I15534970a821c7f1de42f4a5a2560f04ae420d16 Reviewed-by: Gunnar Sletta --- src/gui/painting/qoutlinemapper.cpp | 44 +++++-------------------------------- src/gui/painting/qoutlinemapper_p.h | 23 ++----------------- 2 files changed, 8 insertions(+), 59 deletions(-) diff --git a/src/gui/painting/qoutlinemapper.cpp b/src/gui/painting/qoutlinemapper.cpp index 9eb6ee93f2..0d10fa18bb 100644 --- a/src/gui/painting/qoutlinemapper.cpp +++ b/src/gui/painting/qoutlinemapper.cpp @@ -38,9 +38,10 @@ ****************************************************************************/ #include "qoutlinemapper_p.h" -#include + +#include "qbezier_p.h" #include "qmath.h" -#include +#include "qpainterpath_p.h" #include @@ -187,39 +188,9 @@ void QOutlineMapper::endOutline() QPointF *elements = m_elements.data(); // Transform the outline - if (m_txop == QTransform::TxNone) { - // Nothing to do. - } else if (m_txop == QTransform::TxTranslate) { - for (int i = 0; i < m_elements.size(); ++i) { - QPointF &e = elements[i]; - e = QPointF(e.x() + m_dx, e.y() + m_dy); - } - } else if (m_txop == QTransform::TxScale) { - for (int i = 0; i < m_elements.size(); ++i) { - QPointF &e = elements[i]; - e = QPointF(m_m11 * e.x() + m_dx, m_m22 * e.y() + m_dy); - } - } else if (m_txop < QTransform::TxProject) { - for (int i = 0; i < m_elements.size(); ++i) { - QPointF &e = elements[i]; - e = QPointF(m_m11 * e.x() + m_m21 * e.y() + m_dx, - m_m22 * e.y() + m_m12 * e.x() + m_dy); - } - } else { - const QVectorPath vp((qreal *)elements, m_elements.size(), - m_element_types.size() ? m_element_types.data() : 0); - QPainterPath path = vp.convertToPainterPath(); - path = QTransform(m_m11, m_m12, m_m13, m_m21, m_m22, m_m23, m_dx, m_dy, m_m33).map(path); - if (!(m_outline.flags & QT_FT_OUTLINE_EVEN_ODD_FILL)) - path.setFillRule(Qt::WindingFill); - uint old_txop = m_txop; - m_txop = QTransform::TxNone; - if (path.isEmpty()) - m_valid = false; - else - convertPath(path); - m_txop = old_txop; - return; + if (!m_in_clip_elements) { + for (int i = 0; i < m_elements.size(); ++i) + elements[i] = m_transform.map(elements[i]); } controlPointRect = boundingRect(elements, m_elements.size()); @@ -387,13 +358,10 @@ void QOutlineMapper::clipElements(const QPointF *elements, QPainterPath clipPath; clipPath.addRect(m_clip_rect); QPainterPath clippedPath = path.intersected(clipPath); - uint old_txop = m_txop; - m_txop = QTransform::TxNone; if (clippedPath.isEmpty()) m_valid = false; else convertPath(clippedPath); - m_txop = old_txop; m_in_clip_elements = false; } diff --git a/src/gui/painting/qoutlinemapper_p.h b/src/gui/painting/qoutlinemapper_p.h index 05b2fd14ec..47413d920c 100644 --- a/src/gui/painting/qoutlinemapper_p.h +++ b/src/gui/painting/qoutlinemapper_p.h @@ -104,16 +104,7 @@ public: */ void setMatrix(const QTransform &m) { - m_m11 = m.m11(); - m_m12 = m.m12(); - m_m13 = m.m13(); - m_m21 = m.m21(); - m_m22 = m.m22(); - m_m23 = m.m23(); - m_m33 = m.m33(); - m_dx = m.dx(); - m_dy = m.dy(); - m_txop = m.type(); + m_transform = m; qreal scale; qt_scaleForTransform(m, &scale); @@ -207,20 +198,10 @@ public: QRectF controlPointRect; // only valid after endOutline() QT_FT_Outline m_outline; - uint m_txop; int m_subpath_start; - // Matrix - qreal m_m11; - qreal m_m12; - qreal m_m13; - qreal m_m21; - qreal m_m22; - qreal m_m23; - qreal m_m33; - qreal m_dx; - qreal m_dy; + QTransform m_transform; qreal m_curve_threshold; -- cgit v1.2.3 From 0b3e45fa0ae40e1271256a134effbcc5f3e99017 Mon Sep 17 00:00:00 2001 From: Anton Kudryavtsev Date: Mon, 11 Apr 2016 15:33:41 +0300 Subject: Use takeFirst() instead of first() with removeFirst() Reduce code size and improve readability. Change-Id: I5ec035a39cb607f15748aaa08d73f1c1bc8e4ad8 Reviewed-by: Oswald Buddenhagen Reviewed-by: Thiago Macieira --- src/corelib/io/qprocess.cpp | 6 ++---- src/widgets/itemviews/qheaderview.cpp | 3 +-- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/src/corelib/io/qprocess.cpp b/src/corelib/io/qprocess.cpp index 6f11d0892f..0a0fef4cd8 100644 --- a/src/corelib/io/qprocess.cpp +++ b/src/corelib/io/qprocess.cpp @@ -2309,8 +2309,7 @@ void QProcess::start(const QString &command, OpenMode mode) return; } - QString prog = args.first(); - args.removeFirst(); + const QString prog = args.takeFirst(); start(prog, args, mode); } @@ -2552,8 +2551,7 @@ bool QProcess::startDetached(const QString &command) if (args.isEmpty()) return false; - QString prog = args.first(); - args.removeFirst(); + const QString prog = args.takeFirst(); return QProcessPrivate::startDetached(prog, args); } diff --git a/src/widgets/itemviews/qheaderview.cpp b/src/widgets/itemviews/qheaderview.cpp index e046e4781f..9306b20043 100644 --- a/src/widgets/itemviews/qheaderview.cpp +++ b/src/widgets/itemviews/qheaderview.cpp @@ -3377,8 +3377,7 @@ void QHeaderViewPrivate::resizeSections(QHeaderView::ResizeMode globalMode, bool } section_sizes.removeFirst(); } else { - newSectionLength = section_sizes.front(); - section_sizes.removeFirst(); + newSectionLength = section_sizes.takeFirst(); } } -- cgit v1.2.3 From 33044b83c261c485faa0a6f367773138f9892f76 Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Wed, 16 Dec 2015 15:52:28 +0100 Subject: Add color font support on Windows Detect if DirectWrite 2 is available, and support color fonts if possible. One limitation worth mentioning is that if the color font contains regular, monochrome glyphs as well, then these will be drawn in black, and not in the pen color. Fixing this would require some elaborate rewrites in the font rendering system, since we would have to have two font caches per color font (one for mono and one for colors), or do some sort of trick where we make argb(r, g, b, 0) mean subpixel alpha instead, and detect glyphs that are not correctly premultiplied when blitting to the screen. Another limitation is that the approach does not work with distance field rendering. In principle we could support this on Windows, since the format is vector based, but it would also require substantial work and it is not possible to support for Apple/Google fonts anyway, so it would just lead to code which is not cross-platform. [ChangeLog][Windows] Added support for color fonts (color emojis) when DirectWrite 2 is available. Change-Id: I6a608dd5d2aa3a7e762a06830902bddac7c550a5 Reviewed-by: Simon Hausmann --- config.tests/win/directwrite2/directwrite2.cpp | 50 +++++ config.tests/win/directwrite2/directwrite2.pro | 4 + configure | 14 ++ .../platforms/windows/qwindowsfontdatabase.cpp | 83 ++++++--- .../windows/qwindowsfontenginedirectwrite.cpp | 206 +++++++++++++++++---- .../windows/qwindowsfontenginedirectwrite.h | 3 + src/plugins/platforms/windows/windows.pri | 3 + tools/configure/configureapp.cpp | 13 ++ 8 files changed, 313 insertions(+), 63 deletions(-) create mode 100644 config.tests/win/directwrite2/directwrite2.cpp create mode 100644 config.tests/win/directwrite2/directwrite2.pro diff --git a/config.tests/win/directwrite2/directwrite2.cpp b/config.tests/win/directwrite2/directwrite2.cpp new file mode 100644 index 0000000000..06becaff70 --- /dev/null +++ b/config.tests/win/directwrite2/directwrite2.cpp @@ -0,0 +1,50 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the config.tests 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 + +int main(int, char**) +{ + IUnknown *factory = 0; + DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, + __uuidof(IDWriteFactory2), + &factory); + return 0; +} diff --git a/config.tests/win/directwrite2/directwrite2.pro b/config.tests/win/directwrite2/directwrite2.pro new file mode 100644 index 0000000000..ec37247017 --- /dev/null +++ b/config.tests/win/directwrite2/directwrite2.pro @@ -0,0 +1,4 @@ +SOURCES = directwrite2.cpp +LIBS += -ldwrite +CONFIG -= qt +CONFIG += console diff --git a/configure b/configure index 03e89d56c4..7bcc4ad9c9 100755 --- a/configure +++ b/configure @@ -783,6 +783,7 @@ CFG_PCRE=auto QPA_PLATFORM_GUARD=yes CFG_STDCXX=auto CFG_DIRECTWRITE=no +CFG_DIRECTWRITE2=auto CFG_WERROR=auto CFG_HEADERSCLEAN=auto CFG_QREAL=double @@ -6301,6 +6302,18 @@ if [ "$CFG_LARGEFILE" != "yes" ] && [ "$XPLATFORM_MINGW" = "yes" ]; then CFG_LARGEFILE="yes" fi +# Detect DirectWrite 2 support on Windows +if [ "$CFG_DIRECTWRITE" = "no" ]; then + CFG_DIRECTWRITE2=no +fi +if [ "$CFG_DIRECTWRITE2" = "auto" ]; then + if compileTest win/directwrite2 "directwrite2"; then + CFG_DIRECTWRITE2=yes + else + CFG_DIRECTWRITE2=no + fi +fi + #------------------------------------------------------------------------------- # ask for all that hasn't been auto-detected or specified in the arguments #------------------------------------------------------------------------------- @@ -6568,6 +6581,7 @@ fi [ "$CFG_XINPUT2" = "yes" ] && QT_CONFIG="$QT_CONFIG xinput2" [ "$CFG_SYSTEM_PROXIES" = "yes" ] && QT_CONFIG="$QT_CONFIG system-proxies" [ "$CFG_DIRECTWRITE" = "yes" ] && QT_CONFIG="$QT_CONFIG directwrite" +[ "$CFG_DIRECTWRITE2" = "yes" ] && QT_CONFIG="$QT_CONFIG directwrite2" [ '!' -z "$DEFINES" ] && QMakeVar add EXTRA_DEFINES "$DEFINES" [ '!' -z "$INCLUDES" ] && QMakeVar add EXTRA_INCLUDEPATH "$INCLUDES" diff --git a/src/plugins/platforms/windows/qwindowsfontdatabase.cpp b/src/plugins/platforms/windows/qwindowsfontdatabase.cpp index 966be8c991..68a8fc5390 100644 --- a/src/plugins/platforms/windows/qwindowsfontdatabase.cpp +++ b/src/plugins/platforms/windows/qwindowsfontdatabase.cpp @@ -62,7 +62,11 @@ #endif #if !defined(QT_NO_DIRECTWRITE) -# include +# if defined(QT_USE_DIRECTWRITE2) +# include +# else +# include +# endif # include #endif @@ -86,17 +90,27 @@ static inline DWriteCreateFactoryType resolveDWriteCreateFactory() return reinterpret_cast(result); } -static IDWriteFactory *createDirectWriteFactory() +static void createDirectWriteFactory(IDWriteFactory **factory) { + *factory = Q_NULLPTR; + static const DWriteCreateFactoryType dWriteCreateFactory = resolveDWriteCreateFactory(); if (!dWriteCreateFactory) - return Q_NULLPTR; - IUnknown *result = Q_NULLPTR; - if (FAILED(dWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, __uuidof(IDWriteFactory), &result))) { - qErrnoWarning("DWriteCreateFactory failed"); - return Q_NULLPTR; + return; + + IUnknown *result = NULL; +#if defined(QT_USE_DIRECTWRITE2) + dWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, __uuidof(IDWriteFactory2), &result); +#endif + + if (result == NULL) { + if (FAILED(dWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, __uuidof(IDWriteFactory), &result))) { + qErrnoWarning("DWriteCreateFactory failed"); + return; + } } - return reinterpret_cast(result); + + *factory = static_cast(result); } #endif // !QT_NO_DIRECTWRITE @@ -506,8 +520,10 @@ namespace { class CustomFontFileLoader { public: - CustomFontFileLoader() : m_directWriteFactory(createDirectWriteFactory()), m_directWriteFontFileLoader(0) + CustomFontFileLoader() : m_directWriteFontFileLoader(Q_NULLPTR) { + createDirectWriteFactory(&m_directWriteFactory); + if (m_directWriteFactory) { m_directWriteFontFileLoader = new DirectWriteFontFileLoader(); m_directWriteFactory->RegisterFontFileLoader(m_directWriteFontFileLoader); @@ -606,7 +622,7 @@ qreal QWindowsFontDatabase::fontSmoothingGamma() static inline bool initDirectWrite(QWindowsFontEngineData *d) { if (!d->directWriteFactory) { - d->directWriteFactory = createDirectWriteFactory(); + createDirectWriteFactory(&d->directWriteFactory); if (!d->directWriteFactory) return false; } @@ -1757,10 +1773,7 @@ QFontEngine *QWindowsFontDatabase::createEngine(const QFontDef &request, } #if !defined(QT_NO_DIRECTWRITE) - bool useDirectWrite = (request.hintingPreference == QFont::PreferNoHinting) - || (request.hintingPreference == QFont::PreferVerticalHinting) - || (QHighDpiScaling::isActive() && request.hintingPreference == QFont::PreferDefaultHinting); - if (useDirectWrite && initDirectWrite(data.data())) { + if (initDirectWrite(data.data())) { const QString fam = QString::fromWCharArray(lf.lfFaceName); const QString nameSubstitute = QWindowsFontEngineDirectWrite::fontNameSubstitute(fam); if (nameSubstitute != fam) { @@ -1782,18 +1795,38 @@ QFontEngine *QWindowsFontDatabase::createEngine(const QFontDef &request, qWarning().noquote().nospace() << "DirectWrite: CreateFontFaceFromHDC() failed (" << errorString << ") for " << request << ' ' << lf << " dpi=" << dpi; } else { - QWindowsFontEngineDirectWrite *fedw = new QWindowsFontEngineDirectWrite(directWriteFontFace, - request.pixelSize, - data); - - wchar_t n[64]; - GetTextFace(data->hdc, 64, n); - - QFontDef fontDef = request; - fontDef.family = QString::fromWCharArray(n); + bool isColorFont = false; +#if defined(QT_USE_DIRECTWRITE2) + IDWriteFontFace2 *directWriteFontFace2 = Q_NULLPTR; + if (SUCCEEDED(directWriteFontFace->QueryInterface(__uuidof(IDWriteFontFace2), + reinterpret_cast(&directWriteFontFace2)))) { + if (directWriteFontFace2->IsColorFont()) + isColorFont = true; + } +#endif - fedw->initFontInfo(fontDef, dpi); - fe = fedw; + bool useDirectWrite = (request.hintingPreference == QFont::PreferNoHinting) + || (request.hintingPreference == QFont::PreferVerticalHinting) + || (QHighDpiScaling::isActive() && request.hintingPreference == QFont::PreferDefaultHinting) + || isColorFont; + if (useDirectWrite) { + QWindowsFontEngineDirectWrite *fedw = new QWindowsFontEngineDirectWrite(directWriteFontFace, + request.pixelSize, + data); + + wchar_t n[64]; + GetTextFace(data->hdc, 64, n); + + QFontDef fontDef = request; + fontDef.family = QString::fromWCharArray(n); + + if (isColorFont) + fedw->glyphFormat = QFontEngine::Format_ARGB; + fedw->initFontInfo(fontDef, dpi); + fe = fedw; + } else { + directWriteFontFace->Release(); + } } SelectObject(data->hdc, oldFont); diff --git a/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.cpp b/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.cpp index 9dbfac34ef..5408ff41e5 100644 --- a/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.cpp +++ b/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.cpp @@ -49,7 +49,12 @@ #include #include -#include +#if defined(QT_USE_DIRECTWRITE2) +# include +#else +# include +#endif + #include QT_BEGIN_NAMESPACE @@ -562,61 +567,181 @@ QImage QWindowsFontEngineDirectWrite::imageForGlyph(glyph_t t, RECT rect; glyphAnalysis->GetAlphaTextureBounds(DWRITE_TEXTURE_CLEARTYPE_3x1, &rect); - rect.left -= margin; - rect.top -= margin; - rect.right += margin; - rect.bottom += margin; + QRect boundingRect = QRect(QPoint(rect.left - margin, + rect.top - margin), + QPoint(rect.right + margin, + rect.bottom + margin)); + + + const int width = boundingRect.width() - 1; // -1 due to Qt's off-by-one definition of a QRect + const int height = boundingRect.height() - 1; + + QImage image; +#if defined(QT_USE_DIRECTWRITE2) + HRESULT hr = DWRITE_E_NOCOLOR; + IDWriteColorGlyphRunEnumerator *enumerator = 0; + IDWriteFactory2 *factory2 = Q_NULLPTR; + if (glyphFormat == QFontEngine::Format_ARGB + && SUCCEEDED(m_fontEngineData->directWriteFactory->QueryInterface(__uuidof(IDWriteFactory2), + reinterpret_cast(&factory2)))) { + hr = factory2->TranslateColorGlyphRun(0.0f, + 0.0f, + &glyphRun, + NULL, + DWRITE_MEASURING_MODE_NATURAL, + NULL, + 0, + &enumerator); + image = QImage(width, height, QImage::Format_ARGB32_Premultiplied); + image.fill(0); + } else +#endif + { + image = QImage(width, height, QImage::Format_RGB32); + image.fill(0xffffffff); + } + +#if defined(QT_USE_DIRECTWRITE2) + BOOL ok = true; + if (SUCCEEDED(hr)) { + while (SUCCEEDED(hr) && ok) { + const DWRITE_COLOR_GLYPH_RUN *colorGlyphRun = 0; + hr = enumerator->GetCurrentRun(&colorGlyphRun); + if (FAILED(hr)) { // No colored runs, only outline + qErrnoWarning(hr, "%s: IDWriteColorGlyphRunEnumerator::GetCurrentRun failed", __FUNCTION__); + break; + } + + IDWriteGlyphRunAnalysis *colorGlyphsAnalysis = NULL; + hr = m_fontEngineData->directWriteFactory->CreateGlyphRunAnalysis( + &colorGlyphRun->glyphRun, + 1.0f, + &transform, + renderMode, + DWRITE_MEASURING_MODE_NATURAL, + 0.0, 0.0, + &colorGlyphsAnalysis + ); + if (FAILED(hr)) { + qErrnoWarning(hr, "%s: CreateGlyphRunAnalysis failed for color run", __FUNCTION__); + break; + } + + float r = qBound(0.0f, colorGlyphRun->runColor.r, 1.0f); + float g = qBound(0.0f, colorGlyphRun->runColor.g, 1.0f); + float b = qBound(0.0f, colorGlyphRun->runColor.b, 1.0f); + float a = qBound(0.0f, colorGlyphRun->runColor.a, 1.0f); + + if (!qFuzzyIsNull(a)) { + renderGlyphRun(&image, + r, + g, + b, + a, + colorGlyphsAnalysis, + boundingRect); + } + colorGlyphsAnalysis->Release(); + + hr = enumerator->MoveNext(&ok); + if (FAILED(hr)) { + qErrnoWarning(hr, "%s: IDWriteColorGlyphRunEnumerator::MoveNext failed", __FUNCTION__); + break; + } + } + } else +#endif + { + renderGlyphRun(&image, + 0.0, + 0.0, + 0.0, + 1.0, + glyphAnalysis, + boundingRect); + } + + glyphAnalysis->Release(); + return image; + } else { + qErrnoWarning(hr, "%s: CreateGlyphRunAnalysis failed", __FUNCTION__); + return QImage(); + } +} + - const int width = rect.right - rect.left; - const int height = rect.bottom - rect.top; +void QWindowsFontEngineDirectWrite::renderGlyphRun(QImage *destination, + float r, + float g, + float b, + float a, + IDWriteGlyphRunAnalysis *glyphAnalysis, + const QRect &boundingRect) +{ + const int width = destination->width(); + const int height = destination->height(); - const int size = width * height * 3; - if (size > 0) { - BYTE *alphaValues = new BYTE[size]; - memset(alphaValues, 0, size); + r *= 255.0; + g *= 255.0; + b *= 255.0; - hr = glyphAnalysis->CreateAlphaTexture(DWRITE_TEXTURE_CLEARTYPE_3x1, - &rect, - alphaValues, - size); + const int size = width * height * 3; + if (size > 0) { + RECT rect; + rect.left = boundingRect.left(); + rect.top = boundingRect.top(); + rect.right = boundingRect.right(); + rect.bottom = boundingRect.bottom(); + + QVarLengthArray alphaValueArray(size); + BYTE *alphaValues = alphaValueArray.data(); + memset(alphaValues, 0, size); + + HRESULT hr = glyphAnalysis->CreateAlphaTexture(DWRITE_TEXTURE_CLEARTYPE_3x1, + &rect, + alphaValues, + size); + if (SUCCEEDED(hr)) { + if (destination->hasAlphaChannel()) { + for (int y = 0; y < height; ++y) { + uint *dest = reinterpret_cast(destination->scanLine(y)); + BYTE *src = alphaValues + width * 3 * y; - if (SUCCEEDED(hr)) { - QImage img(width, height, QImage::Format_RGB32); - img.fill(0xffffffff); + for (int x = 0; x < width; ++x) { + float redAlpha = a * *src++ / 255.0; + float greenAlpha = a * *src++ / 255.0; + float blueAlpha = a * *src++ / 255.0; + float averageAlpha = (redAlpha + greenAlpha + blueAlpha) / 3.0; + + QRgb currentRgb = dest[x]; + dest[x] = qRgba(qRound(qRed(currentRgb) * (1.0 - averageAlpha) + averageAlpha * r), + qRound(qGreen(currentRgb) * (1.0 - averageAlpha) + averageAlpha * g), + qRound(qBlue(currentRgb) * (1.0 - averageAlpha) + averageAlpha * b), + qRound(qAlpha(currentRgb) * (1.0 - averageAlpha) + averageAlpha * 255)); + } + } - for (int y=0; y(img.scanLine(y)); + } else { + for (int y = 0; y < height; ++y) { + uint *dest = reinterpret_cast(destination->scanLine(y)); BYTE *src = alphaValues + width * 3 * y; - for (int x=0; xRelease(); - - return img; - } else { - delete[] alphaValues; - glyphAnalysis->Release(); - - qErrnoWarning("%s: CreateAlphaTexture failed", __FUNCTION__); } } else { - glyphAnalysis->Release(); - qWarning("%s: Glyph has no bounds", __FUNCTION__); + qErrnoWarning("%s: CreateAlphaTexture failed", __FUNCTION__); } - } else { - qErrnoWarning("%s: CreateGlyphRunAnalysis failed", __FUNCTION__); + glyphAnalysis->Release(); + qWarning("%s: Glyph has no bounds", __FUNCTION__); } - - return QImage(); } QImage QWindowsFontEngineDirectWrite::alphaRGBMapForGlyph(glyph_t t, @@ -734,6 +859,11 @@ glyph_metrics_t QWindowsFontEngineDirectWrite::alphaMapBoundingBox(glyph_t glyph } } +QImage QWindowsFontEngineDirectWrite::bitmapForGlyph(glyph_t glyph, QFixed subPixelPosition, const QTransform &t) +{ + return imageForGlyph(glyph, subPixelPosition, glyphMargin(QFontEngine::Format_A32), t); +} + QT_END_NAMESPACE #endif // QT_NO_DIRECTWRITE diff --git a/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.h b/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.h index 0aa7e41500..f038dcfde4 100644 --- a/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.h +++ b/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.h @@ -52,6 +52,7 @@ struct IDWriteFontFace; struct IDWriteFactory; struct IDWriteBitmapRenderTarget; struct IDWriteGdiInterop; +struct IDWriteGlyphRunAnalysis; QT_BEGIN_NAMESPACE @@ -96,6 +97,7 @@ public: QImage alphaMapForGlyph(glyph_t glyph, QFixed subPixelPosition) Q_DECL_OVERRIDE; QImage alphaMapForGlyph(glyph_t glyph, QFixed subPixelPosition, const QTransform &t) Q_DECL_OVERRIDE; QImage alphaRGBMapForGlyph(glyph_t t, QFixed subPixelPosition, const QTransform &xform) Q_DECL_OVERRIDE; + QImage bitmapForGlyph(glyph_t, QFixed subPixelPosition, const QTransform &t) Q_DECL_OVERRIDE; QFontEngine *cloneWithSize(qreal pixelSize) const Q_DECL_OVERRIDE; Qt::HANDLE handle() const Q_DECL_OVERRIDE; @@ -109,6 +111,7 @@ public: private: QImage imageForGlyph(glyph_t t, QFixed subPixelPosition, int margin, const QTransform &xform); void collectMetrics(); + void renderGlyphRun(QImage *destination, float r, float g, float b, float a, IDWriteGlyphRunAnalysis *glyphAnalysis, const QRect &boundingRect); const QSharedPointer m_fontEngineData; diff --git a/src/plugins/platforms/windows/windows.pri b/src/plugins/platforms/windows/windows.pri index d46cfbc43a..f4dbd10a49 100644 --- a/src/plugins/platforms/windows/windows.pri +++ b/src/plugins/platforms/windows/windows.pri @@ -13,6 +13,9 @@ wince: DEFINES *= QT_LIBINFIX=L"\"\\\"$${QT_LIBINFIX}\\\"\"" DEFINES *= QT_NO_CAST_FROM_ASCII contains(QT_CONFIG, directwrite) { + contains(QT_CONFIG, directwrite2): \ + DEFINES *= QT_USE_DIRECTWRITE2 + SOURCES += $$PWD/qwindowsfontenginedirectwrite.cpp HEADERS += $$PWD/qwindowsfontenginedirectwrite.h } else { diff --git a/tools/configure/configureapp.cpp b/tools/configure/configureapp.cpp index 466be701c4..59b8e4919b 100644 --- a/tools/configure/configureapp.cpp +++ b/tools/configure/configureapp.cpp @@ -161,6 +161,7 @@ Configure::Configure(int& argc, char** argv) : verbose(0) dictionary[ "QML_DEBUG" ] = "yes"; dictionary[ "PLUGIN_MANIFESTS" ] = "no"; dictionary[ "DIRECTWRITE" ] = "auto"; + dictionary[ "DIRECTWRITE2" ] = "auto"; dictionary[ "DIRECT2D" ] = "no"; dictionary[ "NIS" ] = "no"; dictionary[ "NEON" ] = "auto"; @@ -2235,6 +2236,8 @@ bool Configure::checkAvailability(const QString &part) available = findFile("mfapi.h") && findFile("mf.lib"); } else if (part == "DIRECTWRITE") { available = tryCompileProject("win/directwrite"); + } else if (part == "DIRECTWRITE2") { + available = tryCompileProject("win/directwrite2"); } else if (part == "DIRECT2D") { available = tryCompileProject("qpa/direct2d"); } else if (part == "ICONV") { @@ -2488,6 +2491,9 @@ void Configure::autoDetection() if (dictionary["DIRECTWRITE"] == "auto") dictionary["DIRECTWRITE"] = checkAvailability("DIRECTWRITE") ? "yes" : "no"; + if (dictionary["DIRECTWRITE2"] == "auto") + dictionary["DIRECTWRITE2"] = checkAvailability("DIRECTWRITE2") ? "yes" : "no"; + // Mark all unknown "auto" to the default value.. for (QMap::iterator i = dictionary.begin(); i != dictionary.end(); ++i) { if (i.value() == "auto") @@ -2903,6 +2909,9 @@ void Configure::generateOutputVars() if (dictionary["DIRECTWRITE"] == "yes") qtConfig += "directwrite"; + if (dictionary["DIRECTWRITE2"] == "yes") + qtConfig += "directwrite2"; + if (dictionary["DIRECT2D"] == "yes") qtConfig += "direct2d"; @@ -3428,6 +3437,9 @@ void Configure::generateQConfigPri() if (dictionary["DIRECTWRITE"] == "yes") configStream << " directwrite"; + if (dictionary["DIRECTWRITE2"] == "yes") + configStream << " directwrite2"; + if (dictionary["ANDROID_STYLE_ASSETS"] == "yes") configStream << " android-style-assets"; @@ -3790,6 +3802,7 @@ void Configure::displayConfig() sout << "Qt GUI module support......." << dictionary[ "GUI" ] << endl; sout << "QML debugging..............." << dictionary[ "QML_DEBUG" ] << endl; sout << "DirectWrite support........." << dictionary[ "DIRECTWRITE" ] << endl; + sout << "DirectWrite 2 support......." << dictionary[ "DIRECTWRITE2" ] << endl; sout << "Use system proxies.........." << dictionary[ "SYSTEM_PROXIES" ] << endl; sout << endl; -- cgit v1.2.3 From 2687eb5a8c1495413dabb38750f0b6e8d93771e2 Mon Sep 17 00:00:00 2001 From: Jan Arve Saether Date: Thu, 7 Apr 2016 14:35:46 +0200 Subject: ImQueryInput should include ImAnchorRectangle too Whenever we notify about ImAnchorPosition, we also need to notify about ImAnchorRectangle Change-Id: Ia449396e1b9e91fa0e6f95c323e31533da660171 Reviewed-by: Richard Moe Gustavsen --- src/corelib/global/qnamespace.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/corelib/global/qnamespace.h b/src/corelib/global/qnamespace.h index fc7ca9b216..5a4f499a87 100644 --- a/src/corelib/global/qnamespace.h +++ b/src/corelib/global/qnamespace.h @@ -1343,7 +1343,7 @@ public: ImPlatformData = 0x80000000, ImQueryInput = ImCursorRectangle | ImCursorPosition | ImSurroundingText | - ImCurrentSelection | ImAnchorPosition, + ImCurrentSelection | ImAnchorRectangle | ImAnchorPosition, ImQueryAll = 0xffffffff }; Q_DECLARE_FLAGS(InputMethodQueries, InputMethodQuery) -- cgit v1.2.3 From 9b35b0e8dc6069aed563d0aca61c973eb307d772 Mon Sep 17 00:00:00 2001 From: Rolland Dudemaine Date: Fri, 11 Mar 2016 15:05:56 +0100 Subject: Make the eglfs and eglfs-viv detection and build work for INTEGRITY. The majority of these changes is about #ifdef-ing the Linux-specific use of /dev/fb0. The display handle is also acquired using fbGetDisplay(), which is equivalent to fbGetDisplayByIndex(0) but is also portable. Change-Id: I6f460edc9c06ae7461a6aab2a816ac6f645208c4 Reviewed-by: Andy Nichols --- config.tests/qpa/eglfs-viv/eglfs-viv.cpp | 2 +- config.tests/qpa/eglfs-viv/eglfs-viv.pro | 14 ++++++++++++-- src/gui/opengl/qopenglfunctions.cpp | 4 ++++ .../deviceintegration/eglfs_viv/qeglfsvivintegration.cpp | 8 ++++++++ src/plugins/platforms/eglfs/qeglfsdeviceintegration.cpp | 10 +++++++++- src/plugins/platforms/eglfs/qeglfshooks.cpp | 2 +- 6 files changed, 35 insertions(+), 5 deletions(-) diff --git a/config.tests/qpa/eglfs-viv/eglfs-viv.cpp b/config.tests/qpa/eglfs-viv/eglfs-viv.cpp index 4b08322d66..a41c482b67 100644 --- a/config.tests/qpa/eglfs-viv/eglfs-viv.cpp +++ b/config.tests/qpa/eglfs-viv/eglfs-viv.cpp @@ -43,6 +43,6 @@ int main(int, char **) { - fbGetDisplayByIndex(0); + fbGetDisplay(); return 0; } diff --git a/config.tests/qpa/eglfs-viv/eglfs-viv.pro b/config.tests/qpa/eglfs-viv/eglfs-viv.pro index 99776940ec..3b36dc533f 100644 --- a/config.tests/qpa/eglfs-viv/eglfs-viv.pro +++ b/config.tests/qpa/eglfs-viv/eglfs-viv.pro @@ -1,6 +1,16 @@ SOURCES = eglfs-viv.cpp -DEFINES += LINUX=1 EGL_API_FB=1 - +integrity { + DEFINES += EGL_API_FB=1 +} else { + DEFINES += LINUX=1 EGL_API_FB=1 +} CONFIG -= qt LIBS += -lEGL -lGLESv2 -lGAL + +for(p, QMAKE_LIBDIR_OPENGL_ES2) { + exists($$p):LIBS += -L$$p +} + +!isEmpty(QMAKE_INCDIR_EGL): INCLUDEPATH += $$QMAKE_INCDIR_EGL +!isEmpty(QMAKE_LIBS_EGL): LIBS += $$QMAKE_LIBS_EGL diff --git a/src/gui/opengl/qopenglfunctions.cpp b/src/gui/opengl/qopenglfunctions.cpp index ea5a8e9252..e4e7c6d1b5 100644 --- a/src/gui/opengl/qopenglfunctions.cpp +++ b/src/gui/opengl/qopenglfunctions.cpp @@ -47,6 +47,10 @@ #include #include +#ifdef Q_OS_INTEGRITY +#include +#endif + #ifndef GL_FRAMEBUFFER_SRGB_CAPABLE_EXT #define GL_FRAMEBUFFER_SRGB_CAPABLE_EXT 0x8DBA #endif diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_viv/qeglfsvivintegration.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_viv/qeglfsvivintegration.cpp index eef4feb2c2..ca97f6c8f9 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_viv/qeglfsvivintegration.cpp +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_viv/qeglfsvivintegration.cpp @@ -41,6 +41,10 @@ #include #include +#ifdef Q_OS_INTEGRITY +extern "C" void VivanteInit(void); +#endif + QT_BEGIN_NAMESPACE void QEglFSVivIntegration::platformInit() @@ -57,6 +61,10 @@ void QEglFSVivIntegration::platformInit() qputenv("FB_MULTI_BUFFER", "2"); } +#ifdef Q_OS_INTEGRITY + VivanteInit(); +#endif + mNativeDisplay = fbGetDisplayByIndex(framebufferIndex()); fbGetDisplayGeometry(mNativeDisplay, &width, &height); mScreenSize.setHeight(height); diff --git a/src/plugins/platforms/eglfs/qeglfsdeviceintegration.cpp b/src/plugins/platforms/eglfs/qeglfsdeviceintegration.cpp index 84351dba5a..5cbc5dbdb0 100644 --- a/src/plugins/platforms/eglfs/qeglfsdeviceintegration.cpp +++ b/src/plugins/platforms/eglfs/qeglfsdeviceintegration.cpp @@ -120,11 +120,15 @@ static int framebuffer = -1; QByteArray QEGLDeviceIntegration::fbDeviceName() const { +#ifdef Q_OS_LINUX QByteArray fbDev = qgetenv("QT_QPA_EGLFS_FB"); if (fbDev.isEmpty()) fbDev = QByteArrayLiteral("/dev/fb0"); return fbDev; +#else + return QByteArray(); +#endif } int QEGLDeviceIntegration::framebufferIndex() const @@ -141,6 +145,7 @@ int QEGLDeviceIntegration::framebufferIndex() const void QEGLDeviceIntegration::platformInit() { +#ifdef Q_OS_LINUX QByteArray fbDev = fbDeviceName(); framebuffer = qt_safe_open(fbDev, O_RDONLY); @@ -153,12 +158,15 @@ void QEGLDeviceIntegration::platformInit() #ifdef FBIOBLANK ioctl(framebuffer, FBIOBLANK, VESA_NO_BLANKING); #endif +#endif } void QEGLDeviceIntegration::platformDestroy() { +#ifdef Q_OS_LINUX if (framebuffer != -1) close(framebuffer); +#endif } EGLNativeDisplayType QEGLDeviceIntegration::platformDisplay() const @@ -307,7 +315,7 @@ void QEGLDeviceIntegration::waitForVSync(QPlatformSurface *surface) const { Q_UNUSED(surface); -#if defined(FBIO_WAITFORVSYNC) +#if defined(Q_OS_LINUX) && defined(FBIO_WAITFORVSYNC) static const bool forceSync = qEnvironmentVariableIntValue("QT_QPA_EGLFS_FORCEVSYNC"); if (forceSync && framebuffer != -1) { int arg = 0; diff --git a/src/plugins/platforms/eglfs/qeglfshooks.cpp b/src/plugins/platforms/eglfs/qeglfshooks.cpp index 1cdbb1dd39..87285428df 100644 --- a/src/plugins/platforms/eglfs/qeglfshooks.cpp +++ b/src/plugins/platforms/eglfs/qeglfshooks.cpp @@ -66,7 +66,7 @@ private: Q_GLOBAL_STATIC(DeviceIntegration, deviceIntegration) -DeviceIntegration::DeviceIntegration() +DeviceIntegration::DeviceIntegration() : m_integration(0) { QStringList pluginKeys = QEGLDeviceIntegrationFactory::keys(); if (!pluginKeys.isEmpty()) { -- cgit v1.2.3 From 35fdf91f403056c3b4a9491cc760f218fdc01459 Mon Sep 17 00:00:00 2001 From: Rolland Dudemaine Date: Fri, 1 Apr 2016 08:07:19 +0200 Subject: Enable thread_local support for GHS toolchain. Change-Id: I1ac9fd11b7262a740d21f9b997a5f448636ce826 Reviewed-by: Oswald Buddenhagen Reviewed-by: Andy Nichols --- mkspecs/common/ghs-base.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mkspecs/common/ghs-base.conf b/mkspecs/common/ghs-base.conf index cd1e598942..ad452ecc43 100644 --- a/mkspecs/common/ghs-base.conf +++ b/mkspecs/common/ghs-base.conf @@ -29,7 +29,7 @@ QMAKE_CXXFLAGS_STATIC_LIB += $$QMAKE_CFLAGS_STATIC_LIB QMAKE_CXXFLAGS_APP += $$QMAKE_CFLAGS_APP QMAKE_CXXFLAGS_YACC += $$QMAKE_CFLAGS_YACC QMAKE_CXXFLAGS_HIDESYMS += $$QMAKE_CFLAGS_HIDESYMS -QMAKE_CXXFLAGS_CXX11 += --c++11 +QMAKE_CXXFLAGS_CXX11 += --c++11 --thread_local_storage QMAKE_LFLAGS += --no_commons -non_shared --link_once_templates --exceptions --stdle QMAKE_LFLAGS_RELEASE += -Ospeed -Olink -uvfd -- cgit v1.2.3 From d67327282fb91269a1d034709b4fb320d64dfa05 Mon Sep 17 00:00:00 2001 From: Rolland Dudemaine Date: Fri, 1 Apr 2016 08:07:59 +0200 Subject: Accept correct double conversion unconditionally for GHS toolchain. GHS floating-point libraries always handles double conversion properly. Change-Id: Ic3c6c83e56fa0c7d29707b3939b6e7af38df0f3d Reviewed-by: Oswald Buddenhagen Reviewed-by: Ulf Hermann Reviewed-by: Andy Nichols --- src/3rdparty/double-conversion/include/double-conversion/utils.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/3rdparty/double-conversion/include/double-conversion/utils.h b/src/3rdparty/double-conversion/include/double-conversion/utils.h index 53eec64282..a89b284eda 100644 --- a/src/3rdparty/double-conversion/include/double-conversion/utils.h +++ b/src/3rdparty/double-conversion/include/double-conversion/utils.h @@ -76,6 +76,9 @@ #endif // _WIN32 #elif defined(WINCE) || defined(_WIN32_WCE) #define DOUBLE_CONVERSION_CORRECT_DOUBLE_OPERATIONS 1 +#elif defined(__ghs) +// Green Hills toolchain uses a 64bit wide floating point stack +#define DOUBLE_CONVERSION_CORRECT_DOUBLE_OPERATIONS 1 #else #error Target architecture was not detected as supported by Double-Conversion. #endif -- cgit v1.2.3 From 5469d70418ab458dedcb572f42cf0839bacf210b Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Mon, 11 Apr 2016 13:47:51 +0200 Subject: Fix some qdoc-warnings in 5.7. qtbase/src/corelib/global/qnamespace.qdoc:101: warning: Undocumented enum item 'AA_SynthesizeMouseForUnhandledTabletEvents' in Qt::ApplicationAttribute qtbase/src/corelib/global/qnamespace.qdoc:2554: warning: Undocumented enum item 'ImAnchorRectangle' in Qt::InputMethodQuery qtbase/src/corelib/statemachine/qsignaltransition.cpp:154: warning: Can't link to 'Q_COMPILER_DELEGATING_CONSTRUCTORS' qtbase/src/gui/image/qiconloader.cpp:160: warning: Cannot find 'QIconCacheGtkReader' specified with '\class' in any header file qtbase/src/gui/painting/qpaintengine_raster.cpp:1382: warning: No documentation for 'QRasterPaintEngine::fillPath(const QPainterPath &path, QSpanData *fillData)' qtbase/src/testlib/qtest.h:176: warning: No documentation for 'QTest::toString(const QHostAddress &addr)' qtbase/src/testlib/qtest_gui.h:77: warning: No documentation for 'QTest::toString(const QColor &color)' Change-Id: If9ac0807accf2530ec7fc2ca7db71a110f9f79bb Reviewed-by: Leena Miettinen Reviewed-by: Shawn Rutledge --- src/corelib/global/qnamespace.qdoc | 7 +++++++ src/corelib/statemachine/qsignaltransition.cpp | 5 ++--- src/gui/image/qiconloader.cpp | 1 - src/gui/painting/qpaintengine_raster.cpp | 6 +++--- src/testlib/qtest.h | 3 +++ src/testlib/qtest_gui.h | 3 +++ 6 files changed, 18 insertions(+), 7 deletions(-) diff --git a/src/corelib/global/qnamespace.qdoc b/src/corelib/global/qnamespace.qdoc index dfa7112043..0cc9467921 100644 --- a/src/corelib/global/qnamespace.qdoc +++ b/src/corelib/global/qnamespace.qdoc @@ -234,6 +234,11 @@ set to true won't use the native dialogs provided by the platform. This value has been added in Qt 5.7. + \value AA_SynthesizeMouseForUnhandledTabletEvents All tablet events + that are not accepted by the application will be translated + to mouse events instead. This attribute is enabled + by default. This value has been added in Qt 5.7. + The following values are obsolete: \value AA_ImmediateWidgetCreation This attribute is no longer fully @@ -2576,6 +2581,8 @@ \value ImTextAfterCursor The plain text after the cursor. The widget can decide how much text to return, but \b{must} not return an empty string unless the cursor is at the end of the document. \value ImEnterKeyType The Enter key type. + \value ImAnchorRectangle The bounding rectangle of the selection anchor. + This value has been added in Qt 5.7. Masks: diff --git a/src/corelib/statemachine/qsignaltransition.cpp b/src/corelib/statemachine/qsignaltransition.cpp index 9972487eb5..c4ba8e5315 100644 --- a/src/corelib/statemachine/qsignaltransition.cpp +++ b/src/corelib/statemachine/qsignaltransition.cpp @@ -159,9 +159,8 @@ QSignalTransition::QSignalTransition(const QObject *sender, const char *signal, Constructs a new signal transition associated with the given \a signal of the given \a sender object and with the given \a sourceState. - This constructor is enabled if compiler supports delegating constructor. - - \sa Q_COMPILER_DELEGATING_CONSTRUCTORS + This constructor is enabled if the compiler supports delegating constructors, + as indicated by the presence of the macro Q_COMPILER_DELEGATING_CONSTRUCTORS. */ /*! diff --git a/src/gui/image/qiconloader.cpp b/src/gui/image/qiconloader.cpp index a600aa3299..7b6bfc60b3 100644 --- a/src/gui/image/qiconloader.cpp +++ b/src/gui/image/qiconloader.cpp @@ -158,7 +158,6 @@ QStringList QIconLoader::themeSearchPaths() const } /*! - \class QIconCacheGtkReader \internal Helper class that reads and looks up into the icon-theme.cache generated with gtk-update-icon-cache. If at any point we detect a corruption in the file diff --git a/src/gui/painting/qpaintengine_raster.cpp b/src/gui/painting/qpaintengine_raster.cpp index d3b4acbbcd..0edd9125a3 100644 --- a/src/gui/painting/qpaintengine_raster.cpp +++ b/src/gui/painting/qpaintengine_raster.cpp @@ -1345,9 +1345,9 @@ void QRasterPaintEngine::clip(const QRegion ®ion, Qt::ClipOperation op) */ -///*! -// \internal -//*/ +/*! + \internal +*/ void QRasterPaintEngine::fillPath(const QPainterPath &path, QSpanData *fillData) { #ifdef QT_DEBUG_DRAW diff --git a/src/testlib/qtest.h b/src/testlib/qtest.h index 0c03ab620b..c35b767875 100644 --- a/src/testlib/qtest.h +++ b/src/testlib/qtest.h @@ -173,6 +173,9 @@ template<> inline char *toString(const QVariant &v) } #ifdef QT_NETWORK_LIB +/*! + \internal + */ template<> inline char *toString(const QHostAddress &addr) { switch (addr.protocol()) { diff --git a/src/testlib/qtest_gui.h b/src/testlib/qtest_gui.h index 2faf37f32b..5027aea732 100644 --- a/src/testlib/qtest_gui.h +++ b/src/testlib/qtest_gui.h @@ -74,6 +74,9 @@ QT_BEGIN_NAMESPACE namespace QTest { +/*! + \internal + */ template<> inline char *toString(const QColor &color) { return qstrdup(color.name().toLocal8Bit().constData()); -- cgit v1.2.3 From 10758c5af244c6e7eb53b280d35198311cd548ce Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Wed, 6 Apr 2016 13:26:12 +0200 Subject: Mark some QByteArray relational operators nothrow Specifically, those that compare UTF-8 octet-streams: - QByteArray <-> QByteArray - QByteArray <-> const char* For more, Qt first needs to gain a nothrow UTF-8 <-> UTF-16 comparator. Change-Id: Ibccbdcdc3ebed5b1ac0e65c971f6f7d1bd15b6da Reviewed-by: Thiago Macieira --- src/corelib/tools/qbytearray.h | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/src/corelib/tools/qbytearray.h b/src/corelib/tools/qbytearray.h index a53d4eabd3..d334bb43c5 100644 --- a/src/corelib/tools/qbytearray.h +++ b/src/corelib/tools/qbytearray.h @@ -604,41 +604,41 @@ inline bool QByteArray::contains(const QByteArray &a) const { return indexOf(a) != -1; } inline bool QByteArray::contains(char c) const { return indexOf(c) != -1; } -inline bool operator==(const QByteArray &a1, const QByteArray &a2) +inline bool operator==(const QByteArray &a1, const QByteArray &a2) Q_DECL_NOTHROW { return (a1.size() == a2.size()) && (memcmp(a1.constData(), a2.constData(), a1.size())==0); } -inline bool operator==(const QByteArray &a1, const char *a2) +inline bool operator==(const QByteArray &a1, const char *a2) Q_DECL_NOTHROW { return a2 ? qstrcmp(a1,a2) == 0 : a1.isEmpty(); } -inline bool operator==(const char *a1, const QByteArray &a2) +inline bool operator==(const char *a1, const QByteArray &a2) Q_DECL_NOTHROW { return a1 ? qstrcmp(a1,a2) == 0 : a2.isEmpty(); } -inline bool operator!=(const QByteArray &a1, const QByteArray &a2) +inline bool operator!=(const QByteArray &a1, const QByteArray &a2) Q_DECL_NOTHROW { return !(a1==a2); } -inline bool operator!=(const QByteArray &a1, const char *a2) +inline bool operator!=(const QByteArray &a1, const char *a2) Q_DECL_NOTHROW { return a2 ? qstrcmp(a1,a2) != 0 : !a1.isEmpty(); } -inline bool operator!=(const char *a1, const QByteArray &a2) +inline bool operator!=(const char *a1, const QByteArray &a2) Q_DECL_NOTHROW { return a1 ? qstrcmp(a1,a2) != 0 : !a2.isEmpty(); } -inline bool operator<(const QByteArray &a1, const QByteArray &a2) +inline bool operator<(const QByteArray &a1, const QByteArray &a2) Q_DECL_NOTHROW { return qstrcmp(a1, a2) < 0; } - inline bool operator<(const QByteArray &a1, const char *a2) + inline bool operator<(const QByteArray &a1, const char *a2) Q_DECL_NOTHROW { return qstrcmp(a1, a2) < 0; } -inline bool operator<(const char *a1, const QByteArray &a2) +inline bool operator<(const char *a1, const QByteArray &a2) Q_DECL_NOTHROW { return qstrcmp(a1, a2) < 0; } -inline bool operator<=(const QByteArray &a1, const QByteArray &a2) +inline bool operator<=(const QByteArray &a1, const QByteArray &a2) Q_DECL_NOTHROW { return qstrcmp(a1, a2) <= 0; } -inline bool operator<=(const QByteArray &a1, const char *a2) +inline bool operator<=(const QByteArray &a1, const char *a2) Q_DECL_NOTHROW { return qstrcmp(a1, a2) <= 0; } -inline bool operator<=(const char *a1, const QByteArray &a2) +inline bool operator<=(const char *a1, const QByteArray &a2) Q_DECL_NOTHROW { return qstrcmp(a1, a2) <= 0; } -inline bool operator>(const QByteArray &a1, const QByteArray &a2) +inline bool operator>(const QByteArray &a1, const QByteArray &a2) Q_DECL_NOTHROW { return qstrcmp(a1, a2) > 0; } -inline bool operator>(const QByteArray &a1, const char *a2) +inline bool operator>(const QByteArray &a1, const char *a2) Q_DECL_NOTHROW { return qstrcmp(a1, a2) > 0; } -inline bool operator>(const char *a1, const QByteArray &a2) +inline bool operator>(const char *a1, const QByteArray &a2) Q_DECL_NOTHROW { return qstrcmp(a1, a2) > 0; } -inline bool operator>=(const QByteArray &a1, const QByteArray &a2) +inline bool operator>=(const QByteArray &a1, const QByteArray &a2) Q_DECL_NOTHROW { return qstrcmp(a1, a2) >= 0; } -inline bool operator>=(const QByteArray &a1, const char *a2) +inline bool operator>=(const QByteArray &a1, const char *a2) Q_DECL_NOTHROW { return qstrcmp(a1, a2) >= 0; } -inline bool operator>=(const char *a1, const QByteArray &a2) +inline bool operator>=(const char *a1, const QByteArray &a2) Q_DECL_NOTHROW { return qstrcmp(a1, a2) >= 0; } #if !defined(QT_USE_QSTRINGBUILDER) inline const QByteArray operator+(const QByteArray &a1, const QByteArray &a2) -- cgit v1.2.3 From 07a19c12a39034ff85568d82e800edd50a21741e Mon Sep 17 00:00:00 2001 From: Richard Moe Gustavsen Date: Mon, 21 Mar 2016 13:38:46 +0100 Subject: QWidgetTextControl: implement support for Qt::ImAnchorRectangle MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Implement support in QWidgetTextControl for the new enum Qt::ImAnchorRectangle. Change-Id: I7978915454a6dd93b2f491ed15619016cda85c7e Reviewed-by: Jan Arve Sæther --- src/widgets/widgets/qwidgettextcontrol.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/widgets/widgets/qwidgettextcontrol.cpp b/src/widgets/widgets/qwidgettextcontrol.cpp index af6d879661..080f22656c 100644 --- a/src/widgets/widgets/qwidgettextcontrol.cpp +++ b/src/widgets/widgets/qwidgettextcontrol.cpp @@ -2073,6 +2073,8 @@ QVariant QWidgetTextControl::inputMethodQuery(Qt::InputMethodQuery property, QVa switch(property) { case Qt::ImCursorRectangle: return cursorRect(); + case Qt::ImAnchorRectangle: + return d->rectForPosition(d->cursor.anchor()); case Qt::ImFont: return QVariant(d->cursor.charFormat().font()); case Qt::ImCursorPosition: -- cgit v1.2.3 From ab67a5b7b631709aae779c767a903b8982fa7f8e Mon Sep 17 00:00:00 2001 From: Richard Moe Gustavsen Date: Mon, 11 Apr 2016 14:06:02 +0200 Subject: QLineEdit: add support for ImCursorPosition with position argument MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Follow up f8dbed12, and implement support for IM queries that can take an extra QVariant argument. We use this to implement support for ImCursorPosition with a QPointF argument that specifies that we should return the text position under the given point rather than the current cursor pos (0bb645b). Change-Id: I03ae7af698241f454d35dec84f248ecd5bb6ad51 Reviewed-by: Jan Arve Sæther --- src/widgets/widgets/qlineedit.cpp | 14 +++++++++++--- src/widgets/widgets/qlineedit.h | 1 + 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/widgets/widgets/qlineedit.cpp b/src/widgets/widgets/qlineedit.cpp index 3cdd7dc0f0..5e88c2034a 100644 --- a/src/widgets/widgets/qlineedit.cpp +++ b/src/widgets/widgets/qlineedit.cpp @@ -1745,9 +1745,14 @@ void QLineEdit::inputMethodEvent(QInputMethodEvent *e) #endif } +QVariant QLineEdit::inputMethodQuery(Qt::InputMethodQuery property) const +{ + return inputMethodQuery(property, QVariant()); +} + /*!\reimp */ -QVariant QLineEdit::inputMethodQuery(Qt::InputMethodQuery property) const +QVariant QLineEdit::inputMethodQuery(Qt::InputMethodQuery property, QVariant argument) const { Q_D(const QLineEdit); switch(property) { @@ -1755,8 +1760,11 @@ QVariant QLineEdit::inputMethodQuery(Qt::InputMethodQuery property) const return d->cursorRect(); case Qt::ImFont: return font(); - case Qt::ImCursorPosition: - return QVariant(d->control->cursor()); + case Qt::ImCursorPosition: { + const QPointF pt = argument.toPointF(); + if (!pt.isNull()) + return QVariant(d->xToPos(pt.x(), QTextLine::CursorBetweenCharacters)); + return QVariant(d->control->cursor()); } case Qt::ImSurroundingText: return QVariant(d->control->text()); case Qt::ImCurrentSelection: diff --git a/src/widgets/widgets/qlineedit.h b/src/widgets/widgets/qlineedit.h index 6a24daa873..12fd998c45 100644 --- a/src/widgets/widgets/qlineedit.h +++ b/src/widgets/widgets/qlineedit.h @@ -228,6 +228,7 @@ protected: void initStyleOption(QStyleOptionFrame *option) const; public: QVariant inputMethodQuery(Qt::InputMethodQuery) const Q_DECL_OVERRIDE; + Q_INVOKABLE QVariant inputMethodQuery(Qt::InputMethodQuery property, QVariant argument) const; bool event(QEvent *) Q_DECL_OVERRIDE; protected: QRect cursorRect() const; -- cgit v1.2.3 From 5391f3c72f884fdea0861ceca814d247ef552397 Mon Sep 17 00:00:00 2001 From: Richard Moe Gustavsen Date: Mon, 11 Apr 2016 14:23:22 +0200 Subject: QLineEdit: add support for Qt::ImAnchorRectangle MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: I52e15aa40af5ff77306c43209af87a3e727d2bdb Reviewed-by: Jan Arve Sæther --- src/widgets/widgets/qlineedit.cpp | 2 ++ src/widgets/widgets/qwidgetlinecontrol.cpp | 33 ++++++++++++++++++++++++------ src/widgets/widgets/qwidgetlinecontrol_p.h | 2 ++ 3 files changed, 31 insertions(+), 6 deletions(-) diff --git a/src/widgets/widgets/qlineedit.cpp b/src/widgets/widgets/qlineedit.cpp index 5e88c2034a..499710d18e 100644 --- a/src/widgets/widgets/qlineedit.cpp +++ b/src/widgets/widgets/qlineedit.cpp @@ -1758,6 +1758,8 @@ QVariant QLineEdit::inputMethodQuery(Qt::InputMethodQuery property, QVariant arg switch(property) { case Qt::ImCursorRectangle: return d->cursorRect(); + case Qt::ImAnchorRectangle: + return d->adjustedControlRect(d->control->anchorRect()); case Qt::ImFont: return font(); case Qt::ImCursorPosition: { diff --git a/src/widgets/widgets/qwidgetlinecontrol.cpp b/src/widgets/widgets/qwidgetlinecontrol.cpp index af8e5a8b42..24edca172b 100644 --- a/src/widgets/widgets/qwidgetlinecontrol.cpp +++ b/src/widgets/widgets/qwidgetlinecontrol.cpp @@ -407,22 +407,43 @@ int QWidgetLineControl::xToPos(int x, QTextLine::CursorPosition betweenOrOn) con /*! \internal - Returns the bounds of the current cursor, as defined as a - between characters cursor. + Returns the bounds of the given text position. */ -QRect QWidgetLineControl::cursorRect() const +QRect QWidgetLineControl::rectForPos(int pos) const { QTextLine l = textLayout()->lineAt(0); - int c = m_cursor; if (m_preeditCursor != -1) - c += m_preeditCursor; - int cix = qRound(l.cursorToX(c)); + pos += m_preeditCursor; + int cix = qRound(l.cursorToX(pos)); int w = m_cursorWidth; int ch = l.height() + 1; return QRect(cix-5, 0, w+9, ch); } +/*! + \internal + + Returns the bounds of the current cursor, as defined as a + between characters cursor. +*/ +QRect QWidgetLineControl::cursorRect() const +{ + return rectForPos(m_cursor); +} + +/*! + \internal + + Returns the bounds of the current anchor +*/ +QRect QWidgetLineControl::anchorRect() const +{ + if (!hasSelectedText()) + return cursorRect(); + return rectForPos(m_selstart < m_selend ? m_selstart : m_selend); +} + /*! \internal diff --git a/src/widgets/widgets/qwidgetlinecontrol_p.h b/src/widgets/widgets/qwidgetlinecontrol_p.h index 6fadb64e0c..8b723b0224 100644 --- a/src/widgets/widgets/qwidgetlinecontrol_p.h +++ b/src/widgets/widgets/qwidgetlinecontrol_p.h @@ -212,7 +212,9 @@ public: void end(bool mark) { moveCursor(text().length(), mark); } int xToPos(int x, QTextLine::CursorPosition = QTextLine::CursorBetweenCharacters) const; + QRect rectForPos(int pos) const; QRect cursorRect() const; + QRect anchorRect() const; qreal cursorToX(int cursor) const { return m_textLayout.lineAt(0).cursorToX(cursor); } qreal cursorToX() const -- cgit v1.2.3 From 3b188889820462658ac2078c6a41c9f8a6963d48 Mon Sep 17 00:00:00 2001 From: Richard Moe Gustavsen Date: Mon, 21 Mar 2016 15:44:32 +0100 Subject: QTextEdit: translate IM argument before passing it on to QWidgetTextControl MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since we now have the possibility of providing an extra position argument when querying for Qt::ImCursorPosition, we need to ensure that we translate it from scroll view to local coordinates before passing it on to QWidgetTextControl. Change-Id: I4383ae3ea984b6140d8e9b4198047aec8b7e100b Reviewed-by: Jan Arve Sæther --- src/widgets/widgets/qplaintextedit.cpp | 20 +++++++++++++++++++- src/widgets/widgets/qtextedit.cpp | 20 +++++++++++++++++++- 2 files changed, 38 insertions(+), 2 deletions(-) diff --git a/src/widgets/widgets/qplaintextedit.cpp b/src/widgets/widgets/qplaintextedit.cpp index 17eac9db58..35ec88b881 100644 --- a/src/widgets/widgets/qplaintextedit.cpp +++ b/src/widgets/widgets/qplaintextedit.cpp @@ -2199,8 +2199,26 @@ QVariant QPlainTextEdit::inputMethodQuery(Qt::InputMethodQuery query, QVariant a Q_D(const QPlainTextEdit); if (query == Qt::ImHints) return QWidget::inputMethodQuery(query); - const QVariant v = d->control->inputMethodQuery(query, argument); + const QPointF offset = contentOffset(); + switch (argument.type()) { + case QVariant::RectF: + argument = argument.toRectF().translated(-offset); + break; + case QVariant::PointF: + argument = argument.toPointF() - offset; + break; + case QVariant::Rect: + argument = argument.toRect().translated(-offset.toPoint()); + break; + case QVariant::Point: + argument = argument.toPoint() - offset; + break; + default: + break; + } + + const QVariant v = d->control->inputMethodQuery(query, argument); switch (v.type()) { case QVariant::RectF: return v.toRectF().translated(offset); diff --git a/src/widgets/widgets/qtextedit.cpp b/src/widgets/widgets/qtextedit.cpp index 1dd774cf7a..68b6ea6cbe 100644 --- a/src/widgets/widgets/qtextedit.cpp +++ b/src/widgets/widgets/qtextedit.cpp @@ -1729,8 +1729,26 @@ QVariant QTextEdit::inputMethodQuery(Qt::InputMethodQuery query, QVariant argume Q_D(const QTextEdit); if (query == Qt::ImHints) return QWidget::inputMethodQuery(query); - const QVariant v = d->control->inputMethodQuery(query, argument); + const QPointF offset(-d->horizontalOffset(), -d->verticalOffset()); + switch (argument.type()) { + case QVariant::RectF: + argument = argument.toRectF().translated(-offset); + break; + case QVariant::PointF: + argument = argument.toPointF() - offset; + break; + case QVariant::Rect: + argument = argument.toRect().translated(-offset.toPoint()); + break; + case QVariant::Point: + argument = argument.toPoint() - offset; + break; + default: + break; + } + + const QVariant v = d->control->inputMethodQuery(query, argument); switch (v.type()) { case QVariant::RectF: return v.toRectF().translated(offset); -- cgit v1.2.3 From 382ec79fab49ff490341b92056ee65a646d3ca04 Mon Sep 17 00:00:00 2001 From: Richard Moe Gustavsen Date: Wed, 9 Mar 2016 10:56:19 +0100 Subject: QWidgetTextControl: implement support for pos argument to ImAbsolutePosition MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Implement support in QWidgetTextControl for the new API that lets you specify a position argument when querying for Qt::ImCursorPosition. Change-Id: I123e2522d33e783e6f3467b81be872e3620d6d15 Reviewed-by: Jan Arve Sæther --- src/widgets/widgets/qwidgettextcontrol.cpp | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/widgets/widgets/qwidgettextcontrol.cpp b/src/widgets/widgets/qwidgettextcontrol.cpp index 080f22656c..cc1726c362 100644 --- a/src/widgets/widgets/qwidgettextcontrol.cpp +++ b/src/widgets/widgets/qwidgettextcontrol.cpp @@ -2077,8 +2077,11 @@ QVariant QWidgetTextControl::inputMethodQuery(Qt::InputMethodQuery property, QVa return d->rectForPosition(d->cursor.anchor()); case Qt::ImFont: return QVariant(d->cursor.charFormat().font()); - case Qt::ImCursorPosition: - return QVariant(d->cursor.position() - block.position()); + case Qt::ImCursorPosition: { + const QPointF pt = argument.toPointF(); + if (!pt.isNull()) + return QVariant(cursorForPosition(pt).position() - block.position()); + return QVariant(d->cursor.position() - block.position()); } case Qt::ImSurroundingText: return QVariant(block.text()); case Qt::ImCurrentSelection: @@ -2087,8 +2090,11 @@ QVariant QWidgetTextControl::inputMethodQuery(Qt::InputMethodQuery property, QVa return QVariant(); // No limit. case Qt::ImAnchorPosition: return QVariant(d->cursor.anchor() - block.position()); - case Qt::ImAbsolutePosition: - return QVariant(d->cursor.position()); + case Qt::ImAbsolutePosition: { + const QPointF pt = argument.toPointF(); + if (!pt.isNull()) + return QVariant(cursorForPosition(pt).position()); + return QVariant(d->cursor.position()); } case Qt::ImTextAfterCursor: { int maxLength = argument.isValid() ? argument.toInt() : 1024; -- cgit v1.2.3 From f8efe8e0c91905d5077131d343f2ae2b3ca7daa2 Mon Sep 17 00:00:00 2001 From: Allan Sandfeld Jensen Date: Fri, 11 Mar 2016 14:32:21 +0100 Subject: Skip old benchmark that doesn't build automatically This benchmark requires QtScript1 headers, and can not build as is. Change-Id: I98e57ca2db82270a0887462d7959ff00e352166b Reviewed-by: hjk --- tests/benchmarks/corelib/tools/tools.pro | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/benchmarks/corelib/tools/tools.pro b/tests/benchmarks/corelib/tools/tools.pro index d9ec5edd7c..af9b7d241d 100644 --- a/tests/benchmarks/corelib/tools/tools.pro +++ b/tests/benchmarks/corelib/tools/tools.pro @@ -10,7 +10,6 @@ SUBDIRS = \ qlocale \ qmap \ qrect \ - qregexp \ qringbuffer \ qstack \ qstring \ -- cgit v1.2.3 From 40ece5edcfcc5674524332a4db500371cc109330 Mon Sep 17 00:00:00 2001 From: Richard Moe Gustavsen Date: Wed, 13 Apr 2016 14:40:54 +0200 Subject: QTextEdit: update cursor and anchor rect upon scrolling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Both cursor and anchor rect will change locally when scrolling. So inform IM about it, so that any overlay done from e.g the platform plugins for dealing with text selection etc. can respond to the change. Change-Id: I4e839e691a20ad07d2aa062e028d22cf5f31b7fa Reviewed-by: Jan Arve Sæther --- src/widgets/widgets/qplaintextedit.cpp | 1 + src/widgets/widgets/qtextedit.cpp | 1 + 2 files changed, 2 insertions(+) diff --git a/src/widgets/widgets/qplaintextedit.cpp b/src/widgets/widgets/qplaintextedit.cpp index 35ec88b881..1da8028efb 100644 --- a/src/widgets/widgets/qplaintextedit.cpp +++ b/src/widgets/widgets/qplaintextedit.cpp @@ -667,6 +667,7 @@ void QPlainTextEditPrivate::setTopBlock(int blockNumber, int lineNumber, int dx) if (dx || dy) { viewport->scroll(q->isRightToLeft() ? -dx : dx, dy); + QGuiApplication::inputMethod()->update(Qt::ImCursorRectangle | Qt::ImAnchorRectangle); } else { viewport->update(); topLineFracture = 0; diff --git a/src/widgets/widgets/qtextedit.cpp b/src/widgets/widgets/qtextedit.cpp index 68b6ea6cbe..a81781bd4d 100644 --- a/src/widgets/widgets/qtextedit.cpp +++ b/src/widgets/widgets/qtextedit.cpp @@ -1713,6 +1713,7 @@ void QTextEdit::scrollContentsBy(int dx, int dy) if (isRightToLeft()) dx = -dx; d->viewport->scroll(dx, dy); + QGuiApplication::inputMethod()->update(Qt::ImCursorRectangle | Qt::ImAnchorRectangle); } /*!\reimp -- cgit v1.2.3 From ba30566b259e5f4282697be9a4e31940bebfd55b Mon Sep 17 00:00:00 2001 From: BogDan Vatra Date: Tue, 12 Apr 2016 18:33:17 +0300 Subject: Android: fix crash when subclassing the QtActivity m_context.getClass() returns the top class and this way QtApplication can't find the proper class Name (QtActivity and QtService). This patch passes the right class names to QtLoader/QtApplication. Task-number: QTBUG-52373 Change-Id: Ib69446cdaa38ac8b489872c4850210e5d503492e Reviewed-by: Christian Stromme --- .../src/org/qtproject/qt5/android/bindings/QtActivityLoader.java | 2 +- .../java/src/org/qtproject/qt5/android/bindings/QtApplication.java | 5 ++++- .../java/src/org/qtproject/qt5/android/bindings/QtLoader.java | 6 ++++-- .../src/org/qtproject/qt5/android/bindings/QtServiceLoader.java | 2 +- 4 files changed, 10 insertions(+), 5 deletions(-) diff --git a/src/android/java/src/org/qtproject/qt5/android/bindings/QtActivityLoader.java b/src/android/java/src/org/qtproject/qt5/android/bindings/QtActivityLoader.java index 92cea65e4b..2494035c60 100644 --- a/src/android/java/src/org/qtproject/qt5/android/bindings/QtActivityLoader.java +++ b/src/android/java/src/org/qtproject/qt5/android/bindings/QtActivityLoader.java @@ -55,7 +55,7 @@ public class QtActivityLoader extends QtLoader { QtActivityLoader(QtActivity activity) { - super(activity); + super(activity, QtActivity.class); m_activity = activity; } @Override diff --git a/src/android/java/src/org/qtproject/qt5/android/bindings/QtApplication.java b/src/android/java/src/org/qtproject/qt5/android/bindings/QtApplication.java index 2afede6d66..1078060d7f 100644 --- a/src/android/java/src/org/qtproject/qt5/android/bindings/QtApplication.java +++ b/src/android/java/src/org/qtproject/qt5/android/bindings/QtApplication.java @@ -133,8 +133,11 @@ public class QtApplication extends Application break; } } + if (-1 == stackDeep) + return result; + final String methodName=elements[stackDeep].getMethodName(); - if (-1 == stackDeep || !m_delegateMethods.containsKey(methodName)) + if (!m_delegateMethods.containsKey(methodName)) return result; for (Method m : m_delegateMethods.get(methodName)) { diff --git a/src/android/java/src/org/qtproject/qt5/android/bindings/QtLoader.java b/src/android/java/src/org/qtproject/qt5/android/bindings/QtLoader.java index 3efdbf7a7c..d281cb0996 100644 --- a/src/android/java/src/org/qtproject/qt5/android/bindings/QtLoader.java +++ b/src/android/java/src/org/qtproject/qt5/android/bindings/QtLoader.java @@ -152,9 +152,11 @@ public abstract class QtLoader { public int m_displayDensity = -1; private ContextWrapper m_context; protected ComponentInfo m_contextInfo; + private Class m_delegateClass; - QtLoader(ContextWrapper context) { + QtLoader(ContextWrapper context, Class clazz) { m_context = context; + m_delegateClass = clazz; } // Implement in subclass @@ -235,7 +237,7 @@ public abstract class QtLoader { if (!(Boolean)prepareAppMethod.invoke(qtLoader, m_context, classLoader, loaderParams)) throw new Exception(""); - QtApplication.setQtContextDelegate(m_context.getClass(), qtLoader); + QtApplication.setQtContextDelegate(m_delegateClass, qtLoader); // now load the application library so it's accessible from this class loader if (libName != null) diff --git a/src/android/java/src/org/qtproject/qt5/android/bindings/QtServiceLoader.java b/src/android/java/src/org/qtproject/qt5/android/bindings/QtServiceLoader.java index e64018f0a8..60aecbf7b3 100644 --- a/src/android/java/src/org/qtproject/qt5/android/bindings/QtServiceLoader.java +++ b/src/android/java/src/org/qtproject/qt5/android/bindings/QtServiceLoader.java @@ -42,7 +42,7 @@ import android.content.pm.PackageManager; public class QtServiceLoader extends QtLoader { QtService m_service; QtServiceLoader(QtService service) { - super(service); + super(service, QtService.class); m_service = service; } -- cgit v1.2.3 From f942d82d143a69c34ac769cf201690941d8db648 Mon Sep 17 00:00:00 2001 From: Timur Pocheptsov Date: Wed, 13 Apr 2016 12:58:54 +0200 Subject: Cocoa integration - invert 'masked out event' logic MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If a mask region contains a point - the event is _not_ masked out. Task-number: QTBUG-52533 Change-Id: I56d0276f5e3853479c2687addb95c2600edd3cda Reviewed-by: Shawn Rutledge Reviewed-by: Morten Johan Sørvig --- src/plugins/platforms/cocoa/qnsview.mm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/plugins/platforms/cocoa/qnsview.mm b/src/plugins/platforms/cocoa/qnsview.mm index a2e3b9a949..12629700ec 100644 --- a/src/plugins/platforms/cocoa/qnsview.mm +++ b/src/plugins/platforms/cocoa/qnsview.mm @@ -844,7 +844,7 @@ QT_WARNING_POP Q_UNUSED(qtScreenPoint); // Maintain masked state for the button for use by MouseDragged and MouseUp. - const bool masked = m_maskRegion.contains(qtWindowPoint.toPoint()); + const bool masked = [self hasMask] && !m_maskRegion.contains(qtWindowPoint.toPoint()); if (masked) m_acceptedMouseDowns &= ~button; else @@ -950,7 +950,7 @@ QT_WARNING_POP [self convertFromScreen:[self screenMousePoint:theEvent] toWindowPoint:&qtWindowPoint andScreenPoint:&qtScreenPoint]; Q_UNUSED(qtScreenPoint); - bool masked = m_maskRegion.contains(qtWindowPoint.toPoint()); + const bool masked = [self hasMask] && !m_maskRegion.contains(qtWindowPoint.toPoint()); // Maintain masked state for the button for use by MouseDragged and Up. if (masked) -- cgit v1.2.3 From 48e30656a704ac540986ca4f6d40ae249c3041be Mon Sep 17 00:00:00 2001 From: Richard Moe Gustavsen Date: Wed, 13 Apr 2016 12:14:52 +0200 Subject: QComboBox: Implement support for IM queries with QVariant argument MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: If59c36fa1b18a0d5562047dd06758fbcdbf63bc7 Reviewed-by: Marc Mutz Reviewed-by: Jan Arve Sæther --- src/widgets/widgets/qcombobox.cpp | 8 ++++++++ src/widgets/widgets/qcombobox.h | 1 + 2 files changed, 9 insertions(+) diff --git a/src/widgets/widgets/qcombobox.cpp b/src/widgets/widgets/qcombobox.cpp index 08c8117e0b..7992409265 100644 --- a/src/widgets/widgets/qcombobox.cpp +++ b/src/widgets/widgets/qcombobox.cpp @@ -3352,6 +3352,14 @@ QVariant QComboBox::inputMethodQuery(Qt::InputMethodQuery query) const return QWidget::inputMethodQuery(query); } +QVariant QComboBox::inputMethodQuery(Qt::InputMethodQuery query, const QVariant &argument) const +{ + Q_D(const QComboBox); + if (d->lineEdit) + return d->lineEdit->inputMethodQuery(query, argument); + return QWidget::inputMethodQuery(query); +} + /*! \fn void QComboBox::addItem(const QString &text, const QVariant &userData) diff --git a/src/widgets/widgets/qcombobox.h b/src/widgets/widgets/qcombobox.h index ed967e94f7..095a06fe31 100644 --- a/src/widgets/widgets/qcombobox.h +++ b/src/widgets/widgets/qcombobox.h @@ -202,6 +202,7 @@ public: bool event(QEvent *event) Q_DECL_OVERRIDE; QVariant inputMethodQuery(Qt::InputMethodQuery) const Q_DECL_OVERRIDE; + Q_INVOKABLE QVariant inputMethodQuery(Qt::InputMethodQuery query, const QVariant &argument) const; public Q_SLOTS: void clear(); -- cgit v1.2.3 From dfe8a85e7cdabfd04ad71ecf05110f9754134f95 Mon Sep 17 00:00:00 2001 From: Milla Pohjanheimo Date: Tue, 12 Apr 2016 14:51:11 +0300 Subject: Blacklisting autotests that fail on RHEL 7.1 also on RHEL 7.2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Blacklisting those autotests that prevent us to get RHEL 7.2 in the CI. The same tests have already been blacklisted for RHEL 7.1. Change-Id: I2aa62647f7bd75681ea9e1d69bc62f9542fda5e2 Reviewed-by: Tony Sarajärvi --- tests/auto/network/access/qnetworkreply/BLACKLIST | 2 ++ tests/auto/other/gestures/BLACKLIST | 1 + tests/auto/widgets/dialogs/qfontdialog/BLACKLIST | 1 + tests/auto/widgets/graphicsview/qgraphicsproxywidget/BLACKLIST | 1 + tests/auto/widgets/graphicsview/qgraphicswidget/BLACKLIST | 1 + tests/auto/widgets/kernel/qwidget/BLACKLIST | 1 + 6 files changed, 7 insertions(+) diff --git a/tests/auto/network/access/qnetworkreply/BLACKLIST b/tests/auto/network/access/qnetworkreply/BLACKLIST index 0605677e29..efa9cb61a8 100644 --- a/tests/auto/network/access/qnetworkreply/BLACKLIST +++ b/tests/auto/network/access/qnetworkreply/BLACKLIST @@ -9,5 +9,7 @@ ubuntu-14.04 * [authenticationCacheAfterCancel:http+socksauth] rhel-7.1 +rhel-7.2 [authenticationCacheAfterCancel:https+socksauth] rhel-7.1 +rhel-7.2 diff --git a/tests/auto/other/gestures/BLACKLIST b/tests/auto/other/gestures/BLACKLIST index 28e4856056..e33d36e201 100644 --- a/tests/auto/other/gestures/BLACKLIST +++ b/tests/auto/other/gestures/BLACKLIST @@ -1,4 +1,5 @@ [] rhel-7.1 +rhel-7.2 [customGesture] opensuse-13.1 diff --git a/tests/auto/widgets/dialogs/qfontdialog/BLACKLIST b/tests/auto/widgets/dialogs/qfontdialog/BLACKLIST index 669ec50978..b62f3e3344 100644 --- a/tests/auto/widgets/dialogs/qfontdialog/BLACKLIST +++ b/tests/auto/widgets/dialogs/qfontdialog/BLACKLIST @@ -1,3 +1,4 @@ [task256466_wrongStyle] opensuse-13.1 rhel-7.1 +rhel-7.2 diff --git a/tests/auto/widgets/graphicsview/qgraphicsproxywidget/BLACKLIST b/tests/auto/widgets/graphicsview/qgraphicsproxywidget/BLACKLIST index 373343fa22..16f3534921 100644 --- a/tests/auto/widgets/graphicsview/qgraphicsproxywidget/BLACKLIST +++ b/tests/auto/widgets/graphicsview/qgraphicsproxywidget/BLACKLIST @@ -1,5 +1,6 @@ [hoverEnterLeaveEvent] ubuntu-14.04 rhel-7.1 +rhel-7.2 [QTBUG_6986_sendMouseEventToAlienWidget] rhel-7.1 diff --git a/tests/auto/widgets/graphicsview/qgraphicswidget/BLACKLIST b/tests/auto/widgets/graphicsview/qgraphicswidget/BLACKLIST index c8d93585b2..13ec840eff 100644 --- a/tests/auto/widgets/graphicsview/qgraphicswidget/BLACKLIST +++ b/tests/auto/widgets/graphicsview/qgraphicswidget/BLACKLIST @@ -1,3 +1,4 @@ [initialShow2] ubuntu-14.04 rhel-7.1 +rhel-7.2 diff --git a/tests/auto/widgets/kernel/qwidget/BLACKLIST b/tests/auto/widgets/kernel/qwidget/BLACKLIST index 4563da8d48..0a344cd52d 100644 --- a/tests/auto/widgets/kernel/qwidget/BLACKLIST +++ b/tests/auto/widgets/kernel/qwidget/BLACKLIST @@ -11,6 +11,7 @@ osx [updateWhileMinimized] ubuntu-14.04 rhel-7.1 +rhel-7.2 osx [focusProxyAndInputMethods] linux -- cgit v1.2.3 From 23ab267c724414de67b0ee5b29eca027bdf23fab Mon Sep 17 00:00:00 2001 From: J-P Nurmi Date: Thu, 14 Apr 2016 16:34:36 +0200 Subject: QGuiApplication: don't force lower case styleOverride QtQuick Controls 2.0 is going to have capitalized style names (Material, Universal, ...) so move the toLower() call to QApplication where widgets make use of styleOverride. Change-Id: I5a8c5ee38517690728f5f8f01024d4e692c81668 Reviewed-by: Liang Qi --- src/gui/kernel/qguiapplication.cpp | 4 ++-- src/widgets/kernel/qapplication.cpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/gui/kernel/qguiapplication.cpp b/src/gui/kernel/qguiapplication.cpp index 2bc5462b43..a9f0ab04a1 100644 --- a/src/gui/kernel/qguiapplication.cpp +++ b/src/gui/kernel/qguiapplication.cpp @@ -1366,9 +1366,9 @@ void QGuiApplicationPrivate::init() } else if (strcmp(arg, "-testability") == 0) { loadTestability = true; } else if (strncmp(arg, "-style=", 7) == 0) { - s = QString::fromLocal8Bit(arg + 7).toLower(); + s = QString::fromLocal8Bit(arg + 7); } else if (strcmp(arg, "-style") == 0 && i < argc - 1) { - s = QString::fromLocal8Bit(argv[++i]).toLower(); + s = QString::fromLocal8Bit(argv[++i]); } else { argv[j++] = argv[i]; } diff --git a/src/widgets/kernel/qapplication.cpp b/src/widgets/kernel/qapplication.cpp index 141f15637c..4bc06c94e0 100644 --- a/src/widgets/kernel/qapplication.cpp +++ b/src/widgets/kernel/qapplication.cpp @@ -1127,7 +1127,7 @@ QStyle *QApplication::style() QString style; QString envStyle = QString::fromLocal8Bit(qgetenv("QT_STYLE_OVERRIDE")); if (!QApplicationPrivate::styleOverride.isEmpty()) { - style = QApplicationPrivate::styleOverride; + style = QApplicationPrivate::styleOverride.toLower(); } else if (!envStyle.isEmpty()) { style = envStyle; } else { -- cgit v1.2.3 From 920fc1a523f63cc08d73af32b354379b29572652 Mon Sep 17 00:00:00 2001 From: Allan Sandfeld Jensen Date: Thu, 14 Apr 2016 13:21:40 +0200 Subject: Fix perspective clipping regression Undoes part of c327fb79e1a50c825a945e97f2c66d07a1c6d225 so perspective transforms are still handled by QTransform on the path. Change-Id: I4801f24898a401ff93a96a852170ea6b7b70ce1c Reviewed-by: aavit --- src/gui/painting/qoutlinemapper.cpp | 28 +++++++++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/src/gui/painting/qoutlinemapper.cpp b/src/gui/painting/qoutlinemapper.cpp index 0d10fa18bb..7245b44fc7 100644 --- a/src/gui/painting/qoutlinemapper.cpp +++ b/src/gui/painting/qoutlinemapper.cpp @@ -188,9 +188,27 @@ void QOutlineMapper::endOutline() QPointF *elements = m_elements.data(); // Transform the outline - if (!m_in_clip_elements) { + if (m_transform.isIdentity()) { + // Nothing to do + } else if (m_transform.type() < QTransform::TxProject) { for (int i = 0; i < m_elements.size(); ++i) elements[i] = m_transform.map(elements[i]); + } else { + const QVectorPath vp((qreal *)elements, m_elements.size(), + m_element_types.size() ? m_element_types.data() : 0); + QPainterPath path = vp.convertToPainterPath(); + path = m_transform.map(path); + if (!(m_outline.flags & QT_FT_OUTLINE_EVEN_ODD_FILL)) + path.setFillRule(Qt::WindingFill); + if (path.isEmpty()) { + m_valid = false; + } else { + QTransform oldTransform = m_transform; + m_transform.reset(); + convertPath(path); + m_transform = oldTransform; + } + return; } controlPointRect = boundingRect(elements, m_elements.size()); @@ -358,10 +376,14 @@ void QOutlineMapper::clipElements(const QPointF *elements, QPainterPath clipPath; clipPath.addRect(m_clip_rect); QPainterPath clippedPath = path.intersected(clipPath); - if (clippedPath.isEmpty()) + if (clippedPath.isEmpty()) { m_valid = false; - else + } else { + QTransform oldTransform = m_transform; + m_transform.reset(); convertPath(clippedPath); + m_transform = oldTransform; + } m_in_clip_elements = false; } -- cgit v1.2.3 From 224f31c0b5ad86b5ea56025ff08faf7e25e1a82d Mon Sep 17 00:00:00 2001 From: Dominik Holland Date: Thu, 24 Mar 2016 15:38:05 +0100 Subject: Multi-screen handling for the eglfs_kms_egldevice backend Separates the generic kms classes into a own kms static lib called QtEglFsKmsSupport. The eglfs_kms plugin was changed to use these base classes and got renamed accordingly to QEglFSKmsGbm*. The eglfs_kms_egldevice plugin got extended to also derive from the kms base classed and by this provides multi-screen support Change-Id: I6de6a754e94cb8d52cf8e658b03c6bd6637674a1 Reviewed-by: Laszlo Agocs --- .../eglfs/deviceintegration/deviceintegration.pro | 7 +- .../deviceintegration/eglfs_kms/eglfs_kms.pro | 36 +- .../eglfs_kms/qeglfskmscursor.cpp | 239 ----------- .../deviceintegration/eglfs_kms/qeglfskmscursor.h | 92 ---- .../eglfs_kms/qeglfskmsdevice.cpp | 463 --------------------- .../deviceintegration/eglfs_kms/qeglfskmsdevice.h | 98 ----- .../eglfs_kms/qeglfskmsgbmcursor.cpp | 240 +++++++++++ .../eglfs_kms/qeglfskmsgbmcursor.h | 92 ++++ .../eglfs_kms/qeglfskmsgbmdevice.cpp | 158 +++++++ .../eglfs_kms/qeglfskmsgbmdevice.h | 90 ++++ .../eglfs_kms/qeglfskmsgbmintegration.cpp | 143 +++++++ .../eglfs_kms/qeglfskmsgbmintegration.h | 75 ++++ .../eglfs_kms/qeglfskmsgbmmain.cpp | 57 +++ .../eglfs_kms/qeglfskmsgbmscreen.cpp | 223 ++++++++++ .../eglfs_kms/qeglfskmsgbmscreen.h | 93 +++++ .../eglfs_kms/qeglfskmsintegration.cpp | 275 ------------ .../eglfs_kms/qeglfskmsintegration.h | 91 ---- .../deviceintegration/eglfs_kms/qeglfskmsmain.cpp | 56 --- .../eglfs_kms/qeglfskmsscreen.cpp | 359 ---------------- .../deviceintegration/eglfs_kms/qeglfskmsscreen.h | 149 ------- .../eglfs_kms_egldevice/eglfs_kms_egldevice.pro | 21 +- .../eglfs_kms_egldevice/qeglfskmsegldevice.cpp | 79 ++++ .../eglfs_kms_egldevice/qeglfskmsegldevice.h | 61 +++ .../qeglfskmsegldeviceintegration.cpp | 230 ++-------- .../qeglfskmsegldeviceintegration.h | 46 +- .../qeglfskmsegldevicescreen.cpp | 78 ++++ .../eglfs_kms_egldevice/qeglfskmsegldevicescreen.h | 56 +++ .../eglfs_kms_support/eglfs_kms_support.pro | 28 ++ .../eglfs_kms_support/qeglfskmsdevice.cpp | 404 ++++++++++++++++++ .../eglfs_kms_support/qeglfskmsdevice.h | 98 +++++ .../eglfs_kms_support/qeglfskmsintegration.cpp | 213 ++++++++++ .../eglfs_kms_support/qeglfskmsintegration.h | 93 +++++ .../eglfs_kms_support/qeglfskmsscreen.cpp | 220 ++++++++++ .../eglfs_kms_support/qeglfskmsscreen.h | 130 ++++++ 34 files changed, 2715 insertions(+), 2078 deletions(-) delete mode 100644 src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmscursor.cpp delete mode 100644 src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmscursor.h delete mode 100644 src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsdevice.cpp delete mode 100644 src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsdevice.h create mode 100644 src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmcursor.cpp create mode 100644 src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmcursor.h create mode 100644 src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmdevice.cpp create mode 100644 src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmdevice.h create mode 100644 src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmintegration.cpp create mode 100644 src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmintegration.h create mode 100644 src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmmain.cpp create mode 100644 src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmscreen.cpp create mode 100644 src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmscreen.h delete mode 100644 src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsintegration.cpp delete mode 100644 src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsintegration.h delete mode 100644 src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsmain.cpp delete mode 100644 src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsscreen.cpp delete mode 100644 src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsscreen.h create mode 100644 src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevice.cpp create mode 100644 src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevice.h create mode 100644 src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevicescreen.cpp create mode 100644 src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevicescreen.h create mode 100644 src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/eglfs_kms_support.pro create mode 100644 src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsdevice.cpp create mode 100644 src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsdevice.h create mode 100644 src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsintegration.cpp create mode 100644 src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsintegration.h create mode 100644 src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsscreen.cpp create mode 100644 src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsscreen.h diff --git a/src/plugins/platforms/eglfs/deviceintegration/deviceintegration.pro b/src/plugins/platforms/eglfs/deviceintegration/deviceintegration.pro index 266a97dff5..769c248d0d 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/deviceintegration.pro +++ b/src/plugins/platforms/eglfs/deviceintegration/deviceintegration.pro @@ -1,9 +1,12 @@ TEMPLATE = subdirs contains(QT_CONFIG, egl_x11): SUBDIRS += eglfs_x11 -contains(QT_CONFIG, eglfs_gbm): SUBDIRS += eglfs_kms -contains(QT_CONFIG, eglfs_egldevice): SUBDIRS += eglfs_kms_egldevice +contains(QT_CONFIG, eglfs_gbm): SUBDIRS += eglfs_kms_support eglfs_kms +contains(QT_CONFIG, eglfs_egldevice): SUBDIRS += eglfs_kms_support eglfs_kms_egldevice contains(QT_CONFIG, eglfs_brcm): SUBDIRS += eglfs_brcm contains(QT_CONFIG, eglfs_mali): SUBDIRS += eglfs_mali contains(QT_CONFIG, eglfs_viv): SUBDIRS += eglfs_viv contains(QT_CONFIG, eglfs_viv_wl): SUBDIRS += eglfs_viv_wl + +eglfs_kms_egldevice.depends = eglfs_kms_support +eglfs_kms.depends = eglfs_kms_support diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/eglfs_kms.pro b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/eglfs_kms.pro index 12ae0a13b1..82877710fc 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/eglfs_kms.pro +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/eglfs_kms.pro @@ -1,31 +1,35 @@ TARGET = qeglfs-kms-integration -QT += core-private gui-private platformsupport-private eglfs_device_lib-private +PLUGIN_TYPE = egldeviceintegrations +PLUGIN_CLASS_NAME = QEglFSKmsIntegrationPlugin +load(qt_plugin) + +QT += core-private gui-private platformsupport-private eglfs_device_lib-private eglfs_kms_support-private -INCLUDEPATH += $$PWD/../.. +INCLUDEPATH += $$PWD/../.. $$PWD/../eglfs_kms_support # Avoid X11 header collision DEFINES += MESA_EGL_NO_X11_HEADERS CONFIG += link_pkgconfig -PKGCONFIG += libdrm gbm +!contains(QT_CONFIG, no-pkg-config) { + PKGCONFIG += libdrm gbm +} else { + LIBS += -ldrm -lgbm +} CONFIG += egl QMAKE_LFLAGS += $$QMAKE_LFLAGS_NOUNDEF -SOURCES += $$PWD/qeglfskmsmain.cpp \ - $$PWD/qeglfskmsintegration.cpp \ - $$PWD/qeglfskmsdevice.cpp \ - $$PWD/qeglfskmsscreen.cpp \ - $$PWD/qeglfskmscursor.cpp +SOURCES += $$PWD/qeglfskmsgbmmain.cpp \ + $$PWD/qeglfskmsgbmintegration.cpp \ + $$PWD/qeglfskmsgbmdevice.cpp \ + $$PWD/qeglfskmsgbmscreen.cpp \ + $$PWD/qeglfskmsgbmcursor.cpp -HEADERS += $$PWD/qeglfskmsintegration.h \ - $$PWD/qeglfskmsdevice.h \ - $$PWD/qeglfskmsscreen.h \ - $$PWD/qeglfskmscursor.h +HEADERS += $$PWD/qeglfskmsgbmintegration.h \ + $$PWD/qeglfskmsgbmdevice.h \ + $$PWD/qeglfskmsgbmscreen.h \ + $$PWD/qeglfskmsgbmcursor.h OTHER_FILES += $$PWD/eglfs_kms.json - -PLUGIN_TYPE = egldeviceintegrations -PLUGIN_CLASS_NAME = QEglFSKmsIntegrationPlugin -load(qt_plugin) diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmscursor.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmscursor.cpp deleted file mode 100644 index ac966d23ee..0000000000 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmscursor.cpp +++ /dev/null @@ -1,239 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2015 Pier Luigi Fiorini -** 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 "qeglfskmscursor.h" -#include "qeglfskmsscreen.h" -#include "qeglfskmsdevice.h" - -#include -#include -#include -#include -#include - -#include -#include - -#ifndef DRM_CAP_CURSOR_WIDTH -#define DRM_CAP_CURSOR_WIDTH 0x8 -#endif - -#ifndef DRM_CAP_CURSOR_HEIGHT -#define DRM_CAP_CURSOR_HEIGHT 0x9 -#endif - -QT_BEGIN_NAMESPACE - -Q_DECLARE_LOGGING_CATEGORY(qLcEglfsKmsDebug) - -QEglFSKmsCursor::QEglFSKmsCursor(QEglFSKmsScreen *screen) - : m_screen(screen) - , m_cursorSize(64, 64) // 64x64 is the old standard size, we now try to query the real size below - , m_bo(Q_NULLPTR) - , m_cursorImage(0, 0, 0, 0, 0, 0) - , m_visible(true) -{ - QByteArray hideCursorVal = qgetenv("QT_QPA_EGLFS_HIDECURSOR"); - if (!hideCursorVal.isEmpty()) - m_visible = hideCursorVal.toInt() == 0; - if (!m_visible) - return; - - uint64_t width, height; - if ((drmGetCap(m_screen->device()->fd(), DRM_CAP_CURSOR_WIDTH, &width) == 0) - && (drmGetCap(m_screen->device()->fd(), DRM_CAP_CURSOR_HEIGHT, &height) == 0)) { - m_cursorSize.setWidth(width); - m_cursorSize.setHeight(height); - } - - m_bo = gbm_bo_create(m_screen->device()->device(), m_cursorSize.width(), m_cursorSize.height(), - GBM_FORMAT_ARGB8888, GBM_BO_USE_CURSOR_64X64 | GBM_BO_USE_WRITE); - if (!m_bo) { - qWarning("Could not create buffer for cursor!"); - } else { - initCursorAtlas(); - } - -#ifndef QT_NO_CURSOR - QCursor cursor(Qt::ArrowCursor); - changeCursor(&cursor, 0); -#endif - setPos(QPoint(0, 0)); -} - -QEglFSKmsCursor::~QEglFSKmsCursor() -{ - Q_FOREACH (QPlatformScreen *screen, m_screen->virtualSiblings()) { - QEglFSKmsScreen *kmsScreen = static_cast(screen); - drmModeSetCursor(kmsScreen->device()->fd(), kmsScreen->output().crtc_id, 0, 0, 0); - drmModeMoveCursor(kmsScreen->device()->fd(), kmsScreen->output().crtc_id, 0, 0); - } - - gbm_bo_destroy(m_bo); - m_bo = Q_NULLPTR; -} - -void QEglFSKmsCursor::pointerEvent(const QMouseEvent &event) -{ - setPos(event.screenPos().toPoint()); -} - -#ifndef QT_NO_CURSOR -void QEglFSKmsCursor::changeCursor(QCursor *windowCursor, QWindow *window) -{ - Q_UNUSED(window); - - if (!m_visible) - return; - - const Qt::CursorShape newShape = windowCursor ? windowCursor->shape() : Qt::ArrowCursor; - if (newShape == Qt::BitmapCursor) { - m_cursorImage.set(windowCursor->pixmap().toImage(), - windowCursor->hotSpot().x(), - windowCursor->hotSpot().y()); - } else { - // Standard cursor, look up in atlas - const int width = m_cursorAtlas.cursorWidth; - const int height = m_cursorAtlas.cursorHeight; - const qreal ws = (qreal)m_cursorAtlas.cursorWidth / m_cursorAtlas.width; - const qreal hs = (qreal)m_cursorAtlas.cursorHeight / m_cursorAtlas.height; - - QRect textureRect(ws * (newShape % m_cursorAtlas.cursorsPerRow) * m_cursorAtlas.width, - hs * (newShape / m_cursorAtlas.cursorsPerRow) * m_cursorAtlas.height, - width, - height); - QPoint hotSpot = m_cursorAtlas.hotSpots[newShape]; - m_cursorImage.set(m_cursorAtlas.image.copy(textureRect), - hotSpot.x(), - hotSpot.y()); - } - - if (m_cursorImage.image()->width() > m_cursorSize.width() || m_cursorImage.image()->height() > m_cursorSize.height()) - qWarning("Cursor larger than %dx%d, cursor will be clipped.", m_cursorSize.width(), m_cursorSize.height()); - - QImage cursorImage(m_cursorSize, QImage::Format_ARGB32); - cursorImage.fill(Qt::transparent); - - QPainter painter; - painter.begin(&cursorImage); - painter.drawImage(0, 0, *m_cursorImage.image()); - painter.end(); - - gbm_bo_write(m_bo, cursorImage.constBits(), cursorImage.byteCount()); - - uint32_t handle = gbm_bo_get_handle(m_bo).u32; - - Q_FOREACH (QPlatformScreen *screen, m_screen->virtualSiblings()) { - QEglFSKmsScreen *kmsScreen = static_cast(screen); - - int status = drmModeSetCursor(kmsScreen->device()->fd(), kmsScreen->output().crtc_id, handle, - m_cursorSize.width(), m_cursorSize.height()); - if (status != 0) - qWarning("Could not set cursor on screen %s: %d", kmsScreen->name().toLatin1().constData(), status); - } -} -#endif // QT_NO_CURSOR - -QPoint QEglFSKmsCursor::pos() const -{ - return m_pos; -} - -void QEglFSKmsCursor::setPos(const QPoint &pos) -{ - Q_FOREACH (QPlatformScreen *screen, m_screen->virtualSiblings()) { - QEglFSKmsScreen *kmsScreen = static_cast(screen); - QPoint origin = kmsScreen->geometry().topLeft(); - QPoint localPos = pos - origin; - QPoint adjustedPos = localPos - m_cursorImage.hotspot(); - - int ret = drmModeMoveCursor(kmsScreen->device()->fd(), kmsScreen->output().crtc_id, adjustedPos.x(), adjustedPos.y()); - if (ret == 0) - m_pos = pos; - else - qWarning("Failed to move cursor on screen %s: %d", kmsScreen->name().toLatin1().constData(), ret); - } -} - -void QEglFSKmsCursor::initCursorAtlas() -{ - static QByteArray json = qgetenv("QT_QPA_EGLFS_CURSOR"); - if (json.isEmpty()) - json = ":/cursor.json"; - - qCDebug(qLcEglfsKmsDebug) << "Initializing cursor atlas from" << json; - - QFile file(QString::fromUtf8(json)); - if (!file.open(QFile::ReadOnly)) { - Q_FOREACH (QPlatformScreen *screen, m_screen->virtualSiblings()) { - QEglFSKmsScreen *kmsScreen = static_cast(screen); - drmModeSetCursor(kmsScreen->device()->fd(), kmsScreen->output().crtc_id, 0, 0, 0); - drmModeMoveCursor(kmsScreen->device()->fd(), kmsScreen->output().crtc_id, 0, 0); - } - m_visible = false; - return; - } - - QJsonDocument doc = QJsonDocument::fromJson(file.readAll()); - QJsonObject object = doc.object(); - - QString atlas = object.value(QLatin1String("image")).toString(); - Q_ASSERT(!atlas.isEmpty()); - - const int cursorsPerRow = object.value(QLatin1String("cursorsPerRow")).toDouble(); - Q_ASSERT(cursorsPerRow); - m_cursorAtlas.cursorsPerRow = cursorsPerRow; - - const QJsonArray hotSpots = object.value(QLatin1String("hotSpots")).toArray(); - Q_ASSERT(hotSpots.count() == Qt::LastCursor + 1); - for (int i = 0; i < hotSpots.count(); i++) { - QPoint hotSpot(hotSpots[i].toArray()[0].toDouble(), hotSpots[i].toArray()[1].toDouble()); - m_cursorAtlas.hotSpots << hotSpot; - } - - QImage image = QImage(atlas).convertToFormat(QImage::Format_ARGB32); - m_cursorAtlas.cursorWidth = image.width() / m_cursorAtlas.cursorsPerRow; - m_cursorAtlas.cursorHeight = image.height() / ((Qt::LastCursor + cursorsPerRow) / cursorsPerRow); - m_cursorAtlas.width = image.width(); - m_cursorAtlas.height = image.height(); - m_cursorAtlas.image = image; -} - -QT_END_NAMESPACE diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmscursor.h b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmscursor.h deleted file mode 100644 index bbdd87cefd..0000000000 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmscursor.h +++ /dev/null @@ -1,92 +0,0 @@ -/**************************************************************************** -** -** 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 QEGLFSKMSCURSOR_H -#define QEGLFSKMSCURSOR_H - -#include -#include -#include - -#include - -QT_BEGIN_NAMESPACE - -class QEglFSKmsScreen; - -class QEglFSKmsCursor : public QPlatformCursor -{ - Q_OBJECT - -public: - QEglFSKmsCursor(QEglFSKmsScreen *screen); - ~QEglFSKmsCursor(); - - // input methods - void pointerEvent(const QMouseEvent & event) Q_DECL_OVERRIDE; -#ifndef QT_NO_CURSOR - void changeCursor(QCursor * windowCursor, QWindow * window) Q_DECL_OVERRIDE; -#endif - QPoint pos() const Q_DECL_OVERRIDE; - void setPos(const QPoint &pos) Q_DECL_OVERRIDE; - -private: - void initCursorAtlas(); - - QEglFSKmsScreen *m_screen; - QSize m_cursorSize; - gbm_bo *m_bo; - QPoint m_pos; - QPlatformCursorImage m_cursorImage; - bool m_visible; - - // cursor atlas information - struct CursorAtlas { - CursorAtlas() : cursorsPerRow(0), cursorWidth(0), cursorHeight(0) { } - int cursorsPerRow; - int width, height; // width and height of the atlas - int cursorWidth, cursorHeight; // width and height of cursors inside the atlas - QList hotSpots; - QImage image; - } m_cursorAtlas; -}; - -QT_END_NAMESPACE - -#endif diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsdevice.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsdevice.cpp deleted file mode 100644 index c4673edb11..0000000000 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsdevice.cpp +++ /dev/null @@ -1,463 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2015 Pier Luigi Fiorini -** 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 "qeglfskmsdevice.h" -#include "qeglfskmsscreen.h" - -#include "qeglfsintegration.h" - -#include -#include -#include - -#define ARRAY_LENGTH(a) (sizeof (a) / sizeof (a)[0]) - -QT_BEGIN_NAMESPACE - -Q_DECLARE_LOGGING_CATEGORY(qLcEglfsKmsDebug) - -enum OutputConfiguration { - OutputConfigOff, - OutputConfigPreferred, - OutputConfigCurrent, - OutputConfigMode, - OutputConfigModeline -}; - -int QEglFSKmsDevice::crtcForConnector(drmModeResPtr resources, drmModeConnectorPtr connector) -{ - for (int i = 0; i < connector->count_encoders; i++) { - drmModeEncoderPtr encoder = drmModeGetEncoder(m_dri_fd, connector->encoders[i]); - if (!encoder) { - qWarning("Failed to get encoder"); - continue; - } - - quint32 possibleCrtcs = encoder->possible_crtcs; - drmModeFreeEncoder(encoder); - - for (int j = 0; j < resources->count_crtcs; j++) { - bool isPossible = possibleCrtcs & (1 << j); - bool isAvailable = !(m_crtc_allocator & 1 << resources->crtcs[j]); - - if (isPossible && isAvailable) - return j; - } - } - - return -1; -} - -static const char * const connector_type_names[] = { - "None", - "VGA", - "DVI", - "DVI", - "DVI", - "Composite", - "TV", - "LVDS", - "CTV", - "DIN", - "DP", - "HDMI", - "HDMI", - "TV", - "eDP", -}; - -static QByteArray nameForConnector(const drmModeConnectorPtr connector) -{ - QByteArray connectorName("UNKNOWN"); - - if (connector->connector_type < ARRAY_LENGTH(connector_type_names)) - connectorName = connector_type_names[connector->connector_type]; - - connectorName += QByteArray::number(connector->connector_type_id); - - return connectorName; -} - -static bool parseModeline(const QByteArray &text, drmModeModeInfoPtr mode) -{ - char hsync[16]; - char vsync[16]; - float fclock; - - mode->type = DRM_MODE_TYPE_USERDEF; - mode->hskew = 0; - mode->vscan = 0; - mode->vrefresh = 0; - mode->flags = 0; - - if (sscanf(text.constData(), "%f %hd %hd %hd %hd %hd %hd %hd %hd %15s %15s", - &fclock, - &mode->hdisplay, - &mode->hsync_start, - &mode->hsync_end, - &mode->htotal, - &mode->vdisplay, - &mode->vsync_start, - &mode->vsync_end, - &mode->vtotal, hsync, vsync) != 11) - return false; - - mode->clock = fclock * 1000; - - if (strcmp(hsync, "+hsync") == 0) - mode->flags |= DRM_MODE_FLAG_PHSYNC; - else if (strcmp(hsync, "-hsync") == 0) - mode->flags |= DRM_MODE_FLAG_NHSYNC; - else - return false; - - if (strcmp(vsync, "+vsync") == 0) - mode->flags |= DRM_MODE_FLAG_PVSYNC; - else if (strcmp(vsync, "-vsync") == 0) - mode->flags |= DRM_MODE_FLAG_NVSYNC; - else - return false; - - return true; -} - -QEglFSKmsScreen *QEglFSKmsDevice::screenForConnector(drmModeResPtr resources, drmModeConnectorPtr connector, QPoint pos) -{ - const QByteArray connectorName = nameForConnector(connector); - - const int crtc = crtcForConnector(resources, connector); - if (crtc < 0) { - qWarning() << "No usable crtc/encoder pair for connector" << connectorName; - return Q_NULLPTR; - } - - OutputConfiguration configuration; - QSize configurationSize; - drmModeModeInfo configurationModeline; - - const QByteArray mode = m_integration->outputSettings().value(QString::fromUtf8(connectorName)) - .value(QStringLiteral("mode"), QStringLiteral("preferred")).toByteArray().toLower(); - if (mode == "off") { - configuration = OutputConfigOff; - } else if (mode == "preferred") { - configuration = OutputConfigPreferred; - } else if (mode == "current") { - configuration = OutputConfigCurrent; - } else if (sscanf(mode.constData(), "%dx%d", &configurationSize.rwidth(), &configurationSize.rheight()) == 2) { - configuration = OutputConfigMode; - } else if (parseModeline(mode, &configurationModeline)) { - configuration = OutputConfigModeline; - } else { - qWarning("Invalid mode \"%s\" for output %s", mode.constData(), connectorName.constData()); - configuration = OutputConfigPreferred; - } - - const uint32_t crtc_id = resources->crtcs[crtc]; - - if (configuration == OutputConfigOff) { - qCDebug(qLcEglfsKmsDebug) << "Turning off output" << connectorName; - drmModeSetCrtc(m_dri_fd, crtc_id, 0, 0, 0, 0, 0, Q_NULLPTR); - return Q_NULLPTR; - } - - // Skip disconnected output - if (configuration == OutputConfigPreferred && connector->connection == DRM_MODE_DISCONNECTED) { - qCDebug(qLcEglfsKmsDebug) << "Skipping disconnected output" << connectorName; - return Q_NULLPTR; - } - - // Get the current mode on the current crtc - drmModeModeInfo crtc_mode; - memset(&crtc_mode, 0, sizeof crtc_mode); - if (drmModeEncoderPtr encoder = drmModeGetEncoder(m_dri_fd, connector->connector_id)) { - drmModeCrtcPtr crtc = drmModeGetCrtc(m_dri_fd, encoder->crtc_id); - drmModeFreeEncoder(encoder); - - if (!crtc) - return Q_NULLPTR; - - if (crtc->mode_valid) - crtc_mode = crtc->mode; - - drmModeFreeCrtc(crtc); - } - - QList modes; - modes.reserve(connector->count_modes); - qCDebug(qLcEglfsKmsDebug) << connectorName << "mode count:" << connector->count_modes; - for (int i = 0; i < connector->count_modes; i++) { - const drmModeModeInfo &mode = connector->modes[i]; - qCDebug(qLcEglfsKmsDebug) << "mode" << i << mode.hdisplay << "x" << mode.vdisplay - << '@' << mode.vrefresh << "hz"; - modes << connector->modes[i]; - } - - int preferred = -1; - int current = -1; - int configured = -1; - int best = -1; - - for (int i = modes.size() - 1; i >= 0; i--) { - const drmModeModeInfo &m = modes.at(i); - - if (configuration == OutputConfigMode && - m.hdisplay == configurationSize.width() && - m.vdisplay == configurationSize.height()) { - configured = i; - } - - if (!memcmp(&crtc_mode, &m, sizeof m)) - current = i; - - if (m.type & DRM_MODE_TYPE_PREFERRED) - preferred = i; - - best = i; - } - - if (configuration == OutputConfigModeline) { - modes << configurationModeline; - configured = modes.size() - 1; - } - - if (current < 0 && crtc_mode.clock != 0) { - modes << crtc_mode; - current = mode.size() - 1; - } - - if (configuration == OutputConfigCurrent) - configured = current; - - int selected_mode = -1; - - if (configured >= 0) - selected_mode = configured; - else if (preferred >= 0) - selected_mode = preferred; - else if (current >= 0) - selected_mode = current; - else if (best >= 0) - selected_mode = best; - - if (selected_mode < 0) { - qWarning() << "No modes available for output" << connectorName; - return Q_NULLPTR; - } else { - int width = modes[selected_mode].hdisplay; - int height = modes[selected_mode].vdisplay; - int refresh = modes[selected_mode].vrefresh; - qCDebug(qLcEglfsKmsDebug) << "Selected mode" << selected_mode << ":" << width << "x" << height - << '@' << refresh << "hz for output" << connectorName; - } - static const int width = qEnvironmentVariableIntValue("QT_QPA_EGLFS_PHYSICAL_WIDTH"); - static const int height = qEnvironmentVariableIntValue("QT_QPA_EGLFS_PHYSICAL_HEIGHT"); - QSizeF size(width, height); - if (size.isEmpty()) { - size.setWidth(connector->mmWidth); - size.setHeight(connector->mmHeight); - } - QEglFSKmsOutput output = { - QString::fromUtf8(connectorName), - connector->connector_id, - crtc_id, - size, - selected_mode, - false, - drmModeGetCrtc(m_dri_fd, crtc_id), - modes, - connector->subpixel, - connectorProperty(connector, QByteArrayLiteral("DPMS")) - }; - - m_crtc_allocator |= (1 << output.crtc_id); - m_connector_allocator |= (1 << output.connector_id); - - return new QEglFSKmsScreen(m_integration, this, output, pos); -} - -drmModePropertyPtr QEglFSKmsDevice::connectorProperty(drmModeConnectorPtr connector, const QByteArray &name) -{ - drmModePropertyPtr prop; - - for (int i = 0; i < connector->count_props; i++) { - prop = drmModeGetProperty(m_dri_fd, connector->props[i]); - if (!prop) - continue; - if (strcmp(prop->name, name.constData()) == 0) - return prop; - drmModeFreeProperty(prop); - } - - return Q_NULLPTR; -} - -void QEglFSKmsDevice::pageFlipHandler(int fd, unsigned int sequence, unsigned int tv_sec, unsigned int tv_usec, void *user_data) -{ - Q_UNUSED(fd); - Q_UNUSED(sequence); - Q_UNUSED(tv_sec); - Q_UNUSED(tv_usec); - - QEglFSKmsScreen *screen = static_cast(user_data); - screen->flipFinished(); -} - -QEglFSKmsDevice::QEglFSKmsDevice(QEglFSKmsIntegration *integration, const QString &path) - : m_integration(integration) - , m_path(path) - , m_dri_fd(-1) - , m_gbm_device(Q_NULLPTR) - , m_crtc_allocator(0) - , m_connector_allocator(0) - , m_globalCursor(Q_NULLPTR) -{ -} - -bool QEglFSKmsDevice::open() -{ - Q_ASSERT(m_dri_fd == -1); - Q_ASSERT(m_gbm_device == Q_NULLPTR); - - qCDebug(qLcEglfsKmsDebug) << "Opening device" << m_path; - m_dri_fd = qt_safe_open(m_path.toLocal8Bit().constData(), O_RDWR | O_CLOEXEC); - if (m_dri_fd == -1) { - qErrnoWarning("Could not open DRM device %s", qPrintable(m_path)); - return false; - } - - qCDebug(qLcEglfsKmsDebug) << "Creating GBM device for file descriptor" << m_dri_fd - << "obtained from" << m_path; - m_gbm_device = gbm_create_device(m_dri_fd); - if (!m_gbm_device) { - qErrnoWarning("Could not create GBM device"); - qt_safe_close(m_dri_fd); - m_dri_fd = -1; - return false; - } - - return true; -} - -void QEglFSKmsDevice::close() -{ - if (m_gbm_device) { - gbm_device_destroy(m_gbm_device); - m_gbm_device = Q_NULLPTR; - } - - if (m_dri_fd != -1) { - qt_safe_close(m_dri_fd); - m_dri_fd = -1; - } - - if (m_globalCursor) - m_globalCursor->deleteLater(); - m_globalCursor = Q_NULLPTR; -} - -void QEglFSKmsDevice::createScreens() -{ - drmModeResPtr resources = drmModeGetResources(m_dri_fd); - if (!resources) { - qWarning("drmModeGetResources failed"); - return; - } - - QEglFSKmsScreen *primaryScreen = Q_NULLPTR; - QList siblings; - QPoint pos(0, 0); - QEglFSIntegration *integration = static_cast(QGuiApplicationPrivate::platformIntegration()); - - for (int i = 0; i < resources->count_connectors; i++) { - drmModeConnectorPtr connector = drmModeGetConnector(m_dri_fd, resources->connectors[i]); - if (!connector) - continue; - - QEglFSKmsScreen *screen = screenForConnector(resources, connector, pos); - if (screen) { - integration->addScreen(screen); - pos.rx() += screen->geometry().width(); - siblings << screen; - - if (!primaryScreen) - primaryScreen = screen; - } - - drmModeFreeConnector(connector); - } - - drmModeFreeResources(resources); - - if (!m_integration->separateScreens()) { - Q_FOREACH (QPlatformScreen *screen, siblings) - static_cast(screen)->setVirtualSiblings(siblings); - - if (primaryScreen && m_integration->hwCursor()) - m_globalCursor = new QEglFSKmsCursor(primaryScreen); - } -} - -gbm_device *QEglFSKmsDevice::device() const -{ - return m_gbm_device; -} - -int QEglFSKmsDevice::fd() const -{ - return m_dri_fd; -} - -QPlatformCursor *QEglFSKmsDevice::globalCursor() const -{ - return m_globalCursor; -} - -void QEglFSKmsDevice::handleDrmEvent() -{ - drmEventContext drmEvent = { - DRM_EVENT_CONTEXT_VERSION, - Q_NULLPTR, // vblank handler - pageFlipHandler // page flip handler - }; - - drmHandleEvent(m_dri_fd, &drmEvent); -} - -QT_END_NAMESPACE diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsdevice.h b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsdevice.h deleted file mode 100644 index eab5ac9934..0000000000 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsdevice.h +++ /dev/null @@ -1,98 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2015 Pier Luigi Fiorini -** 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 QEGLFSKMSDEVICE_H -#define QEGLFSKMSDEVICE_H - -#include "qeglfskmscursor.h" -#include "qeglfskmsintegration.h" - -#include -#include -#include - -QT_BEGIN_NAMESPACE - -class QEglFSKmsScreen; - -class QEglFSKmsDevice -{ -public: - QEglFSKmsDevice(QEglFSKmsIntegration *integration, const QString &path); - - bool open(); - void close(); - - void createScreens(); - - gbm_device *device() const; - int fd() const; - - QPlatformCursor *globalCursor() const; - - void handleDrmEvent(); - -private: - Q_DISABLE_COPY(QEglFSKmsDevice) - - QEglFSKmsIntegration *m_integration; - QString m_path; - int m_dri_fd; - gbm_device *m_gbm_device; - - quint32 m_crtc_allocator; - quint32 m_connector_allocator; - - QEglFSKmsCursor *m_globalCursor; - - int crtcForConnector(drmModeResPtr resources, drmModeConnectorPtr connector); - QEglFSKmsScreen *screenForConnector(drmModeResPtr resources, drmModeConnectorPtr connector, QPoint pos); - drmModePropertyPtr connectorProperty(drmModeConnectorPtr connector, const QByteArray &name); - - static void pageFlipHandler(int fd, - unsigned int sequence, - unsigned int tv_sec, - unsigned int tv_usec, - void *user_data); -}; - -QT_END_NAMESPACE - -#endif diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmcursor.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmcursor.cpp new file mode 100644 index 0000000000..8536e2c239 --- /dev/null +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmcursor.cpp @@ -0,0 +1,240 @@ +/**************************************************************************** +** +** Copyright (C) 2015 Pier Luigi Fiorini +** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2016 Pelagicore AG +** 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 "qeglfskmsgbmcursor.h" +#include "qeglfskmsgbmscreen.h" +#include "qeglfskmsgbmdevice.h" + +#include +#include +#include +#include +#include + +#include +#include + +#ifndef DRM_CAP_CURSOR_WIDTH +#define DRM_CAP_CURSOR_WIDTH 0x8 +#endif + +#ifndef DRM_CAP_CURSOR_HEIGHT +#define DRM_CAP_CURSOR_HEIGHT 0x9 +#endif + +QT_BEGIN_NAMESPACE + +Q_DECLARE_LOGGING_CATEGORY(qLcEglfsKmsDebug) + +QEglFSKmsGbmCursor::QEglFSKmsGbmCursor(QEglFSKmsGbmScreen *screen) + : m_screen(screen) + , m_cursorSize(64, 64) // 64x64 is the old standard size, we now try to query the real size below + , m_bo(Q_NULLPTR) + , m_cursorImage(0, 0, 0, 0, 0, 0) + , m_visible(true) +{ + QByteArray hideCursorVal = qgetenv("QT_QPA_EGLFS_HIDECURSOR"); + if (!hideCursorVal.isEmpty()) + m_visible = hideCursorVal.toInt() == 0; + if (!m_visible) + return; + + uint64_t width, height; + if ((drmGetCap(m_screen->device()->fd(), DRM_CAP_CURSOR_WIDTH, &width) == 0) + && (drmGetCap(m_screen->device()->fd(), DRM_CAP_CURSOR_HEIGHT, &height) == 0)) { + m_cursorSize.setWidth(width); + m_cursorSize.setHeight(height); + } + + m_bo = gbm_bo_create(static_cast(m_screen->device())->gbmDevice(), m_cursorSize.width(), m_cursorSize.height(), + GBM_FORMAT_ARGB8888, GBM_BO_USE_CURSOR_64X64 | GBM_BO_USE_WRITE); + if (!m_bo) { + qWarning("Could not create buffer for cursor!"); + } else { + initCursorAtlas(); + } + +#ifndef QT_NO_CURSOR + QCursor cursor(Qt::ArrowCursor); + changeCursor(&cursor, 0); +#endif + setPos(QPoint(0, 0)); +} + +QEglFSKmsGbmCursor::~QEglFSKmsGbmCursor() +{ + Q_FOREACH (QPlatformScreen *screen, m_screen->virtualSiblings()) { + QEglFSKmsScreen *kmsScreen = static_cast(screen); + drmModeSetCursor(kmsScreen->device()->fd(), kmsScreen->output().crtc_id, 0, 0, 0); + drmModeMoveCursor(kmsScreen->device()->fd(), kmsScreen->output().crtc_id, 0, 0); + } + + gbm_bo_destroy(m_bo); + m_bo = Q_NULLPTR; +} + +void QEglFSKmsGbmCursor::pointerEvent(const QMouseEvent &event) +{ + setPos(event.screenPos().toPoint()); +} + +#ifndef QT_NO_CURSOR +void QEglFSKmsGbmCursor::changeCursor(QCursor *windowCursor, QWindow *window) +{ + Q_UNUSED(window); + + if (!m_visible) + return; + + const Qt::CursorShape newShape = windowCursor ? windowCursor->shape() : Qt::ArrowCursor; + if (newShape == Qt::BitmapCursor) { + m_cursorImage.set(windowCursor->pixmap().toImage(), + windowCursor->hotSpot().x(), + windowCursor->hotSpot().y()); + } else { + // Standard cursor, look up in atlas + const int width = m_cursorAtlas.cursorWidth; + const int height = m_cursorAtlas.cursorHeight; + const qreal ws = (qreal)m_cursorAtlas.cursorWidth / m_cursorAtlas.width; + const qreal hs = (qreal)m_cursorAtlas.cursorHeight / m_cursorAtlas.height; + + QRect textureRect(ws * (newShape % m_cursorAtlas.cursorsPerRow) * m_cursorAtlas.width, + hs * (newShape / m_cursorAtlas.cursorsPerRow) * m_cursorAtlas.height, + width, + height); + QPoint hotSpot = m_cursorAtlas.hotSpots[newShape]; + m_cursorImage.set(m_cursorAtlas.image.copy(textureRect), + hotSpot.x(), + hotSpot.y()); + } + + if (m_cursorImage.image()->width() > m_cursorSize.width() || m_cursorImage.image()->height() > m_cursorSize.height()) + qWarning("Cursor larger than %dx%d, cursor will be clipped.", m_cursorSize.width(), m_cursorSize.height()); + + QImage cursorImage(m_cursorSize, QImage::Format_ARGB32); + cursorImage.fill(Qt::transparent); + + QPainter painter; + painter.begin(&cursorImage); + painter.drawImage(0, 0, *m_cursorImage.image()); + painter.end(); + + gbm_bo_write(m_bo, cursorImage.constBits(), cursorImage.byteCount()); + + uint32_t handle = gbm_bo_get_handle(m_bo).u32; + + Q_FOREACH (QPlatformScreen *screen, m_screen->virtualSiblings()) { + QEglFSKmsScreen *kmsScreen = static_cast(screen); + + int status = drmModeSetCursor(kmsScreen->device()->fd(), kmsScreen->output().crtc_id, handle, + m_cursorSize.width(), m_cursorSize.height()); + if (status != 0) + qWarning("Could not set cursor on screen %s: %d", kmsScreen->name().toLatin1().constData(), status); + } +} +#endif // QT_NO_CURSOR + +QPoint QEglFSKmsGbmCursor::pos() const +{ + return m_pos; +} + +void QEglFSKmsGbmCursor::setPos(const QPoint &pos) +{ + Q_FOREACH (QPlatformScreen *screen, m_screen->virtualSiblings()) { + QEglFSKmsScreen *kmsScreen = static_cast(screen); + QPoint origin = kmsScreen->geometry().topLeft(); + QPoint localPos = pos - origin; + QPoint adjustedPos = localPos - m_cursorImage.hotspot(); + + int ret = drmModeMoveCursor(kmsScreen->device()->fd(), kmsScreen->output().crtc_id, adjustedPos.x(), adjustedPos.y()); + if (ret == 0) + m_pos = pos; + else + qWarning("Failed to move cursor on screen %s: %d", kmsScreen->name().toLatin1().constData(), ret); + } +} + +void QEglFSKmsGbmCursor::initCursorAtlas() +{ + static QByteArray json = qgetenv("QT_QPA_EGLFS_CURSOR"); + if (json.isEmpty()) + json = ":/cursor.json"; + + qCDebug(qLcEglfsKmsDebug) << "Initializing cursor atlas from" << json; + + QFile file(QString::fromUtf8(json)); + if (!file.open(QFile::ReadOnly)) { + Q_FOREACH (QPlatformScreen *screen, m_screen->virtualSiblings()) { + QEglFSKmsScreen *kmsScreen = static_cast(screen); + drmModeSetCursor(kmsScreen->device()->fd(), kmsScreen->output().crtc_id, 0, 0, 0); + drmModeMoveCursor(kmsScreen->device()->fd(), kmsScreen->output().crtc_id, 0, 0); + } + m_visible = false; + return; + } + + QJsonDocument doc = QJsonDocument::fromJson(file.readAll()); + QJsonObject object = doc.object(); + + QString atlas = object.value(QLatin1String("image")).toString(); + Q_ASSERT(!atlas.isEmpty()); + + const int cursorsPerRow = object.value(QLatin1String("cursorsPerRow")).toDouble(); + Q_ASSERT(cursorsPerRow); + m_cursorAtlas.cursorsPerRow = cursorsPerRow; + + const QJsonArray hotSpots = object.value(QLatin1String("hotSpots")).toArray(); + Q_ASSERT(hotSpots.count() == Qt::LastCursor + 1); + for (int i = 0; i < hotSpots.count(); i++) { + QPoint hotSpot(hotSpots[i].toArray()[0].toDouble(), hotSpots[i].toArray()[1].toDouble()); + m_cursorAtlas.hotSpots << hotSpot; + } + + QImage image = QImage(atlas).convertToFormat(QImage::Format_ARGB32); + m_cursorAtlas.cursorWidth = image.width() / m_cursorAtlas.cursorsPerRow; + m_cursorAtlas.cursorHeight = image.height() / ((Qt::LastCursor + cursorsPerRow) / cursorsPerRow); + m_cursorAtlas.width = image.width(); + m_cursorAtlas.height = image.height(); + m_cursorAtlas.image = image; +} + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmcursor.h b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmcursor.h new file mode 100644 index 0000000000..c1e3706e91 --- /dev/null +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmcursor.h @@ -0,0 +1,92 @@ +/**************************************************************************** +** +** 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 QEGLFSKMSGBMCURSOR_H +#define QEGLFSKMSGBMCURSOR_H + +#include +#include +#include + +#include + +QT_BEGIN_NAMESPACE + +class QEglFSKmsGbmScreen; + +class QEglFSKmsGbmCursor : public QPlatformCursor +{ + Q_OBJECT + +public: + QEglFSKmsGbmCursor(QEglFSKmsGbmScreen *screen); + ~QEglFSKmsGbmCursor(); + + // input methods + void pointerEvent(const QMouseEvent & event) Q_DECL_OVERRIDE; +#ifndef QT_NO_CURSOR + void changeCursor(QCursor * windowCursor, QWindow * window) Q_DECL_OVERRIDE; +#endif + QPoint pos() const Q_DECL_OVERRIDE; + void setPos(const QPoint &pos) Q_DECL_OVERRIDE; + +private: + void initCursorAtlas(); + + QEglFSKmsGbmScreen *m_screen; + QSize m_cursorSize; + gbm_bo *m_bo; + QPoint m_pos; + QPlatformCursorImage m_cursorImage; + bool m_visible; + + // cursor atlas information + struct CursorAtlas { + CursorAtlas() : cursorsPerRow(0), cursorWidth(0), cursorHeight(0) { } + int cursorsPerRow; + int width, height; // width and height of the atlas + int cursorWidth, cursorHeight; // width and height of cursors inside the atlas + QList hotSpots; + QImage image; + } m_cursorAtlas; +}; + +QT_END_NAMESPACE + +#endif // QEGLFSKMSGBMCURSOR_H diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmdevice.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmdevice.cpp new file mode 100644 index 0000000000..9bb489d6b4 --- /dev/null +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmdevice.cpp @@ -0,0 +1,158 @@ +/**************************************************************************** +** +** Copyright (C) 2015 Pier Luigi Fiorini +** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2016 Pelagicore AG +** 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 "qeglfskmsgbmdevice.h" +#include "qeglfskmsgbmscreen.h" + +#include "qeglfsintegration.h" + +#include +#include +#include + +#define ARRAY_LENGTH(a) (sizeof (a) / sizeof (a)[0]) + +QT_BEGIN_NAMESPACE + +Q_DECLARE_LOGGING_CATEGORY(qLcEglfsKmsDebug) + +void QEglFSKmsGbmDevice::pageFlipHandler(int fd, unsigned int sequence, unsigned int tv_sec, unsigned int tv_usec, void *user_data) +{ + Q_UNUSED(fd); + Q_UNUSED(sequence); + Q_UNUSED(tv_sec); + Q_UNUSED(tv_usec); + + QEglFSKmsScreen *screen = static_cast(user_data); + screen->flipFinished(); +} + +QEglFSKmsGbmDevice::QEglFSKmsGbmDevice(QEglFSKmsIntegration *integration, const QString &path) + : QEglFSKmsDevice(integration, path) + , m_gbm_device(Q_NULLPTR) + , m_globalCursor(Q_NULLPTR) +{ +} + +bool QEglFSKmsGbmDevice::open() +{ + Q_ASSERT(fd() == -1); + Q_ASSERT(m_gbm_device == Q_NULLPTR); + + qCDebug(qLcEglfsKmsDebug) << "Opening device" << devicePath(); + int fd = qt_safe_open(devicePath().toLocal8Bit().constData(), O_RDWR | O_CLOEXEC); + if (fd == -1) { + qErrnoWarning("Could not open DRM device %s", qPrintable(devicePath())); + return false; + } + + qCDebug(qLcEglfsKmsDebug) << "Creating GBM device for file descriptor" << fd + << "obtained from" << devicePath(); + m_gbm_device = gbm_create_device(fd); + if (!m_gbm_device) { + qErrnoWarning("Could not create GBM device"); + qt_safe_close(fd); + fd = -1; + return false; + } + + setFd(fd); + + return true; +} + +void QEglFSKmsGbmDevice::close() +{ + if (m_gbm_device) { + gbm_device_destroy(m_gbm_device); + m_gbm_device = Q_NULLPTR; + } + + if (fd() != -1) { + qt_safe_close(fd()); + setFd(-1); + } + + if (m_globalCursor) + m_globalCursor->deleteLater(); + m_globalCursor = Q_NULLPTR; +} + +EGLNativeDisplayType QEglFSKmsGbmDevice::device() const +{ + return 0; +} + +gbm_device * QEglFSKmsGbmDevice::gbmDevice() const +{ + return m_gbm_device; +} + +QPlatformCursor *QEglFSKmsGbmDevice::globalCursor() const +{ + return m_globalCursor; +} + +void QEglFSKmsGbmDevice::handleDrmEvent() +{ + drmEventContext drmEvent = { + DRM_EVENT_CONTEXT_VERSION, + Q_NULLPTR, // vblank handler + pageFlipHandler // page flip handler + }; + + drmHandleEvent(fd(), &drmEvent); +} + +QEglFSKmsScreen *QEglFSKmsGbmDevice::createScreen(QEglFSKmsIntegration *integration, QEglFSKmsDevice *device, QEglFSKmsOutput output, QPoint position) +{ + static bool firstScreen = true; + QEglFSKmsGbmScreen *screen = new QEglFSKmsGbmScreen(integration, device, output, position); + + if (firstScreen && integration->hwCursor()) { + m_globalCursor = new QEglFSKmsGbmCursor(screen); + firstScreen = false; + } + + return screen; +} + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmdevice.h b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmdevice.h new file mode 100644 index 0000000000..6203a6dc7f --- /dev/null +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmdevice.h @@ -0,0 +1,90 @@ +/**************************************************************************** +** +** Copyright (C) 2015 Pier Luigi Fiorini +** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2016 Pelagicore AG +** 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 QEGLFSKMSGBMDEVICE_H +#define QEGLFSKMSGBMDEVICE_H + +#include "qeglfskmsgbmcursor.h" +#include "qeglfskmsdevice.h" + +#include + +QT_BEGIN_NAMESPACE + +class QEglFSKmsScreen; + +class QEglFSKmsGbmDevice: public QEglFSKmsDevice +{ +public: + QEglFSKmsGbmDevice(QEglFSKmsIntegration *integration, const QString &path); + + bool open() Q_DECL_OVERRIDE; + void close() Q_DECL_OVERRIDE; + + EGLNativeDisplayType device() const Q_DECL_OVERRIDE; + gbm_device *gbmDevice() const; + + QPlatformCursor *globalCursor() const; + + void handleDrmEvent(); + + virtual QEglFSKmsScreen *createScreen(QEglFSKmsIntegration *integration, + QEglFSKmsDevice *device, + QEglFSKmsOutput output, + QPoint position) Q_DECL_OVERRIDE; + +private: + Q_DISABLE_COPY(QEglFSKmsGbmDevice) + + gbm_device *m_gbm_device; + + QEglFSKmsGbmCursor *m_globalCursor; + + static void pageFlipHandler(int fd, + unsigned int sequence, + unsigned int tv_sec, + unsigned int tv_usec, + void *user_data); +}; + +QT_END_NAMESPACE + +#endif // QEGLFSKMSGBMDEVICE_H diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmintegration.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmintegration.cpp new file mode 100644 index 0000000000..1c0a8e1b5f --- /dev/null +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmintegration.cpp @@ -0,0 +1,143 @@ +/**************************************************************************** +** +** Copyright (C) 2015 Pier Luigi Fiorini +** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2016 Pelagicore AG +** 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 "qeglfskmsgbmintegration.h" +#include "qeglfskmsgbmdevice.h" +#include "qeglfskmsgbmscreen.h" +#include "qeglfskmsgbmcursor.h" +#include "qeglfscursor.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +QT_BEGIN_NAMESPACE + +QMutex QEglFSKmsGbmScreen::m_waitForFlipMutex; + +QEglFSKmsGbmIntegration::QEglFSKmsGbmIntegration() + : QEglFSKmsIntegration() +{} + +EGLNativeWindowType QEglFSKmsGbmIntegration::createNativeWindow(QPlatformWindow *platformWindow, + const QSize &size, + const QSurfaceFormat &format) +{ + Q_UNUSED(size); + Q_UNUSED(format); + + QEglFSKmsGbmScreen *screen = static_cast(platformWindow->screen()); + if (screen->surface()) { + qWarning("Only single window per screen supported!"); + return 0; + } + + return reinterpret_cast(screen->createSurface()); +} + +EGLNativeWindowType QEglFSKmsGbmIntegration::createNativeOffscreenWindow(const QSurfaceFormat &format) +{ + Q_UNUSED(format); + Q_ASSERT(device()); + + qCDebug(qLcEglfsKmsDebug) << "Creating native off screen window"; + gbm_surface *surface = gbm_surface_create(static_cast(device())->gbmDevice(), + 1, 1, + GBM_FORMAT_XRGB8888, + GBM_BO_USE_RENDERING); + + return reinterpret_cast(surface); +} + +void QEglFSKmsGbmIntegration::destroyNativeWindow(EGLNativeWindowType window) +{ + gbm_surface *surface = reinterpret_cast(window); + gbm_surface_destroy(surface); +} + +QPlatformCursor *QEglFSKmsGbmIntegration::createCursor(QPlatformScreen *screen) const +{ + if (hwCursor()) + return Q_NULLPTR; + else + return new QEglFSCursor(screen); +} + +void QEglFSKmsGbmIntegration::presentBuffer(QPlatformSurface *surface) +{ + QWindow *window = static_cast(surface->surface()); + QEglFSKmsScreen *screen = static_cast(window->screen()->handle()); + + screen->flip(); +} + +QEglFSKmsDevice *QEglFSKmsGbmIntegration::createDevice(const QString &devicePath) +{ + QString path = devicePath; + if (!devicePath.isEmpty()) { + qCDebug(qLcEglfsKmsDebug) << "Using DRM device" << path << "specified in config file"; + } else { + + QDeviceDiscovery *d = QDeviceDiscovery::create(QDeviceDiscovery::Device_VideoMask); + QStringList devices = d->scanConnectedDevices(); + qCDebug(qLcEglfsKmsDebug) << "Found the following video devices:" << devices; + d->deleteLater(); + + if (Q_UNLIKELY(devices.isEmpty())) + qFatal("Could not find DRM device!"); + + path = devices.first(); + qCDebug(qLcEglfsKmsDebug) << "Using" << path; + } + + return new QEglFSKmsGbmDevice(this, path); +} + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmintegration.h b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmintegration.h new file mode 100644 index 0000000000..727571d3e3 --- /dev/null +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmintegration.h @@ -0,0 +1,75 @@ +/**************************************************************************** +** +** Copyright (C) 2015 Pier Luigi Fiorini +** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2016 Pelagicore AG +** 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 QEGLFSKMSGBMINTEGRATION_H +#define QEGLFSKMSGBMINTEGRATION_H + +#include "qeglfskmsintegration.h" +#include +#include + +QT_BEGIN_NAMESPACE + +class QEglFSKmsDevice; + +class QEglFSKmsGbmIntegration : public QEglFSKmsIntegration +{ +public: + QEglFSKmsGbmIntegration(); + + EGLNativeWindowType createNativeWindow(QPlatformWindow *platformWindow, + const QSize &size, + const QSurfaceFormat &format) Q_DECL_OVERRIDE; + EGLNativeWindowType createNativeOffscreenWindow(const QSurfaceFormat &format) Q_DECL_OVERRIDE; + void destroyNativeWindow(EGLNativeWindowType window) Q_DECL_OVERRIDE; + + QPlatformCursor *createCursor(QPlatformScreen *screen) const Q_DECL_OVERRIDE; + void presentBuffer(QPlatformSurface *surface) Q_DECL_OVERRIDE; + +protected: + QEglFSKmsDevice *createDevice(const QString &devicePath) Q_DECL_OVERRIDE; + +private: +}; + +QT_END_NAMESPACE + +#endif // QEGLFSKMSGBMINTEGRATION_H diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmmain.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmmain.cpp new file mode 100644 index 0000000000..8e8779ca10 --- /dev/null +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmmain.cpp @@ -0,0 +1,57 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2016 Pelagicore AG +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the qmake spec 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 "qeglfsdeviceintegration.h" +#include "qeglfskmsgbmintegration.h" + +QT_BEGIN_NAMESPACE + +class QEglFSKmsGbmIntegrationPlugin : public QEGLDeviceIntegrationPlugin +{ + Q_OBJECT + Q_PLUGIN_METADATA(IID QEGLDeviceIntegrationFactoryInterface_iid FILE "eglfs_kms.json") + +public: + QEGLDeviceIntegration *create() Q_DECL_OVERRIDE { return new QEglFSKmsGbmIntegration; } +}; + +QT_END_NAMESPACE + +#include "qeglfskmsgbmmain.moc" diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmscreen.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmscreen.cpp new file mode 100644 index 0000000000..7a17b60a5e --- /dev/null +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmscreen.cpp @@ -0,0 +1,223 @@ +/**************************************************************************** +** +** Copyright (C) 2015 Pier Luigi Fiorini +** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2016 Pelagicore AG +** 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 "qeglfskmsgbmscreen.h" +#include "qeglfskmsgbmdevice.h" +#include "qeglfskmsgbmcursor.h" +#include "qeglfsintegration.h" + +#include + +#include +#include + +QT_BEGIN_NAMESPACE + +Q_DECLARE_LOGGING_CATEGORY(qLcEglfsKmsDebug) + +void QEglFSKmsGbmScreen::bufferDestroyedHandler(gbm_bo *bo, void *data) +{ + FrameBuffer *fb = static_cast(data); + + if (fb->fb) { + gbm_device *device = gbm_bo_get_device(bo); + drmModeRmFB(gbm_device_get_fd(device), fb->fb); + } + + delete fb; +} + +QEglFSKmsGbmScreen::FrameBuffer *QEglFSKmsGbmScreen::framebufferForBufferObject(gbm_bo *bo) +{ + { + FrameBuffer *fb = static_cast(gbm_bo_get_user_data(bo)); + if (fb) + return fb; + } + + uint32_t width = gbm_bo_get_width(bo); + uint32_t height = gbm_bo_get_height(bo); + uint32_t stride = gbm_bo_get_stride(bo); + uint32_t handle = gbm_bo_get_handle(bo).u32; + + QScopedPointer fb(new FrameBuffer); + + int ret = drmModeAddFB(device()->fd(), width, height, 24, 32, + stride, handle, &fb->fb); + + if (ret) { + qWarning("Failed to create KMS FB!"); + return Q_NULLPTR; + } + + gbm_bo_set_user_data(bo, fb.data(), bufferDestroyedHandler); + return fb.take(); +} + +QEglFSKmsGbmScreen::QEglFSKmsGbmScreen(QEglFSKmsIntegration *integration, + QEglFSKmsDevice *device, + QEglFSKmsOutput output, + QPoint position) + : QEglFSKmsScreen(integration, device, output, position) + , m_gbm_surface(Q_NULLPTR) + , m_gbm_bo_current(Q_NULLPTR) + , m_gbm_bo_next(Q_NULLPTR) + , m_cursor(Q_NULLPTR) +{ +} + +QEglFSKmsGbmScreen::~QEglFSKmsGbmScreen() +{ +} + +QPlatformCursor *QEglFSKmsGbmScreen::cursor() const +{ + if (integration()->hwCursor()) { + if (!integration()->separateScreens()) + return static_cast(device())->globalCursor(); + + if (m_cursor.isNull()) { + QEglFSKmsGbmScreen *that = const_cast(this); + that->m_cursor.reset(new QEglFSKmsGbmCursor(that)); + } + + return m_cursor.data(); + } else { + return QEglFSScreen::cursor(); + } +} + +gbm_surface *QEglFSKmsGbmScreen::createSurface() +{ + if (!m_gbm_surface) { + qCDebug(qLcEglfsKmsDebug) << "Creating window for screen" << name(); + m_gbm_surface = gbm_surface_create(static_cast(device())->gbmDevice(), + geometry().width(), + geometry().height(), + GBM_FORMAT_XRGB8888, + GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING); + } + return m_gbm_surface; +} + +void QEglFSKmsGbmScreen::destroySurface() +{ + if (m_gbm_bo_current) { + gbm_bo_destroy(m_gbm_bo_current); + m_gbm_bo_current = Q_NULLPTR; + } + + if (m_gbm_bo_next) { + gbm_bo_destroy(m_gbm_bo_next); + m_gbm_bo_next = Q_NULLPTR; + } + + if (m_gbm_surface) { + gbm_surface_destroy(m_gbm_surface); + m_gbm_surface = Q_NULLPTR; + } +} + +void QEglFSKmsGbmScreen::waitForFlip() +{ + // Don't lock the mutex unless we actually need to + if (!m_gbm_bo_next) + return; + + QMutexLocker lock(&m_waitForFlipMutex); + while (m_gbm_bo_next) + static_cast(device())->handleDrmEvent(); +} + +void QEglFSKmsGbmScreen::flip() +{ + if (!m_gbm_surface) { + qWarning("Cannot sync before platform init!"); + return; + } + + m_gbm_bo_next = gbm_surface_lock_front_buffer(m_gbm_surface); + if (!m_gbm_bo_next) { + qWarning("Could not lock GBM surface front buffer!"); + return; + } + + FrameBuffer *fb = framebufferForBufferObject(m_gbm_bo_next); + + if (!output().mode_set) { + int ret = drmModeSetCrtc(device()->fd(), + output().crtc_id, + fb->fb, + 0, 0, + &output().connector_id, 1, + &output().modes[output().mode]); + + if (ret) { + qErrnoWarning("Could not set DRM mode!"); + } else { + output().mode_set = true; + setPowerState(PowerStateOn); + } + } + + int ret = drmModePageFlip(device()->fd(), + output().crtc_id, + fb->fb, + DRM_MODE_PAGE_FLIP_EVENT, + this); + if (ret) { + qErrnoWarning("Could not queue DRM page flip!"); + gbm_surface_release_buffer(m_gbm_surface, m_gbm_bo_next); + m_gbm_bo_next = Q_NULLPTR; + } +} + +void QEglFSKmsGbmScreen::flipFinished() +{ + if (m_gbm_bo_current) + gbm_surface_release_buffer(m_gbm_surface, + m_gbm_bo_current); + + m_gbm_bo_current = m_gbm_bo_next; + m_gbm_bo_next = Q_NULLPTR; +} + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmscreen.h b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmscreen.h new file mode 100644 index 0000000000..3381bbfdbb --- /dev/null +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmscreen.h @@ -0,0 +1,93 @@ +/**************************************************************************** +** +** Copyright (C) 2015 Pier Luigi Fiorini +** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2016 Pelagicore AG +** 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 QEGLFSKMSGBMSCREEN_H +#define QEGLFSKMSGBMSCREEN_H + +#include "qeglfskmsscreen.h" +#include + +#include + +QT_BEGIN_NAMESPACE + +class QEglFSKmsGbmCursor; + +class QEglFSKmsGbmScreen : public QEglFSKmsScreen +{ +public: + QEglFSKmsGbmScreen(QEglFSKmsIntegration *integration, + QEglFSKmsDevice *device, + QEglFSKmsOutput output, + QPoint position); + ~QEglFSKmsGbmScreen(); + + QPlatformCursor *cursor() const Q_DECL_OVERRIDE; + + gbm_surface *surface() const { return m_gbm_surface; } + gbm_surface *createSurface(); + void destroySurface(); + + void waitForFlip() Q_DECL_OVERRIDE; + void flip() Q_DECL_OVERRIDE; + void flipFinished() Q_DECL_OVERRIDE; + +private: + gbm_surface *m_gbm_surface; + + gbm_bo *m_gbm_bo_current; + gbm_bo *m_gbm_bo_next; + + QScopedPointer m_cursor; + + struct FrameBuffer { + FrameBuffer() : fb(0) {} + uint32_t fb; + }; + static void bufferDestroyedHandler(gbm_bo *bo, void *data); + FrameBuffer *framebufferForBufferObject(gbm_bo *bo); + + static QMutex m_waitForFlipMutex; +}; + +QT_END_NAMESPACE + +#endif // QEGLFSKMSGBMSCREEN_H diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsintegration.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsintegration.cpp deleted file mode 100644 index db503b6e7f..0000000000 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsintegration.cpp +++ /dev/null @@ -1,275 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2015 Pier Luigi Fiorini -** 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 "qeglfskmsintegration.h" -#include "qeglfskmsdevice.h" -#include "qeglfskmsscreen.h" -#include "qeglfskmscursor.h" -#include "qeglfscursor.h" - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -QT_BEGIN_NAMESPACE - -Q_LOGGING_CATEGORY(qLcEglfsKmsDebug, "qt.qpa.eglfs.kms") - -QMutex QEglFSKmsScreen::m_waitForFlipMutex; - -QEglFSKmsIntegration::QEglFSKmsIntegration() - : m_device(Q_NULLPTR) - , m_hwCursor(true) - , m_pbuffers(false) - , m_separateScreens(false) -{} - -void QEglFSKmsIntegration::platformInit() -{ - loadConfig(); - - if (!m_devicePath.isEmpty()) { - qCDebug(qLcEglfsKmsDebug) << "Using DRM device" << m_devicePath << "specified in config file"; - } else { - - QDeviceDiscovery *d = QDeviceDiscovery::create(QDeviceDiscovery::Device_VideoMask); - QStringList devices = d->scanConnectedDevices(); - qCDebug(qLcEglfsKmsDebug) << "Found the following video devices:" << devices; - d->deleteLater(); - - if (Q_UNLIKELY(devices.isEmpty())) - qFatal("Could not find DRM device!"); - - m_devicePath = devices.first(); - qCDebug(qLcEglfsKmsDebug) << "Using" << m_devicePath; - } - - m_device = new QEglFSKmsDevice(this, m_devicePath); - if (Q_UNLIKELY(!m_device->open())) - qFatal("Could not open device %s - aborting!", qPrintable(m_devicePath)); -} - -void QEglFSKmsIntegration::platformDestroy() -{ - m_device->close(); - delete m_device; - m_device = Q_NULLPTR; -} - -EGLNativeDisplayType QEglFSKmsIntegration::platformDisplay() const -{ - Q_ASSERT(m_device); - return reinterpret_cast(m_device->device()); -} - -bool QEglFSKmsIntegration::usesDefaultScreen() -{ - return false; -} - -void QEglFSKmsIntegration::screenInit() -{ - m_device->createScreens(); -} - -QSurfaceFormat QEglFSKmsIntegration::surfaceFormatFor(const QSurfaceFormat &inputFormat) const -{ - QSurfaceFormat format(inputFormat); - format.setRenderableType(QSurfaceFormat::OpenGLES); - format.setSwapBehavior(QSurfaceFormat::DoubleBuffer); - format.setRedBufferSize(8); - format.setGreenBufferSize(8); - format.setBlueBufferSize(8); - return format; -} - -EGLNativeWindowType QEglFSKmsIntegration::createNativeWindow(QPlatformWindow *platformWindow, - const QSize &size, - const QSurfaceFormat &format) -{ - Q_UNUSED(size); - Q_UNUSED(format); - - QEglFSKmsScreen *screen = static_cast(platformWindow->screen()); - if (screen->surface()) { - qWarning("Only single window per screen supported!"); - return 0; - } - - return reinterpret_cast(screen->createSurface()); -} - -EGLNativeWindowType QEglFSKmsIntegration::createNativeOffscreenWindow(const QSurfaceFormat &format) -{ - Q_UNUSED(format); - Q_ASSERT(m_device); - - qCDebug(qLcEglfsKmsDebug) << "Creating native off screen window"; - gbm_surface *surface = gbm_surface_create(m_device->device(), - 1, 1, - GBM_FORMAT_XRGB8888, - GBM_BO_USE_RENDERING); - - return reinterpret_cast(surface); -} - -void QEglFSKmsIntegration::destroyNativeWindow(EGLNativeWindowType window) -{ - gbm_surface *surface = reinterpret_cast(window); - gbm_surface_destroy(surface); -} - -bool QEglFSKmsIntegration::hasCapability(QPlatformIntegration::Capability cap) const -{ - switch (cap) { - case QPlatformIntegration::ThreadedPixmaps: - case QPlatformIntegration::OpenGL: - case QPlatformIntegration::ThreadedOpenGL: - return true; - default: - return false; - } -} - -QPlatformCursor *QEglFSKmsIntegration::createCursor(QPlatformScreen *screen) const -{ - if (m_hwCursor) - return Q_NULLPTR; - else - return new QEglFSCursor(screen); -} - -void QEglFSKmsIntegration::waitForVSync(QPlatformSurface *surface) const -{ - QWindow *window = static_cast(surface->surface()); - QEglFSKmsScreen *screen = static_cast(window->screen()->handle()); - - screen->waitForFlip(); -} - -void QEglFSKmsIntegration::presentBuffer(QPlatformSurface *surface) -{ - QWindow *window = static_cast(surface->surface()); - QEglFSKmsScreen *screen = static_cast(window->screen()->handle()); - - screen->flip(); -} - -bool QEglFSKmsIntegration::supportsPBuffers() const -{ - return m_pbuffers; -} - -bool QEglFSKmsIntegration::hwCursor() const -{ - return m_hwCursor; -} - -bool QEglFSKmsIntegration::separateScreens() const -{ - return m_separateScreens; -} - -QMap QEglFSKmsIntegration::outputSettings() const -{ - return m_outputSettings; -} - -void QEglFSKmsIntegration::loadConfig() -{ - static QByteArray json = qgetenv("QT_QPA_EGLFS_KMS_CONFIG"); - if (json.isEmpty()) - return; - - qCDebug(qLcEglfsKmsDebug) << "Loading KMS setup from" << json; - - QFile file(QString::fromUtf8(json)); - if (!file.open(QFile::ReadOnly)) { - qCDebug(qLcEglfsKmsDebug) << "Could not open config file" - << json << "for reading"; - return; - } - - const QJsonDocument doc = QJsonDocument::fromJson(file.readAll()); - if (!doc.isObject()) { - qCDebug(qLcEglfsKmsDebug) << "Invalid config file" << json - << "- no top-level JSON object"; - return; - } - - const QJsonObject object = doc.object(); - - m_hwCursor = object.value(QStringLiteral("hwcursor")).toBool(m_hwCursor); - m_pbuffers = object.value(QStringLiteral("pbuffers")).toBool(m_pbuffers); - m_devicePath = object.value(QStringLiteral("device")).toString(); - m_separateScreens = object.value(QStringLiteral("separateScreens")).toBool(m_separateScreens); - - const QJsonArray outputs = object.value(QStringLiteral("outputs")).toArray(); - for (int i = 0; i < outputs.size(); i++) { - const QVariantMap outputSettings = outputs.at(i).toObject().toVariantMap(); - - if (outputSettings.contains(QStringLiteral("name"))) { - const QString name = outputSettings.value(QStringLiteral("name")).toString(); - - if (m_outputSettings.contains(name)) { - qCDebug(qLcEglfsKmsDebug) << "Output" << name << "configured multiple times!"; - } - - m_outputSettings.insert(name, outputSettings); - } - } - - qCDebug(qLcEglfsKmsDebug) << "Configuration:\n" - << "\thwcursor:" << m_hwCursor << "\n" - << "\tpbuffers:" << m_pbuffers << "\n" - << "\tseparateScreens:" << m_separateScreens << "\n" - << "\toutputs:" << m_outputSettings; -} - -QT_END_NAMESPACE diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsintegration.h b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsintegration.h deleted file mode 100644 index ed0cb6a096..0000000000 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsintegration.h +++ /dev/null @@ -1,91 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2015 Pier Luigi Fiorini -** 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 QEGLFSKMSINTEGRATION_H -#define QEGLFSKMSINTEGRATION_H - -#include "qeglfsdeviceintegration.h" -#include -#include - -QT_BEGIN_NAMESPACE - -class QEglFSKmsDevice; - -class QEglFSKmsIntegration : public QEGLDeviceIntegration -{ -public: - QEglFSKmsIntegration(); - - void platformInit() Q_DECL_OVERRIDE; - void platformDestroy() Q_DECL_OVERRIDE; - EGLNativeDisplayType platformDisplay() const Q_DECL_OVERRIDE; - bool usesDefaultScreen() Q_DECL_OVERRIDE; - void screenInit() Q_DECL_OVERRIDE; - QSurfaceFormat surfaceFormatFor(const QSurfaceFormat &inputFormat) const Q_DECL_OVERRIDE; - EGLNativeWindowType createNativeWindow(QPlatformWindow *platformWindow, - const QSize &size, - const QSurfaceFormat &format) Q_DECL_OVERRIDE; - EGLNativeWindowType createNativeOffscreenWindow(const QSurfaceFormat &format) Q_DECL_OVERRIDE; - void destroyNativeWindow(EGLNativeWindowType window) Q_DECL_OVERRIDE; - bool hasCapability(QPlatformIntegration::Capability cap) const Q_DECL_OVERRIDE; - QPlatformCursor *createCursor(QPlatformScreen *screen) const Q_DECL_OVERRIDE; - void waitForVSync(QPlatformSurface *surface) const Q_DECL_OVERRIDE; - void presentBuffer(QPlatformSurface *surface) Q_DECL_OVERRIDE; - bool supportsPBuffers() const Q_DECL_OVERRIDE; - - bool hwCursor() const; - bool separateScreens() const; - QMap outputSettings() const; - -private: - void loadConfig(); - - QEglFSKmsDevice *m_device; - bool m_hwCursor; - bool m_pbuffers; - bool m_separateScreens; - QString m_devicePath; - QMap m_outputSettings; -}; - -QT_END_NAMESPACE - -#endif diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsmain.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsmain.cpp deleted file mode 100644 index a39e2e5434..0000000000 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsmain.cpp +++ /dev/null @@ -1,56 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the qmake spec 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 "qeglfsdeviceintegration.h" -#include "qeglfskmsintegration.h" - -QT_BEGIN_NAMESPACE - -class QEglFSKmsIntegrationPlugin : public QEGLDeviceIntegrationPlugin -{ - Q_OBJECT - Q_PLUGIN_METADATA(IID QEGLDeviceIntegrationFactoryInterface_iid FILE "eglfs_kms.json") - -public: - QEGLDeviceIntegration *create() Q_DECL_OVERRIDE { return new QEglFSKmsIntegration; } -}; - -QT_END_NAMESPACE - -#include "qeglfskmsmain.moc" diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsscreen.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsscreen.cpp deleted file mode 100644 index f53c3e9132..0000000000 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsscreen.cpp +++ /dev/null @@ -1,359 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2015 Pier Luigi Fiorini -** 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 "qeglfskmsscreen.h" -#include "qeglfskmsdevice.h" -#include "qeglfskmscursor.h" -#include "qeglfsintegration.h" - -#include - -#include -#include - -QT_BEGIN_NAMESPACE - -Q_DECLARE_LOGGING_CATEGORY(qLcEglfsKmsDebug) - -class QEglFSKmsInterruptHandler : public QObject -{ -public: - QEglFSKmsInterruptHandler(QEglFSKmsScreen *screen) : m_screen(screen) { - m_vtHandler = static_cast(QGuiApplicationPrivate::platformIntegration())->vtHandler(); - connect(m_vtHandler, &QFbVtHandler::interrupted, this, &QEglFSKmsInterruptHandler::restoreVideoMode); - connect(m_vtHandler, &QFbVtHandler::aboutToSuspend, this, &QEglFSKmsInterruptHandler::restoreVideoMode); - } - -public slots: - void restoreVideoMode() { m_screen->restoreMode(); } - -private: - QFbVtHandler *m_vtHandler; - QEglFSKmsScreen *m_screen; -}; - -void QEglFSKmsScreen::bufferDestroyedHandler(gbm_bo *bo, void *data) -{ - FrameBuffer *fb = static_cast(data); - - if (fb->fb) { - gbm_device *device = gbm_bo_get_device(bo); - drmModeRmFB(gbm_device_get_fd(device), fb->fb); - } - - delete fb; -} - -QEglFSKmsScreen::FrameBuffer *QEglFSKmsScreen::framebufferForBufferObject(gbm_bo *bo) -{ - { - FrameBuffer *fb = static_cast(gbm_bo_get_user_data(bo)); - if (fb) - return fb; - } - - uint32_t width = gbm_bo_get_width(bo); - uint32_t height = gbm_bo_get_height(bo); - uint32_t stride = gbm_bo_get_stride(bo); - uint32_t handle = gbm_bo_get_handle(bo).u32; - - QScopedPointer fb(new FrameBuffer); - - int ret = drmModeAddFB(m_device->fd(), width, height, 24, 32, - stride, handle, &fb->fb); - - if (ret) { - qWarning("Failed to create KMS FB!"); - return Q_NULLPTR; - } - - gbm_bo_set_user_data(bo, fb.data(), bufferDestroyedHandler); - return fb.take(); -} - -QEglFSKmsScreen::QEglFSKmsScreen(QEglFSKmsIntegration *integration, - QEglFSKmsDevice *device, - QEglFSKmsOutput output, - QPoint position) - : QEglFSScreen(eglGetDisplay(reinterpret_cast(device->device()))) - , m_integration(integration) - , m_device(device) - , m_gbm_surface(Q_NULLPTR) - , m_gbm_bo_current(Q_NULLPTR) - , m_gbm_bo_next(Q_NULLPTR) - , m_output(output) - , m_pos(position) - , m_cursor(Q_NULLPTR) - , m_powerState(PowerStateOn) - , m_interruptHandler(new QEglFSKmsInterruptHandler(this)) -{ - m_siblings << this; -} - -QEglFSKmsScreen::~QEglFSKmsScreen() -{ - if (m_output.dpms_prop) { - drmModeFreeProperty(m_output.dpms_prop); - m_output.dpms_prop = Q_NULLPTR; - } - restoreMode(); - if (m_output.saved_crtc) { - drmModeFreeCrtc(m_output.saved_crtc); - m_output.saved_crtc = Q_NULLPTR; - } - delete m_interruptHandler; -} - -QRect QEglFSKmsScreen::geometry() const -{ - const int mode = m_output.mode; - return QRect(m_pos.x(), m_pos.y(), - m_output.modes[mode].hdisplay, - m_output.modes[mode].vdisplay); -} - -int QEglFSKmsScreen::depth() const -{ - return 32; -} - -QImage::Format QEglFSKmsScreen::format() const -{ - return QImage::Format_RGB32; -} - -QSizeF QEglFSKmsScreen::physicalSize() const -{ - return m_output.physical_size; -} - -QDpi QEglFSKmsScreen::logicalDpi() const -{ - const QSizeF ps = physicalSize(); - const QSize s = geometry().size(); - - if (!ps.isEmpty() && !s.isEmpty()) - return QDpi(25.4 * s.width() / ps.width(), - 25.4 * s.height() / ps.height()); - else - return QDpi(100, 100); -} - -Qt::ScreenOrientation QEglFSKmsScreen::nativeOrientation() const -{ - return Qt::PrimaryOrientation; -} - -Qt::ScreenOrientation QEglFSKmsScreen::orientation() const -{ - return Qt::PrimaryOrientation; -} - -QString QEglFSKmsScreen::name() const -{ - return m_output.name; -} - -QPlatformCursor *QEglFSKmsScreen::cursor() const -{ - if (m_integration->hwCursor()) { - if (!m_integration->separateScreens()) - return m_device->globalCursor(); - - if (m_cursor.isNull()) { - QEglFSKmsScreen *that = const_cast(this); - that->m_cursor.reset(new QEglFSKmsCursor(that)); - } - - return m_cursor.data(); - } else { - return QEglFSScreen::cursor(); - } -} - -gbm_surface *QEglFSKmsScreen::createSurface() -{ - if (!m_gbm_surface) { - qCDebug(qLcEglfsKmsDebug) << "Creating window for screen" << name(); - m_gbm_surface = gbm_surface_create(m_device->device(), - geometry().width(), - geometry().height(), - GBM_FORMAT_XRGB8888, - GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING); - } - return m_gbm_surface; -} - -void QEglFSKmsScreen::destroySurface() -{ - if (m_gbm_bo_current) { - gbm_bo_destroy(m_gbm_bo_current); - m_gbm_bo_current = Q_NULLPTR; - } - - if (m_gbm_bo_next) { - gbm_bo_destroy(m_gbm_bo_next); - m_gbm_bo_next = Q_NULLPTR; - } - - if (m_gbm_surface) { - gbm_surface_destroy(m_gbm_surface); - m_gbm_surface = Q_NULLPTR; - } -} - -void QEglFSKmsScreen::waitForFlip() -{ - // Don't lock the mutex unless we actually need to - if (!m_gbm_bo_next) - return; - - QMutexLocker lock(&m_waitForFlipMutex); - while (m_gbm_bo_next) - m_device->handleDrmEvent(); -} - -void QEglFSKmsScreen::flip() -{ - if (!m_gbm_surface) { - qWarning("Cannot sync before platform init!"); - return; - } - - m_gbm_bo_next = gbm_surface_lock_front_buffer(m_gbm_surface); - if (!m_gbm_bo_next) { - qWarning("Could not lock GBM surface front buffer!"); - return; - } - - FrameBuffer *fb = framebufferForBufferObject(m_gbm_bo_next); - - if (!m_output.mode_set) { - int ret = drmModeSetCrtc(m_device->fd(), - m_output.crtc_id, - fb->fb, - 0, 0, - &m_output.connector_id, 1, - &m_output.modes[m_output.mode]); - - if (ret) { - qErrnoWarning("Could not set DRM mode!"); - } else { - m_output.mode_set = true; - setPowerState(PowerStateOn); - } - } - - int ret = drmModePageFlip(m_device->fd(), - m_output.crtc_id, - fb->fb, - DRM_MODE_PAGE_FLIP_EVENT, - this); - if (ret) { - qErrnoWarning("Could not queue DRM page flip!"); - gbm_surface_release_buffer(m_gbm_surface, m_gbm_bo_next); - m_gbm_bo_next = Q_NULLPTR; - } -} - -void QEglFSKmsScreen::flipFinished() -{ - if (m_gbm_bo_current) - gbm_surface_release_buffer(m_gbm_surface, - m_gbm_bo_current); - - m_gbm_bo_current = m_gbm_bo_next; - m_gbm_bo_next = Q_NULLPTR; -} - -void QEglFSKmsScreen::restoreMode() -{ - if (m_output.mode_set && m_output.saved_crtc) { - drmModeSetCrtc(m_device->fd(), - m_output.saved_crtc->crtc_id, - m_output.saved_crtc->buffer_id, - 0, 0, - &m_output.connector_id, 1, - &m_output.saved_crtc->mode); - - m_output.mode_set = false; - } -} - -qreal QEglFSKmsScreen::refreshRate() const -{ - quint32 refresh = m_output.modes[m_output.mode].vrefresh; - return refresh > 0 ? refresh : 60; -} - -QPlatformScreen::SubpixelAntialiasingType QEglFSKmsScreen::subpixelAntialiasingTypeHint() const -{ - switch (m_output.subpixel) { - default: - case DRM_MODE_SUBPIXEL_UNKNOWN: - case DRM_MODE_SUBPIXEL_NONE: - return Subpixel_None; - case DRM_MODE_SUBPIXEL_HORIZONTAL_RGB: - return Subpixel_RGB; - case DRM_MODE_SUBPIXEL_HORIZONTAL_BGR: - return Subpixel_BGR; - case DRM_MODE_SUBPIXEL_VERTICAL_RGB: - return Subpixel_VRGB; - case DRM_MODE_SUBPIXEL_VERTICAL_BGR: - return Subpixel_VBGR; - } -} - -QPlatformScreen::PowerState QEglFSKmsScreen::powerState() const -{ - return m_powerState; -} - -void QEglFSKmsScreen::setPowerState(QPlatformScreen::PowerState state) -{ - if (!m_output.dpms_prop) - return; - - drmModeConnectorSetProperty(m_device->fd(), m_output.connector_id, - m_output.dpms_prop->prop_id, (int)state); - m_powerState = state; -} - -QT_END_NAMESPACE diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsscreen.h b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsscreen.h deleted file mode 100644 index 3f836be143..0000000000 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsscreen.h +++ /dev/null @@ -1,149 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2015 Pier Luigi Fiorini -** 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 QEGLFSKMSSCREEN_H -#define QEGLFSKMSSCREEN_H - -#include "qeglfskmsintegration.h" -#include "qeglfsscreen.h" -#include -#include - -#include -#include -#include - -QT_BEGIN_NAMESPACE - -class QEglFSKmsDevice; -class QEglFSKmsCursor; -class QEglFSKmsInterruptHandler; - -struct QEglFSKmsOutput -{ - QString name; - uint32_t connector_id; - uint32_t crtc_id; - QSizeF physical_size; - int mode; // index of selected mode in list below - bool mode_set; - drmModeCrtcPtr saved_crtc; - QList modes; - int subpixel; - drmModePropertyPtr dpms_prop; -}; - -class QEglFSKmsScreen : public QEglFSScreen -{ -public: - QEglFSKmsScreen(QEglFSKmsIntegration *integration, - QEglFSKmsDevice *device, - QEglFSKmsOutput output, - QPoint position); - ~QEglFSKmsScreen(); - - QRect geometry() const Q_DECL_OVERRIDE; - int depth() const Q_DECL_OVERRIDE; - QImage::Format format() const Q_DECL_OVERRIDE; - - QSizeF physicalSize() const Q_DECL_OVERRIDE; - QDpi logicalDpi() const Q_DECL_OVERRIDE; - Qt::ScreenOrientation nativeOrientation() const Q_DECL_OVERRIDE; - Qt::ScreenOrientation orientation() const Q_DECL_OVERRIDE; - - QString name() const Q_DECL_OVERRIDE; - - QPlatformCursor *cursor() const Q_DECL_OVERRIDE; - - qreal refreshRate() const Q_DECL_OVERRIDE; - - QList virtualSiblings() const Q_DECL_OVERRIDE { return m_siblings; } - void setVirtualSiblings(QList sl) { m_siblings = sl; } - - QEglFSKmsIntegration *integration() const { return m_integration; } - QEglFSKmsDevice *device() const { return m_device; } - - gbm_surface *surface() const { return m_gbm_surface; } - gbm_surface *createSurface(); - void destroySurface(); - - void waitForFlip(); - void flip(); - void flipFinished(); - - QEglFSKmsOutput &output() { return m_output; } - void restoreMode(); - - SubpixelAntialiasingType subpixelAntialiasingTypeHint() const Q_DECL_OVERRIDE; - - QPlatformScreen::PowerState powerState() const Q_DECL_OVERRIDE; - void setPowerState(QPlatformScreen::PowerState state) Q_DECL_OVERRIDE; - -private: - QEglFSKmsIntegration *m_integration; - QEglFSKmsDevice *m_device; - gbm_surface *m_gbm_surface; - - gbm_bo *m_gbm_bo_current; - gbm_bo *m_gbm_bo_next; - - QEglFSKmsOutput m_output; - QPoint m_pos; - QScopedPointer m_cursor; - - QList m_siblings; - - PowerState m_powerState; - - struct FrameBuffer { - FrameBuffer() : fb(0) {} - uint32_t fb; - }; - static void bufferDestroyedHandler(gbm_bo *bo, void *data); - FrameBuffer *framebufferForBufferObject(gbm_bo *bo); - - static QMutex m_waitForFlipMutex; - - QEglFSKmsInterruptHandler *m_interruptHandler; -}; - -QT_END_NAMESPACE - -#endif diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/eglfs_kms_egldevice.pro b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/eglfs_kms_egldevice.pro index 1932f861b9..3a380b7525 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/eglfs_kms_egldevice.pro +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/eglfs_kms_egldevice.pro @@ -1,23 +1,32 @@ TARGET = qeglfs-kms-egldevice-integration -QT += core-private gui-private platformsupport-private eglfs_device_lib-private +QT += core-private gui-private platformsupport-private eglfs_device_lib-private eglfs_kms_support-private -INCLUDEPATH += $$PWD/../.. +INCLUDEPATH += $$PWD/../.. $$PWD/../eglfs_kms_support DEFINES += MESA_EGL_NO_X11_HEADERS +CONFIG += link_pkgconfig +!contains(QT_CONFIG, no-pkg-config) { + PKGCONFIG += libdrm +} else { + LIBS += -ldrm +} + CONFIG += egl QMAKE_LFLAGS += $$QMAKE_LFLAGS_NOUNDEF SOURCES += $$PWD/qeglfskmsegldevicemain.cpp \ - $$PWD/qeglfskmsegldeviceintegration.cpp + $$PWD/qeglfskmsegldeviceintegration.cpp \ + qeglfskmsegldevice.cpp \ + qeglfskmsegldevicescreen.cpp -HEADERS += $$PWD/qeglfskmsegldeviceintegration.h +HEADERS += $$PWD/qeglfskmsegldeviceintegration.h \ + qeglfskmsegldevice.h \ + qeglfskmsegldevicescreen.h OTHER_FILES += $$PWD/eglfs_kms_egldevice.json -LIBS += -ldrm - PLUGIN_TYPE = egldeviceintegrations PLUGIN_CLASS_NAME = QEglFSKmsEglDeviceIntegrationPlugin load(qt_plugin) diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevice.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevice.cpp new file mode 100644 index 0000000000..e09f2fdb18 --- /dev/null +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevice.cpp @@ -0,0 +1,79 @@ +/**************************************************************************** +** +** Copyright (C) 2016 Pelagicore AG +** 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 "qeglfskmsegldevice.h" +#include "qeglfskmsegldevicescreen.h" + +#include + +QEglFSKmsEglDevice::QEglFSKmsEglDevice(QEglFSKmsIntegration *integration, const QString &path) + : QEglFSKmsDevice(integration, path) +{ +} + +bool QEglFSKmsEglDevice::open() +{ + Q_ASSERT(fd() == -1); + + int fd = drmOpen(devicePath().toLocal8Bit().constData(), Q_NULLPTR); + if (Q_UNLIKELY(fd < 0)) + qFatal("Could not open DRM device"); + + setFd(fd); + + return true; +} + +void QEglFSKmsEglDevice::close() +{ + if (qt_safe_close(fd()) == -1) + qErrnoWarning("Could not close DRM device"); + + setFd(-1); +} + +EGLNativeDisplayType QEglFSKmsEglDevice::device() const +{ + return 0; +} + +QEglFSKmsScreen *QEglFSKmsEglDevice::createScreen(QEglFSKmsIntegration *integration, QEglFSKmsDevice *device, QEglFSKmsOutput output, QPoint position) +{ + return new QEglFSKmsEglDeviceScreen(integration, device, output, position); +} diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevice.h b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevice.h new file mode 100644 index 0000000000..f85ec27fa2 --- /dev/null +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevice.h @@ -0,0 +1,61 @@ +/**************************************************************************** +** +** Copyright (C) 2016 Pelagicore AG +** 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 QEGLFSKMSEGLDEVICE_H +#define QEGLFSKMSEGLDEVICE_H + +#include + +class QEglFSKmsEglDevice: public QEglFSKmsDevice +{ +public: + QEglFSKmsEglDevice(QEglFSKmsIntegration *integration, const QString &path); + + virtual bool open() Q_DECL_OVERRIDE; + virtual void close() Q_DECL_OVERRIDE; + + virtual EGLNativeDisplayType device() const Q_DECL_OVERRIDE; + + virtual QEglFSKmsScreen *createScreen(QEglFSKmsIntegration *integration, + QEglFSKmsDevice *device, + QEglFSKmsOutput output, + QPoint position) Q_DECL_OVERRIDE; +}; + +#endif // QEGLFSKMSEGLDEVICE_H diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldeviceintegration.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldeviceintegration.cpp index 201d9d7443..838569d5c6 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldeviceintegration.cpp +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldeviceintegration.cpp @@ -1,6 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2016 Pelagicore AG ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the plugins of the Qt Toolkit. @@ -38,60 +39,26 @@ ****************************************************************************/ #include "qeglfskmsegldeviceintegration.h" +#include +#include "qeglfswindow.h" +#include "qeglfskmsegldevice.h" +#include "qeglfskmsscreen.h" #include #include QT_BEGIN_NAMESPACE -Q_LOGGING_CATEGORY(qLcEglfsKmsDebug, "qt.qpa.eglfs.kms") - QEglFSKmsEglDeviceIntegration::QEglFSKmsEglDeviceIntegration() - : m_dri_fd(-1) + : QEglFSKmsIntegration() , m_egl_device(EGL_NO_DEVICE_EXT) - , m_egl_display(EGL_NO_DISPLAY) - , m_drm_connector(Q_NULLPTR) - , m_drm_encoder(Q_NULLPTR) - , m_drm_crtc(0) , m_funcs(Q_NULLPTR) { qCDebug(qLcEglfsKmsDebug, "New DRM/KMS on EGLDevice integration created"); } -void QEglFSKmsEglDeviceIntegration::platformInit() -{ - if (Q_UNLIKELY(!query_egl_device())) - qFatal("Could not set up EGL device!"); - - const char *deviceName = m_funcs->query_device_string(m_egl_device, EGL_DRM_DEVICE_FILE_EXT); - if (Q_UNLIKELY(!deviceName)) - qFatal("Failed to query device name from EGLDevice"); - - qCDebug(qLcEglfsKmsDebug, "Opening %s", deviceName); - - m_dri_fd = drmOpen(deviceName, Q_NULLPTR); - if (Q_UNLIKELY(m_dri_fd < 0)) - qFatal("Could not open DRM device"); - - if (Q_UNLIKELY(!setup_kms())) - qFatal("Could not set up KMS on device %s!", m_device.constData()); - - qCDebug(qLcEglfsKmsDebug, "DRM/KMS initialized"); -} - -void QEglFSKmsEglDeviceIntegration::platformDestroy() -{ - if (qt_safe_close(m_dri_fd) == -1) - qErrnoWarning("Could not close DRM device"); - - m_dri_fd = -1; - - delete m_funcs; - m_funcs = Q_NULLPTR; -} - -EGLNativeDisplayType QEglFSKmsEglDeviceIntegration::platformDisplay() const +EGLint QEglFSKmsEglDeviceIntegration::surfaceType() const { - return static_cast(m_egl_device); + return EGL_STREAM_BIT_KHR; } EGLDisplay QEglFSKmsEglDeviceIntegration::createDisplay(EGLNativeDisplayType nativeDisplay) @@ -120,46 +87,17 @@ EGLDisplay QEglFSKmsEglDeviceIntegration::createDisplay(EGLNativeDisplayType nat return display; } -QSizeF QEglFSKmsEglDeviceIntegration::physicalScreenSize() const -{ - const int defaultPhysicalDpi = 100; - static const int width = qEnvironmentVariableIntValue("QT_QPA_EGLFS_PHYSICAL_WIDTH"); - static const int height = qEnvironmentVariableIntValue("QT_QPA_EGLFS_PHYSICAL_HEIGHT"); - QSizeF size(width, height); - if (size.isEmpty()) { - size = QSizeF(m_drm_connector->mmWidth, m_drm_connector->mmHeight); - if (size.isEmpty()) { - const float pixelsPerMm = Q_MM_PER_INCH / defaultPhysicalDpi; - size = QSizeF(screenSize().width() * pixelsPerMm, screenSize().height() * pixelsPerMm); - } - } - return size; -} - -QSize QEglFSKmsEglDeviceIntegration::screenSize() const -{ - return QSize(m_drm_mode.hdisplay, m_drm_mode.vdisplay); -} - -int QEglFSKmsEglDeviceIntegration::screenDepth() const -{ - return 32; -} - -QSurfaceFormat QEglFSKmsEglDeviceIntegration::surfaceFormatFor(const QSurfaceFormat &inputFormat) const +bool QEglFSKmsEglDeviceIntegration::supportsSurfacelessContexts() const { - QSurfaceFormat format(inputFormat); - format.setRenderableType(QSurfaceFormat::OpenGLES); - format.setSwapBehavior(QSurfaceFormat::DoubleBuffer); - format.setRedBufferSize(8); - format.setGreenBufferSize(8); - format.setBlueBufferSize(8); - return format; + // Returning false disables the usage of EGL_KHR_surfaceless_context even when the + // extension is available. This is just what we need since, at least with NVIDIA + // 352.00 making a null surface current with a context breaks. + return false; } -EGLint QEglFSKmsEglDeviceIntegration::surfaceType() const +bool QEglFSKmsEglDeviceIntegration::supportsPBuffers() const { - return EGL_STREAM_BIT_KHR; + return true; } class QEglJetsonTK1Window : public QEglFSWindow @@ -216,11 +154,15 @@ void QEglJetsonTK1Window::resetSurface() return; } + QEglFSKmsScreen *cur_screen = static_cast(screen()); + Q_ASSERT(cur_screen); + qCDebug(qLcEglfsKmsDebug, "Searching for id: %d", cur_screen->output().crtc_id); + for (int i = 0; i < actualCount; ++i) { EGLAttrib id; if (m_integration->m_funcs->query_output_layer_attrib(display, layers[i], EGL_DRM_CRTC_EXT, &id)) { qCDebug(qLcEglfsKmsDebug, " [%d] layer %p - crtc %d", i, layers[i], (int) id); - if (id == EGLAttrib(m_integration->m_drm_crtc)) + if (id == EGLAttrib(cur_screen->output().crtc_id)) layer = layers[i]; } else if (m_integration->m_funcs->query_output_layer_attrib(display, layers[i], EGL_DRM_PLANE_EXT, &id)) { // Not used yet, just for debugging. @@ -251,8 +193,8 @@ void QEglJetsonTK1Window::resetSurface() m_format = q_glFormatFromConfig(display, m_config); qCDebug(qLcEglfsKmsDebug) << "Stream producer format is" << m_format; - const int w = m_integration->screenSize().width(); - const int h = m_integration->screenSize().height(); + const int w = cur_screen->geometry().width(); + const int h = cur_screen->geometry().height(); qCDebug(qLcEglfsKmsDebug, "Creating stream producer surface of size %dx%d", w, h); const EGLint stream_producer_attribs[] = { @@ -280,131 +222,23 @@ QEglFSWindow *QEglFSKmsEglDeviceIntegration::createWindow(QWindow *window) const return eglWindow; } -bool QEglFSKmsEglDeviceIntegration::hasCapability(QPlatformIntegration::Capability cap) const -{ - switch (cap) { - case QPlatformIntegration::ThreadedPixmaps: - case QPlatformIntegration::OpenGL: - case QPlatformIntegration::ThreadedOpenGL: - case QPlatformIntegration::BufferQueueingOpenGL: - return true; - default: - return false; - } -} - -void QEglFSKmsEglDeviceIntegration::waitForVSync(QPlatformSurface *) const -{ - static bool mode_set = false; - - if (!mode_set) { - mode_set = true; - - drmModeCrtcPtr currentMode = drmModeGetCrtc(m_dri_fd, m_drm_crtc); - const bool alreadySet = currentMode - && currentMode->width == m_drm_mode.hdisplay - && currentMode->height == m_drm_mode.vdisplay; - if (currentMode) - drmModeFreeCrtc(currentMode); - if (alreadySet) { - // Maybe detecting the DPMS mode could help here, but there are no properties - // exposed on the connector apparently. So rely on an env var for now. - static bool alwaysDoSet = qEnvironmentVariableIntValue("QT_QPA_EGLFS_ALWAYS_SET_MODE"); - if (!alwaysDoSet) { - qCDebug(qLcEglfsKmsDebug, "Mode already set"); - return; - } - } - - qCDebug(qLcEglfsKmsDebug, "Setting mode"); - int ret = drmModeSetCrtc(m_dri_fd, m_drm_crtc, - -1, 0, 0, - &m_drm_connector->connector_id, 1, - const_cast(&m_drm_mode)); - if (Q_UNLIKELY(ret)) - qFatal("drmModeSetCrtc failed"); - } -} - -qreal QEglFSKmsEglDeviceIntegration::refreshRate() const -{ - quint32 refresh = m_drm_mode.vrefresh; - return refresh > 0 ? refresh : 60; -} - -bool QEglFSKmsEglDeviceIntegration::supportsSurfacelessContexts() const +bool QEglFSKmsEglDeviceIntegration::separateScreens() const { - // Returning false disables the usage of EGL_KHR_surfaceless_context even when the - // extension is available. This is just what we need since, at least with NVIDIA - // 352.00 making a null surface current with a context breaks. - return false; + return true; } -bool QEglFSKmsEglDeviceIntegration::setup_kms() +QEglFSKmsDevice *QEglFSKmsEglDeviceIntegration::createDevice(const QString &devicePath) { - drmModeRes *resources; - drmModeConnector *connector; - drmModeEncoder *encoder; - quint32 crtc = 0; - int i; - - resources = drmModeGetResources(m_dri_fd); - if (!resources) { - qWarning("drmModeGetResources failed"); - return false; - } - - for (i = 0; i < resources->count_connectors; i++) { - connector = drmModeGetConnector(m_dri_fd, resources->connectors[i]); - if (!connector) - continue; - - if (connector->connection == DRM_MODE_CONNECTED && connector->count_modes > 0) - break; + Q_UNUSED(devicePath) - drmModeFreeConnector(connector); - } - - if (i == resources->count_connectors) { - qWarning("No currently active connector found."); - return false; - } - - qCDebug(qLcEglfsKmsDebug, "Using connector with type %d", connector->connector_type); - - for (i = 0; i < resources->count_encoders; i++) { - encoder = drmModeGetEncoder(m_dri_fd, resources->encoders[i]); - if (!encoder) - continue; - - if (encoder->encoder_id == connector->encoder_id) - break; - - drmModeFreeEncoder(encoder); - } - - for (int j = 0; j < resources->count_crtcs; j++) { - if ((encoder->possible_crtcs & (1 << j))) { - crtc = resources->crtcs[j]; - break; - } - } - - if (Q_UNLIKELY(crtc == 0)) - qFatal("No suitable CRTC available"); - - m_drm_connector = connector; - m_drm_encoder = encoder; - m_drm_mode = connector->modes[0]; - m_drm_crtc = crtc; - - qCDebug(qLcEglfsKmsDebug).noquote() << "Using crtc" << m_drm_crtc - << "with mode" << m_drm_mode.hdisplay << "x" << m_drm_mode.vdisplay - << "@" << m_drm_mode.vrefresh; + if (Q_UNLIKELY(!query_egl_device())) + qFatal("Could not set up EGL device!"); - drmModeFreeResources(resources); + const char *deviceName = m_funcs->query_device_string(m_egl_device, EGL_DRM_DEVICE_FILE_EXT); + if (Q_UNLIKELY(!deviceName)) + qFatal("Failed to query device name from EGLDevice"); - return true; + return new QEglFSKmsEglDevice(this, deviceName); } bool QEglFSKmsEglDeviceIntegration::query_egl_device() diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldeviceintegration.h b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldeviceintegration.h index 3d8f48d63c..43c1945a7f 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldeviceintegration.h +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldeviceintegration.h @@ -1,6 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2016 Pelagicore AG ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the plugins of the Qt Toolkit. @@ -40,17 +41,7 @@ #ifndef QEGLFSKMSEGLDEVICEINTEGRATION_H #define QEGLFSKMSEGLDEVICEINTEGRATION_H -#include "qeglfsdeviceintegration.h" -#include "qeglfswindow.h" -#include "qeglfsintegration.h" - -#include -#include -#include -#include -#include -#include -#include +#include #include #include @@ -59,41 +50,28 @@ QT_BEGIN_NAMESPACE -class QEglFSKmsEglDeviceIntegration : public QEGLDeviceIntegration +class QEglFSKmsEglDeviceIntegration : public QEglFSKmsIntegration { public: QEglFSKmsEglDeviceIntegration(); - void platformInit() Q_DECL_OVERRIDE; - void platformDestroy() Q_DECL_OVERRIDE; - EGLNativeDisplayType platformDisplay() const Q_DECL_OVERRIDE; - EGLDisplay createDisplay(EGLNativeDisplayType nativeDisplay) Q_DECL_OVERRIDE; - QSizeF physicalScreenSize() const Q_DECL_OVERRIDE; - QSize screenSize() const Q_DECL_OVERRIDE; - int screenDepth() const Q_DECL_OVERRIDE; - qreal refreshRate() const Q_DECL_OVERRIDE; - QSurfaceFormat surfaceFormatFor(const QSurfaceFormat &inputFormat) const Q_DECL_OVERRIDE; EGLint surfaceType() const Q_DECL_OVERRIDE; - QEglFSWindow *createWindow(QWindow *window) const Q_DECL_OVERRIDE; - bool hasCapability(QPlatformIntegration::Capability cap) const Q_DECL_OVERRIDE; - void waitForVSync(QPlatformSurface *surface) const Q_DECL_OVERRIDE; + EGLDisplay createDisplay(EGLNativeDisplayType nativeDisplay) Q_DECL_OVERRIDE; bool supportsSurfacelessContexts() const Q_DECL_OVERRIDE; + bool supportsPBuffers() const Q_DECL_OVERRIDE; + QEglFSWindow *createWindow(QWindow *window) const Q_DECL_OVERRIDE; + + virtual bool separateScreens() const Q_DECL_OVERRIDE; +protected: + QEglFSKmsDevice *createDevice(const QString &devicePath) Q_DECL_OVERRIDE; +private: bool setup_kms(); bool query_egl_device(); - // device bits - QByteArray m_device; - int m_dri_fd; EGLDeviceEXT m_egl_device; - EGLDisplay m_egl_display; - - // KMS bits - drmModeConnector *m_drm_connector; - drmModeEncoder *m_drm_encoder; - drmModeModeInfo m_drm_mode; - quint32 m_drm_crtc; + friend class QEglJetsonTK1Window; // EGLStream infrastructure QEGLStreamConvenience *m_funcs; }; diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevicescreen.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevicescreen.cpp new file mode 100644 index 0000000000..da1b577801 --- /dev/null +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevicescreen.cpp @@ -0,0 +1,78 @@ +/**************************************************************************** +** +** Copyright (C) 2016 Pelagicore AG +** 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 "qeglfskmsegldevicescreen.h" +#include "qeglfskmsegldevice.h" + +QEglFSKmsEglDeviceScreen::QEglFSKmsEglDeviceScreen(QEglFSKmsIntegration *integration, QEglFSKmsDevice *device, QEglFSKmsOutput output, QPoint position) + : QEglFSKmsScreen(integration, device, output, position) +{ +} + +void QEglFSKmsEglDeviceScreen::waitForFlip() +{ + if (!output().mode_set) { + output().mode_set = true; + + drmModeCrtcPtr currentMode = drmModeGetCrtc(device()->fd(), output().crtc_id); + const bool alreadySet = currentMode + && currentMode->width == output().modes[output().mode].hdisplay + && currentMode->height == output().modes[output().mode].vdisplay; + if (currentMode) + drmModeFreeCrtc(currentMode); + if (alreadySet) { + // Maybe detecting the DPMS mode could help here, but there are no properties + // exposed on the connector apparently. So rely on an env var for now. + static bool alwaysDoSet = qEnvironmentVariableIntValue("QT_QPA_EGLFS_ALWAYS_SET_MODE"); + if (!alwaysDoSet) { + qCDebug(qLcEglfsKmsDebug, "Mode already set"); + return; + } + } + + qCDebug(qLcEglfsKmsDebug, "Setting mode"); + int ret = drmModeSetCrtc(device()->fd(), output().crtc_id, + -1, 0, 0, + &output().connector_id, 1, + &output().modes[output().mode]); + if (ret) + qFatal("drmModeSetCrtc failed"); + } + +} diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevicescreen.h b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevicescreen.h new file mode 100644 index 0000000000..0cd46e9f9d --- /dev/null +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevicescreen.h @@ -0,0 +1,56 @@ +/**************************************************************************** +** +** Copyright (C) 2016 Pelagicore AG +** 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 QEGLFSKMSEGLDEVICESCREEN_H +#define QEGLFSKMSEGLDEVICESCREEN_H + +#include + +class QEglFSKmsEglDeviceScreen : public QEglFSKmsScreen +{ +public: + QEglFSKmsEglDeviceScreen(QEglFSKmsIntegration *integration, + QEglFSKmsDevice *device, + QEglFSKmsOutput output, + QPoint position); + + void waitForFlip() Q_DECL_OVERRIDE; +}; + +#endif // QEGLFSKMSEGLDEVICESCREEN_H diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/eglfs_kms_support.pro b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/eglfs_kms_support.pro new file mode 100644 index 0000000000..6355fe6abd --- /dev/null +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/eglfs_kms_support.pro @@ -0,0 +1,28 @@ +TARGET = QtEglFsKmsSupport +CONFIG += no_module_headers internal_module +load(qt_module) + +QT += core-private gui-private platformsupport-private eglfs_device_lib-private + +INCLUDEPATH += $$PWD/../.. + +# Avoid X11 header collision +DEFINES += MESA_EGL_NO_X11_HEADERS + +CONFIG += link_pkgconfig +!contains(QT_CONFIG, no-pkg-config) { + PKGCONFIG += libdrm +} else { + LIBS += -ldrm +} + +CONFIG += egl +QMAKE_LFLAGS += $$QMAKE_LFLAGS_NOUNDEF + +SOURCES += $$PWD/qeglfskmsintegration.cpp \ + $$PWD/qeglfskmsdevice.cpp \ + $$PWD/qeglfskmsscreen.cpp \ + +HEADERS += $$PWD/qeglfskmsintegration.h \ + $$PWD/qeglfskmsdevice.h \ + $$PWD/qeglfskmsscreen.h \ diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsdevice.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsdevice.cpp new file mode 100644 index 0000000000..f4ffee569d --- /dev/null +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsdevice.cpp @@ -0,0 +1,404 @@ +/**************************************************************************** +** +** Copyright (C) 2015 Pier Luigi Fiorini +** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2016 Pelagicore AG +** 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 "qeglfskmsdevice.h" +#include "qeglfskmsscreen.h" + +#include "qeglfsintegration.h" + +#include +#include +#include + +#define ARRAY_LENGTH(a) (sizeof (a) / sizeof (a)[0]) + +QT_BEGIN_NAMESPACE + +Q_DECLARE_LOGGING_CATEGORY(qLcEglfsKmsDebug) + +enum OutputConfiguration { + OutputConfigOff, + OutputConfigPreferred, + OutputConfigCurrent, + OutputConfigMode, + OutputConfigModeline +}; + +int QEglFSKmsDevice::crtcForConnector(drmModeResPtr resources, drmModeConnectorPtr connector) +{ + for (int i = 0; i < connector->count_encoders; i++) { + drmModeEncoderPtr encoder = drmModeGetEncoder(m_dri_fd, connector->encoders[i]); + if (!encoder) { + qWarning("Failed to get encoder"); + continue; + } + + quint32 possibleCrtcs = encoder->possible_crtcs; + drmModeFreeEncoder(encoder); + + for (int j = 0; j < resources->count_crtcs; j++) { + bool isPossible = possibleCrtcs & (1 << j); + bool isAvailable = !(m_crtc_allocator & 1 << resources->crtcs[j]); + + if (isPossible && isAvailable) + return j; + } + } + + return -1; +} + +static const char * const connector_type_names[] = { + "None", + "VGA", + "DVI", + "DVI", + "DVI", + "Composite", + "TV", + "LVDS", + "CTV", + "DIN", + "DP", + "HDMI", + "HDMI", + "TV", + "eDP", +}; + +static QByteArray nameForConnector(const drmModeConnectorPtr connector) +{ + QByteArray connectorName("UNKNOWN"); + + if (connector->connector_type < ARRAY_LENGTH(connector_type_names)) + connectorName = connector_type_names[connector->connector_type]; + + connectorName += QByteArray::number(connector->connector_type_id); + + return connectorName; +} + +static bool parseModeline(const QByteArray &text, drmModeModeInfoPtr mode) +{ + char hsync[16]; + char vsync[16]; + float fclock; + + mode->type = DRM_MODE_TYPE_USERDEF; + mode->hskew = 0; + mode->vscan = 0; + mode->vrefresh = 0; + mode->flags = 0; + + if (sscanf(text.constData(), "%f %hd %hd %hd %hd %hd %hd %hd %hd %15s %15s", + &fclock, + &mode->hdisplay, + &mode->hsync_start, + &mode->hsync_end, + &mode->htotal, + &mode->vdisplay, + &mode->vsync_start, + &mode->vsync_end, + &mode->vtotal, hsync, vsync) != 11) + return false; + + mode->clock = fclock * 1000; + + if (strcmp(hsync, "+hsync") == 0) + mode->flags |= DRM_MODE_FLAG_PHSYNC; + else if (strcmp(hsync, "-hsync") == 0) + mode->flags |= DRM_MODE_FLAG_NHSYNC; + else + return false; + + if (strcmp(vsync, "+vsync") == 0) + mode->flags |= DRM_MODE_FLAG_PVSYNC; + else if (strcmp(vsync, "-vsync") == 0) + mode->flags |= DRM_MODE_FLAG_NVSYNC; + else + return false; + + return true; +} + +QEglFSKmsScreen *QEglFSKmsDevice::screenForConnector(drmModeResPtr resources, drmModeConnectorPtr connector, QPoint pos) +{ + const QByteArray connectorName = nameForConnector(connector); + + const int crtc = crtcForConnector(resources, connector); + if (crtc < 0) { + qWarning() << "No usable crtc/encoder pair for connector" << connectorName; + return Q_NULLPTR; + } + + OutputConfiguration configuration; + QSize configurationSize; + drmModeModeInfo configurationModeline; + + const QByteArray mode = m_integration->outputSettings().value(QString::fromUtf8(connectorName)) + .value(QStringLiteral("mode"), QStringLiteral("preferred")).toByteArray().toLower(); + if (mode == "off") { + configuration = OutputConfigOff; + } else if (mode == "preferred") { + configuration = OutputConfigPreferred; + } else if (mode == "current") { + configuration = OutputConfigCurrent; + } else if (sscanf(mode.constData(), "%dx%d", &configurationSize.rwidth(), &configurationSize.rheight()) == 2) { + configuration = OutputConfigMode; + } else if (parseModeline(mode, &configurationModeline)) { + configuration = OutputConfigModeline; + } else { + qWarning("Invalid mode \"%s\" for output %s", mode.constData(), connectorName.constData()); + configuration = OutputConfigPreferred; + } + + const uint32_t crtc_id = resources->crtcs[crtc]; + + if (configuration == OutputConfigOff) { + qCDebug(qLcEglfsKmsDebug) << "Turning off output" << connectorName; + drmModeSetCrtc(m_dri_fd, crtc_id, 0, 0, 0, 0, 0, Q_NULLPTR); + return Q_NULLPTR; + } + + // Skip disconnected output + if (configuration == OutputConfigPreferred && connector->connection == DRM_MODE_DISCONNECTED) { + qCDebug(qLcEglfsKmsDebug) << "Skipping disconnected output" << connectorName; + return Q_NULLPTR; + } + + // Get the current mode on the current crtc + drmModeModeInfo crtc_mode; + memset(&crtc_mode, 0, sizeof crtc_mode); + if (drmModeEncoderPtr encoder = drmModeGetEncoder(m_dri_fd, connector->connector_id)) { + drmModeCrtcPtr crtc = drmModeGetCrtc(m_dri_fd, encoder->crtc_id); + drmModeFreeEncoder(encoder); + + if (!crtc) + return Q_NULLPTR; + + if (crtc->mode_valid) + crtc_mode = crtc->mode; + + drmModeFreeCrtc(crtc); + } + + QList modes; + modes.reserve(connector->count_modes); + qCDebug(qLcEglfsKmsDebug) << connectorName << "mode count:" << connector->count_modes; + for (int i = 0; i < connector->count_modes; i++) { + const drmModeModeInfo &mode = connector->modes[i]; + qCDebug(qLcEglfsKmsDebug) << "mode" << i << mode.hdisplay << "x" << mode.vdisplay + << '@' << mode.vrefresh << "hz"; + modes << connector->modes[i]; + } + + int preferred = -1; + int current = -1; + int configured = -1; + int best = -1; + + for (int i = modes.size() - 1; i >= 0; i--) { + const drmModeModeInfo &m = modes.at(i); + + if (configuration == OutputConfigMode && + m.hdisplay == configurationSize.width() && + m.vdisplay == configurationSize.height()) { + configured = i; + } + + if (!memcmp(&crtc_mode, &m, sizeof m)) + current = i; + + if (m.type & DRM_MODE_TYPE_PREFERRED) + preferred = i; + + best = i; + } + + if (configuration == OutputConfigModeline) { + modes << configurationModeline; + configured = modes.size() - 1; + } + + if (current < 0 && crtc_mode.clock != 0) { + modes << crtc_mode; + current = mode.size() - 1; + } + + if (configuration == OutputConfigCurrent) + configured = current; + + int selected_mode = -1; + + if (configured >= 0) + selected_mode = configured; + else if (preferred >= 0) + selected_mode = preferred; + else if (current >= 0) + selected_mode = current; + else if (best >= 0) + selected_mode = best; + + if (selected_mode < 0) { + qWarning() << "No modes available for output" << connectorName; + return Q_NULLPTR; + } else { + int width = modes[selected_mode].hdisplay; + int height = modes[selected_mode].vdisplay; + int refresh = modes[selected_mode].vrefresh; + qCDebug(qLcEglfsKmsDebug) << "Selected mode" << selected_mode << ":" << width << "x" << height + << '@' << refresh << "hz for output" << connectorName; + } + static const int width = qEnvironmentVariableIntValue("QT_QPA_EGLFS_PHYSICAL_WIDTH"); + static const int height = qEnvironmentVariableIntValue("QT_QPA_EGLFS_PHYSICAL_HEIGHT"); + QSizeF size(width, height); + if (size.isEmpty()) { + size.setWidth(connector->mmWidth); + size.setHeight(connector->mmHeight); + } + QEglFSKmsOutput output = { + QString::fromUtf8(connectorName), + connector->connector_id, + crtc_id, + size, + selected_mode, + false, + drmModeGetCrtc(m_dri_fd, crtc_id), + modes, + connector->subpixel, + connectorProperty(connector, QByteArrayLiteral("DPMS")) + }; + + m_crtc_allocator |= (1 << output.crtc_id); + m_connector_allocator |= (1 << output.connector_id); + + return createScreen(m_integration, this, output, pos); +} + +drmModePropertyPtr QEglFSKmsDevice::connectorProperty(drmModeConnectorPtr connector, const QByteArray &name) +{ + drmModePropertyPtr prop; + + for (int i = 0; i < connector->count_props; i++) { + prop = drmModeGetProperty(m_dri_fd, connector->props[i]); + if (!prop) + continue; + if (strcmp(prop->name, name.constData()) == 0) + return prop; + drmModeFreeProperty(prop); + } + + return Q_NULLPTR; +} + +QEglFSKmsDevice::QEglFSKmsDevice(QEglFSKmsIntegration *integration, const QString &path) + : m_integration(integration) + , m_path(path) + , m_dri_fd(-1) + , m_crtc_allocator(0) + , m_connector_allocator(0) +{ +} + +QEglFSKmsDevice::~QEglFSKmsDevice() +{ +} + +void QEglFSKmsDevice::createScreens() +{ + drmModeResPtr resources = drmModeGetResources(m_dri_fd); + if (!resources) { + qWarning("drmModeGetResources failed"); + return; + } + + QEglFSKmsScreen *primaryScreen = Q_NULLPTR; + QList siblings; + QPoint pos(0, 0); + QEglFSIntegration *integration = static_cast(QGuiApplicationPrivate::platformIntegration()); + + for (int i = 0; i < resources->count_connectors; i++) { + drmModeConnectorPtr connector = drmModeGetConnector(m_dri_fd, resources->connectors[i]); + if (!connector) + continue; + + QEglFSKmsScreen *screen = screenForConnector(resources, connector, pos); + if (screen) { + integration->addScreen(screen); + pos.rx() += screen->geometry().width(); + siblings << screen; + + if (!primaryScreen) + primaryScreen = screen; + } + + drmModeFreeConnector(connector); + } + + drmModeFreeResources(resources); + + if (!m_integration->separateScreens()) { + Q_FOREACH (QPlatformScreen *screen, siblings) + static_cast(screen)->setVirtualSiblings(siblings); + } +} + +int QEglFSKmsDevice::fd() const +{ + return m_dri_fd; +} + +QString QEglFSKmsDevice::devicePath() const +{ + return m_path; +} + +QEglFSKmsScreen *QEglFSKmsDevice::createScreen(QEglFSKmsIntegration *integration, QEglFSKmsDevice *device, QEglFSKmsOutput output, QPoint position) +{ + return new QEglFSKmsScreen(integration, device, output, position); +} + +void QEglFSKmsDevice::setFd(int fd) +{ + m_dri_fd = fd; +} + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsdevice.h b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsdevice.h new file mode 100644 index 0000000000..ffa8bcbaa5 --- /dev/null +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsdevice.h @@ -0,0 +1,98 @@ +/**************************************************************************** +** +** Copyright (C) 2015 Pier Luigi Fiorini +** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2016 Pelagicore AG +** 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 QEGLFSKMSDEVICE_H +#define QEGLFSKMSDEVICE_H + +#include "qeglfskmsintegration.h" +#include "qeglfskmsscreen.h" + +#include +#include + +QT_BEGIN_NAMESPACE + +class Q_EGLFS_EXPORT QEglFSKmsDevice +{ +public: + QEglFSKmsDevice(QEglFSKmsIntegration *integration, const QString &path); + virtual ~QEglFSKmsDevice(); + + virtual bool open() = 0; + virtual void close() = 0; + + virtual void createScreens(); + + virtual EGLNativeDisplayType device() const = 0; + int fd() const; + QString devicePath() const; + +protected: + virtual QEglFSKmsScreen *createScreen(QEglFSKmsIntegration *integration, + QEglFSKmsDevice *device, + QEglFSKmsOutput output, + QPoint position); + void setFd(int fd); + +private: + Q_DISABLE_COPY(QEglFSKmsDevice) + + QEglFSKmsIntegration *m_integration; + QString m_path; + int m_dri_fd; + + quint32 m_crtc_allocator; + quint32 m_connector_allocator; + + int crtcForConnector(drmModeResPtr resources, drmModeConnectorPtr connector); + QEglFSKmsScreen *screenForConnector(drmModeResPtr resources, drmModeConnectorPtr connector, QPoint pos); + drmModePropertyPtr connectorProperty(drmModeConnectorPtr connector, const QByteArray &name); + + static void pageFlipHandler(int fd, + unsigned int sequence, + unsigned int tv_sec, + unsigned int tv_usec, + void *user_data); +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsintegration.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsintegration.cpp new file mode 100644 index 0000000000..e25e481878 --- /dev/null +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsintegration.cpp @@ -0,0 +1,213 @@ +/**************************************************************************** +** +** Copyright (C) 2015 Pier Luigi Fiorini +** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2016 Pelagicore AG +** 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 "qeglfskmsintegration.h" +#include "qeglfskmsdevice.h" +#include "qeglfskmsscreen.h" +#include "qeglfswindow.h" +#include "qeglfscursor.h" + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +QT_BEGIN_NAMESPACE + +Q_LOGGING_CATEGORY(qLcEglfsKmsDebug, "qt.qpa.eglfs.kms") + +QEglFSKmsIntegration::QEglFSKmsIntegration() + : m_device(Q_NULLPTR) + , m_hwCursor(false) + , m_pbuffers(false) + , m_separateScreens(false) +{} + +void QEglFSKmsIntegration::platformInit() +{ + loadConfig(); + + if (!m_devicePath.isEmpty()) { + qCDebug(qLcEglfsKmsDebug) << "Using DRM device" << m_devicePath << "specified in config file"; + } + + m_device = createDevice(m_devicePath); + if (Q_UNLIKELY(!m_device->open())) + qFatal("Could not open device %s - aborting!", qPrintable(m_devicePath)); +} + +void QEglFSKmsIntegration::platformDestroy() +{ + m_device->close(); + delete m_device; + m_device = Q_NULLPTR; +} + +EGLNativeDisplayType QEglFSKmsIntegration::platformDisplay() const +{ + Q_ASSERT(m_device); + return reinterpret_cast(m_device->device()); +} + +bool QEglFSKmsIntegration::usesDefaultScreen() +{ + return false; +} + +void QEglFSKmsIntegration::screenInit() +{ + m_device->createScreens(); +} + +QSurfaceFormat QEglFSKmsIntegration::surfaceFormatFor(const QSurfaceFormat &inputFormat) const +{ + QSurfaceFormat format(inputFormat); + format.setRenderableType(QSurfaceFormat::OpenGLES); + format.setSwapBehavior(QSurfaceFormat::DoubleBuffer); + format.setRedBufferSize(8); + format.setGreenBufferSize(8); + format.setBlueBufferSize(8); + return format; +} + +bool QEglFSKmsIntegration::hasCapability(QPlatformIntegration::Capability cap) const +{ + switch (cap) { + case QPlatformIntegration::ThreadedPixmaps: + case QPlatformIntegration::OpenGL: + case QPlatformIntegration::ThreadedOpenGL: + return true; + default: + return false; + } +} + +void QEglFSKmsIntegration::waitForVSync(QPlatformSurface *surface) const +{ + QWindow *window = static_cast(surface->surface()); + QEglFSKmsScreen *screen = static_cast(window->screen()->handle()); + + screen->waitForFlip(); +} + +bool QEglFSKmsIntegration::supportsPBuffers() const +{ + return m_pbuffers; +} + +bool QEglFSKmsIntegration::hwCursor() const +{ + return m_hwCursor; +} + +bool QEglFSKmsIntegration::separateScreens() const +{ + return m_separateScreens; +} + +QMap QEglFSKmsIntegration::outputSettings() const +{ + return m_outputSettings; +} + +QEglFSKmsDevice *QEglFSKmsIntegration::device() const +{ + return m_device; +} + +void QEglFSKmsIntegration::loadConfig() +{ + static QByteArray json = qgetenv("QT_QPA_EGLFS_KMS_CONFIG"); + if (json.isEmpty()) + return; + + qCDebug(qLcEglfsKmsDebug) << "Loading KMS setup from" << json; + + QFile file(QString::fromUtf8(json)); + if (!file.open(QFile::ReadOnly)) { + qCDebug(qLcEglfsKmsDebug) << "Could not open config file" + << json << "for reading"; + return; + } + + const QJsonDocument doc = QJsonDocument::fromJson(file.readAll()); + if (!doc.isObject()) { + qCDebug(qLcEglfsKmsDebug) << "Invalid config file" << json + << "- no top-level JSON object"; + return; + } + + const QJsonObject object = doc.object(); + + m_hwCursor = object.value(QStringLiteral("hwcursor")).toBool(m_hwCursor); + m_pbuffers = object.value(QStringLiteral("pbuffers")).toBool(m_pbuffers); + m_devicePath = object.value(QStringLiteral("device")).toString(); + m_separateScreens = object.value(QStringLiteral("separateScreens")).toBool(m_separateScreens); + + const QJsonArray outputs = object.value(QStringLiteral("outputs")).toArray(); + for (int i = 0; i < outputs.size(); i++) { + const QVariantMap outputSettings = outputs.at(i).toObject().toVariantMap(); + + if (outputSettings.contains(QStringLiteral("name"))) { + const QString name = outputSettings.value(QStringLiteral("name")).toString(); + + if (m_outputSettings.contains(name)) { + qCDebug(qLcEglfsKmsDebug) << "Output" << name << "configured multiple times!"; + } + + m_outputSettings.insert(name, outputSettings); + } + } + + qCDebug(qLcEglfsKmsDebug) << "Configuration:\n" + << "\thwcursor:" << m_hwCursor << "\n" + << "\tpbuffers:" << m_pbuffers << "\n" + << "\tseparateScreens:" << m_separateScreens << "\n" + << "\toutputs:" << m_outputSettings; +} + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsintegration.h b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsintegration.h new file mode 100644 index 0000000000..c630d93fce --- /dev/null +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsintegration.h @@ -0,0 +1,93 @@ +/**************************************************************************** +** +** Copyright (C) 2015 Pier Luigi Fiorini +** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2016 Pelagicore AG +** 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 QEGLFSKMSINTEGRATION_H +#define QEGLFSKMSINTEGRATION_H + +#include "qeglfsdeviceintegration.h" +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class QEglFSKmsDevice; + +Q_EGLFS_EXPORT Q_DECLARE_LOGGING_CATEGORY(qLcEglfsKmsDebug) + +class Q_EGLFS_EXPORT QEglFSKmsIntegration : public QEGLDeviceIntegration +{ +public: + QEglFSKmsIntegration(); + + void platformInit() Q_DECL_OVERRIDE; + void platformDestroy() Q_DECL_OVERRIDE; + EGLNativeDisplayType platformDisplay() const Q_DECL_OVERRIDE; + bool usesDefaultScreen() Q_DECL_OVERRIDE; + void screenInit() Q_DECL_OVERRIDE; + QSurfaceFormat surfaceFormatFor(const QSurfaceFormat &inputFormat) const Q_DECL_OVERRIDE; + bool hasCapability(QPlatformIntegration::Capability cap) const Q_DECL_OVERRIDE; + void waitForVSync(QPlatformSurface *surface) const Q_DECL_OVERRIDE; + bool supportsPBuffers() const Q_DECL_OVERRIDE; + + virtual bool hwCursor() const; + virtual bool separateScreens() const; + QMap outputSettings() const; + + QEglFSKmsDevice *device() const; + +protected: + virtual QEglFSKmsDevice *createDevice(const QString &devicePath) = 0; + +private: + void loadConfig(); + + QEglFSKmsDevice *m_device; + bool m_hwCursor; + bool m_pbuffers; + bool m_separateScreens; + QString m_devicePath; + QMap m_outputSettings; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsscreen.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsscreen.cpp new file mode 100644 index 0000000000..f614351a40 --- /dev/null +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsscreen.cpp @@ -0,0 +1,220 @@ +/**************************************************************************** +** +** Copyright (C) 2015 Pier Luigi Fiorini +** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2016 Pelagicore AG +** 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 "qeglfskmsscreen.h" +#include "qeglfskmsdevice.h" +#include "qeglfsintegration.h" + +#include + +#include +#include + +QT_BEGIN_NAMESPACE + +Q_DECLARE_LOGGING_CATEGORY(qLcEglfsKmsDebug) + +class QEglFSKmsInterruptHandler : public QObject +{ +public: + QEglFSKmsInterruptHandler(QEglFSKmsScreen *screen) : m_screen(screen) { + m_vtHandler = static_cast(QGuiApplicationPrivate::platformIntegration())->vtHandler(); + connect(m_vtHandler, &QFbVtHandler::interrupted, this, &QEglFSKmsInterruptHandler::restoreVideoMode); + connect(m_vtHandler, &QFbVtHandler::aboutToSuspend, this, &QEglFSKmsInterruptHandler::restoreVideoMode); + } + +public slots: + void restoreVideoMode() { m_screen->restoreMode(); } + +private: + QFbVtHandler *m_vtHandler; + QEglFSKmsScreen *m_screen; +}; + +QEglFSKmsScreen::QEglFSKmsScreen(QEglFSKmsIntegration *integration, + QEglFSKmsDevice *device, + QEglFSKmsOutput output, + QPoint position) + : QEglFSScreen(eglGetDisplay(reinterpret_cast(device->device()))) + , m_integration(integration) + , m_device(device) + , m_output(output) + , m_pos(position) + , m_powerState(PowerStateOn) + , m_interruptHandler(new QEglFSKmsInterruptHandler(this)) +{ + m_siblings << this; +} + +QEglFSKmsScreen::~QEglFSKmsScreen() +{ + if (m_output.dpms_prop) { + drmModeFreeProperty(m_output.dpms_prop); + m_output.dpms_prop = Q_NULLPTR; + } + restoreMode(); + if (m_output.saved_crtc) { + drmModeFreeCrtc(m_output.saved_crtc); + m_output.saved_crtc = Q_NULLPTR; + } + delete m_interruptHandler; +} + +QRect QEglFSKmsScreen::geometry() const +{ + const int mode = m_output.mode; + return QRect(m_pos.x(), m_pos.y(), + m_output.modes[mode].hdisplay, + m_output.modes[mode].vdisplay); +} + +int QEglFSKmsScreen::depth() const +{ + return 32; +} + +QImage::Format QEglFSKmsScreen::format() const +{ + return QImage::Format_RGB32; +} + +QSizeF QEglFSKmsScreen::physicalSize() const +{ + return m_output.physical_size; +} + +QDpi QEglFSKmsScreen::logicalDpi() const +{ + const QSizeF ps = physicalSize(); + const QSize s = geometry().size(); + + if (!ps.isEmpty() && !s.isEmpty()) + return QDpi(25.4 * s.width() / ps.width(), + 25.4 * s.height() / ps.height()); + else + return QDpi(100, 100); +} + +Qt::ScreenOrientation QEglFSKmsScreen::nativeOrientation() const +{ + return Qt::PrimaryOrientation; +} + +Qt::ScreenOrientation QEglFSKmsScreen::orientation() const +{ + return Qt::PrimaryOrientation; +} + +QString QEglFSKmsScreen::name() const +{ + return m_output.name; +} + +void QEglFSKmsScreen::destroySurface() +{ +} + +void QEglFSKmsScreen::waitForFlip() +{ +} + +void QEglFSKmsScreen::flip() +{ +} + +void QEglFSKmsScreen::flipFinished() +{ +} + +void QEglFSKmsScreen::restoreMode() +{ + if (m_output.mode_set && m_output.saved_crtc) { + drmModeSetCrtc(m_device->fd(), + m_output.saved_crtc->crtc_id, + m_output.saved_crtc->buffer_id, + 0, 0, + &m_output.connector_id, 1, + &m_output.saved_crtc->mode); + + m_output.mode_set = false; + } +} + +qreal QEglFSKmsScreen::refreshRate() const +{ + quint32 refresh = m_output.modes[m_output.mode].vrefresh; + return refresh > 0 ? refresh : 60; +} + +QPlatformScreen::SubpixelAntialiasingType QEglFSKmsScreen::subpixelAntialiasingTypeHint() const +{ + switch (m_output.subpixel) { + default: + case DRM_MODE_SUBPIXEL_UNKNOWN: + case DRM_MODE_SUBPIXEL_NONE: + return Subpixel_None; + case DRM_MODE_SUBPIXEL_HORIZONTAL_RGB: + return Subpixel_RGB; + case DRM_MODE_SUBPIXEL_HORIZONTAL_BGR: + return Subpixel_BGR; + case DRM_MODE_SUBPIXEL_VERTICAL_RGB: + return Subpixel_VRGB; + case DRM_MODE_SUBPIXEL_VERTICAL_BGR: + return Subpixel_VBGR; + } +} + +QPlatformScreen::PowerState QEglFSKmsScreen::powerState() const +{ + return m_powerState; +} + +void QEglFSKmsScreen::setPowerState(QPlatformScreen::PowerState state) +{ + if (!m_output.dpms_prop) + return; + + drmModeConnectorSetProperty(m_device->fd(), m_output.connector_id, + m_output.dpms_prop->prop_id, (int)state); + m_powerState = state; +} + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsscreen.h b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsscreen.h new file mode 100644 index 0000000000..ed26ca0419 --- /dev/null +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsscreen.h @@ -0,0 +1,130 @@ +/**************************************************************************** +** +** Copyright (C) 2015 Pier Luigi Fiorini +** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2016 Pelagicore AG +** 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 QEGLFSKMSSCREEN_H +#define QEGLFSKMSSCREEN_H + +#include "qeglfskmsintegration.h" +#include "qeglfsscreen.h" +#include +#include + +#include +#include + +QT_BEGIN_NAMESPACE + +class QEglFSKmsDevice; +class QEglFSKmsInterruptHandler; + +struct QEglFSKmsOutput +{ + QString name; + uint32_t connector_id; + uint32_t crtc_id; + QSizeF physical_size; + int mode; // index of selected mode in list below + bool mode_set; + drmModeCrtcPtr saved_crtc; + QList modes; + int subpixel; + drmModePropertyPtr dpms_prop; +}; + +class Q_EGLFS_EXPORT QEglFSKmsScreen : public QEglFSScreen +{ +public: + QEglFSKmsScreen(QEglFSKmsIntegration *integration, + QEglFSKmsDevice *device, + QEglFSKmsOutput output, + QPoint position); + ~QEglFSKmsScreen(); + + QRect geometry() const Q_DECL_OVERRIDE; + int depth() const Q_DECL_OVERRIDE; + QImage::Format format() const Q_DECL_OVERRIDE; + + QSizeF physicalSize() const Q_DECL_OVERRIDE; + QDpi logicalDpi() const Q_DECL_OVERRIDE; + Qt::ScreenOrientation nativeOrientation() const Q_DECL_OVERRIDE; + Qt::ScreenOrientation orientation() const Q_DECL_OVERRIDE; + + QString name() const Q_DECL_OVERRIDE; + + qreal refreshRate() const Q_DECL_OVERRIDE; + + QList virtualSiblings() const Q_DECL_OVERRIDE { return m_siblings; } + void setVirtualSiblings(QList sl) { m_siblings = sl; } + + QEglFSKmsIntegration *integration() const { return m_integration; } + QEglFSKmsDevice *device() const { return m_device; } + + void destroySurface(); + + virtual void waitForFlip(); + virtual void flip(); + virtual void flipFinished(); + + QEglFSKmsOutput &output() { return m_output; } + void restoreMode(); + + SubpixelAntialiasingType subpixelAntialiasingTypeHint() const Q_DECL_OVERRIDE; + + QPlatformScreen::PowerState powerState() const Q_DECL_OVERRIDE; + void setPowerState(QPlatformScreen::PowerState state) Q_DECL_OVERRIDE; + +private: + QEglFSKmsIntegration *m_integration; + QEglFSKmsDevice *m_device; + + QEglFSKmsOutput m_output; + QPoint m_pos; + + QList m_siblings; + + PowerState m_powerState; + + QEglFSKmsInterruptHandler *m_interruptHandler; +}; + +QT_END_NAMESPACE + +#endif -- cgit v1.2.3 From 760b2929a3b268e2edf14a561329bdb78fbdc26e Mon Sep 17 00:00:00 2001 From: Louai Al-Khanji Date: Wed, 13 Apr 2016 16:20:40 -0700 Subject: xcb: Fix image scanline padding Commit b9d386f2ccd69c7f6a766a6d90a6024eeb48e90a neglects to account for the scanline padding requested by the X server. This can result in visual artifacts if padding is required. This commit fixes this by factoring in the X server's requested scanline padding when calculating image stride. Change-Id: I082cb7101ec3a9c554b9b58a76f53f780b87d31e Reviewed-by: Lars Knoll --- src/plugins/platforms/xcb/qxcbbackingstore.cpp | 37 +++++++++++++++----------- 1 file changed, 22 insertions(+), 15 deletions(-) diff --git a/src/plugins/platforms/xcb/qxcbbackingstore.cpp b/src/plugins/platforms/xcb/qxcbbackingstore.cpp index 844ed8f579..51c6b198e5 100644 --- a/src/plugins/platforms/xcb/qxcbbackingstore.cpp +++ b/src/plugins/platforms/xcb/qxcbbackingstore.cpp @@ -305,47 +305,52 @@ static inline void copy_unswapped(char *dst, int dstBytesPerLine, const QImage & } template -static inline void copy_swapped(Pixel *dst, const QImage &img, const QRect &rect) +static inline void copy_swapped(char *dst, const int dstStride, const QImage &img, const QRect &rect) { const uchar *srcData = img.constBits(); const int srcBytesPerLine = img.bytesPerLine(); const int left = rect.left(); - const int right = rect.right() + 1; + const int width = rect.width(); const int bottom = rect.bottom() + 1; for (int yy = rect.top(); yy < bottom; ++yy) { - const Pixel *src = reinterpret_cast(srcData + yy * srcBytesPerLine) + left; + Pixel *dstPixels = reinterpret_cast(dst); + const Pixel *srcPixels = reinterpret_cast(srcData + yy * srcBytesPerLine) + left; - for (int xx = left; xx < right; ++xx) - *dst++ = qbswap(*src++); + for (int i = 0; i < width; ++i) + dstPixels[i] = qbswap(*srcPixels++); + + dst += dstStride; } } -static QImage native_sub_image(QByteArray *buffer, const QImage &src, int x, int y, int w, int h, bool swap) +static QImage native_sub_image(QByteArray *buffer, const int dstStride, const QImage &src, const QRect &rect, bool swap) { - const QRect rect(x, y, w, h); - - if (!swap && src.rect() == rect) + if (!swap && src.rect() == rect && src.bytesPerLine() == dstStride) return src; - const int dstStride = w * src.depth() >> 3; - buffer->resize(h * dstStride); + buffer->resize(rect.height() * dstStride); if (swap) { switch (src.depth()) { case 32: - copy_swapped(reinterpret_cast(buffer->data()), src, rect); + copy_swapped(buffer->data(), dstStride, src, rect); break; case 16: - copy_swapped(reinterpret_cast(buffer->data()), src, rect); + copy_swapped(buffer->data(), dstStride, src, rect); break; } } else { copy_unswapped(buffer->data(), dstStride, src, rect); } - return QImage(reinterpret_cast(buffer->constData()), w, h, dstStride, src.format()); + return QImage(reinterpret_cast(buffer->constData()), rect.width(), rect.height(), dstStride, src.format()); +} + +static inline quint32 round_up_scanline(quint32 base, quint32 pad) +{ + return (base + pad - 1) & -pad; } void QXcbShmImage::flushPixmap(const QRegion ®ion) @@ -390,7 +395,9 @@ void QXcbShmImage::flushPixmap(const QRegion ®ion) while (height > 0) { const int rows = std::min(height, rows_per_put); - const QImage subImage = native_sub_image(&m_flushBuffer, m_qimage, x, y, width, rows, needsByteSwap); + const QRect subRect(x, y, width, rows); + const quint32 stride = round_up_scanline(width * m_qimage.depth(), xcb_subimage.scanline_pad) >> 3; + const QImage subImage = native_sub_image(&m_flushBuffer, stride, m_qimage, subRect, needsByteSwap); xcb_subimage.width = width; xcb_subimage.height = rows; -- cgit v1.2.3 From 5361a8dec5300761044dd8a2628db0c0448075cc Mon Sep 17 00:00:00 2001 From: Anton Kudryavtsev Date: Thu, 14 Apr 2016 09:17:55 +0300 Subject: Moc generator: avoid creating QMap::keys(). Iterate the keys directly off the QMap itself. Change-Id: I7792414db250d8ae63a935513a16a01eb184ebde Reviewed-by: Edward Welbourne Reviewed-by: Marc Mutz --- src/tools/moc/generator.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/tools/moc/generator.cpp b/src/tools/moc/generator.cpp index 2b09cf873a..e95ec8296c 100644 --- a/src/tools/moc/generator.cpp +++ b/src/tools/moc/generator.cpp @@ -499,9 +499,9 @@ void Generator::generateCode() // QTBUG-20639 - Accept non-local enums for QML signal/slot parameters. // Look for any scoped enum declarations, and add those to the list // of extra/related metaobjects for this object. - QList enumKeys = cdef->enumDeclarations.keys(); - for (int i = 0; i < enumKeys.count(); ++i) { - const QByteArray &enumKey = enumKeys[i]; + for (auto it = cdef->enumDeclarations.keyBegin(), + end = cdef->enumDeclarations.keyEnd(); it != end; ++it) { + const QByteArray &enumKey = *it; int s = enumKey.lastIndexOf("::"); if (s > 0) { QByteArray scope = enumKey.left(s); -- cgit v1.2.3 From 777d46b40360c302a49fc5b789cee6d0d05f840a Mon Sep 17 00:00:00 2001 From: Anton Kudryavtsev Date: Thu, 14 Apr 2016 09:23:41 +0300 Subject: Moc: use const (and const APIs) more For CoW types, prefer const methods to avoid needless detach()ing. Change-Id: Iefc33552d826aa30320e52acd2d421c9bdae127e Reviewed-by: Edward Welbourne Reviewed-by: Marc Mutz --- src/tools/moc/generator.cpp | 2 +- src/tools/moc/main.cpp | 2 +- src/tools/moc/moc.cpp | 28 ++++++++++++++-------------- src/tools/moc/preprocessor.cpp | 18 +++++++++--------- 4 files changed, 25 insertions(+), 25 deletions(-) diff --git a/src/tools/moc/generator.cpp b/src/tools/moc/generator.cpp index e95ec8296c..3f274401b3 100644 --- a/src/tools/moc/generator.cpp +++ b/src/tools/moc/generator.cpp @@ -79,7 +79,7 @@ Generator::Generator(ClassDef *classDef, const QList &metaTypes, con , knownGadgets(knownGadgets) { if (cdef->superclassList.size()) - purestSuperClass = cdef->superclassList.first().first; + purestSuperClass = cdef->superclassList.constFirst().first; } static inline int lengthOfEscapeSequence(const QByteArray &s, int i) diff --git a/src/tools/moc/main.cpp b/src/tools/moc/main.cpp index 06d1c86d54..0734a92d5a 100644 --- a/src/tools/moc/main.cpp +++ b/src/tools/moc/main.cpp @@ -360,7 +360,7 @@ int runMoc(int argc, char **argv) int spos = filename.lastIndexOf(QDir::separator()); int ppos = filename.lastIndexOf(QLatin1Char('.')); // spos >= -1 && ppos > spos => ppos >= 0 - moc.noInclude = (ppos > spos && filename[ppos + 1].toLower() != QLatin1Char('h')); + moc.noInclude = (ppos > spos && filename.at(ppos + 1).toLower() != QLatin1Char('h')); } if (defaultInclude) { if (moc.includePath.isEmpty()) { diff --git a/src/tools/moc/moc.cpp b/src/tools/moc/moc.cpp index 0e689bd5c1..1cf74c7389 100644 --- a/src/tools/moc/moc.cpp +++ b/src/tools/moc/moc.cpp @@ -136,7 +136,7 @@ bool Moc::parseClassHead(ClassDef *def) } while (test(COMMA)); if (!def->superclassList.isEmpty() - && knownGadgets.contains(def->superclassList.first().first)) { + && knownGadgets.contains(def->superclassList.constFirst().first)) { // Q_GADGET subclasses are treated as Q_GADGETs knownGadgets.insert(def->classname, def->qualified); knownGadgets.insert(def->qualified, def->qualified); @@ -312,7 +312,7 @@ void Moc::parseFunctionArguments(FunctionDef *def) } if (!def->arguments.isEmpty() - && def->arguments.last().normalizedType == "QPrivateSignal") { + && def->arguments.constLast().normalizedType == "QPrivateSignal") { def->arguments.removeLast(); def->isPrivateSignal = true; } @@ -730,7 +730,7 @@ void Moc::parse() if (funcDef.isConstructor) { if ((access == FunctionDef::Public) && funcDef.isInvokable) { def.constructorList += funcDef; - while (funcDef.arguments.size() > 0 && funcDef.arguments.last().isDefault) { + while (funcDef.arguments.size() > 0 && funcDef.arguments.constLast().isDefault) { funcDef.wasCloned = true; funcDef.arguments.removeLast(); def.constructorList += funcDef; @@ -743,7 +743,7 @@ void Moc::parse() def.publicList += funcDef; if (funcDef.isSlot) { def.slotList += funcDef; - while (funcDef.arguments.size() > 0 && funcDef.arguments.last().isDefault) { + while (funcDef.arguments.size() > 0 && funcDef.arguments.constLast().isDefault) { funcDef.wasCloned = true; funcDef.arguments.removeLast(); def.slotList += funcDef; @@ -752,7 +752,7 @@ void Moc::parse() ++def.revisionedMethods; } else if (funcDef.isSignal) { def.signalList += funcDef; - while (funcDef.arguments.size() > 0 && funcDef.arguments.last().isDefault) { + while (funcDef.arguments.size() > 0 && funcDef.arguments.constLast().isDefault) { funcDef.wasCloned = true; funcDef.arguments.removeLast(); def.signalList += funcDef; @@ -761,7 +761,7 @@ void Moc::parse() ++def.revisionedMethods; } else if (funcDef.isInvokable) { def.methodList += funcDef; - while (funcDef.arguments.size() > 0 && funcDef.arguments.last().isDefault) { + while (funcDef.arguments.size() > 0 && funcDef.arguments.constLast().isDefault) { funcDef.wasCloned = true; funcDef.arguments.removeLast(); def.methodList += funcDef; @@ -863,7 +863,7 @@ void Moc::generate(FILE *out) { QByteArray fn = filename; int i = filename.length()-1; - while (i>0 && filename[i-1] != '/' && filename[i-1] != '\\') + while (i > 0 && filename.at(i - 1) != '/' && filename.at(i - 1) != '\\') --i; // skip path if (i >= 0) fn = filename.mid(i); @@ -879,7 +879,7 @@ void Moc::generate(FILE *out) includePath += '/'; for (int i = 0; i < includeFiles.size(); ++i) { QByteArray inc = includeFiles.at(i); - if (inc[0] != '<' && inc[0] != '"') { + if (inc.at(0) != '<' && inc.at(0) != '"') { if (includePath.size() && includePath != "./") inc.prepend(includePath); inc = '\"' + inc + '\"'; @@ -887,7 +887,7 @@ void Moc::generate(FILE *out) fprintf(out, "#include %s\n", inc.constData()); } } - if (classList.size() && classList.first().classname == "Qt") + if (classList.size() && classList.constFirst().classname == "Qt") fprintf(out, "#include \n"); fprintf(out, "#include \n"); // For QByteArrayData @@ -965,7 +965,7 @@ void Moc::parseSlots(ClassDef *def, FunctionDef::Access access) ++def->revisionedMethods; } def->slotList += funcDef; - while (funcDef.arguments.size() > 0 && funcDef.arguments.last().isDefault) { + while (funcDef.arguments.size() > 0 && funcDef.arguments.constLast().isDefault) { funcDef.wasCloned = true; funcDef.arguments.removeLast(); def->slotList += funcDef; @@ -1021,7 +1021,7 @@ void Moc::parseSignals(ClassDef *def) ++def->revisionedMethods; } def->signalList += funcDef; - while (funcDef.arguments.size() > 0 && funcDef.arguments.last().isDefault) { + while (funcDef.arguments.size() > 0 && funcDef.arguments.constLast().isDefault) { funcDef.wasCloned = true; funcDef.arguments.removeLast(); def->signalList += funcDef; @@ -1059,7 +1059,7 @@ void Moc::createPropertyDef(PropertyDef &propDef) next(); propDef.name = lexem(); while (test(IDENTIFIER)) { - QByteArray l = lexem(); + const QByteArray l = lexem(); if (l[0] == 'C' && l == "CONSTANT") { propDef.constant = true; continue; @@ -1395,7 +1395,7 @@ void Moc::parseSlotInPrivate(ClassDef *def, FunctionDef::Access access) funcDef.access = access; parseFunction(&funcDef, true); def->slotList += funcDef; - while (funcDef.arguments.size() > 0 && funcDef.arguments.last().isDefault) { + while (funcDef.arguments.size() > 0 && funcDef.arguments.constLast().isDefault) { funcDef.wasCloned = true; funcDef.arguments.removeLast(); def->slotList += funcDef; @@ -1539,7 +1539,7 @@ void Moc::checkSuperClasses(ClassDef *def) if (interface2IdMap.contains(superClass)) { bool registeredInterface = false; for (int i = 0; i < def->interfaceList.count(); ++i) - if (def->interfaceList.at(i).first().className == superClass) { + if (def->interfaceList.at(i).constFirst().className == superClass) { registeredInterface = true; break; } diff --git a/src/tools/moc/preprocessor.cpp b/src/tools/moc/preprocessor.cpp index 9d9feb3ebe..ca5ee87cf1 100644 --- a/src/tools/moc/preprocessor.cpp +++ b/src/tools/moc/preprocessor.cpp @@ -205,13 +205,13 @@ Symbols Preprocessor::tokenize(const QByteArray& input, int lineNum, Preprocesso // STRING_LITERAL handling in moc if (!Preprocessor::preprocessOnly && !symbols.isEmpty() - && symbols.last().token == STRING_LITERAL) { + && symbols.constLast().token == STRING_LITERAL) { - QByteArray newString = symbols.last().unquotedLexem(); + QByteArray newString = symbols.constLast().unquotedLexem(); newString += input.mid(lexem - begin + 1, data - lexem - 2); newString.prepend('\"'); newString.append('\"'); - symbols.last() = Symbol(symbols.last().lineNum, + symbols.last() = Symbol(symbols.constLast().lineNum, STRING_LITERAL, newString); continue; @@ -679,7 +679,7 @@ Symbols Preprocessor::macroExpandIdentifier(Preprocessor *that, SymbolStack &sym if (s.token == WHITESPACE) continue; - while (expansion.size() && expansion.last().token == PP_WHITESPACE) + while (expansion.size() && expansion.constLast().token == PP_WHITESPACE) expansion.pop_back(); Symbol next = s; @@ -692,8 +692,8 @@ Symbols Preprocessor::macroExpandIdentifier(Preprocessor *that, SymbolStack &sym next = arg.at(0); } - if (!expansion.isEmpty() && expansion.last().token == s.token) { - Symbol last = expansion.last(); + if (!expansion.isEmpty() && expansion.constLast().token == s.token) { + Symbol last = expansion.constLast(); expansion.pop_back(); if (last.token == STRING_LITERAL || s.token == STRING_LITERAL) @@ -1127,12 +1127,12 @@ void Preprocessor::preprocess(const QByteArray &filename, Symbols &preprocessed) } // remove trailing whitespace while (!macro.symbols.isEmpty() && - (macro.symbols.last().token == PP_WHITESPACE || macro.symbols.last().token == WHITESPACE)) + (macro.symbols.constLast().token == PP_WHITESPACE || macro.symbols.constLast().token == WHITESPACE)) macro.symbols.pop_back(); if (!macro.symbols.isEmpty()) { - if (macro.symbols.first().token == PP_HASHHASH || - macro.symbols.last().token == PP_HASHHASH) { + if (macro.symbols.constFirst().token == PP_HASHHASH || + macro.symbols.constLast().token == PP_HASHHASH) { error("'##' cannot appear at either end of a macro expansion"); } } -- cgit v1.2.3 From f083830b8de106ed51d39242008215e9ea2179b2 Mon Sep 17 00:00:00 2001 From: Anton Kudryavtsev Date: Wed, 13 Apr 2016 14:45:11 +0300 Subject: CoreLib: use const (and const APIs) more For CoW types const methods will be called. Mark store_persistent_indexes() as const, because this method does not modify the object. Change-Id: Ic867913b4fb5aaebfbaaffe1d3be45cf7b646403 Reviewed-by: Thiago Macieira --- src/corelib/io/qsettings_mac.cpp | 4 ++-- src/corelib/io/qstandardpaths_mac.mm | 2 +- src/corelib/itemmodels/qabstractitemmodel.cpp | 12 ++++++------ src/corelib/itemmodels/qitemselectionmodel.cpp | 2 +- src/corelib/itemmodels/qsortfilterproxymodel.cpp | 6 +++--- src/corelib/kernel/qcoreapplication_win.cpp | 4 ++-- src/corelib/kernel/qeventdispatcher_glib.cpp | 2 +- src/corelib/kernel/qtimerinfo_unix.cpp | 2 +- src/corelib/mimetypes/qmimedatabase.cpp | 2 +- src/corelib/mimetypes/qmimeprovider.cpp | 6 +++--- src/corelib/statemachine/qhistorystate.cpp | 9 ++++++--- src/corelib/statemachine/qstatemachine.cpp | 2 +- src/corelib/thread/qthread_p.h | 2 +- src/corelib/thread/qthreadpool.cpp | 2 +- src/corelib/thread/qwaitcondition_win.cpp | 2 +- src/corelib/tools/qcommandlineparser.cpp | 7 ++++--- src/corelib/tools/qeasingcurve.cpp | 2 +- src/corelib/tools/qlocale_unix.cpp | 2 +- src/corelib/tools/qringbuffer.cpp | 12 ++++++------ src/corelib/tools/qtimezoneprivate_mac.mm | 2 +- 20 files changed, 44 insertions(+), 40 deletions(-) diff --git a/src/corelib/io/qsettings_mac.cpp b/src/corelib/io/qsettings_mac.cpp index ceee165459..d73cc4d298 100644 --- a/src/corelib/io/qsettings_mac.cpp +++ b/src/corelib/io/qsettings_mac.cpp @@ -149,7 +149,7 @@ static QCFType macValue(const QVariant &value) bool singleton = (values.count() == 1); if (singleton) { - switch (values.first().type()) { + switch (values.constFirst().type()) { // should be same as above (look for LIST) case QVariant::List: case QVariant::StringList: @@ -161,7 +161,7 @@ static QCFType macValue(const QVariant &value) } cfkeys[numUniqueKeys] = QCFString::toCFStringRef(key); - cfvalues[numUniqueKeys] = singleton ? macValue(values.first()) : macList(values); + cfvalues[numUniqueKeys] = singleton ? macValue(values.constFirst()) : macList(values); ++numUniqueKeys; } diff --git a/src/corelib/io/qstandardpaths_mac.mm b/src/corelib/io/qstandardpaths_mac.mm index 33c34d41af..f08a6dac53 100644 --- a/src/corelib/io/qstandardpaths_mac.mm +++ b/src/corelib/io/qstandardpaths_mac.mm @@ -273,7 +273,7 @@ QString QStandardPaths::displayName(StandardLocation type) return QCoreApplication::translate("QStandardPaths", "Applications"); if (QCFType url = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, - standardLocations(type).first().toCFString(), + standardLocations(type).constFirst().toCFString(), kCFURLPOSIXPathStyle, true)) { QCFString name; CFURLCopyResourcePropertyForKey(url, kCFURLLocalizedNameKey, &name, NULL); diff --git a/src/corelib/itemmodels/qabstractitemmodel.cpp b/src/corelib/itemmodels/qabstractitemmodel.cpp index 02b1e1c306..54afb8a974 100644 --- a/src/corelib/itemmodels/qabstractitemmodel.cpp +++ b/src/corelib/itemmodels/qabstractitemmodel.cpp @@ -58,8 +58,8 @@ QPersistentModelIndexData *QPersistentModelIndexData::create(const QModelIndex & QPersistentModelIndexData *d = 0; QAbstractItemModel *model = const_cast(index.model()); QHash &indexes = model->d_func()->persistent.indexes; - const QHash::iterator it = indexes.find(index); - if (it != indexes.end()) { + const auto it = indexes.constFind(index); + if (it != indexes.cend()) { d = (*it); } else { d = new QPersistentModelIndexData(index); @@ -603,13 +603,13 @@ void QAbstractItemModelPrivate::removePersistentIndexData(QPersistentModelIndexD } // make sure our optimization still works for (int i = persistent.moved.count() - 1; i >= 0; --i) { - int idx = persistent.moved[i].indexOf(data); + int idx = persistent.moved.at(i).indexOf(data); if (idx >= 0) persistent.moved[i].remove(idx); } // update the references to invalidated persistent indexes for (int i = persistent.invalidated.count() - 1; i >= 0; --i) { - int idx = persistent.invalidated[i].indexOf(data); + int idx = persistent.invalidated.at(i).indexOf(data); if (idx >= 0) persistent.invalidated[i].remove(idx); } @@ -2544,13 +2544,13 @@ bool QAbstractItemModel::decodeData(int row, int column, const QModelIndex &pare for (int i = 0; i < rows.count(); ++i) rowsToInsert[rows.at(i)] = 1; for (int i = 0; i < rowsToInsert.count(); ++i) { - if (rowsToInsert[i] == 1){ + if (rowsToInsert.at(i) == 1){ rowsToInsert[i] = dragRowCount; ++dragRowCount; } } for (int i = 0; i < rows.count(); ++i) - rows[i] = top + rowsToInsert[rows[i]]; + rows[i] = top + rowsToInsert.at(rows.at(i)); QBitArray isWrittenTo(dragRowCount * dragColumnCount); diff --git a/src/corelib/itemmodels/qitemselectionmodel.cpp b/src/corelib/itemmodels/qitemselectionmodel.cpp index 56df8fd55a..6390d5f389 100644 --- a/src/corelib/itemmodels/qitemselectionmodel.cpp +++ b/src/corelib/itemmodels/qitemselectionmodel.cpp @@ -863,7 +863,7 @@ void QItemSelectionModelPrivate::_q_layoutAboutToBeChanged(const QListrowCount(parent); tableColCount = model->columnCount(parent); diff --git a/src/corelib/itemmodels/qsortfilterproxymodel.cpp b/src/corelib/itemmodels/qsortfilterproxymodel.cpp index 18cb49d483..98202b71ae 100644 --- a/src/corelib/itemmodels/qsortfilterproxymodel.cpp +++ b/src/corelib/itemmodels/qsortfilterproxymodel.cpp @@ -275,7 +275,7 @@ public: const QVector &source_to_proxy, const QVector &source_items, int &proxy_low, int &proxy_high) const; - QModelIndexPairList store_persistent_indexes(); + QModelIndexPairList store_persistent_indexes() const; void update_persistent_indexes(const QModelIndexPairList &source_indexes); void filter_about_to_be_changed(const QModelIndex &source_parent = QModelIndex()); @@ -1014,9 +1014,9 @@ void QSortFilterProxyModelPrivate::build_source_to_proxy_mapping( Maps the persistent proxy indexes to source indexes and returns the list of source indexes. */ -QModelIndexPairList QSortFilterProxyModelPrivate::store_persistent_indexes() +QModelIndexPairList QSortFilterProxyModelPrivate::store_persistent_indexes() const { - Q_Q(QSortFilterProxyModel); + Q_Q(const QSortFilterProxyModel); QModelIndexPairList source_indexes; source_indexes.reserve(persistent.indexes.count()); for (QPersistentModelIndexData *data : qAsConst(persistent.indexes)) { diff --git a/src/corelib/kernel/qcoreapplication_win.cpp b/src/corelib/kernel/qcoreapplication_win.cpp index 9cd8420a32..601733b939 100644 --- a/src/corelib/kernel/qcoreapplication_win.cpp +++ b/src/corelib/kernel/qcoreapplication_win.cpp @@ -59,12 +59,12 @@ int appCmdShow = 0; Q_CORE_EXPORT QString qAppFileName() { - return QFileInfo(QCoreApplication::arguments().first()).filePath(); + return QFileInfo(QCoreApplication::arguments().constFirst()).filePath(); } QString QCoreApplicationPrivate::appName() const { - return QFileInfo(QCoreApplication::arguments().first()).baseName(); + return QFileInfo(QCoreApplication::arguments().constFirst()).baseName(); } #else diff --git a/src/corelib/kernel/qeventdispatcher_glib.cpp b/src/corelib/kernel/qeventdispatcher_glib.cpp index 8c2b47dccb..8ca2ac1c39 100644 --- a/src/corelib/kernel/qeventdispatcher_glib.cpp +++ b/src/corelib/kernel/qeventdispatcher_glib.cpp @@ -143,7 +143,7 @@ static gboolean timerSourceCheckHelper(GTimerSource *src) || (src->processEventsFlags & QEventLoop::X11ExcludeTimers)) return false; - if (src->timerList.updateCurrentTime() < src->timerList.first()->timeout) + if (src->timerList.updateCurrentTime() < src->timerList.constFirst()->timeout) return false; return true; diff --git a/src/corelib/kernel/qtimerinfo_unix.cpp b/src/corelib/kernel/qtimerinfo_unix.cpp index 8f5e8c9523..56337bdb45 100644 --- a/src/corelib/kernel/qtimerinfo_unix.cpp +++ b/src/corelib/kernel/qtimerinfo_unix.cpp @@ -591,7 +591,7 @@ int QTimerInfoList::activateTimers() if (isEmpty()) break; - QTimerInfo *currentTimerInfo = first(); + QTimerInfo *currentTimerInfo = constFirst(); if (currentTime < currentTimerInfo->timeout) break; // no timer has expired diff --git a/src/corelib/mimetypes/qmimedatabase.cpp b/src/corelib/mimetypes/qmimedatabase.cpp index da84523dcb..a32031a788 100644 --- a/src/corelib/mimetypes/qmimedatabase.cpp +++ b/src/corelib/mimetypes/qmimedatabase.cpp @@ -406,7 +406,7 @@ QMimeType QMimeDatabase::mimeTypeForFile(const QString &fileName, MatchMode mode { if (mode == MatchExtension) { QMutexLocker locker(&d->mutex); - QStringList matches = d->mimeTypeForFileName(fileName); + const QStringList matches = d->mimeTypeForFileName(fileName); const int matchCount = matches.count(); if (matchCount == 0) { return d->mimeTypeForName(d->defaultMimeType()); diff --git a/src/corelib/mimetypes/qmimeprovider.cpp b/src/corelib/mimetypes/qmimeprovider.cpp index 677e87077f..dc6eb05d9a 100644 --- a/src/corelib/mimetypes/qmimeprovider.cpp +++ b/src/corelib/mimetypes/qmimeprovider.cpp @@ -205,7 +205,7 @@ bool QMimeBinaryProvider::isValid() return false; // We found exactly one file; is it the user-modified mimes, or a system file? - const QString foundFile = m_cacheFiles.first()->file.fileName(); + const QString foundFile = m_cacheFiles.constFirst()->file.fileName(); const QString localCacheFile = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + QLatin1String("/mime/mime.cache"); return foundFile != localCacheFile; @@ -629,7 +629,7 @@ void QMimeBinaryProvider::loadMimeTypePrivate(QMimeTypePrivate &data) // Let's assume that shared-mime-info is at least version 0.70 // Otherwise we would need 1) a version check, and 2) code for parsing patterns from the globs file. #if 1 - if (!mainPattern.isEmpty() && (data.globPatterns.isEmpty() || data.globPatterns.first() != mainPattern)) { + if (!mainPattern.isEmpty() && (data.globPatterns.isEmpty() || data.globPatterns.constFirst() != mainPattern)) { // ensure it's first in the list of patterns data.globPatterns.removeAll(mainPattern); data.globPatterns.prepend(mainPattern); @@ -637,7 +637,7 @@ void QMimeBinaryProvider::loadMimeTypePrivate(QMimeTypePrivate &data) #else const bool globsInXml = sharedMimeInfoVersion() >= QT_VERSION_CHECK(0, 70, 0); if (globsInXml) { - if (!mainPattern.isEmpty() && data.globPatterns.first() != mainPattern) { + if (!mainPattern.isEmpty() && data.globPatterns.constFirst() != mainPattern) { // ensure it's first in the list of patterns data.globPatterns.removeAll(mainPattern); data.globPatterns.prepend(mainPattern); diff --git a/src/corelib/statemachine/qhistorystate.cpp b/src/corelib/statemachine/qhistorystate.cpp index c3361ad17e..338c89c688 100644 --- a/src/corelib/statemachine/qhistorystate.cpp +++ b/src/corelib/statemachine/qhistorystate.cpp @@ -209,6 +209,11 @@ QAbstractState *QHistoryState::defaultState() const return d->defaultTransition ? d->defaultTransition->targetState() : Q_NULLPTR; } +static inline bool isSoleEntry(const QList &states, const QAbstractState * state) +{ + return states.size() == 1 && states.first() == state; +} + /*! Sets this history state's default state to be the given \a state. \a state must be a sibling of this history state. @@ -224,9 +229,7 @@ void QHistoryState::setDefaultState(QAbstractState *state) "to this history state's group (%p)", state, parentState()); return; } - if (!d->defaultTransition - || d->defaultTransition->targetStates().size() != 1 - || d->defaultTransition->targetStates().first() != state) { + if (!d->defaultTransition || !isSoleEntry(d->defaultTransition->targetStates(), state)) { if (!d->defaultTransition || !qobject_cast(d->defaultTransition)) { d->defaultTransition = new DefaultStateTransition(this, state); emit defaultTransitionChanged(QHistoryState::QPrivateSignal()); diff --git a/src/corelib/statemachine/qstatemachine.cpp b/src/corelib/statemachine/qstatemachine.cpp index 62a4c03d26..d5b01f3c8a 100644 --- a/src/corelib/statemachine/qstatemachine.cpp +++ b/src/corelib/statemachine/qstatemachine.cpp @@ -692,7 +692,7 @@ void QStateMachinePrivate::microstep(QEvent *event, const QList= priority || + constLast().priority >= priority || insertionOffset >= size()) { // optimization: we can simply append if the last event in // the queue has higher or equal priority diff --git a/src/corelib/thread/qthreadpool.cpp b/src/corelib/thread/qthreadpool.cpp index 9230854600..7ce757064f 100644 --- a/src/corelib/thread/qthreadpool.cpp +++ b/src/corelib/thread/qthreadpool.cpp @@ -228,7 +228,7 @@ int QThreadPoolPrivate::activeThreadCount() const void QThreadPoolPrivate::tryToStartMoreThreads() { // try to push tasks on the queue to any available threads - while (!queue.isEmpty() && tryStart(queue.first().first)) + while (!queue.isEmpty() && tryStart(queue.constFirst().first)) queue.removeFirst(); } diff --git a/src/corelib/thread/qwaitcondition_win.cpp b/src/corelib/thread/qwaitcondition_win.cpp index f3a645c504..a95ca0b8fd 100644 --- a/src/corelib/thread/qwaitcondition_win.cpp +++ b/src/corelib/thread/qwaitcondition_win.cpp @@ -141,7 +141,7 @@ void QWaitConditionPrivate::post(QWaitConditionEvent *wce, bool ret) // wakeups delivered after the timeout should be forwarded to the next waiter if (!ret && wce->wokenUp && !queue.isEmpty()) { - QWaitConditionEvent *other = queue.first(); + QWaitConditionEvent *other = queue.constFirst(); SetEvent(other->event); other->wokenUp = true; } diff --git a/src/corelib/tools/qcommandlineparser.cpp b/src/corelib/tools/qcommandlineparser.cpp index 6587d900d2..a7ab8b9e70 100644 --- a/src/corelib/tools/qcommandlineparser.cpp +++ b/src/corelib/tools/qcommandlineparser.cpp @@ -887,7 +887,8 @@ QStringList QCommandLineParser::values(const QString &optionName) const bool QCommandLineParser::isSet(const QCommandLineOption &option) const { // option.names() might be empty if the constructor failed - return !option.names().isEmpty() && isSet(option.names().first()); + const auto names = option.names(); + return !names.isEmpty() && isSet(names.first()); } /*! @@ -905,7 +906,7 @@ bool QCommandLineParser::isSet(const QCommandLineOption &option) const */ QString QCommandLineParser::value(const QCommandLineOption &option) const { - return value(option.names().first()); + return value(option.names().constFirst()); } /*! @@ -923,7 +924,7 @@ QString QCommandLineParser::value(const QCommandLineOption &option) const */ QStringList QCommandLineParser::values(const QCommandLineOption &option) const { - return values(option.names().first()); + return values(option.names().constFirst()); } /*! diff --git a/src/corelib/tools/qeasingcurve.cpp b/src/corelib/tools/qeasingcurve.cpp index 2851dc81d6..4b5f5e7830 100644 --- a/src/corelib/tools/qeasingcurve.cpp +++ b/src/corelib/tools/qeasingcurve.cpp @@ -444,7 +444,7 @@ struct BezierEase : public QEasingCurveFunction void init() { - if (_bezierCurves.last() == QPointF(1.0, 1.0)) { + if (_bezierCurves.constLast() == QPointF(1.0, 1.0)) { _init = true; _curveCount = _bezierCurves.count() / 3; diff --git a/src/corelib/tools/qlocale_unix.cpp b/src/corelib/tools/qlocale_unix.cpp index 9b0d338e46..095001e0a3 100644 --- a/src/corelib/tools/qlocale_unix.cpp +++ b/src/corelib/tools/qlocale_unix.cpp @@ -122,7 +122,7 @@ QLocale QSystemLocale::fallbackUiLocale() const // the first part of LANGUAGE if LANGUAGE is set and has a first part: QByteArray language = qgetenv("LANGUAGE"); if (!language.isEmpty()) { - language = language.split(':').first(); + language = language.split(':').constFirst(); if (!language.isEmpty()) return QLocale(QString::fromLatin1(language)); } diff --git a/src/corelib/tools/qringbuffer.cpp b/src/corelib/tools/qringbuffer.cpp index db2004dfd9..4a2dfdec2b 100644 --- a/src/corelib/tools/qringbuffer.cpp +++ b/src/corelib/tools/qringbuffer.cpp @@ -74,14 +74,14 @@ void QRingBuffer::free(qint64 bytes) Q_ASSERT(bytes <= bufferSize); while (bytes > 0) { - const qint64 blockSize = buffers.first().size() - head; + const qint64 blockSize = buffers.constFirst().size() - head; if (tailBuffer == 0 || blockSize > bytes) { // keep a single block around if it does not exceed // the basic block size, to avoid repeated allocations // between uses of the buffer if (bufferSize <= bytes) { - if (buffers.first().size() <= basicBlockSize) { + if (buffers.constFirst().size() <= basicBlockSize) { bufferSize = 0; head = tail = 0; } else { @@ -114,8 +114,8 @@ char *QRingBuffer::reserve(qint64 bytes) } else { const qint64 newSize = bytes + tail; // if need buffer reallocation - if (newSize > buffers.last().size()) { - if (newSize > buffers.last().capacity() && (tail >= basicBlockSize + if (newSize > buffers.constLast().size()) { + if (newSize > buffers.constLast().capacity() && (tail >= basicBlockSize || newSize >= MaxByteArraySize)) { // shrink this buffer to its current size buffers.last().resize(tail); @@ -180,7 +180,7 @@ void QRingBuffer::chop(qint64 bytes) // the basic block size, to avoid repeated allocations // between uses of the buffer if (bufferSize <= bytes) { - if (buffers.first().size() <= basicBlockSize) { + if (buffers.constFirst().size() <= basicBlockSize) { bufferSize = 0; head = tail = 0; } else { @@ -198,7 +198,7 @@ void QRingBuffer::chop(qint64 bytes) bytes -= tail; buffers.removeLast(); --tailBuffer; - tail = buffers.last().size(); + tail = buffers.constLast().size(); } } diff --git a/src/corelib/tools/qtimezoneprivate_mac.mm b/src/corelib/tools/qtimezoneprivate_mac.mm index 14b0523ca7..3a665c2b00 100644 --- a/src/corelib/tools/qtimezoneprivate_mac.mm +++ b/src/corelib/tools/qtimezoneprivate_mac.mm @@ -243,7 +243,7 @@ QTimeZonePrivate::Data QMacTimeZonePrivate::previousTransition(qint64 beforeMSec } } if (secsList.size() >= 1) - return data(qint64(secsList.last()) * 1000); + return data(qint64(secsList.constLast()) * 1000); else return invalidData(); } -- cgit v1.2.3 From bdf2d7e0af79b0975fd5392d3b3248cb17989798 Mon Sep 17 00:00:00 2001 From: Anton Kudryavtsev Date: Tue, 12 Apr 2016 18:35:45 +0300 Subject: QStringListModel: proper construction of vector ... with known size and known value by corresponding ctor. Don't use appending for this case. Change-Id: I70f5b943cda7e55eeb45becf439f79c9aee77278 Reviewed-by: Edward Welbourne Reviewed-by: Marc Mutz --- src/corelib/itemmodels/qstringlistmodel.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/corelib/itemmodels/qstringlistmodel.cpp b/src/corelib/itemmodels/qstringlistmodel.cpp index 1a1b2b9fb6..f70c318ff7 100644 --- a/src/corelib/itemmodels/qstringlistmodel.cpp +++ b/src/corelib/itemmodels/qstringlistmodel.cpp @@ -187,7 +187,7 @@ bool QStringListModel::setData(const QModelIndex &index, const QVariant &value, if (index.row() >= 0 && index.row() < lst.size() && (role == Qt::EditRole || role == Qt::DisplayRole)) { lst.replace(index.row(), value.toString()); - emit dataChanged(index, index, QVector() << role); + emit dataChanged(index, index, QVector(1, role)); return true; } return false; -- cgit v1.2.3 From b3fcaea5f2b97d3f562add97aee48cbb469c875a Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Tue, 5 Apr 2016 18:19:47 +0200 Subject: make extra compiler targets depend on their respective compiler Change-Id: I6c04e0188137f6bbfeab243f00860b8ff079f69a Reviewed-by: Joerg Bornemann --- mkspecs/features/dbuscommon.pri | 3 +++ mkspecs/features/moc.prf | 6 +++--- mkspecs/features/qgltf.prf | 1 + mkspecs/features/qlalr.prf | 1 + mkspecs/features/qt_functions.prf | 8 ++++++++ mkspecs/features/resources.prf | 1 + mkspecs/features/uic.prf | 1 + mkspecs/features/wayland-scanner.prf | 8 ++++---- mkspecs/features/win32/dumpcpp.prf | 1 + .../auto/tools/qmake/testdata/quotedfilenames/quotedfilenames.pro | 2 +- 10 files changed, 24 insertions(+), 8 deletions(-) diff --git a/mkspecs/features/dbuscommon.pri b/mkspecs/features/dbuscommon.pri index 2f2e6b831f..d836b253dc 100644 --- a/mkspecs/features/dbuscommon.pri +++ b/mkspecs/features/dbuscommon.pri @@ -57,12 +57,14 @@ for(group, groups) { } $${group}_header.commands = $$QMAKE_QDBUSXML2CPP $$hdr_flags $$qdbusxml2cpp_option ${QMAKE_FILE_OUT}: ${QMAKE_FILE_IN} + $${group}_header.depends = $$QMAKE_QDBUSXML2CPP_EXE $${group}_header.output = ${QMAKE_FUNC_FILE_IN_qdbusOutputBasename}_$${dbus_type}.h $${group}_header.name = DBUSXML2CPP $${dbus_TYPE} HEADER ${QMAKE_FILE_IN} $${group}_header.variable_out = $${GROUP}_HEADERS $${group}_header.input = $$input_list $${group}_source.commands = $$QMAKE_QDBUSXML2CPP -i ${QMAKE_FILE_OUT_BASE}.h $$src_flags $$qdbusxml2cpp_option :${QMAKE_FILE_OUT} ${QMAKE_FILE_IN} + $${group}_source.depends = $$QMAKE_QDBUSXML2CPP_EXE $${group}_source.output = ${QMAKE_FUNC_FILE_IN_qdbusOutputBasename}_$${dbus_type}.cpp $${group}_source.name = DBUSXML2CPP $${dbus_TYPE} SOURCE ${QMAKE_FILE_IN} $${group}_source.variable_out = SOURCES @@ -70,6 +72,7 @@ for(group, groups) { $${group}_source.depends = $$eval($${group}_header.output) # this actually belongs to the object file $${group}_moc.commands = $$moc_header.commands + $${group}_moc.depends = $$QMAKE_MOC_EXE $${group}_moc.output = $$moc_header.output $${group}_moc.input = $${GROUP}_HEADERS $${group}_moc.variable_out = GENERATED_SOURCES diff --git a/mkspecs/features/moc.prf b/mkspecs/features/moc.prf index 8e8deec63c..8ddfc38c63 100644 --- a/mkspecs/features/moc.prf +++ b/mkspecs/features/moc.prf @@ -67,9 +67,9 @@ INCREDIBUILD_XGE += moc_source INCLUDEPATH += $$absolute_path($$MOC_DIR, $$OUT_PWD) #auto depend on moc -unix:!no_mocdepend { - moc_source.depends += $$first(QMAKE_MOC) - moc_header.depends += $$first(QMAKE_MOC) +!no_mocdepend { + moc_source.depends += $$QMAKE_MOC_EXE + moc_header.depends += $$QMAKE_MOC_EXE } #generate a mocclean diff --git a/mkspecs/features/qgltf.prf b/mkspecs/features/qgltf.prf index c62e8c2ee8..4a6d16f520 100644 --- a/mkspecs/features/qgltf.prf +++ b/mkspecs/features/qgltf.prf @@ -5,6 +5,7 @@ isEmpty(QGLTF_DIR): QGLTF_DIR = . qgltf.input = QT3D_MODELS qgltf.output = $$QGLTF_DIR/${QMAKE_FILE_BASE}.qrc qgltf.variable_out += RESOURCES +qgltf.depends = $$QMAKE_QGLTF_EXE qgltf.commands = $$QMAKE_QGLTF -d $$QGLTF_DIR $$QGLTF_PARAMS ${QMAKE_FILE_NAME} silent: qgltf.commands = @echo qgltf ${QMAKE_FILE_IN} && $$qgltf.commands -s qgltf.CONFIG += no_link diff --git a/mkspecs/features/qlalr.prf b/mkspecs/features/qlalr.prf index e5e4b87802..5f0f3794cb 100644 --- a/mkspecs/features/qlalr.prf +++ b/mkspecs/features/qlalr.prf @@ -23,6 +23,7 @@ for (s, QLALRSOURCES) { $${base}.input = $$invar $${base}.output = $$QLALR_DIR/$${parser}.cpp $${base}.variable_out = GENERATED_SOURCES + $${base}.depends = $$QMAKE_QLALR_EXE $${base}.commands = $$QMAKE_QLALR $$QMAKE_QLALRFLAGS ${QMAKE_FILE_IN} silent: $${base}.commands = @echo qlalr ${QMAKE_FILE_IN} && $${base}.commands $${base}.name = QLALR ${QMAKE_FILE_IN} diff --git a/mkspecs/features/qt_functions.prf b/mkspecs/features/qt_functions.prf index 9c3414c6fc..cfac583ba8 100644 --- a/mkspecs/features/qt_functions.prf +++ b/mkspecs/features/qt_functions.prf @@ -73,16 +73,24 @@ defineTest(qtPrepareTool) { isEmpty(cmd) { cmd = $$[QT_HOST_BINS]/$$2 exists($${cmd}.pl) { + $${1}_EXE = $${cmd}.pl cmd = perl -w $$system_path($${cmd}.pl) } else: contains(QMAKE_HOST.os, Windows) { + $${1}_EXE = $${cmd}.exe cmd = $$system_path($${cmd}.exe) } else:contains(QMAKE_HOST.os, Darwin) { BUNDLENAME = $${cmd}.app/Contents/MacOS/$$2 exists($$BUNDLENAME) { cmd = $$BUNDLENAME } + $${1}_EXE = $$cmd + } else { + $${1}_EXE = $$cmd } + } else { + $${1}_EXE = $$last(cmd) } + export($${1}_EXE) QT_TOOL_ENV += $$eval(QT_TOOL.$${2}.envvars) QT_TOOL_NAME = $$2 !isEmpty(3)|!isEmpty(4) { diff --git a/mkspecs/features/resources.prf b/mkspecs/features/resources.prf index 1f04c8b0d7..6d0a3187d8 100644 --- a/mkspecs/features/resources.prf +++ b/mkspecs/features/resources.prf @@ -103,6 +103,7 @@ rcc.clean += $$RCC_CPP $$RCC_TMP } +rcc.depends = $$QMAKE_RCC_EXE silent:rcc.commands = @echo rcc ${QMAKE_FILE_IN} && $$rcc.commands else:rcc.commands ~= s/&&/$$escape_expand(\\n\\t)/g QMAKE_EXTRA_COMPILERS += rcc diff --git a/mkspecs/features/uic.prf b/mkspecs/features/uic.prf index c6a64050e0..e6d8b9cc83 100644 --- a/mkspecs/features/uic.prf +++ b/mkspecs/features/uic.prf @@ -3,6 +3,7 @@ qtPrepareTool(QMAKE_UIC, uic, _DEP) isEmpty(UI_DIR):UI_DIR = . isEmpty(QMAKE_MOD_UIC):QMAKE_MOD_UIC = ui_ +uic.depends = $$QMAKE_UIC_EXE uic.commands = $$QMAKE_UIC ${QMAKE_FILE_IN} -o ${QMAKE_FILE_OUT} uic.depend_command = $$QMAKE_UIC_DEP -d ${QMAKE_FILE_IN} uic.output = $$UI_DIR/$${QMAKE_MOD_UIC}${QMAKE_FILE_BASE}$${first(QMAKE_EXT_H)} diff --git a/mkspecs/features/wayland-scanner.prf b/mkspecs/features/wayland-scanner.prf index 5a97d98373..ce833f1c08 100644 --- a/mkspecs/features/wayland-scanner.prf +++ b/mkspecs/features/wayland-scanner.prf @@ -78,7 +78,7 @@ qtPrepareTool(QMAKE_QTWAYLANDSCANNER, qtwaylandscanner) qtwayland_client_header.name = qtwayland ${QMAKE_FILE_BASE} qtwayland_client_header.input = WAYLANDCLIENTSOURCES qtwayland_client_header.variable_out = HEADERS -qtwayland_client_header.depends = $${WAYLAND_CLIENT_HEADER_DEST}wayland-${QMAKE_FILE_BASE}-client-protocol$${first(QMAKE_EXT_H)} +qtwayland_client_header.depends = $$QMAKE_QTWAYLANDSCANNER_EXE $${WAYLAND_CLIENT_HEADER_DEST}wayland-${QMAKE_FILE_BASE}-client-protocol$${first(QMAKE_EXT_H)} qtwayland_client_header.output = $${WAYLAND_CLIENT_HEADER_DEST}qwayland-${QMAKE_FILE_BASE}$${first(QMAKE_EXT_H)} qtwayland_client_header.commands = $$QMAKE_QTWAYLANDSCANNER client-header ${QMAKE_FILE_IN} $$WAYLAND_CLIENT_INCLUDE_DIR > ${QMAKE_FILE_OUT} silent:qtwayland_client_header.commands = @echo QtWayland client header ${QMAKE_FILE_IN} && $$qtwayland_client_header.commands @@ -87,7 +87,7 @@ QMAKE_EXTRA_COMPILERS += qtwayland_client_header qtwayland_client_code.name = qtwayland ${QMAKE_FILE_BASE} qtwayland_client_code.input = WAYLANDCLIENTSOURCES qtwayland_client_code.variable_out = SOURCES -qtwayland_client_code.depends = $${WAYLAND_CLIENT_HEADER_DEST}qwayland-${QMAKE_FILE_BASE}$${first(QMAKE_EXT_H)} +qtwayland_client_code.depends = $$QMAKE_QTWAYLANDSCANNER_EXE $${WAYLAND_CLIENT_HEADER_DEST}qwayland-${QMAKE_FILE_BASE}$${first(QMAKE_EXT_H)} qtwayland_client_code.output = qwayland-${QMAKE_FILE_BASE}.cpp qtwayland_client_code.commands = $$QMAKE_QTWAYLANDSCANNER client-code ${QMAKE_FILE_IN} $$WAYLAND_CLIENT_INCLUDE_DIR > ${QMAKE_FILE_OUT} silent:qtwayland_client_code.commands = @echo QtWayland client code ${QMAKE_FILE_IN} && $$qtwayland_client_code.commands @@ -96,7 +96,7 @@ QMAKE_EXTRA_COMPILERS += qtwayland_client_code qtwayland_server_header.name = qtwayland ${QMAKE_FILE_BASE} qtwayland_server_header.input = WAYLANDSERVERSOURCES qtwayland_server_header.variable_out = HEADERS -qtwayland_server_header.depends = $${WAYLAND_SERVER_HEADER_DEST}wayland-${QMAKE_FILE_BASE}-server-protocol$${first(QMAKE_EXT_H)} +qtwayland_server_header.depends = $$QMAKE_QTWAYLANDSCANNER_EXE $${WAYLAND_SERVER_HEADER_DEST}wayland-${QMAKE_FILE_BASE}-server-protocol$${first(QMAKE_EXT_H)} qtwayland_server_header.output = $${WAYLAND_SERVER_HEADER_DEST}qwayland-server-${QMAKE_FILE_BASE}$${first(QMAKE_EXT_H)} qtwayland_server_header.commands = $$QMAKE_QTWAYLANDSCANNER server-header ${QMAKE_FILE_IN} $$WAYLAND_SERVER_INCLUDE_DIR > ${QMAKE_FILE_OUT} silent:qtwayland_server_header.commands = @echo QtWayland server header ${QMAKE_FILE_IN} && $$qtwayland_server_header.commands @@ -105,7 +105,7 @@ QMAKE_EXTRA_COMPILERS += qtwayland_server_header qtwayland_server_code.name = qtwayland ${QMAKE_FILE_BASE} qtwayland_server_code.input = WAYLANDSERVERSOURCES qtwayland_server_code.variable_out = SOURCES -qtwayland_server_code.depends = $${WAYLAND_SERVER_HEADER_DEST}qwayland-server-${QMAKE_FILE_BASE}$${first(QMAKE_EXT_H)} +qtwayland_server_code.depends = $$QMAKE_QTWAYLANDSCANNER_EXE $${WAYLAND_SERVER_HEADER_DEST}qwayland-server-${QMAKE_FILE_BASE}$${first(QMAKE_EXT_H)} qtwayland_server_code.output = qwayland-server-${QMAKE_FILE_BASE}.cpp qtwayland_server_code.commands = $$QMAKE_QTWAYLANDSCANNER server-code ${QMAKE_FILE_IN} $$WAYLAND_SERVER_INCLUDE_DIR > ${QMAKE_FILE_OUT} silent:qtwayland_server_code.commands = @echo QtWayland server code ${QMAKE_FILE_IN} && $$qtwayland_server_code.commands diff --git a/mkspecs/features/win32/dumpcpp.prf b/mkspecs/features/win32/dumpcpp.prf index 61fd386832..eb2e84d753 100644 --- a/mkspecs/features/win32/dumpcpp.prf +++ b/mkspecs/features/win32/dumpcpp.prf @@ -1,5 +1,6 @@ qtPrepareTool(QMAKE_DUMPCPP, dumpcpp) +dumpcpp_decl.depends = $$QMAKE_DUMPCPP_EXE dumpcpp_decl.commands = $$QMAKE_DUMPCPP ${QMAKE_FILE_IN} -o ${QMAKE_FILE_BASE} qaxcontainer_compat: dumpcpp_decl.commands += -compat dumpcpp_decl.output = ${QMAKE_FILE_BASE}.h diff --git a/tests/auto/tools/qmake/testdata/quotedfilenames/quotedfilenames.pro b/tests/auto/tools/qmake/testdata/quotedfilenames/quotedfilenames.pro index c4e0257769..a4d20cc0f5 100644 --- a/tests/auto/tools/qmake/testdata/quotedfilenames/quotedfilenames.pro +++ b/tests/auto/tools/qmake/testdata/quotedfilenames/quotedfilenames.pro @@ -17,7 +17,7 @@ rcc_test.input = RCCINPUT rcc_test.variable_out = SOURCES rcc_test.name = RCC_TEST rcc_test.CONFIG += no_link -rcc_test.depends = $$QMAKE_RCC +rcc_test.depends = $$QMAKE_RCC_EXE QMAKE_EXTRA_COMPILERS += rcc_test -- cgit v1.2.3