From 2adc06f9406ec2f8c02d1619c73f384eb2947498 Mon Sep 17 00:00:00 2001 From: Robin Lee Date: Wed, 27 Jun 2018 11:54:20 +0800 Subject: IBus: Support the portal, needed for Flatpak environment Following commit 35ce6247 in IBus, IBus input plugin now connects to session bus and use IBus portal to create input context when running in Flatpak environment or IBUS_USE_PORTAL is set. [ChangeLog][plugins][ibus] Support IBus portal. Qt programs in Flatpak environment can now trigger IBus input method. Change-Id: I561f5f873d709b8abeae554d804daa058f9f6e16 Reviewed-by: Lars Knoll Reviewed-by: Takao Fujiwara --- src/plugins/platforminputcontexts/ibus/ibus.pro | 2 + .../interfaces/org.freedesktop.IBus.Portal.xml | 10 ++++ .../ibus/qibusplatforminputcontext.cpp | 64 ++++++++++++++++++---- .../ibus/qibusproxyportal.cpp | 26 +++++++++ .../platforminputcontexts/ibus/qibusproxyportal.h | 49 +++++++++++++++++ 5 files changed, 140 insertions(+), 11 deletions(-) create mode 100644 src/plugins/platforminputcontexts/ibus/interfaces/org.freedesktop.IBus.Portal.xml create mode 100644 src/plugins/platforminputcontexts/ibus/qibusproxyportal.cpp create mode 100644 src/plugins/platforminputcontexts/ibus/qibusproxyportal.h (limited to 'src/plugins') 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 @@ + + + + + + + + + diff --git a/src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.cpp b/src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.cpp index f339938f86..19f0afbf50 100644 --- a/src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.cpp +++ b/src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.cpp @@ -50,6 +50,7 @@ #include #include "qibusproxy.h" +#include "qibusproxyportal.h" #include "qibusinputcontextproxy.h" #include "qibustypes.h" @@ -78,19 +79,22 @@ 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; + bool usePortal; // return value of shouldConnectIbusPortal bool valid; bool busConnected; QString predit; @@ -507,6 +511,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; } @@ -572,15 +579,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 +629,35 @@ 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 ic; + if (usePortal) { + portalBus = new QIBusProxyPortal(QLatin1String(ibusService), + QLatin1String("/org/freedesktop/IBus"), + *connection); + if (!portalBus->isValid()) { + qWarning("QIBusPlatformInputContext: invalid portal bus."); + return; + } - QDBusReply ic = bus->CreateInputContext(QLatin1String("QIBusInputContext")); + 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")); + } 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 +705,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/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 +#include +#include +#include +#include +#include +#include +#include + +/* + * 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 CreateInputContext(const QString &name) + { + QList argumentList; + argumentList << QVariant::fromValue(name); + return asyncCallWithArgumentList(QStringLiteral("CreateInputContext"), argumentList); + } + +Q_SIGNALS: // SIGNALS +}; + +#endif -- cgit v1.2.3 From 04671a80db32bd7fce470c50934cf60f2e8ffa70 Mon Sep 17 00:00:00 2001 From: Gabriel de Dietrich Date: Fri, 15 Jun 2018 23:15:10 +0200 Subject: macOS: Force light theme on macOS 10.14+ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Until we can properly fix QPalette and QMacStyle, we should disable dark appearance in Qt applications. Disable by setting NSApp.appearance to Aqua, unless dark mode support has been requested via Info.plist or environment variable. Read the NSRequiresAquaSystemAppearance Info.plist key, don’t set NSApp.appearance if its value is false. Also check the QT_MAC_REQUIRES_AQUA_SYSTEM_APPEARANCE environment variable and apply similar logic. You then enable dark mode support by setting: QT_MAC_REQUIRES_AQUA_SYSTEM_APPEARANCE=0 which is slightly awkward, but matches Info.plist behavior. Task-number: QTBUG-68891 Change-Id: I86dc6cf3dee951d46c953396c57d2c31f2e4afcc Reviewed-by: Morten Johan Sørvig --- src/plugins/platforms/cocoa/qcocoaintegration.mm | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) (limited to 'src/plugins') diff --git a/src/plugins/platforms/cocoa/qcocoaintegration.mm b/src/plugins/platforms/cocoa/qcocoaintegration.mm index 55b3805df3..79f7ebda54 100644 --- a/src/plugins/platforms/cocoa/qcocoaintegration.mm +++ b/src/plugins/platforms/cocoa/qcocoaintegration.mm @@ -70,6 +70,12 @@ #include +#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); @@ -131,6 +137,21 @@ QCocoaIntegration::QCocoaIntegration(const QStringList ¶mList) 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 -- cgit v1.2.3 From e9a8facc96ce6d3b8df4832032ca4df9fac6e9d7 Mon Sep 17 00:00:00 2001 From: Takao Fujiwara Date: Thu, 9 Aug 2018 16:37:21 +0900 Subject: IBus: connect to ibus-daemon when it restarts in Flatpak IBus clients cannot access the IBus socket path in Flatpak and need to watch the D-Bus disconnection. Change-Id: Ida1a5ce4fe112c1c4f8855ec886e74f2cbdcc8a0 Reviewed-by: Lars Knoll --- .../ibus/qibusplatforminputcontext.cpp | 49 +++++++++++++++++----- .../ibus/qibusplatforminputcontext.h | 2 + 2 files changed, 40 insertions(+), 11 deletions(-) (limited to 'src/plugins') diff --git a/src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.cpp b/src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.cpp index 19f0afbf50..0e587965ca 100644 --- a/src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.cpp +++ b/src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.cpp @@ -93,6 +93,7 @@ public: QIBusProxy *bus; QIBusProxyPortal *portalBus; // bus and portalBus are alternative. QIBusInputContextProxy *context; + QDBusServiceWatcher serviceWatcher; bool usePortal; // return value of shouldConnectIbusPortal bool valid; @@ -107,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(); @@ -534,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() @@ -543,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 } @@ -652,6 +674,11 @@ void QIBusPlatformInputContextPrivate::createBusProxy() ic = bus->CreateInputContext(QLatin1String("QIBusInputContext")); } + + serviceWatcher.removeWatchedService(ibusService); + serviceWatcher.setConnection(*connection); + serviceWatcher.addWatchedService(ibusService); + if (!ic.isValid()) { qWarning("QIBusPlatformInputContext: CreateInputContext failed."); return; 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); -- cgit v1.2.3 From 833b9997fd8c93132186d6538770f0c415f73d53 Mon Sep 17 00:00:00 2001 From: Gatis Paeglis Date: Fri, 27 Jul 2018 12:25:12 +0200 Subject: xcb: make sure we have a valid m_qimage in backing store MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch amends a62f1d03560937a306c7586669a46cd9575e9464. If the initial backing store resize request is called with QSize(0, 0), we end up with QXcbBackingStoreImage holding a default contructed QImage / m_qimage. This happens because of the logic in QXcbBackingStoreImage::create(), where if we detect that the requested segmentSize == 0, we do not allocate any memory, and thus don't create a valid image in m_qimage. On subsequent call to QXcbBackingStore::resize() we would only check if QXcbBackingStoreImage object has been created, but not if it is in a valid state. This obviously would cause problems. This patch re-factors the logic to handle better resize to QSize(0, 0). And make the code cleaner by: - merging ::create and ::resize as semantically it is always resize(). - dropping unnecessary argument passing. Task-number: QTBUG-69581 Change-Id: Ied337beb449dea8259fcf6b7d29f0a5bd553019d Reviewed-by: Błażej Szczygieł Reviewed-by: Shawn Rutledge --- src/plugins/platforms/xcb/qxcbbackingstore.cpp | 111 ++++++++++++++----------- 1 file changed, 61 insertions(+), 50 deletions(-) (limited to 'src/plugins') diff --git a/src/plugins/platforms/xcb/qxcbbackingstore.cpp b/src/plugins/platforms/xcb/qxcbbackingstore.cpp index b81cb8efa1..8ae9d9899e 100644 --- a/src/plugins/platforms/xcb/qxcbbackingstore.cpp +++ b/src/plugins/platforms/xcb/qxcbbackingstore.cpp @@ -100,9 +100,7 @@ public: private: void createShmSegment(size_t segmentSize); - void destroyShmSegment(size_t segmentSize); - - void create(const QSize &size, const xcb_format_t *fmt, QImage::Format format); + void destroyShmSegment(); void destroy(bool destroyShm); void ensureGC(xcb_drawable_t dst); @@ -142,6 +140,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 @@ -183,58 +184,66 @@ QXcbBackingStoreImage::QXcbBackingStoreImage(QXcbBackingStore *backingStore, con : QXcbObject(backingStore->connection()) , m_backingStore(backingStore) { - QXcbWindow *window = static_cast(backingStore->window()->handle()); - const xcb_format_t *fmt = connection()->formatForDepth(window->depth()); - Q_ASSERT(fmt); + auto window = static_cast(m_backingStore->window()->handle()); + m_xcb_format = connection()->formatForDepth(window->depth()); + Q_ASSERT(m_xcb_format); + + m_qimage_format = window->imageFormat(); + 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); - QImage::Format format = window->imageFormat(); - 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(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()); @@ -248,17 +257,18 @@ void QXcbBackingStoreImage::create(const QSize &size, const xcb_format_t *fmt, Q 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; @@ -268,8 +278,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) @@ -412,11 +426,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) @@ -425,9 +436,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 -- cgit v1.2.3 From f2862b4d5def2c07b8b018532ab74a12b129db2c Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Tue, 22 May 2018 13:00:38 +0200 Subject: VNC plugin: explicitly cast int to uint16_t before calling htons Otherwise there is a -Werror=narrowing error on big-endian architectures (where htons does nothing). Task-number: QTBUG-68390 Change-Id: Idb204a81aaedb9f4fde1d5fae406da36c7a1953e Reviewed-by: Thiago Macieira (cherry-picked from b206d1c8082a9e01ad3755d311a4cf683ec35161) --- src/plugins/platforms/vnc/qvnc.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/plugins') diff --git a/src/plugins/platforms/vnc/qvnc.cpp b/src/plugins/platforms/vnc/qvnc.cpp index 44fc1c6101..ffe00de2b1 100644 --- a/src/plugins/platforms/vnc/qvnc.cpp +++ b/src/plugins/platforms/vnc/qvnc.cpp @@ -552,9 +552,9 @@ void QVncClientCursor::write(QVncClient *client) const { const quint16 tmp[6] = { htons(0), htons(1), - htons(hotspot.x()), htons(hotspot.y()), - htons(cursor.width()), - htons(cursor.height()) }; + htons(uint16_t(hotspot.x())), htons(uint16_t(hotspot.y())), + htons(uint16_t(cursor.width())), + htons(uint16_t(cursor.height())) }; socket->write((char*)tmp, sizeof(tmp)); const qint32 encoding = qToBigEndian(-239); -- cgit v1.2.3 From 8f1851013363ae22d311881abcb1186949068270 Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Tue, 14 Aug 2018 07:19:02 +0200 Subject: Silence warning about comparing signed and unsigned qxcbimage.cpp:72:26: error: comparison between signed and unsigned integer expressions [-Werror=sign-compare] Task-number: QTBUG-69923 Change-Id: Icdb4ce8cb7ce5b48d7ee3839166eb1c7c9520c78 Reviewed-by: Thiago Macieira --- src/plugins/platforms/xcb/qxcbimage.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/plugins') 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; -- cgit v1.2.3 From 1ae3db46e8e98b6c3ce07a5b35330bc75dd86bfc Mon Sep 17 00:00:00 2001 From: Gatis Paeglis Date: Tue, 14 Aug 2018 11:29:31 +0200 Subject: drop usages of Q_COMPILER_CLASS_ENUM It is not relevant anymore. C++11 is a hard requirement for a while already. Change-Id: Idb8fbdcd13398cc85fba583f40c2b5c4dc7c4943 Reviewed-by: Thiago Macieira --- src/plugins/platforms/windows/qwindowsmousehandler.cpp | 5 ----- src/plugins/platforms/windows/qwindowsscreen.cpp | 5 +---- src/plugins/platforms/xcb/qxcbwindow.cpp | 4 ---- 3 files changed, 1 insertion(+), 13 deletions(-) (limited to 'src/plugins') diff --git a/src/plugins/platforms/windows/qwindowsmousehandler.cpp b/src/plugins/platforms/windows/qwindowsmousehandler.cpp index 87f48e0c84..c1c275144f 100644 --- a/src/plugins/platforms/windows/qwindowsmousehandler.cpp +++ b/src/plugins/platforms/windows/qwindowsmousehandler.cpp @@ -257,12 +257,7 @@ bool QWindowsMouseHandler::translateMouseEvent(QWindow *window, HWND hwnd, QtWindows::WindowsEventType et, MSG msg, LRESULT *result) { -#ifdef Q_COMPILER_CLASS_ENUM enum : quint64 { signatureMask = 0xffffff00, miWpSignature = 0xff515700 }; -#else - static const quint64 signatureMask = 0xffffff00; - static const quint64 miWpSignature = 0xff515700; -#endif // !Q_COMPILER_CLASS_ENUM if (et == QtWindows::MouseWheelEvent) return translateMouseWheelEvent(window, hwnd, msg, result); diff --git a/src/plugins/platforms/windows/qwindowsscreen.cpp b/src/plugins/platforms/windows/qwindowsscreen.cpp index 29165ef72c..2eaf386d42 100644 --- a/src/plugins/platforms/windows/qwindowsscreen.cpp +++ b/src/plugins/platforms/windows/qwindowsscreen.cpp @@ -330,10 +330,7 @@ QRect QWindowsScreen::virtualGeometry(const QPlatformScreen *screen) // cf QScre return result; } -enum OrientationPreference // matching Win32 API ORIENTATION_PREFERENCE -#if defined(Q_COMPILER_CLASS_ENUM) || defined(Q_CC_MSVC) - : DWORD -#endif +enum OrientationPreference : DWORD // matching Win32 API ORIENTATION_PREFERENCE { orientationPreferenceNone = 0, orientationPreferenceLandscape = 0x1, diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp index d42d95f890..e313e2f648 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.cpp +++ b/src/plugins/platforms/xcb/qxcbwindow.cpp @@ -275,11 +275,7 @@ QXcbWindow::QXcbWindow(QWindow *window) setConnection(xcbScreen()->connection()); } -#ifdef Q_COMPILER_CLASS_ENUM enum : quint32 { -#else -enum { -#endif baseEventMask = XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_PROPERTY_CHANGE | XCB_EVENT_MASK_FOCUS_CHANGE, -- cgit v1.2.3 From 540525bceb23d63198f89a0987c4a6042b323ce0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Arve=20S=C3=A6ther?= Date: Tue, 31 Jul 2018 13:49:58 +0200 Subject: Windows QPA: Do not double delete the QTouchDevice This caused a crash on destruction because as soon as you construct a QTouchDevice it will register itself to a list of devices. On application exit the function cleanupDevicesList() in qtouchdevice.cpp would go through all registered QTouchDevices and destroy them. Therefore, there is no need to delete the QTouchDevice from QWindowsPointerHandler. This was a regression that was caused by 20d6dac63c25d227ed5315801e3e853ee78ec248 Change-Id: I58fb50016c047c3843a3f9677f2c2ef824223d43 Reviewed-by: Friedemann Kleint Reviewed-by: Andre de la Rocha --- src/plugins/platforms/windows/qwindowspointerhandler.cpp | 6 +++--- src/plugins/platforms/windows/qwindowspointerhandler.h | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'src/plugins') diff --git a/src/plugins/platforms/windows/qwindowspointerhandler.cpp b/src/plugins/platforms/windows/qwindowspointerhandler.cpp index f25e6d13d8..c11be972b0 100644 --- a/src/plugins/platforms/windows/qwindowspointerhandler.cpp +++ b/src/plugins/platforms/windows/qwindowspointerhandler.cpp @@ -239,8 +239,8 @@ static QTouchDevice *createTouchDevice() QTouchDevice *QWindowsPointerHandler::ensureTouchDevice() { if (!m_touchDevice) - m_touchDevice.reset(createTouchDevice()); - return m_touchDevice.data(); + m_touchDevice = createTouchDevice(); + return m_touchDevice; } Qt::MouseButtons QWindowsPointerHandler::queryMouseButtons() @@ -400,7 +400,7 @@ bool QWindowsPointerHandler::translateTouchEvent(QWindow *window, HWND hwnd, touchPoints.append(touchPoint); } - QWindowSystemInterface::handleTouchEvent(window, m_touchDevice.data(), touchPoints, + QWindowSystemInterface::handleTouchEvent(window, m_touchDevice, touchPoints, QWindowsKeyMapper::queryKeyboardModifiers()); if (!(QWindowsIntegration::instance()->options() & QWindowsIntegration::DontPassOsMouseEventsSynthesizedFromTouch)) { diff --git a/src/plugins/platforms/windows/qwindowspointerhandler.h b/src/plugins/platforms/windows/qwindowspointerhandler.h index 11bc9419d7..c4d0e0ce4a 100644 --- a/src/plugins/platforms/windows/qwindowspointerhandler.h +++ b/src/plugins/platforms/windows/qwindowspointerhandler.h @@ -59,7 +59,7 @@ public: QWindowsPointerHandler() = default; bool translatePointerEvent(QWindow *window, HWND hwnd, QtWindows::WindowsEventType et, MSG msg, LRESULT *result); bool translateMouseEvent(QWindow *window, HWND hwnd, QtWindows::WindowsEventType et, MSG msg, LRESULT *result); - QTouchDevice *touchDevice() const { return m_touchDevice.data(); } + QTouchDevice *touchDevice() const { return m_touchDevice; } QTouchDevice *ensureTouchDevice(); Qt::MouseButtons queryMouseButtons(); QWindow *windowUnderMouse() const { return m_windowUnderPointer.data(); } @@ -70,7 +70,7 @@ private: bool translateTouchEvent(QWindow *window, HWND hwnd, QtWindows::WindowsEventType et, MSG msg, PVOID vTouchInfo, unsigned int count); bool translatePenEvent(QWindow *window, HWND hwnd, QtWindows::WindowsEventType et, MSG msg, PVOID vPenInfo); - QScopedPointer m_touchDevice; + QTouchDevice *m_touchDevice = nullptr; QHash m_lastTouchPositions; QPointer m_windowUnderPointer; QPointer m_currentWindow; -- cgit v1.2.3 From 1a350077ff6aae315b87f220276f3fba8038d93d Mon Sep 17 00:00:00 2001 From: Liang Qi Date: Tue, 14 Aug 2018 09:03:57 +0200 Subject: Revert "macOS: Don't call [NSOpenGLContext update] for every frame" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 823acb069d92b68b36f1b2bb59575bb0595275b4. It caused some test failures in qtdeclarative and etc. Task-number: QTBUG-69891 Change-Id: I2e4038a46de254834e6389c63f6dad0c2e523b8e Reviewed-by: Tor Arne Vestbø --- src/plugins/platforms/cocoa/qcocoaglcontext.h | 9 +- src/plugins/platforms/cocoa/qcocoaglcontext.mm | 132 ++++++--------------- .../platforms/cocoa/qcocoanativeinterface.mm | 4 + src/plugins/platforms/cocoa/qcocoawindow.h | 8 ++ src/plugins/platforms/cocoa/qcocoawindow.mm | 22 ++++ 5 files changed, 76 insertions(+), 99 deletions(-) (limited to 'src/plugins') diff --git a/src/plugins/platforms/cocoa/qcocoaglcontext.h b/src/plugins/platforms/cocoa/qcocoaglcontext.h index 3f7966b247..0e5934bc23 100644 --- a/src/plugins/platforms/cocoa/qcocoaglcontext.h +++ b/src/plugins/platforms/cocoa/qcocoaglcontext.h @@ -41,9 +41,6 @@ #define QCOCOAGLCONTEXT_H #include -#include -#include - #include #include #include @@ -68,6 +65,8 @@ public: bool isSharing() const override; bool isValid() const override; + void windowWasHidden(); + NSOpenGLContext *nativeContext() const; QFunctionPointer getProcAddress(const char *procName) override; @@ -75,14 +74,14 @@ public: private: static NSOpenGLPixelFormat *pixelFormatForSurfaceFormat(const QSurfaceFormat &format); - bool setDrawable(QPlatformSurface *surface); + bool setActiveWindow(QWindow *window); void updateSurfaceFormat(); NSOpenGLContext *m_context = nil; NSOpenGLContext *m_shareContext = nil; QSurfaceFormat m_format; + QPointer m_currentWindow; bool m_didCheckForSoftwareContext = false; - QVarLengthArray m_observers; }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/cocoa/qcocoaglcontext.mm b/src/plugins/platforms/cocoa/qcocoaglcontext.mm index cba9e90a78..4d0fa2e28e 100644 --- a/src/plugins/platforms/cocoa/qcocoaglcontext.mm +++ b/src/plugins/platforms/cocoa/qcocoaglcontext.mm @@ -41,8 +41,6 @@ #include "qcocoawindow.h" #include "qcocoahelpers.h" #include -#include -#include #include #include #include @@ -322,6 +320,9 @@ void QCocoaGLContext::updateSurfaceFormat() QCocoaGLContext::~QCocoaGLContext() { + if (m_currentWindow && m_currentWindow.data()->handle()) + static_cast(m_currentWindow.data()->handle())->setCurrentContext(0); + [m_context release]; } @@ -330,14 +331,6 @@ bool QCocoaGLContext::makeCurrent(QPlatformSurface *surface) qCDebug(lcQpaOpenGLContext) << "Making" << m_context << "current" << "in" << QThread::currentThread() << "for" << surface; - // No need to make context current if it already is. This also ensures - // that we only lock the context once, meaning we don't need to keep - // track of how many times we've locked it to undo it in doneCurrent(). - // Note that we're not using QOpenGLContext::currentContext() here, as - // that has already been updated to match context() before this call. - if ([NSOpenGLContext currentContext] == m_context) - return true; - Q_ASSERT(surface->surface()->supportsOpenGL()); if (surface->surface()->surfaceClass() == QSurface::Offscreen) { @@ -345,14 +338,11 @@ bool QCocoaGLContext::makeCurrent(QPlatformSurface *surface) return true; } - if (!setDrawable(surface)) + QWindow *window = static_cast(surface)->window(); + if (!setActiveWindow(window)) { + qCDebug(lcQpaOpenGLContext) << "Failed to activate window, skipping makeCurrent"; return false; - - // The context may be owned and used by a dedicated render thread, but - // we will get notifications that trigger update() on the main thread, - // so we need to guard against concurrent uses of the context. We hold - // this lock until swapBuffer() or doneCurrent() gets called. - CGLLockContext(m_context.CGLContextObj); + } [m_context makeCurrentContext]; @@ -373,74 +363,43 @@ bool QCocoaGLContext::makeCurrent(QPlatformSurface *surface) } } + update(); return true; } -/*! - Sets the drawable object of the NSOpenGLContext, which is the - frame buffer that is the target of OpenGL drawing operations. -*/ -bool QCocoaGLContext::setDrawable(QPlatformSurface *surface) +bool QCocoaGLContext::setActiveWindow(QWindow *window) { - Q_ASSERT(surface->surface()->surfaceClass() == QSurface::Window); - NSView *view = static_cast(surface)->view(); - - if (view == m_context.view) + if (window == m_currentWindow.data()) return true; - m_observers.clear(); + Q_ASSERT(window->handle()); + QCocoaWindow *cocoaWindow = static_cast(window->handle()); + NSView *view = cocoaWindow->view(); if ((m_context.view = view) != view) { - qCInfo(lcQpaOpenGLContext) << "Failed to set" << view << "as drawable for" << m_context; + qCDebug(lcQpaOpenGLContext) << "Associating" << view << "with" << m_context << "failed"; return false; } - qCInfo(lcQpaOpenGLContext) << "Set drawable for" << m_context << "to" << m_context.view; - - auto updateCallback = [&]() { update(); }; + qCDebug(lcQpaOpenGLContext) << m_context << "now associated with" << m_context.view; - if (view.layer) { - m_observers.append(QMacScopedObserver(view, NSViewFrameDidChangeNotification, updateCallback)); - m_observers.append(QMacScopedObserver(view.window, NSWindowDidChangeScreenNotification, updateCallback)); - } else { - m_observers.append(QMacScopedObserver(view, NSViewGlobalFrameDidChangeNotification, updateCallback)); - } + if (m_currentWindow && m_currentWindow.data()->handle()) + static_cast(m_currentWindow.data()->handle())->setCurrentContext(0); - m_observers.append(QMacScopedObserver([NSApplication sharedApplication], - NSApplicationDidChangeScreenParametersNotification, updateCallback)); + m_currentWindow = window; + cocoaWindow->setCurrentContext(this); return true; } -// NSOpenGLContext is not re-entrant, which means that even when using separate -// contexts per thread, per view, and window, calls into the API will still deadlock. -// Note that this is different from the use of CGLLockContext and CGLUnlockContext -// to prevent concurrent access to the _same_ context from two different threads. -// The latter is expected due to NSOpenGLContext not being thread-safe, while the -// former is working around bugs in NSOpenGLContext that make it not re-entrant. -// For more information see https://openradar.appspot.com/37064579 +// NSOpenGLContext is not re-entrant (https://openradar.appspot.com/37064579) static QMutex s_contextMutex; void QCocoaGLContext::update() { - // Updating the context may result in a call to [NSSurface setFrame:], which - // will recurse back here through NSViewGlobalFrameDidChangeNotification. We - // could use a recursive mutex to prevent a deadlock, but since they are slower - // we opt for a manual recursion check. - static QAtomicPointer updatingThread = nullptr; - if (updatingThread == QThread::currentThreadId()) - return; - - // Guard against concurrent access to the context in the case where there - // is a dedicated render thread operating on the context. See makeCurrent(). - CGLLockContext(m_context.CGLContextObj); - QMutexLocker locker(&s_contextMutex); - QScopedValueRollback> rollback(updatingThread, QThread::currentThreadId()); qCInfo(lcQpaOpenGLContext) << "Updating" << m_context << "for" << m_context.view; [m_context update]; - - CGLUnlockContext(m_context.CGLContextObj); } void QCocoaGLContext::swapBuffers(QPlatformSurface *surface) @@ -451,52 +410,37 @@ void QCocoaGLContext::swapBuffers(QPlatformSurface *surface) if (surface->surface()->surfaceClass() == QSurface::Offscreen) return; // Nothing to do - if (!setDrawable(surface)) { - qCWarning(lcQpaOpenGLContext) << "Can't flush" << m_context - << "without" << surface << "as drawable"; + QWindow *window = static_cast(surface)->window(); + if (!setActiveWindow(window)) { + qCWarning(lcQpaOpenGLContext) << "Failed to activate window, skipping swapBuffers"; return; } QMutexLocker locker(&s_contextMutex); [m_context flushBuffer]; - - // We're done flushing, and should release the lock we have on the - // context. To ensure that we're not leaving the context current - // without a lock held on it, we need to couple this with actually - // clearing the context. This should not be a performance hit for the - // case where the same context is made current and then cleared, and - // QOpenGLContext::swapBuffers is documented as requiring makeCurrent - // again before beginning a new frame, so the user can't expect the - // context to be current after a call to swapBuffers(). We explicitly - // go via QOpenGLContext for this, instead of calling our platform - // method directly, as that will ensure QOpenGLContext records the - // fact that there is no longer a current context. We then end up - // in QCocoaGLContext::doneCurrent, where we clear the lock. - context()->doneCurrent(); } void QCocoaGLContext::doneCurrent() { - auto currentContext = QOpenGLContext::currentContext(); - if (!currentContext) - return; - - // QOpenGLContext::doneCurrent() clears the current context, but can - // be called on any context, not necessarily the current one. Since - // we rely on unlocking the context lock we must propagate the call - // to the right context. - if (context() != currentContext) { - currentContext->doneCurrent(); - return; - } - - Q_ASSERT([NSOpenGLContext currentContext] == m_context); - qCDebug(lcQpaOpenGLContext) << "Clearing current context" << [NSOpenGLContext currentContext] << "in" << QThread::currentThread(); + if (m_currentWindow && m_currentWindow.data()->handle()) + static_cast(m_currentWindow.data()->handle())->setCurrentContext(nullptr); + + m_currentWindow.clear(); + [NSOpenGLContext clearCurrentContext]; - CGLUnlockContext(m_context.CGLContextObj); +} + +void QCocoaGLContext::windowWasHidden() +{ + // If the window is hidden, we need to unset the m_currentWindow + // variable so that succeeding makeCurrent's will not abort prematurely + // because of the optimization in setActiveWindow. + // Doing a full doneCurrent here is not preferable, because the GL context + // might be rendering in a different thread at this time. + m_currentWindow.clear(); } QSurfaceFormat QCocoaGLContext::format() const diff --git a/src/plugins/platforms/cocoa/qcocoanativeinterface.mm b/src/plugins/platforms/cocoa/qcocoanativeinterface.mm index 7979e430ac..228df50d86 100644 --- a/src/plugins/platforms/cocoa/qcocoanativeinterface.mm +++ b/src/plugins/platforms/cocoa/qcocoanativeinterface.mm @@ -102,6 +102,10 @@ void *QCocoaNativeInterface::nativeResourceForWindow(const QByteArray &resourceS if (resourceString == "nsview") { return static_cast(window->handle())->m_view; +#ifndef QT_NO_OPENGL + } else if (resourceString == "nsopenglcontext") { + return static_cast(window->handle())->currentContext()->nativeContext(); +#endif } else if (resourceString == "nswindow") { return static_cast(window->handle())->nativeWindow(); #if QT_CONFIG(vulkan) diff --git a/src/plugins/platforms/cocoa/qcocoawindow.h b/src/plugins/platforms/cocoa/qcocoawindow.h index 8f1bdb8af0..225c7eda84 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.h +++ b/src/plugins/platforms/cocoa/qcocoawindow.h @@ -169,6 +169,11 @@ public: NSUInteger windowStyleMask(Qt::WindowFlags flags); void setWindowZoomButton(Qt::WindowFlags flags); +#ifndef QT_NO_OPENGL + void setCurrentContext(QCocoaGLContext *context); + QCocoaGLContext *currentContext() const; +#endif + bool setWindowModified(bool modified) override; void setFrameStrutEventsEnabled(bool enabled) override; @@ -248,6 +253,9 @@ public: // for QNSView bool m_inSetVisible; bool m_inSetGeometry; bool m_inSetStyleMask; +#ifndef QT_NO_OPENGL + QCocoaGLContext *m_glContext; +#endif QCocoaMenuBar *m_menubar; bool m_needsInvalidateShadow; diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm index b79804fd0b..3148501006 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.mm +++ b/src/plugins/platforms/cocoa/qcocoawindow.mm @@ -41,6 +41,9 @@ #include "qcocoascreen.h" #include "qnswindowdelegate.h" #include "qcocoaeventdispatcher.h" +#ifndef QT_NO_OPENGL +#include "qcocoaglcontext.h" +#endif #include "qcocoahelpers.h" #include "qcocoanativeinterface.h" #include "qnsview.h" @@ -148,6 +151,9 @@ QCocoaWindow::QCocoaWindow(QWindow *win, WId nativeHandle) , m_inSetVisible(false) , m_inSetGeometry(false) , m_inSetStyleMask(false) +#ifndef QT_NO_OPENGL + , m_glContext(nullptr) +#endif , m_menubar(nullptr) , m_needsInvalidateShadow(false) , m_hasModalSession(false) @@ -397,6 +403,10 @@ void QCocoaWindow::setVisible(bool visible) [m_view setHidden:NO]; } else { // qDebug() << "close" << this; +#ifndef QT_NO_OPENGL + if (m_glContext) + m_glContext->windowWasHidden(); +#endif QCocoaEventDispatcher *cocoaEventDispatcher = qobject_cast(QGuiApplication::instance()->eventDispatcher()); QCocoaEventDispatcherPrivate *cocoaEventDispatcherPrivate = nullptr; if (cocoaEventDispatcher) @@ -1324,6 +1334,18 @@ bool QCocoaWindow::windowIsPopupType(Qt::WindowType type) const return ((type & Qt::Popup) == Qt::Popup); } +#ifndef QT_NO_OPENGL +void QCocoaWindow::setCurrentContext(QCocoaGLContext *context) +{ + m_glContext = context; +} + +QCocoaGLContext *QCocoaWindow::currentContext() const +{ + return m_glContext; +} +#endif + /*! Checks if the window is the content view of its immediate NSWindow. -- cgit v1.2.3 From b7dcc3455f1270cef3b21699e909ef502374db97 Mon Sep 17 00:00:00 2001 From: Gatis Paeglis Date: Sat, 28 Jul 2018 14:40:12 +0200 Subject: xcb: Use functors in QXcbConnection::checkEvent() ... to check for buffered events. This makes the code less verbose and easier to read. Changed the filter signature to pass an event type in addition to the actual event, for the convenience of API user. And do not pass worthless nullptr-s to the filter. The only reason why KeyChecker from qxcbkeyboard.cpp was not converted to lambda expression is that the code looks suspicious - KeyChecker::m_release default value is 'true' and I don't see where it would ever be assigned 'false' (ref. QTBUG-69679) and the code is known to be buggy (ref. QTBUG-57335). Those issues are out-of-scope for this patch. Change-Id: If2fdd60fbb93eb983f3c9ad616aaf04834fede9f Reviewed-by: Shawn Rutledge Reviewed-by: Mikhail Svetkin --- src/plugins/platforms/xcb/qxcbclipboard.cpp | 79 +++++++--------------- src/plugins/platforms/xcb/qxcbclipboard.h | 2 +- src/plugins/platforms/xcb/qxcbconnection.cpp | 43 ++++-------- src/plugins/platforms/xcb/qxcbconnection.h | 14 ++-- src/plugins/platforms/xcb/qxcbdrag.cpp | 14 ++-- src/plugins/platforms/xcb/qxcbkeyboard.cpp | 6 +- src/plugins/platforms/xcb/qxcbwindow.cpp | 98 ++++++++-------------------- src/plugins/platforms/xcb/qxcbwindow.h | 2 - 8 files changed, 80 insertions(+), 178 deletions(-) (limited to 'src/plugins') diff --git a/src/plugins/platforms/xcb/qxcbclipboard.cpp b/src/plugins/platforms/xcb/qxcbclipboard.cpp index 24eb13326c..7b1cca4070 100644 --- a/src/plugins/platforms/xcb/qxcbclipboard.cpp +++ b/src/plugins/platforms/xcb/qxcbclipboard.cpp @@ -807,73 +807,44 @@ bool QXcbClipboard::clipboardReadProperty(xcb_window_t win, xcb_atom_t property, return ok; } - -namespace +xcb_generic_event_t *QXcbClipboard::waitForClipboardEvent(xcb_window_t window, int type, int timeout, bool checkManager) { - class Notify { - public: - Notify(xcb_window_t win, int t) - : window(win), type(t) {} - xcb_window_t window; - int type; - bool checkEvent(xcb_generic_event_t *event) const { - if (!event) - return false; - int t = event->response_type & 0x7f; - if (t != type) + QElapsedTimer timer; + timer.start(); + do { + auto e = connection()->checkEvent([window, type](xcb_generic_event_t *event, int eventType) { + if (eventType != type) return false; - if (t == XCB_PROPERTY_NOTIFY) { - xcb_property_notify_event_t *pn = (xcb_property_notify_event_t *)event; - if (pn->window == window) + if (eventType == XCB_PROPERTY_NOTIFY) { + auto propertyNotify = reinterpret_cast(event); + if (propertyNotify->window == window) return true; - } else if (t == XCB_SELECTION_NOTIFY) { - xcb_selection_notify_event_t *sn = (xcb_selection_notify_event_t *)event; - if (sn->requestor == window) + } else if (eventType == XCB_SELECTION_NOTIFY) { + auto selectionNotify = reinterpret_cast(event); + if (selectionNotify->requestor == window) return true; } return false; - } - }; - class ClipboardEvent { - public: - ClipboardEvent(QXcbConnection *c) - { clipboard = c->internAtom("CLIPBOARD"); } - xcb_atom_t clipboard; - bool checkEvent(xcb_generic_event_t *e) const { - if (!e) - return false; - int type = e->response_type & 0x7f; - if (type == XCB_SELECTION_REQUEST) { - xcb_selection_request_event_t *sr = (xcb_selection_request_event_t *)e; - return sr->selection == XCB_ATOM_PRIMARY || sr->selection == clipboard; - } else if (type == XCB_SELECTION_CLEAR) { - xcb_selection_clear_event_t *sc = (xcb_selection_clear_event_t *)e; - return sc->selection == XCB_ATOM_PRIMARY || sc->selection == clipboard; - } - return false; - } - }; -} - -xcb_generic_event_t *QXcbClipboard::waitForClipboardEvent(xcb_window_t win, int type, int timeout, bool checkManager) -{ - QElapsedTimer timer; - timer.start(); - do { - Notify notify(win, type); - xcb_generic_event_t *e = connection()->checkEvent(notify); - if (e) + }); + if (e) // found the waited for event return e; if (checkManager) { auto reply = Q_XCB_REPLY(xcb_get_selection_owner, xcb_connection(), atom(QXcbAtom::CLIPBOARD_MANAGER)); if (!reply || reply->owner == XCB_NONE) - return 0; + return nullptr; } // process other clipboard events, since someone is probably requesting data from us - ClipboardEvent clipboard(connection()); - e = connection()->checkEvent(clipboard); + auto clipboardAtom = connection()->internAtom("CLIPBOARD"); + e = connection()->checkEvent([clipboardAtom](xcb_generic_event_t *event, int type) { + xcb_atom_t selection = XCB_ATOM_NONE; + if (type == XCB_SELECTION_REQUEST) + selection = reinterpret_cast(event)->selection; + else if (type == XCB_SELECTION_CLEAR) + selection = reinterpret_cast(event)->selection; + return selection == XCB_ATOM_PRIMARY || selection == clipboardAtom; + }); if (e) { connection()->handleXcbEvent(e); free(e); @@ -885,7 +856,7 @@ xcb_generic_event_t *QXcbClipboard::waitForClipboardEvent(xcb_window_t win, int QThread::msleep(50); } while (timer.elapsed() < timeout); - return 0; + return nullptr; } QByteArray QXcbClipboard::clipboardReadIncrementalProperty(xcb_window_t win, xcb_atom_t property, int nbytes, bool nullterm) diff --git a/src/plugins/platforms/xcb/qxcbclipboard.h b/src/plugins/platforms/xcb/qxcbclipboard.h index bfeae13e10..8d0df39ac8 100644 --- a/src/plugins/platforms/xcb/qxcbclipboard.h +++ b/src/plugins/platforms/xcb/qxcbclipboard.h @@ -89,7 +89,7 @@ public: QByteArray getSelection(xcb_atom_t selection, xcb_atom_t target, xcb_atom_t property, xcb_timestamp_t t = 0); private: - xcb_generic_event_t *waitForClipboardEvent(xcb_window_t win, int type, int timeout, bool checkManager = false); + xcb_generic_event_t *waitForClipboardEvent(xcb_window_t window, int type, int timeout, bool checkManager = false); xcb_atom_t sendTargetsSelection(QMimeData *d, xcb_window_t window, xcb_atom_t property); xcb_atom_t sendSelection(QMimeData *d, xcb_atom_t target, xcb_window_t window, xcb_atom_t property); diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp index c14f3f3703..1a5d9d1667 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.cpp +++ b/src/plugins/platforms/xcb/qxcbconnection.cpp @@ -1484,54 +1484,35 @@ void QXcbConnection::sendConnectionEvent(QXcbAtom::Atom a, uint id) xcb_flush(xcb_connection()); } -namespace -{ - class PropertyNotifyEvent { - public: - PropertyNotifyEvent(xcb_window_t win, xcb_atom_t property) - : window(win), type(XCB_PROPERTY_NOTIFY), atom(property) {} - xcb_window_t window; - int type; - xcb_atom_t atom; - bool checkEvent(xcb_generic_event_t *event) const { - if (!event) - return false; - if ((event->response_type & ~0x80) != type) { - return false; - } else { - xcb_property_notify_event_t *pn = reinterpret_cast(event); - if ((pn->window == window) && (pn->atom == atom)) - return true; - } - return false; - } - }; -} - xcb_timestamp_t QXcbConnection::getTimestamp() { // send a dummy event to myself to get the timestamp from X server. - xcb_window_t root_win = rootWindow(); - xcb_change_property(xcb_connection(), XCB_PROP_MODE_APPEND, root_win, atom(QXcbAtom::CLIP_TEMPORARY), - XCB_ATOM_INTEGER, 32, 0, NULL); + xcb_window_t window = rootWindow(); + xcb_atom_t dummyAtom = atom(QXcbAtom::CLIP_TEMPORARY); + xcb_change_property(xcb_connection(), XCB_PROP_MODE_APPEND, window, dummyAtom, + XCB_ATOM_INTEGER, 32, 0, nullptr); connection()->flush(); - PropertyNotifyEvent checker(root_win, atom(QXcbAtom::CLIP_TEMPORARY)); - xcb_generic_event_t *event = 0; + xcb_generic_event_t *event = nullptr; // lets keep this inside a loop to avoid a possible race condition, where // reader thread has not yet had the time to acquire the mutex in order // to add the new set of events to its event queue while (!event) { connection()->sync(); - event = checkEvent(checker); + event = checkEvent([window, dummyAtom](xcb_generic_event_t *event, int type) { + if (type != XCB_PROPERTY_NOTIFY) + return false; + auto propertyNotify = reinterpret_cast(event); + return propertyNotify->window == window && propertyNotify->atom == dummyAtom; + }); } xcb_property_notify_event_t *pn = reinterpret_cast(event); xcb_timestamp_t timestamp = pn->time; free(event); - xcb_delete_property(xcb_connection(), root_win, atom(QXcbAtom::CLIP_TEMPORARY)); + xcb_delete_property(xcb_connection(), window, dummyAtom); return timestamp; } diff --git a/src/plugins/platforms/xcb/qxcbconnection.h b/src/plugins/platforms/xcb/qxcbconnection.h index 0b31e9c3e7..24719a6c31 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.h +++ b/src/plugins/platforms/xcb/qxcbconnection.h @@ -440,8 +440,8 @@ public: QXcbWindowEventListener *windowEventListenerFromId(xcb_window_t id); QXcbWindow *platformWindowFromId(xcb_window_t id); - template - inline xcb_generic_event_t *checkEvent(T &checker); + template + inline xcb_generic_event_t *checkEvent(Functor &&filter); typedef bool (*PeekFunc)(QXcbConnection *, xcb_generic_event_t *); void addPeekFunc(PeekFunc f); @@ -734,21 +734,21 @@ Q_DECLARE_TYPEINFO(QXcbConnection::TabletData, Q_MOVABLE_TYPE); #endif #endif -template -xcb_generic_event_t *QXcbConnection::checkEvent(T &checker) +template +xcb_generic_event_t *QXcbConnection::checkEvent(Functor &&filter) { QXcbEventArray *eventqueue = m_reader->lock(); for (int i = 0; i < eventqueue->size(); ++i) { xcb_generic_event_t *event = eventqueue->at(i); - if (checker.checkEvent(event)) { - (*eventqueue)[i] = 0; + if (event && filter(event, event->response_type & ~0x80)) { + (*eventqueue)[i] = nullptr; m_reader->unlock(); return event; } } m_reader->unlock(); - return 0; + return nullptr; } class QXcbConnectionGrabber diff --git a/src/plugins/platforms/xcb/qxcbdrag.cpp b/src/plugins/platforms/xcb/qxcbdrag.cpp index 0d72da0701..2b8e507f30 100644 --- a/src/plugins/platforms/xcb/qxcbdrag.cpp +++ b/src/plugins/platforms/xcb/qxcbdrag.cpp @@ -781,12 +781,11 @@ namespace public: ClientMessageScanner(xcb_atom_t a) : atom(a) {} xcb_atom_t atom; - bool checkEvent(xcb_generic_event_t *event) const { - if (!event) + bool operator() (xcb_generic_event_t *event, int type) const { + if (type != XCB_CLIENT_MESSAGE) return false; - if ((event->response_type & 0x7f) != XCB_CLIENT_MESSAGE) - return false; - return ((xcb_client_message_event_t *)event)->type == atom; + auto clientMessage = reinterpret_cast(event); + return clientMessage->type == atom; } }; } @@ -794,12 +793,11 @@ namespace void QXcbDrag::handlePosition(QPlatformWindow * w, const xcb_client_message_event_t *event) { xcb_client_message_event_t *lastEvent = const_cast(event); - xcb_generic_event_t *nextEvent; ClientMessageScanner scanner(atom(QXcbAtom::XdndPosition)); - while ((nextEvent = connection()->checkEvent(scanner))) { + while (auto nextEvent = connection()->checkEvent(scanner)) { if (lastEvent != event) free(lastEvent); - lastEvent = (xcb_client_message_event_t *)nextEvent; + lastEvent = reinterpret_cast(nextEvent); } handle_xdnd_position(w, lastEvent); diff --git a/src/plugins/platforms/xcb/qxcbkeyboard.cpp b/src/plugins/platforms/xcb/qxcbkeyboard.cpp index 5a2dac4a5a..37c8def6cc 100644 --- a/src/plugins/platforms/xcb/qxcbkeyboard.cpp +++ b/src/plugins/platforms/xcb/qxcbkeyboard.cpp @@ -1485,12 +1485,11 @@ public: { } - bool checkEvent(xcb_generic_event_t *ev) + bool operator() (xcb_generic_event_t *ev, int type) { if (m_error || !ev) return false; - int type = ev->response_type & ~0x80; if (type != XCB_KEY_PRESS && type != XCB_KEY_RELEASE) return false; @@ -1517,9 +1516,6 @@ public: return false; } - bool release() const { return m_release; } - xcb_timestamp_t time() const { return m_time; } - private: xcb_window_t m_window; xcb_keycode_t m_code; diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp index e313e2f648..9c589771d0 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.cpp +++ b/src/plugins/platforms/xcb/qxcbwindow.cpp @@ -1809,53 +1809,6 @@ bool QXcbWindow::requestSystemTrayWindowDock() return true; } -class ExposeCompressor -{ -public: - ExposeCompressor(xcb_window_t window, QRegion *region) - : m_window(window) - , m_region(region) - , m_pending(true) - { - } - - bool checkEvent(xcb_generic_event_t *event) - { - if (!event) - return false; - if ((event->response_type & ~0x80) != XCB_EXPOSE) - return false; - xcb_expose_event_t *expose = (xcb_expose_event_t *)event; - if (expose->window != m_window) - return false; - if (expose->count == 0) - m_pending = false; - *m_region |= QRect(expose->x, expose->y, expose->width, expose->height); - return true; - } - - bool pending() const - { - return m_pending; - } - -private: - xcb_window_t m_window; - QRegion *m_region; - bool m_pending; -}; - -bool QXcbWindow::compressExposeEvent(QRegion &exposeRegion) -{ - ExposeCompressor compressor(m_window, &exposeRegion); - xcb_generic_event_t *filter = 0; - do { - filter = connection()->checkEvent(compressor); - free(filter); - } while (filter); - return compressor.pending(); -} - bool QXcbWindow::handleGenericEvent(xcb_generic_event_t *event, long *result) { return QWindowSystemInterface::handleNativeEvent(window(), @@ -1867,9 +1820,24 @@ bool QXcbWindow::handleGenericEvent(xcb_generic_event_t *event, long *result) void QXcbWindow::handleExposeEvent(const xcb_expose_event_t *event) { QRect rect(event->x, event->y, event->width, event->height); - m_exposeRegion |= rect; - bool pending = compressExposeEvent(m_exposeRegion); + + bool pending = true; + xcb_generic_event_t *e = nullptr; + do { // compress expose events + e = connection()->checkEvent([this, &pending](xcb_generic_event_t *event, int type) { + if (type != XCB_EXPOSE) + return false; + auto expose = reinterpret_cast(event); + if (expose->window != m_window) + return false; + if (expose->count == 0) + pending = false; + m_exposeRegion |= QRect(expose->x, expose->y, expose->width, expose->height); + return true; + }); + free(e); + } while (e); // if count is non-zero there are more expose events pending if (event->count == 0 || !pending) { @@ -2162,24 +2130,6 @@ static bool ignoreEnterEvent(quint8 mode, quint8 detail, QXcbConnection *conn = || detail == XCB_NOTIFY_DETAIL_NONLINEAR_VIRTUAL); } -class EnterEventChecker -{ -public: - bool checkEvent(xcb_generic_event_t *event) - { - if (!event) - return false; - if ((event->response_type & ~0x80) != XCB_ENTER_NOTIFY) - return false; - - xcb_enter_notify_event_t *enter = (xcb_enter_notify_event_t *)event; - if (ignoreEnterEvent(enter->mode, enter->detail)) - return false; - - return true; - } -}; - void QXcbWindow::handleEnterNotifyEvent(int event_x, int event_y, int root_x, int root_y, quint8 mode, quint8 detail, xcb_timestamp_t timestamp) { @@ -2206,9 +2156,17 @@ void QXcbWindow::handleLeaveNotifyEvent(int root_x, int root_y, if (ignoreLeaveEvent(mode, detail, connection()) || connection()->mousePressWindow()) return; - EnterEventChecker checker; - xcb_enter_notify_event_t *enter = (xcb_enter_notify_event_t *)connection()->checkEvent(checker); - QXcbWindow *enterWindow = enter ? connection()->platformWindowFromId(enter->event) : 0; + // check if enter event is buffered + auto event = connection()->checkEvent([](xcb_generic_event_t *event, int type) { + if (type != XCB_ENTER_NOTIFY) + return false; + auto enter = reinterpret_cast(event); + if (ignoreEnterEvent(enter->mode, enter->detail)) + return false; + return true; + }); + auto enter = reinterpret_cast(event); + QXcbWindow *enterWindow = enter ? connection()->platformWindowFromId(enter->event) : nullptr; if (enterWindow) { QPoint local(enter->event_x, enter->event_y); diff --git a/src/plugins/platforms/xcb/qxcbwindow.h b/src/plugins/platforms/xcb/qxcbwindow.h index 047ee2eae9..128c6e126d 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.h +++ b/src/plugins/platforms/xcb/qxcbwindow.h @@ -217,8 +217,6 @@ protected: void doFocusIn(); void doFocusOut(); - bool compressExposeEvent(QRegion &exposeRegion); - void handleButtonPressEvent(int event_x, int event_y, int root_x, int root_y, int detail, Qt::KeyboardModifiers modifiers, xcb_timestamp_t timestamp, QEvent::Type type, Qt::MouseEventSource source = Qt::MouseEventNotSynthesized); -- cgit v1.2.3 From f79cb977e672949a2b42206c407a9f9ba7d8d544 Mon Sep 17 00:00:00 2001 From: Gatis Paeglis Date: Sat, 28 Jul 2018 21:47:28 +0200 Subject: xcb: remove redudant timeout arg from QXcbClipboard::waitForClipboardEvent ... clipboard_timeout is QXcbClipboard class member, accessible directly from QXcbClipboard::waitForClipboardEvent(). Change-Id: Ibc241d1da4baedc0eaf84063251a1359b1cf4162 Reviewed-by: Laszlo Agocs --- src/plugins/platforms/xcb/qxcbclipboard.cpp | 10 +++++----- src/plugins/platforms/xcb/qxcbclipboard.h | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'src/plugins') diff --git a/src/plugins/platforms/xcb/qxcbclipboard.cpp b/src/plugins/platforms/xcb/qxcbclipboard.cpp index 7b1cca4070..4be0f31b4d 100644 --- a/src/plugins/platforms/xcb/qxcbclipboard.cpp +++ b/src/plugins/platforms/xcb/qxcbclipboard.cpp @@ -305,7 +305,7 @@ QXcbClipboard::~QXcbClipboard() connection()->sync(); // waiting until the clipboard manager fetches the content. - if (!waitForClipboardEvent(m_owner, XCB_SELECTION_NOTIFY, clipboard_timeout, true)) { + if (!waitForClipboardEvent(m_owner, XCB_SELECTION_NOTIFY, true)) { qWarning("QXcbClipboard: Unable to receive an event from the " "clipboard manager in a reasonable time"); } @@ -807,7 +807,7 @@ bool QXcbClipboard::clipboardReadProperty(xcb_window_t win, xcb_atom_t property, return ok; } -xcb_generic_event_t *QXcbClipboard::waitForClipboardEvent(xcb_window_t window, int type, int timeout, bool checkManager) +xcb_generic_event_t *QXcbClipboard::waitForClipboardEvent(xcb_window_t window, int type, bool checkManager) { QElapsedTimer timer; timer.start(); @@ -854,7 +854,7 @@ xcb_generic_event_t *QXcbClipboard::waitForClipboardEvent(xcb_window_t window, i // sleep 50 ms, so we don't use up CPU cycles all the time. QThread::msleep(50); - } while (timer.elapsed() < timeout); + } while (timer.elapsed() < clipboard_timeout); return nullptr; } @@ -878,7 +878,7 @@ QByteArray QXcbClipboard::clipboardReadIncrementalProperty(xcb_window_t win, xcb for (;;) { connection()->flush(); - xcb_generic_event_t *ge = waitForClipboardEvent(win, XCB_PROPERTY_NOTIFY, clipboard_timeout); + xcb_generic_event_t *ge = waitForClipboardEvent(win, XCB_PROPERTY_NOTIFY); if (!ge) break; xcb_property_notify_event_t *event = (xcb_property_notify_event_t *)ge; @@ -941,7 +941,7 @@ QByteArray QXcbClipboard::getSelection(xcb_atom_t selection, xcb_atom_t target, connection()->sync(); - xcb_generic_event_t *ge = waitForClipboardEvent(win, XCB_SELECTION_NOTIFY, clipboard_timeout); + xcb_generic_event_t *ge = waitForClipboardEvent(win, XCB_SELECTION_NOTIFY); bool no_selection = !ge || ((xcb_selection_notify_event_t *)ge)->property == XCB_NONE; free(ge); diff --git a/src/plugins/platforms/xcb/qxcbclipboard.h b/src/plugins/platforms/xcb/qxcbclipboard.h index 8d0df39ac8..abab42a613 100644 --- a/src/plugins/platforms/xcb/qxcbclipboard.h +++ b/src/plugins/platforms/xcb/qxcbclipboard.h @@ -89,7 +89,7 @@ public: QByteArray getSelection(xcb_atom_t selection, xcb_atom_t target, xcb_atom_t property, xcb_timestamp_t t = 0); private: - xcb_generic_event_t *waitForClipboardEvent(xcb_window_t window, int type, int timeout, bool checkManager = false); + xcb_generic_event_t *waitForClipboardEvent(xcb_window_t window, int type, bool checkManager = false); xcb_atom_t sendTargetsSelection(QMimeData *d, xcb_window_t window, xcb_atom_t property); xcb_atom_t sendSelection(QMimeData *d, xcb_atom_t target, xcb_window_t window, xcb_atom_t property); -- cgit v1.2.3 From 279edd52548b2b3d0fb0566157de148d1d0ddbaf Mon Sep 17 00:00:00 2001 From: Gatis Paeglis Date: Sat, 11 Aug 2018 16:55:47 +0200 Subject: xcb: remove a redundant call to xcb_change_window_attributes() Few lines above we use the same attributes to create the window. If attributes don't change, there is not need to call xcb_change_window_attributes() Change-Id: I1335b8be866bdd9911d7911c87f09091bf77e955 Reviewed-by: Shawn Rutledge --- src/plugins/platforms/xcb/qxcbwindow.cpp | 2 -- 1 file changed, 2 deletions(-) (limited to 'src/plugins') diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp index 9c589771d0..fd0d2f9f07 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.cpp +++ b/src/plugins/platforms/xcb/qxcbwindow.cpp @@ -437,8 +437,6 @@ void QXcbWindow::create() connection()->addWindowEventListener(m_window, this); - xcb_change_window_attributes(xcb_connection(), m_window, mask, values); - propagateSizeHints(); xcb_atom_t properties[5]; -- cgit v1.2.3 From 32e21762fa58be2459c43fe17ec87bd302d04d59 Mon Sep 17 00:00:00 2001 From: Gatis Paeglis Date: Wed, 8 Aug 2018 11:58:19 +0200 Subject: xcb: remove unused xcb_icccm.h include from qxcbclipboard.cpp Change-Id: I7afe3bece5f143f6040cf1009d6345c1fe430367 Reviewed-by: Shawn Rutledge --- src/plugins/platforms/xcb/qxcbclipboard.cpp | 4 ---- 1 file changed, 4 deletions(-) (limited to 'src/plugins') diff --git a/src/plugins/platforms/xcb/qxcbclipboard.cpp b/src/plugins/platforms/xcb/qxcbclipboard.cpp index 4be0f31b4d..ca2eff170d 100644 --- a/src/plugins/platforms/xcb/qxcbclipboard.cpp +++ b/src/plugins/platforms/xcb/qxcbclipboard.cpp @@ -49,10 +49,6 @@ #include -#define class class_name // Workaround XCB-ICCCM 3.8 breakage -#include -#undef class - QT_BEGIN_NAMESPACE #ifndef QT_NO_CLIPBOARD -- cgit v1.2.3 From 21f976f4f0f79b1c4c77a402ebed88d8afb3d9e1 Mon Sep 17 00:00:00 2001 From: Gatis Paeglis Date: Sat, 4 Aug 2018 00:47:14 +0200 Subject: xcb: rewrite auto-repeat key detection logic It's unclear what the original code was doing. It relied on 'm_release' which could never be 'false' (ref. QTBUG-69679). It was subtracting event times and comparing with arbitrary '10'. On X11 auto-repeat keys can be detected by checking time and keycode of the current release event and the next event in the queue. If an event is an auto-repeat, then next event in the queue will be a key press with matching time and keycode. Verified that auto-repeat was unreliable in Qt 4 as well. With this patch auto-repeat works as expected. Added support for Xlib's XPeekEvent in our XCB implementation QXcbConnection::checkEvent(): "The XPeekEvent() function returns the first event from the event queue, but it does not remove the event from the queue." Sneaking in one variable renaming: "string" -> "text", to match the QKeyEvent::text(). Task-number: QTBUG-57335 Task-number: QTBUG-69679 Change-Id: I0a23f138287f57eaaecf1a009bd939e7e0e23269 Reviewed-by: Shawn Rutledge --- src/plugins/platforms/xcb/qxcbconnection.h | 7 +- src/plugins/platforms/xcb/qxcbkeyboard.cpp | 108 ++++++----------------------- src/plugins/platforms/xcb/qxcbkeyboard.h | 3 +- 3 files changed, 26 insertions(+), 92 deletions(-) (limited to 'src/plugins') diff --git a/src/plugins/platforms/xcb/qxcbconnection.h b/src/plugins/platforms/xcb/qxcbconnection.h index 24719a6c31..697b509bf0 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.h +++ b/src/plugins/platforms/xcb/qxcbconnection.h @@ -441,7 +441,7 @@ public: QXcbWindow *platformWindowFromId(xcb_window_t id); template - inline xcb_generic_event_t *checkEvent(Functor &&filter); + inline xcb_generic_event_t *checkEvent(Functor &&filter, bool removeFromQueue = true); typedef bool (*PeekFunc)(QXcbConnection *, xcb_generic_event_t *); void addPeekFunc(PeekFunc f); @@ -735,14 +735,15 @@ Q_DECLARE_TYPEINFO(QXcbConnection::TabletData, Q_MOVABLE_TYPE); #endif template -xcb_generic_event_t *QXcbConnection::checkEvent(Functor &&filter) +xcb_generic_event_t *QXcbConnection::checkEvent(Functor &&filter, bool removeFromQueue) { QXcbEventArray *eventqueue = m_reader->lock(); for (int i = 0; i < eventqueue->size(); ++i) { xcb_generic_event_t *event = eventqueue->at(i); if (event && filter(event, event->response_type & ~0x80)) { - (*eventqueue)[i] = nullptr; + if (removeFromQueue) + (*eventqueue)[i] = nullptr; m_reader->unlock(); return event; } diff --git a/src/plugins/platforms/xcb/qxcbkeyboard.cpp b/src/plugins/platforms/xcb/qxcbkeyboard.cpp index 37c8def6cc..40100c3a62 100644 --- a/src/plugins/platforms/xcb/qxcbkeyboard.cpp +++ b/src/plugins/platforms/xcb/qxcbkeyboard.cpp @@ -1472,60 +1472,6 @@ void QXcbKeyboard::resolveMaskConflicts() } } -class KeyChecker -{ -public: - KeyChecker(xcb_window_t window, xcb_keycode_t code, xcb_timestamp_t time, quint16 state) - : m_window(window) - , m_code(code) - , m_time(time) - , m_state(state) - , m_error(false) - , m_release(true) - { - } - - bool operator() (xcb_generic_event_t *ev, int type) - { - if (m_error || !ev) - return false; - - if (type != XCB_KEY_PRESS && type != XCB_KEY_RELEASE) - return false; - - xcb_key_press_event_t *event = (xcb_key_press_event_t *)ev; - - if (event->event != m_window || event->detail != m_code || event->state != m_state) { - m_error = true; - return false; - } - - if (type == XCB_KEY_PRESS) { - m_error = !m_release || event->time - m_time > 10; - return !m_error; - } - - if (m_release) { - m_error = true; - return false; - } - - m_release = true; - m_time = event->time; - - return false; - } - -private: - xcb_window_t m_window; - xcb_keycode_t m_code; - xcb_timestamp_t m_time; - quint16 m_state; - - bool m_error; - bool m_release; -}; - void QXcbKeyboard::handleKeyEvent(xcb_window_t sourceWindow, QEvent::Type type, xcb_keycode_t code, quint16 state, xcb_timestamp_t time, bool fromSendEvent) { @@ -1539,7 +1485,6 @@ void QXcbKeyboard::handleKeyEvent(xcb_window_t sourceWindow, QEvent::Type type, if (type == QEvent::KeyPress) targetWindow->updateNetWmUserTime(time); - ScopedXKBState sendEventState; if (fromSendEvent) { // Have a temporary keyboard state filled in from state @@ -1557,7 +1502,7 @@ void QXcbKeyboard::handleKeyEvent(xcb_window_t sourceWindow, QEvent::Type type, struct xkb_state *xkbState = fromSendEvent ? sendEventState.get() : m_xkbState.get(); xcb_keysym_t sym = xkb_state_key_get_one_sym(xkbState, code); - QString string = lookupString(xkbState, code); + QString text = lookupString(xkbState, code); Qt::KeyboardModifiers modifiers = translateModifiers(state); if (sym >= XKB_KEY_KP_Space && sym <= XKB_KEY_KP_9) @@ -1582,55 +1527,42 @@ void QXcbKeyboard::handleKeyEvent(xcb_window_t sourceWindow, QEvent::Type type, int qtcode = keysymToQtKey(latinKeysym != XKB_KEY_NoSymbol ? latinKeysym : sym, modifiers, xkbState, code); - bool isAutoRepeat = false; if (type == QEvent::KeyPress) { - if (m_autorepeat_code == code) { - isAutoRepeat = true; - m_autorepeat_code = 0; - } + if (m_isAutoRepeat && m_autoRepeatCode != code) + // Some other key was pressed while we are auto-repeating on a different key. + m_isAutoRepeat = false; } else { - // look ahead for auto-repeat - KeyChecker checker(source->xcb_window(), code, time, state); - xcb_generic_event_t *event = connection()->checkEvent(checker); - if (event) { - isAutoRepeat = true; - free(event); - } - m_autorepeat_code = isAutoRepeat ? code : 0; + m_isAutoRepeat = false; + // Look at the next event in the queue to see if we are auto-repeating. + connection()->checkEvent([this, time, code](xcb_generic_event_t *event, int type) { + if (type == XCB_KEY_PRESS) { + auto keyPress = reinterpret_cast(event); + m_isAutoRepeat = keyPress->time == time && keyPress->detail == code; + if (m_isAutoRepeat) + m_autoRepeatCode = code; + } + return true; + }, false /* removeFromQueue */); } bool filtered = false; - QPlatformInputContext *inputContext = QGuiApplicationPrivate::platformIntegration()->inputContext(); - if (inputContext) { - QKeyEvent event(type, qtcode, modifiers, code, sym, state, string, isAutoRepeat, string.length()); + if (auto inputContext = QGuiApplicationPrivate::platformIntegration()->inputContext()) { + QKeyEvent event(type, qtcode, modifiers, code, sym, state, text, m_isAutoRepeat, text.size()); event.setTimestamp(time); filtered = inputContext->filterEvent(&event); } - QWindow *window = targetWindow->window(); if (!filtered) { + QWindow *window = targetWindow->window(); #ifndef QT_NO_CONTEXTMENU if (type == QEvent::KeyPress && qtcode == Qt::Key_Menu) { const QPoint globalPos = window->screen()->handle()->cursor()->pos(); const QPoint pos = window->mapFromGlobal(globalPos); QWindowSystemInterface::handleContextMenuEvent(window, false, pos, globalPos, modifiers); } -#endif // QT_NO_CONTEXTMENU +#endif QWindowSystemInterface::handleExtendedKeyEvent(window, time, type, qtcode, modifiers, - code, sym, state, string, isAutoRepeat); - } - - if (isAutoRepeat && type == QEvent::KeyRelease) { - // since we removed it from the event queue using checkEvent we need to send the key press here - filtered = false; - if (inputContext) { - QKeyEvent event(QEvent::KeyPress, qtcode, modifiers, code, sym, state, string, isAutoRepeat, string.length()); - event.setTimestamp(time); - filtered = inputContext->filterEvent(&event); - } - if (!filtered) - QWindowSystemInterface::handleExtendedKeyEvent(window, time, QEvent::KeyPress, qtcode, modifiers, - code, sym, state, string, isAutoRepeat); + code, sym, state, text, m_isAutoRepeat); } } diff --git a/src/plugins/platforms/xcb/qxcbkeyboard.h b/src/plugins/platforms/xcb/qxcbkeyboard.h index ab926eab84..95915fb2e6 100644 --- a/src/plugins/platforms/xcb/qxcbkeyboard.h +++ b/src/plugins/platforms/xcb/qxcbkeyboard.h @@ -109,7 +109,8 @@ protected: private: bool m_config = false; - xcb_keycode_t m_autorepeat_code = 0; + bool m_isAutoRepeat = false; + xcb_keycode_t m_autoRepeatCode = 0; struct _mod_masks { uint alt; -- cgit v1.2.3 From f1a6b97fe2d3eda9455b13bb79828f250d46b92e Mon Sep 17 00:00:00 2001 From: Mikhail Svetkin Date: Sun, 29 Jul 2018 11:55:01 +0200 Subject: xcb: Add missing X11/XCB keysyms Undo, Redo, Find, Cancel It was added 558dd7f58735716d7d1f61fb5323d807b178f0c7 It was missed after 128a6eec065dfe683e6d776183d63908ca02e8fb Change-Id: I99f5c42ea45227bef08092e22d656e2d7d3cf60f Reviewed-by: Gatis Paeglis --- src/plugins/platforms/xcb/qxcbkeyboard.cpp | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'src/plugins') diff --git a/src/plugins/platforms/xcb/qxcbkeyboard.cpp b/src/plugins/platforms/xcb/qxcbkeyboard.cpp index 40100c3a62..20c169fc53 100644 --- a/src/plugins/platforms/xcb/qxcbkeyboard.cpp +++ b/src/plugins/platforms/xcb/qxcbkeyboard.cpp @@ -161,6 +161,13 @@ static constexpr const auto KeyTbl = qMakeArray( Xkb2Qt, Xkb2Qt, + // special non-XF86 function keys + + Xkb2Qt, + Xkb2Qt, + Xkb2Qt, + Xkb2Qt, + // International input method support keys // International & multi-key character composition -- cgit v1.2.3 From 0f6b941ca54f9714627b8d5a94be163dc02126c1 Mon Sep 17 00:00:00 2001 From: Gatis Paeglis Date: Mon, 30 Jul 2018 18:31:50 +0200 Subject: xcb: cleanup QXcbConnection::handleXcbEvent() - the usage of 'handled' variable was a mess. - remove "generic" from API names. The naming was probably influenced too much from underlying C API (xcb_generic_event_t): - handleGenericEvent() -> handleNativeEvent() to be consistent with QWindow::nativeEvent(). - dropped unnecessary 'long *result' from signature. It is useful only on MS Windows. - genericEventFilterType() -> nativeEventType(), it *is* an event type, not a filter type. - XCB_CLIENT_MESSAGE was not passed to QWindow::nativeEvent(), which is done via HANDLE_PLATFORM_WINDOW_EVENT. - minor: added some 'auto's where it makes sense and improved some variable names. Change-Id: Id1c9896054e2dbd9a79bacd88394149c8cf2cdea Reviewed-by: Shawn Rutledge --- .../gl_integrations/xcb_glx/qxcbglxintegration.cpp | 4 +- src/plugins/platforms/xcb/qxcbconnection.cpp | 367 ++++++++++----------- src/plugins/platforms/xcb/qxcbconnection.h | 3 +- src/plugins/platforms/xcb/qxcbconnection_xi2.cpp | 3 +- src/plugins/platforms/xcb/qxcbnativeinterface.cpp | 3 +- src/plugins/platforms/xcb/qxcbnativeinterface.h | 4 +- src/plugins/platforms/xcb/qxcbwindow.cpp | 9 +- src/plugins/platforms/xcb/qxcbwindow.h | 2 +- 8 files changed, 189 insertions(+), 206 deletions(-) (limited to 'src/plugins') diff --git a/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qxcbglxintegration.cpp b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qxcbglxintegration.cpp index a7641baea1..b751aaf8a3 100644 --- a/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qxcbglxintegration.cpp +++ b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qxcbglxintegration.cpp @@ -163,9 +163,9 @@ bool QXcbGlxIntegration::handleXcbEvent(xcb_generic_event_t *event, uint respons // Unlock the display before calling the native event filter XUnlockDisplay(xdisplay); locked = false; - QByteArray genericEventFilterType = m_connection->nativeInterface()->genericEventFilterType(); + auto eventType = m_connection->nativeInterface()->nativeEventType(); long result = 0; - handled = dispatcher->filterNativeEvent(genericEventFilterType, &ev, &result); + handled = dispatcher->filterNativeEvent(eventType, &ev, &result); } #endif } diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp index 1a5d9d1667..75275f6fd2 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.cpp +++ b/src/plugins/platforms/xcb/qxcbconnection.cpp @@ -733,22 +733,22 @@ QXcbWindow *QXcbConnection::platformWindowFromId(xcb_window_t id) #define HANDLE_PLATFORM_WINDOW_EVENT(event_t, windowMember, handler) \ { \ - event_t *e = reinterpret_cast(event); \ + auto e = reinterpret_cast(event); \ if (QXcbWindowEventListener *eventListener = windowEventListenerFromId(e->windowMember)) { \ - handled = eventListener->handleGenericEvent(event, &result); \ - if (!handled) \ - eventListener->handler(e); \ + if (eventListener->handleNativeEvent(event)) \ + return; \ + eventListener->handler(e); \ } \ } \ break; #define HANDLE_KEYBOARD_EVENT(event_t, handler) \ { \ - event_t *e = reinterpret_cast(event); \ + auto e = reinterpret_cast(event); \ if (QXcbWindowEventListener *eventListener = windowEventListenerFromId(e->event)) { \ - handled = eventListener->handleGenericEvent(event, &result); \ - if (!handled) \ - m_keyboard->handler(e); \ + if (eventListener->handleNativeEvent(event)) \ + return; \ + m_keyboard->handler(e); \ } \ } \ break; @@ -974,7 +974,7 @@ void QXcbConnection::handleXcbError(xcb_generic_error_t *error) { long result = 0; QAbstractEventDispatcher* dispatcher = QAbstractEventDispatcher::instance(); - if (dispatcher && dispatcher->filterNativeEvent(m_nativeInterface->genericEventFilterType(), error, &result)) + if (dispatcher && dispatcher->filterNativeEvent(m_nativeInterface->nativeEventType(), error, &result)) return; printXcbError("QXcbConnection: XCB error", error); @@ -1066,197 +1066,206 @@ namespace { void QXcbConnection::handleXcbEvent(xcb_generic_event_t *event) { - long result = 0; + if (Q_UNLIKELY(lcQpaEvents().isDebugEnabled())) + printXcbEvent(lcQpaEvents(), "Event", event); + + long result = 0; // Used only by MS Windows QAbstractEventDispatcher* dispatcher = QAbstractEventDispatcher::instance(); - bool handled = dispatcher && dispatcher->filterNativeEvent(m_nativeInterface->genericEventFilterType(), event, &result); + bool handledByNativeEventFilter = dispatcher && dispatcher->filterNativeEvent( + m_nativeInterface->nativeEventType(), event, &result); + if (handledByNativeEventFilter) + return; uint response_type = event->response_type & ~0x80; - if (!handled) { - switch (response_type) { - case XCB_EXPOSE: - HANDLE_PLATFORM_WINDOW_EVENT(xcb_expose_event_t, window, handleExposeEvent); - - case XCB_BUTTON_PRESS: { - xcb_button_press_event_t *ev = (xcb_button_press_event_t *)event; - m_keyboard->updateXKBStateFromCore(ev->state); - // the event explicitly contains the state of the three first buttons, - // the rest we need to manage ourselves - m_buttonState = (m_buttonState & ~0x7) | translateMouseButtons(ev->state); - setButtonState(translateMouseButton(ev->detail), true); - if (Q_UNLIKELY(lcQpaXInputEvents().isDebugEnabled())) - qCDebug(lcQpaXInputEvents, "legacy mouse press, button %d state %X", ev->detail, static_cast(m_buttonState)); - HANDLE_PLATFORM_WINDOW_EVENT(xcb_button_press_event_t, event, handleButtonPressEvent); - } - case XCB_BUTTON_RELEASE: { - xcb_button_release_event_t *ev = (xcb_button_release_event_t *)event; - m_keyboard->updateXKBStateFromCore(ev->state); - m_buttonState = (m_buttonState & ~0x7) | translateMouseButtons(ev->state); - setButtonState(translateMouseButton(ev->detail), false); - if (Q_UNLIKELY(lcQpaXInputEvents().isDebugEnabled())) - qCDebug(lcQpaXInputEvents, "legacy mouse release, button %d state %X", ev->detail, static_cast(m_buttonState)); - HANDLE_PLATFORM_WINDOW_EVENT(xcb_button_release_event_t, event, handleButtonReleaseEvent); - } - case XCB_MOTION_NOTIFY: { - xcb_motion_notify_event_t *ev = (xcb_motion_notify_event_t *)event; - m_keyboard->updateXKBStateFromCore(ev->state); - m_buttonState = (m_buttonState & ~0x7) | translateMouseButtons(ev->state); - if (Q_UNLIKELY(lcQpaXInputEvents().isDebugEnabled())) - qCDebug(lcQpaXInputEvents, "legacy mouse move %d,%d button %d state %X", ev->event_x, ev->event_y, - ev->detail, static_cast(m_buttonState)); - HANDLE_PLATFORM_WINDOW_EVENT(xcb_motion_notify_event_t, event, handleMotionNotifyEvent); - } - - case XCB_CONFIGURE_NOTIFY: - HANDLE_PLATFORM_WINDOW_EVENT(xcb_configure_notify_event_t, event, handleConfigureNotifyEvent); - case XCB_MAP_NOTIFY: - HANDLE_PLATFORM_WINDOW_EVENT(xcb_map_notify_event_t, event, handleMapNotifyEvent); - case XCB_UNMAP_NOTIFY: - HANDLE_PLATFORM_WINDOW_EVENT(xcb_unmap_notify_event_t, event, handleUnmapNotifyEvent); - case XCB_DESTROY_NOTIFY: - HANDLE_PLATFORM_WINDOW_EVENT(xcb_destroy_notify_event_t, event, handleDestroyNotifyEvent); - case XCB_CLIENT_MESSAGE: - handleClientMessageEvent((xcb_client_message_event_t *)event); - break; - case XCB_ENTER_NOTIFY: -#if QT_CONFIG(xcb_xinput) - if (hasXInput2() && !xi2MouseEventsDisabled()) - break; + bool handled = true; + switch (response_type) { + case XCB_EXPOSE: + HANDLE_PLATFORM_WINDOW_EVENT(xcb_expose_event_t, window, handleExposeEvent); + case XCB_BUTTON_PRESS: { + auto ev = reinterpret_cast(event); + m_keyboard->updateXKBStateFromCore(ev->state); + // the event explicitly contains the state of the three first buttons, + // the rest we need to manage ourselves + m_buttonState = (m_buttonState & ~0x7) | translateMouseButtons(ev->state); + setButtonState(translateMouseButton(ev->detail), true); + if (Q_UNLIKELY(lcQpaXInputEvents().isDebugEnabled())) + qCDebug(lcQpaXInputEvents, "legacy mouse press, button %d state %X", + ev->detail, static_cast(m_buttonState)); + HANDLE_PLATFORM_WINDOW_EVENT(xcb_button_press_event_t, event, handleButtonPressEvent); + } + case XCB_BUTTON_RELEASE: { + auto ev = reinterpret_cast(event); + m_keyboard->updateXKBStateFromCore(ev->state); + m_buttonState = (m_buttonState & ~0x7) | translateMouseButtons(ev->state); + setButtonState(translateMouseButton(ev->detail), false); + if (Q_UNLIKELY(lcQpaXInputEvents().isDebugEnabled())) + qCDebug(lcQpaXInputEvents, "legacy mouse release, button %d state %X", + ev->detail, static_cast(m_buttonState)); + HANDLE_PLATFORM_WINDOW_EVENT(xcb_button_release_event_t, event, handleButtonReleaseEvent); + } + case XCB_MOTION_NOTIFY: { + auto ev = reinterpret_cast(event); + m_keyboard->updateXKBStateFromCore(ev->state); + m_buttonState = (m_buttonState & ~0x7) | translateMouseButtons(ev->state); + if (Q_UNLIKELY(lcQpaXInputEvents().isDebugEnabled())) + qCDebug(lcQpaXInputEvents, "legacy mouse move %d,%d button %d state %X", + ev->event_x, ev->event_y, ev->detail, static_cast(m_buttonState)); + HANDLE_PLATFORM_WINDOW_EVENT(xcb_motion_notify_event_t, event, handleMotionNotifyEvent); + } + case XCB_CONFIGURE_NOTIFY: + HANDLE_PLATFORM_WINDOW_EVENT(xcb_configure_notify_event_t, event, handleConfigureNotifyEvent); + case XCB_MAP_NOTIFY: + HANDLE_PLATFORM_WINDOW_EVENT(xcb_map_notify_event_t, event, handleMapNotifyEvent); + case XCB_UNMAP_NOTIFY: + HANDLE_PLATFORM_WINDOW_EVENT(xcb_unmap_notify_event_t, event, handleUnmapNotifyEvent); + case XCB_DESTROY_NOTIFY: + HANDLE_PLATFORM_WINDOW_EVENT(xcb_destroy_notify_event_t, event, handleDestroyNotifyEvent); + case XCB_CLIENT_MESSAGE: { + auto clientMessage = reinterpret_cast(event); + if (clientMessage->format != 32) + return; +#if QT_CONFIG(draganddrop) + if (clientMessage->type == atom(QXcbAtom::XdndStatus)) + drag()->handleStatus(clientMessage); + else if (clientMessage->type == atom(QXcbAtom::XdndFinished)) + drag()->handleFinished(clientMessage); #endif - HANDLE_PLATFORM_WINDOW_EVENT(xcb_enter_notify_event_t, event, handleEnterNotifyEvent); - case XCB_LEAVE_NOTIFY: + if (m_systemTrayTracker && clientMessage->type == atom(QXcbAtom::MANAGER)) + m_systemTrayTracker->notifyManagerClientMessageEvent(clientMessage); + HANDLE_PLATFORM_WINDOW_EVENT(xcb_client_message_event_t, window, handleClientMessageEvent); + } + case XCB_ENTER_NOTIFY: #if QT_CONFIG(xcb_xinput) - if (hasXInput2() && !xi2MouseEventsDisabled()) - break; + if (hasXInput2() && !xi2MouseEventsDisabled()) + break; #endif - m_keyboard->updateXKBStateFromCore(((xcb_leave_notify_event_t *)event)->state); - HANDLE_PLATFORM_WINDOW_EVENT(xcb_leave_notify_event_t, event, handleLeaveNotifyEvent); - case XCB_FOCUS_IN: - HANDLE_PLATFORM_WINDOW_EVENT(xcb_focus_in_event_t, event, handleFocusInEvent); - case XCB_FOCUS_OUT: - HANDLE_PLATFORM_WINDOW_EVENT(xcb_focus_out_event_t, event, handleFocusOutEvent); - case XCB_KEY_PRESS: - { - xcb_key_press_event_t *kp = (xcb_key_press_event_t *)event; - m_keyboard->updateXKBStateFromCore(kp->state); - setTime(kp->time); - HANDLE_KEYBOARD_EVENT(xcb_key_press_event_t, handleKeyPressEvent); - } - case XCB_KEY_RELEASE: - m_keyboard->updateXKBStateFromCore(((xcb_key_release_event_t *)event)->state); - HANDLE_KEYBOARD_EVENT(xcb_key_release_event_t, handleKeyReleaseEvent); - case XCB_MAPPING_NOTIFY: - m_keyboard->updateKeymap(reinterpret_cast(event)); + HANDLE_PLATFORM_WINDOW_EVENT(xcb_enter_notify_event_t, event, handleEnterNotifyEvent); + case XCB_LEAVE_NOTIFY: +#if QT_CONFIG(xcb_xinput) + if (hasXInput2() && !xi2MouseEventsDisabled()) break; - case XCB_SELECTION_REQUEST: - { +#endif + m_keyboard->updateXKBStateFromCore(reinterpret_cast(event)->state); + HANDLE_PLATFORM_WINDOW_EVENT(xcb_leave_notify_event_t, event, handleLeaveNotifyEvent); + case XCB_FOCUS_IN: + HANDLE_PLATFORM_WINDOW_EVENT(xcb_focus_in_event_t, event, handleFocusInEvent); + case XCB_FOCUS_OUT: + HANDLE_PLATFORM_WINDOW_EVENT(xcb_focus_out_event_t, event, handleFocusOutEvent); + case XCB_KEY_PRESS: + { + auto keyPress = reinterpret_cast(event); + m_keyboard->updateXKBStateFromCore(keyPress->state); + setTime(keyPress->time); + HANDLE_KEYBOARD_EVENT(xcb_key_press_event_t, handleKeyPressEvent); + } + case XCB_KEY_RELEASE: + m_keyboard->updateXKBStateFromCore(reinterpret_cast(event)->state); + HANDLE_KEYBOARD_EVENT(xcb_key_release_event_t, handleKeyReleaseEvent); + case XCB_MAPPING_NOTIFY: + m_keyboard->updateKeymap(reinterpret_cast(event)); + break; + case XCB_SELECTION_REQUEST: + { #if QT_CONFIG(draganddrop) || QT_CONFIG(clipboard) - xcb_selection_request_event_t *sr = reinterpret_cast(event); + auto selectionRequest = reinterpret_cast(event); #endif #if QT_CONFIG(draganddrop) - if (sr->selection == atom(QXcbAtom::XdndSelection)) - m_drag->handleSelectionRequest(sr); - else + if (selectionRequest->selection == atom(QXcbAtom::XdndSelection)) + m_drag->handleSelectionRequest(selectionRequest); + else #endif - { + { #ifndef QT_NO_CLIPBOARD - m_clipboard->handleSelectionRequest(sr); + m_clipboard->handleSelectionRequest(selectionRequest); #endif - } - break; } - case XCB_SELECTION_CLEAR: - setTime((reinterpret_cast(event))->time); + break; + } + case XCB_SELECTION_CLEAR: + setTime((reinterpret_cast(event))->time); #ifndef QT_NO_CLIPBOARD - m_clipboard->handleSelectionClearRequest(reinterpret_cast(event)); + m_clipboard->handleSelectionClearRequest(reinterpret_cast(event)); #endif - handled = true; - break; - case XCB_SELECTION_NOTIFY: - setTime((reinterpret_cast(event))->time); - handled = false; - break; - case XCB_PROPERTY_NOTIFY: - { - xcb_property_notify_event_t *pn = reinterpret_cast(event); - if (pn->atom == atom(QXcbAtom::_NET_WORKAREA)) { - QXcbVirtualDesktop *virtualDesktop = virtualDesktopForRootWindow(pn->window); - if (virtualDesktop) - virtualDesktop->updateWorkArea(); - } else { - HANDLE_PLATFORM_WINDOW_EVENT(xcb_property_notify_event_t, window, handlePropertyNotifyEvent); - } - break; + break; + case XCB_SELECTION_NOTIFY: + setTime((reinterpret_cast(event))->time); + break; + case XCB_PROPERTY_NOTIFY: + { + auto propertyNotify = reinterpret_cast(event); + if (propertyNotify->atom == atom(QXcbAtom::_NET_WORKAREA)) { + QXcbVirtualDesktop *virtualDesktop = virtualDesktopForRootWindow(propertyNotify->window); + if (virtualDesktop) + virtualDesktop->updateWorkArea(); + } else { + HANDLE_PLATFORM_WINDOW_EVENT(xcb_property_notify_event_t, window, handlePropertyNotifyEvent); } + break; + } #if QT_CONFIG(xcb_xinput) - case XCB_GE_GENERIC: - // Here the windowEventListener is invoked from xi2HandleEvent() - if (hasXInput2() && isXIEvent(event, m_xiOpCode)) - xi2HandleEvent(reinterpret_cast(event)); - break; + case XCB_GE_GENERIC: + // Here the windowEventListener is invoked from xi2HandleEvent() + if (hasXInput2() && isXIEvent(event, m_xiOpCode)) + xi2HandleEvent(reinterpret_cast(event)); + break; #endif - default: - handled = false; - break; - } + default: + handled = false; // event type not recognized + break; } - if (!handled) { - if (has_xfixes && response_type == xfixes_first_event + XCB_XFIXES_SELECTION_NOTIFY) { - xcb_xfixes_selection_notify_event_t *notify_event = reinterpret_cast(event); - setTime(notify_event->timestamp); + if (handled) + return; + + handled = true; + if (has_xfixes && response_type == xfixes_first_event + XCB_XFIXES_SELECTION_NOTIFY) { + auto notify_event = reinterpret_cast(event); + setTime(notify_event->timestamp); #ifndef QT_NO_CLIPBOARD - m_clipboard->handleXFixesSelectionRequest(notify_event); + m_clipboard->handleXFixesSelectionRequest(notify_event); #endif - for (QXcbVirtualDesktop *virtualDesktop : qAsConst(m_virtualDesktops)) - virtualDesktop->handleXFixesSelectionNotify(notify_event); - - handled = true; - } else if (has_randr_extension && response_type == xrandr_first_event + XCB_RANDR_NOTIFY) { - updateScreens(reinterpret_cast(event)); - handled = true; - } else if (has_randr_extension && response_type == xrandr_first_event + XCB_RANDR_SCREEN_CHANGE_NOTIFY) { - xcb_randr_screen_change_notify_event_t *change_event = reinterpret_cast(event); - if (auto *virtualDesktop = virtualDesktopForRootWindow(change_event->root)) - virtualDesktop->handleScreenChange(change_event); - - handled = true; + for (QXcbVirtualDesktop *virtualDesktop : qAsConst(m_virtualDesktops)) + virtualDesktop->handleXFixesSelectionNotify(notify_event); + } else if (has_randr_extension && response_type == xrandr_first_event + XCB_RANDR_NOTIFY) { + updateScreens(reinterpret_cast(event)); + } else if (has_randr_extension && response_type == xrandr_first_event + XCB_RANDR_SCREEN_CHANGE_NOTIFY) { + auto change_event = reinterpret_cast(event); + if (auto virtualDesktop = virtualDesktopForRootWindow(change_event->root)) + virtualDesktop->handleScreenChange(change_event); #if QT_CONFIG(xkb) - } else if (response_type == xkb_first_event) { // https://bugs.freedesktop.org/show_bug.cgi?id=51295 - _xkb_event *xkb_event = reinterpret_cast<_xkb_event *>(event); - if (xkb_event->any.deviceID == m_keyboard->coreDeviceId()) { - switch (xkb_event->any.xkbType) { - // XkbNewKkdNotify and XkbMapNotify together capture all sorts of keymap - // updates (e.g. xmodmap, xkbcomp, setxkbmap), with minimal redundent recompilations. - case XCB_XKB_STATE_NOTIFY: - m_keyboard->updateXKBState(&xkb_event->state_notify); - handled = true; - break; - case XCB_XKB_MAP_NOTIFY: + } else if (response_type == xkb_first_event) { // https://bugs.freedesktop.org/show_bug.cgi?id=51295 + auto xkb_event = reinterpret_cast<_xkb_event *>(event); + if (xkb_event->any.deviceID == m_keyboard->coreDeviceId()) { + switch (xkb_event->any.xkbType) { + // XkbNewKkdNotify and XkbMapNotify together capture all sorts of keymap + // updates (e.g. xmodmap, xkbcomp, setxkbmap), with minimal redundent recompilations. + case XCB_XKB_STATE_NOTIFY: + m_keyboard->updateXKBState(&xkb_event->state_notify); + break; + case XCB_XKB_MAP_NOTIFY: + m_keyboard->updateKeymap(); + break; + case XCB_XKB_NEW_KEYBOARD_NOTIFY: { + xcb_xkb_new_keyboard_notify_event_t *ev = &xkb_event->new_keyboard_notify; + if (ev->changed & XCB_XKB_NKN_DETAIL_KEYCODES) m_keyboard->updateKeymap(); - handled = true; - break; - case XCB_XKB_NEW_KEYBOARD_NOTIFY: { - xcb_xkb_new_keyboard_notify_event_t *ev = &xkb_event->new_keyboard_notify; - if (ev->changed & XCB_XKB_NKN_DETAIL_KEYCODES) - m_keyboard->updateKeymap(); - break; - } - default: - break; + break; } + default: + break; } -#endif } +#endif + } else { + handled = false; // event type still not recognized } - if (!handled && m_glIntegration) - handled = m_glIntegration->handleXcbEvent(event, response_type); + if (handled) + return; -#if 0 - if (Q_UNLIKELY(lcQpaEvents().isDebugEnabled())) - printXcbEvent(lcQpaEvents(), handled ? "Handled" : "Unhandled", event); -#endif + if (m_glIntegration) + m_glIntegration->handleXcbEvent(event, response_type); } void QXcbConnection::addPeekFunc(PeekFunc f) @@ -1761,28 +1770,6 @@ void QXcbConnection::processXcbEvents() xcb_flush(xcb_connection()); } -void QXcbConnection::handleClientMessageEvent(const xcb_client_message_event_t *event) -{ - if (event->format != 32) - return; - -#if QT_CONFIG(draganddrop) - if (event->type == atom(QXcbAtom::XdndStatus)) { - drag()->handleStatus(event); - } else if (event->type == atom(QXcbAtom::XdndFinished)) { - drag()->handleFinished(event); - } -#endif - if (m_systemTrayTracker && event->type == atom(QXcbAtom::MANAGER)) - m_systemTrayTracker->notifyManagerClientMessageEvent(event); - - QXcbWindow *window = platformWindowFromId(event->window); - if (!window) - return; - - window->handleClientMessageEvent(event); -} - static const char * xcb_atomnames = { // window-manager <-> client protocols "WM_PROTOCOLS\0" diff --git a/src/plugins/platforms/xcb/qxcbconnection.h b/src/plugins/platforms/xcb/qxcbconnection.h index 697b509bf0..342efca55e 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.h +++ b/src/plugins/platforms/xcb/qxcbconnection.h @@ -335,7 +335,7 @@ class QXcbWindowEventListener { public: virtual ~QXcbWindowEventListener() {} - virtual bool handleGenericEvent(xcb_generic_event_t *, long *) { return false; } + virtual bool handleNativeEvent(xcb_generic_event_t *) { return false; } virtual void handleExposeEvent(const xcb_expose_event_t *) {} virtual void handleClientMessageEvent(const xcb_client_message_event_t *) {} @@ -553,7 +553,6 @@ private: void initializeXShape(); void initializeXKB(); void initializeXSync(); - void handleClientMessageEvent(const xcb_client_message_event_t *event); QXcbScreen* findScreenForCrtc(xcb_window_t rootWindow, xcb_randr_crtc_t crtc) const; QXcbScreen* findScreenForOutput(xcb_window_t rootWindow, xcb_randr_output_t output) const; QXcbVirtualDesktop* virtualDesktopForRootWindow(xcb_window_t rootWindow) const; diff --git a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp index a327d8dea7..a3befc7384 100644 --- a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp +++ b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp @@ -581,8 +581,7 @@ void QXcbConnection::xi2HandleEvent(xcb_ge_event_t *event) } if (eventListener) { - long result = 0; - if (eventListener->handleGenericEvent(reinterpret_cast(event), &result)) + if (eventListener->handleNativeEvent(reinterpret_cast(event))) return; } diff --git a/src/plugins/platforms/xcb/qxcbnativeinterface.cpp b/src/plugins/platforms/xcb/qxcbnativeinterface.cpp index 26b9fcc15a..3d2197796f 100644 --- a/src/plugins/platforms/xcb/qxcbnativeinterface.cpp +++ b/src/plugins/platforms/xcb/qxcbnativeinterface.cpp @@ -92,8 +92,7 @@ static int resourceType(const QByteArray &key) return int(result - names); } -QXcbNativeInterface::QXcbNativeInterface() : - m_genericEventFilterType(QByteArrayLiteral("xcb_generic_event_t")) +QXcbNativeInterface::QXcbNativeInterface() { } diff --git a/src/plugins/platforms/xcb/qxcbnativeinterface.h b/src/plugins/platforms/xcb/qxcbnativeinterface.h index 5ec3827afd..d1f2747bea 100644 --- a/src/plugins/platforms/xcb/qxcbnativeinterface.h +++ b/src/plugins/platforms/xcb/qxcbnativeinterface.h @@ -98,7 +98,7 @@ public: QFunctionPointer platformFunction(const QByteArray &function) const override; - inline const QByteArray &genericEventFilterType() const { return m_genericEventFilterType; } + inline const QByteArray &nativeEventType() const { return m_nativeEventType; } void *displayForWindow(QWindow *window); void *connectionForWindow(QWindow *window); @@ -131,7 +131,7 @@ signals: void systemTrayWindowChanged(QScreen *screen); private: - const QByteArray m_genericEventFilterType; + const QByteArray m_nativeEventType = QByteArrayLiteral("xcb_generic_event_t"); xcb_atom_t m_sysTraySelectionAtom = XCB_ATOM_NONE; diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp index fd0d2f9f07..2c333cb22b 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.cpp +++ b/src/plugins/platforms/xcb/qxcbwindow.cpp @@ -1807,12 +1807,11 @@ bool QXcbWindow::requestSystemTrayWindowDock() return true; } -bool QXcbWindow::handleGenericEvent(xcb_generic_event_t *event, long *result) +bool QXcbWindow::handleNativeEvent(xcb_generic_event_t *event) { - return QWindowSystemInterface::handleNativeEvent(window(), - connection()->nativeInterface()->genericEventFilterType(), - event, - result); + auto eventType = connection()->nativeInterface()->nativeEventType(); + long result = 0; // Used only by MS Windows + return QWindowSystemInterface::handleNativeEvent(window(), eventType, event, &result); } void QXcbWindow::handleExposeEvent(const xcb_expose_event_t *event) diff --git a/src/plugins/platforms/xcb/qxcbwindow.h b/src/plugins/platforms/xcb/qxcbwindow.h index 128c6e126d..99e8e40725 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.h +++ b/src/plugins/platforms/xcb/qxcbwindow.h @@ -121,7 +121,7 @@ public: QImage::Format imageFormat() const { return m_imageFormat; } bool imageNeedsRgbSwap() const { return m_imageRgbSwap; } - bool handleGenericEvent(xcb_generic_event_t *event, long *result) override; + bool handleNativeEvent(xcb_generic_event_t *event) override; void handleExposeEvent(const xcb_expose_event_t *event) override; void handleClientMessageEvent(const xcb_client_message_event_t *event) override; -- cgit v1.2.3 From 0a06e1baf9e6da5308582b9dc928f4d9fea508d0 Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Thu, 29 Dec 2016 17:11:24 +0100 Subject: Modernize the "thread" feature Add it to configure.json and replace all occurrences of QT_NO_THREAD with QT_CONFIG(thread). Add conditions for other features that depend on thread support. Remove conditions where we can use the QMutex and QThreadStorage stubs. Change-Id: I284e5d794fda9a4c6f4a1ab29e55aa686272a0eb Reviewed-by: Eskil Abrahamsen Blomfeldt --- src/plugins/platforms/windows/qwindowsthreadpoolrunner.h | 6 +++--- src/plugins/sqldrivers/mysql/qsql_mysql.cpp | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'src/plugins') diff --git a/src/plugins/platforms/windows/qwindowsthreadpoolrunner.h b/src/plugins/platforms/windows/qwindowsthreadpoolrunner.h index 99705927af..731e4b5432 100644 --- a/src/plugins/platforms/windows/qwindowsthreadpoolrunner.h +++ b/src/plugins/platforms/windows/qwindowsthreadpoolrunner.h @@ -61,7 +61,7 @@ class QWindowsThreadPoolRunner { Q_DISABLE_COPY(QWindowsThreadPoolRunner) -#ifndef QT_NO_THREAD +#if QT_CONFIG(thread) template // nested class implementing QRunnable to execute a function. class Runnable : public QRunnable { @@ -104,7 +104,7 @@ public: private: QMutex m_mutex; QWaitCondition m_condition; -#else // !QT_NO_THREAD +#else // QT_CONFIG(thread) public: QWindowsThreadPoolRunner() {} @@ -114,7 +114,7 @@ public: f(); return true; } -#endif // QT_NO_THREAD +#endif // QT_CONFIG(thread) }; QT_END_NAMESPACE diff --git a/src/plugins/sqldrivers/mysql/qsql_mysql.cpp b/src/plugins/sqldrivers/mysql/qsql_mysql.cpp index a1636302b7..e2455f87fb 100644 --- a/src/plugins/sqldrivers/mysql/qsql_mysql.cpp +++ b/src/plugins/sqldrivers/mysql/qsql_mysql.cpp @@ -1454,7 +1454,7 @@ bool QMYSQLDriver::open(const QString& db, d->preparedQuerysEnabled = false; #endif -#ifndef QT_NO_THREAD +#if QT_CONFIG(thread) mysql_thread_init(); #endif @@ -1468,7 +1468,7 @@ void QMYSQLDriver::close() { Q_D(QMYSQLDriver); if (isOpen()) { -#ifndef QT_NO_THREAD +#if QT_CONFIG(thread) mysql_thread_end(); #endif mysql_close(d->mysql); -- cgit v1.2.3 From 0e63111416e3407c4fa3eac33ae69028216cf1b7 Mon Sep 17 00:00:00 2001 From: Gatis Paeglis Date: Fri, 3 Aug 2018 15:00:39 +0200 Subject: xcb: avoid unnecessary InternAtom requests QXcbConnection::internAtom() creates the atom if it does not exist. The lifetime of an atom is not tied to the interning client. Atoms remain defined until server reset (lost connection, restart). So create the atom once via QXcbConnection::initializeAllAtoms(), and later fetch the atom value from local array, instead of repeating InternAtom requests. Change-Id: I3cae21895febad6e5daf8c32e72612202baaad64 Reviewed-by: Gatis Paeglis --- src/plugins/platforms/xcb/qxcbclipboard.cpp | 2 +- src/plugins/platforms/xcb/qxcbconnection.cpp | 4 ++++ src/plugins/platforms/xcb/qxcbconnection.h | 6 ++++++ src/plugins/platforms/xcb/qxcbnativeinterface.cpp | 2 +- src/plugins/platforms/xcb/qxcbscreen.cpp | 16 ++++++---------- 5 files changed, 18 insertions(+), 12 deletions(-) (limited to 'src/plugins') diff --git a/src/plugins/platforms/xcb/qxcbclipboard.cpp b/src/plugins/platforms/xcb/qxcbclipboard.cpp index ca2eff170d..84831cdbe5 100644 --- a/src/plugins/platforms/xcb/qxcbclipboard.cpp +++ b/src/plugins/platforms/xcb/qxcbclipboard.cpp @@ -832,7 +832,7 @@ xcb_generic_event_t *QXcbClipboard::waitForClipboardEvent(xcb_window_t window, i } // process other clipboard events, since someone is probably requesting data from us - auto clipboardAtom = connection()->internAtom("CLIPBOARD"); + auto clipboardAtom = atom(QXcbAtom::CLIPBOARD); e = connection()->checkEvent([clipboardAtom](xcb_generic_event_t *event, int type) { xcb_atom_t selection = XCB_ATOM_NONE; if (type == XCB_SELECTION_REQUEST) diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp index 75275f6fd2..84551fd74b 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.cpp +++ b/src/plugins/platforms/xcb/qxcbconnection.cpp @@ -1964,6 +1964,10 @@ static const char * xcb_atomnames = { "_COMPIZ_DECOR_DELETE_PIXMAP\0" "_COMPIZ_TOOLKIT_ACTION\0" "_GTK_LOAD_ICONTHEMES\0" + "AT_SPI_BUS\0" + "EDID\0" + "EDID_DATA\0" + "XFree86_DDC_EDID1_RAWDATA\0" // \0\0 terminates loop. }; diff --git a/src/plugins/platforms/xcb/qxcbconnection.h b/src/plugins/platforms/xcb/qxcbconnection.h index 342efca55e..596174d234 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.h +++ b/src/plugins/platforms/xcb/qxcbconnection.h @@ -295,6 +295,12 @@ namespace QXcbAtom { _COMPIZ_TOOLKIT_ACTION, _GTK_LOAD_ICONTHEMES, + AT_SPI_BUS, + + EDID, + EDID_DATA, + XFree86_DDC_EDID1_RAWDATA, + NAtoms }; } diff --git a/src/plugins/platforms/xcb/qxcbnativeinterface.cpp b/src/plugins/platforms/xcb/qxcbnativeinterface.cpp index 3d2197796f..98bedea48a 100644 --- a/src/plugins/platforms/xcb/qxcbnativeinterface.cpp +++ b/src/plugins/platforms/xcb/qxcbnativeinterface.cpp @@ -408,7 +408,7 @@ void *QXcbNativeInterface::atspiBus() QXcbIntegration *integration = static_cast(QGuiApplicationPrivate::platformIntegration()); QXcbConnection *defaultConnection = integration->defaultConnection(); if (defaultConnection) { - xcb_atom_t atspiBusAtom = defaultConnection->internAtom("AT_SPI_BUS"); + auto atspiBusAtom = defaultConnection->atom(QXcbAtom::AT_SPI_BUS); auto reply = Q_XCB_REPLY(xcb_get_property, defaultConnection->xcb_connection(), false, defaultConnection->rootWindow(), atspiBusAtom, XCB_ATOM_STRING, 0, 128); diff --git a/src/plugins/platforms/xcb/qxcbscreen.cpp b/src/plugins/platforms/xcb/qxcbscreen.cpp index b398768bbc..8c0ce8dd7e 100644 --- a/src/plugins/platforms/xcb/qxcbscreen.cpp +++ b/src/plugins/platforms/xcb/qxcbscreen.cpp @@ -906,16 +906,12 @@ QByteArray QXcbScreen::getEdid() const return result; // Try a bunch of atoms - xcb_atom_t atom = connection()->internAtom("EDID"); - result = getOutputProperty(atom); - if (result.isEmpty()) { - atom = connection()->internAtom("EDID_DATA"); - result = getOutputProperty(atom); - } - if (result.isEmpty()) { - atom = connection()->internAtom("XFree86_DDC_EDID1_RAWDATA"); - result = getOutputProperty(atom); - } + result = getOutputProperty(atom(QXcbAtom::EDID)); + if (result.isEmpty()) + result = getOutputProperty(atom(QXcbAtom::EDID_DATA)); + if (result.isEmpty()) + result = getOutputProperty(atom(QXcbAtom::XFree86_DDC_EDID1_RAWDATA)); + return result; } -- cgit v1.2.3 From 52d4a2976fd7edaf68d697bb1f5cb379cb1739cc Mon Sep 17 00:00:00 2001 From: Gatis Paeglis Date: Mon, 13 Aug 2018 15:38:30 +0200 Subject: xcb: replace tiny helper function with an inline code Having these 2 lines in a function does not add much value and requires scrolling that could be avoided. Change-Id: Ife814be6478521cd64b0048d1b6ee447afea55de Reviewed-by: Shawn Rutledge --- src/plugins/platforms/xcb/qxcbwindow.cpp | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) (limited to 'src/plugins') diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp index 2c333cb22b..52c87ee8a4 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.cpp +++ b/src/plugins/platforms/xcb/qxcbwindow.cpp @@ -732,13 +732,6 @@ void QXcbWindow::setVisible(bool visible) hide(); } -static inline bool testShowWithoutActivating(const QWindow *window) -{ - // QWidget-attribute Qt::WA_ShowWithoutActivating. - const QVariant showWithoutActivating = window->property("_q_showWithoutActivating"); - return showWithoutActivating.isValid() && showWithoutActivating.toBool(); -} - void QXcbWindow::show() { if (window()->isTopLevel()) { @@ -786,7 +779,9 @@ void QXcbWindow::show() updateNetWmStateBeforeMap(); } - if (testShowWithoutActivating(window())) + // QWidget-attribute Qt::WA_ShowWithoutActivating. + const auto showWithoutActivating = window()->property("_q_showWithoutActivating"); + if (showWithoutActivating.isValid() && showWithoutActivating.toBool()) updateNetWmUserTime(0); else if (connection()->time() != XCB_TIME_CURRENT_TIME) updateNetWmUserTime(connection()->time()); -- cgit v1.2.3 From df91fd119828b75cb5c411e3e8b9e9af64c864e1 Mon Sep 17 00:00:00 2001 From: Andre de la Rocha Date: Thu, 16 Aug 2018 16:45:26 +0200 Subject: WinRT QPA: Fix mapping of static text accessibility role QAccessible::StaticText should be mapped to AutomationControlType_Text instead of AutomationControlType_Edit. Change-Id: If8c840f0dea553c1a750225586778a7d24cf424a Reviewed-by: Oliver Wolff --- src/plugins/platforms/winrt/uiautomation/qwinrtuiautils.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/plugins') diff --git a/src/plugins/platforms/winrt/uiautomation/qwinrtuiautils.cpp b/src/plugins/platforms/winrt/uiautomation/qwinrtuiautils.cpp index 98483216c0..16197c99b9 100644 --- a/src/plugins/platforms/winrt/uiautomation/qwinrtuiautils.cpp +++ b/src/plugins/platforms/winrt/uiautomation/qwinrtuiautils.cpp @@ -126,7 +126,7 @@ AutomationControlType roleToControlType(QAccessible::Role role) {QAccessible::PropertyPage, AutomationControlType::AutomationControlType_Custom}, {QAccessible::Indicator, AutomationControlType::AutomationControlType_Custom}, {QAccessible::Graphic, AutomationControlType::AutomationControlType_Image}, - {QAccessible::StaticText, AutomationControlType::AutomationControlType_Edit}, + {QAccessible::StaticText, AutomationControlType::AutomationControlType_Text}, {QAccessible::EditableText, AutomationControlType::AutomationControlType_Edit}, {QAccessible::Button, AutomationControlType::AutomationControlType_Button}, {QAccessible::CheckBox, AutomationControlType::AutomationControlType_CheckBox}, -- cgit v1.2.3 From e09f5b17865a09dac41d0f30ef2ea238f38873eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Fri, 17 Aug 2018 13:30:38 +0200 Subject: macOS: Teach QWheelEvent to handle a new ScrollMomentum phase We detect if there's an upcoming momentum phase using the same trick used by e.g. Mozilla in their event handling: https://tinyurl.com/yd8lcs4l, and as recommended by an Apple engineer: https://tinyurl.com/y8yytlgv The event is not guaranteed to be in the queue, but in practice it seems to be. If this assumption fails we can add a wait timeout to the event search instead of using [NSDate distantPast] as a timeout (which only looks at queued events). When the momentum phase is detected, QWheelEvent::phase will have the new ScrollMomentum value, and the phase transitions will be ScrollBegin -> ScrollUpdate -> ScrollMomentum -> ScrollEnd. We no longer send ScrollEnd to signify that the user's fingers have been lifted off the trackpad; rather, the first event with ScrollMomentum phase means that the fingers have been lifted and macOS is now sending simulated-momentum events. This means ScrollEnd is a reliable indicator that the entire scroll gesture (both the user interaction and the momentum) has ended. If the ScrollMomentum phase is skipped, it means the user's fingers came to rest before being lifted, so there is no momentum. In that case the transitions will be ScrollBegin -> ScrollUpdate -> ScrollEnd. Task-number: QTBUG-63026 Task-number: QTBUG-65160 Change-Id: I80191a472f6fa892387004c199166a6350124274 Reviewed-by: Shawn Rutledge --- src/plugins/platforms/cocoa/qnsview_mouse.mm | 64 ++++++++++++++++++---------- 1 file changed, 41 insertions(+), 23 deletions(-) (limited to 'src/plugins') diff --git a/src/plugins/platforms/cocoa/qnsview_mouse.mm b/src/plugins/platforms/cocoa/qnsview_mouse.mm index 1de256825a..65bc9f837d 100644 --- a/src/plugins/platforms/cocoa/qnsview_mouse.mm +++ b/src/plugins/platforms/cocoa/qnsview_mouse.mm @@ -566,6 +566,42 @@ NSTimeInterval timestamp = [theEvent timestamp]; ulong qt_timestamp = timestamp * 1000; + Qt::ScrollPhase phase = Qt::NoScrollPhase; + if (theEvent.phase == NSEventPhaseMayBegin || theEvent.phase == NSEventPhaseBegan) { + // MayBegin is likely to happen. We treat it the same as an actual begin, + // and follow it with an update when the actual begin is delivered. + phase = m_scrolling ? Qt::ScrollUpdate : Qt::ScrollBegin; + m_scrolling = true; + } else if (theEvent.phase == NSEventPhaseStationary || theEvent.phase == NSEventPhaseChanged) { + phase = Qt::ScrollUpdate; + } else if (theEvent.phase == NSEventPhaseEnded) { + // A scroll event phase may be followed by a momentum phase after the user releases + // the finger, and in that case we don't want to send a Qt::ScrollEnd until after + // the momentum phase has ended. Unfortunately there isn't any guaranteed way of + // knowing whether or not a NSEventPhaseEnded will be followed by a momentum phase. + // The best we can do is to look at the event queue and hope that the system has + // had time to emit a momentum phase event. + if ([NSApp nextEventMatchingMask:NSScrollWheelMask untilDate:[NSDate distantPast] + inMode:@"QtMomementumEventSearchMode" dequeue:NO].momentumPhase == NSEventPhaseBegan) { + Q_ASSERT(pixelDelta.isNull() && angleDelta.isNull()); + return; // Ignore this event, as it has a delta of 0,0 + } + phase = Qt::ScrollEnd; + m_scrolling = false; + } else if (theEvent.momentumPhase == NSEventPhaseBegan) { + Q_ASSERT(!pixelDelta.isNull() && !angleDelta.isNull()); + phase = Qt::ScrollUpdate; // Send as update, it has a delta + } else if (theEvent.momentumPhase == NSEventPhaseChanged) { + phase = Qt::ScrollMomentum; + } else if (theEvent.phase == NSEventPhaseCancelled + || theEvent.momentumPhase == NSEventPhaseEnded + || theEvent.momentumPhase == NSEventPhaseCancelled) { + phase = Qt::ScrollEnd; + m_scrolling = false; + } else { + Q_ASSERT(theEvent.momentumPhase != NSEventPhaseStationary); + } + // Prevent keyboard modifier state from changing during scroll event streams. // A two-finger trackpad flick generates a stream of scroll events. We want // the keyboard modifier state to be the state at the beginning of the @@ -573,34 +609,16 @@ // mid-stream. One example of this happening would be when pressing cmd // after scrolling in Qt Creator: not taking the phase into account causes // the end of the event stream to be interpreted as font size changes. - NSEventPhase momentumPhase = [theEvent momentumPhase]; - if (momentumPhase == NSEventPhaseNone) + if (theEvent.momentumPhase == NSEventPhaseNone) m_currentWheelModifiers = [QNSView convertKeyModifiers:[theEvent modifierFlags]]; - NSEventPhase phase = [theEvent phase]; - Qt::ScrollPhase ph = Qt::ScrollUpdate; - - // MayBegin is likely to happen. We treat it the same as an actual begin. - if (phase == NSEventPhaseMayBegin) { - m_scrolling = true; - ph = Qt::ScrollBegin; - } else if (phase == NSEventPhaseBegan) { - // If MayBegin did not happen, Began is the actual beginning. - if (!m_scrolling) - ph = Qt::ScrollBegin; - m_scrolling = true; - } else if (phase == NSEventPhaseEnded || phase == NSEventPhaseCancelled || - momentumPhase == NSEventPhaseEnded || momentumPhase == NSEventPhaseCancelled) { - ph = Qt::ScrollEnd; - m_scrolling = false; - } else if (phase == NSEventPhaseNone && momentumPhase == NSEventPhaseNone) { - ph = Qt::NoScrollPhase; - } // "isInverted": natural OS X scrolling, inverted from the Qt/other platform/Jens perspective. bool isInverted = [theEvent isDirectionInvertedFromDevice]; - qCDebug(lcQpaMouse) << "scroll wheel @ window pos" << qt_windowPoint << "delta px" << pixelDelta << "angle" << angleDelta << "phase" << ph << (isInverted ? "inverted" : ""); - QWindowSystemInterface::handleWheelEvent(m_platformWindow->window(), qt_timestamp, qt_windowPoint, qt_screenPoint, pixelDelta, angleDelta, m_currentWheelModifiers, ph, source, isInverted); + qCDebug(lcQpaMouse) << "scroll wheel @ window pos" << qt_windowPoint << "delta px" << pixelDelta + << "angle" << angleDelta << "phase" << phase << (isInverted ? "inverted" : ""); + QWindowSystemInterface::handleWheelEvent(m_platformWindow->window(), qt_timestamp, qt_windowPoint, + qt_screenPoint, pixelDelta, angleDelta, m_currentWheelModifiers, phase, source, isInverted); } #endif // QT_CONFIG(wheelevent) -- cgit v1.2.3