summaryrefslogtreecommitdiffstats
path: root/src/plugins
diff options
context:
space:
mode:
authorLiang Qi <liang.qi@qt.io>2018-08-16 17:50:08 +0000
committerThe Qt Project <gerrit-noreply@qt-project.org>2018-08-16 18:59:13 +0000
commitd98106d1d5a9ac68f0e4d20429d2d41b3dbcc131 (patch)
tree98af6e7d8be4bc026f0c2734a855580bf3e4bef2 /src/plugins
parent30b0701c9b50ec718ec858d7777a01c66e333a9c (diff)
parent8559bf934def636ccff487464adb600d219f8778 (diff)
Merge "Merge remote-tracking branch 'origin/5.11' into dev" into refs/staging/dev
Diffstat (limited to 'src/plugins')
-rw-r--r--src/plugins/platforminputcontexts/ibus/ibus.pro2
-rw-r--r--src/plugins/platforminputcontexts/ibus/interfaces/org.freedesktop.IBus.Portal.xml10
-rw-r--r--src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.cpp111
-rw-r--r--src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.h2
-rw-r--r--src/plugins/platforminputcontexts/ibus/qibusproxyportal.cpp26
-rw-r--r--src/plugins/platforminputcontexts/ibus/qibusproxyportal.h49
-rw-r--r--src/plugins/platforms/cocoa/qcocoaintegration.mm21
-rw-r--r--src/plugins/platforms/xcb/qxcbbackingstore.cpp143
-rw-r--r--src/plugins/platforms/xcb/qxcbimage.cpp4
9 files changed, 288 insertions, 80 deletions
diff --git a/src/plugins/platforminputcontexts/ibus/ibus.pro b/src/plugins/platforminputcontexts/ibus/ibus.pro
index 9f6c848e6a..52836bb8b6 100644
--- a/src/plugins/platforminputcontexts/ibus/ibus.pro
+++ b/src/plugins/platforminputcontexts/ibus/ibus.pro
@@ -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
diff --git a/src/plugins/platforminputcontexts/ibus/interfaces/org.freedesktop.IBus.Portal.xml b/src/plugins/platforminputcontexts/ibus/interfaces/org.freedesktop.IBus.Portal.xml
new file mode 100644
index 0000000000..1a5414d0ae
--- /dev/null
+++ b/src/plugins/platforminputcontexts/ibus/interfaces/org.freedesktop.IBus.Portal.xml
@@ -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>
diff --git a/src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.cpp b/src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.cpp
index f339938f86..0e587965ca 100644
--- a/src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.cpp
+++ b/src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.cpp
@@ -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))
diff --git a/src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.h b/src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.h
index 9b92b2e1f9..f37552b937 100644
--- a/src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.h
+++ b/src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.h
@@ -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);
diff --git a/src/plugins/platforminputcontexts/ibus/qibusproxyportal.cpp b/src/plugins/platforminputcontexts/ibus/qibusproxyportal.cpp
new file mode 100644
index 0000000000..50482e2d9a
--- /dev/null
+++ b/src/plugins/platforminputcontexts/ibus/qibusproxyportal.cpp
@@ -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()
+{
+}
+
diff --git a/src/plugins/platforminputcontexts/ibus/qibusproxyportal.h b/src/plugins/platforminputcontexts/ibus/qibusproxyportal.h
new file mode 100644
index 0000000000..bdd1d9c395
--- /dev/null
+++ b/src/plugins/platforminputcontexts/ibus/qibusproxyportal.h
@@ -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
diff --git a/src/plugins/platforms/cocoa/qcocoaintegration.mm b/src/plugins/platforms/cocoa/qcocoaintegration.mm
index 612290c9bd..0f87109ada 100644
--- a/src/plugins/platforms/cocoa/qcocoaintegration.mm
+++ b/src/plugins/platforms/cocoa/qcocoaintegration.mm
@@ -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
diff --git a/src/plugins/platforms/xcb/qxcbbackingstore.cpp b/src/plugins/platforms/xcb/qxcbbackingstore.cpp
index e73e6f3e61..c29eb29b7e 100644
--- a/src/plugins/platforms/xcb/qxcbbackingstore.cpp
+++ b/src/plugins/platforms/xcb/qxcbbackingstore.cpp
@@ -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());
+}
- memset(&m_shm_info, 0, sizeof m_shm_info);
+QXcbBackingStoreImage::QXcbBackingStoreImage(QXcbBackingStore *backingStore, const QSize &size,
+ uint depth, QImage::Format format)
+ : QXcbObject(backingStore->connection())
+ , m_backingStore(backingStore)
+{
+ init(size, depth, format);
+}
- m_hasAlpha = QImage::toPixelFormat(format).alphaUsage() == QPixelFormat::UsesAlpha;
+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)
- create(size, fmt, qt_maybeAlphaVersionWithSameDepth(format));
- else
- create(size, fmt, format);
+ m_qimage_format = qt_maybeAlphaVersionWithSameDepth(m_qimage_format);
+
+ memset(&m_shm_info, 0, sizeof m_shm_info);
+
+ 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)
}
diff --git a/src/plugins/platforms/xcb/qxcbimage.cpp b/src/plugins/platforms/xcb/qxcbimage.cpp
index e18a08755b..44c7d22344 100644
--- a/src/plugins/platforms/xcb/qxcbimage.cpp
+++ b/src/plugins/platforms/xcb/qxcbimage.cpp
@@ -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;