diff options
author | Liang Qi <liang.qi@qt.io> | 2016-04-27 09:18:05 +0200 |
---|---|---|
committer | Liang Qi <liang.qi@qt.io> | 2016-04-27 09:18:05 +0200 |
commit | 23a36fd2bfcdb57849deaa1e10e6e3f7b1156ed8 (patch) | |
tree | b527c7e3ba4a831b542b0bccfb6a5a748a8a4fd9 /src/plugins/platforms | |
parent | c003a18ee332abf2387172eb0856a176a32a6c8f (diff) | |
parent | 072f5b513e486e884ea7fa4a1cac9aedf3846374 (diff) |
Merge remote-tracking branch 'origin/5.6' into 5.7
Conflicts:
src/corelib/io/qprocess_win.cpp
src/widgets/itemviews/qheaderview.cpp
Change-Id: I0a59ade9cd6e91f770fdf298a7d72a41e79fd761
Diffstat (limited to 'src/plugins/platforms')
-rw-r--r-- | src/plugins/platforms/cocoa/qcocoawindow.h | 6 | ||||
-rw-r--r-- | src/plugins/platforms/cocoa/qcocoawindow.mm | 6 | ||||
-rw-r--r-- | src/plugins/platforms/windows/qwindowsintegration.cpp | 5 | ||||
-rw-r--r-- | src/plugins/platforms/winrt/qwinrtscreen.cpp | 2 | ||||
-rw-r--r-- | src/plugins/platforms/xcb/qxcbconnection.cpp | 6 | ||||
-rw-r--r-- | src/plugins/platforms/xcb/qxcbconnection.h | 3 | ||||
-rw-r--r-- | src/plugins/platforms/xcb/qxcbwindow.cpp | 70 |
7 files changed, 78 insertions, 20 deletions
diff --git a/src/plugins/platforms/cocoa/qcocoawindow.h b/src/plugins/platforms/cocoa/qcocoawindow.h index 4d2af84e8e..4d5f5d74f2 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.h +++ b/src/plugins/platforms/cocoa/qcocoawindow.h @@ -72,6 +72,7 @@ typedef NSWindow<QNSWindowProtocol> QCocoaNSWindow; QCocoaWindow *_platformWindow; BOOL _grabbingMouse; BOOL _releaseOnMouseUp; + QPointer<QObject> _watcher; } @property (nonatomic, readonly) QCocoaNSWindow *window; @@ -321,6 +322,11 @@ public: // for QNSView }; QHash<quintptr, BorderRange> m_contentBorderAreas; // identifer -> uppper/lower QHash<quintptr, bool> m_enabledContentBorderAreas; // identifer -> enabled state (true/false) + + // This object is tracked by a 'watcher' + // object in a window helper, preventing use of dangling + // pointers. + QObject sentinel; }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm index 29cc4130ed..01e72303be 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.mm +++ b/src/plugins/platforms/cocoa/qcocoawindow.mm @@ -99,6 +99,7 @@ static bool isMouseEvent(NSEvent *ev) // make sure that m_nsWindow stays valid until the // QCocoaWindow is deleted by Qt. [_window setReleasedWhenClosed:NO]; + _watcher = &_platformWindow->sentinel; } return self; @@ -107,7 +108,7 @@ static bool isMouseEvent(NSEvent *ev) - (void)handleWindowEvent:(NSEvent *)theEvent { QCocoaWindow *pw = self.platformWindow; - if (pw && pw->m_forwardWindow) { + if (_watcher && pw && pw->m_forwardWindow) { if (theEvent.type == NSLeftMouseUp || theEvent.type == NSLeftMouseDragged) { QNSView *forwardView = pw->m_qtView; if (theEvent.type == NSLeftMouseUp) { @@ -146,7 +147,7 @@ static bool isMouseEvent(NSEvent *ev) if (!self.window.delegate) return; // Already detached, pending NSAppKitDefined event - if (pw && pw->frameStrutEventsEnabled() && isMouseEvent(theEvent)) { + if (_watcher && pw && pw->frameStrutEventsEnabled() && isMouseEvent(theEvent)) { NSPoint loc = [theEvent locationInWindow]; NSRect windowFrame = [self.window convertRectFromScreen:[self.window frame]]; NSRect contentFrame = [[self.window contentView] frame]; @@ -162,6 +163,7 @@ static bool isMouseEvent(NSEvent *ev) - (void)detachFromPlatformWindow { _platformWindow = 0; + _watcher.clear(); [self.window.delegate release]; self.window.delegate = nil; } diff --git a/src/plugins/platforms/windows/qwindowsintegration.cpp b/src/plugins/platforms/windows/qwindowsintegration.cpp index 9486dd84f0..b524adb2cb 100644 --- a/src/plugins/platforms/windows/qwindowsintegration.cpp +++ b/src/plugins/platforms/windows/qwindowsintegration.cpp @@ -374,13 +374,11 @@ QWindowsWindow *QWindowsIntegration::createPlatformWindowHelper(QWindow *window, QWindowsStaticOpenGLContext *QWindowsStaticOpenGLContext::doCreate() { #if defined(QT_OPENGL_DYNAMIC) - const QWindowsOpenGLTester::Renderers supportedRenderers = QWindowsOpenGLTester::supportedRenderers(); - QWindowsOpenGLTester::Renderer requestedRenderer = QWindowsOpenGLTester::requestedRenderer(); switch (requestedRenderer) { case QWindowsOpenGLTester::DesktopGl: if (QWindowsStaticOpenGLContext *glCtx = QOpenGLStaticContext::create()) { - if ((supportedRenderers & QWindowsOpenGLTester::DisableRotationFlag) + if ((QWindowsOpenGLTester::supportedRenderers() & QWindowsOpenGLTester::DisableRotationFlag) && !QWindowsScreen::setOrientationPreference(Qt::LandscapeOrientation)) { qCWarning(lcQpaGl, "Unable to disable rotation."); } @@ -406,6 +404,7 @@ QWindowsStaticOpenGLContext *QWindowsStaticOpenGLContext::doCreate() break; } + const QWindowsOpenGLTester::Renderers supportedRenderers = QWindowsOpenGLTester::supportedRenderers(); if (supportedRenderers & QWindowsOpenGLTester::DesktopGl) { if (QWindowsStaticOpenGLContext *glCtx = QOpenGLStaticContext::create()) { if ((supportedRenderers & QWindowsOpenGLTester::DisableRotationFlag) diff --git a/src/plugins/platforms/winrt/qwinrtscreen.cpp b/src/plugins/platforms/winrt/qwinrtscreen.cpp index aec09a260b..f3667aaa0d 100644 --- a/src/plugins/platforms/winrt/qwinrtscreen.cpp +++ b/src/plugins/platforms/winrt/qwinrtscreen.cpp @@ -1135,6 +1135,8 @@ HRESULT QWinRTScreen::onActivated(ICoreWindow *, IWindowActivatedEventArgs *args return S_OK; } + QWindowSystemInterface::handleApplicationStateChanged(Qt::ApplicationActive); + // Activate topWindow if (!d->visibleWindows.isEmpty()) { Qt::FocusReason focusReason = activationState == CoreWindowActivationState_PointerActivated diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp index 2e51576e3b..5ad349fdc2 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.cpp +++ b/src/plugins/platforms/xcb/qxcbconnection.cpp @@ -567,6 +567,7 @@ QXcbConnection::QXcbConnection(QXcbNativeInterface *nativeInterface, bool canGra , m_buttons(0) , m_focusWindow(0) , m_mouseGrabber(0) + , m_mousePressWindow(0) , m_clientLeader(0) , m_systemTrayTracker(0) , m_glIntegration(Q_NULLPTR) @@ -1379,6 +1380,11 @@ void QXcbConnection::setFocusWindow(QXcbWindow *w) void QXcbConnection::setMouseGrabber(QXcbWindow *w) { m_mouseGrabber = w; + m_mousePressWindow = Q_NULLPTR; +} +void QXcbConnection::setMousePressWindow(QXcbWindow *w) +{ + m_mousePressWindow = w; } void QXcbConnection::grabServer() diff --git a/src/plugins/platforms/xcb/qxcbconnection.h b/src/plugins/platforms/xcb/qxcbconnection.h index e8af82ec8c..68d7b5622f 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.h +++ b/src/plugins/platforms/xcb/qxcbconnection.h @@ -481,6 +481,8 @@ public: void setFocusWindow(QXcbWindow *); QXcbWindow *mouseGrabber() const { return m_mouseGrabber; } void setMouseGrabber(QXcbWindow *); + QXcbWindow *mousePressWindow() const { return m_mousePressWindow; } + void setMousePressWindow(QXcbWindow *); QByteArray startupId() const { return m_startupId; } void setStartupId(const QByteArray &nextId) { m_startupId = nextId; } @@ -668,6 +670,7 @@ private: QXcbWindow *m_focusWindow; QXcbWindow *m_mouseGrabber; + QXcbWindow *m_mousePressWindow; xcb_window_t m_clientLeader; QByteArray m_startupId; diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp index 5e4aaa37d9..c507ac09b6 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.cpp +++ b/src/plugins/platforms/xcb/qxcbwindow.cpp @@ -592,8 +592,12 @@ QXcbWindow::~QXcbWindow() { if (window()->type() != Qt::ForeignWindow) destroy(); - else if (connection()->mouseGrabber() == this) - connection()->setMouseGrabber(Q_NULLPTR); + else { + if (connection()->mouseGrabber() == this) + connection()->setMouseGrabber(Q_NULLPTR); + if (connection()->mousePressWindow() == this) + connection()->setMousePressWindow(Q_NULLPTR); + } } void QXcbWindow::destroy() @@ -851,6 +855,16 @@ void QXcbWindow::hide() if (connection()->mouseGrabber() == this) connection()->setMouseGrabber(Q_NULLPTR); + if (QPlatformWindow *w = connection()->mousePressWindow()) { + // Unset mousePressWindow when it (or one of its parents) is unmapped + while (w) { + if (w == this) { + connection()->setMousePressWindow(Q_NULLPTR); + break; + } + w = w->parent(); + } + } m_mapped = false; @@ -2199,6 +2213,8 @@ void QXcbWindow::handleButtonPressEvent(int event_x, int event_y, int root_x, in return; } + connection()->setMousePressWindow(this); + handleMouseEvent(timestamp, local, global, modifiers, source); } @@ -2213,19 +2229,44 @@ void QXcbWindow::handleButtonReleaseEvent(int event_x, int event_y, int root_x, return; } + if (connection()->buttons() == Qt::NoButton) + connection()->setMousePressWindow(Q_NULLPTR); + handleMouseEvent(timestamp, local, global, modifiers, source); } -static bool ignoreLeaveEvent(quint8 mode, quint8 detail) +static inline bool doCheckUnGrabAncestor(QXcbConnection *conn) +{ + /* Checking for XCB_NOTIFY_MODE_GRAB and XCB_NOTIFY_DETAIL_ANCESTOR prevents unwanted + * enter/leave events on AwesomeWM on mouse button press. It also ignores duplicated + * enter/leave events on Alt+Tab switching on some WMs with XInput2 events. + * Without XInput2 events the (Un)grabAncestor cannot be checked when mouse button is + * not pressed, otherwise (e.g. on Alt+Tab) it can igonre important enter/leave events. + */ + if (conn) { + const bool mouseButtonsPressed = (conn->buttons() != Qt::NoButton); +#ifdef XCB_USE_XINPUT22 + return mouseButtonsPressed || (conn->isAtLeastXI22() && conn->xi2MouseEvents()); +#else + return mouseButtonsPressed; +#endif + } + return true; +} + +static bool ignoreLeaveEvent(quint8 mode, quint8 detail, QXcbConnection *conn = Q_NULLPTR) { - return (mode == XCB_NOTIFY_MODE_GRAB && detail == XCB_NOTIFY_DETAIL_ANCESTOR) // Check for AwesomeWM + return ((doCheckUnGrabAncestor(conn) + && mode == XCB_NOTIFY_MODE_GRAB && detail == XCB_NOTIFY_DETAIL_ANCESTOR) + || (mode == XCB_NOTIFY_MODE_UNGRAB && detail == XCB_NOTIFY_DETAIL_INFERIOR) || detail == XCB_NOTIFY_DETAIL_VIRTUAL - || detail == XCB_NOTIFY_DETAIL_NONLINEAR_VIRTUAL; + || detail == XCB_NOTIFY_DETAIL_NONLINEAR_VIRTUAL); } -static bool ignoreEnterEvent(quint8 mode, quint8 detail) +static bool ignoreEnterEvent(quint8 mode, quint8 detail, QXcbConnection *conn = Q_NULLPTR) { - return ((mode == XCB_NOTIFY_MODE_UNGRAB && detail == XCB_NOTIFY_DETAIL_ANCESTOR) // Check for AwesomeWM + return ((doCheckUnGrabAncestor(conn) + && mode == XCB_NOTIFY_MODE_UNGRAB && detail == XCB_NOTIFY_DETAIL_ANCESTOR) || (mode != XCB_NOTIFY_MODE_NORMAL && mode != XCB_NOTIFY_MODE_UNGRAB) || detail == XCB_NOTIFY_DETAIL_VIRTUAL || detail == XCB_NOTIFY_DETAIL_NONLINEAR_VIRTUAL); @@ -2259,9 +2300,7 @@ void QXcbWindow::handleEnterNotifyEvent(int event_x, int event_y, int root_x, in const QPoint global = QPoint(root_x, root_y); - if (ignoreEnterEvent(mode, detail) - || (connection()->buttons() != Qt::NoButton - && QGuiApplicationPrivate::lastCursorPosition != global)) + if (ignoreEnterEvent(mode, detail, connection()) || connection()->mousePressWindow()) return; const QPoint local(event_x, event_y); @@ -2273,11 +2312,7 @@ void QXcbWindow::handleLeaveNotifyEvent(int root_x, int root_y, { connection()->setTime(timestamp); - const QPoint global(root_x, root_y); - - if (ignoreLeaveEvent(mode, detail) - || (connection()->buttons() != Qt::NoButton - && QGuiApplicationPrivate::lastCursorPosition != global)) + if (ignoreLeaveEvent(mode, detail, connection()) || connection()->mousePressWindow()) return; EnterEventChecker checker; @@ -2300,6 +2335,11 @@ void QXcbWindow::handleMotionNotifyEvent(int event_x, int event_y, int root_x, i { QPoint local(event_x, event_y); QPoint global(root_x, root_y); + + // "mousePressWindow" can be NULL i.e. if a window will be grabbed or umnapped, so set it again here + if (connection()->buttons() != Qt::NoButton && connection()->mousePressWindow() == Q_NULLPTR) + connection()->setMousePressWindow(this); + handleMouseEvent(timestamp, local, global, modifiers, source); } |