summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java1
-rw-r--r--src/android/jar/src/org/qtproject/qt5/android/QtNative.java7
-rw-r--r--src/corelib/io/qprocess_unix.cpp10
-rw-r--r--src/corelib/json/qjsonobject.cpp10
-rw-r--r--src/corelib/json/qjsonobject.h2
-rw-r--r--src/corelib/kernel/qeventdispatcher_winrt.cpp13
-rw-r--r--src/corelib/kernel/qsharedmemory_win.cpp6
-rw-r--r--src/corelib/kernel/qvariant.h4
-rw-r--r--src/corelib/plugin/qlibrary_win.cpp9
-rw-r--r--src/corelib/tools/qsharedpointer_impl.h2
-rw-r--r--src/corelib/tools/qstring.cpp24
-rw-r--r--src/corelib/tools/qstring.h7
-rw-r--r--src/corelib/tools/qtimezone.cpp5
-rw-r--r--src/gui/image/qimage_conversions.cpp11
-rw-r--r--src/gui/kernel/qplatformdialoghelper.h17
-rw-r--r--src/gui/kernel/qplatformmenu.h2
-rw-r--r--src/gui/kernel/qplatformsystemtrayicon.h2
-rw-r--r--src/gui/kernel/qplatformtheme.h2
-rw-r--r--src/gui/kernel/qscreen.cpp4
-rw-r--r--src/gui/kernel/qwindow_p.h2
-rw-r--r--src/gui/opengl/qopengltexture.cpp4
-rw-r--r--src/gui/opengl/qopengltexture_p.h1
-rw-r--r--src/gui/painting/qdrawhelper.cpp28
-rw-r--r--src/gui/painting/qpaintengine_raster.cpp5
-rw-r--r--src/gui/painting/qplatformbackingstore.cpp2
-rw-r--r--src/gui/painting/qregion.cpp33
-rw-r--r--src/gui/text/qfont.cpp6
-rw-r--r--src/gui/text/qfontdatabase.cpp55
-rw-r--r--src/network/kernel/qdnslookup.cpp3
-rw-r--r--src/network/kernel/qdnslookup_p.h2
-rw-r--r--src/network/kernel/qdnslookup_unix.cpp4
-rw-r--r--src/network/kernel/qdnslookup_win.cpp4
-rw-r--r--src/network/kernel/qnetworkinterface_unix.cpp38
-rw-r--r--src/network/socket/qnativesocketengine_winrt_p.h2
-rw-r--r--src/platformheaders/windowsfunctions/qwindowswindowfunctions.h9
-rw-r--r--src/platformheaders/windowsfunctions/qwindowswindowfunctions.qdoc26
-rw-r--r--src/platformsupport/platformcompositor/qopenglcompositorbackingstore.cpp3
-rw-r--r--src/plugins/platforminputcontexts/compose/generator/qtablegenerator.cpp6
-rw-r--r--src/plugins/platforms/android/androidjnimain.cpp20
-rw-r--r--src/plugins/platforms/android/qandroidplatformfontdatabase.cpp2
-rw-r--r--src/plugins/platforms/cocoa/qcocoawindow.mm6
-rw-r--r--src/plugins/platforms/ios/qioscontext.mm9
-rw-r--r--src/plugins/platforms/ios/qiosmenu.mm17
-rw-r--r--src/plugins/platforms/ios/qiostextresponder.mm61
-rw-r--r--src/plugins/platforms/windows/qwindowsbackingstore.cpp7
-rw-r--r--src/plugins/platforms/windows/qwindowsfontdatabase_ft.cpp75
-rw-r--r--src/plugins/platforms/windows/qwindowsfontenginedirectwrite.cpp15
-rw-r--r--src/plugins/platforms/windows/qwindowsfontenginedirectwrite.h1
-rw-r--r--src/plugins/platforms/windows/qwindowskeymapper.cpp11
-rw-r--r--src/plugins/platforms/windows/qwindowsnativeinterface.cpp2
-rw-r--r--src/plugins/platforms/windows/qwindowswindow.cpp21
-rw-r--r--src/plugins/platforms/windows/qwindowswindow.h6
-rw-r--r--src/plugins/platforms/winrt/qwinrtfontdatabase.cpp15
-rw-r--r--src/plugins/platforms/winrt/qwinrtfontdatabase.h2
-rw-r--r--src/plugins/platforms/xcb/qxcbconnection.cpp273
-rw-r--r--src/plugins/platforms/xcb/qxcbconnection.h10
-rw-r--r--src/plugins/platforms/xcb/qxcbconnection_xi2.cpp11
-rw-r--r--src/plugins/platforms/xcb/qxcbscreen.cpp49
-rw-r--r--src/plugins/platforms/xcb/qxcbscreen.h10
-rw-r--r--src/plugins/platforms/xcb/qxcbwindow.cpp82
-rw-r--r--src/plugins/platforms/xcb/qxcbwindow.h3
-rw-r--r--src/widgets/dialogs/qfiledialog.cpp2
-rw-r--r--src/widgets/dialogs/qfilesystemmodel.cpp24
-rw-r--r--src/widgets/doc/src/guibooks.qdoc2
-rw-r--r--src/widgets/itemviews/qlistwidget.cpp2
-rw-r--r--src/widgets/kernel/qaction.cpp4
-rw-r--r--src/widgets/kernel/qwidgetbackingstore.cpp26
-rw-r--r--src/widgets/widgets/qdockarealayout.cpp3
-rw-r--r--src/widgets/widgets/qdockwidget.cpp8
-rw-r--r--src/winmain/qtmain_winrt.cpp20
70 files changed, 831 insertions, 339 deletions
diff --git a/src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java b/src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java
index f75b6562af..0a10a12660 100644
--- a/src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java
+++ b/src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java
@@ -904,6 +904,7 @@ public class QtActivityDelegate
public void onDestroy()
{
if (m_quitApp) {
+ QtNative.terminateQt();
if (m_debuggerProcess != null)
m_debuggerProcess.destroy();
System.exit(0);// FIXME remove it or find a better way
diff --git a/src/android/jar/src/org/qtproject/qt5/android/QtNative.java b/src/android/jar/src/org/qtproject/qt5/android/QtNative.java
index 804347e080..5ff5bbc32f 100644
--- a/src/android/jar/src/org/qtproject/qt5/android/QtNative.java
+++ b/src/android/jar/src/org/qtproject/qt5/android/QtNative.java
@@ -294,7 +294,12 @@ public class QtNative
private static void quitApp()
{
- m_activity.finish();
+ runAction(new Runnable() {
+ @Override
+ public void run() {
+ m_activity.finish();
+ }
+ });
}
//@ANDROID-9
diff --git a/src/corelib/io/qprocess_unix.cpp b/src/corelib/io/qprocess_unix.cpp
index 9a25f56c5f..ab5734a298 100644
--- a/src/corelib/io/qprocess_unix.cpp
+++ b/src/corelib/io/qprocess_unix.cpp
@@ -92,6 +92,7 @@ QT_END_NAMESPACE
#include <private/qthread_p.h>
#include <qfile.h>
#include <qfileinfo.h>
+#include <qdir.h>
#include <qlist.h>
#include <qmutex.h>
#include <qsemaphore.h>
@@ -362,11 +363,14 @@ void QProcessPrivate::startProcess()
static QBasicMutex cfbundleMutex;
QMutexLocker lock(&cfbundleMutex);
QCFType<CFBundleRef> bundle = CFBundleCreate(0, url);
- url = CFBundleCopyExecutableURL(bundle);
+ // 'executableURL' can be either relative or absolute ...
+ QCFType<CFURLRef> executableURL = CFBundleCopyExecutableURL(bundle);
+ // not to depend on caching - make sure it's always absolute.
+ url = CFURLCopyAbsoluteURL(executableURL);
}
if (url) {
- QCFString str = CFURLCopyFileSystemPath(url, kCFURLPOSIXPathStyle);
- encodedProgramName += "/Contents/MacOS/" + QCFString::toQString(str).toUtf8();
+ const QCFString str = CFURLCopyFileSystemPath(url, kCFURLPOSIXPathStyle);
+ encodedProgramName += (QDir::separator() + QDir(program).relativeFilePath(QCFString::toQString(str))).toUtf8();
}
}
#endif
diff --git a/src/corelib/json/qjsonobject.cpp b/src/corelib/json/qjsonobject.cpp
index b7dfe88434..c225606717 100644
--- a/src/corelib/json/qjsonobject.cpp
+++ b/src/corelib/json/qjsonobject.cpp
@@ -693,6 +693,11 @@ QJsonObject::const_iterator QJsonObject::constFind(const QString &key) const
\internal
*/
+/*! \typedef QJsonObject::iterator::pointer
+
+ \internal
+*/
+
/*! \fn QJsonObject::iterator::iterator()
Constructs an uninitialized iterator.
@@ -895,6 +900,11 @@ QJsonObject::const_iterator QJsonObject::constFind(const QString &key) const
\internal
*/
+/*! \typedef QJsonObject::const_iterator::pointer
+
+ \internal
+*/
+
/*! \fn QJsonObject::const_iterator::const_iterator()
Constructs an uninitialized iterator.
diff --git a/src/corelib/json/qjsonobject.h b/src/corelib/json/qjsonobject.h
index 19c938fd83..5b475f52ae 100644
--- a/src/corelib/json/qjsonobject.h
+++ b/src/corelib/json/qjsonobject.h
@@ -104,6 +104,7 @@ public:
typedef int difference_type;
typedef QJsonValue value_type;
typedef QJsonValueRef reference;
+ typedef QJsonValuePtr pointer;
Q_DECL_CONSTEXPR inline iterator() : o(Q_NULLPTR), i(0) {}
Q_DECL_CONSTEXPR inline iterator(QJsonObject *obj, int index) : o(obj), i(index) {}
@@ -146,6 +147,7 @@ public:
typedef int difference_type;
typedef QJsonValue value_type;
typedef QJsonValue reference;
+ typedef QJsonValuePtr pointer;
Q_DECL_CONSTEXPR inline const_iterator() : o(Q_NULLPTR), i(0) {}
Q_DECL_CONSTEXPR inline const_iterator(const QJsonObject *obj, int index)
diff --git a/src/corelib/kernel/qeventdispatcher_winrt.cpp b/src/corelib/kernel/qeventdispatcher_winrt.cpp
index 58b87bd36b..df070dd1ae 100644
--- a/src/corelib/kernel/qeventdispatcher_winrt.cpp
+++ b/src/corelib/kernel/qeventdispatcher_winrt.cpp
@@ -201,14 +201,16 @@ bool QEventDispatcherWinRT::processEvents(QEventLoop::ProcessEventsFlags flags)
{
Q_D(QEventDispatcherWinRT);
+ DWORD waitTime = 0;
do {
// Additional user events have to be handled before timer events, but the function may not
// return yet.
const bool userEventsSent = sendPostedEvents(flags);
- emit aboutToBlock();
const QVector<HANDLE> timerHandles = d->timerIdToHandle.values().toVector();
- DWORD waitResult = WaitForMultipleObjectsEx(timerHandles.count(), timerHandles.constData(), FALSE, 1, TRUE);
+ if (waitTime)
+ emit aboutToBlock();
+ DWORD waitResult = WaitForMultipleObjectsEx(timerHandles.count(), timerHandles.constData(), FALSE, waitTime, TRUE);
if (waitResult >= WAIT_OBJECT_0 && waitResult < WAIT_OBJECT_0 + timerHandles.count()) {
const HANDLE handle = timerHandles.value(waitResult - WAIT_OBJECT_0);
ResetEvent(handle);
@@ -231,6 +233,13 @@ bool QEventDispatcherWinRT::processEvents(QEventLoop::ProcessEventsFlags flags)
if (userEventsSent)
return true;
+
+ // We cannot wait infinitely like on other platforms, as
+ // WaitForMultipleObjectsEx might not return.
+ // For instance win32 uses MsgWaitForMultipleObjects to hook
+ // into the native event loop, while WinRT handles those
+ // via callbacks.
+ waitTime = 1;
} while (flags & QEventLoop::WaitForMoreEvents);
return false;
}
diff --git a/src/corelib/kernel/qsharedmemory_win.cpp b/src/corelib/kernel/qsharedmemory_win.cpp
index 5cc54b1def..f90763d308 100644
--- a/src/corelib/kernel/qsharedmemory_win.cpp
+++ b/src/corelib/kernel/qsharedmemory_win.cpp
@@ -58,7 +58,7 @@ void QSharedMemoryPrivate::setErrorString(QLatin1String function)
errorString = QSharedMemory::tr("%1: already exists").arg(function);
break;
case ERROR_FILE_NOT_FOUND:
-#ifdef Q_OS_WINCE
+#if defined(Q_OS_WINCE) || (defined(Q_OS_WINRT) && _MSC_VER < 1900)
// This happens on CE only if no file is present as CreateFileMappingW
// bails out with this error code
case ERROR_INVALID_PARAMETER:
@@ -101,7 +101,11 @@ HANDLE QSharedMemoryPrivate::handle()
Q_UNIMPLEMENTED();
hand = 0;
#elif defined(Q_OS_WINRT)
+#if _MSC_VER >= 1900
+ hand = OpenFileMappingFromApp(FILE_MAP_ALL_ACCESS, FALSE, reinterpret_cast<PCWSTR>(nativeKey.utf16()));
+#else
hand = CreateFileMappingFromApp(INVALID_HANDLE_VALUE, 0, PAGE_READWRITE, 0, (PCWSTR)nativeKey.utf16());
+#endif
#elif defined(Q_OS_WINCE)
// This works for opening a mapping too, but always opens it with read/write access in
// attach as it seems.
diff --git a/src/corelib/kernel/qvariant.h b/src/corelib/kernel/qvariant.h
index 4c7e498280..bed0e193db 100644
--- a/src/corelib/kernel/qvariant.h
+++ b/src/corelib/kernel/qvariant.h
@@ -772,7 +772,7 @@ namespace QtPrivate {
QVariantHash l;
l.reserve(iter.size());
for (QAssociativeIterable::const_iterator it = iter.begin(), end = iter.end(); it != end; ++it)
- l.insert(it.key().toString(), it.value());
+ l.insertMulti(it.key().toString(), it.value());
return l;
}
return QVariantValueHelper<QVariantHash>::invoke(v);
@@ -788,7 +788,7 @@ namespace QtPrivate {
QAssociativeIterable iter = QVariantValueHelperInterface<QAssociativeIterable>::invoke(v);
QVariantMap l;
for (QAssociativeIterable::const_iterator it = iter.begin(), end = iter.end(); it != end; ++it)
- l.insert(it.key().toString(), it.value());
+ l.insertMulti(it.key().toString(), it.value());
return l;
}
return QVariantValueHelper<QVariantMap>::invoke(v);
diff --git a/src/corelib/plugin/qlibrary_win.cpp b/src/corelib/plugin/qlibrary_win.cpp
index c1ce198c84..f5604a24bd 100644
--- a/src/corelib/plugin/qlibrary_win.cpp
+++ b/src/corelib/plugin/qlibrary_win.cpp
@@ -124,7 +124,8 @@ bool QLibraryPrivate::load_sys()
SetErrorMode(oldmode);
#endif
if (!pHnd) {
- errorString = QLibrary::tr("Cannot load library %1: %2").arg(fileName).arg(qt_error_string());
+ errorString = QLibrary::tr("Cannot load library %1: %2").arg(
+ QDir::toNativeSeparators(fileName)).arg(qt_error_string());
} else {
// Query the actual name of the library that was loaded
errorString.clear();
@@ -148,7 +149,8 @@ bool QLibraryPrivate::load_sys()
bool QLibraryPrivate::unload_sys()
{
if (!FreeLibrary(pHnd)) {
- errorString = QLibrary::tr("Cannot unload library %1: %2").arg(fileName).arg(qt_error_string());
+ errorString = QLibrary::tr("Cannot unload library %1: %2").arg(
+ QDir::toNativeSeparators(fileName)).arg(qt_error_string());
return false;
}
errorString.clear();
@@ -164,7 +166,8 @@ QFunctionPointer QLibraryPrivate::resolve_sys(const char* symbol)
#endif
if (!address) {
errorString = QLibrary::tr("Cannot resolve symbol \"%1\" in %2: %3").arg(
- QString::fromLatin1(symbol)).arg(fileName).arg(qt_error_string());
+ QString::fromLatin1(symbol)).arg(
+ QDir::toNativeSeparators(fileName)).arg(qt_error_string());
} else {
errorString.clear();
}
diff --git a/src/corelib/tools/qsharedpointer_impl.h b/src/corelib/tools/qsharedpointer_impl.h
index ace6c5d093..6827483464 100644
--- a/src/corelib/tools/qsharedpointer_impl.h
+++ b/src/corelib/tools/qsharedpointer_impl.h
@@ -500,7 +500,7 @@ private:
template <class X>
inline void enableSharedFromThis(const QEnableSharedFromThis<X> *ptr)
{
- ptr->initializeFromSharedPointer(*this);
+ ptr->initializeFromSharedPointer(constCast<typename QtPrivate::remove_cv<T>::type>());
}
inline void enableSharedFromThis(...) {}
diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp
index b582204d67..2f340477fc 100644
--- a/src/corelib/tools/qstring.cpp
+++ b/src/corelib/tools/qstring.cpp
@@ -1819,6 +1819,17 @@ QString &QString::operator=(const QString &other) Q_DECL_NOTHROW
Assigns the Latin-1 string \a str to this string.
*/
+QString &QString::operator=(QLatin1String other)
+{
+ if (isDetached() && other.size() <= capacity()) { // assumes d->alloc == 0 → !isDetached() (sharedNull)
+ d->size = other.size();
+ d->data()[other.size()] = 0;
+ qt_from_latin1(d->data(), other.latin1(), other.size());
+ } else {
+ *this = fromLatin1(other.latin1(), other.size());
+ }
+ return *this;
+}
/*! \fn QString &QString::operator=(const QByteArray &ba)
@@ -1869,7 +1880,16 @@ QString &QString::operator=(const QString &other) Q_DECL_NOTHROW
*/
QString &QString::operator=(QChar ch)
{
- return operator=(QString(ch));
+ if (isDetached() && capacity() >= 1) { // assumes d->alloc == 0 → !isDetached() (sharedNull)
+ // re-use existing capacity:
+ ushort *dat = d->data();
+ dat[0] = ch.unicode();
+ dat[1] = 0;
+ d->size = 1;
+ } else {
+ operator=(QString(ch));
+ }
+ return *this;
}
/*!
@@ -5667,7 +5687,7 @@ QString QString::rightJustified(int width, QChar fill, bool truncate) const
*/
namespace QUnicodeTables {
-/*!
+/*
\internal
Converts the \a str string starting from the position pointed to by the \a
it iterator, using the Unicode case traits \c Traits, and returns the
diff --git a/src/corelib/tools/qstring.h b/src/corelib/tools/qstring.h
index 4ae81f9269..75f94d7f93 100644
--- a/src/corelib/tools/qstring.h
+++ b/src/corelib/tools/qstring.h
@@ -221,7 +221,7 @@ public:
inline ~QString();
QString &operator=(QChar c);
QString &operator=(const QString &) Q_DECL_NOTHROW;
- inline QString &operator=(QLatin1String latin1);
+ QString &operator=(QLatin1String latin1);
#ifdef Q_COMPILER_RVALUE_REFS
inline QString(QString && other) Q_DECL_NOTHROW : d(other.d) { other.d = Data::sharedNull(); }
inline QString &operator=(QString &&other) Q_DECL_NOTHROW
@@ -885,11 +885,6 @@ inline void QString::detach()
{ if (d->ref.isShared() || (d->offset != sizeof(QStringData))) reallocData(uint(d->size) + 1u); }
inline bool QString::isDetached() const
{ return !d->ref.isShared(); }
-inline QString &QString::operator=(QLatin1String s)
-{
- *this = fromLatin1(s.latin1(), s.size());
- return *this;
-}
inline void QString::clear()
{ if (!isNull()) *this = QString(); }
inline QString::QString(const QString &other) Q_DECL_NOTHROW : d(other.d)
diff --git a/src/corelib/tools/qtimezone.cpp b/src/corelib/tools/qtimezone.cpp
index 57c1838b76..333a5c3471 100644
--- a/src/corelib/tools/qtimezone.cpp
+++ b/src/corelib/tools/qtimezone.cpp
@@ -695,6 +695,11 @@ QTimeZone::OffsetData QTimeZone::offsetData(const QDateTime &forDateTime) const
/*!
Returns \c true if the system backend supports obtaining transitions.
+
+ Transitions are changes in the time-zone: these happen when DST turns on or
+ off and when authorities alter the offsets for the time-zone.
+
+ \sa nextTransition(), previousTransition(), transitions()
*/
bool QTimeZone::hasTransitions() const
diff --git a/src/gui/image/qimage_conversions.cpp b/src/gui/image/qimage_conversions.cpp
index cbdcf49da7..cc79e73534 100644
--- a/src/gui/image/qimage_conversions.cpp
+++ b/src/gui/image/qimage_conversions.cpp
@@ -2967,15 +2967,6 @@ static void qInitImageConversions()
#endif
}
-class QImageConversionsInitializer {
-public:
- QImageConversionsInitializer()
- {
- qInitImageConversions();
- }
-};
-
-// Ensure initialization if this object file is linked.
-static QImageConversionsInitializer qImageConversionsInitializer;
+Q_CONSTRUCTOR_FUNCTION(qInitImageConversions);
QT_END_NAMESPACE
diff --git a/src/gui/kernel/qplatformdialoghelper.h b/src/gui/kernel/qplatformdialoghelper.h
index 936dbdfa89..5b2f4ece77 100644
--- a/src/gui/kernel/qplatformdialoghelper.h
+++ b/src/gui/kernel/qplatformdialoghelper.h
@@ -104,6 +104,7 @@ public:
};
Q_DECLARE_FLAGS(StandardButtons, StandardButton)
+ Q_FLAG(StandardButtons)
enum ButtonRole {
// keep this in sync with QDialogButtonBox::ButtonRole and QMessageBox::ButtonRole
@@ -128,6 +129,7 @@ public:
Reverse = 0x40000000,
EOL = InvalidRole
};
+ Q_ENUM(ButtonRole)
enum ButtonLayout {
// keep this in sync with QDialogButtonBox::ButtonLayout and QMessageBox::ButtonLayout
@@ -167,6 +169,7 @@ QT_BEGIN_NAMESPACE
class Q_GUI_EXPORT QColorDialogOptions
{
+ Q_GADGET
public:
enum ColorDialogOption {
ShowAlphaChannel = 0x00000001,
@@ -175,6 +178,7 @@ public:
};
Q_DECLARE_FLAGS(ColorDialogOptions, ColorDialogOption)
+ Q_FLAG(ColorDialogOptions)
QColorDialogOptions();
QColorDialogOptions(const QColorDialogOptions &rhs);
@@ -226,6 +230,7 @@ private:
class Q_GUI_EXPORT QFontDialogOptions
{
+ Q_GADGET
public:
enum FontDialogOption {
NoButtons = 0x00000001,
@@ -237,6 +242,7 @@ public:
};
Q_DECLARE_FLAGS(FontDialogOptions, FontDialogOption)
+ Q_FLAG(FontDialogOptions)
QFontDialogOptions();
QFontDialogOptions(const QFontDialogOptions &rhs);
@@ -279,11 +285,19 @@ private:
class Q_GUI_EXPORT QFileDialogOptions
{
+ Q_GADGET
public:
enum ViewMode { Detail, List };
+ Q_ENUM(ViewMode)
+
enum FileMode { AnyFile, ExistingFile, Directory, ExistingFiles, DirectoryOnly };
+ Q_ENUM(FileMode)
+
enum AcceptMode { AcceptOpen, AcceptSave };
+ Q_ENUM(AcceptMode)
+
enum DialogLabel { LookIn, FileName, FileType, Accept, Reject, DialogLabelCount };
+ Q_ENUM(DialogLabel)
enum FileDialogOption
{
@@ -297,6 +311,7 @@ public:
DontUseCustomDirectoryIcons = 0x00000080
};
Q_DECLARE_FLAGS(FileDialogOptions, FileDialogOption)
+ Q_FLAG(FileDialogOptions)
QFileDialogOptions();
QFileDialogOptions(const QFileDialogOptions &rhs);
@@ -396,9 +411,11 @@ private:
class Q_GUI_EXPORT QMessageDialogOptions
{
+ Q_GADGET
public:
// Keep in sync with QMessageBox::Icon
enum Icon { NoIcon, Information, Warning, Critical, Question };
+ Q_ENUM(Icon)
QMessageDialogOptions();
QMessageDialogOptions(const QMessageDialogOptions &rhs);
diff --git a/src/gui/kernel/qplatformmenu.h b/src/gui/kernel/qplatformmenu.h
index 1022d0ed4a..bc0b3a4870 100644
--- a/src/gui/kernel/qplatformmenu.h
+++ b/src/gui/kernel/qplatformmenu.h
@@ -63,6 +63,7 @@ public:
// They could be added as public QAction roles if necessary.
CutRole, CopyRole, PasteRole, SelectAllRole,
RoleCount };
+ Q_ENUM(MenuRole)
virtual void setTag(quintptr tag) = 0;
virtual quintptr tag()const = 0;
@@ -91,6 +92,7 @@ class Q_GUI_EXPORT QPlatformMenu : public QObject
Q_OBJECT
public:
enum MenuType { DefaultMenu = 0, EditMenu };
+ Q_ENUM(MenuType)
virtual void insertMenuItem(QPlatformMenuItem *menuItem, QPlatformMenuItem *before) = 0;
virtual void removeMenuItem(QPlatformMenuItem *menuItem) = 0;
diff --git a/src/gui/kernel/qplatformsystemtrayicon.h b/src/gui/kernel/qplatformsystemtrayicon.h
index 437f5e02b1..6ef2d1538f 100644
--- a/src/gui/kernel/qplatformsystemtrayicon.h
+++ b/src/gui/kernel/qplatformsystemtrayicon.h
@@ -57,8 +57,10 @@ public:
Trigger,
MiddleClick
};
+ Q_ENUM(ActivationReason)
enum MessageIcon { NoIcon, Information, Warning, Critical };
+ Q_ENUM(MessageIcon)
QPlatformSystemTrayIcon();
~QPlatformSystemTrayIcon();
diff --git a/src/gui/kernel/qplatformtheme.h b/src/gui/kernel/qplatformtheme.h
index 9355e83491..2bd35491fb 100644
--- a/src/gui/kernel/qplatformtheme.h
+++ b/src/gui/kernel/qplatformtheme.h
@@ -164,6 +164,8 @@ public:
SmallFont,
MiniFont,
FixedFont,
+ GroupBoxTitleFont,
+ TabButtonFont,
NFonts
};
diff --git a/src/gui/kernel/qscreen.cpp b/src/gui/kernel/qscreen.cpp
index fb322ae74f..52e7686439 100644
--- a/src/gui/kernel/qscreen.cpp
+++ b/src/gui/kernel/qscreen.cpp
@@ -116,8 +116,8 @@ QScreen::~QScreen()
bool movingFromVirtualSibling = primaryScreen && primaryScreen->handle()->virtualSiblings().contains(handle());
// Move any leftover windows to the primary screen
- foreach (QWindow *window, QGuiApplication::topLevelWindows()) {
- if (window->screen() != this)
+ foreach (QWindow *window, QGuiApplication::allWindows()) {
+ if (!window->isTopLevel() || window->screen() != this)
continue;
const bool wasVisible = window->isVisible();
diff --git a/src/gui/kernel/qwindow_p.h b/src/gui/kernel/qwindow_p.h
index 23a6d800c0..6880edaada 100644
--- a/src/gui/kernel/qwindow_p.h
+++ b/src/gui/kernel/qwindow_p.h
@@ -50,6 +50,7 @@
#include <qpa/qplatformwindow.h>
#include <QtCore/private/qobject_p.h>
+#include <QtCore/qelapsedtimer.h>
#include <QtGui/QIcon>
QT_BEGIN_NAMESPACE
@@ -187,6 +188,7 @@ public:
#endif
bool compositing;
+ QElapsedTimer lastComposeTime;
};
diff --git a/src/gui/opengl/qopengltexture.cpp b/src/gui/opengl/qopengltexture.cpp
index 301b2ad13d..02dee5a90a 100644
--- a/src/gui/opengl/qopengltexture.cpp
+++ b/src/gui/opengl/qopengltexture.cpp
@@ -97,9 +97,11 @@ QOpenGLTexturePrivate::QOpenGLTexturePrivate(QOpenGLTexture::Target textureTarge
break;
case QOpenGLTexture::TargetCubeMap:
bindingTarget = QOpenGLTexture::BindingTargetCubeMap;
+ faces = 6;
break;
case QOpenGLTexture::TargetCubeMapArray:
bindingTarget = QOpenGLTexture::BindingTargetCubeMapArray;
+ faces = 6;
break;
case QOpenGLTexture::Target2DMultisample:
bindingTarget = QOpenGLTexture::BindingTarget2DMultisample;
@@ -175,7 +177,7 @@ bool QOpenGLTexturePrivate::create()
void QOpenGLTexturePrivate::destroy()
{
- if (!context) {
+ if (!textureId) {
// not created or already destroyed
return;
}
diff --git a/src/gui/opengl/qopengltexture_p.h b/src/gui/opengl/qopengltexture_p.h
index ac9d44db42..40ceb1936c 100644
--- a/src/gui/opengl/qopengltexture_p.h
+++ b/src/gui/opengl/qopengltexture_p.h
@@ -156,7 +156,6 @@ public:
bool autoGenerateMipMaps;
bool storageAllocated;
- QPair<int, int> glVersion;
QOpenGLTextureHelper *texFuncs;
QOpenGLTexture::Features features;
diff --git a/src/gui/painting/qdrawhelper.cpp b/src/gui/painting/qdrawhelper.cpp
index 4e40d250d3..e7b81ebdd3 100644
--- a/src/gui/painting/qdrawhelper.cpp
+++ b/src/gui/painting/qdrawhelper.cpp
@@ -32,11 +32,6 @@
****************************************************************************/
#include <qglobal.h>
-#ifdef Q_OS_IOS
-// We don't build the NEON drawhelpers as they are implemented partly
-// in GAS syntax assembly, which is not supported by the iOS toolchain.
-#undef __ARM_NEON__
-#endif
#include <qstylehints.h>
#include <qguiapplication.h>
@@ -6314,8 +6309,13 @@ void qt_memfill32(quint32 *dest, quint32 color, int count)
template<QtPixelOrder> const uint *QT_FASTCALL convertA2RGB30PMFromARGB32PM_sse4(uint *buffer, const uint *src, int count, const QPixelLayout *, const QRgb *);
#endif
+extern void qInitBlendFunctions();
+
static void qInitDrawhelperFunctions()
{
+ // Set up basic blend function tables.
+ qInitBlendFunctions();
+
#ifdef __SSE2__
qDrawHelper[QImage::Format_RGB32].bitmapBlit = qt_bitmapblit32_sse2;
qDrawHelper[QImage::Format_ARGB32].bitmapBlit = qt_bitmapblit32_sse2;
@@ -6411,7 +6411,7 @@ static void qInitDrawhelperFunctions()
#endif // SSE2
-#if defined(__ARM_NEON__) && !defined(Q_OS_IOS)
+#if defined(__ARM_NEON__)
qBlendFunctions[QImage::Format_RGB32][QImage::Format_RGB32] = qt_blend_rgb32_on_rgb32_neon;
qBlendFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_RGB32] = qt_blend_rgb32_on_rgb32_neon;
qBlendFunctions[QImage::Format_RGB32][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_argb32_neon;
@@ -6432,7 +6432,7 @@ static void qInitDrawhelperFunctions()
qt_fetch_radial_gradient = qt_fetch_radial_gradient_neon;
-#if !defined(Q_PROCESSOR_ARM_64)
+#if defined(ENABLE_PIXMAN_DRAWHELPERS)
// The RGB16 helpers are using Arm32 assemblythat has not been ported to AArch64
qBlendFunctions[QImage::Format_RGB16][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_rgb16_neon;
qBlendFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_RGB16] = qt_blend_rgb16_on_argb32_neon;
@@ -6509,19 +6509,7 @@ static void qInitDrawhelperFunctions()
#endif // QT_COMPILER_SUPPORTS_MIPS_DSP || QT_COMPILER_SUPPORTS_MIPS_DSPR2
}
-extern void qInitBlendFunctions();
-class DrawHelperInitializer {
-public:
- DrawHelperInitializer()
- {
- // Set up basic blend function tables.
- qInitBlendFunctions();
- // Set up architecture optimized methods for the current machine.
- qInitDrawhelperFunctions();
- }
-};
-
// Ensure initialization if this object file is linked.
-static DrawHelperInitializer drawHelperInitializer;
+Q_CONSTRUCTOR_FUNCTION(qInitDrawhelperFunctions);
QT_END_NAMESPACE
diff --git a/src/gui/painting/qpaintengine_raster.cpp b/src/gui/painting/qpaintengine_raster.cpp
index 7f8000c856..8409481ad5 100644
--- a/src/gui/painting/qpaintengine_raster.cpp
+++ b/src/gui/painting/qpaintengine_raster.cpp
@@ -3653,8 +3653,9 @@ QImage::Format QRasterBuffer::prepare(QImage *image)
drawHelper = qDrawHelper + format;
if (image->depth() == 1 && image->colorTable().size() == 2) {
monoDestinationWithClut = true;
- destColor0 = qPremultiply(image->colorTable()[0]);
- destColor1 = qPremultiply(image->colorTable()[1]);
+ const QVector<QRgb> colorTable = image->colorTable();
+ destColor0 = qPremultiply(colorTable[0]);
+ destColor1 = qPremultiply(colorTable[1]);
}
return format;
diff --git a/src/gui/painting/qplatformbackingstore.cpp b/src/gui/painting/qplatformbackingstore.cpp
index 4e26d8f741..cda2446a5e 100644
--- a/src/gui/painting/qplatformbackingstore.cpp
+++ b/src/gui/painting/qplatformbackingstore.cpp
@@ -301,6 +301,8 @@ void QPlatformBackingStore::composeAndFlush(QWindow *window, const QRegion &regi
return;
}
+ QWindowPrivate::get(window)->lastComposeTime.start();
+
QOpenGLFunctions *funcs = context->functions();
funcs->glViewport(0, 0, window->width() * window->devicePixelRatio(), window->height() * window->devicePixelRatio());
funcs->glClearColor(0, 0, 0, translucentBackground ? 0 : 1);
diff --git a/src/gui/painting/qregion.cpp b/src/gui/painting/qregion.cpp
index e6b777a30e..5e648eabf5 100644
--- a/src/gui/painting/qregion.cpp
+++ b/src/gui/painting/qregion.cpp
@@ -41,7 +41,7 @@
#include "qimage.h"
#include "qbitmap.h"
-#include <qdebug.h>
+#include <private/qdebug_p.h>
QT_BEGIN_NAMESPACE
@@ -422,11 +422,32 @@ QDataStream &operator>>(QDataStream &s, QRegion &r)
#ifndef QT_NO_DEBUG_STREAM
QDebug operator<<(QDebug s, const QRegion &r)
{
- QVector<QRect> rects = r.rects();
- s.nospace() << "QRegion(size=" << rects.size() << "), "
- << "bounds = " << r.boundingRect() << '\n';
- for (int i=0; i<rects.size(); ++i)
- s << "- " << i << rects.at(i) << '\n';
+ QDebugStateSaver saver(s);
+ s.nospace();
+ s << "QRegion(";
+ if (r.isNull()) {
+ s << "null";
+ } else if (r.isEmpty()) {
+ s << "empty";
+ } else {
+ const QVector<QRect> rects = r.rects();
+ const int count = rects.size();
+ if (count > 1)
+ s << "size=" << count << ", bounds=(";
+ QtDebugUtils::formatQRect(s, r.boundingRect());
+ if (count > 1) {
+ s << ") - [";
+ for (int i = 0; i < count; ++i) {
+ if (i)
+ s << ", ";
+ s << '(';
+ QtDebugUtils::formatQRect(s, rects.at(i));
+ s << ')';
+ }
+ s << ']';
+ }
+ }
+ s << ')';
return s;
}
#endif
diff --git a/src/gui/text/qfont.cpp b/src/gui/text/qfont.cpp
index a0a64cae01..ed4a932a32 100644
--- a/src/gui/text/qfont.cpp
+++ b/src/gui/text/qfont.cpp
@@ -2110,6 +2110,9 @@ QString QFont::lastResortFamily() const
return QString::fromLatin1("helvetica");
}
+extern QStringList qt_fallbacksForFamily(const QString &family, QFont::Style style,
+ QFont::StyleHint styleHint, QChar::Script script);
+
/*!
\fn QString QFont::defaultFamily() const
@@ -2120,8 +2123,7 @@ QString QFont::lastResortFamily() const
*/
QString QFont::defaultFamily() const
{
- QPlatformFontDatabase *fontDB = QGuiApplicationPrivate::platformIntegration()->fontDatabase();
- const QStringList fallbacks = fontDB->fallbacksForFamily(QString(), QFont::StyleNormal
+ const QStringList fallbacks = qt_fallbacksForFamily(QString(), QFont::StyleNormal
, QFont::StyleHint(d->request.styleHint), QChar::Script_Common);
if (!fallbacks.isEmpty())
return fallbacks.first();
diff --git a/src/gui/text/qfontdatabase.cpp b/src/gui/text/qfontdatabase.cpp
index 8916705c0e..2f8af2315d 100644
--- a/src/gui/text/qfontdatabase.cpp
+++ b/src/gui/text/qfontdatabase.cpp
@@ -47,6 +47,7 @@
#include <qpa/qplatformfontdatabase.h>
#include <qpa/qplatformtheme.h>
+#include <QtCore/qcache.h>
#include <QtCore/qmath.h>
#include <stdlib.h>
@@ -413,11 +414,45 @@ void QtFontFamily::ensurePopulated()
Q_ASSERT_X(populated, Q_FUNC_INFO, qPrintable(name));
}
+
+struct FallbacksCacheKey {
+ QString family;
+ QFont::Style style;
+ QFont::StyleHint styleHint;
+ QChar::Script script;
+};
+
+inline bool operator==(const FallbacksCacheKey &lhs, const FallbacksCacheKey &rhs) Q_DECL_NOTHROW
+{
+ return lhs.script == rhs.script &&
+ lhs.styleHint == rhs.styleHint &&
+ lhs.style == rhs.style &&
+ lhs.family == rhs.family;
+}
+
+inline bool operator!=(const FallbacksCacheKey &lhs, const FallbacksCacheKey &rhs) Q_DECL_NOTHROW
+{
+ return !operator==(lhs, rhs);
+}
+
+inline uint qHash(const FallbacksCacheKey &key, uint seed = 0) Q_DECL_NOTHROW
+{
+ QtPrivate::QHashCombine hash;
+ seed = hash(seed, key.family);
+ seed = hash(seed, int(key.style));
+ seed = hash(seed, int(key.styleHint));
+ seed = hash(seed, int(key.script));
+ return seed;
+}
+
+
class QFontDatabasePrivate
{
public:
QFontDatabasePrivate()
- : count(0), families(0), reregisterAppFonts(false)
+ : count(0), families(0),
+ fallbacksCache(64),
+ reregisterAppFonts(false)
{ }
~QFontDatabasePrivate() {
@@ -443,6 +478,7 @@ public:
int count;
QtFontFamily **families;
+ QCache<FallbacksCacheKey, QStringList> fallbacksCache;
struct ApplicationFont {
@@ -461,6 +497,8 @@ public:
void QFontDatabasePrivate::invalidate()
{
QFontCache::instance()->clear();
+
+ fallbacksCache.clear();
free();
QGuiApplicationPrivate::platformIntegration()->fontDatabase()->invalidate();
emit static_cast<QGuiApplication *>(QCoreApplication::instance())->fontDatabaseChanged();
@@ -680,8 +718,10 @@ Q_GLOBAL_STATIC_WITH_ARGS(QMutex, fontDatabaseMutex, (QMutex::Recursive))
void qt_cleanupFontDatabase()
{
QFontDatabasePrivate *db = privateDb();
- if (db)
+ if (db) {
+ db->fallbacksCache.clear();
db->free();
+ }
}
// used in qfontengine_x11.cpp
@@ -800,9 +840,15 @@ QStringList QPlatformFontDatabase::fallbacksForFamily(const QString &family, QFo
QStringList qt_fallbacksForFamily(const QString &family, QFont::Style style, QFont::StyleHint styleHint, QChar::Script script)
{
+ QFontDatabasePrivate *db = privateDb();
+
+ const FallbacksCacheKey cacheKey = { family, style, styleHint, script };
+
+ if (const QStringList *fallbacks = db->fallbacksCache.object(cacheKey))
+ return *fallbacks;
+
// make sure that the db has all fallback families
QStringList retList = QGuiApplicationPrivate::platformIntegration()->fontDatabase()->fallbacksForFamily(family,style,styleHint,script);
- QFontDatabasePrivate *db = privateDb();
QStringList::iterator i;
for (i = retList.begin(); i != retList.end(); ++i) {
@@ -818,6 +864,9 @@ QStringList qt_fallbacksForFamily(const QString &family, QFont::Style style, QFo
--i;
}
}
+
+ db->fallbacksCache.insert(cacheKey, new QStringList(retList));
+
return retList;
}
diff --git a/src/network/kernel/qdnslookup.cpp b/src/network/kernel/qdnslookup.cpp
index 150beb4d39..4a275f0700 100644
--- a/src/network/kernel/qdnslookup.cpp
+++ b/src/network/kernel/qdnslookup.cpp
@@ -148,6 +148,9 @@ static void qt_qdnsservicerecord_sort(QList<QDnsServiceRecord> &records)
}
}
+const char *QDnsLookupPrivate::msgNoIpV6NameServerAdresses =
+ QT_TRANSLATE_NOOP("QDnsLookupRunnable", "IPv6 addresses for nameservers are currently not supported");
+
/*!
\class QDnsLookup
\brief The QDnsLookup class represents a DNS lookup.
diff --git a/src/network/kernel/qdnslookup_p.h b/src/network/kernel/qdnslookup_p.h
index 0ac37f6636..3c8c4d5824 100644
--- a/src/network/kernel/qdnslookup_p.h
+++ b/src/network/kernel/qdnslookup_p.h
@@ -89,6 +89,8 @@ public:
void _q_lookupFinished(const QDnsLookupReply &reply);
+ static const char *msgNoIpV6NameServerAdresses;
+
bool isFinished;
QString name;
QDnsLookup::Type type;
diff --git a/src/network/kernel/qdnslookup_unix.cpp b/src/network/kernel/qdnslookup_unix.cpp
index cb8129efc5..b78db338ce 100644
--- a/src/network/kernel/qdnslookup_unix.cpp
+++ b/src/network/kernel/qdnslookup_unix.cpp
@@ -168,9 +168,9 @@ void QDnsLookupRunnable::query(const int requestType, const QByteArray &requestN
ns->sin6_addr.s6_addr[i] = ipv6Address[i];
}
#else
- qWarning("IPv6 addresses for nameservers is currently not supported");
+ qWarning("%s", QDnsLookupPrivate::msgNoIpV6NameServerAdresses);
reply->error = QDnsLookup::ResolverError;
- reply->errorString = tr("IPv6 addresses for nameservers is currently not supported");
+ reply->errorString = tr(QDnsLookupPrivate::msgNoIpV6NameServerAdresses);
return;
#endif
}
diff --git a/src/network/kernel/qdnslookup_win.cpp b/src/network/kernel/qdnslookup_win.cpp
index 4a6c631983..df0203bebb 100644
--- a/src/network/kernel/qdnslookup_win.cpp
+++ b/src/network/kernel/qdnslookup_win.cpp
@@ -60,9 +60,9 @@ void QDnsLookupRunnable::query(const int requestType, const QByteArray &requestN
// For supoprting IPv6 nameserver addresses, we'll need to switch
// from DnsQuey() to DnsQueryEx() as it supports passing an IPv6
// address in the nameserver list
- qWarning("IPv6 addresses for nameservers are currently not supported");
+ qWarning("%s", QDnsLookupPrivate::msgNoIpV6NameServerAdresses);
reply->error = QDnsLookup::ResolverError;
- reply->errorString = tr("IPv6 addresses for nameservers are currently not supported");
+ reply->errorString = tr(QDnsLookupPrivate::msgNoIpV6NameServerAdresses);
return;
}
}
diff --git a/src/network/kernel/qnetworkinterface_unix.cpp b/src/network/kernel/qnetworkinterface_unix.cpp
index dca9aa2c93..e7b62effcb 100644
--- a/src/network/kernel/qnetworkinterface_unix.cpp
+++ b/src/network/kernel/qnetworkinterface_unix.cpp
@@ -360,10 +360,15 @@ static QList<QNetworkInterfacePrivate *> createInterfaces(ifaddrs *rawList)
{
QList<QNetworkInterfacePrivate *> interfaces;
QSet<QString> seenInterfaces;
-
- // on Linux, AF_PACKET addresses carry the hardware address and interface index;
- // scan for them first (they're usually first, but we have no guarantee this
- // will be the case forever)
+ QVarLengthArray<int, 16> seenIndexes; // faster than QSet<int>
+
+ // On Linux, glibc, uClibc and MUSL obtain the address listing via two
+ // netlink calls: first an RTM_GETLINK to obtain the interface listing,
+ // then one RTM_GETADDR to get all the addresses (uClibc implementation is
+ // copied from glibc; Bionic currently doesn't support getifaddrs). They
+ // synthesize AF_PACKET addresses from the RTM_GETLINK responses, which
+ // means by construction they currently show up first in the interface
+ // listing.
for (ifaddrs *ptr = rawList; ptr; ptr = ptr->ifa_next) {
if (ptr->ifa_addr && ptr->ifa_addr->sa_family == AF_PACKET) {
sockaddr_ll *sll = (sockaddr_ll *)ptr->ifa_addr;
@@ -374,23 +379,30 @@ static QList<QNetworkInterfacePrivate *> createInterfaces(ifaddrs *rawList)
iface->flags = convertFlags(ptr->ifa_flags);
iface->hardwareAddress = iface->makeHwAddress(sll->sll_halen, (uchar*)sll->sll_addr);
+ Q_ASSERT(!seenIndexes.contains(iface->index));
+ seenIndexes.append(iface->index);
seenInterfaces.insert(iface->name);
}
}
// see if we missed anything:
- // virtual interfaces with no HW address have no AF_PACKET
+ // - virtual interfaces with no HW address have no AF_PACKET
+ // - interface labels have no AF_PACKET, but shouldn't be shown as a new interface
for (ifaddrs *ptr = rawList; ptr; ptr = ptr->ifa_next) {
if (ptr->ifa_addr && ptr->ifa_addr->sa_family != AF_PACKET) {
QString name = QString::fromLatin1(ptr->ifa_name);
if (seenInterfaces.contains(name))
continue;
+ int ifindex = if_nametoindex(ptr->ifa_name);
+ if (seenIndexes.contains(ifindex))
+ continue;
+
QNetworkInterfacePrivate *iface = new QNetworkInterfacePrivate;
interfaces << iface;
iface->name = name;
iface->flags = convertFlags(ptr->ifa_flags);
- iface->index = if_nametoindex(ptr->ifa_name);
+ iface->index = ifindex;
}
}
@@ -469,7 +481,7 @@ static QList<QNetworkInterfacePrivate *> interfaceListing()
interfaces = createInterfaces(interfaceListing);
for (ifaddrs *ptr = interfaceListing; ptr; ptr = ptr->ifa_next) {
- // Get the interface index
+ // Find the interface
QString name = QString::fromLatin1(ptr->ifa_name);
QNetworkInterfacePrivate *iface = 0;
QList<QNetworkInterfacePrivate *>::Iterator if_it = interfaces.begin();
@@ -479,6 +491,18 @@ static QList<QNetworkInterfacePrivate *> interfaceListing()
iface = *if_it;
break;
}
+
+ if (!iface) {
+ // it may be an interface label, search by interface index
+ int ifindex = if_nametoindex(ptr->ifa_name);
+ for (if_it = interfaces.begin(); if_it != interfaces.end(); ++if_it)
+ if ((*if_it)->index == ifindex) {
+ // found this interface already
+ iface = *if_it;
+ break;
+ }
+ }
+
if (!iface) {
// skip all non-IP interfaces
continue;
diff --git a/src/network/socket/qnativesocketengine_winrt_p.h b/src/network/socket/qnativesocketengine_winrt_p.h
index 912b7db973..c48b0e85d9 100644
--- a/src/network/socket/qnativesocketengine_winrt_p.h
+++ b/src/network/socket/qnativesocketengine_winrt_p.h
@@ -96,7 +96,7 @@ public:
qint64 read(char *data, qint64 maxlen);
qint64 write(const char *data, qint64 len);
- qint64 readDatagram(char *data, qint64 maxlen, QIpPacketHeader *, PacketHeaderOptions);
+ qint64 readDatagram(char *data, qint64 maxlen, QIpPacketHeader * = 0, PacketHeaderOptions = WantNone);
qint64 writeDatagram(const char *data, qint64 len, const QIpPacketHeader &header);
bool hasPendingDatagrams() const;
qint64 pendingDatagramSize() const;
diff --git a/src/platformheaders/windowsfunctions/qwindowswindowfunctions.h b/src/platformheaders/windowsfunctions/qwindowswindowfunctions.h
index 4c6d01cc52..720f7f31be 100644
--- a/src/platformheaders/windowsfunctions/qwindowswindowfunctions.h
+++ b/src/platformheaders/windowsfunctions/qwindowswindowfunctions.h
@@ -60,6 +60,15 @@ public:
if (func)
func(window, type);
}
+
+ typedef void (*SetHasBorderInFullScreen)(QWindow *window, bool border);
+ static const QByteArray setHasBorderInFullScreenIdentifier() { return QByteArrayLiteral("WindowsSetHasBorderInFullScreen"); }
+ static void setHasBorderInFullScreen(QWindow *window, bool border)
+ {
+ SetHasBorderInFullScreen func = reinterpret_cast<SetHasBorderInFullScreen>(QGuiApplication::platformFunction(setHasBorderInFullScreenIdentifier()));
+ if (func)
+ func(window, border);
+ }
};
Q_DECLARE_OPERATORS_FOR_FLAGS(QWindowsWindowFunctions::TouchWindowTouchTypes)
diff --git a/src/platformheaders/windowsfunctions/qwindowswindowfunctions.qdoc b/src/platformheaders/windowsfunctions/qwindowswindowfunctions.qdoc
index 84fae2f56d..d6b8764e7b 100644
--- a/src/platformheaders/windowsfunctions/qwindowswindowfunctions.qdoc
+++ b/src/platformheaders/windowsfunctions/qwindowswindowfunctions.qdoc
@@ -69,3 +69,29 @@
This is a convenience function that can be used directly instead of resolving the function pointer.
\a window and \a type will be relayed to the function retrieved by QGuiApplication
*/
+
+/*!
+ \typedef QWindowsWindowFunctions::SetHasBorderInFullScreen
+
+ This is the typedef for the function returned by QGuiApplication::platformFunction when passed setHasBorderInFullScreenIdentifier.
+*/
+
+/*!
+ \fn QByteArray QWindowsWindowFunctions::setHasBorderInFullScreenIdentifier()
+ \since 5.6
+
+ This function returns the bytearray that can be used to query
+ QGuiApplication::platformFunction to retrieve the SetHasBorderInFullScreen function.
+*/
+
+/*!
+ \fn void QWindowsWindowFunctions::setHasBorderInFullScreen(QWindow *window, bool border)
+ \since 5.6
+
+ This is a convenience function that can be used directly instead of resolving the function pointer.
+ \a window and \a border will be relayed to the function retrieved by QGuiApplication. When \a border
+ is true then it will enable the WS_BORDER flag in full screen mode to enable other top level windows
+ inside the application to appear on top when required.
+
+ See also \l [QtDoc] {Fullscreen OpenGL Based Windows}
+*/
diff --git a/src/platformsupport/platformcompositor/qopenglcompositorbackingstore.cpp b/src/platformsupport/platformcompositor/qopenglcompositorbackingstore.cpp
index 6f71fb637f..fee3146f04 100644
--- a/src/platformsupport/platformcompositor/qopenglcompositorbackingstore.cpp
+++ b/src/platformsupport/platformcompositor/qopenglcompositorbackingstore.cpp
@@ -35,6 +35,7 @@
#include <QtGui/QWindow>
#include <QtGui/QPainter>
#include <qpa/qplatformbackingstore.h>
+#include <private/qwindow_p.h>
#include "qopenglcompositorbackingstore_p.h"
#include "qopenglcompositor_p.h"
@@ -198,6 +199,8 @@ void QOpenGLCompositorBackingStore::composeAndFlush(QWindow *window, const QRegi
dstCtx->makeCurrent(dstWin);
+ QWindowPrivate::get(window)->lastComposeTime.start();
+
m_textures->clear();
for (int i = 0; i < textures->count(); ++i)
m_textures->appendTexture(textures->source(i), textures->textureId(i), textures->geometry(i),
diff --git a/src/plugins/platforminputcontexts/compose/generator/qtablegenerator.cpp b/src/plugins/platforminputcontexts/compose/generator/qtablegenerator.cpp
index ad9877eb25..4126456f90 100644
--- a/src/plugins/platforminputcontexts/compose/generator/qtablegenerator.cpp
+++ b/src/plugins/platforminputcontexts/compose/generator/qtablegenerator.cpp
@@ -263,11 +263,11 @@ QString TableGenerator::findComposeFile()
{
// check if XCOMPOSEFILE points to a Compose file
if (qEnvironmentVariableIsSet("XCOMPOSEFILE")) {
- QString path(qgetenv("XCOMPOSEFILE"));
- if (path.endsWith(QLatin1String("Compose")))
+ const QString path = QFile::decodeName(qgetenv("XCOMPOSEFILE"));
+ if (QFile::exists(path))
return path;
else
- qWarning("Qt Warning: XCOMPOSEFILE doesn't point to a valid Compose file");
+ qWarning("$XCOMPOSEFILE doesn't point to an existing file");
}
// check if user’s home directory has a file named .XCompose
diff --git a/src/plugins/platforms/android/androidjnimain.cpp b/src/plugins/platforms/android/androidjnimain.cpp
index 2bc3b0dc7d..7045533fca 100644
--- a/src/plugins/platforms/android/androidjnimain.cpp
+++ b/src/plugins/platforms/android/androidjnimain.cpp
@@ -34,6 +34,7 @@
#include <dlfcn.h>
#include <pthread.h>
+#include <semaphore.h>
#include <qplugin.h>
#include <qdebug.h>
@@ -91,6 +92,8 @@ extern "C" typedef int (*Main)(int, char **); //use the standard main method to
static Main m_main = nullptr;
static void *m_mainLibraryHnd = nullptr;
static QList<QByteArray> m_applicationParams;
+pthread_t m_qtAppThread = 0;
+static sem_t m_exitSemaphore, m_terminateSemaphore;
struct SurfaceData
{
@@ -454,6 +457,10 @@ static void *startMainMethod(void */*data*/)
if (vm != 0)
vm->DetachCurrentThread();
+ sem_post(&m_terminateSemaphore);
+ sem_wait(&m_exitSemaphore);
+ sem_destroy(&m_exitSemaphore);
+
// We must call exit() to ensure that all global objects will be destructed
exit(ret);
return 0;
@@ -503,8 +510,13 @@ static jboolean startQtApplication(JNIEnv *env, jobject /*object*/, jstring para
return false;
}
- pthread_t appThread;
- return pthread_create(&appThread, nullptr, startMainMethod, nullptr) == 0;
+ if (sem_init(&m_exitSemaphore, 0, 0) == -1)
+ return false;
+
+ if (sem_init(&m_terminateSemaphore, 0, 0) == -1)
+ return false;
+
+ return pthread_create(&m_qtAppThread, nullptr, startMainMethod, nullptr) == 0;
}
@@ -518,6 +530,8 @@ static void quitQtAndroidPlugin(JNIEnv *env, jclass /*clazz*/)
static void terminateQt(JNIEnv *env, jclass /*clazz*/)
{
+ sem_wait(&m_terminateSemaphore);
+ sem_destroy(&m_terminateSemaphore);
env->DeleteGlobalRef(m_applicationClass);
env->DeleteGlobalRef(m_classLoaderObject);
if (m_resourcesObj)
@@ -535,6 +549,8 @@ static void terminateQt(JNIEnv *env, jclass /*clazz*/)
m_androidPlatformIntegration = nullptr;
delete m_androidAssetsFileEngineHandler;
m_androidAssetsFileEngineHandler = nullptr;
+ sem_post(&m_exitSemaphore);
+ pthread_join(m_qtAppThread, nullptr);
}
static void setSurface(JNIEnv *env, jobject /*thiz*/, jint id, jobject jSurface, jint w, jint h)
diff --git a/src/plugins/platforms/android/qandroidplatformfontdatabase.cpp b/src/plugins/platforms/android/qandroidplatformfontdatabase.cpp
index 835ca8a10a..a21aac51b4 100644
--- a/src/plugins/platforms/android/qandroidplatformfontdatabase.cpp
+++ b/src/plugins/platforms/android/qandroidplatformfontdatabase.cpp
@@ -74,7 +74,7 @@ QStringList QAndroidPlatformFontDatabase::fallbacksForFamily(const QString &fami
result.append(QString(qgetenv("QT_ANDROID_FONTS_SERIF")).split(QLatin1Char(';')));
else
result.append(QString(qgetenv("QT_ANDROID_FONTS")).split(QLatin1Char(';')));
- result.append(QPlatformFontDatabase::fallbacksForFamily(family, style, styleHint, script));
+ result.append(QBasicFontDatabase::fallbacksForFamily(family, style, styleHint, script));
return result;
}
diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm
index 18abaddfd7..2d8abba189 100644
--- a/src/plugins/platforms/cocoa/qcocoawindow.mm
+++ b/src/plugins/platforms/cocoa/qcocoawindow.mm
@@ -502,7 +502,11 @@ void QCocoaWindow::setCocoaGeometry(const QRect &rect)
QMacAutoReleasePool pool;
if (m_contentViewIsEmbedded) {
- QPlatformWindow::setGeometry(rect);
+ if (m_qtView) {
+ [m_qtView setFrame:NSMakeRect(0, 0, rect.width(), rect.height())];
+ } else {
+ QPlatformWindow::setGeometry(rect);
+ }
return;
}
diff --git a/src/plugins/platforms/ios/qioscontext.mm b/src/plugins/platforms/ios/qioscontext.mm
index fe0ca33c13..8bdb4bcdb3 100644
--- a/src/plugins/platforms/ios/qioscontext.mm
+++ b/src/plugins/platforms/ios/qioscontext.mm
@@ -45,12 +45,15 @@
QIOSContext::QIOSContext(QOpenGLContext *context)
: QPlatformOpenGLContext()
, m_sharedContext(static_cast<QIOSContext *>(context->shareHandle()))
+ , m_eaglContext(0)
, m_format(context->format())
{
m_format.setRenderableType(QSurfaceFormat::OpenGLES);
- m_eaglContext = [[EAGLContext alloc]
- initWithAPI:EAGLRenderingAPI(m_format.majorVersion())
- sharegroup:m_sharedContext ? [m_sharedContext->m_eaglContext sharegroup] : nil];
+
+ EAGLSharegroup *shareGroup = m_sharedContext ? [m_sharedContext->m_eaglContext sharegroup] : nil;
+ const int preferredVersion = m_format.majorVersion() == 1 ? kEAGLRenderingAPIOpenGLES1 : kEAGLRenderingAPIOpenGLES3;
+ for (int version = preferredVersion; !m_eaglContext && version >= m_format.majorVersion(); --version)
+ m_eaglContext = [[EAGLContext alloc] initWithAPI:EAGLRenderingAPI(version) sharegroup:shareGroup];
if (m_eaglContext != nil) {
EAGLContext *originalContext = [EAGLContext currentContext];
diff --git a/src/plugins/platforms/ios/qiosmenu.mm b/src/plugins/platforms/ios/qiosmenu.mm
index f68321fb3b..5f9346816a 100644
--- a/src/plugins/platforms/ios/qiosmenu.mm
+++ b/src/plugins/platforms/ios/qiosmenu.mm
@@ -62,11 +62,23 @@ static NSString *const kSelectorPrefix = @"_qtMenuItem_";
{
if (self = [super init]) {
[self setVisibleMenuItems:visibleMenuItems];
+ [[NSNotificationCenter defaultCenter]
+ addObserver:self
+ selector:@selector(menuClosed)
+ name:UIMenuControllerDidHideMenuNotification object:nil];
}
return self;
}
+-(void)dealloc
+{
+ [[NSNotificationCenter defaultCenter]
+ removeObserver:self
+ name:UIMenuControllerDidHideMenuNotification object:nil];
+ [super dealloc];
+}
+
- (void)setVisibleMenuItems:(const QIOSMenuItemList &)visibleMenuItems
{
m_visibleMenuItems = visibleMenuItems;
@@ -86,6 +98,11 @@ static NSString *const kSelectorPrefix = @"_qtMenuItem_";
[[UIMenuController sharedMenuController] setMenuVisible:YES animated:NO];
}
+-(void)menuClosed
+{
+ QIOSMenu::currentMenu()->dismiss();
+}
+
- (id)targetForAction:(SEL)action withSender:(id)sender
{
Q_UNUSED(sender);
diff --git a/src/plugins/platforms/ios/qiostextresponder.mm b/src/plugins/platforms/ios/qiostextresponder.mm
index 9ca5e22b90..320b1cac61 100644
--- a/src/plugins/platforms/ios/qiostextresponder.mm
+++ b/src/plugins/platforms/ios/qiostextresponder.mm
@@ -318,7 +318,11 @@
// a regular responder transfer to another window. In the former case, iOS
// will set the new first-responder to our next-responder, and in the latter
// case we'll have an active responder candidate.
- if ([UIResponder currentFirstResponder] == [self nextResponder]) {
+ if (![UIResponder currentFirstResponder]) {
+ // No first responder set anymore, sync this with Qt by clearing the
+ // focus object.
+ m_inputContext->clearCurrentFocusObject();
+ } else if ([UIResponder currentFirstResponder] == [self nextResponder]) {
// We have resigned the keyboard, and transferred first responder back to the parent view
Q_ASSERT(!FirstResponderCandidate::currentCandidate());
if ([self currentImeState:Qt::ImEnabled].toBool()) {
@@ -364,6 +368,32 @@
[self sendKeyPressRelease:key modifiers:modifiers];
}
+- (BOOL)canPerformAction:(SEL)action withSender:(id)sender
+{
+ bool isEditAction = (action == @selector(cut:)
+ || action == @selector(copy:)
+ || action == @selector(paste:)
+ || action == @selector(delete:)
+ || action == @selector(toggleBoldface:)
+ || action == @selector(toggleItalics:)
+ || action == @selector(toggleUnderline:)
+ || action == @selector(undo)
+ || action == @selector(redo));
+
+ bool isSelectAction = (action == @selector(select:)
+ || action == @selector(selectAll:)
+ || action == @selector(paste:)
+ || action == @selector(undo)
+ || action == @selector(redo));
+
+ const bool unknownAction = !isEditAction && !isSelectAction;
+ const bool hasSelection = ![self selectedTextRange].empty;
+
+ if (unknownAction)
+ return [super canPerformAction:action withSender:sender];
+ return (hasSelection && isEditAction) || (!hasSelection && isSelectAction);
+}
+
- (void)cut:(id)sender
{
Q_UNUSED(sender);
@@ -382,6 +412,13 @@
[self sendShortcut:QKeySequence::Paste];
}
+- (void)select:(id)sender
+{
+ Q_UNUSED(sender);
+ [self sendShortcut:QKeySequence::MoveToPreviousWord];
+ [self sendShortcut:QKeySequence::SelectNextWord];
+}
+
- (void)selectAll:(id)sender
{
Q_UNUSED(sender);
@@ -580,7 +617,8 @@
- (UITextPosition *)endOfDocument
{
- int endPosition = [self currentImeState:Qt::ImSurroundingText].toString().length();
+ QString surroundingText = [self currentImeState:Qt::ImSurroundingText].toString();
+ int endPosition = surroundingText.length() + m_markedText.length();
return [QUITextPosition positionWithIndex:endPosition];
}
@@ -611,9 +649,18 @@
- (NSString *)textInRange:(UITextRange *)range
{
+ QString text = [self currentImeState:Qt::ImSurroundingText].toString();
+ if (!m_markedText.isEmpty()) {
+ // [UITextInput textInRange] is sparsely documented, but it turns out that unconfirmed
+ // marked text should be seen as a part of the text document. This is different from
+ // ImSurroundingText, which excludes it.
+ int cursorPos = [self currentImeState:Qt::ImCursorPosition].toInt();
+ text = text.left(cursorPos) + m_markedText + text.mid(cursorPos);
+ }
+
int s = static_cast<QUITextPosition *>([range start]).index;
int e = static_cast<QUITextPosition *>([range end]).index;
- return [self currentImeState:Qt::ImSurroundingText].toString().mid(s, e - s).toNSString();
+ return text.mid(s, e - s).toNSString();
}
- (void)setMarkedText:(NSString *)markedText selectedRange:(NSRange)selectedRange
@@ -882,6 +929,14 @@
if ([text isEqualToString:@"\n"]) {
[self sendKeyPressRelease:Qt::Key_Return modifiers:Qt::NoModifier];
+ // An onEnter handler of a TextInput might move to the next input by calling
+ // nextInput.forceActiveFocus() which changes the focusObject.
+ // In that case we don't want to hide the VKB.
+ if (focusObject != QGuiApplication::focusObject()) {
+ qImDebug() << "focusObject already changed, not resigning first responder.";
+ return;
+ }
+
if (self.returnKeyType == UIReturnKeyDone || self.returnKeyType == UIReturnKeyGo
|| self.returnKeyType == UIReturnKeySend || self.returnKeyType == UIReturnKeySearch)
[self resignFirstResponder];
diff --git a/src/plugins/platforms/windows/qwindowsbackingstore.cpp b/src/plugins/platforms/windows/qwindowsbackingstore.cpp
index bd5c35037d..135c9eb601 100644
--- a/src/plugins/platforms/windows/qwindowsbackingstore.cpp
+++ b/src/plugins/platforms/windows/qwindowsbackingstore.cpp
@@ -96,7 +96,12 @@ void QWindowsBackingStore::flush(QWindow *window, const QRegion &region,
RECT dirty = {dirtyRect.x(), dirtyRect.y(),
dirtyRect.x() + dirtyRect.width(), dirtyRect.y() + dirtyRect.height()};
UPDATELAYEREDWINDOWINFO info = {sizeof(info), NULL, &ptDst, &size, m_image->hdc(), &ptSrc, 0, &blend, ULW_ALPHA, &dirty};
- QWindowsContext::user32dll.updateLayeredWindowIndirect(rw->handle(), &info);
+ const BOOL result = QWindowsContext::user32dll.updateLayeredWindowIndirect(rw->handle(), &info);
+ if (!result)
+ qErrnoWarning("UpdateLayeredWindowIndirect failed for ptDst=(%d, %d),"
+ " size=(%dx%d), dirty=(%dx%d %d, %d)", r.x(), r.y(),
+ r.width(), r.height(), dirtyRect.width(), dirtyRect.height(),
+ dirtyRect.x(), dirtyRect.y());
} else {
QWindowsContext::user32dll.updateLayeredWindow(rw->handle(), NULL, &ptDst, &size, m_image->hdc(), &ptSrc, 0, &blend, ULW_ALPHA);
}
diff --git a/src/plugins/platforms/windows/qwindowsfontdatabase_ft.cpp b/src/plugins/platforms/windows/qwindowsfontdatabase_ft.cpp
index 361e7f4445..183c198806 100644
--- a/src/plugins/platforms/windows/qwindowsfontdatabase_ft.cpp
+++ b/src/plugins/platforms/windows/qwindowsfontdatabase_ft.cpp
@@ -192,7 +192,14 @@ typedef struct {
quint16 stringOffset;
} NAME_RECORD;
-static QString fontNameFromTTFile(const QString &filename)
+typedef struct {
+ quint32 tag;
+ quint16 majorVersion;
+ quint16 minorVersion;
+ quint32 numFonts;
+} TTC_TABLE_HEADER;
+
+static QString fontNameFromTTFile(const QString &filename, int startPos = 0)
{
QFile f(filename);
QString retVal;
@@ -200,6 +207,7 @@ static QString fontNameFromTTFile(const QString &filename)
qint64 bytesToRead;
if (f.open(QIODevice::ReadOnly)) {
+ f.seek(startPos);
OFFSET_TABLE ttOffsetTable;
bytesToRead = sizeof(OFFSET_TABLE);
bytesRead = f.read((char*)&ttOffsetTable, bytesToRead);
@@ -280,6 +288,37 @@ static QString fontNameFromTTFile(const QString &filename)
return retVal;
}
+static QStringList fontNamesFromTTCFile(const QString &filename)
+{
+ QFile f(filename);
+ QStringList retVal;
+ qint64 bytesRead;
+ qint64 bytesToRead;
+
+ if (f.open(QIODevice::ReadOnly)) {
+ TTC_TABLE_HEADER ttcTableHeader;
+ bytesToRead = sizeof(TTC_TABLE_HEADER);
+ bytesRead = f.read((char*)&ttcTableHeader, bytesToRead);
+ if (bytesToRead != bytesRead)
+ return retVal;
+ ttcTableHeader.majorVersion = qFromBigEndian(ttcTableHeader.majorVersion);
+ ttcTableHeader.minorVersion = qFromBigEndian(ttcTableHeader.minorVersion);
+ ttcTableHeader.numFonts = qFromBigEndian(ttcTableHeader.numFonts);
+
+ if (ttcTableHeader.majorVersion < 1 || ttcTableHeader.majorVersion > 2)
+ return retVal;
+ QVarLengthArray<quint32> offsetTable(ttcTableHeader.numFonts);
+ bytesToRead = sizeof(offsetTable) * ttcTableHeader.numFonts;
+ bytesRead = f.read((char*)offsetTable.data(), bytesToRead);
+ if (bytesToRead != bytesRead)
+ return retVal;
+ f.close();
+ for (int i = 0; i < (int)ttcTableHeader.numFonts; ++i)
+ retVal << fontNameFromTTFile(filename, qFromBigEndian(offsetTable[i]));
+ }
+ return retVal;
+}
+
static inline QString fontSettingsOrganization() { return QStringLiteral("Qt-Project"); }
static inline QString fontSettingsApplication() { return QStringLiteral("Qtbase"); }
static inline QString fontSettingsGroup() { return QStringLiteral("CEFontCache"); }
@@ -306,20 +345,28 @@ static QString findFontFile(const QString &faceName)
//empty the cache first, as it seems that it is dirty
settings.remove(QString());
- QDirIterator it(QStringLiteral("/Windows"), QStringList(QStringLiteral("*.ttf")), QDir::Files | QDir::Hidden | QDir::System);
-
+ QDirIterator it(QStringLiteral("/Windows"), QStringList() << QStringLiteral("*.ttf") << QStringLiteral("*.ttc"), QDir::Files | QDir::Hidden | QDir::System);
+ const QLatin1Char lowerF('f');
+ const QLatin1Char upperF('F');
while (it.hasNext()) {
const QString fontFile = it.next();
- const QString fontName = fontNameFromTTFile(fontFile);
- if (fontName.isEmpty())
- continue;
- fontCache.insert(fontName, fontFile);
- settings.setValue(fontName, fontFile);
-
- if (localizedName(fontName)) {
- QString englishFontName = getEnglishName(fontName);
- fontCache.insert(englishFontName, fontFile);
- settings.setValue(englishFontName, fontFile);
+ QStringList fontNames;
+ const QChar c = fontFile[fontFile.size() - 1];
+ if (c == lowerF || c == upperF)
+ fontNames << fontNameFromTTFile(fontFile);
+ else
+ fontNames << fontNamesFromTTCFile(fontFile);
+ foreach (const QString fontName, fontNames) {
+ if (fontName.isEmpty())
+ continue;
+ fontCache.insert(fontName, fontFile);
+ settings.setValue(fontName, fontFile);
+
+ if (localizedName(fontName)) {
+ QString englishFontName = getEnglishName(fontName);
+ fontCache.insert(englishFontName, fontFile);
+ settings.setValue(englishFontName, fontFile);
+ }
}
}
settings.endGroup();
@@ -675,7 +722,7 @@ QStringList QWindowsFontDatabaseFT::fallbacksForFamily(const QString &family, QF
result.append(QWindowsFontDatabase::extraTryFontsForFamily(family));
- result.append(QPlatformFontDatabase::fallbacksForFamily(family, style, styleHint, script));
+ result.append(QBasicFontDatabase::fallbacksForFamily(family, style, styleHint, script));
qCDebug(lcQpaFonts) << __FUNCTION__ << family << style << styleHint
<< script << result;
diff --git a/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.cpp b/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.cpp
index 593ac7d810..5e2e9f6454 100644
--- a/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.cpp
+++ b/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.cpp
@@ -485,9 +485,9 @@ qreal QWindowsFontEngineDirectWrite::maxCharWidth() const
return 0;
}
-QImage QWindowsFontEngineDirectWrite::alphaMapForGlyph(glyph_t glyph, QFixed subPixelPosition)
+QImage QWindowsFontEngineDirectWrite::alphaMapForGlyph(glyph_t glyph, QFixed subPixelPosition, const QTransform &t)
{
- QImage im = imageForGlyph(glyph, subPixelPosition, 0, QTransform());
+ QImage im = alphaRGBMapForGlyph(glyph, subPixelPosition, t);
QImage alphaMap(im.width(), im.height(), QImage::Format_Alpha8);
@@ -504,6 +504,11 @@ QImage QWindowsFontEngineDirectWrite::alphaMapForGlyph(glyph_t glyph, QFixed sub
return alphaMap;
}
+QImage QWindowsFontEngineDirectWrite::alphaMapForGlyph(glyph_t glyph, QFixed subPixelPosition)
+{
+ return alphaMapForGlyph(glyph, subPixelPosition, QTransform());
+}
+
bool QWindowsFontEngineDirectWrite::supportsSubPixelPositions() const
{
return true;
@@ -709,9 +714,9 @@ QString QWindowsFontEngineDirectWrite::fontNameSubstitute(const QString &familyN
glyph_metrics_t QWindowsFontEngineDirectWrite::alphaMapBoundingBox(glyph_t glyph, QFixed pos, const QTransform &matrix, GlyphFormat format)
{
Q_UNUSED(pos);
- int margin = 0;
- if (format == QFontEngine::Format_A32 || format == QFontEngine::Format_ARGB)
- margin = glyphMargin(QFontEngine::Format_A32);
+ Q_UNUSED(format);
+
+ int margin = glyphMargin(QFontEngine::Format_A32);
glyph_metrics_t gm = QFontEngine::boundingBox(glyph, matrix);
gm.width += margin * 2;
gm.height += margin * 2;
diff --git a/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.h b/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.h
index da772469e9..cee8691d69 100644
--- a/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.h
+++ b/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.h
@@ -86,6 +86,7 @@ public:
bool supportsSubPixelPositions() const;
QImage alphaMapForGlyph(glyph_t glyph, QFixed subPixelPosition);
+ QImage alphaMapForGlyph(glyph_t glyph, QFixed subPixelPosition, const QTransform &t);
QImage alphaRGBMapForGlyph(glyph_t t, QFixed subPixelPosition, const QTransform &xform);
QFontEngine *cloneWithSize(qreal pixelSize) const;
diff --git a/src/plugins/platforms/windows/qwindowskeymapper.cpp b/src/plugins/platforms/windows/qwindowskeymapper.cpp
index 4c0b94e6e7..c5dff60114 100644
--- a/src/plugins/platforms/windows/qwindowskeymapper.cpp
+++ b/src/plugins/platforms/windows/qwindowskeymapper.cpp
@@ -86,10 +86,15 @@ QT_BEGIN_NAMESPACE
The code originates from \c qkeymapper_win.cpp.
*/
+static void clearKeyRecorderOnApplicationInActive(Qt::ApplicationState state);
+
QWindowsKeyMapper::QWindowsKeyMapper()
: m_useRTLExtensions(false), m_keyGrabber(0)
{
memset(keyLayout, 0, sizeof(keyLayout));
+ QGuiApplication *app = static_cast<QGuiApplication *>(QGuiApplication::instance());
+ QObject::connect(app, &QGuiApplication::applicationStateChanged,
+ app, clearKeyRecorderOnApplicationInActive);
}
QWindowsKeyMapper::~QWindowsKeyMapper()
@@ -144,6 +149,12 @@ struct KeyRecorder
};
static KeyRecorder key_recorder;
+static void clearKeyRecorderOnApplicationInActive(Qt::ApplicationState state)
+{
+ if (state == Qt::ApplicationInactive)
+ key_recorder.clearKeys();
+}
+
KeyRecord *KeyRecorder::findKey(int code, bool remove)
{
KeyRecord *result = 0;
diff --git a/src/plugins/platforms/windows/qwindowsnativeinterface.cpp b/src/plugins/platforms/windows/qwindowsnativeinterface.cpp
index 5b0f6f637e..c5c60aa882 100644
--- a/src/plugins/platforms/windows/qwindowsnativeinterface.cpp
+++ b/src/plugins/platforms/windows/qwindowsnativeinterface.cpp
@@ -245,6 +245,8 @@ QFunctionPointer QWindowsNativeInterface::platformFunction(const QByteArray &fun
{
if (function == QWindowsWindowFunctions::setTouchWindowTouchTypeIdentifier())
return QFunctionPointer(QWindowsWindow::setTouchWindowTouchTypeStatic);
+ else if (function == QWindowsWindowFunctions::setHasBorderInFullScreenIdentifier())
+ return QFunctionPointer(QWindowsWindow::setHasBorderInFullScreenStatic);
return Q_NULLPTR;
}
diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp
index 611d586b19..cac8ec5ecc 100644
--- a/src/plugins/platforms/windows/qwindowswindow.cpp
+++ b/src/plugins/platforms/windows/qwindowswindow.cpp
@@ -1720,7 +1720,7 @@ void QWindowsWindow::setWindowState_sys(Qt::WindowState newState)
if (!m_savedStyle) {
m_savedStyle = style();
#ifndef Q_OS_WINCE
- if (oldState == Qt::WindowMinimized) {
+ if (oldState == Qt::WindowMinimized || oldState == Qt::WindowMaximized) {
const QRect nf = normalFrameGeometry(m_data.hwnd);
if (nf.isValid())
m_savedFrameGeometry = nf;
@@ -1735,6 +1735,8 @@ void QWindowsWindow::setWindowState_sys(Qt::WindowState newState)
newStyle |= WS_SYSMENU;
if (visible)
newStyle |= WS_VISIBLE;
+ if (testFlag(HasBorderInFullScreen))
+ newStyle |= WS_BORDER;
setStyle(newStyle);
// Use geometry of QWindow::screen() within creation or the virtual screen the
// window is in (QTBUG-31166, QTBUG-30724).
@@ -1769,7 +1771,7 @@ void QWindowsWindow::setWindowState_sys(Qt::WindowState newState)
// preserve maximized state
if (visible) {
setFlag(WithinMaximize);
- ShowWindow(m_data.hwnd, (newState == Qt::WindowMaximized) ? SW_MAXIMIZE : SW_SHOWNOACTIVATE);
+ ShowWindow(m_data.hwnd, (newState == Qt::WindowMaximized) ? SW_MAXIMIZE : SW_SHOWNA);
clearFlag(WithinMaximize);
}
m_savedStyle = 0;
@@ -2371,4 +2373,19 @@ void QWindowsWindow::aboutToMakeCurrent()
#endif
}
+void QWindowsWindow::setHasBorderInFullScreenStatic(QWindow *window, bool border)
+{
+ if (!window->handle())
+ return;
+ static_cast<QWindowsWindow *>(window->handle())->setHasBorderInFullScreen(border);
+}
+
+void QWindowsWindow::setHasBorderInFullScreen(bool border)
+{
+ if (border)
+ setFlag(HasBorderInFullScreen);
+ else
+ clearFlag(HasBorderInFullScreen);
+}
+
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/windows/qwindowswindow.h b/src/plugins/platforms/windows/qwindowswindow.h
index 4172a3d850..710cab8597 100644
--- a/src/plugins/platforms/windows/qwindowswindow.h
+++ b/src/plugins/platforms/windows/qwindowswindow.h
@@ -137,7 +137,8 @@ public:
WithinMaximize = 0x40000,
MaximizeToFullScreen = 0x80000,
InputMethodDisabled = 0x100000,
- Compositing = 0x200000
+ Compositing = 0x200000,
+ HasBorderInFullScreen = 0x400000
};
QWindowsWindow(QWindow *window, const QWindowsWindowData &data);
@@ -251,7 +252,8 @@ public:
static void setTouchWindowTouchTypeStatic(QWindow *window, QWindowsWindowFunctions::TouchWindowTouchTypes touchTypes);
void registerTouchWindow(QWindowsWindowFunctions::TouchWindowTouchTypes touchTypes = QWindowsWindowFunctions::NormalTouch);
-
+ static void setHasBorderInFullScreenStatic(QWindow *window, bool border);
+ void setHasBorderInFullScreen(bool border);
private:
inline void show_sys() const;
inline void hide_sys() const;
diff --git a/src/plugins/platforms/winrt/qwinrtfontdatabase.cpp b/src/plugins/platforms/winrt/qwinrtfontdatabase.cpp
index c348faf015..793256a83f 100644
--- a/src/plugins/platforms/winrt/qwinrtfontdatabase.cpp
+++ b/src/plugins/platforms/winrt/qwinrtfontdatabase.cpp
@@ -428,6 +428,21 @@ QFontEngine *QWinRTFontDatabase::fontEngine(const QFontDef &fontDef, void *handl
return engine;
}
+QStringList QWinRTFontDatabase::fallbacksForFamily(const QString &family, QFont::Style style,
+ QFont::StyleHint styleHint,
+ QChar::Script script) const
+{
+ Q_UNUSED(style)
+ Q_UNUSED(styleHint)
+ Q_UNUSED(script)
+
+ QStringList result;
+ if (family == QLatin1String("Helvetica"))
+ result.append(QStringLiteral("Arial"));
+ result.append(QBasicFontDatabase::fallbacksForFamily(family, style, styleHint, script));
+ return result;
+}
+
void QWinRTFontDatabase::releaseHandle(void *handle)
{
if (!handle)
diff --git a/src/plugins/platforms/winrt/qwinrtfontdatabase.h b/src/plugins/platforms/winrt/qwinrtfontdatabase.h
index a88092e432..41619f5bd8 100644
--- a/src/plugins/platforms/winrt/qwinrtfontdatabase.h
+++ b/src/plugins/platforms/winrt/qwinrtfontdatabase.h
@@ -60,6 +60,8 @@ public:
void populateFontDatabase() Q_DECL_OVERRIDE;
void populateFamily(const QString &familyName) Q_DECL_OVERRIDE;
QFontEngine *fontEngine(const QFontDef &fontDef, void *handle) Q_DECL_OVERRIDE;
+ QStringList fallbacksForFamily(const QString &family, QFont::Style style,
+ QFont::StyleHint styleHint, QChar::Script script) const Q_DECL_OVERRIDE;
void releaseHandle(void *handle) Q_DECL_OVERRIDE;
private:
QHash<IDWriteFontFile *, FontDescription> m_fonts;
diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp
index 1d20432bd4..e28d84cf92 100644
--- a/src/plugins/platforms/xcb/qxcbconnection.cpp
+++ b/src/plugins/platforms/xcb/qxcbconnection.cpp
@@ -179,42 +179,6 @@ QXcbScreen* QXcbConnection::findScreenForOutput(xcb_window_t rootWindow, xcb_ran
return 0;
}
-QXcbScreen* QXcbConnection::createScreen(QXcbVirtualDesktop* virtualDesktop,
- xcb_randr_output_t outputId,
- xcb_randr_get_output_info_reply_t *output)
-{
- QString name;
- if (output)
- name = QString::fromUtf8((const char*)xcb_randr_get_output_info_name(output),
- xcb_randr_get_output_info_name_length(output));
- else {
- QByteArray displayName = m_displayName;
- int dotPos = displayName.lastIndexOf('.');
- if (dotPos != -1)
- displayName.truncate(dotPos);
- name = QString::fromLocal8Bit(displayName) + QLatin1Char('.') + QString::number(virtualDesktop->number());
- }
-
- return new QXcbScreen(this, virtualDesktop, outputId, output, name);
-}
-
-bool QXcbConnection::checkOutputIsPrimary(xcb_window_t rootWindow, xcb_randr_output_t output)
-{
- xcb_generic_error_t *error = 0;
- xcb_randr_get_output_primary_cookie_t primaryCookie =
- xcb_randr_get_output_primary(xcb_connection(), rootWindow);
- QScopedPointer<xcb_randr_get_output_primary_reply_t, QScopedPointerPodDeleter> primary (
- xcb_randr_get_output_primary_reply(xcb_connection(), primaryCookie, &error));
- if (!primary || error) {
- qWarning("failed to get the primary output of the screen");
- free(error);
- error = NULL;
- }
- const bool isPrimary = primary ? (primary->output == output) : false;
-
- return isPrimary;
-}
-
QXcbVirtualDesktop* QXcbConnection::virtualDesktopForRootWindow(xcb_window_t rootWindow)
{
foreach (QXcbVirtualDesktop *virtualDesktop, m_virtualDesktops) {
@@ -237,8 +201,9 @@ void QXcbConnection::updateScreens(const xcb_randr_notify_event_t *event)
// Not for us
return;
- qCDebug(lcQpaScreen) << "QXcbConnection: XCB_RANDR_NOTIFY_CRTC_CHANGE:" << crtc.crtc;
QXcbScreen *screen = findScreenForCrtc(crtc.window, crtc.crtc);
+ qCDebug(lcQpaScreen) << "QXcbConnection: XCB_RANDR_NOTIFY_CRTC_CHANGE:" << crtc.crtc
+ << "mode" << crtc.mode << "relevant screen" << screen;
// Only update geometry when there's a valid mode on the CRTC
// CRTC with node mode could mean that output has been disabled, and we'll
// get RRNotifyOutputChange notification for that.
@@ -260,16 +225,7 @@ void QXcbConnection::updateScreens(const xcb_randr_notify_event_t *event)
if (screen && output.connection == XCB_RANDR_CONNECTION_DISCONNECTED) {
qCDebug(lcQpaScreen) << "screen" << screen->name() << "has been disconnected";
-
- // Known screen removed -> delete it
- m_screens.removeOne(screen);
- virtualDesktop->removeScreen(screen);
-
- QXcbIntegration::instance()->destroyScreen(screen);
-
- // QTBUG-40174, QTBUG-42985: If all screens are removed, wait
- // and start rendering again later if a screen becomes available.
-
+ destroyScreen(screen);
} else if (!screen && output.connection == XCB_RANDR_CONNECTION_CONNECTED) {
// New XRandR output is available and it's enabled
if (output.crtc != XCB_NONE && output.mode != XCB_NONE) {
@@ -278,59 +234,142 @@ void QXcbConnection::updateScreens(const xcb_randr_notify_event_t *event)
QScopedPointer<xcb_randr_get_output_info_reply_t, QScopedPointerPodDeleter> outputInfo(
xcb_randr_get_output_info_reply(xcb_connection(), outputInfoCookie, NULL));
- screen = createScreen(virtualDesktop, output.output, outputInfo.data());
- qCDebug(lcQpaScreen) << "output" << screen->name() << "is connected and enabled";
-
- screen->setPrimary(checkOutputIsPrimary(output.window, output.output));
- virtualDesktop->addScreen(screen);
- m_screens << screen;
- QXcbIntegration::instance()->screenAdded(screen, screen->isPrimary());
+ // Find a fake screen
+ foreach (QPlatformScreen *scr, virtualDesktop->screens()) {
+ QXcbScreen *xcbScreen = (QXcbScreen *)scr;
+ if (xcbScreen->output() == XCB_NONE) {
+ screen = xcbScreen;
+ break;
+ }
+ }
- // Windows which had null screens have already had expose events by now.
- // They need to be told the screen is back, it's OK to render.
- foreach (QWindow *window, QGuiApplication::topLevelWindows()) {
- QXcbWindow *xcbWin = static_cast<QXcbWindow*>(window->handle());
- if (xcbWin)
- xcbWin->maybeSetScreen(screen);
+ if (screen) {
+ QString nameWas = screen->name();
+ // Transform the fake screen into a physical screen
+ screen->setOutput(output.output, outputInfo.data());
+ updateScreen(screen, output);
+ qCDebug(lcQpaScreen) << "output" << screen->name()
+ << "is connected and enabled; was fake:" << nameWas;
+ } else {
+ screen = createScreen(virtualDesktop, output, outputInfo.data());
+ qCDebug(lcQpaScreen) << "output" << screen->name() << "is connected and enabled";
}
}
- // else ignore disabled screens
} else if (screen) {
- // Screen has been disabled -> remove
if (output.crtc == XCB_NONE && output.mode == XCB_NONE) {
+ // Screen has been disabled
xcb_randr_get_output_info_cookie_t outputInfoCookie =
xcb_randr_get_output_info(xcb_connection(), output.output, output.config_timestamp);
QScopedPointer<xcb_randr_get_output_info_reply_t, QScopedPointerPodDeleter> outputInfo(
xcb_randr_get_output_info_reply(xcb_connection(), outputInfoCookie, NULL));
if (outputInfo->crtc == XCB_NONE) {
qCDebug(lcQpaScreen) << "output" << screen->name() << "has been disabled";
- m_screens.removeOne(screen);
- virtualDesktop->removeScreen(screen);
- QXcbIntegration::instance()->destroyScreen(screen);
+ destroyScreen(screen);
} else {
qCDebug(lcQpaScreen) << "output" << screen->name() << "has been temporarily disabled for the mode switch";
+ // Reset crtc to skip RRCrtcChangeNotify events,
+ // because they may be invalid in the middle of the mode switch
+ screen->setCrtc(XCB_NONE);
}
} else {
- // Just update existing screen
- screen->updateGeometry(output.config_timestamp);
- const bool wasPrimary = screen->isPrimary();
- screen->setPrimary(checkOutputIsPrimary(output.window, output.output));
- if (screen->mode() != output.mode)
- screen->updateRefreshRate(output.mode);
-
- // If the screen became primary, reshuffle the order in QGuiApplicationPrivate
- if (!wasPrimary && screen->isPrimary()) {
- const int idx = m_screens.indexOf(screen);
- m_screens.swap(0, idx);
- QXcbIntegration::instance()->setPrimaryScreen(screen);
- }
+ updateScreen(screen, output);
qCDebug(lcQpaScreen) << "output has changed" << screen;
}
}
+
+ qCDebug(lcQpaScreen) << "primary output is" << m_screens.first()->name();
+ }
+}
+
+bool QXcbConnection::checkOutputIsPrimary(xcb_window_t rootWindow, xcb_randr_output_t output)
+{
+ xcb_generic_error_t *error = 0;
+ xcb_randr_get_output_primary_cookie_t primaryCookie =
+ xcb_randr_get_output_primary(xcb_connection(), rootWindow);
+ QScopedPointer<xcb_randr_get_output_primary_reply_t, QScopedPointerPodDeleter> primary (
+ xcb_randr_get_output_primary_reply(xcb_connection(), primaryCookie, &error));
+ if (!primary || error) {
+ qWarning("failed to get the primary output of the screen");
+ free(error);
+ error = NULL;
+ }
+ const bool isPrimary = primary ? (primary->output == output) : false;
+
+ return isPrimary;
+}
+
+void QXcbConnection::updateScreen(QXcbScreen *screen, const xcb_randr_output_change_t &outputChange)
+{
+ screen->setCrtc(outputChange.crtc); // Set the new crtc, because it can be invalid
+ screen->updateGeometry(outputChange.config_timestamp);
+ if (screen->mode() != outputChange.mode)
+ screen->updateRefreshRate(outputChange.mode);
+ // Only screen which belongs to the primary virtual desktop can be a primary screen
+ if (screen->screenNumber() == m_primaryScreenNumber) {
+ if (!screen->isPrimary() && checkOutputIsPrimary(outputChange.window, outputChange.output)) {
+ screen->setPrimary(true);
+
+ // If the screen became primary, reshuffle the order in QGuiApplicationPrivate
+ const int idx = m_screens.indexOf(screen);
+ if (idx > 0) {
+ m_screens.first()->setPrimary(false);
+ m_screens.swap(0, idx);
+ }
+ screen->virtualDesktop()->setPrimaryScreen(screen);
+ QXcbIntegration::instance()->setPrimaryScreen(screen);
+ }
+ }
+}
+
+QXcbScreen *QXcbConnection::createScreen(QXcbVirtualDesktop *virtualDesktop,
+ const xcb_randr_output_change_t &outputChange,
+ xcb_randr_get_output_info_reply_t *outputInfo)
+{
+ QXcbScreen *screen = new QXcbScreen(this, virtualDesktop, outputChange.output, outputInfo);
+ // Only screen which belongs to the primary virtual desktop can be a primary screen
+ if (screen->screenNumber() == m_primaryScreenNumber)
+ screen->setPrimary(checkOutputIsPrimary(outputChange.window, outputChange.output));
+
+ if (screen->isPrimary()) {
if (!m_screens.isEmpty())
- qCDebug(lcQpaScreen) << "primary output is" << m_screens.first()->name();
- else
- qCDebug(lcQpaScreen) << "no outputs";
+ m_screens.first()->setPrimary(false);
+
+ m_screens.prepend(screen);
+ } else {
+ m_screens.append(screen);
+ }
+ virtualDesktop->addScreen(screen);
+ QXcbIntegration::instance()->screenAdded(screen, screen->isPrimary());
+
+ return screen;
+}
+
+void QXcbConnection::destroyScreen(QXcbScreen *screen)
+{
+ QXcbVirtualDesktop *virtualDesktop = screen->virtualDesktop();
+ if (virtualDesktop->screens().count() == 1) {
+ // If there are no other screens on the same virtual desktop,
+ // then transform the physical screen into a fake screen.
+ const QString nameWas = screen->name();
+ screen->setOutput(XCB_NONE, Q_NULLPTR);
+ qCDebug(lcQpaScreen) << "transformed" << nameWas << "to fake" << screen;
+ } else {
+ // There is more than one screen on the same virtual desktop, remove the screen
+ m_screens.removeOne(screen);
+ virtualDesktop->removeScreen(screen);
+
+ // When primary screen is removed, set the new primary screen
+ // which belongs to the primary virtual desktop.
+ if (screen->isPrimary()) {
+ QXcbScreen *newPrimary = (QXcbScreen *)virtualDesktop->screens().at(0);
+ newPrimary->setPrimary(true);
+ const int idx = m_screens.indexOf(newPrimary);
+ if (idx > 0)
+ m_screens.swap(0, idx);
+ QXcbIntegration::instance()->setPrimaryScreen(newPrimary);
+ }
+
+ QXcbIntegration::instance()->destroyScreen(screen);
}
}
@@ -338,8 +377,7 @@ void QXcbConnection::initializeScreens()
{
xcb_screen_iterator_t it = xcb_setup_roots_iterator(m_setup);
int xcbScreenNumber = 0; // screen number in the xcb sense
- QXcbScreen* primaryScreen = Q_NULLPTR;
- bool hasOutputs = false;
+ QXcbScreen *primaryScreen = Q_NULLPTR;
while (it.rem) {
// Each "screen" in xcb terminology is a virtual desktop,
// potentially a collection of separate juxtaposed monitors.
@@ -348,8 +386,6 @@ void QXcbConnection::initializeScreens()
xcb_screen_t *xcbScreen = it.data;
QXcbVirtualDesktop *virtualDesktop = new QXcbVirtualDesktop(this, xcbScreen, xcbScreenNumber);
m_virtualDesktops.append(virtualDesktop);
- QList<QPlatformScreen *> siblings;
- int outputCount = 0;
if (has_randr_extension) {
xcb_generic_error_t *error = NULL;
// RRGetScreenResourcesCurrent is fast but it may return nothing if the
@@ -366,7 +402,7 @@ void QXcbConnection::initializeScreens()
} else {
xcb_timestamp_t timestamp;
xcb_randr_output_t *outputs = Q_NULLPTR;
- outputCount = xcb_randr_get_screen_resources_current_outputs_length(resources_current.data());
+ int outputCount = xcb_randr_get_screen_resources_current_outputs_length(resources_current.data());
if (outputCount) {
timestamp = resources_current->config_timestamp;
outputs = xcb_randr_get_screen_resources_current_outputs(resources_current.data());
@@ -393,6 +429,7 @@ void QXcbConnection::initializeScreens()
qWarning("failed to get the primary output of the screen");
free(error);
} else {
+ QList<QPlatformScreen *> siblings;
for (int i = 0; i < outputCount; i++) {
QScopedPointer<xcb_randr_get_output_info_reply_t, QScopedPointerPodDeleter> output(
xcb_randr_get_output_info_reply(xcb_connection(),
@@ -416,9 +453,8 @@ void QXcbConnection::initializeScreens()
continue;
}
- QXcbScreen *screen = createScreen(virtualDesktop, outputs[i], output.data());
+ QXcbScreen *screen = new QXcbScreen(this, virtualDesktop, outputs[i], output.data());
siblings << screen;
- hasOutputs = true;
m_screens << screen;
// There can be multiple outputs per screen, use either
@@ -435,11 +471,23 @@ void QXcbConnection::initializeScreens()
}
}
}
+ virtualDesktop->setScreens(siblings);
}
}
}
}
- virtualDesktop->setScreens(siblings);
+ if (virtualDesktop->screens().isEmpty()) {
+ // If there are no XRandR outputs or XRandR extension is missing,
+ // then create a fake/legacy screen.
+ QXcbScreen *screen = new QXcbScreen(this, virtualDesktop, XCB_NONE, Q_NULLPTR);
+ qCDebug(lcQpaScreen) << "created fake screen" << screen;
+ m_screens << screen;
+ if (m_primaryScreenNumber == xcbScreenNumber) {
+ primaryScreen = screen;
+ primaryScreen->setPrimary(true);
+ }
+ virtualDesktop->addScreen(screen);
+ }
xcb_screen_next(&it);
++xcbScreenNumber;
} // for each xcb screen
@@ -447,39 +495,25 @@ void QXcbConnection::initializeScreens()
foreach (QXcbVirtualDesktop *virtualDesktop, m_virtualDesktops)
virtualDesktop->subscribeToXFixesSelectionNotify();
- // If there's no randr extension, or there was some error above, or we found a
- // screen which doesn't have outputs for some other reason (e.g. on VNC or ssh -X),
- // but the dimensions are known anyway, and we don't already have any lingering
- // (possibly disconnected) screens, then showing windows should be possible,
- // so create one screen. (QTBUG-31389)
- QXcbVirtualDesktop *virtualDesktop = m_virtualDesktops.value(0);
- if (virtualDesktop && !hasOutputs && !virtualDesktop->size().isEmpty() && m_screens.isEmpty()) {
- QXcbScreen *screen = createScreen(virtualDesktop, 0, Q_NULLPTR);
- virtualDesktop->setScreens(QList<QPlatformScreen *>() << screen);
- m_screens << screen;
- primaryScreen = screen;
- primaryScreen->setPrimary(true);
- qCDebug(lcQpaScreen) << "found a screen with zero outputs" << screen;
- }
-
- // Ensure the primary screen is first in the list
- if (primaryScreen) {
- Q_ASSERT(!m_screens.isEmpty());
- if (m_screens.first() != primaryScreen) {
- m_screens.removeOne(primaryScreen);
- m_screens.prepend(primaryScreen);
+ if (m_virtualDesktops.isEmpty()) {
+ qFatal("QXcbConnection: no screens available");
+ } else {
+ // Ensure the primary screen is first on the list
+ if (primaryScreen) {
+ if (m_screens.first() != primaryScreen) {
+ m_screens.removeOne(primaryScreen);
+ m_screens.prepend(primaryScreen);
+ }
}
- }
- // Push the screens to QApplication
- QXcbIntegration *integration = QXcbIntegration::instance();
- foreach (QXcbScreen* screen, m_screens) {
- qCDebug(lcQpaScreen) << "adding" << screen << "(Primary:" << screen->isPrimary() << ')';
- integration->screenAdded(screen, screen->isPrimary());
- }
+ // Push the screens to QGuiApplication
+ foreach (QXcbScreen *screen, m_screens) {
+ qCDebug(lcQpaScreen) << "adding" << screen << "(Primary:" << screen->isPrimary() << ")";
+ QXcbIntegration::instance()->screenAdded(screen, screen->isPrimary());
+ }
- if (!m_screens.isEmpty())
qCDebug(lcQpaScreen) << "primary output is" << m_screens.first()->name();
+ }
}
QXcbConnection::QXcbConnection(QXcbNativeInterface *nativeInterface, bool canGrabServer, xcb_visualid_t defaultVisualId, const char *displayName)
@@ -553,9 +587,6 @@ QXcbConnection::QXcbConnection(QXcbNativeInterface *nativeInterface, bool canGra
initializeXFixes();
initializeScreens();
- if (Q_UNLIKELY(m_screens.isEmpty()))
- qFatal("QXcbConnection: no screens available");
-
initializeXRender();
m_xi2Enabled = false;
#if defined(XCB_USE_XINPUT2)
diff --git a/src/plugins/platforms/xcb/qxcbconnection.h b/src/plugins/platforms/xcb/qxcbconnection.h
index cf50076f98..4acca7d374 100644
--- a/src/plugins/platforms/xcb/qxcbconnection.h
+++ b/src/plugins/platforms/xcb/qxcbconnection.h
@@ -518,15 +518,17 @@ private:
void initializeXShape();
void initializeXKB();
void handleClientMessageEvent(const xcb_client_message_event_t *event);
- QXcbScreen* createScreen(QXcbVirtualDesktop *virtualDesktop,
- xcb_randr_output_t outputId = XCB_NONE,
- xcb_randr_get_output_info_reply_t *output = 0);
QXcbScreen* findScreenForCrtc(xcb_window_t rootWindow, xcb_randr_crtc_t crtc);
QXcbScreen* findScreenForOutput(xcb_window_t rootWindow, xcb_randr_output_t output);
QXcbVirtualDesktop* virtualDesktopForRootWindow(xcb_window_t rootWindow);
+ void updateScreens(const xcb_randr_notify_event_t *event);
bool checkOutputIsPrimary(xcb_window_t rootWindow, xcb_randr_output_t output);
+ void updateScreen(QXcbScreen *screen, const xcb_randr_output_change_t &outputChange);
+ QXcbScreen *createScreen(QXcbVirtualDesktop *virtualDesktop,
+ const xcb_randr_output_change_t &outputChange,
+ xcb_randr_get_output_info_reply_t *outputInfo);
+ void destroyScreen(QXcbScreen *screen);
void initializeScreens();
- void updateScreens(const xcb_randr_notify_event_t *event);
bool compressEvent(xcb_generic_event_t *event, int currentIndex, QXcbEventArray *eventqueue) const;
bool m_xi2Enabled;
diff --git a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp
index 8097cce709..1a123703a5 100644
--- a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp
+++ b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp
@@ -406,6 +406,9 @@ XInput2TouchDeviceData *QXcbConnection::touchDeviceForId(int id)
#endif // XCB_USE_XINPUT22
case XIValuatorClass: {
XIValuatorClassInfo *vci = reinterpret_cast<XIValuatorClassInfo *>(classinfo);
+ // Some devices (mice) report a resolution of 0; they will be excluded later,
+ // for now just prevent a division by zero
+ const int vciResolution = vci->resolution ? vci->resolution : 1;
if (vci->label == atom(QXcbAtom::AbsMTPositionX))
caps |= QTouchDevice::Position | QTouchDevice::NormalizedPosition;
else if (vci->label == atom(QXcbAtom::AbsMTTouchMajor))
@@ -414,16 +417,16 @@ XInput2TouchDeviceData *QXcbConnection::touchDeviceForId(int id)
caps |= QTouchDevice::Pressure;
else if (vci->label == atom(QXcbAtom::RelX)) {
hasRelativeCoords = true;
- dev->size.setWidth((vci->max - vci->min) * 1000.0 / vci->resolution);
+ dev->size.setWidth((vci->max - vci->min) * 1000.0 / vciResolution);
} else if (vci->label == atom(QXcbAtom::RelY)) {
hasRelativeCoords = true;
- dev->size.setHeight((vci->max - vci->min) * 1000.0 / vci->resolution);
+ dev->size.setHeight((vci->max - vci->min) * 1000.0 / vciResolution);
} else if (vci->label == atom(QXcbAtom::AbsX)) {
caps |= QTouchDevice::Position;
- dev->size.setHeight((vci->max - vci->min) * 1000.0 / vci->resolution);
+ dev->size.setHeight((vci->max - vci->min) * 1000.0 / vciResolution);
} else if (vci->label == atom(QXcbAtom::AbsY)) {
caps |= QTouchDevice::Position;
- dev->size.setWidth((vci->max - vci->min) * 1000.0 / vci->resolution);
+ dev->size.setWidth((vci->max - vci->min) * 1000.0 / vciResolution);
}
break;
}
diff --git a/src/plugins/platforms/xcb/qxcbscreen.cpp b/src/plugins/platforms/xcb/qxcbscreen.cpp
index db7d837e01..9b1b9fcbb0 100644
--- a/src/plugins/platforms/xcb/qxcbscreen.cpp
+++ b/src/plugins/platforms/xcb/qxcbscreen.cpp
@@ -81,6 +81,13 @@ void QXcbVirtualDesktop::addScreen(QPlatformScreen *s)
((QXcbScreen *) s)->isPrimary() ? m_screens.prepend(s) : m_screens.append(s);
}
+void QXcbVirtualDesktop::setPrimaryScreen(QPlatformScreen *s)
+{
+ const int idx = m_screens.indexOf(s);
+ Q_ASSERT(idx > -1);
+ m_screens.swap(0, idx);
+}
+
QXcbXSettings *QXcbVirtualDesktop::xSettings() const
{
if (!m_xSettings) {
@@ -149,16 +156,15 @@ void QXcbVirtualDesktop::updateWorkArea()
}
QXcbScreen::QXcbScreen(QXcbConnection *connection, QXcbVirtualDesktop *virtualDesktop,
- xcb_randr_output_t outputId, xcb_randr_get_output_info_reply_t *output,
- QString outputName)
+ xcb_randr_output_t outputId, xcb_randr_get_output_info_reply_t *output)
: QXcbObject(connection)
, m_virtualDesktop(virtualDesktop)
, m_output(outputId)
- , m_crtc(output ? output->crtc : 0)
+ , m_crtc(output ? output->crtc : XCB_NONE)
, m_mode(XCB_NONE)
, m_primary(false)
, m_rotation(XCB_RANDR_ROTATION_ROTATE_0)
- , m_outputName(outputName)
+ , m_outputName(getOutputName(output))
, m_outputSizeMillimeters(output ? QSize(output->mm_width, output->mm_height) : QSize())
, m_virtualSize(virtualDesktop->size())
, m_virtualSizeMillimeters(virtualDesktop->physicalSize())
@@ -266,6 +272,22 @@ QXcbScreen::~QXcbScreen()
delete m_cursor;
}
+QString QXcbScreen::getOutputName(xcb_randr_get_output_info_reply_t *outputInfo)
+{
+ QString name;
+ if (outputInfo) {
+ name = QString::fromUtf8((const char*)xcb_randr_get_output_info_name(outputInfo),
+ xcb_randr_get_output_info_name_length(outputInfo));
+ } else {
+ QByteArray displayName = connection()->displayName();
+ int dotPos = displayName.lastIndexOf('.');
+ if (dotPos != -1)
+ displayName.truncate(dotPos);
+ name = QString::fromLocal8Bit(displayName) + QLatin1Char('.')
+ + QString::number(m_virtualDesktop->number());
+ }
+ return name;
+}
QWindow *QXcbScreen::topLevelAt(const QPoint &p) const
{
@@ -390,6 +412,16 @@ QPlatformCursor *QXcbScreen::cursor() const
return m_cursor;
}
+void QXcbScreen::setOutput(xcb_randr_output_t outputId,
+ xcb_randr_get_output_info_reply_t *outputInfo)
+{
+ m_output = outputId;
+ m_crtc = outputInfo ? outputInfo->crtc : XCB_NONE;
+ m_mode = XCB_NONE;
+ m_outputName = getOutputName(outputInfo);
+ // TODO: Send an event to the QScreen instance that the screen changed its name
+}
+
/*!
\brief handle the XCB screen change event and update properties
@@ -458,19 +490,10 @@ void QXcbScreen::handleScreenChange(xcb_randr_screen_change_notify_event_t *chan
updateGeometry(change_event->timestamp);
- QWindowSystemInterface::handleScreenGeometryChange(QPlatformScreen::screen(), geometry(), availableGeometry());
QWindowSystemInterface::handleScreenOrientationChange(QPlatformScreen::screen(), m_orientation);
QDpi ldpi = logicalDpi();
QWindowSystemInterface::handleScreenLogicalDotsPerInchChange(QPlatformScreen::screen(), ldpi.first, ldpi.second);
-
- // Windows which had null screens have already had expose events by now.
- // They need to be told the screen is back, it's OK to render.
- foreach (QWindow *window, QGuiApplication::topLevelWindows()) {
- QXcbWindow *xcbWin = static_cast<QXcbWindow*>(window->handle());
- if (xcbWin)
- xcbWin->maybeSetScreen(this);
- }
}
void QXcbScreen::updateGeometry(xcb_timestamp_t timestamp)
diff --git a/src/plugins/platforms/xcb/qxcbscreen.h b/src/plugins/platforms/xcb/qxcbscreen.h
index c68c290791..79620f40ec 100644
--- a/src/plugins/platforms/xcb/qxcbscreen.h
+++ b/src/plugins/platforms/xcb/qxcbscreen.h
@@ -72,6 +72,7 @@ public:
void setScreens(QList<QPlatformScreen *> sl) { m_screens = sl; }
void removeScreen(QPlatformScreen *s) { m_screens.removeOne(s); }
void addScreen(QPlatformScreen *s);
+ void setPrimaryScreen(QPlatformScreen *s);
QXcbXSettings *xSettings() const;
@@ -101,10 +102,11 @@ class Q_XCB_EXPORT QXcbScreen : public QXcbObject, public QPlatformScreen
{
public:
QXcbScreen(QXcbConnection *connection, QXcbVirtualDesktop *virtualDesktop,
- xcb_randr_output_t outputId, xcb_randr_get_output_info_reply_t *output,
- QString outputName);
+ xcb_randr_output_t outputId, xcb_randr_get_output_info_reply_t *outputInfo);
~QXcbScreen();
+ QString getOutputName(xcb_randr_get_output_info_reply_t *outputInfo);
+
QPixmap grabWindow(WId window, int x, int y, int width, int height) const Q_DECL_OVERRIDE;
QWindow *topLevelAt(const QPoint &point) const Q_DECL_OVERRIDE;
@@ -137,6 +139,10 @@ public:
xcb_randr_crtc_t crtc() const { return m_crtc; }
xcb_randr_mode_t mode() const { return m_mode; }
+ void setOutput(xcb_randr_output_t outputId,
+ xcb_randr_get_output_info_reply_t *outputInfo);
+ void setCrtc(xcb_randr_crtc_t crtc) { m_crtc = crtc; }
+
void windowShown(QXcbWindow *window);
QString windowManagerName() const { return m_windowManagerName; }
bool syncRequestSupported() const { return m_syncRequestSupported; }
diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp
index 3e01a90402..ae81674eca 100644
--- a/src/plugins/platforms/xcb/qxcbwindow.cpp
+++ b/src/plugins/platforms/xcb/qxcbwindow.cpp
@@ -143,7 +143,7 @@ const quint32 XEMBED_VERSION = 0;
QXcbScreen *QXcbWindow::parentScreen()
{
- return parent() ? static_cast<QXcbWindow*>(parent())->parentScreen() : m_xcbScreen;
+ return parent() ? static_cast<QXcbWindow*>(parent())->parentScreen() : xcbScreen();
}
// Returns \c true if we should set WM_TRANSIENT_FOR on \a w
@@ -266,7 +266,6 @@ static const char *wm_window_type_property_id = "_q_xcb_wm_window_type";
QXcbWindow::QXcbWindow(QWindow *window)
: QPlatformWindow(window)
, m_window(0)
- , m_xcbScreen(0)
, m_syncCounter(0)
, m_gravity(XCB_GRAVITY_STATIC)
, m_mapped(false)
@@ -322,7 +321,6 @@ void QXcbWindow::create()
QRect rect = windowGeometry();
QXcbScreen *platformScreen = parent() ? parentScreen() : static_cast<QXcbScreen*>(screenForGeometry(rect));
- m_xcbScreen = platformScreen;
if (type == Qt::Desktop) {
m_window = platformScreen->root();
m_depth = platformScreen->screen()->root_depth;
@@ -624,27 +622,18 @@ void QXcbWindow::destroy()
m_pendingSyncRequest->invalidate();
}
-void QXcbWindow::maybeSetScreen(QXcbScreen *screen)
-{
- if (!window()->screen() && screen->geometry().contains(geometry().topLeft())) {
- QWindowSystemInterface::handleWindowScreenChanged(window(), static_cast<QPlatformScreen *>(screen)->screen());
- QWindowSystemInterface::handleExposeEvent(window(), QRegion(QRect(QPoint(0, 0), window()->size())));
- }
-}
-
void QXcbWindow::setGeometry(const QRect &rect)
{
QPlatformWindow::setGeometry(rect);
propagateSizeHints();
- QXcbScreen *currentScreen = m_xcbScreen;
+ QXcbScreen *currentScreen = xcbScreen();
QXcbScreen *newScreen = parent() ? parentScreen() : static_cast<QXcbScreen*>(screenForGeometry(rect));
if (!newScreen)
newScreen = xcbScreen();
- m_xcbScreen = newScreen;
const QRect wmGeometry = windowToWmGeometry(rect);
if (newScreen && newScreen != currentScreen)
@@ -848,15 +837,13 @@ void QXcbWindow::hide()
Q_XCB_CALL(xcb_unmap_window(xcb_connection(), m_window));
// send synthetic UnmapNotify event according to icccm 4.1.4
- if (xcbScreen()) {
- xcb_unmap_notify_event_t event;
- event.response_type = XCB_UNMAP_NOTIFY;
- event.event = xcbScreen()->root();
- event.window = m_window;
- event.from_configure = false;
- Q_XCB_CALL(xcb_send_event(xcb_connection(), false, xcbScreen()->root(),
- XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, (const char *)&event));
- }
+ xcb_unmap_notify_event_t event;
+ event.response_type = XCB_UNMAP_NOTIFY;
+ event.event = xcbScreen()->root();
+ event.window = m_window;
+ event.from_configure = false;
+ Q_XCB_CALL(xcb_send_event(xcb_connection(), false, xcbScreen()->root(),
+ XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, (const char *)&event));
xcb_flush(xcb_connection());
@@ -1185,8 +1172,6 @@ void QXcbWindow::changeNetWmState(bool set, xcb_atom_t one, xcb_atom_t two)
event.data.data32[3] = 0;
event.data.data32[4] = 0;
- if (!xcbScreen())
- return;
Q_XCB_CALL(xcb_send_event(xcb_connection(), 0, xcbScreen()->root(), XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, (const char *)&event));
}
@@ -1448,8 +1433,6 @@ void QXcbWindow::setParent(const QPlatformWindow *parent)
xcb_parent_id = qXcbParent->xcb_window();
m_embedded = qXcbParent->window()->type() == Qt::ForeignWindow;
} else {
- if (!xcbScreen())
- return;
xcb_parent_id = xcbScreen()->root();
m_embedded = false;
}
@@ -2005,7 +1988,7 @@ void QXcbWindow::handleConfigureNotifyEvent(const xcb_configure_notify_event_t *
{
bool fromSendEvent = (event->response_type & 0x80);
QPoint pos(event->x, event->y);
- if (!parent() && !fromSendEvent && xcbScreen()) {
+ if (!parent() && !fromSendEvent) {
// Do not trust the position, query it instead.
xcb_translate_coordinates_cookie_t cookie = xcb_translate_coordinates(xcb_connection(), xcb_window(),
xcbScreen()->root(), 0, 0);
@@ -2017,21 +2000,38 @@ void QXcbWindow::handleConfigureNotifyEvent(const xcb_configure_notify_event_t *
}
}
- const QRect rect = QRect(pos, QSize(event->width, event->height));
- QPlatformScreen *newScreen = parent() ? parent()->screen() : screenForGeometry(rect);
+ // The original geometry requested by setGeometry() might be different
+ // from what we end up with after applying window constraints.
+ QRect requestedGeometry = geometry();
- QXcbScreen *currentScreen = m_xcbScreen;
- m_xcbScreen = static_cast<QXcbScreen*>(newScreen);
+ const QRect actualGeometry = QRect(pos, QSize(event->width, event->height));
+ QPlatformScreen *newScreen = parent() ? parent()->screen() : screenForGeometry(actualGeometry);
if (!newScreen)
return;
- QPlatformWindow::setGeometry(rect);
- QWindowSystemInterface::handleGeometryChange(window(), rect);
- if (newScreen != currentScreen)
- QWindowSystemInterface::handleWindowScreenChanged(window(), newScreen->screen());
+ // Persist the actual geometry so that QWindow::geometry() can
+ // be queried in the resize event.
+ QPlatformWindow::setGeometry(actualGeometry);
- if (m_mapped)
- QWindowSystemInterface::handleExposeEvent(window(), QRect(QPoint(), geometry().size()));
+ // FIXME: In the case of the requestedGeometry not matching the actualGeometry due
+ // to e.g. the window manager applying restrictions to the geometry, the application
+ // will never see a move/resize event if the actualGeometry is the same as the current
+ // geometry, and may think the requested geometry was fulfilled.
+ QWindowSystemInterface::handleGeometryChange(window(), actualGeometry);
+
+ // QPlatformScreen::screen() is updated asynchronously, so we can't compare it
+ // with the newScreen. Just send the WindowScreenChanged event and QGuiApplication
+ // will make the comparison later.
+ QWindowSystemInterface::handleWindowScreenChanged(window(), newScreen->screen());
+
+ // For expose events we have no way of telling QGuiApplication to used the locally
+ // cached version of the previous state, so we may in some situations end up with
+ // an additional expose event.
+ QRect previousGeometry = requestedGeometry != actualGeometry ?
+ requestedGeometry : qt_window_private(window())->geometry;
+
+ if (m_mapped && actualGeometry.size() != previousGeometry.size())
+ QWindowSystemInterface::handleExposeEvent(window(), QRect(QPoint(), actualGeometry.size()));
if (m_usingSyncProtocol && m_syncState == SyncReceived)
m_syncState = SyncAndConfigureReceived;
@@ -2298,8 +2298,6 @@ void QXcbWindow::handleEnterNotifyEvent(const xcb_enter_notify_event_t *event)
return;
const QPoint local(event->event_x, event->event_y);
- if (!xcbScreen())
- return;
QPoint global = QPoint(event->root_x, event->root_y);
QWindowSystemInterface::handleEnterEvent(window(), local, global);
}
@@ -2317,8 +2315,6 @@ void QXcbWindow::handleLeaveNotifyEvent(const xcb_leave_notify_event_t *event)
if (enterWindow) {
QPoint local(enter->event_x, enter->event_y);
- if (!xcbScreen())
- return;
QPoint global = QPoint(event->root_x, event->root_y);
QWindowSystemInterface::handleEnterLeaveEvent(enterWindow->window(), window(), local, global);
@@ -2334,8 +2330,6 @@ void QXcbWindow::handlePropertyNotifyEvent(const xcb_property_notify_event_t *ev
connection()->setTime(event->time);
const bool propertyDeleted = event->state == XCB_PROPERTY_DELETE;
- if (!xcbScreen())
- return;
if (event->atom == atom(QXcbAtom::_NET_WM_STATE) || event->atom == atom(QXcbAtom::WM_STATE)) {
if (propertyDeleted)
@@ -2655,8 +2649,6 @@ bool QXcbWindow::needsSync() const
void QXcbWindow::postSyncWindowRequest()
{
- if (!xcbScreen())
- return;
if (!m_pendingSyncRequest) {
QXcbSyncWindowRequest *e = new QXcbSyncWindowRequest(this);
m_pendingSyncRequest = e;
diff --git a/src/plugins/platforms/xcb/qxcbwindow.h b/src/plugins/platforms/xcb/qxcbwindow.h
index c42c98c205..587be22915 100644
--- a/src/plugins/platforms/xcb/qxcbwindow.h
+++ b/src/plugins/platforms/xcb/qxcbwindow.h
@@ -167,7 +167,6 @@ public:
virtual void create();
virtual void destroy();
- void maybeSetScreen(QXcbScreen *screen);
QXcbScreen *screenForNativeGeometry(const QRect &newGeometry) const;
public Q_SLOTS:
@@ -215,8 +214,6 @@ protected:
xcb_window_t m_window;
- QXcbScreen *m_xcbScreen;
-
uint m_depth;
QImage::Format m_imageFormat;
bool m_imageRgbSwap;
diff --git a/src/widgets/dialogs/qfiledialog.cpp b/src/widgets/dialogs/qfiledialog.cpp
index 07d1ab0add..62022e6ef2 100644
--- a/src/widgets/dialogs/qfiledialog.cpp
+++ b/src/widgets/dialogs/qfiledialog.cpp
@@ -3795,7 +3795,7 @@ bool QFileDialogPrivate::itemViewKeyboardEvent(QKeyEvent *event) {
Q_Q(QFileDialog);
if (event->matches(QKeySequence::Cancel)) {
- q->hide();
+ q->reject();
return true;
}
diff --git a/src/widgets/dialogs/qfilesystemmodel.cpp b/src/widgets/dialogs/qfilesystemmodel.cpp
index c1d0ecf33b..90d7db7bd1 100644
--- a/src/widgets/dialogs/qfilesystemmodel.cpp
+++ b/src/widgets/dialogs/qfilesystemmodel.cpp
@@ -198,13 +198,14 @@ QFileInfo QFileSystemModel::fileInfo(const QModelIndex &index) const
bool QFileSystemModel::remove(const QModelIndex &aindex)
{
const QString path = filePath(aindex);
+ const bool success = QFileInfo(path).isFile() ? QFile::remove(path) : QDir(path).removeRecursively();
#ifndef QT_NO_FILESYSTEMWATCHER
- QFileSystemModelPrivate * d = const_cast<QFileSystemModelPrivate*>(d_func());
- d->fileInfoGatherer.removePath(path);
+ if (success) {
+ QFileSystemModelPrivate * d = const_cast<QFileSystemModelPrivate*>(d_func());
+ d->fileInfoGatherer.removePath(path);
+ }
#endif
- if (QFileInfo(path).isFile())
- return QFile::remove(path);
- return QDir(path).removeRecursively();
+ return success;
}
/*!
@@ -1620,11 +1621,14 @@ bool QFileSystemModel::event(QEvent *event)
bool QFileSystemModel::rmdir(const QModelIndex &aindex)
{
QString path = filePath(aindex);
+ const bool success = QDir().rmdir(path);
#ifndef QT_NO_FILESYSTEMWATCHER
- QFileSystemModelPrivate * d = const_cast<QFileSystemModelPrivate*>(d_func());
- d->fileInfoGatherer.removePath(path);
+ if (success) {
+ QFileSystemModelPrivate * d = const_cast<QFileSystemModelPrivate*>(d_func());
+ d->fileInfoGatherer.removePath(path);
+ }
#endif
- return QDir().rmdir(path);
+ return success;
}
/*!
@@ -1800,10 +1804,6 @@ void QFileSystemModelPrivate::_q_fileSystemChanged(const QString &path, const QV
node->fileName = fileName;
}
- if (info.size() == -1 && !info.isSymLink()) {
- removeNode(parentNode, fileName);
- continue;
- }
if (*node != info ) {
node->populate(info);
bypassFilters.remove(node);
diff --git a/src/widgets/doc/src/guibooks.qdoc b/src/widgets/doc/src/guibooks.qdoc
index 8a1198c328..b3afe06961 100644
--- a/src/widgets/doc/src/guibooks.qdoc
+++ b/src/widgets/doc/src/guibooks.qdoc
@@ -76,7 +76,7 @@
advises against will produce more easily comprehensible software.
Doing what it tells you to do may also help.
- \b{\l{http://www.amazon.com/exec/obidos/ASIN/047159900X/trolltech/t}{The
+ \b{\l{http://www.amazon.com/New-Windows-Interface-Microsoft-Press/dp/1556156790/}{The
Microsoft Windows User Experience}}, ISBN 1-55615-679-0,
is Microsoft's look and feel bible. Indispensable for everyone who
has customers that worship Microsoft, and it's quite good, too.
diff --git a/src/widgets/itemviews/qlistwidget.cpp b/src/widgets/itemviews/qlistwidget.cpp
index 00ac2b54bf..275fc2a1f1 100644
--- a/src/widgets/itemviews/qlistwidget.cpp
+++ b/src/widgets/itemviews/qlistwidget.cpp
@@ -1262,7 +1262,7 @@ void QListWidgetPrivate::_q_dataChanged(const QModelIndex &topLeft,
activated when the user clicks or double clicks on it, depending on the
system configuration. It is also activated when the user presses the
activation key (on Windows and X11 this is the \uicontrol Return key, on Mac OS
- X it is \uicontrol{Ctrl+0}).
+ X it is \uicontrol{Command+O}).
*/
/*!
diff --git a/src/widgets/kernel/qaction.cpp b/src/widgets/kernel/qaction.cpp
index 3306754623..66e8e5379f 100644
--- a/src/widgets/kernel/qaction.cpp
+++ b/src/widgets/kernel/qaction.cpp
@@ -255,7 +255,7 @@ void QActionPrivate::setShortcutEnabled(bool enable, QShortcutMap &map)
\value TextHeuristicRole This action should be put in the application menu based on the action's text
as described in the QMenuBar documentation.
\value ApplicationSpecificRole This action should be put in the application menu with an application specific role
- \value AboutQtRole This action matches handles the "About Qt" menu item.
+ \value AboutQtRole This action handles the "About Qt" menu item.
\value AboutRole This action should be placed where the "About" menu item is in the application menu. The text of
the menu item will be set to "About <application name>". The application name is fetched from the
\c{Info.plist} file in the application's bundle (See \l{Qt for OS X - Deployment}).
@@ -1231,7 +1231,7 @@ void QAction::activate(ActionEvent event)
\since 4.2
This indicates what role the action serves in the application menu on Mac
- OS X. By default all action have the TextHeuristicRole, which means that
+ OS X. By default all actions have the TextHeuristicRole, which means that
the action is added based on its text (see QMenuBar for more information).
The menu role can only be changed before the actions are put into the menu
diff --git a/src/widgets/kernel/qwidgetbackingstore.cpp b/src/widgets/kernel/qwidgetbackingstore.cpp
index d5c8691459..63419ea093 100644
--- a/src/widgets/kernel/qwidgetbackingstore.cpp
+++ b/src/widgets/kernel/qwidgetbackingstore.cpp
@@ -448,6 +448,26 @@ void QWidgetBackingStore::sendUpdateRequest(QWidget *widget, UpdateTime updateTi
if (!widget)
return;
+#ifndef QT_NO_OPENGL
+ // Having every repaint() leading to a sync/flush is bad as it causes
+ // compositing and waiting for vsync each and every time. Change to
+ // UpdateLater, except for approx. once per frame to prevent starvation in
+ // case the control does not get back to the event loop.
+ QWidget *w = widget->window();
+ if (updateTime == UpdateNow && w && w->windowHandle() && QWindowPrivate::get(w->windowHandle())->compositing) {
+ int refresh = 60;
+ QScreen *ws = w->windowHandle()->screen();
+ if (ws)
+ refresh = ws->refreshRate();
+ QWindowPrivate *wd = QWindowPrivate::get(w->windowHandle());
+ if (wd->lastComposeTime.isValid()) {
+ const qint64 elapsed = wd->lastComposeTime.elapsed();
+ if (elapsed <= qint64(1000.0f / refresh))
+ updateTime = UpdateLater;
+ }
+ }
+#endif
+
switch (updateTime) {
case UpdateLater:
updateRequestSent = true;
@@ -621,7 +641,11 @@ void QWidgetBackingStore::markDirty(const QRect &rect, QWidget *widget,
const QRect widgetRect = widget->d_func()->effectiveRectFor(rect);
- const QRect translatedRect(widgetRect.translated(widget->mapTo(tlw, QPoint())));
+ QRect translatedRect = widgetRect;
+ if (widget != tlw)
+ translatedRect.translate(widget->mapTo(tlw, QPoint()));
+ // Graphics effects may exceed window size, clamp.
+ translatedRect = translatedRect.intersected(QRect(QPoint(), tlw->size()));
if (qt_region_strictContains(dirty, translatedRect)) {
if (updateTime == UpdateNow)
sendUpdateRequest(tlw, updateTime);
diff --git a/src/widgets/widgets/qdockarealayout.cpp b/src/widgets/widgets/qdockarealayout.cpp
index 8523f43328..07efbafb31 100644
--- a/src/widgets/widgets/qdockarealayout.cpp
+++ b/src/widgets/widgets/qdockarealayout.cpp
@@ -1816,7 +1816,8 @@ void QDockAreaLayoutInfo::saveState(QDataStream &stream) const
stream << flags;
if (w->isWindow()) {
- stream << w->x() << w->y() << w->width() << w->height();
+ const QRect geometry = w->geometry();
+ stream << geometry.x() << geometry.y() << geometry.width() << geometry.height();
} else {
stream << item.pos << item.size << pick(o, item.minimumSize())
<< pick(o, item.maximumSize());
diff --git a/src/widgets/widgets/qdockwidget.cpp b/src/widgets/widgets/qdockwidget.cpp
index 292681584d..67eb466ba8 100644
--- a/src/widgets/widgets/qdockwidget.cpp
+++ b/src/widgets/widgets/qdockwidget.cpp
@@ -1093,14 +1093,8 @@ void QDockWidgetPrivate::setWindowState(bool floating, bool unplug, const QRect
q->setWindowFlags(flags);
- if (!rect.isNull()) {
- if (floating) {
- q->resize(rect.size());
- q->move(rect.topLeft());
- } else {
+ if (!rect.isNull())
q->setGeometry(rect);
- }
- }
updateButtons();
diff --git a/src/winmain/qtmain_winrt.cpp b/src/winmain/qtmain_winrt.cpp
index 473c41ab8e..098ae45dc8 100644
--- a/src/winmain/qtmain_winrt.cpp
+++ b/src/winmain/qtmain_winrt.cpp
@@ -140,6 +140,8 @@ public:
hr = applicationFactory->CreateInstance(this, &base, &core);
RETURN_VOID_IF_FAILED("Failed to create application container instance");
+
+ pidFile = INVALID_HANDLE_VALUE;
}
~AppContainer()
@@ -157,6 +159,13 @@ public:
int argc = app->args.count();
char **argv = app->args.data();
const int res = main(argc, argv);
+ if (app->pidFile != INVALID_HANDLE_VALUE) {
+ const QByteArray resString = QByteArray::number(res);
+ WriteFile(app->pidFile, reinterpret_cast<LPCVOID>(resString.constData()),
+ resString.size(), NULL, NULL);
+ FlushFileBuffers(app->pidFile);
+ CloseHandle(app->pidFile);
+ }
app->core->Exit();
return res;
}, this, CREATE_SUSPENDED, nullptr);
@@ -234,6 +243,9 @@ private:
}
}
+ if (args.count() >= 2 && strncmp(args.at(1), "-ServerName:", 12) == 0)
+ args.remove(1);
+
bool develMode = false;
bool debugWait = false;
foreach (const char *arg, args) {
@@ -248,11 +260,10 @@ private:
.absoluteFilePath(QString::number(uint(GetCurrentProcessId())) + QStringLiteral(".pid"));
CREATEFILE2_EXTENDED_PARAMETERS params = {
sizeof(CREATEFILE2_EXTENDED_PARAMETERS),
- FILE_ATTRIBUTE_NORMAL, FILE_FLAG_DELETE_ON_CLOSE
+ FILE_ATTRIBUTE_NORMAL
};
- // (Unused) handle will automatically be closed when the app exits
- CreateFile2(reinterpret_cast<LPCWSTR>(pidFileName.utf16()),
- 0, FILE_SHARE_READ|FILE_SHARE_DELETE, CREATE_ALWAYS, &params);
+ pidFile = CreateFile2(reinterpret_cast<LPCWSTR>(pidFileName.utf16()),
+ GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ, CREATE_ALWAYS, &params);
// Install the develMode message handler
#ifndef Q_OS_WINPHONE
defaultMessageHandler = qInstallMessageHandler(devMessageHandler);
@@ -315,6 +326,7 @@ private:
QByteArray commandLine;
QVarLengthArray<char *> args;
HANDLE mainThread;
+ HANDLE pidFile;
};
// Main entry point for Appx containers