Update Keyboard focus when the Surface of the active client changes
Summary: For XWayland windows the window might be activated before the Wayland Surface is set for it. Thus the keyboard focus is not passed to the window. Only on the next activate after the window got created the window got keyboard focus. This change addresses this problem by emitting a signal from Toplevel when the surface changes. The KeyboardInput listens to this signal for the active client and updates keyboard focus again if the surface changes. Thus keyboard focus is properly passed to XWayland windows. Test Plan: Test case which creates an X11 window is adjusted to verify the condition. Reviewers: #plasma_on_wayland, #kwin Subscribers: plasma-devel, kwin Tags: #plasma_on_wayland, #kwin Differential Revision: https://phabricator.kde.org/D2009
This commit is contained in:
parent
b487da02cd
commit
7adf69dece
5 changed files with 28 additions and 1 deletions
|
@ -36,6 +36,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
#include <KWayland/Client/shell.h>
|
||||
#include <KWayland/Client/shm_pool.h>
|
||||
#include <KWayland/Client/surface.h>
|
||||
#include <KWayland/Server/seat_interface.h>
|
||||
//screenlocker
|
||||
#include <KScreenLocker/KsldApp>
|
||||
|
||||
|
@ -211,6 +212,15 @@ void PlasmaWindowTest::testCreateDestroyX11PlasmaWindow()
|
|||
QCOMPARE(client->window(), w);
|
||||
QVERIFY(client->isDecorated());
|
||||
QVERIFY(client->isActive());
|
||||
// verify that it gets the keyboard focus
|
||||
QVERIFY(!client->surface());
|
||||
// we don't have a surface yet, so focused keyboard surface if set is not ours
|
||||
QVERIFY(!waylandServer()->seat()->focusedKeyboardSurface());
|
||||
QSignalSpy surfaceChangedSpy(client, &Toplevel::surfaceChanged);
|
||||
QVERIFY(surfaceChangedSpy.isValid());
|
||||
QVERIFY(surfaceChangedSpy.wait());
|
||||
QVERIFY(client->surface());
|
||||
QCOMPARE(waylandServer()->seat()->focusedKeyboardSurface(), client->surface());
|
||||
|
||||
// now that should also give it to us on client side
|
||||
QVERIFY(plasmaWindowCreatedSpy.wait());
|
||||
|
|
|
@ -374,7 +374,17 @@ void KeyboardInputRedirection::init()
|
|||
|
||||
connect(workspace(), &QObject::destroyed, this, [this] { m_inited = false; });
|
||||
connect(waylandServer(), &QObject::destroyed, this, [this] { m_inited = false; });
|
||||
connect(workspace(), &Workspace::clientActivated, this, &KeyboardInputRedirection::update);
|
||||
connect(workspace(), &Workspace::clientActivated, this,
|
||||
[this] {
|
||||
disconnect(m_activeClientSurfaceChangedConnection);
|
||||
if (auto c = workspace()->activeClient()) {
|
||||
m_activeClientSurfaceChangedConnection = connect(c, &Toplevel::surfaceChanged, this, &KeyboardInputRedirection::update);
|
||||
} else {
|
||||
m_activeClientSurfaceChangedConnection = QMetaObject::Connection();
|
||||
}
|
||||
update();
|
||||
}
|
||||
);
|
||||
if (waylandServer()->hasScreenLockerIntegration()) {
|
||||
connect(ScreenLocker::KSldApp::self(), &ScreenLocker::KSldApp::lockStateChanged, this, &KeyboardInputRedirection::update);
|
||||
}
|
||||
|
|
|
@ -126,6 +126,7 @@ private:
|
|||
bool m_inited = false;
|
||||
QScopedPointer<Xkb> m_xkb;
|
||||
QHash<quint32, QTimer*> m_repeatTimers;
|
||||
QMetaObject::Connection m_activeClientSurfaceChangedConnection;
|
||||
};
|
||||
|
||||
inline
|
||||
|
|
|
@ -478,6 +478,7 @@ void Toplevel::setSurface(KWayland::Server::SurfaceInterface *surface)
|
|||
m_surface = nullptr;
|
||||
}
|
||||
);
|
||||
emit surfaceChanged();
|
||||
}
|
||||
|
||||
void Toplevel::addDamage(const QRegion &damage)
|
||||
|
|
|
@ -450,6 +450,11 @@ Q_SIGNALS:
|
|||
**/
|
||||
void hasAlphaChanged();
|
||||
|
||||
/**
|
||||
* Emitted whenever the Surface for this Toplevel changes.
|
||||
**/
|
||||
void surfaceChanged();
|
||||
|
||||
protected Q_SLOTS:
|
||||
/**
|
||||
* Checks whether the screen number for this Toplevel changed and updates if needed.
|
||||
|
|
Loading…
Reference in a new issue