summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/3rdparty/double-conversion/include/double-conversion/utils.h3
-rw-r--r--src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java17
-rw-r--r--src/android/java/src/org/qtproject/qt5/android/bindings/QtActivityLoader.java2
-rw-r--r--src/android/java/src/org/qtproject/qt5/android/bindings/QtApplication.java5
-rw-r--r--src/android/java/src/org/qtproject/qt5/android/bindings/QtLoader.java6
-rw-r--r--src/android/java/src/org/qtproject/qt5/android/bindings/QtServiceLoader.java2
-rw-r--r--src/corelib/global/qglobal.cpp14
-rw-r--r--src/corelib/global/qnamespace.h2
-rw-r--r--src/corelib/global/qnamespace.qdoc7
-rw-r--r--src/corelib/io/qipaddress.cpp3
-rw-r--r--src/corelib/io/qlockfile_p.h3
-rw-r--r--src/corelib/io/qlockfile_unix.cpp2
-rw-r--r--src/corelib/io/qprocess.cpp6
-rw-r--r--src/corelib/io/qresource.cpp6
-rw-r--r--src/corelib/io/qsettings_mac.cpp4
-rw-r--r--src/corelib/io/qstandardpaths_mac.mm2
-rw-r--r--src/corelib/itemmodels/qabstractitemmodel.cpp12
-rw-r--r--src/corelib/itemmodels/qitemselectionmodel.cpp2
-rw-r--r--src/corelib/itemmodels/qsortfilterproxymodel.cpp6
-rw-r--r--src/corelib/itemmodels/qstringlistmodel.cpp2
-rw-r--r--src/corelib/kernel/qcoreapplication_win.cpp4
-rw-r--r--src/corelib/kernel/qeventdispatcher_glib.cpp2
-rw-r--r--src/corelib/kernel/qtimerinfo_unix.cpp2
-rw-r--r--src/corelib/mimetypes/qmimedatabase.cpp2
-rw-r--r--src/corelib/mimetypes/qmimeprovider.cpp6
-rw-r--r--src/corelib/statemachine/qhistorystate.cpp9
-rw-r--r--src/corelib/statemachine/qsignaltransition.cpp5
-rw-r--r--src/corelib/statemachine/qstatemachine.cpp2
-rw-r--r--src/corelib/thread/qthread_p.h2
-rw-r--r--src/corelib/thread/qthreadpool.cpp2
-rw-r--r--src/corelib/thread/qwaitcondition_win.cpp2
-rw-r--r--src/corelib/tools/qbytearray.h36
-rw-r--r--src/corelib/tools/qcommandlineparser.cpp7
-rw-r--r--src/corelib/tools/qdatetimeparser.cpp29
-rw-r--r--src/corelib/tools/qdatetimeparser_p.h13
-rw-r--r--src/corelib/tools/qeasingcurve.cpp2
-rw-r--r--src/corelib/tools/qelapsedtimer_generic.cpp22
-rw-r--r--src/corelib/tools/qlocale.cpp6
-rw-r--r--src/corelib/tools/qlocale_unix.cpp2
-rw-r--r--src/corelib/tools/qringbuffer.cpp12
-rw-r--r--src/corelib/tools/qstring.cpp10
-rw-r--r--src/corelib/tools/qtimezoneprivate_mac.mm2
-rw-r--r--src/dbus/qdbusconnection_p.h1
-rw-r--r--src/dbus/qdbusintegrator.cpp26
-rw-r--r--src/gui/image/qiconloader.cpp1
-rw-r--r--src/gui/kernel/qguiapplication.cpp4
-rw-r--r--src/gui/opengl/qopenglfunctions.cpp4
-rw-r--r--src/gui/painting/qoutlinemapper.cpp52
-rw-r--r--src/gui/painting/qoutlinemapper_p.h23
-rw-r--r--src/gui/painting/qpaintengine_raster.cpp6
-rw-r--r--src/gui/text/qtextlayout.cpp19
-rw-r--r--src/network/access/qnetworkreply.cpp2
-rw-r--r--src/network/access/qnetworkrequest.cpp10
-rw-r--r--src/network/bearer/qnetworkconfigmanager_p.cpp2
-rw-r--r--src/network/kernel/qnetworkinterface_winrt.cpp1
-rw-r--r--src/network/kernel/qnetworkproxy_win.cpp15
-rw-r--r--src/network/network.pro4
-rw-r--r--src/network/socket/qnativesocketengine_winrt.cpp122
-rw-r--r--src/platformsupport/dbustray/qdbustrayicon.cpp18
-rw-r--r--src/plugins/platforms/android/qandroidplatformtheme.cpp3
-rw-r--r--src/plugins/platforms/cocoa/qnsview.mm5
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/deviceintegration.pro7
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/eglfs_kms.pro36
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmcursor.cpp (renamed from src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmscursor.cpp)23
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmcursor.h (renamed from src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmscursor.h)16
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmdevice.cpp158
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmdevice.h90
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmintegration.cpp143
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmintegration.h75
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmmain.cpp (renamed from src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsmain.cpp)9
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmscreen.cpp223
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmscreen.h93
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/eglfs_kms_egldevice.pro21
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevice.cpp79
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevice.h61
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldeviceintegration.cpp230
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldeviceintegration.h46
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevicescreen.cpp78
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevicescreen.h56
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/eglfs_kms_support.pro28
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsdevice.cpp (renamed from src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsdevice.cpp)81
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsdevice.h (renamed from src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsdevice.h)30
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsintegration.cpp (renamed from src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsintegration.cpp)82
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsintegration.h (renamed from src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsintegration.h)22
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsscreen.cpp (renamed from src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsscreen.cpp)141
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsscreen.h (renamed from src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsscreen.h)29
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_viv/qeglfsvivintegration.cpp8
-rw-r--r--src/plugins/platforms/eglfs/qeglfsdeviceintegration.cpp10
-rw-r--r--src/plugins/platforms/eglfs/qeglfshooks.cpp2
-rw-r--r--src/plugins/platforms/windows/qwindowsfontdatabase.cpp83
-rw-r--r--src/plugins/platforms/windows/qwindowsfontenginedirectwrite.cpp206
-rw-r--r--src/plugins/platforms/windows/qwindowsfontenginedirectwrite.h3
-rw-r--r--src/plugins/platforms/windows/windows.pri3
-rw-r--r--src/plugins/platforms/winrt/qwinrtscreen.cpp50
-rw-r--r--src/plugins/platforms/xcb/qxcbbackingstore.cpp37
-rw-r--r--src/testlib/qtest.h3
-rw-r--r--src/testlib/qtest_gui.h3
-rw-r--r--src/testlib/qtestcase.cpp1
-rw-r--r--src/testlib/qtestcase.qdoc1
-rw-r--r--src/tools/moc/generator.cpp8
-rw-r--r--src/tools/moc/main.cpp2
-rw-r--r--src/tools/moc/moc.cpp28
-rw-r--r--src/tools/moc/preprocessor.cpp18
-rw-r--r--src/tools/rcc/main.cpp5
-rw-r--r--src/widgets/itemviews/qheaderview.cpp3
-rw-r--r--src/widgets/itemviews/qtreeview.cpp2
-rw-r--r--src/widgets/kernel/qapplication.cpp2
-rw-r--r--src/widgets/util/qundostack.cpp2
-rw-r--r--src/widgets/widgets/qcombobox.cpp8
-rw-r--r--src/widgets/widgets/qcombobox.h1
-rw-r--r--src/widgets/widgets/qdatetimeedit.cpp17
-rw-r--r--src/widgets/widgets/qdatetimeedit.h2
-rw-r--r--src/widgets/widgets/qdatetimeedit_p.h27
-rw-r--r--src/widgets/widgets/qlineedit.cpp16
-rw-r--r--src/widgets/widgets/qlineedit.h1
-rw-r--r--src/widgets/widgets/qplaintextedit.cpp21
-rw-r--r--src/widgets/widgets/qtextedit.cpp21
-rw-r--r--src/widgets/widgets/qwidgetlinecontrol.cpp33
-rw-r--r--src/widgets/widgets/qwidgetlinecontrol_p.h2
-rw-r--r--src/widgets/widgets/qwidgettextcontrol.cpp16
120 files changed, 2081 insertions, 1024 deletions
diff --git a/src/3rdparty/double-conversion/include/double-conversion/utils.h b/src/3rdparty/double-conversion/include/double-conversion/utils.h
index 01f1dbd3ae..20bfd36c84 100644
--- a/src/3rdparty/double-conversion/include/double-conversion/utils.h
+++ b/src/3rdparty/double-conversion/include/double-conversion/utils.h
@@ -74,6 +74,9 @@
#else
#undef DOUBLE_CONVERSION_CORRECT_DOUBLE_OPERATIONS
#endif // _WIN32
+#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
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 ac471bf126..0cfce2c6af 100644
--- a/src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java
+++ b/src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java
@@ -153,16 +153,15 @@ public class QtActivityDelegate
m_activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
m_activity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);
try {
- int flags = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
- flags |= View.SYSTEM_UI_FLAG_LAYOUT_STABLE;
- flags |= View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION;
- flags |= View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
- flags |= View.SYSTEM_UI_FLAG_FULLSCREEN;
-
- if (Build.VERSION.SDK_INT >= 19)
+ if (Build.VERSION.SDK_INT >= 19) {
+ int flags = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
+ flags |= View.SYSTEM_UI_FLAG_LAYOUT_STABLE;
+ flags |= View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION;
+ flags |= View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
+ flags |= View.SYSTEM_UI_FLAG_FULLSCREEN;
flags |= View.class.getDeclaredField("SYSTEM_UI_FLAG_IMMERSIVE_STICKY").getInt(null);
-
- m_activity.getWindow().getDecorView().setSystemUiVisibility(flags | View.INVISIBLE);
+ m_activity.getWindow().getDecorView().setSystemUiVisibility(flags | View.INVISIBLE);
+ }
} catch (Exception e) {
e.printStackTrace();
}
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;
}
diff --git a/src/corelib/global/qglobal.cpp b/src/corelib/global/qglobal.cpp
index 2bd87626c2..7e4e09c6c7 100644
--- a/src/corelib/global/qglobal.cpp
+++ b/src/corelib/global/qglobal.cpp
@@ -1183,13 +1183,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
diff --git a/src/corelib/global/qnamespace.h b/src/corelib/global/qnamespace.h
index 268f555c25..c8699c15fe 100644
--- a/src/corelib/global/qnamespace.h
+++ b/src/corelib/global/qnamespace.h
@@ -1339,7 +1339,7 @@ public:
ImPlatformData = 0x80000000,
ImQueryInput = ImCursorRectangle | ImCursorPosition | ImSurroundingText |
- ImCurrentSelection | ImAnchorPosition,
+ ImCurrentSelection | ImAnchorRectangle | ImAnchorPosition,
ImQueryAll = 0xffffffff
};
Q_DECLARE_FLAGS(InputMethodQueries, InputMethodQuery)
diff --git a/src/corelib/global/qnamespace.qdoc b/src/corelib/global/qnamespace.qdoc
index f028cff6e4..13e2b55e2a 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.
+
\value AA_DontCheckOpenGLContextThreadAffinity When making a context
current using QOpenGLContext, do not check that the
\l{QObject#Thread Affinity}{QObject thread affinity}
@@ -2575,6 +2580,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/io/qipaddress.cpp b/src/corelib/io/qipaddress.cpp
index 13636ebb8b..02b12f635a 100644
--- a/src/corelib/io/qipaddress.cpp
+++ b/src/corelib/io/qipaddress.cpp
@@ -117,6 +117,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/src/corelib/io/qlockfile_p.h b/src/corelib/io/qlockfile_p.h
index b41b9b4604..d7f2a1d52d 100644
--- a/src/corelib/io/qlockfile_p.h
+++ b/src/corelib/io/qlockfile_p.h
@@ -81,7 +81,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/corelib/io/qlockfile_unix.cpp b/src/corelib/io/qlockfile_unix.cpp
index 3455305858..7255414bdc 100644
--- a/src/corelib/io/qlockfile_unix.cpp
+++ b/src/corelib/io/qlockfile_unix.cpp
@@ -148,6 +148,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/src/corelib/io/qprocess.cpp b/src/corelib/io/qprocess.cpp
index 8b794df6df..439f9fce5a 100644
--- a/src/corelib/io/qprocess.cpp
+++ b/src/corelib/io/qprocess.cpp
@@ -2297,8 +2297,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);
}
@@ -2540,8 +2539,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/corelib/io/qresource.cpp b/src/corelib/io/qresource.cpp
index ad24b43568..1ead114235 100644
--- a/src/corelib/io/qresource.cpp
+++ b/src/corelib/io/qresource.cpp
@@ -1259,8 +1259,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/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<CFPropertyListRef> 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<CFPropertyListRef> 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<CFURLRef> 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<QAbstractItemModel *>(index.model());
QHash<QModelIndex, QPersistentModelIndexData *> &indexes = model->d_func()->persistent.indexes;
- const QHash<QModelIndex, QPersistentModelIndexData *>::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 QList<QPersiste
// optimization for when all indexes are selected
// (only if there is lots of items (1000) because this is not entirely correct)
if (ranges.isEmpty() && currentSelection.count() == 1) {
- QItemSelectionRange range = currentSelection.first();
+ QItemSelectionRange range = currentSelection.constFirst();
QModelIndex parent = range.parent();
tableRowCount = model->rowCount(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<int> &source_to_proxy, const QVector<int> &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/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<int>() << role);
+ emit dataChanged(index, index, QVector<int>(1, role));
return true;
}
return false;
diff --git a/src/corelib/kernel/qcoreapplication_win.cpp b/src/corelib/kernel/qcoreapplication_win.cpp
index 61576daba2..8ad4ba273c 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<QAbstractState*> &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<DefaultStateTransition*>(d->defaultTransition)) {
d->defaultTransition = new DefaultStateTransition(this, state);
emit defaultTransitionChanged(QHistoryState::QPrivateSignal());
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/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<QAbstractTransit
// Add "implicit" assignments for restored properties to the first
// (outermost) entered state
Q_ASSERT(!enteredStates.isEmpty());
- QAbstractState *s = enteredStates.first();
+ QAbstractState *s = enteredStates.constFirst();
assignmentsForEnteredStates[s] << restorablesToPropertyList(pendingRestorables);
}
diff --git a/src/corelib/thread/qthread_p.h b/src/corelib/thread/qthread_p.h
index 5f7d01f50f..adcd98b609 100644
--- a/src/corelib/thread/qthread_p.h
+++ b/src/corelib/thread/qthread_p.h
@@ -121,7 +121,7 @@ public:
void addEvent(const QPostEvent &ev) {
int priority = ev.priority;
if (isEmpty() ||
- last().priority >= 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 34db71808d..e6610f18c8 100644
--- a/src/corelib/thread/qwaitcondition_win.cpp
+++ b/src/corelib/thread/qwaitcondition_win.cpp
@@ -136,7 +136,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/qbytearray.h b/src/corelib/tools/qbytearray.h
index 35efd5d6a9..97c44629eb 100644
--- a/src/corelib/tools/qbytearray.h
+++ b/src/corelib/tools/qbytearray.h
@@ -600,41 +600,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)
diff --git a/src/corelib/tools/qcommandlineparser.cpp b/src/corelib/tools/qcommandlineparser.cpp
index c0bd132fc3..2450484ce9 100644
--- a/src/corelib/tools/qcommandlineparser.cpp
+++ b/src/corelib/tools/qcommandlineparser.cpp
@@ -901,7 +901,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());
}
/*!
@@ -919,7 +920,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());
}
/*!
@@ -937,7 +938,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/qdatetimeparser.cpp b/src/corelib/tools/qdatetimeparser.cpp
index 867aea4184..c1abdf11a7 100644
--- a/src/corelib/tools/qdatetimeparser.cpp
+++ b/src/corelib/tools/qdatetimeparser.cpp
@@ -167,7 +167,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();
@@ -633,6 +633,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());
@@ -987,33 +991,27 @@ 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;
}
}
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) {
@@ -1025,8 +1023,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;
@@ -1054,7 +1053,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
@@ -1313,7 +1312,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 ad403f695b..9689d88616 100644
--- a/src/corelib/tools/qdatetimeparser_p.h
+++ b/src/corelib/tools/qdatetimeparser_p.h
@@ -120,14 +120,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,
@@ -138,7 +144,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 {
@@ -224,6 +230,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/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/qelapsedtimer_generic.cpp b/src/corelib/tools/qelapsedtimer_generic.cpp
index e053d4ced4..8c724247be 100644
--- a/src/corelib/tools/qelapsedtimer_generic.cpp
+++ b/src/corelib/tools/qelapsedtimer_generic.cpp
@@ -85,7 +85,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
@@ -93,7 +94,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
{
@@ -106,8 +107,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.
@@ -121,10 +124,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
{
@@ -172,7 +177,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()
*/
diff --git a/src/corelib/tools/qlocale.cpp b/src/corelib/tools/qlocale.cpp
index 241d3808a1..52f82827f2 100644
--- a/src/corelib/tools/qlocale.cpp
+++ b/src/corelib/tools/qlocale.cpp
@@ -1831,7 +1831,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
@@ -1862,7 +1862,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
@@ -1895,7 +1895,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
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/qstring.cpp b/src/corelib/tools/qstring.cpp
index 92d187c3ec..12fb30593c 100644
--- a/src/corelib/tools/qstring.cpp
+++ b/src/corelib/tools/qstring.cpp
@@ -5841,7 +5841,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, ...)
{
@@ -5897,7 +5899,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)
{
@@ -10609,7 +10613,7 @@ float QStringRef::toFloat(bool *ok) const
\obsolete
\fn QString Qt::escape(const QString &plain)
- \sa QString::toHtmlEscaped()
+ Use QString::toHtmlEscaped() instead.
*/
/*!
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();
}
diff --git a/src/dbus/qdbusconnection_p.h b/src/dbus/qdbusconnection_p.h
index 83a2e6fc32..b2fa8faae8 100644
--- a/src/dbus/qdbusconnection_p.h
+++ b/src/dbus/qdbusconnection_p.h
@@ -259,6 +259,7 @@ private:
const QVector<int> &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 105714ee64..6d4a27cdb5 100644
--- a/src/dbus/qdbusintegrator.cpp
+++ b/src/dbus/qdbusintegrator.cpp
@@ -1055,7 +1055,6 @@ QDBusConnectionPrivate::~QDBusConnectionPrivate()
qPrintable(name));
closeConnection();
- rootNode.children.clear(); // free resources
qDeleteAll(cachedMetaObjects);
if (mode == ClientMode || mode == PeerMode) {
@@ -1077,6 +1076,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);
@@ -1100,6 +1112,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()
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/kernel/qguiapplication.cpp b/src/gui/kernel/qguiapplication.cpp
index 1f102dcec5..239c5e135b 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/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 <qpa/qplatformintegration.h>
#include <QtCore/qloggingcategory.h>
+#ifdef Q_OS_INTEGRITY
+#include <EGL/egl.h>
+#endif
+
#ifndef GL_FRAMEBUFFER_SRGB_CAPABLE_EXT
#define GL_FRAMEBUFFER_SRGB_CAPABLE_EXT 0x8DBA
#endif
diff --git a/src/gui/painting/qoutlinemapper.cpp b/src/gui/painting/qoutlinemapper.cpp
index 9eb6ee93f2..7245b44fc7 100644
--- a/src/gui/painting/qoutlinemapper.cpp
+++ b/src/gui/painting/qoutlinemapper.cpp
@@ -38,9 +38,10 @@
****************************************************************************/
#include "qoutlinemapper_p.h"
-#include <private/qpainterpath_p.h>
+
+#include "qbezier_p.h"
#include "qmath.h"
-#include <private/qbezier_p.h>
+#include "qpainterpath_p.h"
#include <stdlib.h>
@@ -187,38 +188,26 @@ 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);
- }
+ 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 = QTransform(m_m11, m_m12, m_m13, m_m21, m_m22, m_m23, m_dx, m_dy, m_m33).map(path);
+ path = m_transform.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())
+ if (path.isEmpty()) {
m_valid = false;
- else
+ } else {
+ QTransform oldTransform = m_transform;
+ m_transform.reset();
convertPath(path);
- m_txop = old_txop;
+ m_transform = oldTransform;
+ }
return;
}
@@ -387,13 +376,14 @@ 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())
+ if (clippedPath.isEmpty()) {
m_valid = false;
- else
+ } else {
+ QTransform oldTransform = m_transform;
+ m_transform.reset();
convertPath(clippedPath);
- m_txop = old_txop;
+ m_transform = oldTransform;
+ }
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;
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 &region, Qt::ClipOperation op)
*/
-///*!
-// \internal
-//*/
+/*!
+ \internal
+*/
void QRasterPaintEngine::fillPath(const QPainterPath &path, QSpanData *fillData)
{
#ifdef QT_DEBUG_DRAW
diff --git a/src/gui/text/qtextlayout.cpp b/src/gui/text/qtextlayout.cpp
index 83f2a9bc25..f5827bb683 100644
--- a/src/gui/text/qtextlayout.cpp
+++ b/src/gui/text/qtextlayout.cpp
@@ -2151,7 +2151,6 @@ static QGlyphRun glyphRunWithInfo(QFontEngine *fontEngine,
QGlyphRunPrivate *d = QGlyphRunPrivate::get(glyphRun);
int rangeStart = textPosition;
- logClusters += textPosition;
while (*logClusters != glyphsStart && rangeStart < textPosition + textLength) {
++logClusters;
++rangeStart;
@@ -2360,9 +2359,9 @@ QList<QGlyphRun> 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();
@@ -2390,9 +2389,9 @@ QList<QGlyphRun> 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 {
@@ -2406,9 +2405,9 @@ QList<QGlyphRun> 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);
}
diff --git a/src/network/access/qnetworkreply.cpp b/src/network/access/qnetworkreply.cpp
index 876e095a0c..3f17b68e79 100644
--- a/src/network/access/qnetworkreply.cpp
+++ b/src/network/access/qnetworkreply.cpp
@@ -141,10 +141,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 f674cd5c2e..2ee85fd049 100644
--- a/src/network/access/qnetworkrequest.cpp
+++ b/src/network/access/qnetworkrequest.cpp
@@ -146,11 +146,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.
@@ -271,6 +272,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
diff --git a/src/network/bearer/qnetworkconfigmanager_p.cpp b/src/network/bearer/qnetworkconfigmanager_p.cpp
index 232875f43c..f2a79319a1 100644
--- a/src/network/bearer/qnetworkconfigmanager_p.cpp
+++ b/src/network/bearer/qnetworkconfigmanager_p.cpp
@@ -420,6 +420,8 @@ void QNetworkConfigurationManagerPrivate::updateConfigurations()
if (generic) {
if (!envOK || skipGeneric <= 0)
sessionEngines.append(generic);
+ else
+ delete generic;
}
}
diff --git a/src/network/kernel/qnetworkinterface_winrt.cpp b/src/network/kernel/qnetworkinterface_winrt.cpp
index 1cbc4d686f..24ac3df52f 100644
--- a/src/network/kernel/qnetworkinterface_winrt.cpp
+++ b/src/network/kernel/qnetworkinterface_winrt.cpp
@@ -92,6 +92,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<INetworkAdapter> adapter;
hr = profile->get_NetworkAdapter(&adapter);
diff --git a/src/network/kernel/qnetworkproxy_win.cpp b/src/network/kernel/qnetworkproxy_win.cpp
index ccc7aa1cf5..a37585b5cd 100644
--- a/src/network/kernel/qnetworkproxy_win.cpp
+++ b/src/network/kernel/qnetworkproxy_win.cpp
@@ -47,6 +47,7 @@
#include <qurl.h>
#include <private/qsystemlibrary_p.h>
#include <qnetworkinterface.h>
+#include <qdebug.h>
#include <string.h>
#include <qt_windows.h>
@@ -587,8 +588,16 @@ QList<QNetworkProxy> 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();
@@ -605,7 +614,7 @@ QList<QNetworkProxy> 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();
@@ -618,7 +627,7 @@ QList<QNetworkProxy> 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();
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)
diff --git a/src/network/socket/qnativesocketengine_winrt.cpp b/src/network/socket/qnativesocketengine_winrt.cpp
index 0f632abbb3..45ed1465f2 100644
--- a/src/network/socket/qnativesocketengine_winrt.cpp
+++ b/src/network/socket/qnativesocketengine_winrt.cpp
@@ -304,8 +304,10 @@ bool QNativeSocketEngine::connectToHostByName(const QString &name, quint16 port)
Q_ASSERT_SUCCEEDED(hr);
d->socketState = QAbstractSocket::ConnectingState;
- hr = d->connectOp->put_Completed(Callback<IAsyncActionCompletedHandler>(
+ hr = QEventDispatcherWinRT::runOnXamlThread([d]() {
+ return d->connectOp->put_Completed(Callback<IAsyncActionCompletedHandler>(
d, &QNativeSocketEnginePrivate::handleConnectToHost).Get());
+ });
Q_ASSERT_SUCCEEDED(hr);
return d->socketState == QAbstractSocket::ConnectedState;
@@ -315,50 +317,53 @@ bool QNativeSocketEngine::bind(const QHostAddress &address, quint16 port)
{
Q_D(QNativeSocketEngine);
HRESULT hr;
- ComPtr<IHostName> hostAddress;
+ hr = QEventDispatcherWinRT::runOnXamlThread([address, d, port, this]() {
+ HRESULT hr;
+ ComPtr<IHostName> hostAddress;
- if (address != QHostAddress::Any && address != QHostAddress::AnyIPv4 && address != QHostAddress::AnyIPv6) {
- ComPtr<IHostNameFactory> hostNameFactory;
- hr = GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Networking_HostName).Get(),
- &hostNameFactory);
- Q_ASSERT_SUCCEEDED(hr);
- const QString addressString = address.toString();
- HStringReference addressRef(reinterpret_cast<LPCWSTR>(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<IHostNameFactory> 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<LPCWSTR>(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<LPCWSTR>(portQString.utf16()));
+ QString portQString = port ? QString::number(port) : QString();
+ HStringReference portString(reinterpret_cast<LPCWSTR>(portQString.utf16()));
- ComPtr<IAsyncAction> 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<IAsyncAction> 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<ClientConnectedHandler>(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<IAsyncActionCompletedHandler>(d, &QNativeSocketEnginePrivate::handleBindCompleted).Get());
- Q_ASSERT_SUCCEEDED(hr);
- hr = QWinRTFunctions::await(op);
+ hr = op->put_Completed(Callback<IAsyncActionCompletedHandler>(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;
@@ -410,7 +415,9 @@ int QNativeSocketEngine::accept()
socketDescription(this).constData());
return -1;
}
- hr = op->put_Completed(Callback<SocketReadCompletedHandler>(d, &QNativeSocketEnginePrivate::handleReadyRead).Get());
+ hr = QEventDispatcherWinRT::runOnXamlThread([d, op]() {
+ return op->put_Completed(Callback<SocketReadCompletedHandler>(d, &QNativeSocketEnginePrivate::handleReadyRead).Get());
+ });
if (FAILED(hr)) {
qErrnoWarning(hr, "accept(): Failed to set socket read callback (%s).",
socketDescription(this).constData());
@@ -781,18 +788,22 @@ void QNativeSocketEngine::establishRead()
Q_D(QNativeSocketEngine);
HRESULT hr;
- ComPtr<IInputStream> stream;
- hr = d->tcpSocket()->get_InputStream(&stream);
- RETURN_VOID_IF_FAILED("Failed to get socket input stream");
+ hr = QEventDispatcherWinRT::runOnXamlThread([d]() {
+ ComPtr<IInputStream> stream;
+ HRESULT hr = d->tcpSocket()->get_InputStream(&stream);
+ RETURN_HR_IF_FAILED("QNativeSocketEngine::establishRead: Failed to get socket input stream");
- ComPtr<IBuffer> buffer;
- hr = g->bufferFactory->Create(READ_BUFFER_SIZE, &buffer);
- Q_ASSERT_SUCCEEDED(hr);
+ ComPtr<IBuffer> buffer;
+ hr = g->bufferFactory->Create(READ_BUFFER_SIZE, &buffer);
+ RETURN_HR_IF_FAILED("QNativeSocketEngine::establishRead: Failed to create buffer");
- ComPtr<IAsyncBufferOperation> 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<SocketReadCompletedHandler>(d, &QNativeSocketEnginePrivate::handleReadyRead).Get());
+ ComPtr<IAsyncBufferOperation> 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<SocketReadCompletedHandler>(d, &QNativeSocketEnginePrivate::handleReadyRead).Get());
+ RETURN_HR_IF_FAILED("QNativeSocketEngine::establishRead: Failed to register read callback");
+ return S_OK;
+ });
Q_ASSERT_SUCCEEDED(hr);
}
@@ -814,7 +825,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<DatagramReceivedHandler>(this, &QNativeSocketEnginePrivate::handleNewDatagram).Get(), &connectionToken);
+ hr = QEventDispatcherWinRT::runOnXamlThread([this]() {
+ HRESULT hr = udpSocket()->add_MessageReceived(Callback<DatagramReceivedHandler>(this, &QNativeSocketEnginePrivate::handleNewDatagram).Get(), &connectionToken);
+ return hr;
+ });
Q_ASSERT_SUCCEEDED(hr);
break;
}
@@ -1242,7 +1256,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();
@@ -1261,7 +1275,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();
@@ -1307,7 +1321,9 @@ HRESULT QNativeSocketEnginePrivate::handleReadyRead(IAsyncBufferOperation *async
socketDescription(q).constData());
return S_OK;
}
- hr = op->put_Completed(Callback<SocketReadCompletedHandler>(this, &QNativeSocketEnginePrivate::handleReadyRead).Get());
+ hr = QEventDispatcherWinRT::runOnXamlThread([op, this]() {
+ return op->put_Completed(Callback<SocketReadCompletedHandler>(this, &QNativeSocketEnginePrivate::handleReadyRead).Get());
+ });
if (FAILED(hr)) {
qErrnoWarning(hr, "handleReadyRead(): Failed to set socket read callback (%s).",
socketDescription(q).constData());
diff --git a/src/platformsupport/dbustray/qdbustrayicon.cpp b/src/platformsupport/dbustray/qdbustrayicon.cpp
index 5351bc9f59..c8de50ebe1 100644
--- a/src/platformsupport/dbustray/qdbustrayicon.cpp
+++ b/src/platformsupport/dbustray/qdbustrayicon.cpp
@@ -53,13 +53,19 @@
#include <qloggingcategory.h>
#include <qplatformintegration.h>
#include <qplatformservices.h>
+#include <qdbusconnectioninterface.h>
+#include <private/qlockfile_p.h>
#include <private/qguiapplication_p.h>
+// 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");
@@ -142,9 +148,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);
diff --git a/src/plugins/platforms/android/qandroidplatformtheme.cpp b/src/plugins/platforms/android/qandroidplatformtheme.cpp
index f8d0b9c8ba..3949113240 100644
--- a/src/plugins/platforms/android/qandroidplatformtheme.cpp
+++ b/src/plugins/platforms/android/qandroidplatformtheme.cpp
@@ -368,6 +368,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
diff --git a/src/plugins/platforms/cocoa/qnsview.mm b/src/plugins/platforms/cocoa/qnsview.mm
index fb20b4d23b..66df5c724b 100644
--- a/src/plugins/platforms/cocoa/qnsview.mm
+++ b/src/plugins/platforms/cocoa/qnsview.mm
@@ -170,6 +170,7 @@ static NSString *_q_NSWindowDidChangeOcclusionStateNotification = nil;
}
m_isMenuView = false;
+ self.focusRingType = NSFocusRingTypeNone;
}
return self;
}
@@ -843,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
@@ -949,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)
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/qeglfskmsgbmcursor.cpp
index ac966d23ee..8536e2c239 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmscursor.cpp
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmcursor.cpp
@@ -2,6 +2,7 @@
**
** Copyright (C) 2015 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com>
** 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,9 +39,9 @@
**
****************************************************************************/
-#include "qeglfskmscursor.h"
-#include "qeglfskmsscreen.h"
-#include "qeglfskmsdevice.h"
+#include "qeglfskmsgbmcursor.h"
+#include "qeglfskmsgbmscreen.h"
+#include "qeglfskmsgbmdevice.h"
#include <QtCore/QJsonDocument>
#include <QtCore/QJsonObject>
@@ -63,7 +64,7 @@ QT_BEGIN_NAMESPACE
Q_DECLARE_LOGGING_CATEGORY(qLcEglfsKmsDebug)
-QEglFSKmsCursor::QEglFSKmsCursor(QEglFSKmsScreen *screen)
+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)
@@ -83,7 +84,7 @@ QEglFSKmsCursor::QEglFSKmsCursor(QEglFSKmsScreen *screen)
m_cursorSize.setHeight(height);
}
- m_bo = gbm_bo_create(m_screen->device()->device(), m_cursorSize.width(), m_cursorSize.height(),
+ m_bo = gbm_bo_create(static_cast<QEglFSKmsGbmDevice *>(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!");
@@ -98,7 +99,7 @@ QEglFSKmsCursor::QEglFSKmsCursor(QEglFSKmsScreen *screen)
setPos(QPoint(0, 0));
}
-QEglFSKmsCursor::~QEglFSKmsCursor()
+QEglFSKmsGbmCursor::~QEglFSKmsGbmCursor()
{
Q_FOREACH (QPlatformScreen *screen, m_screen->virtualSiblings()) {
QEglFSKmsScreen *kmsScreen = static_cast<QEglFSKmsScreen *>(screen);
@@ -110,13 +111,13 @@ QEglFSKmsCursor::~QEglFSKmsCursor()
m_bo = Q_NULLPTR;
}
-void QEglFSKmsCursor::pointerEvent(const QMouseEvent &event)
+void QEglFSKmsGbmCursor::pointerEvent(const QMouseEvent &event)
{
setPos(event.screenPos().toPoint());
}
#ifndef QT_NO_CURSOR
-void QEglFSKmsCursor::changeCursor(QCursor *windowCursor, QWindow *window)
+void QEglFSKmsGbmCursor::changeCursor(QCursor *windowCursor, QWindow *window)
{
Q_UNUSED(window);
@@ -171,12 +172,12 @@ void QEglFSKmsCursor::changeCursor(QCursor *windowCursor, QWindow *window)
}
#endif // QT_NO_CURSOR
-QPoint QEglFSKmsCursor::pos() const
+QPoint QEglFSKmsGbmCursor::pos() const
{
return m_pos;
}
-void QEglFSKmsCursor::setPos(const QPoint &pos)
+void QEglFSKmsGbmCursor::setPos(const QPoint &pos)
{
Q_FOREACH (QPlatformScreen *screen, m_screen->virtualSiblings()) {
QEglFSKmsScreen *kmsScreen = static_cast<QEglFSKmsScreen *>(screen);
@@ -192,7 +193,7 @@ void QEglFSKmsCursor::setPos(const QPoint &pos)
}
}
-void QEglFSKmsCursor::initCursorAtlas()
+void QEglFSKmsGbmCursor::initCursorAtlas()
{
static QByteArray json = qgetenv("QT_QPA_EGLFS_CURSOR");
if (json.isEmpty())
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmscursor.h b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmcursor.h
index bbdd87cefd..c1e3706e91 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmscursor.h
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmcursor.h
@@ -37,8 +37,8 @@
**
****************************************************************************/
-#ifndef QEGLFSKMSCURSOR_H
-#define QEGLFSKMSCURSOR_H
+#ifndef QEGLFSKMSGBMCURSOR_H
+#define QEGLFSKMSGBMCURSOR_H
#include <qpa/qplatformcursor.h>
#include <QtCore/QList>
@@ -48,15 +48,15 @@
QT_BEGIN_NAMESPACE
-class QEglFSKmsScreen;
+class QEglFSKmsGbmScreen;
-class QEglFSKmsCursor : public QPlatformCursor
+class QEglFSKmsGbmCursor : public QPlatformCursor
{
Q_OBJECT
public:
- QEglFSKmsCursor(QEglFSKmsScreen *screen);
- ~QEglFSKmsCursor();
+ QEglFSKmsGbmCursor(QEglFSKmsGbmScreen *screen);
+ ~QEglFSKmsGbmCursor();
// input methods
void pointerEvent(const QMouseEvent & event) Q_DECL_OVERRIDE;
@@ -69,7 +69,7 @@ public:
private:
void initCursorAtlas();
- QEglFSKmsScreen *m_screen;
+ QEglFSKmsGbmScreen *m_screen;
QSize m_cursorSize;
gbm_bo *m_bo;
QPoint m_pos;
@@ -89,4 +89,4 @@ private:
QT_END_NAMESPACE
-#endif
+#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 <pierluigi.fiorini@gmail.com>
+** 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 <QtCore/QLoggingCategory>
+#include <QtCore/private/qcore_unix_p.h>
+#include <QtGui/private/qguiapplication_p.h>
+
+#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<QEglFSKmsScreen *>(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 <pierluigi.fiorini@gmail.com>
+** 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 <gbm.h>
+
+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 <pierluigi.fiorini@gmail.com>
+** 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 <QtPlatformSupport/private/qdevicediscovery_p.h>
+#include <QtCore/QLoggingCategory>
+#include <QtCore/QJsonDocument>
+#include <QtCore/QJsonObject>
+#include <QtCore/QJsonArray>
+#include <QtGui/qpa/qplatformwindow.h>
+#include <QtGui/qpa/qplatformcursor.h>
+#include <QtGui/QScreen>
+
+#include <xf86drm.h>
+#include <xf86drmMode.h>
+#include <gbm.h>
+
+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<QEglFSKmsGbmScreen *>(platformWindow->screen());
+ if (screen->surface()) {
+ qWarning("Only single window per screen supported!");
+ return 0;
+ }
+
+ return reinterpret_cast<EGLNativeWindowType>(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<QEglFSKmsGbmDevice *>(device())->gbmDevice(),
+ 1, 1,
+ GBM_FORMAT_XRGB8888,
+ GBM_BO_USE_RENDERING);
+
+ return reinterpret_cast<EGLNativeWindowType>(surface);
+}
+
+void QEglFSKmsGbmIntegration::destroyNativeWindow(EGLNativeWindowType window)
+{
+ gbm_surface *surface = reinterpret_cast<gbm_surface *>(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<QWindow *>(surface->surface());
+ QEglFSKmsScreen *screen = static_cast<QEglFSKmsScreen *>(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 <pierluigi.fiorini@gmail.com>
+** 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 <QtCore/QMap>
+#include <QtCore/QVariant>
+
+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/qeglfskmsmain.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmmain.cpp
index a39e2e5434..8e8779ca10 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsmain.cpp
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmmain.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 qmake spec of the Qt Toolkit.
@@ -38,19 +39,19 @@
****************************************************************************/
#include "qeglfsdeviceintegration.h"
-#include "qeglfskmsintegration.h"
+#include "qeglfskmsgbmintegration.h"
QT_BEGIN_NAMESPACE
-class QEglFSKmsIntegrationPlugin : public QEGLDeviceIntegrationPlugin
+class QEglFSKmsGbmIntegrationPlugin : public QEGLDeviceIntegrationPlugin
{
Q_OBJECT
Q_PLUGIN_METADATA(IID QEGLDeviceIntegrationFactoryInterface_iid FILE "eglfs_kms.json")
public:
- QEGLDeviceIntegration *create() Q_DECL_OVERRIDE { return new QEglFSKmsIntegration; }
+ QEGLDeviceIntegration *create() Q_DECL_OVERRIDE { return new QEglFSKmsGbmIntegration; }
};
QT_END_NAMESPACE
-#include "qeglfskmsmain.moc"
+#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 <pierluigi.fiorini@gmail.com>
+** 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 <QtCore/QLoggingCategory>
+
+#include <QtGui/private/qguiapplication_p.h>
+#include <QtPlatformSupport/private/qfbvthandler_p.h>
+
+QT_BEGIN_NAMESPACE
+
+Q_DECLARE_LOGGING_CATEGORY(qLcEglfsKmsDebug)
+
+void QEglFSKmsGbmScreen::bufferDestroyedHandler(gbm_bo *bo, void *data)
+{
+ FrameBuffer *fb = static_cast<FrameBuffer *>(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<FrameBuffer *>(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<FrameBuffer> 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<QEglFSKmsGbmDevice *>(device())->globalCursor();
+
+ if (m_cursor.isNull()) {
+ QEglFSKmsGbmScreen *that = const_cast<QEglFSKmsGbmScreen *>(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<QEglFSKmsGbmDevice *>(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<QEglFSKmsGbmDevice *>(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 <pierluigi.fiorini@gmail.com>
+** 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 <QtCore/QMutex>
+
+#include <gbm.h>
+
+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<QEglFSKmsGbmCursor> 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_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 <QtCore/private/qcore_unix_p.h>
+
+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 <qeglfskmsdevice.h>
+
+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 <QtPlatformSupport/private/qeglconvenience_p.h>
+#include "qeglfswindow.h"
+#include "qeglfskmsegldevice.h"
+#include "qeglfskmsscreen.h"
#include <QLoggingCategory>
#include <private/qmath_p.h>
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<EGLNativeDisplayType>(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<QEglFSKmsScreen*>(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<const drmModeModeInfoPtr>(&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 <QtPlatformSupport/private/qdevicediscovery_p.h>
-#include <QtPlatformSupport/private/qeglconvenience_p.h>
-#include <QtCore/private/qcore_unix_p.h>
-#include <QtCore/QScopedPointer>
-#include <QtGui/qpa/qplatformwindow.h>
-#include <QtGui/qguiapplication.h>
-#include <QDebug>
+#include <qeglfskmsintegration.h>
#include <xf86drm.h>
#include <xf86drmMode.h>
@@ -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 <qeglfskmsscreen.h>
+
+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/qeglfskmsdevice.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsdevice.cpp
index 80885df536..f4ffee569d 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsdevice.cpp
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsdevice.cpp
@@ -2,6 +2,7 @@
**
** Copyright (C) 2015 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com>
** 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.
@@ -309,7 +310,7 @@ QEglFSKmsScreen *QEglFSKmsDevice::screenForConnector(drmModeResPtr resources, dr
m_crtc_allocator |= (1 << output.crtc_id);
m_connector_allocator |= (1 << output.connector_id);
- return new QEglFSKmsScreen(m_integration, this, output, pos);
+ return createScreen(m_integration, this, output, pos);
}
drmModePropertyPtr QEglFSKmsDevice::connectorProperty(drmModeConnectorPtr connector, const QByteArray &name)
@@ -328,68 +329,17 @@ drmModePropertyPtr QEglFSKmsDevice::connectorProperty(drmModeConnectorPtr connec
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<QEglFSKmsScreen *>(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()
+QEglFSKmsDevice::~QEglFSKmsDevice()
{
- 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()
@@ -428,36 +378,27 @@ void QEglFSKmsDevice::createScreens()
if (!m_integration->separateScreens()) {
Q_FOREACH (QPlatformScreen *screen, siblings)
static_cast<QEglFSKmsScreen *>(screen)->setVirtualSiblings(siblings);
-
- if (primaryScreen)
- 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
+QString QEglFSKmsDevice::devicePath() const
{
- return m_globalCursor;
+ return m_path;
}
-void QEglFSKmsDevice::handleDrmEvent()
+QEglFSKmsScreen *QEglFSKmsDevice::createScreen(QEglFSKmsIntegration *integration, QEglFSKmsDevice *device, QEglFSKmsOutput output, QPoint position)
{
- drmEventContext drmEvent = {
- DRM_EVENT_CONTEXT_VERSION,
- Q_NULLPTR, // vblank handler
- pageFlipHandler // page flip handler
- };
+ return new QEglFSKmsScreen(integration, device, output, position);
+}
- drmHandleEvent(m_dri_fd, &drmEvent);
+void QEglFSKmsDevice::setFd(int fd)
+{
+ m_dri_fd = fd;
}
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsdevice.h b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsdevice.h
index eab5ac9934..ffa8bcbaa5 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsdevice.h
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsdevice.h
@@ -2,6 +2,7 @@
**
** Copyright (C) 2015 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com>
** 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.
@@ -41,33 +42,35 @@
#ifndef QEGLFSKMSDEVICE_H
#define QEGLFSKMSDEVICE_H
-#include "qeglfskmscursor.h"
#include "qeglfskmsintegration.h"
+#include "qeglfskmsscreen.h"
#include <xf86drm.h>
#include <xf86drmMode.h>
-#include <gbm.h>
QT_BEGIN_NAMESPACE
-class QEglFSKmsScreen;
-
-class QEglFSKmsDevice
+class Q_EGLFS_EXPORT QEglFSKmsDevice
{
public:
QEglFSKmsDevice(QEglFSKmsIntegration *integration, const QString &path);
+ virtual ~QEglFSKmsDevice();
- bool open();
- void close();
+ virtual bool open() = 0;
+ virtual void close() = 0;
- void createScreens();
+ virtual void createScreens();
- gbm_device *device() const;
+ virtual EGLNativeDisplayType device() const = 0;
int fd() const;
+ QString devicePath() const;
- QPlatformCursor *globalCursor() const;
-
- void handleDrmEvent();
+protected:
+ virtual QEglFSKmsScreen *createScreen(QEglFSKmsIntegration *integration,
+ QEglFSKmsDevice *device,
+ QEglFSKmsOutput output,
+ QPoint position);
+ void setFd(int fd);
private:
Q_DISABLE_COPY(QEglFSKmsDevice)
@@ -75,13 +78,10 @@ private:
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);
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsintegration.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsintegration.cpp
index db503b6e7f..e25e481878 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsintegration.cpp
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsintegration.cpp
@@ -2,6 +2,7 @@
**
** Copyright (C) 2015 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com>
** 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.
@@ -41,11 +42,10 @@
#include "qeglfskmsintegration.h"
#include "qeglfskmsdevice.h"
#include "qeglfskmsscreen.h"
-#include "qeglfskmscursor.h"
+#include "qeglfswindow.h"
#include "qeglfscursor.h"
-#include <QtPlatformSupport/private/qdevicediscovery_p.h>
-#include <QtCore/QLoggingCategory>
+#include <QtPlatformSupport/private/qeglconvenience_p.h>
#include <QtCore/QJsonDocument>
#include <QtCore/QJsonObject>
#include <QtCore/QJsonArray>
@@ -55,17 +55,14 @@
#include <xf86drm.h>
#include <xf86drmMode.h>
-#include <gbm.h>
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_hwCursor(false)
, m_pbuffers(false)
, m_separateScreens(false)
{}
@@ -76,21 +73,9 @@ void QEglFSKmsIntegration::platformInit()
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);
+ m_device = createDevice(m_devicePath);
if (Q_UNLIKELY(!m_device->open()))
qFatal("Could not open device %s - aborting!", qPrintable(m_devicePath));
}
@@ -129,42 +114,6 @@ QSurfaceFormat QEglFSKmsIntegration::surfaceFormatFor(const QSurfaceFormat &inpu
return format;
}
-EGLNativeWindowType QEglFSKmsIntegration::createNativeWindow(QPlatformWindow *platformWindow,
- const QSize &size,
- const QSurfaceFormat &format)
-{
- Q_UNUSED(size);
- Q_UNUSED(format);
-
- QEglFSKmsScreen *screen = static_cast<QEglFSKmsScreen *>(platformWindow->screen());
- if (screen->surface()) {
- qWarning("Only single window per screen supported!");
- return 0;
- }
-
- return reinterpret_cast<EGLNativeWindowType>(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<EGLNativeWindowType>(surface);
-}
-
-void QEglFSKmsIntegration::destroyNativeWindow(EGLNativeWindowType window)
-{
- gbm_surface *surface = reinterpret_cast<gbm_surface *>(window);
- gbm_surface_destroy(surface);
-}
-
bool QEglFSKmsIntegration::hasCapability(QPlatformIntegration::Capability cap) const
{
switch (cap) {
@@ -177,14 +126,6 @@ bool QEglFSKmsIntegration::hasCapability(QPlatformIntegration::Capability cap) c
}
}
-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<QWindow *>(surface->surface());
@@ -193,14 +134,6 @@ void QEglFSKmsIntegration::waitForVSync(QPlatformSurface *surface) const
screen->waitForFlip();
}
-void QEglFSKmsIntegration::presentBuffer(QPlatformSurface *surface)
-{
- QWindow *window = static_cast<QWindow *>(surface->surface());
- QEglFSKmsScreen *screen = static_cast<QEglFSKmsScreen *>(window->screen()->handle());
-
- screen->flip();
-}
-
bool QEglFSKmsIntegration::supportsPBuffers() const
{
return m_pbuffers;
@@ -221,6 +154,11 @@ QMap<QString, QVariantMap> 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");
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsintegration.h b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsintegration.h
index ed0cb6a096..c630d93fce 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsintegration.h
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsintegration.h
@@ -2,6 +2,7 @@
**
** Copyright (C) 2015 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com>
** 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.
@@ -44,12 +45,15 @@
#include "qeglfsdeviceintegration.h"
#include <QtCore/QMap>
#include <QtCore/QVariant>
+#include <QtCore/QLoggingCategory>
QT_BEGIN_NAMESPACE
class QEglFSKmsDevice;
-class QEglFSKmsIntegration : public QEGLDeviceIntegration
+Q_EGLFS_EXPORT Q_DECLARE_LOGGING_CATEGORY(qLcEglfsKmsDebug)
+
+class Q_EGLFS_EXPORT QEglFSKmsIntegration : public QEGLDeviceIntegration
{
public:
QEglFSKmsIntegration();
@@ -60,21 +64,19 @@ public:
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;
+ virtual bool hwCursor() const;
+ virtual bool separateScreens() const;
QMap<QString, QVariantMap> outputSettings() const;
+ QEglFSKmsDevice *device() const;
+
+protected:
+ virtual QEglFSKmsDevice *createDevice(const QString &devicePath) = 0;
+
private:
void loadConfig();
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsscreen.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsscreen.cpp
index f53c3e9132..f614351a40 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsscreen.cpp
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsscreen.cpp
@@ -2,6 +2,7 @@
**
** Copyright (C) 2015 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com>
** 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,7 +41,6 @@
#include "qeglfskmsscreen.h"
#include "qeglfskmsdevice.h"
-#include "qeglfskmscursor.h"
#include "qeglfsintegration.h"
#include <QtCore/QLoggingCategory>
@@ -69,45 +69,6 @@ private:
QEglFSKmsScreen *m_screen;
};
-void QEglFSKmsScreen::bufferDestroyedHandler(gbm_bo *bo, void *data)
-{
- FrameBuffer *fb = static_cast<FrameBuffer *>(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<FrameBuffer *>(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<FrameBuffer> 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,
@@ -115,12 +76,8 @@ QEglFSKmsScreen::QEglFSKmsScreen(QEglFSKmsIntegration *integration,
: QEglFSScreen(eglGetDisplay(reinterpret_cast<EGLNativeDisplayType>(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))
{
@@ -191,116 +148,20 @@ 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<QEglFSKmsScreen *>(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()
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsscreen.h b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsscreen.h
index 3f836be143..ed26ca0419 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsscreen.h
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsscreen.h
@@ -2,6 +2,7 @@
**
** Copyright (C) 2015 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com>
** 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.
@@ -48,12 +49,10 @@
#include <xf86drm.h>
#include <xf86drmMode.h>
-#include <gbm.h>
QT_BEGIN_NAMESPACE
class QEglFSKmsDevice;
-class QEglFSKmsCursor;
class QEglFSKmsInterruptHandler;
struct QEglFSKmsOutput
@@ -70,7 +69,7 @@ struct QEglFSKmsOutput
drmModePropertyPtr dpms_prop;
};
-class QEglFSKmsScreen : public QEglFSScreen
+class Q_EGLFS_EXPORT QEglFSKmsScreen : public QEglFSScreen
{
public:
QEglFSKmsScreen(QEglFSKmsIntegration *integration,
@@ -90,8 +89,6 @@ public:
QString name() const Q_DECL_OVERRIDE;
- QPlatformCursor *cursor() const Q_DECL_OVERRIDE;
-
qreal refreshRate() const Q_DECL_OVERRIDE;
QList<QPlatformScreen *> virtualSiblings() const Q_DECL_OVERRIDE { return m_siblings; }
@@ -100,13 +97,11 @@ public:
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();
+ virtual void waitForFlip();
+ virtual void flip();
+ virtual void flipFinished();
QEglFSKmsOutput &output() { return m_output; }
void restoreMode();
@@ -119,28 +114,14 @@ public:
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<QEglFSKmsCursor> m_cursor;
QList<QPlatformScreen *> 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;
};
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 <EGL/eglvivante.h>
#include <QDebug>
+#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()) {
diff --git a/src/plugins/platforms/windows/qwindowsfontdatabase.cpp b/src/plugins/platforms/windows/qwindowsfontdatabase.cpp
index e81841d3da..be183034de 100644
--- a/src/plugins/platforms/windows/qwindowsfontdatabase.cpp
+++ b/src/plugins/platforms/windows/qwindowsfontdatabase.cpp
@@ -58,7 +58,11 @@
#include <wchar.h>
#if !defined(QT_NO_DIRECTWRITE)
-# include <dwrite.h>
+# if defined(QT_USE_DIRECTWRITE2)
+# include <dwrite_2.h>
+# else
+# include <dwrite.h>
+# endif
# include <d2d1.h>
#endif
@@ -82,17 +86,27 @@ static inline DWriteCreateFactoryType resolveDWriteCreateFactory()
return reinterpret_cast<DWriteCreateFactoryType>(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<IDWriteFactory *>(result);
+
+ *factory = static_cast<IDWriteFactory *>(result);
}
#endif // !QT_NO_DIRECTWRITE
@@ -502,8 +516,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);
@@ -602,7 +618,7 @@ qreal QWindowsFontDatabase::fontSmoothingGamma()
static inline bool initDirectWrite(QWindowsFontEngineData *d)
{
if (!d->directWriteFactory) {
- d->directWriteFactory = createDirectWriteFactory();
+ createDirectWriteFactory(&d->directWriteFactory);
if (!d->directWriteFactory)
return false;
}
@@ -1735,10 +1751,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) {
@@ -1760,18 +1773,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<void **>(&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 <private/qstringiterator_p.h>
#include <QtCore/private/qsystemlibrary_p.h>
-#include <dwrite.h>
+#if defined(QT_USE_DIRECTWRITE2)
+# include <dwrite_2.h>
+#else
+# include <dwrite.h>
+#endif
+
#include <d2d1.h>
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<void **>(&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<BYTE, 1024> 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<uint *>(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<height; ++y) {
- uint *dest = reinterpret_cast<uint *>(img.scanLine(y));
+ } else {
+ for (int y = 0; y < height; ++y) {
+ uint *dest = reinterpret_cast<uint *>(destination->scanLine(y));
BYTE *src = alphaValues + width * 3 * y;
- for (int x=0; x<width; ++x) {
- dest[x] = *(src) << 16
+ for (int x = 0; x < width; ++x) {
+ dest[x] = *(src + 0) << 16
| *(src + 1) << 8
| *(src + 2);
src += 3;
}
}
-
- delete[] alphaValues;
- glyphAnalysis->Release();
-
- 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<QWindowsFontEngineData> m_fontEngineData;
diff --git a/src/plugins/platforms/windows/windows.pri b/src/plugins/platforms/windows/windows.pri
index 2c6d316c34..b8476df792 100644
--- a/src/plugins/platforms/windows/windows.pri
+++ b/src/plugins/platforms/windows/windows.pri
@@ -10,6 +10,9 @@ LIBS += -lshlwapi -lshell32 -ladvapi32
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/src/plugins/platforms/winrt/qwinrtscreen.cpp b/src/plugins/platforms/winrt/qwinrtscreen.cpp
index 9b7f9cd5b0..562372d0b8 100644
--- a/src/plugins/platforms/winrt/qwinrtscreen.cpp
+++ b/src/plugins/platforms/winrt/qwinrtscreen.cpp
@@ -419,6 +419,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')
@@ -873,12 +890,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,
@@ -888,7 +926,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;
@@ -915,7 +953,7 @@ HRESULT QWinRTScreen::onKeyUp(ABI::Windows::UI::Core::ICoreWindow *, ABI::Window
virtualKey,
0,
info.text,
- status.RepeatCount > 1,
+ false, // The final key release does not have autoRepeat set on Windows
!status.RepeatCount ? 1 : status.RepeatCount,
false);
return S_OK;
@@ -948,7 +986,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));
diff --git a/src/plugins/platforms/xcb/qxcbbackingstore.cpp b/src/plugins/platforms/xcb/qxcbbackingstore.cpp
index d635c69175..2925917562 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 <class Pixel>
-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<const Pixel *>(srcData + yy * srcBytesPerLine) + left;
+ Pixel *dstPixels = reinterpret_cast<Pixel *>(dst);
+ const Pixel *srcPixels = reinterpret_cast<const Pixel *>(srcData + yy * srcBytesPerLine) + left;
- for (int xx = left; xx < right; ++xx)
- *dst++ = qbswap<Pixel>(*src++);
+ for (int i = 0; i < width; ++i)
+ dstPixels[i] = qbswap<Pixel>(*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<quint32 *>(buffer->data()), src, rect);
+ copy_swapped<quint32>(buffer->data(), dstStride, src, rect);
break;
case 16:
- copy_swapped(reinterpret_cast<quint16 *>(buffer->data()), src, rect);
+ copy_swapped<quint16>(buffer->data(), dstStride, src, rect);
break;
}
} else {
copy_unswapped(buffer->data(), dstStride, src, rect);
}
- return QImage(reinterpret_cast<const uchar *>(buffer->constData()), w, h, dstStride, src.format());
+ return QImage(reinterpret_cast<const uchar *>(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 &region)
@@ -390,7 +395,9 @@ void QXcbShmImage::flushPixmap(const QRegion &region)
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;
diff --git a/src/testlib/qtest.h b/src/testlib/qtest.h
index 7352e89016..261c769c15 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());
diff --git a/src/testlib/qtestcase.cpp b/src/testlib/qtestcase.cpp
index 385e456923..ed26c406a5 100644
--- a/src/testlib/qtestcase.cpp
+++ b/src/testlib/qtestcase.cpp
@@ -121,6 +121,7 @@ static void stackTrace()
char cmd[512];
qsnprintf(cmd, 512, "gdb --pid %d 2>/dev/null <<EOF\n"
"set prompt\n"
+ "set height 0\n"
"thread apply all where full\n"
"detach\n"
"quit\n"
diff --git a/src/testlib/qtestcase.qdoc b/src/testlib/qtestcase.qdoc
index e2fc6e107f..9513cf0c58 100644
--- a/src/testlib/qtestcase.qdoc
+++ b/src/testlib/qtestcase.qdoc
@@ -528,6 +528,7 @@
\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
diff --git a/src/tools/moc/generator.cpp b/src/tools/moc/generator.cpp
index 2b09cf873a..3f274401b3 100644
--- a/src/tools/moc/generator.cpp
+++ b/src/tools/moc/generator.cpp
@@ -79,7 +79,7 @@ Generator::Generator(ClassDef *classDef, const QList<QByteArray> &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)
@@ -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<QByteArray> 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);
diff --git a/src/tools/moc/main.cpp b/src/tools/moc/main.cpp
index db81ecabd2..491301d582 100644
--- a/src/tools/moc/main.cpp
+++ b/src/tools/moc/main.cpp
@@ -370,7 +370,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 <QtCore/qobject.h>\n");
fprintf(out, "#include <QtCore/qbytearray.h>\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");
}
}
diff --git a/src/tools/rcc/main.cpp b/src/tools/rcc/main.cpp
index e71ea57389..423b566896 100644
--- a/src/tools/rcc/main.cpp
+++ b/src/tools/rcc/main.cpp
@@ -250,6 +250,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);
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();
}
}
diff --git a/src/widgets/itemviews/qtreeview.cpp b/src/widgets/itemviews/qtreeview.cpp
index e9d866525d..cd3081dae5 100644
--- a/src/widgets/itemviews/qtreeview.cpp
+++ b/src/widgets/itemviews/qtreeview.cpp
@@ -2555,7 +2555,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();
diff --git a/src/widgets/kernel/qapplication.cpp b/src/widgets/kernel/qapplication.cpp
index f901f6fb16..a8a0968ff8 100644
--- a/src/widgets/kernel/qapplication.cpp
+++ b/src/widgets/kernel/qapplication.cpp
@@ -1088,7 +1088,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 {
diff --git a/src/widgets/util/qundostack.cpp b/src/widgets/util/qundostack.cpp
index 7361adfdd5..1863ab9145 100644
--- a/src/widgets/util/qundostack.cpp
+++ b/src/widgets/util/qundostack.cpp
@@ -928,7 +928,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,
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();
diff --git a/src/widgets/widgets/qdatetimeedit.cpp b/src/widgets/widgets/qdatetimeedit.cpp
index f72dc088da..cfba2cc87f 100644
--- a/src/widgets/widgets/qdatetimeedit.cpp
+++ b/src/widgets/widgets/qdatetimeedit.cpp
@@ -1674,12 +1674,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;
@@ -2053,7 +2048,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);
@@ -2068,7 +2063,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);
@@ -2086,7 +2081,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<int>(oldDay, cachedDay);
}
@@ -2278,15 +2273,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 420ce82f1c..f050061dea 100644
--- a/src/widgets/widgets/qdatetimeedit.h
+++ b/src/widgets/widgets/qdatetimeedit.h
@@ -75,7 +75,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,
diff --git a/src/widgets/widgets/qdatetimeedit_p.h b/src/widgets/widgets/qdatetimeedit_p.h
index e8e0749623..6abb3cd9a3 100644
--- a/src/widgets/widgets/qdatetimeedit_p.h
+++ b/src/widgets/widgets/qdatetimeedit_p.h
@@ -81,14 +81,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;
@@ -102,18 +113,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;
diff --git a/src/widgets/widgets/qlineedit.cpp b/src/widgets/widgets/qlineedit.cpp
index 9e489fad14..9be20ebb74 100644
--- a/src/widgets/widgets/qlineedit.cpp
+++ b/src/widgets/widgets/qlineedit.cpp
@@ -1743,18 +1743,28 @@ 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) {
case Qt::ImCursorRectangle:
return d->cursorRect();
+ case Qt::ImAnchorRectangle:
+ return d->adjustedControlRect(d->control->anchorRect());
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;
diff --git a/src/widgets/widgets/qplaintextedit.cpp b/src/widgets/widgets/qplaintextedit.cpp
index 17eac9db58..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;
@@ -2199,8 +2200,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..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
@@ -1729,8 +1730,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);
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,16 +407,14 @@ 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;
@@ -426,6 +424,29 @@ QRect QWidgetLineControl::cursorRect() const
/*!
\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
+
Fixes the current text so that it is valid given any set validators.
Returns \c true if the text was changed. Otherwise returns \c false.
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
diff --git a/src/widgets/widgets/qwidgettextcontrol.cpp b/src/widgets/widgets/qwidgettextcontrol.cpp
index af6d879661..cc1726c362 100644
--- a/src/widgets/widgets/qwidgettextcontrol.cpp
+++ b/src/widgets/widgets/qwidgettextcontrol.cpp
@@ -2073,10 +2073,15 @@ 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:
- 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:
@@ -2085,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;