diff options
author | Johan Klokkhammer Helsing <johan.helsing@qt.io> | 2016-06-01 16:23:23 +0200 |
---|---|---|
committer | Johan Helsing <johan.helsing@qt.io> | 2016-07-04 14:05:30 +0000 |
commit | f497a5bb87270174b8e0106b7eca1992d44ff15d (patch) | |
tree | 78c0a273b27de1dee2beed135cae18524a71f9e5 /src/client/qwaylanddisplay.cpp | |
parent | 00a65be5ae8e1253ed6fd1f2e1df745f4c319de5 (diff) |
Use xdg_shell configure events to determine active window
According to the xdg_shell protocol, the compositor is allowed to set multiple
active windows. Qt's model, however, allows only a single active window.
In order to map between the models, a list of the compositor's active windows
is kept in QWaylandDisplay in the order they were activated. Hence, the front
of this list will always be the most recently activated window, and it will be
mapped as Qt's active window.
Previously keyboard focus was used to determine the active window, this method
has been disabled for xdg_shell.
Functionality for delaying the call to
QWindowSystemInterface::handleWindowActivated has been moved from
QWaylandInputDevice::Keyboard to QWaylandDisplay so the implementations can
share the workaround.
Task-number: QTBUG-53702
Change-Id: I878151f9c52ed09a8d6571c6208920436c3ca8fc
Reviewed-by: Giulio Camuffo <giulio.camuffo@kdab.com>
Diffstat (limited to 'src/client/qwaylanddisplay.cpp')
-rw-r--r-- | src/client/qwaylanddisplay.cpp | 69 |
1 files changed, 69 insertions, 0 deletions
diff --git a/src/client/qwaylanddisplay.cpp b/src/client/qwaylanddisplay.cpp index 4358bf69f..f6d86bb39 100644 --- a/src/client/qwaylanddisplay.cpp +++ b/src/client/qwaylanddisplay.cpp @@ -130,6 +130,8 @@ QWaylandDisplay::QWaylandDisplay(QWaylandIntegration *waylandIntegration) , mLastInputSerial(0) , mLastInputDevice(0) , mLastInputWindow(0) + , mLastKeyboardFocus(Q_NULLPTR) + , mSyncCallback(Q_NULLPTR) { qRegisterMetaType<uint32_t>("uint32_t"); @@ -383,6 +385,73 @@ void QWaylandDisplay::setLastInputDevice(QWaylandInputDevice *device, uint32_t s mLastInputWindow = win; } +bool QWaylandDisplay::shellManagesActiveState() const +{ + //TODO: This should be part of a shell interface used by the shell protocol implementations + return mShellXdg; +} + +void QWaylandDisplay::handleWindowActivated(QWaylandWindow *window) +{ + if (mActiveWindows.contains(window)) + return; + + mActiveWindows.append(window); + requestWaylandSync(); +} + +void QWaylandDisplay::handleWindowDeactivated(QWaylandWindow *window) +{ + Q_ASSERT(!mActiveWindows.empty()); + + if (mActiveWindows.last() == window) + requestWaylandSync(); + + mActiveWindows.removeOne(window); +} + +void QWaylandDisplay::handleKeyboardFocusChanged(QWaylandInputDevice *inputDevice) +{ + QWaylandWindow *keyboardFocus = inputDevice->keyboardFocus(); + + if (!shellManagesActiveState() && mLastKeyboardFocus != keyboardFocus) { + if (keyboardFocus) + handleWindowActivated(keyboardFocus); + if (mLastKeyboardFocus) + handleWindowDeactivated(mLastKeyboardFocus); + } + mLastKeyboardFocus = inputDevice->keyboardFocus(); +} + +void QWaylandDisplay::handleWaylandSync() +{ + // This callback is used to set the window activation because we may get an activate/deactivate + // pair, and the latter one would be lost in the QWindowSystemInterface queue, if we issue the + // handleWindowActivated() calls immediately. + QWindow *activeWindow = mActiveWindows.empty() ? Q_NULLPTR : mActiveWindows.last()->window(); + if (activeWindow != QGuiApplication::focusWindow()) + QWindowSystemInterface::handleWindowActivated(activeWindow); +} + +const wl_callback_listener QWaylandDisplay::syncCallbackListener = { + [](void *data, struct wl_callback *callback, uint32_t time){ + Q_UNUSED(time); + wl_callback_destroy(callback); + QWaylandDisplay *display = static_cast<QWaylandDisplay *>(data); + display->mSyncCallback = Q_NULLPTR; + display->handleWaylandSync(); + } +}; + +void QWaylandDisplay::requestWaylandSync() +{ + if (mSyncCallback) + return; + + mSyncCallback = wl_display_sync(mDisplay); + wl_callback_add_listener(mSyncCallback, &syncCallbackListener, this); +} + } QT_END_NAMESPACE |