summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/3rdparty/freetype/freetype.pro1
-rw-r--r--src/corelib/global/qoperatingsystemversion.cpp18
-rw-r--r--src/corelib/io/qdatastream.cpp1
-rw-r--r--src/corelib/io/qdir.cpp2
-rw-r--r--src/corelib/io/qfilesystemengine_unix.cpp9
-rw-r--r--src/corelib/io/qfsfileengine_unix.cpp2
-rw-r--r--src/corelib/kernel/qabstracteventdispatcher.h2
-rw-r--r--src/corelib/kernel/qobject.cpp2
-rw-r--r--src/corelib/tools/qlocale_mac.mm33
-rw-r--r--src/gui/kernel/qoffscreensurface.cpp2
-rw-r--r--src/gui/kernel/qplatformintegration.cpp2
-rw-r--r--src/gui/kernel/qplatformintegration.h3
-rw-r--r--src/gui/kernel/qstylehints.cpp31
-rw-r--r--src/gui/kernel/qstylehints.h4
-rw-r--r--src/gui/opengl/qopenglprogrambinarycache.cpp136
-rw-r--r--src/gui/painting/qdrawhelper.cpp30
-rw-r--r--src/gui/painting/qdrawhelper_neon.cpp2
-rw-r--r--src/gui/painting/qdrawhelper_neon_p.h2
-rw-r--r--src/gui/painting/qdrawhelper_p.h4
-rw-r--r--src/gui/painting/qpaintengine_raster.cpp15
-rw-r--r--src/gui/painting/qpaintengine_raster_p.h2
-rw-r--r--src/gui/text/qfontengine.cpp5
-rw-r--r--src/gui/text/qfontengine_ft.cpp36
-rw-r--r--src/gui/text/qfontengine_ft_p.h2
-rw-r--r--src/gui/text/qfontengine_p.h1
-rw-r--r--src/network/access/access.pri6
-rw-r--r--src/network/access/qhsts.cpp180
-rw-r--r--src/network/access/qhsts_p.h81
-rw-r--r--src/network/access/qhstspolicy.cpp218
-rw-r--r--src/network/access/qhstspolicy.h82
-rw-r--r--src/network/access/qnetworkaccessmanager.cpp41
-rw-r--r--src/network/access/qnetworkaccessmanager.h3
-rw-r--r--src/network/access/qnetworkdiskcache.cpp2
-rw-r--r--src/network/bearer/qnetworkconfiguration.cpp2
-rw-r--r--src/network/kernel/qhostinfo.cpp148
-rw-r--r--src/network/kernel/qhostinfo.h63
-rw-r--r--src/network/kernel/qhostinfo_p.h42
-rw-r--r--src/network/kernel/qnetworkproxy.cpp19
-rw-r--r--src/network/kernel/qnetworkproxy.h4
-rw-r--r--src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm42
-rw-r--r--src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm13
-rw-r--r--src/platformsupport/fontdatabases/mac/qfontengine_coretext_p.h1
-rw-r--r--src/platformsupport/fontdatabases/windows/qwindowsfontdatabase.cpp3
-rw-r--r--src/platformsupport/linuxaccessibility/atspiadaptor.cpp2
-rw-r--r--src/plugins/bearer/corewlan/qcorewlanengine.mm40
-rw-r--r--src/plugins/platforms/cocoa/qcocoacolordialoghelper.mm14
-rw-r--r--src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm4
-rw-r--r--src/plugins/platforms/cocoa/qcocoafontdialoghelper.mm14
-rw-r--r--src/plugins/platforms/cocoa/qcocoanativeinterface.mm7
-rw-r--r--src/plugins/platforms/windows/qwindowswindow.cpp21
-rw-r--r--src/plugins/platforms/xcb/qxcbintegration.cpp3
-rw-r--r--src/printsupport/dialogs/qpagesetupdialog_mac.mm4
-rw-r--r--src/printsupport/dialogs/qprintdialog_mac.mm4
-rw-r--r--src/tools/uic/main.cpp2
-rw-r--r--src/widgets/kernel/qapplication.cpp14
-rw-r--r--src/widgets/widgets/qcalendarwidget.cpp2
-rw-r--r--src/widgets/widgets/qmenubar.cpp2
-rw-r--r--src/widgets/widgets/qtabbar.cpp3
58 files changed, 1048 insertions, 385 deletions
diff --git a/src/3rdparty/freetype/freetype.pro b/src/3rdparty/freetype/freetype.pro
index 390a6da749..47ac9122ae 100644
--- a/src/3rdparty/freetype/freetype.pro
+++ b/src/3rdparty/freetype/freetype.pro
@@ -24,6 +24,7 @@ SOURCES += \
$$PWD/src/base/ftbbox.c \
$$PWD/src/base/ftdebug.c \
$$PWD/src/base/ftglyph.c \
+ $$PWD/src/base/ftfntfmt.c \
$$PWD/src/base/ftinit.c \
$$PWD/src/base/ftlcdfil.c \
$$PWD/src/base/ftmm.c \
diff --git a/src/corelib/global/qoperatingsystemversion.cpp b/src/corelib/global/qoperatingsystemversion.cpp
index 0cfc70a790..bed08f0000 100644
--- a/src/corelib/global/qoperatingsystemversion.cpp
+++ b/src/corelib/global/qoperatingsystemversion.cpp
@@ -118,7 +118,7 @@ QT_BEGIN_NAMESPACE
current >= QOperatingSystemVersion(QOperatingSystemVersion::IOS, 8)) {
// returns true on macOS >= 10.10 and iOS >= 8.0, but false on macOS < 10.10 and iOS < 8.0
}
- \encode
+ \endcode
A more naive comparison algorithm might incorrectly return true on all versions of macOS,
including Mac OS 9. This behavior is achieved by overloading the comparison operators to return
@@ -144,10 +144,10 @@ QT_BEGIN_NAMESPACE
*/
/*!
- \fn QOperatingSystemVersion::QOperatingSystemVersion(int maj, int min, int mic)
+ \fn QOperatingSystemVersion::QOperatingSystemVersion(OSType osType, int vmajor, int vminor = -1, int vmicro = -1)
- Constructs a QOperatingSystemVersion consisting of the OS type \a os, and
- major, minor, and micro version numbers \a maj, \a min and \a mic, respectively.
+ Constructs a QOperatingSystemVersion consisting of the OS type \a osType, and
+ major, minor, and micro version numbers \a vmajor, \a vminor and \a vmicro, respectively.
*/
/*!
@@ -264,7 +264,7 @@ int QOperatingSystemVersion::compare(const QOperatingSystemVersion &v1,
-1 indicates an unknown or absent version number component.
- \sa majorVersion(), macro()
+ \sa majorVersion(), microVersion()
*/
/*!
@@ -282,11 +282,17 @@ int QOperatingSystemVersion::compare(const QOperatingSystemVersion &v1,
*/
/*!
+ \fn int QOperatingSystemVersion::segmentCount() const
+
+ Returns the number of integers stored in the version number.
+*/
+
+/*!
\fn QOperatingSystemVersion::OSType QOperatingSystemVersion::type() const
Returns the OS type identified by the QOperatingSystemVersion.
- \sa typeName()
+ \sa name()
*/
/*!
diff --git a/src/corelib/io/qdatastream.cpp b/src/corelib/io/qdatastream.cpp
index b4eb98e062..2730fd7f11 100644
--- a/src/corelib/io/qdatastream.cpp
+++ b/src/corelib/io/qdatastream.cpp
@@ -557,6 +557,7 @@ void QDataStream::setByteOrder(ByteOrder bo)
\value Qt_5_6 Version 17 (Qt 5.6)
\value Qt_5_7 Same as Qt_5_6
\value Qt_5_8 Same as Qt_5_6
+ \value Qt_5_9 Same as Qt_5_6
\omitvalue Qt_DefaultCompiledVersion
\sa setVersion(), version()
diff --git a/src/corelib/io/qdir.cpp b/src/corelib/io/qdir.cpp
index 37795ae5c4..bfb91c131f 100644
--- a/src/corelib/io/qdir.cpp
+++ b/src/corelib/io/qdir.cpp
@@ -1849,7 +1849,7 @@ bool QDir::exists(const QString &name) const
\c{QDir::AllEntries | QDir::NoDotAndDotDot}, but faster as it just checks
whether the directory contains at least one entry.
- \note Unless you set the \p filters flags to include \c{QDir::NoDotAndDotDot}
+ \note Unless you set the \a filters flags to include \c{QDir::NoDotAndDotDot}
(as the default value does), no directory is empty.
\sa count(), entryList(), setFilter()
diff --git a/src/corelib/io/qfilesystemengine_unix.cpp b/src/corelib/io/qfilesystemengine_unix.cpp
index 1b908eac55..40eadfb3e6 100644
--- a/src/corelib/io/qfilesystemengine_unix.cpp
+++ b/src/corelib/io/qfilesystemengine_unix.cpp
@@ -122,13 +122,10 @@ static bool isPackage(const QFileSystemMetaData &data, const QFileSystemEntry &e
if (CFBundleGetPackageInfoInDirectory(url, &type, &creator))
return true;
-#ifdef Q_OS_OSX
+#ifdef Q_OS_MACOS
// Find if an application other than Finder claims to know how to handle the package
- QCFType<CFURLRef> application;
- LSGetApplicationForURL(url,
- kLSRolesEditor|kLSRolesViewer,
- NULL,
- &application);
+ QCFType<CFURLRef> application = LSCopyDefaultApplicationURLForURL(url,
+ kLSRolesEditor | kLSRolesViewer, nullptr);
if (application) {
QCFType<CFBundleRef> bundle = CFBundleCreate(kCFAllocatorDefault, application);
diff --git a/src/corelib/io/qfsfileengine_unix.cpp b/src/corelib/io/qfsfileengine_unix.cpp
index b2e3df79b8..ca5af924e9 100644
--- a/src/corelib/io/qfsfileengine_unix.cpp
+++ b/src/corelib/io/qfsfileengine_unix.cpp
@@ -629,7 +629,7 @@ QString QFSFileEngine::fileName(FileName file) const
bool QFSFileEngine::isRelativePath() const
{
Q_D(const QFSFileEngine);
- return d->fileEntry.filePath().length() ? d->fileEntry.filePath()[0] != QLatin1Char('/') : true;
+ return d->fileEntry.filePath().length() ? d->fileEntry.filePath().at(0) != QLatin1Char('/') : true;
}
uint QFSFileEngine::ownerId(FileOwner own) const
diff --git a/src/corelib/kernel/qabstracteventdispatcher.h b/src/corelib/kernel/qabstracteventdispatcher.h
index f92e418ebf..68d9bf180f 100644
--- a/src/corelib/kernel/qabstracteventdispatcher.h
+++ b/src/corelib/kernel/qabstracteventdispatcher.h
@@ -95,7 +95,7 @@ public:
virtual int remainingTime(int timerId) = 0;
-#ifdef Q_OS_WIN
+#if defined(Q_OS_WIN) || defined(Q_QDOC)
virtual bool registerEventNotifier(QWinEventNotifier *notifier) = 0;
virtual void unregisterEventNotifier(QWinEventNotifier *notifier) = 0;
#endif
diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp
index ac1b2d41bf..5e6c44fb13 100644
--- a/src/corelib/kernel/qobject.cpp
+++ b/src/corelib/kernel/qobject.cpp
@@ -1642,7 +1642,7 @@ int QObject::startTimer(int interval, Qt::TimerType timerType)
it could not start a timer.
A timer event will occur every \a time interval until killTimer()
- is called. If \a interval is equal to \c{std::chrono::duration::zero()},
+ is called. If \a time is equal to \c{std::chrono::duration::zero()},
then the timer event occurs once every time there are no more window
system events to process.
diff --git a/src/corelib/tools/qlocale_mac.mm b/src/corelib/tools/qlocale_mac.mm
index 8587716446..c5519bfabf 100644
--- a/src/corelib/tools/qlocale_mac.mm
+++ b/src/corelib/tools/qlocale_mac.mm
@@ -43,9 +43,11 @@
#include "qvariant.h"
#include "qdatetime.h"
-#if !defined(QWS) && defined(Q_OS_MAC)
-# include "private/qcore_mac_p.h"
-# include <CoreFoundation/CoreFoundation.h>
+#ifdef Q_OS_DARWIN
+#include "qtimezone.h"
+#include "private/qcore_mac_p.h"
+#include <CoreFoundation/CoreFoundation.h>
+QT_REQUIRE_CONFIG(timezone);
#endif
QT_BEGIN_NAMESPACE
@@ -121,16 +123,7 @@ static QString macDayName(int day, bool short_format)
static QString macDateToString(const QDate &date, bool short_format)
{
- CFGregorianDate macGDate;
- macGDate.year = date.year();
- macGDate.month = date.month();
- macGDate.day = date.day();
- macGDate.hour = 0;
- macGDate.minute = 0;
- macGDate.second = 0.0;
- QCFType<CFDateRef> myDate
- = CFDateCreate(0, CFGregorianDateGetAbsoluteTime(macGDate,
- QCFType<CFTimeZoneRef>(CFTimeZoneCopyDefault())));
+ QCFType<CFDateRef> myDate = QDateTime(date, QTime()).toCFDate();
QCFType<CFLocaleRef> mylocale = CFLocaleCopyCurrent();
CFDateFormatterStyle style = short_format ? kCFDateFormatterShortStyle : kCFDateFormatterLongStyle;
QCFType<CFDateFormatterRef> myFormatter
@@ -142,19 +135,7 @@ static QString macDateToString(const QDate &date, bool short_format)
static QString macTimeToString(const QTime &time, bool short_format)
{
- CFGregorianDate macGDate;
- // Assume this is local time and the current date
- QDate dt = QDate::currentDate();
- macGDate.year = dt.year();
- macGDate.month = dt.month();
- macGDate.day = dt.day();
- macGDate.hour = time.hour();
- macGDate.minute = time.minute();
- macGDate.second = time.second();
- QCFType<CFDateRef> myDate
- = CFDateCreate(0, CFGregorianDateGetAbsoluteTime(macGDate,
- QCFType<CFTimeZoneRef>(CFTimeZoneCopyDefault())));
-
+ QCFType<CFDateRef> myDate = QDateTime(QDate::currentDate(), time).toCFDate();
QCFType<CFLocaleRef> mylocale = CFLocaleCopyCurrent();
CFDateFormatterStyle style = short_format ? kCFDateFormatterShortStyle : kCFDateFormatterLongStyle;
QCFType<CFDateFormatterRef> myFormatter = CFDateFormatterCreate(kCFAllocatorDefault,
diff --git a/src/gui/kernel/qoffscreensurface.cpp b/src/gui/kernel/qoffscreensurface.cpp
index e8a86590b5..307bc5e62f 100644
--- a/src/gui/kernel/qoffscreensurface.cpp
+++ b/src/gui/kernel/qoffscreensurface.cpp
@@ -335,7 +335,7 @@ void QOffscreenSurface::setScreen(QScreen *newScreen)
}
/*!
- Sets the native handle to which the offscreen surface is connected.
+ Sets the native handle to which the offscreen surface is connected to \a handle.
The native handle will be resolved in the create() function. Calling
this function after create() will not re-create a native surface.
diff --git a/src/gui/kernel/qplatformintegration.cpp b/src/gui/kernel/qplatformintegration.cpp
index fd7f475bee..fe1861e08b 100644
--- a/src/gui/kernel/qplatformintegration.cpp
+++ b/src/gui/kernel/qplatformintegration.cpp
@@ -409,6 +409,8 @@ QVariant QPlatformIntegration::styleHint(StyleHint hint) const
return QPlatformTheme::defaultThemeHint(QPlatformTheme::ItemViewActivateItemOnSingleClick);
case UiEffects:
return QPlatformTheme::defaultThemeHint(QPlatformTheme::UiEffects);
+ case WheelScrollLines:
+ return QPlatformTheme::defaultThemeHint(QPlatformTheme::WheelScrollLines);
}
return 0;
diff --git a/src/gui/kernel/qplatformintegration.h b/src/gui/kernel/qplatformintegration.h
index 22a834f0e1..466b3348bd 100644
--- a/src/gui/kernel/qplatformintegration.h
+++ b/src/gui/kernel/qplatformintegration.h
@@ -157,7 +157,8 @@ public:
TabFocusBehavior,
ReplayMousePressOutsidePopup,
ItemViewActivateItemOnSingleClick,
- UiEffects
+ UiEffects,
+ WheelScrollLines,
};
virtual QVariant styleHint(StyleHint hint) const;
diff --git a/src/gui/kernel/qstylehints.cpp b/src/gui/kernel/qstylehints.cpp
index 22c077da41..85c0768e35 100644
--- a/src/gui/kernel/qstylehints.cpp
+++ b/src/gui/kernel/qstylehints.cpp
@@ -78,6 +78,7 @@ public:
, m_cursorFlashTime(-1)
, m_tabFocusBehavior(-1)
, m_uiEffects(-1)
+ , m_wheelScrollLines(-1)
{}
int m_mouseDoubleClickInterval;
@@ -88,6 +89,7 @@ public:
int m_cursorFlashTime;
int m_tabFocusBehavior;
int m_uiEffects;
+ int m_wheelScrollLines;
};
/*!
@@ -495,4 +497,33 @@ void QStyleHints::setUseHoverEffects(bool useHoverEffects)
emit useHoverEffectsChanged(useHoverEffects);
}
+/*!
+ \property QStyleHints::wheelScrollLines
+ \brief Number of lines to scroll by default for each wheel click.
+
+ \since 5.9
+*/
+int QStyleHints::wheelScrollLines() const
+{
+ Q_D(const QStyleHints);
+ if (d->m_wheelScrollLines > 0)
+ return d->m_wheelScrollLines;
+ return themeableHint(QPlatformTheme::WheelScrollLines, QPlatformIntegration::WheelScrollLines).toInt();
+}
+
+/*!
+ Sets the \a wheelScrollLines.
+ \internal
+ \sa wheelScrollLines()
+ \since 5.9
+*/
+void QStyleHints::setWheelScrollLines(int scrollLines)
+{
+ Q_D(QStyleHints);
+ if (d->m_wheelScrollLines == scrollLines)
+ return;
+ d->m_wheelScrollLines = scrollLines;
+ emit wheelScrollLinesChanged(scrollLines);
+}
+
QT_END_NAMESPACE
diff --git a/src/gui/kernel/qstylehints.h b/src/gui/kernel/qstylehints.h
index fb55cc7ed6..b9bf428edd 100644
--- a/src/gui/kernel/qstylehints.h
+++ b/src/gui/kernel/qstylehints.h
@@ -71,6 +71,7 @@ class Q_GUI_EXPORT QStyleHints : public QObject
Q_PROPERTY(Qt::TabFocusBehavior tabFocusBehavior READ tabFocusBehavior NOTIFY tabFocusBehaviorChanged FINAL)
Q_PROPERTY(bool singleClickActivation READ singleClickActivation STORED false CONSTANT FINAL)
Q_PROPERTY(bool useHoverEffects READ useHoverEffects WRITE setUseHoverEffects NOTIFY useHoverEffectsChanged FINAL)
+ Q_PROPERTY(int wheelScrollLines READ wheelScrollLines NOTIFY wheelScrollLinesChanged FINAL)
public:
void setMouseDoubleClickInterval(int mouseDoubleClickInterval);
@@ -99,6 +100,8 @@ public:
bool singleClickActivation() const;
bool useHoverEffects() const;
void setUseHoverEffects(bool useHoverEffects);
+ int wheelScrollLines() const;
+ void setWheelScrollLines(int scrollLines);
Q_SIGNALS:
void cursorFlashTimeChanged(int cursorFlashTime);
@@ -109,6 +112,7 @@ Q_SIGNALS:
void startDragTimeChanged(int startDragTime);
void tabFocusBehaviorChanged(Qt::TabFocusBehavior tabFocusBehavior);
void useHoverEffectsChanged(bool useHoverEffects);
+ void wheelScrollLinesChanged(int scrollLines);
private:
friend class QGuiApplication;
diff --git a/src/gui/opengl/qopenglprogrambinarycache.cpp b/src/gui/opengl/qopenglprogrambinarycache.cpp
index 5c8e425e29..06373e1113 100644
--- a/src/gui/opengl/qopenglprogrambinarycache.cpp
+++ b/src/gui/opengl/qopenglprogrambinarycache.cpp
@@ -59,7 +59,7 @@ Q_DECLARE_LOGGING_CATEGORY(DBG_SHADER_CACHE)
#endif
const quint32 BINSHADER_MAGIC = 0x5174;
-const quint32 BINSHADER_VERSION = 0x1;
+const quint32 BINSHADER_VERSION = 0x2;
const quint32 BINSHADER_QTVERSION = QT_VERSION;
struct GLEnvInfo
@@ -114,24 +114,42 @@ QString QOpenGLProgramBinaryCache::cacheFileName(const QByteArray &cacheKey) con
return m_cacheDir + QString::fromUtf8(cacheKey);
}
-static const int HEADER_SIZE = 3 * sizeof(quint32);
+#define BASE_HEADER_SIZE (int(3 * sizeof(quint32)))
+#define FULL_HEADER_SIZE(stringsSize) (BASE_HEADER_SIZE + 12 + stringsSize + 8)
+#define PADDING_SIZE(fullHeaderSize) (((fullHeaderSize + 3) & ~3) - fullHeaderSize)
+
+static inline quint32 readUInt(const uchar **p)
+{
+ quint32 v;
+ memcpy(&v, *p, sizeof(quint32));
+ *p += sizeof(quint32);
+ return v;
+}
+
+static inline QByteArray readStr(const uchar **p)
+{
+ quint32 len = readUInt(p);
+ QByteArray ba = QByteArray::fromRawData(reinterpret_cast<const char *>(*p), len);
+ *p += len;
+ return ba;
+}
bool QOpenGLProgramBinaryCache::verifyHeader(const QByteArray &buf) const
{
- if (buf.size() < HEADER_SIZE) {
+ if (buf.size() < BASE_HEADER_SIZE) {
qCDebug(DBG_SHADER_CACHE, "Cached size too small");
return false;
}
- const quint32 *p = reinterpret_cast<const quint32 *>(buf.constData());
- if (*p++ != BINSHADER_MAGIC) {
+ const uchar *p = reinterpret_cast<const uchar *>(buf.constData());
+ if (readUInt(&p) != BINSHADER_MAGIC) {
qCDebug(DBG_SHADER_CACHE, "Magic does not match");
return false;
}
- if (*p++ != BINSHADER_VERSION) {
+ if (readUInt(&p) != BINSHADER_VERSION) {
qCDebug(DBG_SHADER_CACHE, "Version does not match");
return false;
}
- if (*p++ != BINSHADER_QTVERSION) {
+ if (readUInt(&p) != BINSHADER_QTVERSION) {
qCDebug(DBG_SHADER_CACHE, "Qt version does not match");
return false;
}
@@ -219,15 +237,15 @@ bool QOpenGLProgramBinaryCache::load(const QByteArray &cacheKey, uint programId)
FdWrapper fdw(fn);
if (fdw.fd == -1)
return false;
- char header[HEADER_SIZE];
- qint64 bytesRead = qt_safe_read(fdw.fd, header, HEADER_SIZE);
- if (bytesRead == HEADER_SIZE)
- buf = QByteArray::fromRawData(header, HEADER_SIZE);
+ char header[BASE_HEADER_SIZE];
+ qint64 bytesRead = qt_safe_read(fdw.fd, header, BASE_HEADER_SIZE);
+ if (bytesRead == BASE_HEADER_SIZE)
+ buf = QByteArray::fromRawData(header, BASE_HEADER_SIZE);
#else
QFile f(fn);
if (!f.open(QIODevice::ReadOnly))
return false;
- buf = f.read(HEADER_SIZE);
+ buf = f.read(BASE_HEADER_SIZE);
#endif
if (!verifyHeader(buf)) {
@@ -235,52 +253,63 @@ bool QOpenGLProgramBinaryCache::load(const QByteArray &cacheKey, uint programId)
return false;
}
- const quint32 *p;
+ const uchar *p;
#ifdef Q_OS_UNIX
if (!fdw.map()) {
undertaker.setActive();
return false;
}
- p = reinterpret_cast<const quint32 *>(static_cast<const char *>(fdw.ptr) + HEADER_SIZE);
+ p = static_cast<const uchar *>(fdw.ptr) + BASE_HEADER_SIZE;
#else
buf = f.readAll();
- p = reinterpret_cast<const quint32 *>(buf.constData());
+ p = reinterpret_cast<const uchar *>(buf.constData());
#endif
GLEnvInfo info;
- quint32 v = *p++;
- QByteArray vendor = QByteArray::fromRawData(reinterpret_cast<const char *>(p), v);
+ QByteArray vendor = readStr(&p);
if (vendor != info.glvendor) {
- qCDebug(DBG_SHADER_CACHE, "GL_VENDOR does not match (%s, %s)", vendor.constData(), info.glvendor.constData());
+ // readStr returns non-null terminated strings just pointing to inside
+ // 'p' so must print these via the stream qCDebug and not constData().
+ qCDebug(DBG_SHADER_CACHE) << "GL_VENDOR does not match" << vendor << info.glvendor;
undertaker.setActive();
return false;
}
- p = reinterpret_cast<const quint32 *>(reinterpret_cast<const char *>(p) + v);
- v = *p++;
- QByteArray renderer = QByteArray::fromRawData(reinterpret_cast<const char *>(p), v);
+ QByteArray renderer = readStr(&p);
if (renderer != info.glrenderer) {
- qCDebug(DBG_SHADER_CACHE, "GL_RENDERER does not match (%s, %s)", renderer.constData(), info.glrenderer.constData());
+ qCDebug(DBG_SHADER_CACHE) << "GL_RENDERER does not match" << renderer << info.glrenderer;
undertaker.setActive();
return false;
}
- p = reinterpret_cast<const quint32 *>(reinterpret_cast<const char *>(p) + v);
- v = *p++;
- QByteArray version = QByteArray::fromRawData(reinterpret_cast<const char *>(p), v);
+ QByteArray version = readStr(&p);
if (version != info.glversion) {
- qCDebug(DBG_SHADER_CACHE, "GL_VERSION does not match (%s, %s)", version.constData(), info.glversion.constData());
+ qCDebug(DBG_SHADER_CACHE) << "GL_VERSION does not match" << version << info.glversion;
undertaker.setActive();
return false;
}
- p = reinterpret_cast<const quint32 *>(reinterpret_cast<const char *>(p) + v);
- quint32 blobFormat = *p++;
- quint32 blobSize = *p++;
+ quint32 blobFormat = readUInt(&p);
+ quint32 blobSize = readUInt(&p);
+
+ p += PADDING_SIZE(FULL_HEADER_SIZE(vendor.size() + renderer.size() + version.size()));
return setProgramBinary(programId, blobFormat, p, blobSize)
&& m_memCache.insert(cacheKey, new MemCacheEntry(p, blobSize, blobFormat));
}
+static inline void writeUInt(uchar **p, quint32 value)
+{
+ memcpy(*p, &value, sizeof(quint32));
+ *p += sizeof(quint32);
+}
+
+static inline void writeStr(uchar **p, const QByteArray &str)
+{
+ writeUInt(p, str.size());
+ memcpy(*p, str.constData(), str.size());
+ *p += str.size();
+}
+
void QOpenGLProgramBinaryCache::save(const QByteArray &cacheKey, uint programId)
{
if (!m_cacheWritable)
@@ -292,37 +321,48 @@ void QOpenGLProgramBinaryCache::save(const QByteArray &cacheKey, uint programId)
GLint blobSize = 0;
while (funcs->glGetError() != GL_NO_ERROR) { }
funcs->glGetProgramiv(programId, GL_PROGRAM_BINARY_LENGTH, &blobSize);
- int totalSize = blobSize + 8 + 12 + 12 + info.glvendor.size() + info.glrenderer.size() + info.glversion.size();
+
+ const int headerSize = FULL_HEADER_SIZE(info.glvendor.size() + info.glrenderer.size() + info.glversion.size());
+
+ // Add padding to make the blob start 4-byte aligned in order to support
+ // OpenGL implementations on ARM that choke on non-aligned pointers passed
+ // to glProgramBinary.
+ const int paddingSize = PADDING_SIZE(headerSize);
+
+ const int totalSize = headerSize + paddingSize + blobSize;
+
qCDebug(DBG_SHADER_CACHE, "Program binary is %d bytes, err = 0x%x, total %d", blobSize, funcs->glGetError(), totalSize);
if (!blobSize)
return;
QByteArray blob(totalSize, Qt::Uninitialized);
- quint32 *p = reinterpret_cast<quint32 *>(blob.data());
-
- *p++ = BINSHADER_MAGIC;
- *p++ = BINSHADER_VERSION;
- *p++ = BINSHADER_QTVERSION;
-
- *p++ = info.glvendor.size();
- memcpy(p, info.glvendor.constData(), info.glvendor.size());
- p = reinterpret_cast<quint32 *>(reinterpret_cast<char *>(p) + info.glvendor.size());
- *p++ = info.glrenderer.size();
- memcpy(p, info.glrenderer.constData(), info.glrenderer.size());
- p = reinterpret_cast<quint32 *>(reinterpret_cast<char *>(p) + info.glrenderer.size());
- *p++ = info.glversion.size();
- memcpy(p, info.glversion.constData(), info.glversion.size());
- p = reinterpret_cast<quint32 *>(reinterpret_cast<char *>(p) + info.glversion.size());
+ uchar *p = reinterpret_cast<uchar *>(blob.data());
+
+ writeUInt(&p, BINSHADER_MAGIC);
+ writeUInt(&p, BINSHADER_VERSION);
+ writeUInt(&p, BINSHADER_QTVERSION);
+
+ writeStr(&p, info.glvendor);
+ writeStr(&p, info.glrenderer);
+ writeStr(&p, info.glversion);
+
+ quint32 blobFormat = 0;
+ uchar *blobFormatPtr = p;
+ writeUInt(&p, blobFormat);
+ writeUInt(&p, blobSize);
+
+ for (int i = 0; i < paddingSize; ++i)
+ *p++ = 0;
GLint outSize = 0;
- quint32 *blobFormat = p++;
- *p++ = blobSize;
- funcs->glGetProgramBinary(programId, blobSize, &outSize, blobFormat, p);
+ funcs->glGetProgramBinary(programId, blobSize, &outSize, &blobFormat, p);
if (blobSize != outSize) {
qCDebug(DBG_SHADER_CACHE, "glGetProgramBinary returned size %d instead of %d", outSize, blobSize);
return;
}
+ writeUInt(&blobFormatPtr, blobFormat);
+
QSaveFile f(cacheFileName(cacheKey));
if (f.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
f.write(blob);
diff --git a/src/gui/painting/qdrawhelper.cpp b/src/gui/painting/qdrawhelper.cpp
index 7cf0dd7f03..021361b738 100644
--- a/src/gui/painting/qdrawhelper.cpp
+++ b/src/gui/painting/qdrawhelper.cpp
@@ -5547,7 +5547,7 @@ static void qt_alphamapblit_quint16(QRasterBuffer *rasterBuffer,
int x, int y, const QRgba64 &color,
const uchar *map,
int mapWidth, int mapHeight, int mapStride,
- const QClipData *)
+ const QClipData *, bool /*useGammaCorrection*/)
{
const quint16 c = color.toRgb16();
quint16 *dest = reinterpret_cast<quint16*>(rasterBuffer->scanLine(y)) + x;
@@ -5572,18 +5572,16 @@ static void qt_alphamapblit_quint16(QRasterBuffer *rasterBuffer,
}
}
-static inline void rgbBlendPixel(quint32 *dst, int coverage, QRgba64 slinear, const QColorProfile *colorProfile)
+static inline void rgbBlendPixel(quint32 *dst, int coverage, QRgba64 slinear, const QColorProfile *colorProfile, bool useGammaCorrection)
{
// Do a gammacorrected RGB alphablend...
- const QRgba64 dlinear = colorProfile->toLinear64(*dst);
+ const QRgba64 dlinear = useGammaCorrection ? colorProfile->toLinear64(*dst) : QRgba64::fromArgb32(*dst);
QRgba64 blend = rgbBlend(dlinear, slinear, coverage);
- *dst = colorProfile->fromLinear64(blend);
+ *dst = useGammaCorrection ? colorProfile->fromLinear64(blend) : toArgb32(blend);
}
-Q_GUI_EXPORT bool qt_needs_a8_gamma_correction = false;
-
static inline void grayBlendPixel(quint32 *dst, int coverage, QRgba64 slinear, const QColorProfile *colorProfile)
{
// Do a gammacorrected gray alphablend...
@@ -5598,7 +5596,7 @@ static void qt_alphamapblit_uint32(QRasterBuffer *rasterBuffer,
int x, int y, quint32 color,
const uchar *map,
int mapWidth, int mapHeight, int mapStride,
- const QClipData *clip)
+ const QClipData *clip, bool useGammaCorrection)
{
const quint32 c = color;
const int destStride = rasterBuffer->bytesPerLine() / sizeof(quint32);
@@ -5610,7 +5608,7 @@ static void qt_alphamapblit_uint32(QRasterBuffer *rasterBuffer,
const QRgba64 slinear = colorProfile->toLinear64(c);
bool opaque_src = (qAlpha(color) == 255);
- bool doGrayBlendPixel = opaque_src && qt_needs_a8_gamma_correction;
+ bool doGrayBlendPixel = opaque_src && useGammaCorrection;
if (!clip) {
quint32 *dest = reinterpret_cast<quint32*>(rasterBuffer->scanLine(y)) + x;
@@ -5680,9 +5678,9 @@ static void qt_alphamapblit_argb32(QRasterBuffer *rasterBuffer,
int x, int y, const QRgba64 &color,
const uchar *map,
int mapWidth, int mapHeight, int mapStride,
- const QClipData *clip)
+ const QClipData *clip, bool useGammaCorrection)
{
- qt_alphamapblit_uint32(rasterBuffer, x, y, color.toArgb32(), map, mapWidth, mapHeight, mapStride, clip);
+ qt_alphamapblit_uint32(rasterBuffer, x, y, color.toArgb32(), map, mapWidth, mapHeight, mapStride, clip, useGammaCorrection);
}
#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
@@ -5690,9 +5688,9 @@ static void qt_alphamapblit_rgba8888(QRasterBuffer *rasterBuffer,
int x, int y, const QRgba64 &color,
const uchar *map,
int mapWidth, int mapHeight, int mapStride,
- const QClipData *clip)
+ const QClipData *clip, bool useGammaCorrection)
{
- qt_alphamapblit_uint32(rasterBuffer, x, y, ARGB2RGBA(color.toArgb32()), map, mapWidth, mapHeight, mapStride, clip);
+ qt_alphamapblit_uint32(rasterBuffer, x, y, ARGB2RGBA(color.toArgb32()), map, mapWidth, mapHeight, mapStride, clip, useGammaCorrection);
}
#endif
@@ -5704,7 +5702,7 @@ inline static int qRgbAvg(QRgb rgb)
static void qt_alphargbblit_argb32(QRasterBuffer *rasterBuffer,
int x, int y, const QRgba64 &color,
const uint *src, int mapWidth, int mapHeight, int srcStride,
- const QClipData *clip)
+ const QClipData *clip, bool useGammaCorrection)
{
const quint32 c = color.toArgb32();
@@ -5714,7 +5712,7 @@ static void qt_alphargbblit_argb32(QRasterBuffer *rasterBuffer,
if (!colorProfile)
return;
- const QRgba64 slinear = colorProfile->toLinear64(c);
+ const QRgba64 slinear = useGammaCorrection ? colorProfile->toLinear64(c) : color;
if (sa == 0)
return;
@@ -5729,7 +5727,7 @@ static void qt_alphargbblit_argb32(QRasterBuffer *rasterBuffer,
dst[i] = c;
} else if (coverage != 0xff000000) {
if (dst[i] >= 0xff000000) {
- rgbBlendPixel(dst+i, coverage, slinear, colorProfile);
+ rgbBlendPixel(dst+i, coverage, slinear, colorProfile, useGammaCorrection);
} else {
// Give up and do a naive blend.
const int a = qRgbAvg(coverage);
@@ -5765,7 +5763,7 @@ static void qt_alphargbblit_argb32(QRasterBuffer *rasterBuffer,
dst[xp] = c;
} else if (coverage != 0xff000000) {
if (dst[xp] >= 0xff000000) {
- rgbBlendPixel(dst+xp, coverage, slinear, colorProfile);
+ rgbBlendPixel(dst+xp, coverage, slinear, colorProfile, useGammaCorrection);
} else {
// Give up and do a naive blend.
const int a = qRgbAvg(coverage);
diff --git a/src/gui/painting/qdrawhelper_neon.cpp b/src/gui/painting/qdrawhelper_neon.cpp
index a833520b00..cdb374f823 100644
--- a/src/gui/painting/qdrawhelper_neon.cpp
+++ b/src/gui/painting/qdrawhelper_neon.cpp
@@ -539,7 +539,7 @@ void qt_alphamapblit_quint16_neon(QRasterBuffer *rasterBuffer,
int x, int y, const QRgba64 &color,
const uchar *bitmap,
int mapWidth, int mapHeight, int mapStride,
- const QClipData *)
+ const QClipData *, bool /*useGammaCorrection*/)
{
quint16 *dest = reinterpret_cast<quint16*>(rasterBuffer->scanLine(y)) + x;
const int destStride = rasterBuffer->bytesPerLine() / sizeof(quint16);
diff --git a/src/gui/painting/qdrawhelper_neon_p.h b/src/gui/painting/qdrawhelper_neon_p.h
index 3cf949fc32..40475a9bde 100644
--- a/src/gui/painting/qdrawhelper_neon_p.h
+++ b/src/gui/painting/qdrawhelper_neon_p.h
@@ -91,7 +91,7 @@ void qt_alphamapblit_quint16_neon(QRasterBuffer *rasterBuffer,
int x, int y, const QRgba64 &color,
const uchar *bitmap,
int mapWidth, int mapHeight, int mapStride,
- const QClipData *clip);
+ const QClipData *clip, bool /*useGammaCorrection*/);
void qt_scale_image_argb32_on_rgb16_neon(uchar *destPixels, int dbpl,
const uchar *srcPixels, int sbpl, int srch,
diff --git a/src/gui/painting/qdrawhelper_p.h b/src/gui/painting/qdrawhelper_p.h
index e4a1faf25b..cf2213042d 100644
--- a/src/gui/painting/qdrawhelper_p.h
+++ b/src/gui/painting/qdrawhelper_p.h
@@ -113,13 +113,13 @@ typedef void (*AlphamapBlitFunc)(QRasterBuffer *rasterBuffer,
int x, int y, const QRgba64 &color,
const uchar *bitmap,
int mapWidth, int mapHeight, int mapStride,
- const QClipData *clip);
+ const QClipData *clip, bool useGammaCorrection);
typedef void (*AlphaRGBBlitFunc)(QRasterBuffer *rasterBuffer,
int x, int y, const QRgba64 &color,
const uint *rgbmask,
int mapWidth, int mapHeight, int mapStride,
- const QClipData *clip);
+ const QClipData *clip, bool useGammaCorrection);
typedef void (*RectFillFunc)(QRasterBuffer *rasterBuffer,
int x, int y, int width, int height,
diff --git a/src/gui/painting/qpaintengine_raster.cpp b/src/gui/painting/qpaintengine_raster.cpp
index 43464d5d2c..09177db2ab 100644
--- a/src/gui/painting/qpaintengine_raster.cpp
+++ b/src/gui/painting/qpaintengine_raster.cpp
@@ -2555,7 +2555,7 @@ QRasterBuffer *QRasterPaintEngine::rasterBuffer()
/*!
\internal
*/
-void QRasterPaintEngine::alphaPenBlt(const void* src, int bpl, int depth, int rx,int ry,int w,int h)
+void QRasterPaintEngine::alphaPenBlt(const void* src, int bpl, int depth, int rx,int ry,int w,int h, bool useGammaCorrection)
{
Q_D(QRasterPaintEngine);
QRasterPaintEngineState *s = state();
@@ -2610,14 +2610,14 @@ void QRasterPaintEngine::alphaPenBlt(const void* src, int bpl, int depth, int rx
} else if (depth == 8) {
if (s->penData.alphamapBlit) {
s->penData.alphamapBlit(rb, rx, ry, s->penData.solid.color,
- scanline, w, h, bpl, 0);
+ scanline, w, h, bpl, 0, useGammaCorrection);
return;
}
} else if (depth == 32) {
// (A)RGB Alpha mask where the alpha component is not used.
if (s->penData.alphaRGBBlit) {
s->penData.alphaRGBBlit(rb, rx, ry, s->penData.solid.color,
- (const uint *) scanline, w, h, bpl / 4, 0);
+ (const uint *) scanline, w, h, bpl / 4, 0, useGammaCorrection);
return;
}
}
@@ -2646,10 +2646,10 @@ void QRasterPaintEngine::alphaPenBlt(const void* src, int bpl, int depth, int rx
}
if (depth == 8)
s->penData.alphamapBlit(rb, rx, ry, s->penData.solid.color,
- scanline, w, h, bpl, clip);
+ scanline, w, h, bpl, clip, useGammaCorrection);
else if (depth == 32)
s->penData.alphaRGBBlit(rb, rx, ry, s->penData.solid.color,
- (const uint *) scanline, w, h, bpl / 4, clip);
+ (const uint *) scanline, w, h, bpl / 4, clip, useGammaCorrection);
return;
}
}
@@ -2807,7 +2807,8 @@ bool QRasterPaintEngine::drawCachedGlyphs(int numGlyphs, const glyph_t *glyphs,
alphaPenBlt(alphaMap->constBits(), alphaMap->bytesPerLine(), alphaMap->depth(),
qFloor(positions[i].x) + offset.x(),
qRound(positions[i].y) + offset.y(),
- alphaMap->width(), alphaMap->height());
+ alphaMap->width(), alphaMap->height(),
+ fontEngine->expectsGammaCorrectedBlending());
fontEngine->unlockAlphaMapForGlyph();
}
@@ -2868,7 +2869,7 @@ bool QRasterPaintEngine::drawCachedGlyphs(int numGlyphs, const glyph_t *glyphs,
drawImage(QPoint(x, y), QImage(glyphBits, c.w, c.h, bpl, image.format()));
s->matrix = originalTransform;
} else {
- alphaPenBlt(glyphBits, bpl, depth, x, y, c.w, c.h);
+ alphaPenBlt(glyphBits, bpl, depth, x, y, c.w, c.h, fontEngine->expectsGammaCorrectedBlending());
}
}
}
diff --git a/src/gui/painting/qpaintengine_raster_p.h b/src/gui/painting/qpaintengine_raster_p.h
index 59213220a6..d0b82b3a93 100644
--- a/src/gui/painting/qpaintengine_raster_p.h
+++ b/src/gui/painting/qpaintengine_raster_p.h
@@ -225,7 +225,7 @@ public:
#endif
QRasterBuffer *rasterBuffer();
- void alphaPenBlt(const void* src, int bpl, int depth, int rx,int ry,int w,int h);
+ void alphaPenBlt(const void* src, int bpl, int depth, int rx,int ry,int w,int h, bool useGammaCorrection);
Type type() const Q_DECL_OVERRIDE { return Raster; }
diff --git a/src/gui/text/qfontengine.cpp b/src/gui/text/qfontengine.cpp
index 0b2972f189..8d8ca1ba2c 100644
--- a/src/gui/text/qfontengine.cpp
+++ b/src/gui/text/qfontengine.cpp
@@ -445,6 +445,11 @@ bool QFontEngine::supportsTransformation(const QTransform &transform) const
return transform.type() < QTransform::TxProject;
}
+bool QFontEngine::expectsGammaCorrectedBlending() const
+{
+ return true;
+}
+
void QFontEngine::getGlyphPositions(const QGlyphLayout &glyphs, const QTransform &matrix, QTextItem::RenderFlags flags,
QVarLengthArray<glyph_t> &glyphs_out, QVarLengthArray<QFixedPoint> &positions)
{
diff --git a/src/gui/text/qfontengine_ft.cpp b/src/gui/text/qfontengine_ft.cpp
index de6da88245..03e72546eb 100644
--- a/src/gui/text/qfontengine_ft.cpp
+++ b/src/gui/text/qfontengine_ft.cpp
@@ -61,17 +61,19 @@
#include FT_TRUETYPE_TABLES_H
#include FT_TYPE1_TABLES_H
#include FT_GLYPH_H
+#include FT_MODULE_H
#if defined(FT_LCD_FILTER_H)
#include FT_LCD_FILTER_H
+#define QT_USE_FREETYPE_LCDFILTER
#endif
#if defined(FT_CONFIG_OPTIONS_H)
#include FT_CONFIG_OPTIONS_H
#endif
-#if defined(FT_LCD_FILTER_H)
-#define QT_USE_FREETYPE_LCDFILTER
+#if defined(FT_FONT_FORMATS_H)
+#include FT_FONT_FORMATS_H
#endif
#ifdef QT_LINUXBASE
@@ -151,6 +153,14 @@ QtFreetypeData *qt_getFreetypeData()
QtFreetypeData *&freetypeData = theFreetypeData()->localData();
if (!freetypeData)
freetypeData = new QtFreetypeData;
+ if (!freetypeData->library) {
+ FT_Init_FreeType(&freetypeData->library);
+#if defined(FT_FONT_FORMATS_H)
+ // Freetype defaults to disabling stem-darkening on CFF, we re-enable it.
+ FT_Bool no_darkening = false;
+ FT_Property_Set(freetypeData->library, "cff", "no-stem-darkening", &no_darkening);
+#endif
+ }
return freetypeData;
}
#endif
@@ -158,8 +168,7 @@ QtFreetypeData *qt_getFreetypeData()
FT_Library qt_getFreetype()
{
QtFreetypeData *freetypeData = qt_getFreetypeData();
- if (!freetypeData->library)
- FT_Init_FreeType(&freetypeData->library);
+ Q_ASSERT(freetypeData->library);
return freetypeData->library;
}
@@ -218,8 +227,6 @@ QFreetypeFace *QFreetypeFace::getFace(const QFontEngine::FaceId &face_id,
return 0;
QtFreetypeData *freetypeData = qt_getFreetypeData();
- if (!freetypeData->library)
- FT_Init_FreeType(&freetypeData->library);
QFreetypeFace *freetype = freetypeData->faces.value(face_id, 0);
if (freetype) {
@@ -687,6 +694,7 @@ QFontEngineFT::QFontEngineFT(const QFontDef &fd)
cacheEnabled = env.isEmpty() || env.toInt() == 0;
m_subPixelPositionCount = 4;
forceAutoHint = false;
+ stemDarkeningDriver = false;
}
QFontEngineFT::~QFontEngineFT()
@@ -798,6 +806,17 @@ bool QFontEngineFT::init(FaceId faceId, bool antialias, GlyphFormat format,
}
}
}
+#if defined(FT_FONT_FORMATS_H)
+ const char *fmt = FT_Get_Font_Format(face);
+ if (fmt && qstrncmp(fmt, "CFF", 4) == 0) {
+ FT_Bool no_stem_darkening = true;
+ FT_Error err = FT_Property_Get(qt_getFreetype(), "cff", "no-stem-darkening", &no_stem_darkening);
+ if (err == FT_Err_Ok)
+ stemDarkeningDriver = !no_stem_darkening;
+ else
+ stemDarkeningDriver = false;
+ }
+#endif
fontDef.styleName = QString::fromUtf8(face->style_name);
@@ -841,6 +860,11 @@ void QFontEngineFT::setDefaultHintStyle(HintStyle style)
default_hint_style = style;
}
+bool QFontEngineFT::expectsGammaCorrectedBlending() const
+{
+ return stemDarkeningDriver;
+}
+
int QFontEngineFT::loadFlags(QGlyphSet *set, GlyphFormat format, int flags,
bool &hsubpixel, int &vfactor) const
{
diff --git a/src/gui/text/qfontengine_ft_p.h b/src/gui/text/qfontengine_ft_p.h
index 32357d0076..47f13eb274 100644
--- a/src/gui/text/qfontengine_ft_p.h
+++ b/src/gui/text/qfontengine_ft_p.h
@@ -252,6 +252,7 @@ private:
QPoint *offset) Q_DECL_OVERRIDE;
bool hasInternalCaching() const Q_DECL_OVERRIDE { return cacheEnabled; }
void unlockAlphaMapForGlyph() Q_DECL_OVERRIDE;
+ bool expectsGammaCorrectedBlending() const Q_DECL_OVERRIDE;
void removeGlyphFromCache(glyph_t glyph) Q_DECL_OVERRIDE;
int glyphMargin(QFontEngine::GlyphFormat /* format */) Q_DECL_OVERRIDE { return 0; }
@@ -311,6 +312,7 @@ protected:
bool embeddedbitmap;
bool cacheEnabled;
bool forceAutoHint;
+ bool stemDarkeningDriver;
private:
friend class QFontEngineFTRawFont;
diff --git a/src/gui/text/qfontengine_p.h b/src/gui/text/qfontengine_p.h
index c0e350f755..514e9424b2 100644
--- a/src/gui/text/qfontengine_p.h
+++ b/src/gui/text/qfontengine_p.h
@@ -254,6 +254,7 @@ public:
static QByteArray convertToPostscriptFontFamilyName(const QByteArray &fontFamily);
virtual bool hasUnreliableGlyphOutline() const;
+ virtual bool expectsGammaCorrectedBlending() const;
enum HintStyle {
HintNone,
diff --git a/src/network/access/access.pri b/src/network/access/access.pri
index 766d72590c..13d52ea44a 100644
--- a/src/network/access/access.pri
+++ b/src/network/access/access.pri
@@ -40,7 +40,8 @@ HEADERS += \
access/qhttpmultipart_p.h \
access/qnetworkfile_p.h \
access/qhttp2protocolhandler_p.h \
- access/qhsts_p.h
+ access/qhsts_p.h \
+ access/qhstspolicy.h
SOURCES += \
access/qftp.cpp \
@@ -74,7 +75,8 @@ SOURCES += \
access/qhttpmultipart.cpp \
access/qnetworkfile.cpp \
access/qhttp2protocolhandler.cpp \
- access/qhsts.cpp
+ access/qhsts.cpp \
+ access/qhstspolicy.cpp
mac: LIBS_PRIVATE += -framework Security
diff --git a/src/network/access/qhsts.cpp b/src/network/access/qhsts.cpp
index 2352c3e4f2..5e4f75b0ed 100644
--- a/src/network/access/qhsts.cpp
+++ b/src/network/access/qhsts.cpp
@@ -45,17 +45,8 @@
QT_BEGIN_NAMESPACE
-static bool expired_policy(const QDateTime &expires)
+static bool is_valid_domain_name(const QString &host)
{
- return !expires.isValid() || expires <= QDateTime::currentDateTimeUtc();
-}
-
-static bool has_valid_domain_name(const QUrl &url)
-{
- if (!url.isValid())
- return false;
-
- const QString host(url.host());
if (!host.size())
return false;
@@ -82,117 +73,106 @@ static bool has_valid_domain_name(const QUrl &url)
return true;
}
-QHstsCache::QHstsCache()
-{
- // Top-level domain without any label.
- children.push_back(Domain());
-}
-
void QHstsCache::updateFromHeaders(const QList<QPair<QByteArray, QByteArray>> &headers,
const QUrl &url)
{
- if (!has_valid_domain_name(url))
+ if (!url.isValid())
return;
QHstsHeaderParser parser;
if (parser.parse(headers))
- updateKnownHost(url, parser.expirationDate(), parser.includeSubDomains());
+ updateKnownHost(url.host(), parser.expirationDate(), parser.includeSubDomains());
+}
+
+void QHstsCache::updateFromPolicies(const QList<QHstsPolicy> &policies)
+{
+ for (const auto &policy : policies)
+ updateKnownHost(policy.host(), policy.expiry(), policy.includesSubDomains());
}
-void QHstsCache::updateKnownHost(const QUrl &originalUrl, const QDateTime &expires,
+void QHstsCache::updateKnownHost(const QUrl &url, const QDateTime &expires,
bool includeSubDomains)
{
- if (!has_valid_domain_name(originalUrl))
+ if (!url.isValid())
return;
- // HSTS is a per-host policy, regardless of protocol, port or any of the other
- // details in an URL; so we only want the host part. We still package this as
- // a QUrl since this handles IDNA 2003 (RFC3490) for us, as required by
- // HSTS (RFC6797, section 10).
- QUrl url;
- url.setHost(originalUrl.host());
-
- // 1. Update our hosts:
- QStringList labels(url.host().split(QLatin1Char('.')));
- std::reverse(labels.begin(), labels.end());
-
- size_type domainIndex = 0;
- for (int i = 0, e = labels.size(); i < e; ++i) {
- Q_ASSERT(domainIndex < children.size());
- auto &subDomains = children[domainIndex].labels;
- const auto &label = labels[i];
- auto pos = std::lower_bound(subDomains.begin(), subDomains.end(), label);
- if (pos == subDomains.end() || pos->label != label) {
- // A new, previously unknown host.
- if (expired_policy(expires)) {
- // Nothing to do at all - we did not know this host previously,
- // we do not have to - since its policy expired.
- return;
- }
-
- pos = subDomains.insert(pos, label);
- domainIndex = children.size();
- pos->domainIndex = domainIndex;
- children.resize(children.size() + (e - i));
+ updateKnownHost(url.host(), expires, includeSubDomains);
+}
- for (int j = i + 1; j < e; ++j) {
- auto &newDomain = children[domainIndex];
- newDomain.labels.push_back(labels[j]);
- newDomain.labels.back().domainIndex = ++domainIndex;
- }
+void QHstsCache::updateKnownHost(const QString &host, const QDateTime &expires,
+ bool includeSubDomains)
+{
+ if (!is_valid_domain_name(host))
+ return;
- break;
+ // HSTS is a per-host policy, regardless of protocol, port or any of the other
+ // details in an URL; so we only want the host part. QUrl::host handles
+ // IDNA 2003 (RFC3490) for us, as required by HSTS (RFC6797, section 10).
+ const HostName hostName(host);
+ const auto pos = knownHosts.find(hostName);
+ const QHstsPolicy newPolicy(expires, includeSubDomains, hostName.name);
+ if (pos == knownHosts.end()) {
+ // A new, previously unknown host.
+ if (newPolicy.isExpired()) {
+ // Nothing to do at all - we did not know this host previously,
+ // we do not have to - since its policy expired.
+ return;
}
- domainIndex = pos->domainIndex;
+ knownHosts.insert(pos, hostName, newPolicy);
+ return;
}
- Q_ASSERT(domainIndex > 0 && domainIndex < children.size());
- children[domainIndex].setHostPolicy(expires, includeSubDomains);
+ if (newPolicy.isExpired())
+ knownHosts.erase(pos);
+ else
+ *pos = std::move(newPolicy);
}
-bool QHstsCache::isKnownHost(const QUrl &originalUrl) const
+bool QHstsCache::isKnownHost(const QUrl &url) const
{
- if (!has_valid_domain_name(originalUrl))
+ if (!url.isValid() || !is_valid_domain_name(url.host()))
return false;
- QUrl url;
- url.setHost(originalUrl.host());
-
- QStringList labels(url.host().split(QLatin1Char('.')));
- std::reverse(labels.begin(), labels.end());
+ /*
+ RFC6797, 8.2. Known HSTS Host Domain Name Matching
+
+ * Superdomain Match
+ If a label-for-label match between an entire Known HSTS Host's
+ domain name and a right-hand portion of the given domain name
+ is found, then this Known HSTS Host's domain name is a
+ superdomain match for the given domain name. There could be
+ multiple superdomain matches for a given domain name.
+ * Congruent Match
+ If a label-for-label match between a Known HSTS Host's domain
+ name and the given domain name is found -- i.e., there are no
+ further labels to compare -- then the given domain name
+ congruently matches this Known HSTS Host.
+
+ We start from the congruent match, and then chop labels and dots and
+ proceed with superdomain match. While RFC6797 recommends to start from
+ superdomain, the result is the same - some valid policy will make a host
+ known.
+ */
+
+ bool superDomainMatch = false;
+ const QString hostNameAsString(url.host());
+ HostName nameToTest(static_cast<QStringRef>(&hostNameAsString));
+ while (nameToTest.fragment.size()) {
+ auto const pos = knownHosts.find(nameToTest);
+ if (pos != knownHosts.end()) {
+ if (pos.value().isExpired())
+ knownHosts.erase(pos);
+ else if (!superDomainMatch || pos.value().includesSubDomains())
+ return true;
+ }
- Q_ASSERT(children.size());
- size_type domainIndex = 0;
- for (int i = 0, e = labels.size(); i < e; ++i) {
- Q_ASSERT(domainIndex < children.size());
- const auto &subDomains = children[domainIndex].labels;
- auto pos = std::lower_bound(subDomains.begin(), subDomains.end(), labels[i]);
- if (pos == subDomains.end() || pos->label != labels[i])
- return false;
+ const int dot = nameToTest.fragment.indexOf(QLatin1Char('.'));
+ if (dot == -1)
+ break;
- Q_ASSERT(pos->domainIndex < children.size());
- domainIndex = pos->domainIndex;
- auto &domain = children[domainIndex];
- if (domain.validateHostPolicy() && (i + 1 == e || domain.includeSubDomains)) {
- /*
- RFC6797, 8.2. Known HSTS Host Domain Name Matching
-
- * Superdomain Match
- If a label-for-label match between an entire Known HSTS Host's
- domain name and a right-hand portion of the given domain name
- is found, then this Known HSTS Host's domain name is a
- superdomain match for the given domain name. There could be
- multiple superdomain matches for a given domain name.
- * Congruent Match
- If a label-for-label match between a Known HSTS Host's domain
- name and the given domain name is found -- i.e., there are no
- further labels to compare -- then the given domain name
- congruently matches this Known HSTS Host.
- */
-
- return true;
- }
+ nameToTest.fragment = nameToTest.fragment.mid(dot + 1);
+ superDomainMatch = true;
}
return false;
@@ -200,10 +180,12 @@ bool QHstsCache::isKnownHost(const QUrl &originalUrl) const
void QHstsCache::clear()
{
- children.resize(1);
- children[0].labels.clear();
- // Top-level is never known:
- Q_ASSERT(!children[0].isKnownHost);
+ knownHosts.clear();
+}
+
+QList<QHstsPolicy> QHstsCache::policies() const
+{
+ return knownHosts.values();
}
// The parser is quite simple: 'nextToken' knowns exactly what kind of tokens
diff --git a/src/network/access/qhsts_p.h b/src/network/access/qhsts_p.h
index f3d5da9d23..5d95f39b96 100644
--- a/src/network/access/qhsts_p.h
+++ b/src/network/access/qhsts_p.h
@@ -51,17 +51,16 @@
// We mean it.
//
+#include <QtNetwork/qhstspolicy.h>
+
#include <QtCore/qbytearray.h>
#include <QtCore/qdatetime.h>
#include <QtCore/qstring.h>
#include <QtCore/qglobal.h>
-#include <QtCore/qvector.h>
#include <QtCore/qlist.h>
#include <QtCore/qpair.h>
#include <QtCore/qurl.h>
-
-#include <algorithm>
-#include <vector>
+#include <QtCore/qmap.h>
QT_BEGIN_NAMESPACE
@@ -69,72 +68,48 @@ class Q_AUTOTEST_EXPORT QHstsCache
{
public:
- QHstsCache();
-
void updateFromHeaders(const QList<QPair<QByteArray, QByteArray>> &headers,
const QUrl &url);
+ void updateFromPolicies(const QList<QHstsPolicy> &hosts);
void updateKnownHost(const QUrl &url, const QDateTime &expires,
bool includeSubDomains);
bool isKnownHost(const QUrl &url) const;
-
void clear();
-private:
-
- using size_type = std::vector<int>::size_type;
-
- struct DomainLabel
- {
- DomainLabel(const QString &name = QString()) : label(name), domainIndex(0) {}
+ QList<QHstsPolicy> policies() const;
- bool operator < (const DomainLabel &rhs) const
- { return label < rhs.label; }
+private:
- QString label;
- size_type domainIndex;
- };
+ void updateKnownHost(const QString &hostName, const QDateTime &expires,
+ bool includeSubDomains);
- struct Domain
+ struct HostName
{
- void setHostPolicy(const QDateTime &expiration, bool subs)
- {
- expirationTime = expiration;
- isKnownHost = expirationTime.isValid()
- && expirationTime > QDateTime::currentDateTimeUtc();
- includeSubDomains = subs;
- }
+ explicit HostName(const QString &n) : name(n) { }
+ explicit HostName(const QStringRef &r) : fragment(r) { }
- bool validateHostPolicy()
+ bool operator < (const HostName &rhs) const
{
- if (!isKnownHost)
- return false;
-
- if (expirationTime > QDateTime::currentDateTimeUtc())
- return true;
-
- isKnownHost = false;
- includeSubDomains = false;
- return false;
+ if (fragment.size()) {
+ if (rhs.fragment.size())
+ return fragment < rhs.fragment;
+ return fragment < QStringRef(&rhs.name);
+ }
+
+ if (rhs.fragment.size())
+ return QStringRef(&name) < rhs.fragment;
+ return name < rhs.name;
}
- bool isKnownHost = false;
- bool includeSubDomains = false;
- QDateTime expirationTime;
- std::vector<DomainLabel> labels;
+ // We use 'name' for a HostName object contained in our dictionary;
+ // we use 'fragment' only during lookup, when chopping the complete host
+ // name, removing subdomain names (such HostName object is 'transient', it
+ // must not outlive the original QString object.
+ QString name;
+ QStringRef fragment;
};
- /*
- Each Domain represents a DNS name or prefix thereof; each entry in its
- std::vector<DomainLabel> labels pairs the next fragment of a DNS name
- with the index into 'children' at which to find another Domain object.
- The root Domain, children[0], has top-level-domain DomainLabel entries,
- such as "com", "org" and "net"; the entry in 'children' at the index it
- pairs with "com" is the Domain entry for .com; if that has "example" in
- its labels, it'll be paired with the index of the entry in 'children'
- that represents example.com; from which, in turn, we can find the
- Domain object for www.example.com, and so on.
- */
- mutable std::vector<Domain> children;
+ mutable QMap<HostName, QHstsPolicy> knownHosts;
};
class Q_AUTOTEST_EXPORT QHstsHeaderParser
diff --git a/src/network/access/qhstspolicy.cpp b/src/network/access/qhstspolicy.cpp
new file mode 100644
index 0000000000..2cec587f4d
--- /dev/null
+++ b/src/network/access/qhstspolicy.cpp
@@ -0,0 +1,218 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtNetwork module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qhstspolicy.h"
+
+#include <QtCore/qdatetime.h>
+#include <QtCore/qstring.h>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QHstsPolicy
+ \brief The QHstsPolicy class specifies that a host supports HTTP Strict Transport
+ Security policy (HSTS).
+ \since 5.9
+ \ingroup network
+ \inmodule QtNetwork
+
+ HSTS policy defines a period of time during which QNetworkAccessManager
+ should only access a host in a secure fashion. HSTS policy is defined by
+ RFC6797.
+
+ You can set expiry time and host name for this policy, and control whether it
+ applies to subdomains, either in the constructor or by calling setExpiry(),
+ setHost() and setIncludesSubdomains().
+
+ \sa QNetworkAccessManager::enableStrictTransportSecurity()
+*/
+
+class QHstsPolicyPrivate
+{
+public:
+ QUrl url;
+ QDateTime expiry;
+ bool includeSubDomains = false;
+
+ bool operator == (const QHstsPolicyPrivate &other) const
+ {
+ return url.host() == other.url.host() && expiry == other.expiry
+ && includeSubDomains == other.includeSubDomains;
+ }
+};
+
+/*!
+ Constructs an invalid (expired) policy with empty host name and subdomains
+ not included.
+*/
+QHstsPolicy::QHstsPolicy() : d(new QHstsPolicyPrivate)
+{
+}
+
+/*!
+ Constructs QHstsPolicy with \a expiry (in UTC); \a includeSubDomains parameter
+ defines if this policy must also include subdomains, \a host data is interpreted
+ according to \a mode.
+
+ \sa QUrl::setHost(), QUrl::ParsingMode
+*/
+QHstsPolicy::QHstsPolicy(const QDateTime &expiry, bool includeSubDomains, const QString &host,
+ QUrl::ParsingMode mode)
+ : d(new QHstsPolicyPrivate)
+{
+ d->url.setHost(host, mode);
+ d->expiry = expiry;
+ d->includeSubDomains = includeSubDomains;
+}
+
+/*!
+ Creates a copy of \a other object.
+*/
+QHstsPolicy::QHstsPolicy(const QHstsPolicy &other)
+ : d(new QHstsPolicyPrivate(*other.d))
+{
+}
+
+/*!
+ Destructor.
+*/
+QHstsPolicy::~QHstsPolicy()
+{
+}
+
+/*!
+ Copy-assignment operator, makes a copy of \a other.
+*/
+QHstsPolicy &QHstsPolicy::operator=(const QHstsPolicy &other)
+{
+ *d = *other.d;
+ return *this;
+}
+
+
+/*!
+ Move-assignment operator.
+*/
+QHstsPolicy &QHstsPolicy::operator=(QHstsPolicy &&other) Q_DECL_NOTHROW
+{
+ qSwap(d, other.d);
+ return *this;
+}
+
+/*!
+ Sets a host, \a host data is interpreted according to \a mode parameter.
+
+ \sa host(), QUrl::setHost(), QUrl::ParsingMode
+*/
+void QHstsPolicy::setHost(const QString &host, QUrl::ParsingMode mode)
+{
+ d->url.setHost(host, mode);
+}
+
+/*!
+ Returns a host for a given policy, formatted according to \a options.
+
+ \sa setHost(), QUrl::host(), QUrl::ComponentFormattingOptions
+*/
+QString QHstsPolicy::host(QUrl::ComponentFormattingOptions options) const
+{
+ return d->url.host(options);
+}
+
+/*!
+ Sets the expiration date for the policy (in UTC).
+
+ \sa expiry()
+*/
+void QHstsPolicy::setExpiry(const QDateTime &expiry)
+{
+ d->expiry = expiry;
+}
+
+/*!
+ Returns the expiration date for the policy (in UTC).
+
+ \sa setExpiry()
+*/
+QDateTime QHstsPolicy::expiry() const
+{
+ return d->expiry;
+}
+
+/*!
+ Includes or excludes subdomains for this policy.
+
+ \sa includeSubdomains()
+*/
+void QHstsPolicy::setIncludesSubDomains(bool include)
+{
+ d->includeSubDomains = include;
+}
+
+/*!
+ Returns \c true if this policy also includes subdomains.
+
+ \sa setIncludesSubDomains()
+ */
+bool QHstsPolicy::includesSubDomains() const
+{
+ return d->includeSubDomains;
+}
+
+/*!
+ Returns \c true if the two policies have the same host and expriration date
+ while agreeing on whether to include or exclude subdomains.
+*/
+bool QHstsPolicy::operator==(const QHstsPolicy &other) const
+{
+ return *d == *other.d;
+}
+
+/*!
+ Return \c true if this policy has a valid expiration date and this date
+ is greater than QDateTime::currentGetDateTimeUtc().
+
+ \sa setExpiry(), expiry()
+*/
+bool QHstsPolicy::isExpired() const
+{
+ return !d->expiry.isValid() || d->expiry <= QDateTime::currentDateTimeUtc();
+}
+
+QT_END_NAMESPACE
diff --git a/src/network/access/qhstspolicy.h b/src/network/access/qhstspolicy.h
new file mode 100644
index 0000000000..4260ac278c
--- /dev/null
+++ b/src/network/access/qhstspolicy.h
@@ -0,0 +1,82 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtNetwork module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QHSTSPOLICY_H
+#define QHSTSPOLICY_H
+
+#include <QtNetwork/qtnetworkglobal.h>
+
+#include <QtCore/qscopedpointer.h>
+#include <QtCore/qurl.h>
+
+QT_BEGIN_NAMESPACE
+
+class QHstsPolicyPrivate;
+class QDateTime;
+class QString;
+class Q_NETWORK_EXPORT QHstsPolicy
+{
+public:
+
+ QHstsPolicy();
+ QHstsPolicy(const QDateTime &expiry, bool includeSubDomains, const QString &host,
+ QUrl::ParsingMode mode = QUrl::DecodedMode);
+ QHstsPolicy(const QHstsPolicy &rhs);
+ QHstsPolicy &operator=(const QHstsPolicy &rhs);
+ QHstsPolicy &operator=(QHstsPolicy &&rhs) Q_DECL_NOTHROW;
+ ~QHstsPolicy();
+
+ void setHost(const QString &host, QUrl::ParsingMode mode = QUrl::DecodedMode);
+ QString host(QUrl::ComponentFormattingOptions options = QUrl::FullyDecoded) const;
+ void setExpiry(const QDateTime &expiry);
+ QDateTime expiry() const;
+ void setIncludesSubDomains(bool include);
+ bool includesSubDomains() const;
+
+ bool operator==(const QHstsPolicy &rhs) const;
+ bool isExpired() const;
+
+private:
+
+ QScopedPointer<QHstsPolicyPrivate> d;
+};
+
+QT_END_NAMESPACE
+
+#endif // QHSTSPOLICY_H
diff --git a/src/network/access/qnetworkaccessmanager.cpp b/src/network/access/qnetworkaccessmanager.cpp
index 7aa8e61d26..19e9ecc265 100644
--- a/src/network/access/qnetworkaccessmanager.cpp
+++ b/src/network/access/qnetworkaccessmanager.cpp
@@ -45,6 +45,8 @@
#include "qnetworkcookie.h"
#include "qnetworkcookiejar.h"
#include "qabstractnetworkcache.h"
+#include "qhstspolicy.h"
+#include "qhsts_p.h"
#include "QtNetwork/qnetworksession.h"
#include "QtNetwork/private/qsharednetworksession_p.h"
@@ -742,6 +744,45 @@ bool QNetworkAccessManager::strictTransportSecurityEnabled() const
}
/*!
+ \since 5.9
+
+ Adds HTTP Strict Transport Security policies into HSTS cache.
+
+ \note An expired policy will remove a known host from the cache, if previously
+ present.
+
+ \note While processing HTTP responses, QNetworkAccessManager can also update
+ the HSTS cache, removing or updating exitsting policies or introducing new
+ known hosts. The current implementation thus is server-driven, client code
+ can provide QNetworkAccessManager with previously known or discovered
+ policies, but this information can be overridden by "Strict-Transport-Security"
+ response headers.
+
+ \sa addStrictTransportSecurityHosts(), QHstsPolicy
+*/
+
+void QNetworkAccessManager::addStrictTransportSecurityHosts(const QList<QHstsPolicy> &knownHosts)
+{
+ Q_D(QNetworkAccessManager);
+ d->stsCache.updateFromPolicies(knownHosts);
+}
+
+/*!
+ \since 5.9
+
+ Returns the list of HTTP Strict Transport Security policies. This list can
+ differ from what was initially set via addStrictTransportSecurityHosts() if
+ HSTS cache was updated from a "Strict-Transport-Security" response header.
+
+ \sa addStrictTransportSecurityHosts(), QHstsPolicy
+*/
+QList<QHstsPolicy> QNetworkAccessManager::strictTransportSecurityHosts() const
+{
+ Q_D(const QNetworkAccessManager);
+ return d->stsCache.policies();
+}
+
+/*!
Posts a request to obtain the network headers for \a request
and returns a new QNetworkReply object which will contain such headers.
diff --git a/src/network/access/qnetworkaccessmanager.h b/src/network/access/qnetworkaccessmanager.h
index 143407fb25..52769627f3 100644
--- a/src/network/access/qnetworkaccessmanager.h
+++ b/src/network/access/qnetworkaccessmanager.h
@@ -61,6 +61,7 @@ class QNetworkReply;
class QNetworkProxy;
class QNetworkProxyFactory;
class QSslError;
+class QHstsPolicy;
#ifndef QT_NO_BEARERMANAGEMENT
class QNetworkConfiguration;
#endif
@@ -123,6 +124,8 @@ public:
void enableStrictTransportSecurity();
void disableStrictTransportSecurity();
bool strictTransportSecurityEnabled() const;
+ void addStrictTransportSecurityHosts(const QList<QHstsPolicy> &knownHosts);
+ QList<QHstsPolicy> strictTransportSecurityHosts() const;
QNetworkReply *head(const QNetworkRequest &request);
QNetworkReply *get(const QNetworkRequest &request);
diff --git a/src/network/access/qnetworkdiskcache.cpp b/src/network/access/qnetworkdiskcache.cpp
index ce3b773c64..d72791c1f0 100644
--- a/src/network/access/qnetworkdiskcache.cpp
+++ b/src/network/access/qnetworkdiskcache.cpp
@@ -606,7 +606,7 @@ QString QNetworkDiskCachePrivate::uniqueFileName(const QUrl &url)
QCryptographicHash hash(QCryptographicHash::Sha1);
hash.addData(cleanUrl.toEncoded());
// convert sha1 to base36 form and return first 8 bytes for use as string
- QByteArray id = QByteArray::number(*(qlonglong*)hash.result().data(), 36).left(8);
+ const QByteArray id = QByteArray::number(*(qlonglong*)hash.result().constData(), 36).left(8);
// generates <one-char subdir>/<8-char filname.d>
uint code = (uint)id.at(id.length()-1) % 16;
QString pathFragment = QString::number(code, 16) + QLatin1Char('/')
diff --git a/src/network/bearer/qnetworkconfiguration.cpp b/src/network/bearer/qnetworkconfiguration.cpp
index d2feffb316..f1619ab7c0 100644
--- a/src/network/bearer/qnetworkconfiguration.cpp
+++ b/src/network/bearer/qnetworkconfiguration.cpp
@@ -343,7 +343,7 @@ int QNetworkConfiguration::connectTimeout() const
/*!
\since 5.9
- Sets the connect timeout of this configuration.
+ Sets the connect timeout of this configuration to \a timeout.
This allows control of the timeout used by \c QAbstractSocket
to establish a connection.
diff --git a/src/network/kernel/qhostinfo.cpp b/src/network/kernel/qhostinfo.cpp
index 88df65dbcb..193c990d8c 100644
--- a/src/network/kernel/qhostinfo.cpp
+++ b/src/network/kernel/qhostinfo.cpp
@@ -95,6 +95,38 @@ std::pair<OutputIt1, OutputIt2> separate_if(InputIt first, InputIt last, OutputI
}
return std::make_pair(dest1, dest2);
}
+
+int get_signal_index()
+{
+ static auto senderMetaObject = &QHostInfoResult::staticMetaObject;
+ static auto signal = &QHostInfoResult::resultsReady;
+ int signal_index = -1;
+ void *args[] = { &signal_index, &signal };
+ senderMetaObject->static_metacall(QMetaObject::IndexOfMethod, 0, args);
+ return signal_index + QMetaObjectPrivate::signalOffset(senderMetaObject);
+}
+
+void emit_results_ready(const QHostInfo &hostInfo, const QObject *receiver,
+ QtPrivate::QSlotObjectBase *slotObj)
+{
+ static const int signal_index = get_signal_index();
+ auto result = new QHostInfoResult(receiver, slotObj);
+ Q_CHECK_PTR(result);
+ const int nargs = 2;
+ auto types = reinterpret_cast<int *>(malloc(nargs * sizeof(int)));
+ Q_CHECK_PTR(types);
+ types[0] = QMetaType::type("void");
+ types[1] = QMetaType::type("QHostInfo");
+ auto args = reinterpret_cast<void **>(malloc(nargs * sizeof(void *)));
+ Q_CHECK_PTR(args);
+ args[0] = 0;
+ args[1] = QMetaType::create(types[1], &hostInfo);
+ Q_CHECK_PTR(args[1]);
+ auto metaCallEvent = new QMetaCallEvent(slotObj, nullptr, signal_index, nargs, types, args);
+ Q_CHECK_PTR(metaCallEvent);
+ qApp->postEvent(result, metaCallEvent);
+}
+
}
/*!
@@ -243,6 +275,67 @@ int QHostInfo::lookupHost(const QString &name, QObject *receiver,
}
/*!
+ \fn int QHostInfo::lookupHost(const QString &name, const QObject *receiver, PointerToMemberFunction function)
+
+ \since 5.9
+
+ \overload
+
+ Looks up the IP address(es) associated with host name \a name, and
+ returns an ID for the lookup. When the result of the lookup is
+ ready, the slot or signal \a function in \a receiver is called with
+ a QHostInfo argument. The QHostInfo object can then be inspected
+ to get the results of the lookup.
+
+ \note There is no guarantee on the order the signals will be emitted
+ if you start multiple requests with lookupHost().
+
+ \sa abortHostLookup(), addresses(), error(), fromName()
+*/
+
+/*!
+ \fn int QHostInfo::lookupHost(const QString &name, Functor functor)
+
+ \since 5.9
+
+ \overload
+
+ Looks up the IP address(es) associated with host name \a name, and
+ returns an ID for the lookup. When the result of the lookup is
+ ready, the \a functor is called with a QHostInfo argument. The
+ QHostInfo object can then be inspected to get the results of the
+ lookup.
+ \note There is no guarantee on the order the signals will be emitted
+ if you start multiple requests with lookupHost().
+
+ \sa abortHostLookup(), addresses(), error(), fromName()
+*/
+
+/*!
+ \fn int QHostInfo::lookupHost(const QString &name, const QObject *context, Functor functor)
+
+ \since 5.9
+
+ \overload
+
+ Looks up the IP address(es) associated with host name \a name, and
+ returns an ID for the lookup. When the result of the lookup is
+ ready, the \a functor is called with a QHostInfo argument. The
+ QHostInfo object can then be inspected to get the results of the
+ lookup.
+
+ If \a context is destroyed before the lookup completes, the
+ \a functor will not be called. The \a functor will be run in the
+ thread of \a context. The context's thread must have a running Qt
+ event loop.
+
+ \note There is no guarantee on the order the signals will be emitted
+ if you start multiple requests with lookupHost().
+
+ \sa abortHostLookup(), addresses(), error(), fromName()
+*/
+
+/*!
Aborts the host lookup with the ID \a id, as returned by lookupHost().
\sa lookupHost(), lookupId()
@@ -487,11 +580,66 @@ QString QHostInfo::localHostName()
\sa hostName()
*/
+int QHostInfo::lookupHostImpl(const QString &name,
+ const QObject *receiver,
+ QtPrivate::QSlotObjectBase *slotObj)
+{
+#if defined QHOSTINFO_DEBUG
+ qDebug("QHostInfo::lookupHost(\"%s\", %p, %p)",
+ name.toLatin1().constData(), receiver, slotObj);
+#endif
+
+ if (!QAbstractEventDispatcher::instance(QThread::currentThread())) {
+ qWarning("QHostInfo::lookupHost() called with no event dispatcher");
+ return -1;
+ }
+
+ qRegisterMetaType<QHostInfo>();
+
+ int id = theIdCounter.fetchAndAddRelaxed(1); // generate unique ID
+
+ if (Q_UNLIKELY(name.isEmpty())) {
+ QHostInfo hostInfo(id);
+ hostInfo.setError(QHostInfo::HostNotFound);
+ hostInfo.setErrorString(QCoreApplication::translate("QHostInfo", "No host name given"));
+ emit_results_ready(hostInfo, receiver, slotObj);
+ return id;
+ }
+
+ QHostInfoLookupManager *manager = theHostInfoLookupManager();
+
+ if (Q_LIKELY(manager)) {
+ // the application is still alive
+ if (manager->cache.isEnabled()) {
+ // check cache first
+ bool valid = false;
+ QHostInfo info = manager->cache.get(name, &valid);
+ if (valid) {
+ info.setLookupId(id);
+ emit_results_ready(info, receiver, slotObj);
+ return id;
+ }
+ }
+
+ // cache is not enabled or it was not in the cache, do normal lookup
+ QHostInfoRunnable* runnable = new QHostInfoRunnable(name, id, receiver, slotObj);
+ manager->scheduleLookup(runnable);
+ }
+ return id;
+}
+
QHostInfoRunnable::QHostInfoRunnable(const QString &hn, int i) : toBeLookedUp(hn), id(i)
{
setAutoDelete(true);
}
+QHostInfoRunnable::QHostInfoRunnable(const QString &hn, int i, const QObject *receiver,
+ QtPrivate::QSlotObjectBase *slotObj) :
+ toBeLookedUp(hn), id(i), resultEmitter(receiver, slotObj)
+{
+ setAutoDelete(true);
+}
+
// the QHostInfoLookupManager will at some point call this via a QThreadPool
void QHostInfoRunnable::run()
{
diff --git a/src/network/kernel/qhostinfo.h b/src/network/kernel/qhostinfo.h
index 9b4a4853d9..4484d718bd 100644
--- a/src/network/kernel/qhostinfo.h
+++ b/src/network/kernel/qhostinfo.h
@@ -87,8 +87,71 @@ public:
static QString localHostName();
static QString localDomainName();
+#ifdef Q_QDOC
+ template<typename PointerToMemberFunction>
+ static int QHostInfo::lookupHost(const QString &name, const QObject *receiver,
+ PointerToMemberFunction function);
+ template<typename Functor>
+ static int QHostInfo::lookupHost(const QString &name, Functor functor);
+ template<typename Functor>
+ static int QHostInfo::lookupHost(const QString &name, const QObject *context, Functor functor);
+#else
+ // lookupHost to a QObject slot
+ template <typename Func>
+ static inline int lookupHost(const QString &name,
+ const typename QtPrivate::FunctionPointer<Func>::Object *receiver,
+ Func slot)
+ {
+ typedef QtPrivate::FunctionPointer<Func> SlotType;
+
+ typedef QtPrivate::FunctionPointer<void (*)(QHostInfo)> SignalType;
+ Q_STATIC_ASSERT_X(int(SignalType::ArgumentCount) >= int(SlotType::ArgumentCount),
+ "The slot requires more arguments than the signal provides.");
+ Q_STATIC_ASSERT_X((QtPrivate::CheckCompatibleArguments<typename SignalType::Arguments,
+ typename SlotType::Arguments>::value),
+ "Signal and slot arguments are not compatible.");
+ Q_STATIC_ASSERT_X((QtPrivate::AreArgumentsCompatible<typename SlotType::ReturnType,
+ typename SignalType::ReturnType>::value),
+ "Return type of the slot is not compatible "
+ "with the return type of the signal.");
+
+ auto slotObj = new QtPrivate::QSlotObject<Func, typename SlotType::Arguments, void>(slot);
+ return lookupHostImpl(name, receiver, slotObj);
+ }
+
+ // lookupHost to a callable (without context)
+ template <typename Func>
+ static inline typename std::enable_if<!QtPrivate::FunctionPointer<Func>::IsPointerToMemberFunction &&
+ !std::is_same<const char *, Func>::value, int>::type
+ lookupHost(const QString &name, Func slot)
+ {
+ return lookupHost(name, nullptr, slot);
+ }
+
+ // lookupHost to a functor or function pointer (with context)
+ template <typename Func1>
+ static inline typename std::enable_if<!QtPrivate::FunctionPointer<Func1>::IsPointerToMemberFunction &&
+ !std::is_same<const char*, Func1>::value, int>::type
+ lookupHost(const QString &name, QObject *context, Func1 slot)
+ {
+ typedef QtPrivate::FunctionPointer<Func1> SlotType;
+
+ Q_STATIC_ASSERT_X(int(SlotType::ArgumentCount) <= 1,
+ "The slot must not require more than one argument");
+
+ auto slotObj = new QtPrivate::QFunctorSlotObject<Func1, 1,
+ typename QtPrivate::List<QHostInfo>,
+ void>(slot);
+ return lookupHostImpl(name, context, slotObj);
+ }
+#endif // Q_QDOC
+
private:
QScopedPointer<QHostInfoPrivate> d;
+
+ static int lookupHostImpl(const QString &name,
+ const QObject *receiver,
+ QtPrivate::QSlotObjectBase *slotObj);
};
QT_END_NAMESPACE
diff --git a/src/network/kernel/qhostinfo_p.h b/src/network/kernel/qhostinfo_p.h
index ba342bf533..dd46818a19 100644
--- a/src/network/kernel/qhostinfo_p.h
+++ b/src/network/kernel/qhostinfo_p.h
@@ -54,6 +54,7 @@
#include <QtNetwork/private/qtnetworkglobal_p.h>
#include "QtCore/qcoreapplication.h"
#include "private/qcoreapplication_p.h"
+#include "private/qmetaobject_p.h"
#include "QtNetwork/qhostinfo.h"
#include "QtCore/qmutex.h"
#include "QtCore/qwaitcondition.h"
@@ -77,10 +78,47 @@ QT_BEGIN_NAMESPACE
class QHostInfoResult : public QObject
{
Q_OBJECT
+
+ QPointer<const QObject> receiver = nullptr;
+ QtPrivate::QSlotObjectBase *slotObj = nullptr;
+
+public:
+ QHostInfoResult() = default;
+ QHostInfoResult(const QObject *receiver, QtPrivate::QSlotObjectBase *slotObj) :
+ receiver(receiver),
+ slotObj(slotObj)
+ {
+ connect(QCoreApplication::instance(), &QCoreApplication::aboutToQuit, this,
+ &QObject::deleteLater);
+ if (slotObj && receiver)
+ moveToThread(receiver->thread());
+ }
+
public Q_SLOTS:
inline void emitResultsReady(const QHostInfo &info)
{
- emit resultsReady(info);
+ if (slotObj) {
+ QHostInfo copy = info;
+ void *args[2] = { 0, reinterpret_cast<void *>(&copy) };
+ slotObj->call(const_cast<QObject*>(receiver.data()), args);
+ slotObj->destroyIfLastRef();
+ } else {
+ emit resultsReady(info);
+ }
+ }
+
+protected:
+ bool event(QEvent *event)
+ {
+ if (event->type() == QEvent::MetaCall) {
+ auto metaCallEvent = static_cast<QMetaCallEvent *>(event);
+ auto args = metaCallEvent->args();
+ auto hostInfo = reinterpret_cast<QHostInfo *>(args[1]);
+ emitResultsReady(*hostInfo);
+ deleteLater();
+ return true;
+ }
+ return QObject::event(event);
}
Q_SIGNALS:
@@ -154,6 +192,8 @@ class QHostInfoRunnable : public QRunnable
{
public:
QHostInfoRunnable(const QString &hn, int i);
+ QHostInfoRunnable(const QString &hn, int i, const QObject *receiver,
+ QtPrivate::QSlotObjectBase *slotObj);
void run() Q_DECL_OVERRIDE;
QString toBeLookedUp;
diff --git a/src/network/kernel/qnetworkproxy.cpp b/src/network/kernel/qnetworkproxy.cpp
index 0be8a7f79e..11e8fa6264 100644
--- a/src/network/kernel/qnetworkproxy.cpp
+++ b/src/network/kernel/qnetworkproxy.cpp
@@ -1636,10 +1636,6 @@ QList<QNetworkProxy> QNetworkProxyFactory::proxyForQuery(const QNetworkProxyQuer
}
#ifndef QT_NO_DEBUG_STREAM
-/*!
- \since 5.0
- Outputs a QNetworkProxy details to a debug stream
-*/
QDebug operator<<(QDebug debug, const QNetworkProxy &proxy)
{
QDebugStateSaver saver(debug);
@@ -1688,6 +1684,21 @@ QDebug operator<<(QDebug debug, const QNetworkProxy &proxy)
debug << '[' << scaps.join(QLatin1Char(' ')) << ']';
return debug;
}
+
+QDebug operator<<(QDebug debug, const QNetworkProxyQuery &proxyQuery)
+{
+ QDebugStateSaver saver(debug);
+ debug.resetFormat().nospace()
+ << "ProxyQuery("
+ << "type: " << proxyQuery.queryType()
+ << ", protocol: " << proxyQuery.protocolTag()
+ << ", peerPort: " << proxyQuery.peerPort()
+ << ", peerHostName: " << proxyQuery.peerHostName()
+ << ", localPort: " << proxyQuery.localPort()
+ << ", url: " << proxyQuery.url()
+ << ')';
+ return debug;
+}
#endif
QT_END_NAMESPACE
diff --git a/src/network/kernel/qnetworkproxy.h b/src/network/kernel/qnetworkproxy.h
index 8fcb7e33cf..8699c313e9 100644
--- a/src/network/kernel/qnetworkproxy.h
+++ b/src/network/kernel/qnetworkproxy.h
@@ -56,6 +56,8 @@ class QNetworkConfiguration;
class QNetworkProxyQueryPrivate;
class Q_NETWORK_EXPORT QNetworkProxyQuery
{
+ Q_GADGET
+
public:
enum QueryType {
TcpSocket,
@@ -65,6 +67,7 @@ public:
UrlRequest,
SctpServer
};
+ Q_ENUM(QueryType)
QNetworkProxyQuery();
explicit QNetworkProxyQuery(const QUrl &requestUrl, QueryType queryType = UrlRequest);
@@ -222,6 +225,7 @@ public:
#ifndef QT_NO_DEBUG_STREAM
Q_NETWORK_EXPORT QDebug operator<<(QDebug debug, const QNetworkProxy &proxy);
+Q_NETWORK_EXPORT QDebug operator<<(QDebug debug, const QNetworkProxyQuery &proxyQuery);
#endif
QT_END_NAMESPACE
diff --git a/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm b/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm
index 1e29b12ec4..6466db59ce 100644
--- a/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm
+++ b/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm
@@ -708,71 +708,71 @@ static CTFontUIFontType fontTypeFromTheme(QPlatformTheme::Font f)
{
switch (f) {
case QPlatformTheme::SystemFont:
- return kCTFontSystemFontType;
+ return kCTFontUIFontSystem;
case QPlatformTheme::MenuFont:
case QPlatformTheme::MenuBarFont:
case QPlatformTheme::MenuItemFont:
- return kCTFontMenuItemFontType;
+ return kCTFontUIFontMenuItem;
case QPlatformTheme::MessageBoxFont:
- return kCTFontEmphasizedSystemFontType;
+ return kCTFontUIFontEmphasizedSystem;
case QPlatformTheme::LabelFont:
- return kCTFontSystemFontType;
+ return kCTFontUIFontSystem;
case QPlatformTheme::TipLabelFont:
return kCTFontToolTipFontType;
case QPlatformTheme::StatusBarFont:
- return kCTFontSystemFontType;
+ return kCTFontUIFontSystem;
case QPlatformTheme::TitleBarFont:
- return kCTFontWindowTitleFontType;
+ return kCTFontUIFontWindowTitle;
case QPlatformTheme::MdiSubWindowTitleFont:
case QPlatformTheme::DockWidgetTitleFont:
- return kCTFontSystemFontType;
+ return kCTFontUIFontSystem;
case QPlatformTheme::PushButtonFont:
- return kCTFontPushButtonFontType;
+ return kCTFontUIFontPushButton;
case QPlatformTheme::CheckBoxFont:
case QPlatformTheme::RadioButtonFont:
- return kCTFontSystemFontType;
+ return kCTFontUIFontSystem;
case QPlatformTheme::ToolButtonFont:
- return kCTFontSmallToolbarFontType;
+ return kCTFontUIFontSmallToolbar;
case QPlatformTheme::ItemViewFont:
- return kCTFontSystemFontType;
+ return kCTFontUIFontSystem;
case QPlatformTheme::ListViewFont:
- return kCTFontViewsFontType;
+ return kCTFontUIFontViews;
case QPlatformTheme::HeaderViewFont:
- return kCTFontSmallSystemFontType;
+ return kCTFontUIFontSmallSystem;
case QPlatformTheme::ListBoxFont:
- return kCTFontViewsFontType;
+ return kCTFontUIFontViews;
case QPlatformTheme::ComboMenuItemFont:
- return kCTFontSystemFontType;
+ return kCTFontUIFontSystem;
case QPlatformTheme::ComboLineEditFont:
- return kCTFontViewsFontType;
+ return kCTFontUIFontViews;
case QPlatformTheme::SmallFont:
- return kCTFontSmallSystemFontType;
+ return kCTFontUIFontSmallSystem;
case QPlatformTheme::MiniFont:
- return kCTFontMiniSystemFontType;
+ return kCTFontUIFontMiniSystem;
case QPlatformTheme::FixedFont:
- return kCTFontUserFixedPitchFontType;
+ return kCTFontUIFontUserFixedPitch;
default:
- return kCTFontSystemFontType;
+ return kCTFontUIFontSystem;
}
}
@@ -848,7 +848,7 @@ QFont *QCoreTextFontDatabase::themeFont(QPlatformTheme::Font f) const
QFont QCoreTextFontDatabase::defaultFont() const
{
if (defaultFontName.isEmpty()) {
- QCFType<CTFontRef> font = CTFontCreateUIFontForLanguage(kCTFontSystemFontType, 12.0, NULL);
+ QCFType<CTFontRef> font = CTFontCreateUIFontForLanguage(kCTFontUIFontSystem, 12.0, NULL);
defaultFontName = (QString) QCFString(CTFontCopyFullName(font));
}
diff --git a/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm b/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm
index 7a06d5f1c9..c8ae342f16 100644
--- a/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm
+++ b/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm
@@ -141,7 +141,7 @@ static void loadAdvancesForGlyphs(CTFontRef ctfont,
{
Q_UNUSED(flags);
QVarLengthArray<CGSize> advances(len);
- CTFontGetAdvancesForGlyphs(ctfont, kCTFontHorizontalOrientation, cgGlyphs.data(), advances.data(), len);
+ CTFontGetAdvancesForGlyphs(ctfont, kCTFontOrientationHorizontal, cgGlyphs.data(), advances.data(), len);
for (int i = 0; i < len; ++i) {
if (glyphs->glyphs[i] & 0xff000000)
@@ -320,7 +320,7 @@ bool QCoreTextFontEngine::stringToCMap(const QChar *str, int len, QGlyphLayout *
return true;
QVarLengthArray<CGSize> advances(glyph_pos);
- CTFontGetAdvancesForGlyphs(ctfont, kCTFontHorizontalOrientation, cgGlyphs.data(), advances.data(), glyph_pos);
+ CTFontGetAdvancesForGlyphs(ctfont, kCTFontOrientationHorizontal, cgGlyphs.data(), advances.data(), glyph_pos);
for (int i = 0; i < glyph_pos; ++i) {
if (glyphs->glyphs[i] & 0xff000000)
@@ -351,7 +351,7 @@ glyph_metrics_t QCoreTextFontEngine::boundingBox(glyph_t glyph)
{
glyph_metrics_t ret;
CGGlyph g = glyph;
- CGRect rect = CTFontGetBoundingRectsForGlyphs(ctfont, kCTFontHorizontalOrientation, &g, 0, 1);
+ CGRect rect = CTFontGetBoundingRectsForGlyphs(ctfont, kCTFontOrientationHorizontal, &g, 0, 1);
if (synthesisFlags & QFontEngine::SynthesizedItalic) {
rect.size.width += rect.size.height * SYNTHETIC_ITALIC_SKEW;
}
@@ -360,7 +360,7 @@ glyph_metrics_t QCoreTextFontEngine::boundingBox(glyph_t glyph)
ret.x = QFixed::fromReal(rect.origin.x);
ret.y = -QFixed::fromReal(rect.origin.y) - ret.height;
CGSize advances[1];
- CTFontGetAdvancesForGlyphs(ctfont, kCTFontHorizontalOrientation, &g, advances, 1);
+ CTFontGetAdvancesForGlyphs(ctfont, kCTFontOrientationHorizontal, &g, advances, 1);
ret.xoff = QFixed::fromReal(advances[0].width);
ret.yoff = QFixed::fromReal(advances[0].height);
@@ -602,6 +602,11 @@ glyph_metrics_t QCoreTextFontEngine::alphaMapBoundingBox(glyph_t glyph, QFixed s
return br;
}
+bool QCoreTextFontEngine::expectsGammaCorrectedBlending() const
+{
+ // Only works well when font-smoothing is enabled
+ return (glyphFormat == Format_A32) && !(fontDef.styleStrategy & (QFont::NoAntialias | QFont::NoSubpixelAntialias));
+}
QImage QCoreTextFontEngine::imageForGlyph(glyph_t glyph, QFixed subPixelPosition, bool aa, const QTransform &matrix)
{
diff --git a/src/platformsupport/fontdatabases/mac/qfontengine_coretext_p.h b/src/platformsupport/fontdatabases/mac/qfontengine_coretext_p.h
index d9ffbb5697..0074790e43 100644
--- a/src/platformsupport/fontdatabases/mac/qfontengine_coretext_p.h
+++ b/src/platformsupport/fontdatabases/mac/qfontengine_coretext_p.h
@@ -110,6 +110,7 @@ public:
void doKerning(QGlyphLayout *g, ShaperFlags flags) const Q_DECL_OVERRIDE;
bool supportsTransformation(const QTransform &transform) const Q_DECL_OVERRIDE;
+ bool expectsGammaCorrectedBlending() const Q_DECL_OVERRIDE;
QFontEngine *cloneWithSize(qreal pixelSize) const Q_DECL_OVERRIDE;
Qt::HANDLE handle() const Q_DECL_OVERRIDE;
diff --git a/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase.cpp b/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase.cpp
index ab1fc9d647..f3d56eee6c 100644
--- a/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase.cpp
+++ b/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase.cpp
@@ -1216,8 +1216,6 @@ QWindowsFontEngineDataPtr sharedFontData()
}
#endif // QT_NO_THREAD
-extern Q_GUI_EXPORT bool qt_needs_a8_gamma_correction;
-
QWindowsFontDatabase::QWindowsFontDatabase()
{
// Properties accessed by QWin32PrintEngine (Qt Print Support)
@@ -1231,7 +1229,6 @@ QWindowsFontDatabase::QWindowsFontDatabase()
qCDebug(lcQpaFonts) << __FUNCTION__ << "Clear type: "
<< data->clearTypeEnabled << "gamma: " << data->fontSmoothingGamma;
}
- qt_needs_a8_gamma_correction = true;
}
QWindowsFontDatabase::~QWindowsFontDatabase()
diff --git a/src/platformsupport/linuxaccessibility/atspiadaptor.cpp b/src/platformsupport/linuxaccessibility/atspiadaptor.cpp
index 70c4aa563c..6561e95a0d 100644
--- a/src/platformsupport/linuxaccessibility/atspiadaptor.cpp
+++ b/src/platformsupport/linuxaccessibility/atspiadaptor.cpp
@@ -1398,7 +1398,7 @@ bool AtSpiAdaptor::accessibleInterface(QAccessibleInterface *interface, const QS
sendReply(connection, message, QVariant::fromValue(
QDBusVariant(QVariant::fromValue(QSpiObjectReference(connection, QDBusObjectPath(path))))));
} else if (function == QLatin1String("GetChildAtIndex")) {
- int index = message.arguments().first().toInt();
+ const int index = message.arguments().at(0).toInt();
if (index < 0) {
sendReply(connection, message, QVariant::fromValue(
QSpiObjectReference(connection, QDBusObjectPath(ATSPI_DBUS_PATH_NULL))));
diff --git a/src/plugins/bearer/corewlan/qcorewlanengine.mm b/src/plugins/bearer/corewlan/qcorewlanengine.mm
index 7cf9365513..341d3bccf2 100644
--- a/src/plugins/bearer/corewlan/qcorewlanengine.mm
+++ b/src/plugins/bearer/corewlan/qcorewlanengine.mm
@@ -61,14 +61,14 @@ extern "C" { // Otherwise it won't find CWKeychain* symbols at link time
#include <net/if.h>
#include <ifaddrs.h>
-@interface QT_MANGLE_NAMESPACE(QNSListener) : NSObject
+@interface QT_MANGLE_NAMESPACE(QNSListener) : NSObject <CWEventDelegate>
{
NSNotificationCenter *notificationCenter;
- CWInterface *currentInterface;
+ CWWiFiClient *client;
QCoreWlanEngine *engine;
NSLock *locker;
}
-- (void)notificationHandler:(NSNotification *)notification;
+- (void)powerStateDidChangeForWiFiInterfaceWithName:(NSString *)interfaceName;
- (void)remove;
- (void)setEngine:(QCoreWlanEngine *)coreEngine;
- (QCoreWlanEngine *)engine;
@@ -85,8 +85,9 @@ extern "C" { // Otherwise it won't find CWKeychain* symbols at link time
[locker lock];
QMacAutoReleasePool pool;
notificationCenter = [NSNotificationCenter defaultCenter];
- currentInterface = [CWInterface interface];
- [notificationCenter addObserver:self selector:@selector(notificationHandler:) name:CWPowerDidChangeNotification object:nil];
+ client = [CWWiFiClient sharedWiFiClient];
+ client.delegate = self;
+ [client startMonitoringEventWithType:CWEventTypePowerDidChange error:nil];
[locker unlock];
return self;
}
@@ -95,6 +96,7 @@ static QT_MANGLE_NAMESPACE(QNSListener) *listener = 0;
-(void)dealloc
{
+ client.delegate = nil;
listener = nil;
[super dealloc];
}
@@ -115,13 +117,13 @@ static QT_MANGLE_NAMESPACE(QNSListener) *listener = 0;
-(void)remove
{
[locker lock];
- [notificationCenter removeObserver:self];
+ [client stopMonitoringAllEventsAndReturnError:nil];
[locker unlock];
}
-- (void)notificationHandler:(NSNotification *)notification
+- (void)powerStateDidChangeForWiFiInterfaceWithName:(NSString *)interfaceName
{
- Q_UNUSED(notification);
+ Q_UNUSED(interfaceName);
engine->requestUpdate();
}
@end
@@ -162,7 +164,8 @@ void QScanThread::run()
QMacAutoReleasePool pool;
QStringList found;
mutex.lock();
- CWInterface *currentInterface = [CWInterface interfaceWithName:interfaceName.toNSString()];
+ CWInterface *currentInterface = [[CWWiFiClient sharedWiFiClient]
+ interfaceWithName:interfaceName.toNSString()];
mutex.unlock();
const bool currentInterfaceServiceActive = currentInterface.serviceActive;
@@ -284,10 +287,10 @@ void QScanThread::getUserConfigurations()
QMacAutoReleasePool pool;
userProfiles.clear();
- NSSet *wifiInterfaces = [CWInterface interfaceNames];
+ NSArray<NSString *> *wifiInterfaces = [CWWiFiClient interfaceNames];
for (NSString *ifName in wifiInterfaces) {
- CWInterface *wifiInterface = [CWInterface interfaceWithName:ifName];
+ CWInterface *wifiInterface = [[CWWiFiClient sharedWiFiClient] interfaceWithName:ifName];
NSString *nsInterfaceName = wifiInterface.ssid;
// add user configured system networks
@@ -442,7 +445,7 @@ void QCoreWlanEngine::initialize()
QMutexLocker locker(&mutex);
QMacAutoReleasePool pool;
- if ([[CWInterface interfaceNames] count] > 0 && !listener) {
+ if ([[CWWiFiClient interfaceNames] count] > 0 && !listener) {
listener = [[QT_MANGLE_NAMESPACE(QNSListener) alloc] init];
listener.engine = this;
hasWifi = true;
@@ -476,7 +479,7 @@ void QCoreWlanEngine::connectToId(const QString &id)
QString interfaceString = getInterfaceFromId(id);
CWInterface *wifiInterface =
- [CWInterface interfaceWithName:interfaceString.toNSString()];
+ [[CWWiFiClient sharedWiFiClient] interfaceWithName:interfaceString.toNSString()];
if (wifiInterface.powerOn) {
NSError *err = nil;
@@ -559,7 +562,7 @@ void QCoreWlanEngine::disconnectFromId(const QString &id)
QMacAutoReleasePool pool;
CWInterface *wifiInterface =
- [CWInterface interfaceWithName:interfaceString.toNSString()];
+ [[CWWiFiClient sharedWiFiClient] interfaceWithName:interfaceString.toNSString()];
disconnectedInterfaceString = interfaceString;
[wifiInterface disassociate];
@@ -573,8 +576,8 @@ void QCoreWlanEngine::checkDisconnect()
if (!disconnectedInterfaceString.isEmpty()) {
QMacAutoReleasePool pool;
- CWInterface *wifiInterface =
- [CWInterface interfaceWithName:disconnectedInterfaceString.toNSString()];
+ CWInterface *wifiInterface = [[CWWiFiClient sharedWiFiClient]
+ interfaceWithName:disconnectedInterfaceString.toNSString()];
const QString networkSsid = QString::fromNSString([wifiInterface ssid]);
if (!networkSsid.isEmpty()) {
@@ -599,7 +602,7 @@ void QCoreWlanEngine::doRequestUpdate()
QMacAutoReleasePool pool;
- NSSet *wifiInterfaces = [CWInterface interfaceNames];
+ NSArray<NSString *> *wifiInterfaces = [CWWiFiClient interfaceNames];
for (NSString *ifName in wifiInterfaces) {
scanThread->interfaceName = QString::fromNSString(ifName);
scanThread->start();
@@ -615,7 +618,8 @@ bool QCoreWlanEngine::isWifiReady(const QString &wifiDeviceName)
bool haswifi = false;
if(hasWifi) {
QMacAutoReleasePool pool;
- CWInterface *defaultInterface = [CWInterface interfaceWithName:wifiDeviceName.toNSString()];
+ CWInterface *defaultInterface = [[CWWiFiClient sharedWiFiClient]
+ interfaceWithName:wifiDeviceName.toNSString()];
if (defaultInterface.powerOn) {
haswifi = true;
}
diff --git a/src/plugins/platforms/cocoa/qcocoacolordialoghelper.mm b/src/plugins/platforms/cocoa/qcocoacolordialoghelper.mm
index e53c085e41..a8974c4de5 100644
--- a/src/plugins/platforms/cocoa/qcocoacolordialoghelper.mm
+++ b/src/plugins/platforms/cocoa/qcocoacolordialoghelper.mm
@@ -80,7 +80,7 @@ QT_NAMESPACE_ALIAS_OBJC_CLASS(QNSColorPanelDelegate);
mHelper = 0;
mStolenContentView = 0;
mPanelButtons = nil;
- mResultCode = NSCancelButton;
+ mResultCode = NSModalResponseCancel;
mDialogIsExecuting = false;
mResultSet = false;
mClosingDueToKnownButton = false;
@@ -168,7 +168,7 @@ QT_NAMESPACE_ALIAS_OBJC_CLASS(QNSColorPanelDelegate);
mClosingDueToKnownButton = true;
[mColorPanel close];
[self updateQtColor];
- [self finishOffWithCode:NSOKButton];
+ [self finishOffWithCode:NSModalResponseOK];
}
- (void)onCancelClicked
@@ -177,7 +177,7 @@ QT_NAMESPACE_ALIAS_OBJC_CLASS(QNSColorPanelDelegate);
mClosingDueToKnownButton = true;
[mColorPanel close];
mQtColor = QColor();
- [self finishOffWithCode:NSCancelButton];
+ [self finishOffWithCode:NSModalResponseCancel];
}
}
@@ -238,12 +238,12 @@ QT_NAMESPACE_ALIAS_OBJC_CLASS(QNSColorPanelDelegate);
[NSApp runModalForWindow:mColorPanel];
mDialogIsExecuting = false;
- return (mResultCode == NSOKButton);
+ return (mResultCode == NSModalResponseOK);
}
- (QPlatformDialogHelper::DialogCode)dialogResultCode
{
- return (mResultCode == NSOKButton) ? QPlatformDialogHelper::Accepted : QPlatformDialogHelper::Rejected;
+ return (mResultCode == NSModalResponseOK) ? QPlatformDialogHelper::Accepted : QPlatformDialogHelper::Rejected;
}
- (BOOL)windowShouldClose:(id)window
@@ -252,7 +252,7 @@ QT_NAMESPACE_ALIAS_OBJC_CLASS(QNSColorPanelDelegate);
if (!mPanelButtons)
[self updateQtColor];
if (mDialogIsExecuting) {
- [self finishOffWithCode:NSCancelButton];
+ [self finishOffWithCode:NSModalResponseCancel];
} else {
mResultSet = true;
if (mHelper)
@@ -278,7 +278,7 @@ QT_NAMESPACE_ALIAS_OBJC_CLASS(QNSColorPanelDelegate);
// This check will prevent any such recursion.
if (!mResultSet) {
mResultSet = true;
- if (mResultCode == NSCancelButton) {
+ if (mResultCode == NSModalResponseCancel) {
emit mHelper->reject();
} else {
emit mHelper->accept();
diff --git a/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm b/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm
index 72c7856c2d..d2f985ec87 100644
--- a/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm
+++ b/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm
@@ -401,7 +401,7 @@ bool QCocoaEventDispatcher::processEvents(QEventLoop::ProcessEventsFlags flags)
// [NSApp run], which is the normal code path for cocoa applications.
if (NSModalSession session = d->currentModalSession()) {
QBoolBlocker execGuard(d->currentExecIsNSAppRun, false);
- while ([NSApp runModalSession:session] == NSRunContinuesResponse && !d->interrupt)
+ while ([NSApp runModalSession:session] == NSModalResponseContinue && !d->interrupt)
qt_mac_waitForMoreEvents(NSModalPanelRunLoopMode);
if (!d->interrupt && session == d->currentModalSessionCached) {
@@ -435,7 +435,7 @@ bool QCocoaEventDispatcher::processEvents(QEventLoop::ProcessEventsFlags flags)
if (flags & QEventLoop::WaitForMoreEvents)
qt_mac_waitForMoreEvents(NSModalPanelRunLoopMode);
NSInteger status = [NSApp runModalSession:session];
- if (status != NSRunContinuesResponse && session == d->currentModalSessionCached) {
+ if (status != NSModalResponseContinue && session == d->currentModalSessionCached) {
// INVARIANT: Someone called [NSApp stopModal:] from outside the event
// dispatcher (e.g to stop a native dialog). But that call wrongly stopped
// 'session' as well. As a result, we need to restart all internal sessions:
diff --git a/src/plugins/platforms/cocoa/qcocoafontdialoghelper.mm b/src/plugins/platforms/cocoa/qcocoafontdialoghelper.mm
index 33dd4260a5..e4b796dcde 100644
--- a/src/plugins/platforms/cocoa/qcocoafontdialoghelper.mm
+++ b/src/plugins/platforms/cocoa/qcocoafontdialoghelper.mm
@@ -106,7 +106,7 @@ QT_NAMESPACE_ALIAS_OBJC_CLASS(QNSFontPanelDelegate);
mHelper = 0;
mStolenContentView = 0;
mPanelButtons = 0;
- mResultCode = NSCancelButton;
+ mResultCode = NSModalResponseCancel;
mDialogIsExecuting = false;
mResultSet = false;
@@ -171,7 +171,7 @@ QT_NAMESPACE_ALIAS_OBJC_CLASS(QNSFontPanelDelegate);
- (void)onOkClicked
{
[mFontPanel close];
- [self finishOffWithCode:NSOKButton];
+ [self finishOffWithCode:NSModalResponseOK];
}
- (void)onCancelClicked
@@ -179,7 +179,7 @@ QT_NAMESPACE_ALIAS_OBJC_CLASS(QNSFontPanelDelegate);
if (mPanelButtons) {
[mFontPanel close];
mQtFont = QFont();
- [self finishOffWithCode:NSCancelButton];
+ [self finishOffWithCode:NSModalResponseCancel];
}
}
@@ -224,12 +224,12 @@ QT_NAMESPACE_ALIAS_OBJC_CLASS(QNSFontPanelDelegate);
[NSApp runModalForWindow:mFontPanel];
mDialogIsExecuting = false;
- return (mResultCode == NSOKButton);
+ return (mResultCode == NSModalResponseOK);
}
- (QPlatformDialogHelper::DialogCode)dialogResultCode
{
- return (mResultCode == NSOKButton) ? QPlatformDialogHelper::Accepted : QPlatformDialogHelper::Rejected;
+ return (mResultCode == NSModalResponseOK) ? QPlatformDialogHelper::Accepted : QPlatformDialogHelper::Rejected;
}
- (BOOL)windowShouldClose:(id)window
@@ -238,7 +238,7 @@ QT_NAMESPACE_ALIAS_OBJC_CLASS(QNSFontPanelDelegate);
if (!mPanelButtons)
[self updateQtFont];
if (mDialogIsExecuting) {
- [self finishOffWithCode:NSCancelButton];
+ [self finishOffWithCode:NSModalResponseCancel];
} else {
mResultSet = true;
if (mHelper)
@@ -264,7 +264,7 @@ QT_NAMESPACE_ALIAS_OBJC_CLASS(QNSFontPanelDelegate);
// This check will prevent any such recursion.
if (!mResultSet) {
mResultSet = true;
- if (mResultCode == NSCancelButton) {
+ if (mResultCode == NSModalResponseCancel) {
emit mHelper->reject();
} else {
emit mHelper->accept();
diff --git a/src/plugins/platforms/cocoa/qcocoanativeinterface.mm b/src/plugins/platforms/cocoa/qcocoanativeinterface.mm
index 972230349b..26ab07ffaf 100644
--- a/src/plugins/platforms/cocoa/qcocoanativeinterface.mm
+++ b/src/plugins/platforms/cocoa/qcocoanativeinterface.mm
@@ -172,11 +172,12 @@ void *QCocoaNativeInterface::NSPrintInfoForPrintEngine(QPrintEngine *printEngine
QPixmap QCocoaNativeInterface::defaultBackgroundPixmapForQWizard()
{
- QCFType<CFURLRef> url;
const int ExpectedImageWidth = 242;
const int ExpectedImageHeight = 414;
- if (LSFindApplicationForInfo(kLSUnknownCreator, CFSTR("com.apple.KeyboardSetupAssistant"),
- 0, 0, &url) == noErr) {
+ QCFType<CFArrayRef> urls = LSCopyApplicationURLsForBundleIdentifier(
+ CFSTR("com.apple.KeyboardSetupAssistant"), nullptr);
+ if (urls && CFArrayGetCount(urls) > 0) {
+ CFURLRef url = (CFURLRef)CFArrayGetValueAtIndex(urls, 0);
QCFType<CFBundleRef> bundle = CFBundleCreate(kCFAllocatorDefault, url);
if (bundle) {
url = CFBundleCopyResourceURL(bundle, CFSTR("Background"), CFSTR("png"), 0);
diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp
index 96027f8e0a..04db975360 100644
--- a/src/plugins/platforms/windows/qwindowswindow.cpp
+++ b/src/plugins/platforms/windows/qwindowswindow.cpp
@@ -1494,18 +1494,22 @@ void QWindowsWindow::handleResized(int wParam)
case SIZE_MAXHIDE: // Some other window affected.
case SIZE_MAXSHOW:
return;
- case SIZE_MINIMIZED:
- handleWindowStateChange(Qt::WindowMinimized);
+ case SIZE_MINIMIZED: // QTBUG-53577, prevent state change events during programmatic state change
+ if (!testFlag(WithinSetStyle))
+ handleWindowStateChange(Qt::WindowMinimized);
return;
case SIZE_MAXIMIZED:
- handleWindowStateChange(Qt::WindowMaximized);
+ if (!testFlag(WithinSetStyle))
+ handleWindowStateChange(Qt::WindowMaximized);
handleGeometryChange();
break;
case SIZE_RESTORED:
- if (isFullScreen_sys())
- handleWindowStateChange(Qt::WindowFullScreen);
- else if (m_windowState != Qt::WindowNoState && !testFlag(MaximizeToFullScreen))
- handleWindowStateChange(Qt::WindowNoState);
+ if (!testFlag(WithinSetStyle)) {
+ if (isFullScreen_sys())
+ handleWindowStateChange(Qt::WindowFullScreen);
+ else if (m_windowState != Qt::WindowNoState && !testFlag(MaximizeToFullScreen))
+ handleWindowStateChange(Qt::WindowNoState);
+ }
handleGeometryChange();
break;
}
@@ -1513,9 +1517,6 @@ void QWindowsWindow::handleResized(int wParam)
void QWindowsWindow::handleGeometryChange()
{
- //Prevent recursive resizes for Windows CE
- if (testFlag(WithinSetStyle))
- return;
const QRect previousGeometry = m_data.geometry;
m_data.geometry = geometry_sys();
QPlatformWindow::setGeometry(m_data.geometry);
diff --git a/src/plugins/platforms/xcb/qxcbintegration.cpp b/src/plugins/platforms/xcb/qxcbintegration.cpp
index af9ffab8ae..47c85fce18 100644
--- a/src/plugins/platforms/xcb/qxcbintegration.cpp
+++ b/src/plugins/platforms/xcb/qxcbintegration.cpp
@@ -384,9 +384,6 @@ QVariant QXcbIntegration::styleHint(QPlatformIntegration::StyleHint hint) const
case QPlatformIntegration::PasswordMaskCharacter:
// TODO using various xcb, gnome or KDE settings
break; // Not implemented, use defaults
- case QPlatformIntegration::FontSmoothingGamma:
- // Match Qt 4.8 text rendering, and rendering of other X11 toolkits.
- return qreal(1.0);
case QPlatformIntegration::StartDragDistance: {
// The default (in QPlatformTheme::defaultThemeHint) is 10 pixels, but
// on a high-resolution screen it makes sense to increase it.
diff --git a/src/printsupport/dialogs/qpagesetupdialog_mac.mm b/src/printsupport/dialogs/qpagesetupdialog_mac.mm
index c29b911e35..581c0271f1 100644
--- a/src/printsupport/dialogs/qpagesetupdialog_mac.mm
+++ b/src/printsupport/dialogs/qpagesetupdialog_mac.mm
@@ -78,7 +78,7 @@ QT_USE_NAMESPACE
QPageSetupDialog *dialog = static_cast<QPageSetupDialog *>(contextInfo);
QPrinter *printer = dialog->printer();
- if (returnCode == NSOKButton) {
+ if (returnCode == NSModalResponseOK) {
PMPageFormat format = static_cast<PMPageFormat>([printInfo PMPageFormat]);
PMRect paperRect;
PMGetUnadjustedPaperRect(format, &paperRect);
@@ -89,7 +89,7 @@ QT_USE_NAMESPACE
printer->printEngine()->setProperty(QPrintEngine::PPK_Orientation, orientation == kPMLandscape ? QPrinter::Landscape : QPrinter::Portrait);
}
- dialog->done((returnCode == NSOKButton) ? QDialog::Accepted : QDialog::Rejected);
+ dialog->done((returnCode == NSModalResponseOK) ? QDialog::Accepted : QDialog::Rejected);
}
@end
diff --git a/src/printsupport/dialogs/qprintdialog_mac.mm b/src/printsupport/dialogs/qprintdialog_mac.mm
index c630ab634a..4595ed71ff 100644
--- a/src/printsupport/dialogs/qprintdialog_mac.mm
+++ b/src/printsupport/dialogs/qprintdialog_mac.mm
@@ -103,7 +103,7 @@ QT_USE_NAMESPACE
QPrintDialog *dialog = static_cast<QPrintDialog *>(contextInfo);
QPrinter *printer = dialog->printer();
- if (returnCode == NSOKButton) {
+ if (returnCode == NSModalResponseOK) {
PMPrintSession session = static_cast<PMPrintSession>([printInfo PMPrintSession]);
PMPrintSettings settings = static_cast<PMPrintSettings>([printInfo PMPrintSettings]);
@@ -192,7 +192,7 @@ QT_USE_NAMESPACE
printer->setPageSize(pageSize);
printer->setOrientation(orientation == kPMLandscape ? QPrinter::Landscape : QPrinter::Portrait);
- dialog->done((returnCode == NSOKButton) ? QDialog::Accepted : QDialog::Rejected);
+ dialog->done((returnCode == NSModalResponseOK) ? QDialog::Accepted : QDialog::Rejected);
}
@end
diff --git a/src/tools/uic/main.cpp b/src/tools/uic/main.cpp
index e2399cd1fd..fca604690e 100644
--- a/src/tools/uic/main.cpp
+++ b/src/tools/uic/main.cpp
@@ -115,7 +115,7 @@ int runUic(int argc, char *argv[])
QString inputFile;
if (!parser.positionalArguments().isEmpty())
- inputFile = parser.positionalArguments().first();
+ inputFile = parser.positionalArguments().at(0);
else // reading from stdin
driver.option().headerProtection = false;
diff --git a/src/widgets/kernel/qapplication.cpp b/src/widgets/kernel/qapplication.cpp
index c6d59907a0..008b2a0d77 100644
--- a/src/widgets/kernel/qapplication.cpp
+++ b/src/widgets/kernel/qapplication.cpp
@@ -408,7 +408,6 @@ QWidget *QApplicationPrivate::focus_widget = 0; // has keyboard input foc
QWidget *QApplicationPrivate::hidden_focus_widget = 0; // will get keyboard input focus after show()
QWidget *QApplicationPrivate::active_window = 0; // toplevel with keyboard focus
#ifndef QT_NO_WHEELEVENT
-int QApplicationPrivate::wheel_scroll_lines; // number of lines to scroll
QPointer<QWidget> QApplicationPrivate::wheel_widget;
#endif
bool qt_in_tab_key_event = false;
@@ -642,19 +641,12 @@ void QApplicationPrivate::initialize()
if (qEnvironmentVariableIntValue("QT_USE_NATIVE_WINDOWS") > 0)
QCoreApplication::setAttribute(Qt::AA_NativeWindows);
-#ifndef QT_NO_WHEELEVENT
- QApplicationPrivate::wheel_scroll_lines = 3;
-#endif
-
if (qt_is_gui_used)
initializeMultitouch();
if (QApplication::desktopSettingsAware())
if (const QPlatformTheme *theme = QGuiApplicationPrivate::platformTheme()) {
QApplicationPrivate::enabledAnimations = theme->themeHint(QPlatformTheme::UiEffects).toInt();
-#ifndef QT_NO_WHEELEVENT
- QApplicationPrivate::wheel_scroll_lines = theme->themeHint(QPlatformTheme::WheelScrollLines).toInt();
-#endif
}
is_app_running = true; // no longer starting up
@@ -4049,16 +4041,18 @@ int QApplication::keyboardInputInterval()
or \l{QAbstractItemView::ScrollPerPixel}{scroll one pixel}.
By default, this property has a value of 3.
+
+ \sa QStyleHints::wheelScrollLines()
*/
#ifndef QT_NO_WHEELEVENT
int QApplication::wheelScrollLines()
{
- return QApplicationPrivate::wheel_scroll_lines;
+ return styleHints()->wheelScrollLines();
}
void QApplication::setWheelScrollLines(int lines)
{
- QApplicationPrivate::wheel_scroll_lines = lines;
+ styleHints()->setWheelScrollLines(lines);
}
#endif
diff --git a/src/widgets/widgets/qcalendarwidget.cpp b/src/widgets/widgets/qcalendarwidget.cpp
index b0ded70c4a..da4850a816 100644
--- a/src/widgets/widgets/qcalendarwidget.cpp
+++ b/src/widgets/widgets/qcalendarwidget.cpp
@@ -765,7 +765,7 @@ bool QCalendarTextNavigator::eventFilter(QObject *o, QEvent *e)
if (m_widget) {
if (e->type() == QEvent::KeyPress || e->type() == QEvent::KeyRelease) {
QKeyEvent* ke = (QKeyEvent*)e;
- if ((ke->text().length() > 0 && ke->text()[0].isPrint()) || m_dateFrame) {
+ if ((ke->text().length() > 0 && ke->text().at(0).isPrint()) || m_dateFrame) {
if (ke->key() == Qt::Key_Return || ke->key() == Qt::Key_Enter || ke->key() == Qt::Key_Select) {
applyDate();
emit editingFinished();
diff --git a/src/widgets/widgets/qmenubar.cpp b/src/widgets/widgets/qmenubar.cpp
index 2a76f1e8a0..77ed7a4f78 100644
--- a/src/widgets/widgets/qmenubar.cpp
+++ b/src/widgets/widgets/qmenubar.cpp
@@ -1119,7 +1119,7 @@ void QMenuBar::keyPressEvent(QKeyEvent *e)
int clashCount = 0;
QAction *first = 0, *currentSelected = 0, *firstAfterCurrent = 0;
{
- QChar c = e->text()[0].toUpper();
+ const QChar c = e->text().at(0).toUpper();
for(int i = 0; i < d->actions.size(); ++i) {
if (d->actionRects.at(i).isNull())
continue;
diff --git a/src/widgets/widgets/qtabbar.cpp b/src/widgets/widgets/qtabbar.cpp
index 6e34198f67..ba67baeadb 100644
--- a/src/widgets/widgets/qtabbar.cpp
+++ b/src/widgets/widgets/qtabbar.cpp
@@ -177,8 +177,7 @@ void QTabBarPrivate::initBasicStyleOption(QStyleOptionTab *option, int tabIndex)
if (tab.textColor.isValid())
option->palette.setColor(q->foregroundRole(), tab.textColor);
#ifdef Q_OS_MACOS
- else if (isCurrent && !documentMode
- && (QSysInfo::MacintoshVersion < QSysInfo::MV_10_10 || q->isActiveWindow())) {
+ else if (isCurrent && !documentMode && q->isActiveWindow()) {
option->palette.setColor(QPalette::WindowText, Qt::white);
}
#endif