diff options
Diffstat (limited to 'src/plugins/platforms')
21 files changed, 166 insertions, 97 deletions
diff --git a/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm b/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm index a1176da33f..38a402fb2f 100644 --- a/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm +++ b/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm @@ -51,6 +51,19 @@ QT_USE_NAMESPACE #ifndef QT_NO_ACCESSIBILITY +/** + * Converts between absolute character offsets and line numbers of a + * QAccessibleTextInterface. Works in exactly one of two modes: + * + * - Pass *line == -1 in order to get a line containing character at the given + * *offset + * - Pass *offset == -1 in order to get the offset of first character of the + * given *line + * + * You can optionally also pass non-NULL `start` and `end`, which will in both + * modes be filled with the offset of the first and last characters of the + * relevant line. + */ static void convertLineOffset(QAccessibleTextInterface *text, int *line, int *offset, NSUInteger *start = 0, NSUInteger *end = 0) { Q_ASSERT(*line == -1 || *offset == -1); @@ -228,7 +241,7 @@ static void convertLineOffset(QAccessibleTextInterface *text, int *line, int *of return [attributes autorelease]; } -- (id)parentElement { +- (id)accessibilityParent { QAccessibleInterface *iface = QAccessible::accessibleInterface(axid); if (!iface || !iface->isValid()) return nil; @@ -241,7 +254,7 @@ static void convertLineOffset(QAccessibleTextInterface *text, int *line, int *of if (QAccessibleInterface *parent = iface->parent()) { if (parent->role() != QAccessible::Application) { QAccessible::Id parentId = QAccessible::uniqueId(parent); - return [QMacAccessibilityElement elementWithId: parentId]; + return NSAccessibilityUnignoredAncestor([QMacAccessibilityElement elementWithId: parentId]); } } @@ -249,12 +262,18 @@ static void convertLineOffset(QAccessibleTextInterface *text, int *line, int *of QPlatformWindow *platformWindow = window->handle(); if (platformWindow) { QCocoaWindow *win = static_cast<QCocoaWindow*>(platformWindow); - return qnsview_cast(win->view()); + return NSAccessibilityUnignoredAncestor(qnsview_cast(win->view())); } } return nil; } +- (NSRect)accessibilityFrame { + QAccessibleInterface *iface = QAccessible::accessibleInterface(axid); + if (!iface || !iface->isValid()) + return NSZeroRect; + return QCocoaScreen::mapToNative(iface->rect()); +} - (id) minValueAttribute:(QAccessibleInterface*)iface { if (QAccessibleValueInterface *val = iface->valueInterface()) @@ -288,13 +307,13 @@ static void convertLineOffset(QAccessibleTextInterface *text, int *line, int *of id focusedElement = [NSApp accessibilityAttributeValue:NSAccessibilityFocusedUIElementAttribute]; return @([focusedElement isEqual:self]); } else if ([attribute isEqualToString:NSAccessibilityParentAttribute]) { - return NSAccessibilityUnignoredAncestor([self parentElement]); + return self.accessibilityParent; } else if ([attribute isEqualToString:NSAccessibilityWindowAttribute]) { // We're in the same window as our parent. - return [[self parentElement] accessibilityAttributeValue:NSAccessibilityWindowAttribute]; + return [[self accessibilityParent] accessibilityAttributeValue:NSAccessibilityWindowAttribute]; } else if ([attribute isEqualToString:NSAccessibilityTopLevelUIElementAttribute]) { // We're in the same top level element as our parent. - return [[self parentElement] accessibilityAttributeValue:NSAccessibilityTopLevelUIElementAttribute]; + return [[self accessibilityParent] accessibilityAttributeValue:NSAccessibilityTopLevelUIElementAttribute]; } else if ([attribute isEqualToString:NSAccessibilityPositionAttribute]) { // The position in points of the element's lower-left corner in screen-relative coordinates QPointF qtPosition = QRectF(iface->rect()).bottomLeft(); @@ -350,12 +369,8 @@ static void convertLineOffset(QAccessibleTextInterface *text, int *line, int *of return [NSValue valueWithRange: NSMakeRange(0, iface->text(QAccessible::Name).length())]; } else if ([attribute isEqualToString:NSAccessibilityInsertionPointLineNumberAttribute]) { if (QAccessibleTextInterface *text = iface->textInterface()) { - int line = 0; // true for all single line edits - if (iface->state().multiLine) { - int position = text->cursorPosition(); - convertLineOffset(text, &line, &position); - } - return @(line); + int position = text->cursorPosition(); + return [self accessibilityAttributeValue:NSAccessibilityLineForIndexParameterizedAttribute forParameter:@(position)]; } return nil; } else if ([attribute isEqualToString:NSAccessibilityMinValueAttribute]) { @@ -411,8 +426,11 @@ static void convertLineOffset(QAccessibleTextInterface *text, int *line, int *of int index = [parameter intValue]; if (index < 0 || index > iface->textInterface()->characterCount()) return nil; - int line = -1; - convertLineOffset(iface->textInterface(), &line, &index); + int line = 0; // true for all single line edits + if (iface->state().multiLine) { + line = -1; + convertLineOffset(iface->textInterface(), &line, &index); + } return @(line); } if ([attribute isEqualToString: NSAccessibilityRangeForLineParameterizedAttribute]) { diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm index df1ad82592..774ccdbf4c 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.mm +++ b/src/plugins/platforms/cocoa/qcocoawindow.mm @@ -218,6 +218,7 @@ QCocoaWindow::~QCocoaWindow() } [m_view release]; + [m_nsWindow close]; [m_nsWindow release]; } diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmscreen.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmscreen.cpp index 24f82e7843..24051c352e 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmscreen.cpp +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmscreen.cpp @@ -423,7 +423,7 @@ void QEglFSKmsGbmScreen::updateFlipStatus() if (m_flipPending) return; - for (const CloneDestination &d : m_cloneDests) { + for (const CloneDestination &d : qAsConst(m_cloneDests)) { if (d.cloneFlipPending) return; } diff --git a/src/plugins/platforms/qnx/qqnxscreeneventhandler.cpp b/src/plugins/platforms/qnx/qqnxscreeneventhandler.cpp index e4843cb438..f29e11489b 100644 --- a/src/plugins/platforms/qnx/qqnxscreeneventhandler.cpp +++ b/src/plugins/platforms/qnx/qqnxscreeneventhandler.cpp @@ -381,6 +381,8 @@ void QQnxScreenEventHandler::handlePointerEvent(screen_event_t event) if (m_lastGlobalMousePoint != globalPoint || m_lastLocalMousePoint != localPoint || m_lastButtonState != buttons) { + if (m_lastButtonState != 0 && buttons == 0) + (static_cast<QQnxWindow *>(w->handle()))->handleActivationEvent(); QWindowSystemInterface::handleMouseEvent(w, localPoint, globalPoint, buttons); qScreenEventDebug() << "Qt mouse, w=" << w << ", (" << localPoint.x() << "," << localPoint.y() << "), b=" << static_cast<int>(buttons); } @@ -457,6 +459,9 @@ void QQnxScreenEventHandler::handleTouchEvent(screen_event_t event, int qnxType) m_lastMouseWindow = qnxWindow; if (w) { + if (qnxType == SCREEN_EVENT_MTOUCH_RELEASE) + (static_cast<QQnxWindow *>(w->handle()))->handleActivationEvent(); + // get size of screen which contains window QPlatformScreen *platformScreen = QPlatformScreen::platformScreenForWindow(w); QSizeF screenSize = platformScreen->geometry().size(); diff --git a/src/plugins/platforms/qnx/qqnxwindow.cpp b/src/plugins/platforms/qnx/qqnxwindow.cpp index 2096bc789e..7644e28b44 100644 --- a/src/plugins/platforms/qnx/qqnxwindow.cpp +++ b/src/plugins/platforms/qnx/qqnxwindow.cpp @@ -156,7 +156,8 @@ QQnxWindow::QQnxWindow(QWindow *window, screen_context_t context, bool needRootW m_visible(false), m_exposed(true), m_windowState(Qt::WindowNoState), - m_mmRendererWindow(0) + m_mmRendererWindow(0), + m_firstActivateHandled(false) { qWindowDebug() << "window =" << window << ", size =" << window->size(); @@ -341,6 +342,14 @@ void QQnxWindow::setVisible(bool visible) if (visible) { applyWindowState(); } else { + if (showWithoutActivating() && focusable() && m_firstActivateHandled) { + m_firstActivateHandled = false; + int val = SCREEN_SENSITIVITY_NO_FOCUS; + Q_SCREEN_CHECKERROR( + screen_set_window_property_iv(m_window, SCREEN_PROPERTY_SENSITIVITY, &val), + "Failed to set window sensitivity"); + } + // Flush the context, otherwise it won't disappear immediately screen_flush_context(m_screenContext, 0); } @@ -618,13 +627,56 @@ void QQnxWindow::requestActivateWindow() void QQnxWindow::setFocus(screen_window_t newFocusWindow) { + screen_window_t temporaryFocusWindow = nullptr; + screen_group_t screenGroup = 0; - screen_get_window_property_pv(nativeHandle(), SCREEN_PROPERTY_GROUP, - reinterpret_cast<void**>(&screenGroup)); - if (screenGroup) { - screen_set_group_property_pv(screenGroup, SCREEN_PROPERTY_FOCUS, - reinterpret_cast<void**>(&newFocusWindow)); + Q_SCREEN_CHECKERROR(screen_get_window_property_pv(nativeHandle(), SCREEN_PROPERTY_GROUP, + reinterpret_cast<void **>(&screenGroup)), + "Failed to retrieve window group"); + + if (showWithoutActivating() && focusable() && !m_firstActivateHandled) { + m_firstActivateHandled = true; + int val = SCREEN_SENSITIVITY_TEST; + Q_SCREEN_CHECKERROR( + screen_set_window_property_iv(m_window, SCREEN_PROPERTY_SENSITIVITY, &val), + "Failed to set window sensitivity"); + +#if _SCREEN_VERSION < _SCREEN_MAKE_VERSION(1, 0, 0) + // For older versions of screen, the window may still have group + // focus even though it was marked NO_FOCUS when it was hidden. + // In that situation, focus has to be given to another window + // so that this window can take focus back from it. + screen_window_t oldFocusWindow = nullptr; + Q_SCREEN_CHECKERROR( + screen_get_group_property_pv(screenGroup, SCREEN_PROPERTY_FOCUS, + reinterpret_cast<void **>(&oldFocusWindow)), + "Failed to retrieve group focus"); + if (newFocusWindow == oldFocusWindow) { + char groupName[256]; + memset(groupName, 0, sizeof(groupName)); + Q_SCREEN_CHECKERROR(screen_get_group_property_cv(screenGroup, SCREEN_PROPERTY_NAME, + sizeof(groupName) - 1, groupName), + "Failed to retrieve group name"); + + Q_SCREEN_CHECKERROR(screen_create_window_type(&temporaryFocusWindow, + m_screenContext, SCREEN_CHILD_WINDOW), + "Failed to create temporary focus window"); + Q_SCREEN_CHECKERROR(screen_join_window_group(temporaryFocusWindow, groupName), + "Temporary focus window failed to join window group"); + Q_SCREEN_CHECKERROR( + screen_set_group_property_pv(screenGroup, SCREEN_PROPERTY_FOCUS, + reinterpret_cast<void **>(&temporaryFocusWindow)), + "Temporary focus window failed to take focus"); + screen_flush_context(m_screenContext, 0); + } +#endif } + + Q_SCREEN_CHECKERROR(screen_set_group_property_pv(screenGroup, SCREEN_PROPERTY_FOCUS, + reinterpret_cast<void **>(&newFocusWindow)), + "Failed to set group focus"); + + screen_destroy_window(temporaryFocusWindow); } void QQnxWindow::setWindowState(Qt::WindowStates state) @@ -711,7 +763,11 @@ void QQnxWindow::initWindow() screen_set_window_property_iv(m_window, SCREEN_PROPERTY_SWAP_INTERVAL, &val), "Failed to set swap interval"); - if (window()->flags() & Qt::WindowDoesNotAcceptFocus) { + if (showWithoutActivating() || !focusable()) { + // NO_FOCUS is temporary for showWithoutActivating (and pop-up) windows. + // Using NO_FOCUS ensures that screen doesn't activate the window because + // it was just created. Sensitivity will be changed to TEST when the + // window is clicked or touched. val = SCREEN_SENSITIVITY_NO_FOCUS; Q_SCREEN_CHECKERROR( screen_set_window_property_iv(m_window, SCREEN_PROPERTY_SENSITIVITY, &val), @@ -825,4 +881,22 @@ bool QQnxWindow::shouldMakeFullScreen() const && (QQnxIntegration::instance()->options() & QQnxIntegration::FullScreenApplication)); } + +void QQnxWindow::handleActivationEvent() +{ + if (showWithoutActivating() && focusable() && !m_firstActivateHandled) + requestActivateWindow(); +} + +bool QQnxWindow::showWithoutActivating() const +{ + return (window()->flags() & Qt::Popup) == Qt::Popup + || window()->property("_q_showWithoutActivating").toBool(); +} + +bool QQnxWindow::focusable() const +{ + return (window()->flags() & Qt::WindowDoesNotAcceptFocus) != Qt::WindowDoesNotAcceptFocus; +} + QT_END_NAMESPACE diff --git a/src/plugins/platforms/qnx/qqnxwindow.h b/src/plugins/platforms/qnx/qqnxwindow.h index 2895a547b1..20c38cb4b7 100644 --- a/src/plugins/platforms/qnx/qqnxwindow.h +++ b/src/plugins/platforms/qnx/qqnxwindow.h @@ -113,6 +113,7 @@ public: bool shouldMakeFullScreen() const; void windowPosted(); + void handleActivationEvent(); protected: virtual int pixelFormat() const = 0; @@ -131,6 +132,8 @@ private: void updateZorder(screen_window_t window, int &zOrder); void applyWindowState(); void setFocus(screen_window_t newFocusWindow); + bool showWithoutActivating() const; + bool focusable() const; screen_window_t m_window; QSize m_bufferSize; @@ -152,6 +155,7 @@ private: QByteArray m_parentGroupName; bool m_isTopLevel; + bool m_firstActivateHandled; }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/vnc/qvnc.cpp b/src/plugins/platforms/vnc/qvnc.cpp index ffe00de2b1..32114c6443 100644 --- a/src/plugins/platforms/vnc/qvnc.cpp +++ b/src/plugins/platforms/vnc/qvnc.cpp @@ -600,7 +600,7 @@ void QVncClientCursor::changeCursor(QCursor *widgetCursor, QWindow *window) cursor = *platformImage.image(); hotspot = platformImage.hotspot(); } - for (auto client : clients) + for (auto client : qAsConst(clients)) client->setDirtyCursor(); } @@ -638,16 +638,14 @@ void QVncServer::init() QVncServer::~QVncServer() { - for (auto client : clients) { - delete client; - } + qDeleteAll(clients); } void QVncServer::setDirty() { - for (auto client : clients) { + for (auto client : qAsConst(clients)) client->setDirty(qvnc_screen->dirtyRegion); - } + qvnc_screen->clearDirty(); } diff --git a/src/plugins/platforms/vnc/qvncscreen.cpp b/src/plugins/platforms/vnc/qvncscreen.cpp index 67d33de2f0..2eca18fb4d 100644 --- a/src/plugins/platforms/vnc/qvncscreen.cpp +++ b/src/plugins/platforms/vnc/qvncscreen.cpp @@ -75,7 +75,7 @@ bool QVncScreen::initialize() mDepth = 32; mPhysicalSize = QSizeF(mGeometry.width()/96.*25.4, mGeometry.height()/96.*25.4); - for (const QString &arg : mArgs) { + for (const QString &arg : qAsConst(mArgs)) { QRegularExpressionMatch match; if (arg.contains(mmSizeRx, &match)) { mPhysicalSize = QSizeF(match.captured("width").toDouble(), match.captured("height").toDouble()); diff --git a/src/plugins/platforms/windows/qwindowsnativeinterface.cpp b/src/plugins/platforms/windows/qwindowsnativeinterface.cpp index de11356fd4..a1ff6f1141 100644 --- a/src/plugins/platforms/windows/qwindowsnativeinterface.cpp +++ b/src/plugins/platforms/windows/qwindowsnativeinterface.cpp @@ -277,6 +277,8 @@ QFunctionPointer QWindowsNativeInterface::platformFunction(const QByteArray &fun return QFunctionPointer(QWindowsWindow::setTouchWindowTouchTypeStatic); if (function == QWindowsWindowFunctions::setHasBorderInFullScreenIdentifier()) return QFunctionPointer(QWindowsWindow::setHasBorderInFullScreenStatic); + if (function == QWindowsWindowFunctions::setHasBorderInFullScreenDefaultIdentifier()) + return QFunctionPointer(QWindowsWindow::setHasBorderInFullScreenDefault); if (function == QWindowsWindowFunctions::setWindowActivationBehaviorIdentifier()) return QFunctionPointer(QWindowsNativeInterface::setWindowActivationBehavior); if (function == QWindowsWindowFunctions::isTabletModeIdentifier()) diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp index f340f16679..6201da7b72 100644 --- a/src/plugins/platforms/windows/qwindowswindow.cpp +++ b/src/plugins/platforms/windows/qwindowswindow.cpp @@ -1190,6 +1190,7 @@ QWindowCreationContext::QWindowCreationContext(const QWindow *w, const char *QWindowsWindow::embeddedNativeParentHandleProperty = "_q_embedded_native_parent_handle"; const char *QWindowsWindow::hasBorderInFullScreenProperty = "_q_has_border_in_fullscreen"; +bool QWindowsWindow::m_borderInFullScreenDefault = false; QWindowsWindow::QWindowsWindow(QWindow *aWindow, const QWindowsWindowData &data) : QWindowsBaseWindow(aWindow), @@ -1227,7 +1228,7 @@ QWindowsWindow::QWindowsWindow(QWindow *aWindow, const QWindowsWindowData &data) if (aWindow->isTopLevel()) setWindowIcon(aWindow->icon()); - if (aWindow->property(hasBorderInFullScreenProperty).toBool()) + if (m_borderInFullScreenDefault || aWindow->property(hasBorderInFullScreenProperty).toBool()) setFlag(HasBorderInFullScreen); clearFlag(WithinCreate); } @@ -2804,6 +2805,11 @@ void QWindowsWindow::setHasBorderInFullScreenStatic(QWindow *window, bool border window->setProperty(hasBorderInFullScreenProperty, QVariant(border)); } +void QWindowsWindow::setHasBorderInFullScreenDefault(bool border) +{ + m_borderInFullScreenDefault = border; +} + void QWindowsWindow::setHasBorderInFullScreen(bool border) { if (testFlag(HasBorderInFullScreen) == border) diff --git a/src/plugins/platforms/windows/qwindowswindow.h b/src/plugins/platforms/windows/qwindowswindow.h index e8c30bd44b..4d136151fe 100644 --- a/src/plugins/platforms/windows/qwindowswindow.h +++ b/src/plugins/platforms/windows/qwindowswindow.h @@ -338,6 +338,7 @@ public: static void setTouchWindowTouchTypeStatic(QWindow *window, QWindowsWindowFunctions::TouchWindowTouchTypes touchTypes); void registerTouchWindow(QWindowsWindowFunctions::TouchWindowTouchTypes touchTypes = QWindowsWindowFunctions::NormalTouch); static void setHasBorderInFullScreenStatic(QWindow *window, bool border); + static void setHasBorderInFullScreenDefault(bool border); void setHasBorderInFullScreen(bool border); static QString formatWindowTitle(const QString &title); @@ -381,6 +382,7 @@ private: // note: intentionally not using void * in order to avoid breaking x86 VkSurfaceKHR m_vkSurface = 0; #endif + static bool m_borderInFullScreenDefault; }; #ifndef QT_NO_DEBUG_STREAM diff --git a/src/plugins/platforms/xcb/nativepainting/qpaintengine_x11_p.h b/src/plugins/platforms/xcb/nativepainting/qpaintengine_x11_p.h index 9b01c0a3fc..bc82351283 100644 --- a/src/plugins/platforms/xcb/nativepainting/qpaintengine_x11_p.h +++ b/src/plugins/platforms/xcb/nativepainting/qpaintengine_x11_p.h @@ -116,7 +116,7 @@ protected: friend GC qt_x11_get_brush_gc(QPainter *); private: - Q_DISABLE_COPY(QX11PaintEngine) + Q_DISABLE_COPY_MOVE(QX11PaintEngine) }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp index 29acf0e86d..1ff06dd39e 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.cpp +++ b/src/plugins/platforms/xcb/qxcbconnection.cpp @@ -132,6 +132,12 @@ QXcbConnection::QXcbConnection(QXcbNativeInterface *nativeInterface, bool canGra if (!m_startupId.isNull()) qunsetenv("DESKTOP_STARTUP_ID"); + m_focusInTimer.setSingleShot(true); + m_focusInTimer.callOnTimeout([]() { + // No FocusIn events for us, proceed with FocusOut normally. + QWindowSystemInterface::handleWindowActivated(nullptr, Qt::ActiveWindowFocusReason); + }); + sync(); } @@ -732,11 +738,6 @@ void QXcbConnection::handleXcbEvent(xcb_generic_event_t *event) m_glIntegration->handleXcbEvent(event, response_type); } -void QXcbConnection::addPeekFunc(PeekFunc f) -{ - m_peekFuncs.append(f); -} - void QXcbConnection::setFocusWindow(QWindow *w) { m_focusWindow = w ? static_cast<QXcbWindow *>(w->handle()) : nullptr; @@ -1016,15 +1017,6 @@ void QXcbConnection::processXcbEvents(QEventLoop::ProcessEventsFlags flags) if (compressEvent(event)) continue; - auto isWaitingFor = [=](PeekFunc peekFunc) { - // These callbacks return true if the event is what they were - // waiting for, remove them from the list in that case. - return peekFunc(this, event); - }; - m_peekFuncs.erase(std::remove_if(m_peekFuncs.begin(), m_peekFuncs.end(), - isWaitingFor), - m_peekFuncs.end()); - handleXcbEvent(event); // The lock-based solution used to free the lock inside this loop, @@ -1033,12 +1025,6 @@ void QXcbConnection::processXcbEvents(QEventLoop::ProcessEventsFlags flags) m_eventQueue->flushBufferedEvents(); } - // Indicate with a null event that the event the callbacks are waiting for - // is not in the queue currently. - for (PeekFunc f : qAsConst(m_peekFuncs)) - f(this, nullptr); - m_peekFuncs.clear(); - xcb_flush(xcb_connection()); } diff --git a/src/plugins/platforms/xcb/qxcbconnection.h b/src/plugins/platforms/xcb/qxcbconnection.h index 47036ca257..d63888b48f 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.h +++ b/src/plugins/platforms/xcb/qxcbconnection.h @@ -43,6 +43,7 @@ #include <xcb/xcb.h> #include <xcb/randr.h> +#include <QtCore/QTimer> #include <QtGui/private/qtguiglobal_p.h> #include "qxcbexport.h" #include <QHash> @@ -183,9 +184,6 @@ public: QXcbWindowEventListener *windowEventListenerFromId(xcb_window_t id); QXcbWindow *platformWindowFromId(xcb_window_t id); - typedef bool (*PeekFunc)(QXcbConnection *, xcb_generic_event_t *); - void addPeekFunc(PeekFunc f); - inline xcb_timestamp_t time() const { return m_time; } inline void setTime(xcb_timestamp_t t) { if (t > m_time) m_time = t; } @@ -247,6 +245,8 @@ public: void flush() { xcb_flush(xcb_connection()); } void processXcbEvents(QEventLoop::ProcessEventsFlags flags); + QTimer &focusInTimer() { return m_focusInTimer; }; + protected: bool event(QEvent *e) override; @@ -364,8 +364,6 @@ private: WindowMapper m_mapper; - QVector<PeekFunc> m_peekFuncs; - Qt::MouseButtons m_buttonState = 0; Qt::MouseButton m_button = Qt::NoButton; @@ -386,6 +384,8 @@ private: friend class QXcbEventQueue; QByteArray m_xdgCurrentDesktop; + QTimer m_focusInTimer; + }; #if QT_CONFIG(xcb_xinput) #if QT_CONFIG(tabletevent) diff --git a/src/plugins/platforms/xcb/qxcbconnection_screens.cpp b/src/plugins/platforms/xcb/qxcbconnection_screens.cpp index 9aba996bb9..4bafe83156 100644 --- a/src/plugins/platforms/xcb/qxcbconnection_screens.cpp +++ b/src/plugins/platforms/xcb/qxcbconnection_screens.cpp @@ -208,7 +208,7 @@ void QXcbConnection::updateScreen(QXcbScreen *screen, const xcb_randr_output_cha const int idx = m_screens.indexOf(screen); if (idx > 0) { qAsConst(m_screens).first()->setPrimary(false); - m_screens.swap(0, idx); + m_screens.swapItemsAt(0, idx); } screen->virtualDesktop()->setPrimaryScreen(screen); QXcbIntegration::instance()->setPrimaryScreen(screen); @@ -260,7 +260,7 @@ void QXcbConnection::destroyScreen(QXcbScreen *screen) newPrimary->setPrimary(true); const int idx = m_screens.indexOf(newPrimary); if (idx > 0) - m_screens.swap(0, idx); + m_screens.swapItemsAt(0, idx); QXcbIntegration::instance()->setPrimaryScreen(newPrimary); } diff --git a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp index 04ddd3c98c..78ef7760af 100644 --- a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp +++ b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp @@ -637,7 +637,7 @@ void QXcbConnection::xi2ProcessTouch(void *xiDevEvent, QXcbWindow *platformWindo qreal nx = -1.0, ny = -1.0; qreal w = 0.0, h = 0.0; bool majorAxisIsY = touchPoint.area.height() > touchPoint.area.width(); - for (const TouchDeviceData::ValuatorClassInfo vci : dev->valuatorInfo) { + for (const TouchDeviceData::ValuatorClassInfo &vci : qAsConst(dev->valuatorInfo)) { double value; if (!xi2GetValuatorValueIfSet(xiDeviceEvent, vci.number, &value)) continue; @@ -823,7 +823,7 @@ bool QXcbConnection::xi2SetMouseGrabEnabled(xcb_window_t w, bool grab) | XCB_INPUT_XI_EVENT_MASK_TOUCH_UPDATE | XCB_INPUT_XI_EVENT_MASK_TOUCH_END; - for (int id : m_xiMasterPointerIds) { + for (int id : qAsConst(m_xiMasterPointerIds)) { xcb_generic_error_t *error = nullptr; auto cookie = xcb_input_xi_grab_device(xcb_connection(), w, XCB_CURRENT_TIME, XCB_CURSOR_NONE, id, XCB_INPUT_GRAB_MODE_22_ASYNC, XCB_INPUT_GRAB_MODE_22_ASYNC, @@ -841,7 +841,7 @@ bool QXcbConnection::xi2SetMouseGrabEnabled(xcb_window_t w, bool grab) free(reply); } } else { // ungrab - for (int id : m_xiMasterPointerIds) { + for (int id : qAsConst(m_xiMasterPointerIds)) { auto cookie = xcb_input_xi_ungrab_device_checked(xcb_connection(), XCB_CURRENT_TIME, id); xcb_generic_error_t *error = xcb_request_check(xcb_connection(), cookie); if (error) { diff --git a/src/plugins/platforms/xcb/qxcbeventqueue.cpp b/src/plugins/platforms/xcb/qxcbeventqueue.cpp index f6158d3127..527bca26a8 100644 --- a/src/plugins/platforms/xcb/qxcbeventqueue.cpp +++ b/src/plugins/platforms/xcb/qxcbeventqueue.cpp @@ -260,7 +260,7 @@ qint32 QXcbEventQueue::generatePeekerId() bool QXcbEventQueue::removePeekerId(qint32 peekerId) { - const auto it = m_peekerToNode.find(peekerId); + const auto it = m_peekerToNode.constFind(peekerId); if (it == m_peekerToNode.constEnd()) { qCWarning(lcQpaXcb, "failed to remove unknown peeker id: %d", peekerId); return false; @@ -279,7 +279,7 @@ bool QXcbEventQueue::peekEventQueue(PeekerCallback peeker, void *peekerData, const bool peekerIdProvided = peekerId != -1; auto peekerToNodeIt = m_peekerToNode.find(peekerId); - if (peekerIdProvided && peekerToNodeIt == m_peekerToNode.constEnd()) { + if (peekerIdProvided && peekerToNodeIt == m_peekerToNode.end()) { qCWarning(lcQpaXcb, "failed to find index for unknown peeker id: %d", peekerId); return false; } @@ -339,7 +339,7 @@ bool QXcbEventQueue::peekEventQueue(PeekerCallback peeker, void *peekerData, // Before updating, make sure that a peeker callback did not remove // the peeker id. peekerToNodeIt = m_peekerToNode.find(peekerId); - if (peekerToNodeIt != m_peekerToNode.constEnd()) + if (peekerToNodeIt != m_peekerToNode.end()) *peekerToNodeIt = node; // id still in the cache, update node } diff --git a/src/plugins/platforms/xcb/qxcbnativeinterface.cpp b/src/plugins/platforms/xcb/qxcbnativeinterface.cpp index 524af5a2a7..4d526a6bda 100644 --- a/src/plugins/platforms/xcb/qxcbnativeinterface.cpp +++ b/src/plugins/platforms/xcb/qxcbnativeinterface.cpp @@ -304,7 +304,7 @@ QPlatformNativeInterface::NativeResourceForWindowFunction QXcbNativeInterface::n QPlatformNativeInterface::NativeResourceForBackingStoreFunction QXcbNativeInterface::nativeResourceFunctionForBackingStore(const QByteArray &resource) { const QByteArray lowerCaseResource = resource.toLower(); - NativeResourceForBackingStoreFunction func = handlerNativeResourceFunctionForBackingStore(resource); + NativeResourceForBackingStoreFunction func = handlerNativeResourceFunctionForBackingStore(lowerCaseResource); return func; } diff --git a/src/plugins/platforms/xcb/qxcbscreen.cpp b/src/plugins/platforms/xcb/qxcbscreen.cpp index 57dbdc9bec..0fa0e8cd7b 100644 --- a/src/plugins/platforms/xcb/qxcbscreen.cpp +++ b/src/plugins/platforms/xcb/qxcbscreen.cpp @@ -147,7 +147,7 @@ void QXcbVirtualDesktop::setPrimaryScreen(QPlatformScreen *s) { const int idx = m_screens.indexOf(s); Q_ASSERT(idx > -1); - m_screens.swap(0, idx); + m_screens.swapItemsAt(0, idx); } QXcbXSettings *QXcbVirtualDesktop::xSettings() const diff --git a/src/plugins/platforms/xcb/qxcbsessionmanager.h b/src/plugins/platforms/xcb/qxcbsessionmanager.h index 0ad9445361..79c587b38d 100644 --- a/src/plugins/platforms/xcb/qxcbsessionmanager.h +++ b/src/plugins/platforms/xcb/qxcbsessionmanager.h @@ -85,8 +85,6 @@ public: private: QEventLoop *m_eventLoop; - - Q_DISABLE_COPY(QXcbSessionManager) }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp index 3bfcbf2adb..9382488b74 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.cpp +++ b/src/plugins/platforms/xcb/qxcbwindow.cpp @@ -843,40 +843,12 @@ void QXcbWindow::doFocusIn() QWindowSystemInterface::handleWindowActivated(w, Qt::ActiveWindowFocusReason); } -static bool focusInPeeker(QXcbConnection *connection, xcb_generic_event_t *event) -{ - if (!event) { - // FocusIn event is not in the queue, proceed with FocusOut normally. - QWindowSystemInterface::handleWindowActivated(nullptr, Qt::ActiveWindowFocusReason); - return true; - } - uint response_type = event->response_type & ~0x80; - if (response_type == XCB_FOCUS_IN) { - // Ignore focus events that are being sent only because the pointer is over - // our window, even if the input focus is in a different window. - xcb_focus_in_event_t *e = (xcb_focus_in_event_t *) event; - if (e->detail != XCB_NOTIFY_DETAIL_POINTER) - return true; - } - - /* We are also interested in XEMBED_FOCUS_IN events */ - if (response_type == XCB_CLIENT_MESSAGE) { - xcb_client_message_event_t *cme = (xcb_client_message_event_t *)event; - if (cme->type == connection->atom(QXcbAtom::_XEMBED) - && cme->data.data32[1] == XEMBED_FOCUS_IN) - return true; - } - - return false; -} - void QXcbWindow::doFocusOut() { connection()->setFocusWindow(nullptr); relayFocusToModalWindow(); // Do not set the active window to nullptr if there is a FocusIn coming. - // The FocusIn handler will update QXcbConnection::setFocusWindow() accordingly. - connection()->addPeekFunc(focusInPeeker); + connection()->focusInTimer().start(400); } struct QtMotifWmHints { @@ -2264,6 +2236,8 @@ void QXcbWindow::handleFocusInEvent(const xcb_focus_in_event_t *event) // our window, even if the input focus is in a different window. if (event->detail == XCB_NOTIFY_DETAIL_POINTER) return; + + connection()->focusInTimer().stop(); doFocusIn(); } @@ -2491,6 +2465,7 @@ void QXcbWindow::handleXEmbedMessage(const xcb_client_message_event_t *event) xcbScreen()->windowShown(this); break; case XEMBED_FOCUS_IN: + connection()->focusInTimer().stop(); Qt::FocusReason reason; switch (event->data.data32[2]) { case XEMBED_FOCUS_FIRST: |