Delayed focus updates for Toplevels without surface

Summary:
XWayland clients have a surface associated with them asynchronously. In this
case we don't directly want to set focus on this Toplevel, but wait until the
surface is set.

This patch aims in conjunction with an unrelated fix to SDL at improving Steam
Big Picture Mode in our Wayland session.

Test Plan: Steam BPM regains focus on game close.

Reviewers: #kwin, zzag

Reviewed By: #kwin, zzag

Subscribers: anthonyfieroni, davidedmundson, zzag, kwin

Tags: #kwin

Differential Revision: https://phabricator.kde.org/D19262
master
Roman Gilg 5 years ago
parent 2e20cac5e2
commit 846961bfae

@ -2249,11 +2249,14 @@ void InputDeviceHandler::init()
bool InputDeviceHandler::setAt(Toplevel *toplevel)
{
if (m_at == toplevel) {
if (m_at.at == toplevel) {
return false;
}
auto old = m_at;
m_at = toplevel;
auto old = m_at.at;
disconnect(m_at.surfaceCreatedConnection);
m_at.surfaceCreatedConnection = QMetaObject::Connection();
m_at.at = toplevel;
emit atChanged(old, toplevel);
return true;
}
@ -2281,7 +2284,19 @@ void InputDeviceHandler::setInternalWindow(QWindow *window)
void InputDeviceHandler::updateFocus()
{
auto oldFocus = m_focus.focus;
m_focus.focus = m_at;
if (m_at.at && !m_at.at->surface()) {
// The surface has not yet been created (special XWayland case).
// Therefore listen for its creation.
if (!m_at.surfaceCreatedConnection) {
m_at.surfaceCreatedConnection = connect(m_at.at, &Toplevel::surfaceChanged,
this, &InputDeviceHandler::update);
}
m_focus.focus = nullptr;
} else {
m_focus.focus = m_at.at;
}
focusUpdate(oldFocus, m_focus.focus);
}
@ -2290,7 +2305,7 @@ bool InputDeviceHandler::updateDecoration()
const auto oldDeco = m_focus.decoration;
m_focus.decoration = nullptr;
auto *ac = qobject_cast<AbstractClient*>(m_at);
auto *ac = qobject_cast<AbstractClient*>(m_at.at);
if (ac && ac->decoratedClient()) {
const QRect clientRect = QRect(ac->clientPos(), ac->clientSize()).translated(ac->pos());
if (!clientRect.contains(position().toPoint())) {
@ -2358,7 +2373,7 @@ void InputDeviceHandler::update()
}
updateInternalWindow(nullptr);
if (m_focus.focus != m_at) {
if (m_focus.focus != m_at.at) {
// focus change
updateDecoration();
updateFocus();

@ -389,7 +389,7 @@ public:
* @return Toplevel* at device position.
**/
QPointer<Toplevel> at() const {
return m_at;
return m_at.at;
}
/**
* @brief Toplevel currently having pointer input focus (this might
@ -459,7 +459,11 @@ private:
QWindow* findInternalWindow(const QPoint &pos) const;
QPointer<Toplevel> m_at;
struct {
QPointer<Toplevel> at;
QMetaObject::Connection surfaceCreatedConnection;
} m_at;
struct {
QPointer<Toplevel> focus;
QPointer<Decoration::DecoratedClientImpl> decoration;

Loading…
Cancel
Save