Merge remote-tracking branch 'origin/5.11' into dev

Conflicts:
	src/corelib/global/qconfig-bootstrapped.h
	src/plugins/platforms/xcb/qxcbbackingstore.cpp

Done-with: Gatis Paeglis <gatis.paeglis@qt.io>
Change-Id: I4af138ffb2f5306373244523768209e8873b2798
This commit is contained in:
Liang Qi 2018-08-16 13:34:53 +02:00
commit 8559bf934d
26 changed files with 379 additions and 96 deletions

View File

@ -996,9 +996,9 @@ defineTest(qtConfTest_compile) {
# add compiler flags, these are set for the target and should not be applied to host tests
!isEmpty(EXTRA_DEFINES): \
qmake_args += $$system_quote(DEFINES += $$val_escape(EXTRA_DEFINES))
!isEmpty(EXTRA_LIBDIR) \
!isEmpty(EXTRA_LIBDIR): \
qmake_args += $$system_quote(QMAKE_LIBDIR += $$val_escape(EXTRA_LIBDIR))
!isEmpty(EXTRA_FRAMEWORKPATH) \
!isEmpty(EXTRA_FRAMEWORKPATH): \
qmake_args += $$system_quote(QMAKE_FRAMEWORKPATH += $$val_escape(EXTRA_FRAMEWORKPATH))
!isEmpty(EXTRA_INCLUDEPATH): \
qmake_args += $$system_quote(INCLUDEPATH += $$val_escape(EXTRA_INCLUDEPATH))

View File

@ -557,6 +557,12 @@ void VCXProjectWriter::write(XmlOutput &xml, VCProjectSingleConfig &tool)
addFilters(tempProj, xmlFilter, "Deployment Files");
addFilters(tempProj, xmlFilter, "Distribution Files");
tempProj.ExtraCompilers.reserve(tool.ExtraCompilersFiles.size());
std::transform(tool.ExtraCompilersFiles.cbegin(), tool.ExtraCompilersFiles.cend(),
std::back_inserter(tempProj.ExtraCompilers),
[] (const VCFilter &filter) { return filter.Name; });
tempProj.ExtraCompilers.removeDuplicates();
for (int x = 0; x < tempProj.ExtraCompilers.count(); ++x)
addFilters(tempProj, xmlFilter, tempProj.ExtraCompilers.at(x));
@ -1977,6 +1983,15 @@ bool VCXProjectWriter::outputFileConfig(OutputFilterData *d, XmlOutput &xml, Xml
return fileAdded;
}
static bool isFileClCompatible(const QString &filePath)
{
auto filePathEndsWith = [&filePath] (const QString &ext) {
return filePath.endsWith(ext, Qt::CaseInsensitive);
};
return std::any_of(Option::cpp_ext.cbegin(), Option::cpp_ext.cend(), filePathEndsWith)
|| std::any_of(Option::c_ext.cbegin(), Option::c_ext.cend(), filePathEndsWith);
}
void VCXProjectWriter::outputFileConfig(XmlOutput &xml, XmlOutput &xmlFilter,
const QString &filePath, const QString &filterName)
{
@ -2000,7 +2015,7 @@ void VCXProjectWriter::outputFileConfig(XmlOutput &xml, XmlOutput &xmlFilter,
<< attrTagS("Filter", filterName);
xml << tag("ClInclude")
<< attrTag("Include", nativeFilePath);
} else if (filePath.endsWith(".cpp")) {
} else if (isFileClCompatible(filePath)) {
xmlFilter << tag("ClCompile")
<< attrTag("Include", nativeFilePath)
<< attrTagS("Filter", filterName);

View File

@ -6,6 +6,7 @@
"Description": "xkbcommon is a keymap compiler and support library which processes a reduced subset of keymaps as defined by the XKB specification.",
"Homepage": "http://xkbcommon.org/",
"Version": "0.4.1",
"License": "MIT Licenses (with no-advertisement clause)",
"LicenseId": "MIT",
"LicenseFile": "COPYING",

View File

@ -98,11 +98,19 @@
#define QT_NO_QOBJECT
#define QT_FEATURE_process -1
#define QT_FEATURE_regularexpression -1
#define QT_FEATURE_renameat2 -1
#ifdef __GLIBC_PREREQ
# define QT_FEATURE_renameat2 (__GLIBC_PREREQ(2, 28) ? 1 : -1)
#else
# define QT_FEATURE_renameat2 -1
#endif
#define QT_FEATURE_settings -1
#define QT_FEATURE_sharedmemory -1
#define QT_FEATURE_slog2 -1
#define QT_FEATURE_statx -1
#ifdef __GLIBC_PREREQ
# define QT_FEATURE_statx (__GLIBC_PREREQ(2, 28) ? 1 : -1)
#else
# define QT_FEATURE_statx -1
#endif
#define QT_FEATURE_syslog -1
#define QT_NO_SYSTEMLOCALE
#define QT_FEATURE_systemsemaphore -1

View File

@ -2212,10 +2212,19 @@ static bool readEtcFile(QUnixOSVersion &v, const char *filename,
return true;
}
static bool readEtcOsRelease(QUnixOSVersion &v)
static bool readOsRelease(QUnixOSVersion &v)
{
return readEtcFile(v, "/etc/os-release", QByteArrayLiteral("ID="),
QByteArrayLiteral("VERSION_ID="), QByteArrayLiteral("PRETTY_NAME="));
QByteArray id = QByteArrayLiteral("ID=");
QByteArray versionId = QByteArrayLiteral("VERSION_ID=");
QByteArray prettyName = QByteArrayLiteral("PRETTY_NAME=");
// man os-release(5) says:
// The file /etc/os-release takes precedence over /usr/lib/os-release.
// Applications should check for the former, and exclusively use its data
// if it exists, and only fall back to /usr/lib/os-release if it is
// missing.
return readEtcFile(v, "/etc/os-release", id, versionId, prettyName) ||
readEtcFile(v, "/usr/lib/os-release", id, versionId, prettyName);
}
static bool readEtcLsbRelease(QUnixOSVersion &v)
@ -2297,7 +2306,7 @@ static bool readEtcDebianVersion(QUnixOSVersion &v)
static bool findUnixOsVersion(QUnixOSVersion &v)
{
if (readEtcOsRelease(v))
if (readOsRelease(v))
return true;
if (readEtcLsbRelease(v))
return true;

View File

@ -91,7 +91,6 @@ extern "C" NSString *NSTemporaryDirectory();
# include <sys/syscall.h>
# include <sys/sendfile.h>
# include <linux/fs.h>
# include <linux/stat.h>
// in case linux/fs.h is too old and doesn't define it:
#ifndef FICLONE
@ -112,6 +111,7 @@ static int renameat2(int oldfd, const char *oldpath, int newfd, const char *newp
# endif
# if !QT_CONFIG(statx) && defined(SYS_statx)
# include <linux/stat.h>
static int statx(int dirfd, const char *pathname, int flag, unsigned mask, struct statx *statxbuf)
{ return syscall(SYS_statx, dirfd, pathname, flag, mask, statxbuf); }
# elif !QT_CONFIG(statx) && !defined(SYS_statx)

View File

@ -345,7 +345,6 @@ QEventDispatcherGlibPrivate::QEventDispatcherGlibPrivate(GMainContext *context)
sizeof(GIdleTimerSource)));
idleTimerSource->timerSource = timerSource;
g_source_set_can_recurse(&idleTimerSource->source, true);
g_source_set_priority(&idleTimerSource->source, G_PRIORITY_DEFAULT_IDLE);
g_source_attach(&idleTimerSource->source, mainContext);
}

View File

@ -1250,7 +1250,7 @@ bool QXmlStreamReaderPrivate::parse()
state_stack[tos] = 0;
return true;
} else if (act > 0) {
if (++tos == stack_size-1)
if (++tos >= stack_size-1)
reallocateStack();
Value &val = sym_stack[tos];

View File

@ -227,7 +227,7 @@ QTimeZonePrivate::Data QMacTimeZonePrivate::nextTransition(qint64 afterMSecsSinc
QTimeZonePrivate::Data QMacTimeZonePrivate::previousTransition(qint64 beforeMSecsSinceEpoch) const
{
// The native API only lets us search forward, so we need to find an early-enough start:
const NSTimeInterval lowerBound = std::numeric_limits<NSTimeInterval>::min();
const NSTimeInterval lowerBound = std::numeric_limits<NSTimeInterval>::lowest();
const qint64 endSecs = beforeMSecsSinceEpoch / 1000;
const int year = 366 * 24 * 3600; // a (long) year, in seconds
NSTimeInterval prevSecs = endSecs; // sentinel for later check

View File

@ -2053,7 +2053,7 @@ void QTextEngine::itemize() const
layoutData->string.detach();
string = reinterpret_cast<const ushort *>(layoutData->string.unicode());
uc = string + offset;
e = uc + length;
e = string + length;
*const_cast<ushort*>(uc) = 0x21B5; // visual line separator
}
break;

View File

@ -133,6 +133,8 @@ QByteArray QHttpNetworkRequest::uri(bool throughProxy) const
QUrl copy = d->url;
if (copy.path().isEmpty())
copy.setPath(QStringLiteral("/"));
else
format |= QUrl::NormalizePathSegments;
QByteArray uri = copy.toEncoded(format);
return uri;
}

View File

@ -3,12 +3,14 @@ TARGET = ibusplatforminputcontextplugin
QT += dbus gui-private
SOURCES += $$PWD/qibusplatforminputcontext.cpp \
$$PWD/qibusproxy.cpp \
$$PWD/qibusproxyportal.cpp \
$$PWD/qibusinputcontextproxy.cpp \
$$PWD/qibustypes.cpp \
$$PWD/main.cpp
HEADERS += $$PWD/qibusplatforminputcontext.h \
$$PWD/qibusproxy.h \
$$PWD/qibusproxyportal.h \
$$PWD/qibusinputcontextproxy.h \
$$PWD/qibustypes.h

View File

@ -0,0 +1,10 @@
<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
<node>
<interface name="org.freedesktop.IBus.Portal">
<method name="CreateInputContext">
<arg name="name" direction="in" type="s"/>
<arg name="context" direction="out" type="o"/>
</method>
</interface>
</node>

View File

@ -50,6 +50,7 @@
#include <qpa/qwindowsysteminterface.h>
#include "qibusproxy.h"
#include "qibusproxyportal.h"
#include "qibusinputcontextproxy.h"
#include "qibustypes.h"
@ -78,19 +79,23 @@ public:
{
delete context;
delete bus;
delete portalBus;
delete connection;
}
static QString getSocketPath();
static QDBusConnection *createConnection();
QDBusConnection *createConnection();
void initBus();
void createBusProxy();
QDBusConnection *connection;
QIBusProxy *bus;
QIBusProxyPortal *portalBus; // bus and portalBus are alternative.
QIBusInputContextProxy *context;
QDBusServiceWatcher serviceWatcher;
bool usePortal; // return value of shouldConnectIbusPortal
bool valid;
bool busConnected;
QString predit;
@ -103,20 +108,25 @@ public:
QIBusPlatformInputContext::QIBusPlatformInputContext ()
: d(new QIBusPlatformInputContextPrivate())
{
QString socketPath = QIBusPlatformInputContextPrivate::getSocketPath();
QFile file(socketPath);
if (file.open(QFile::ReadOnly)) {
if (!d->usePortal) {
QString socketPath = QIBusPlatformInputContextPrivate::getSocketPath();
QFile file(socketPath);
if (file.open(QFile::ReadOnly)) {
#ifndef QT_NO_FILESYSTEMWATCHER
// If KDE session save is used or restart ibus-daemon,
// the applications could run before ibus-daemon runs.
// We watch the getSocketPath() to get the launching ibus-daemon.
m_socketWatcher.addPath(socketPath);
connect(&m_socketWatcher, SIGNAL(fileChanged(QString)), this, SLOT(socketChanged(QString)));
qCDebug(qtQpaInputMethods) << "socketWatcher.addPath" << socketPath;
// If KDE session save is used or restart ibus-daemon,
// the applications could run before ibus-daemon runs.
// We watch the getSocketPath() to get the launching ibus-daemon.
m_socketWatcher.addPath(socketPath);
connect(&m_socketWatcher, SIGNAL(fileChanged(QString)), this, SLOT(socketChanged(QString)));
#endif
}
m_timer.setSingleShot(true);
connect(&m_timer, SIGNAL(timeout()), this, SLOT(connectToBus()));
}
m_timer.setSingleShot(true);
connect(&m_timer, SIGNAL(timeout()), this, SLOT(connectToBus()));
QObject::connect(&d->serviceWatcher, SIGNAL(serviceRegistered(QString)), this, SLOT(busRegistered(QString)));
QObject::connect(&d->serviceWatcher, SIGNAL(serviceUnregistered(QString)), this, SLOT(busUnregistered(QString)));
connectToContextSignals();
@ -507,6 +517,9 @@ void QIBusPlatformInputContext::filterEventFinished(QDBusPendingCallWatcher *cal
QLocale QIBusPlatformInputContext::locale() const
{
// d->locale is not updated when IBus portal is used
if (d->usePortal)
return QPlatformInputContext::locale();
return d->locale;
}
@ -527,6 +540,22 @@ void QIBusPlatformInputContext::socketChanged(const QString &str)
m_timer.start(100);
}
void QIBusPlatformInputContext::busRegistered(const QString &str)
{
qCDebug(qtQpaInputMethods) << "busRegistered";
Q_UNUSED (str);
if (d->usePortal) {
connectToBus();
}
}
void QIBusPlatformInputContext::busUnregistered(const QString &str)
{
qCDebug(qtQpaInputMethods) << "busUnregistered";
Q_UNUSED (str);
d->busConnected = false;
}
// When getSocketPath() is modified, the bus is not established yet
// so use m_timer.
void QIBusPlatformInputContext::connectToBus()
@ -536,7 +565,7 @@ void QIBusPlatformInputContext::connectToBus()
connectToContextSignals();
#ifndef QT_NO_FILESYSTEMWATCHER
if (m_socketWatcher.files().size() == 0)
if (!d->usePortal && m_socketWatcher.files().size() == 0)
m_socketWatcher.addPath(QIBusPlatformInputContextPrivate::getSocketPath());
#endif
}
@ -572,15 +601,34 @@ void QIBusPlatformInputContext::connectToContextSignals()
}
}
static inline bool checkRunningUnderFlatpak()
{
return !QStandardPaths::locate(QStandardPaths::RuntimeLocation, QLatin1String("flatpak-info")).isEmpty();
}
static bool shouldConnectIbusPortal()
{
// honor the same env as ibus-gtk
return (checkRunningUnderFlatpak() || !qgetenv("IBUS_USE_PORTAL").isNull());
}
QIBusPlatformInputContextPrivate::QIBusPlatformInputContextPrivate()
: connection(0),
bus(0),
portalBus(0),
context(0),
usePortal(shouldConnectIbusPortal()),
valid(false),
busConnected(false),
needsSurroundingText(false)
{
valid = !QStandardPaths::findExecutable(QString::fromLocal8Bit("ibus-daemon"), QStringList()).isEmpty();
if (usePortal) {
valid = true;
if (debug)
qDebug() << "use IBus portal";
} else {
valid = !QStandardPaths::findExecutable(QString::fromLocal8Bit("ibus-daemon"), QStringList()).isEmpty();
}
if (!valid)
return;
initBus();
@ -603,21 +651,40 @@ void QIBusPlatformInputContextPrivate::createBusProxy()
if (!connection || !connection->isConnected())
return;
bus = new QIBusProxy(QLatin1String("org.freedesktop.IBus"),
QLatin1String("/org/freedesktop/IBus"),
*connection);
if (!bus->isValid()) {
qWarning("QIBusPlatformInputContext: invalid bus.");
return;
const char* ibusService = usePortal ? "org.freedesktop.portal.IBus" : "org.freedesktop.IBus";
QDBusReply<QDBusObjectPath> ic;
if (usePortal) {
portalBus = new QIBusProxyPortal(QLatin1String(ibusService),
QLatin1String("/org/freedesktop/IBus"),
*connection);
if (!portalBus->isValid()) {
qWarning("QIBusPlatformInputContext: invalid portal bus.");
return;
}
ic = portalBus->CreateInputContext(QLatin1String("QIBusInputContext"));
} else {
bus = new QIBusProxy(QLatin1String(ibusService),
QLatin1String("/org/freedesktop/IBus"),
*connection);
if (!bus->isValid()) {
qWarning("QIBusPlatformInputContext: invalid bus.");
return;
}
ic = bus->CreateInputContext(QLatin1String("QIBusInputContext"));
}
QDBusReply<QDBusObjectPath> ic = bus->CreateInputContext(QLatin1String("QIBusInputContext"));
serviceWatcher.removeWatchedService(ibusService);
serviceWatcher.setConnection(*connection);
serviceWatcher.addWatchedService(ibusService);
if (!ic.isValid()) {
qWarning("QIBusPlatformInputContext: CreateInputContext failed.");
return;
}
context = new QIBusInputContextProxy(QLatin1String("org.freedesktop.IBus"), ic.value().path(), *connection);
context = new QIBusInputContextProxy(QLatin1String(ibusService), ic.value().path(), *connection);
if (!context->isValid()) {
qWarning("QIBusPlatformInputContext: invalid input context.");
@ -665,6 +732,8 @@ QString QIBusPlatformInputContextPrivate::getSocketPath()
QDBusConnection *QIBusPlatformInputContextPrivate::createConnection()
{
if (usePortal)
return new QDBusConnection(QDBusConnection::connectToBus(QDBusConnection::SessionBus, QLatin1String("QIBusProxy")));
QFile file(getSocketPath());
if (!file.open(QFile::ReadOnly))

View File

@ -108,6 +108,8 @@ public Q_SLOTS:
void showPreeditText();
void filterEventFinished(QDBusPendingCallWatcher *call);
void socketChanged(const QString &str);
void busRegistered(const QString &str);
void busUnregistered(const QString &str);
void connectToBus();
void globalEngineChanged(const QString &engine_name);

View File

@ -0,0 +1,26 @@
/*
* This file was generated by qdbusxml2cpp version 0.8
* Command line was: qdbusxml2cpp -N -p qibusproxyportal -c QIBusProxyPortal interfaces/org.freedesktop.IBus.Portal.xml
*
* qdbusxml2cpp is Copyright (C) 2017 The Qt Company Ltd.
*
* This is an auto-generated file.
* This file may have been hand-edited. Look for HAND-EDIT comments
* before re-generating it.
*/
#include "qibusproxyportal.h"
/*
* Implementation of interface class QIBusProxyPortal
*/
QIBusProxyPortal::QIBusProxyPortal(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent)
: QDBusAbstractInterface(service, path, staticInterfaceName(), connection, parent)
{
}
QIBusProxyPortal::~QIBusProxyPortal()
{
}

View File

@ -0,0 +1,49 @@
/*
* This file was generated by qdbusxml2cpp version 0.8
* Command line was: qdbusxml2cpp -N -p qibusproxyportal -c QIBusProxyPortal interfaces/org.freedesktop.IBus.Portal.xml
*
* qdbusxml2cpp is Copyright (C) 2017 The Qt Company Ltd.
*
* This is an auto-generated file.
* Do not edit! All changes made to it will be lost.
*/
#ifndef QIBUSPROXYPORTAL_H
#define QIBUSPROXYPORTAL_H
#include <QtCore/QObject>
#include <QtCore/QByteArray>
#include <QtCore/QList>
#include <QtCore/QMap>
#include <QtCore/QString>
#include <QtCore/QStringList>
#include <QtCore/QVariant>
#include <QtDBus/QtDBus>
/*
* Proxy class for interface org.freedesktop.IBus.Portal
*/
class QIBusProxyPortal: public QDBusAbstractInterface
{
Q_OBJECT
public:
static inline const char *staticInterfaceName()
{ return "org.freedesktop.IBus.Portal"; }
public:
QIBusProxyPortal(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = nullptr);
~QIBusProxyPortal();
public Q_SLOTS: // METHODS
inline QDBusPendingReply<QDBusObjectPath> CreateInputContext(const QString &name)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(name);
return asyncCallWithArgumentList(QStringLiteral("CreateInputContext"), argumentList);
}
Q_SIGNALS: // SIGNALS
};
#endif

View File

@ -72,6 +72,12 @@
#include <IOKit/graphics/IOGraphicsLib.h>
#if !QT_MACOS_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_14)
@interface NSApplication (MojaveForwardDeclarations)
@property (strong) NSAppearance *appearance NS_AVAILABLE_MAC(10_14);
@end
#endif
static void initResources()
{
Q_INIT_RESOURCE(qcocoaresources);
@ -133,6 +139,21 @@ QCocoaIntegration::QCocoaIntegration(const QStringList &paramList)
NSApplication *cocoaApplication = [QNSApplication sharedApplication];
qt_redirectNSApplicationSendEvent();
if (__builtin_available(macOS 10.14, *)) {
// Disable dark appearance, unless the Info.plist or environment requests that it should be enabled
bool plistEnablesDarkAppearance = [[[NSBundle mainBundle] objectForInfoDictionaryKey:
@"NSRequiresAquaSystemAppearance"] boolValue];
bool hasEnvironmentRequiresAquaAppearance;
int environmentRequiresAquaAppearance = qEnvironmentVariableIntValue(
"QT_MAC_REQUIRES_AQUA_SYSTEM_APPEARANCE", &hasEnvironmentRequiresAquaAppearance);
bool environmentEnablesDarkAppearance = hasEnvironmentRequiresAquaAppearance
&& environmentRequiresAquaAppearance == 0;
if (!(plistEnablesDarkAppearance || environmentEnablesDarkAppearance))
NSApp.appearance = [NSAppearance appearanceNamed:NSAppearanceNameAqua];
}
if (qEnvironmentVariableIsEmpty("QT_MAC_DISABLE_FOREGROUND_APPLICATION_TRANSFORM")) {
// Applications launched from plain executables (without an app
// bundle) are "background" applications that does not take keybaord

View File

@ -85,7 +85,8 @@ class QXcbBackingStore;
class QXcbBackingStoreImage : public QXcbObject
{
public:
QXcbBackingStoreImage(QXcbScreen *screen, const QSize &size, uint depth, QImage::Format format);
QXcbBackingStoreImage(QXcbBackingStore *backingStore, const QSize &size);
QXcbBackingStoreImage(QXcbBackingStore *backingStore, const QSize &size, uint depth, QImage::Format format);
~QXcbBackingStoreImage() { destroy(true); }
void resize(const QSize &size);
@ -109,10 +110,10 @@ public:
xcb_shm_segment_info_t *shm_info = nullptr);
private:
void createShmSegment(size_t segmentSize);
void destroyShmSegment(size_t segmentSize);
void init(const QSize &size, uint depth, QImage::Format format);
void create(const QSize &size, const xcb_format_t *fmt, QImage::Format format);
void createShmSegment(size_t segmentSize);
void destroyShmSegment();
void destroy(bool destroyShm);
void ensureGC(xcb_drawable_t dst);
@ -120,10 +121,9 @@ private:
void flushPixmap(const QRegion &region, bool fullRegion = false);
void setClip(const QRegion &region);
xcb_window_t m_screen_root;
xcb_shm_segment_info_t m_shm_info;
size_t m_segmentSize = 0;
QXcbBackingStore *m_backingStore = nullptr;
xcb_image_t *m_xcb_image = nullptr;
@ -153,6 +153,9 @@ private:
bool m_hasAlpha = false;
bool m_clientSideScroll = false;
const xcb_format_t *m_xcb_format = nullptr;
QImage::Format m_qimage_format = QImage::Format_Invalid;
};
class QXcbGraphicsBuffer : public QPlatformGraphicsBuffer
@ -190,83 +193,108 @@ static inline size_t imageDataSize(const xcb_image_t *image)
return static_cast<size_t>(image->stride) * image->height;
}
QXcbBackingStoreImage::QXcbBackingStoreImage(QXcbScreen *screen, const QSize &size, uint depth, QImage::Format format)
: QXcbObject(screen->connection())
, m_screen_root(screen->screen()->root)
QXcbBackingStoreImage::QXcbBackingStoreImage(QXcbBackingStore *backingStore, const QSize &size)
: QXcbObject(backingStore->connection())
, m_backingStore(backingStore)
{
const xcb_format_t *fmt = connection()->formatForDepth(depth);
Q_ASSERT(fmt);
auto window = static_cast<QXcbWindow *>(m_backingStore->window()->handle());
init(size, window->depth(), window->imageFormat());
}
QXcbBackingStoreImage::QXcbBackingStoreImage(QXcbBackingStore *backingStore, const QSize &size,
uint depth, QImage::Format format)
: QXcbObject(backingStore->connection())
, m_backingStore(backingStore)
{
init(size, depth, format);
}
void QXcbBackingStoreImage::init(const QSize &size, uint depth, QImage::Format format)
{
m_xcb_format = connection()->formatForDepth(depth);
Q_ASSERT(m_xcb_format);
m_qimage_format = format;
m_hasAlpha = QImage::toPixelFormat(m_qimage_format).alphaUsage() == QPixelFormat::UsesAlpha;
if (!m_hasAlpha)
m_qimage_format = qt_maybeAlphaVersionWithSameDepth(m_qimage_format);
memset(&m_shm_info, 0, sizeof m_shm_info);
m_hasAlpha = QImage::toPixelFormat(format).alphaUsage() == QPixelFormat::UsesAlpha;
if (!m_hasAlpha)
create(size, fmt, qt_maybeAlphaVersionWithSameDepth(format));
else
create(size, fmt, format);
resize(size);
}
void QXcbBackingStoreImage::resize(const QSize &size)
{
xcb_format_t fmt;
fmt.depth = m_xcb_image->depth;
fmt.bits_per_pixel = m_xcb_image->bpp;
fmt.scanline_pad = m_xcb_image->scanline_pad;
memset(fmt.pad0, 0, sizeof(fmt.pad0));
destroy(false);
create(size, &fmt, m_qimage.format());
}
void QXcbBackingStoreImage::create(const QSize &size, const xcb_format_t *fmt, QImage::Format format)
{
auto byteOrder = QSysInfo::ByteOrder == QSysInfo::BigEndian ? XCB_IMAGE_ORDER_MSB_FIRST
: XCB_IMAGE_ORDER_LSB_FIRST;
m_xcb_image = xcb_image_create(size.width(), size.height(),
XCB_IMAGE_FORMAT_Z_PIXMAP,
fmt->scanline_pad,
fmt->depth, fmt->bits_per_pixel, 0,
QSysInfo::ByteOrder == QSysInfo::BigEndian ? XCB_IMAGE_ORDER_MSB_FIRST : XCB_IMAGE_ORDER_LSB_FIRST,
m_xcb_format->scanline_pad,
m_xcb_format->depth,
m_xcb_format->bits_per_pixel,
0, byteOrder,
XCB_IMAGE_ORDER_MSB_FIRST,
0, ~0, 0);
const size_t segmentSize = imageDataSize(m_xcb_image);
if (!segmentSize)
return;
if (connection()->hasShm()) {
if (m_shm_info.shmaddr && (m_segmentSize < segmentSize || m_segmentSize / 2 >= segmentSize))
destroyShmSegment(m_segmentSize);
if (!m_shm_info.shmaddr) {
qCDebug(lcQpaXcb) << "creating shared memory" << segmentSize << "for"
<< size << "depth" << fmt->depth << "bits" << fmt->bits_per_pixel;
createShmSegment(segmentSize);
if (segmentSize == 0) {
if (m_segmentSize > 0) {
destroyShmSegment();
qCDebug(lcQpaXcb) << "[" << m_backingStore->window()
<< "] destroyed SHM segment due to resize to" << size;
}
} else {
// Destroy shared memory segment if it is double (or more) of what we actually
// need with new window size. Or if the new size is bigger than what we currently
// have allocated.
if (m_shm_info.shmaddr && (m_segmentSize < segmentSize || m_segmentSize / 2 >= segmentSize))
destroyShmSegment();
if (!m_shm_info.shmaddr) {
qCDebug(lcQpaXcb) << "[" << m_backingStore->window()
<< "] creating shared memory" << segmentSize << "bytes for"
<< size << "depth" << m_xcb_format->depth << "bits"
<< m_xcb_format->bits_per_pixel;
createShmSegment(segmentSize);
}
}
}
m_xcb_image->data = m_shm_info.shmaddr ? m_shm_info.shmaddr : (uint8_t *)malloc(segmentSize);
if (segmentSize == 0)
return;
m_qimage = QImage( (uchar*) m_xcb_image->data, m_xcb_image->width, m_xcb_image->height, m_xcb_image->stride, format);
m_xcb_image->data = m_shm_info.shmaddr ? m_shm_info.shmaddr : (uint8_t *)malloc(segmentSize);
m_qimage = QImage(static_cast<uchar *>(m_xcb_image->data), m_xcb_image->width,
m_xcb_image->height, m_xcb_image->stride, m_qimage_format);
m_graphics_buffer = new QXcbGraphicsBuffer(&m_qimage);
m_xcb_pixmap = xcb_generate_id(xcb_connection());
auto xcbScreen = static_cast<QXcbScreen *>(m_backingStore->window()->screen()->handle());
xcb_create_pixmap(xcb_connection(),
m_xcb_image->depth,
m_xcb_pixmap,
m_screen_root,
xcbScreen->root(),
m_xcb_image->width, m_xcb_image->height);
}
void QXcbBackingStoreImage::destroy(bool destroyShm)
{
if (m_xcb_image->data) {
if (m_shm_info.shmaddr) {
if (destroyShm)
destroyShmSegment(m_segmentSize);
} else {
free(m_xcb_image->data);
if (m_xcb_image) {
if (m_xcb_image->data) {
if (m_shm_info.shmaddr) {
if (destroyShm)
destroyShmSegment();
} else {
free(m_xcb_image->data);
}
}
xcb_image_destroy(m_xcb_image);
}
xcb_image_destroy(m_xcb_image);
if (m_gc) {
xcb_free_gc(xcb_connection(), m_gc);
m_gc = 0;
@ -276,8 +304,12 @@ void QXcbBackingStoreImage::destroy(bool destroyShm)
delete m_graphics_buffer;
m_graphics_buffer = nullptr;
xcb_free_pixmap(xcb_connection(), m_xcb_pixmap);
m_xcb_pixmap = 0;
if (m_xcb_pixmap) {
xcb_free_pixmap(xcb_connection(), m_xcb_pixmap);
m_xcb_pixmap = 0;
}
m_qimage = QImage();
}
void QXcbBackingStoreImage::flushScrolledRegion(bool clientSideScroll)
@ -420,11 +452,8 @@ bool QXcbBackingStoreImage::createSystemVShmSegment(QXcbConnection *c, size_t se
return true;
}
void QXcbBackingStoreImage::destroyShmSegment(size_t segmentSize)
void QXcbBackingStoreImage::destroyShmSegment()
{
#ifndef XCB_USE_SHM_FD
Q_UNUSED(segmentSize)
#endif
auto cookie = xcb_shm_detach_checked(xcb_connection(), m_shm_info.shmseg);
xcb_generic_error_t *error = xcb_request_check(xcb_connection(), cookie);
if (error)
@ -433,9 +462,9 @@ void QXcbBackingStoreImage::destroyShmSegment(size_t segmentSize)
#ifdef XCB_USE_SHM_FD
if (connection()->hasShmFd()) {
if (munmap(m_shm_info.shmaddr, segmentSize) == -1) {
if (munmap(m_shm_info.shmaddr, m_segmentSize) == -1) {
qCWarning(lcQpaXcb, "munmap() failed (%d: %s) for %p with size %zu",
errno, strerror(errno), m_shm_info.shmaddr, segmentSize);
errno, strerror(errno), m_shm_info.shmaddr, m_segmentSize);
}
} else
#endif
@ -894,7 +923,7 @@ void QXcbBackingStore::recreateImage(QXcbWindow *win, const QSize &size)
if (m_image)
m_image->resize(size);
else
m_image = new QXcbBackingStoreImage(win->xcbScreen(), size, win->depth(), win->imageFormat());
m_image = new QXcbBackingStoreImage(this, size);
// Slow path for bgr888 VNC: Create an additional image, paint into that and
// swap R and B while copying to m_image after each paint.
@ -1024,7 +1053,7 @@ void QXcbSystemTrayBackingStore::recreateImage(QXcbWindow *win, const QSize &siz
if (m_image)
m_image->resize(size);
else
m_image = new QXcbBackingStoreImage(screen, size, 32, QImage::Format_ARGB32_Premultiplied);
m_image = new QXcbBackingStoreImage(this, size, 32, QImage::Format_ARGB32_Premultiplied);
#endif // QT_CONFIG(xcb_render)
}

View File

@ -69,7 +69,7 @@ QImage::Format imageFormatForMasks(int depth, int bits_per_pixel, int red_mask,
if (red_mask == 0xff && blue_mask == 0xff0000)
return QImage::Format_RGBA8888_Premultiplied;
#else
if (red_mask == 0xff000000 && blue_mask == 0xff00)
if (unsigned(red_mask) == unsigned(0xff000000) && blue_mask == 0xff00)
return QImage::Format_RGBA8888_Premultiplied;
#endif
if (red_mask == 0x3ff && blue_mask == 0x3ff00000)
@ -90,7 +90,7 @@ QImage::Format imageFormatForMasks(int depth, int bits_per_pixel, int red_mask,
if (red_mask == 0xff && blue_mask == 0xff0000)
return QImage::Format_RGBX8888;
#else
if (red_mask == 0xff000000 && blue_mask == 0xff00)
if (unsigned(red_mask) == unsigned(0xff000000) && blue_mask == 0xff00)
return QImage::Format_RGBX8888;
#endif
break;

View File

@ -1022,6 +1022,16 @@ void QMessageBoxPrivate::detectEscapeButton()
return;
}
// If there are two buttons and one of them is the "Show Details..."
// button, then make the other one the escape button
if (buttons.count() == 2 && detailsButton) {
auto idx = buttons.indexOf(detailsButton);
if (idx != -1) {
detectedEscapeButton = buttons.at(1 - idx);
return;
}
}
// if the message box has one RejectRole button, make it the escape button
for (auto *button : buttons) {
if (buttonBox->buttonRole(button) == QDialogButtonBox::RejectRole) {

View File

@ -153,3 +153,4 @@ if (NOT CMAKE_VERSION VERSION_LESS 3.8)
# /usr/bin/ld: CMakeFiles/mywidget.dir/moc_mywidget.cpp.o: previous definition here
# Reason: SKIP_* properties were added in CMake 3.8 only
expect_pass(test_QTBUG-63422)
endif()

View File

@ -137,6 +137,7 @@ private slots:
void nbspWithFormat();
void noModificationOfInputString();
void superscriptCrash_qtbug53911();
void showLineAndParagraphSeparatorsCrash();
private:
QFont testFont;
@ -2199,6 +2200,23 @@ void tst_QTextLayout::noModificationOfInputString()
}
}
void tst_QTextLayout::showLineAndParagraphSeparatorsCrash()
{
QString s = QString(100000, QChar('a')) + QChar(QChar::LineSeparator);
{
QTextLayout layout;
layout.setText(s);
QTextOption option;
option.setFlags(QTextOption::ShowLineAndParagraphSeparators);
layout.setTextOption(option);
layout.beginLayout();
layout.createLine();
layout.endLayout();
}
}
void tst_QTextLayout::superscriptCrash_qtbug53911()
{
static int fontSizes = 64;

View File

@ -1,4 +1,4 @@
CONFIG += testcase
TARGET = tst_qfocusevent
QT += widgets testlib
QT += widgets testlib gui-private
SOURCES += tst_qfocusevent.cpp

View File

@ -38,6 +38,9 @@
#include <QBoxLayout>
#include <QSysInfo>
#include <qpa/qplatformintegration.h>
#include <private/qguiapplication_p.h>
QT_FORWARD_DECLARE_CLASS(QWidget)
class FocusLineEdit : public QLineEdit
@ -92,13 +95,16 @@ private slots:
void checkReason_ActiveWindow();
private:
QWidget* testFocusWidget;
QWidget* testFocusWidget = nullptr;
FocusLineEdit* childFocusWidgetOne;
FocusLineEdit* childFocusWidgetTwo;
};
void tst_QFocusEvent::initTestCase()
{
if (!QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowActivation))
QSKIP("QWindow::requestActivate() is not supported on this platform.");
testFocusWidget = new QWidget( 0 );
childFocusWidgetOne = new FocusLineEdit( testFocusWidget );
childFocusWidgetOne->setGeometry( 10, 10, 180, 20 );

View File

@ -331,6 +331,12 @@ void tst_QMessageBox::escapeButton()
closeHelper.start(ExecCloseHelper::CloseWindow, &msgBox2);
msgBox2.exec();
QVERIFY(msgBox2.clickedButton() == msgBox2.button(QMessageBox::No)); // auto detected (one No button only)
QMessageBox msgBox3;
msgBox3.setDetailedText("Details");
closeHelper.start(ExecCloseHelper::CloseWindow, &msgBox3);
msgBox3.exec();
QVERIFY(msgBox3.clickedButton() == msgBox3.button(QMessageBox::Ok)); // auto detected
}
void tst_QMessageBox::statics()