From 93c09bcafbc6f2accd11d34433dc475822ba7712 Mon Sep 17 00:00:00 2001 From: Johan Klokkhammer Helsing Date: Wed, 24 Aug 2016 16:08:56 +0200 Subject: Client: Fix keyboard focus logic and crash The previous solution did not check for nullptr before dereferencing, which caused a crash. Furthermore, it checked the new ShellSurface's shellManagesActiveState before deciding whether to unfocus the old one. Task-number: QTBUG-55526 Change-Id: I410b6200a5b7b86806f70970730045a4a25f21db Reviewed-by: Paul Olav Tvete --- src/client/qwaylanddisplay.cpp | 17 ++++++++++------- src/client/qwaylandwindow.cpp | 5 +++++ src/client/qwaylandwindow_p.h | 2 ++ 3 files changed, 17 insertions(+), 7 deletions(-) diff --git a/src/client/qwaylanddisplay.cpp b/src/client/qwaylanddisplay.cpp index 7225d24af..ae28eb779 100644 --- a/src/client/qwaylanddisplay.cpp +++ b/src/client/qwaylanddisplay.cpp @@ -399,13 +399,16 @@ void QWaylandDisplay::handleKeyboardFocusChanged(QWaylandInputDevice *inputDevic { QWaylandWindow *keyboardFocus = inputDevice->keyboardFocus(); - if (!keyboardFocus->shellSurface()->shellManagesActiveState() && mLastKeyboardFocus != keyboardFocus) { - if (keyboardFocus) - handleWindowActivated(keyboardFocus); - if (mLastKeyboardFocus) - handleWindowDeactivated(mLastKeyboardFocus); - } - mLastKeyboardFocus = inputDevice->keyboardFocus(); + if (mLastKeyboardFocus == keyboardFocus) + return; + + if (keyboardFocus && !keyboardFocus->shellManagesActiveState()) + handleWindowActivated(keyboardFocus); + + if (mLastKeyboardFocus && !mLastKeyboardFocus->shellManagesActiveState()) + handleWindowDeactivated(mLastKeyboardFocus); + + mLastKeyboardFocus = keyboardFocus; } void QWaylandDisplay::handleWaylandSync() diff --git a/src/client/qwaylandwindow.cpp b/src/client/qwaylandwindow.cpp index aba676533..8885c0e5d 100644 --- a/src/client/qwaylandwindow.cpp +++ b/src/client/qwaylandwindow.cpp @@ -500,6 +500,11 @@ QWaylandSubSurface *QWaylandWindow::subSurfaceWindow() const return mSubSurfaceWindow; } +bool QWaylandWindow::shellManagesActiveState() const +{ + return mShellSurface && mShellSurface->shellManagesActiveState(); +} + void QWaylandWindow::handleContentOrientationChange(Qt::ScreenOrientation orientation) { if (mDisplay->compositorVersion() < 2) diff --git a/src/client/qwaylandwindow_p.h b/src/client/qwaylandwindow_p.h index c60891d49..d7e795159 100644 --- a/src/client/qwaylandwindow_p.h +++ b/src/client/qwaylandwindow_p.h @@ -136,6 +136,8 @@ public: QWaylandSubSurface *subSurfaceWindow() const; QWaylandScreen *screen() const { return mScreen; } + bool shellManagesActiveState() const; + void handleContentOrientationChange(Qt::ScreenOrientation orientation) Q_DECL_OVERRIDE; void setOrientationMask(Qt::ScreenOrientations mask); -- cgit v1.2.3 From 54b819679cd39e997cc9319deaf432c37667ae6f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Gr=C3=A4=C3=9Flin?= Date: Mon, 22 Aug 2016 08:18:53 +0200 Subject: Pass TRANSIENT_INACTIVE flag for windows with WA_ShowWithoutActivating When setting a transient window also evaluate the state of the window attribute WA_ShowWithoutActivating. If that flag is set the transient should get the inactive flag as well. Task-number: QTBUG-55403 Change-Id: I757e5527e78f730a440e26abb52e84c9b2bb2f3a Reviewed-by: Johan Helsing Reviewed-by: Giulio Camuffo --- src/client/qwaylandwlshellsurface.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/client/qwaylandwlshellsurface.cpp b/src/client/qwaylandwlshellsurface.cpp index 7235931d3..553d458d3 100644 --- a/src/client/qwaylandwlshellsurface.cpp +++ b/src/client/qwaylandwlshellsurface.cpp @@ -151,6 +151,13 @@ void QWaylandWlShellSurface::setTopLevel() set_toplevel(); } +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 QWaylandWlShellSurface::updateTransientParent(QWindow *parent) { QWaylandWindow *parent_wayland_window = static_cast(parent->handle()); @@ -168,7 +175,8 @@ void QWaylandWlShellSurface::updateTransientParent(QWindow *parent) uint32_t flags = 0; Qt::WindowFlags wf = m_window->window()->flags(); if (wf.testFlag(Qt::ToolTip) - || wf.testFlag(Qt::WindowTransparentForInput)) + || wf.testFlag(Qt::WindowTransparentForInput) + || testShowWithoutActivating(m_window->window())) flags |= WL_SHELL_SURFACE_TRANSIENT_INACTIVE; set_transient(parent_wayland_window->object(), -- cgit v1.2.3