diff --git a/main_wayland.cpp b/main_wayland.cpp
index fad16d8ae1..ce0a7a7832 100644
--- a/main_wayland.cpp
+++ b/main_wayland.cpp
@@ -221,6 +221,7 @@ void ApplicationWayland::continueStartupWithX()
Xcb::sync(); // Trigger possible errors, there's still a chance to abort
notifyKSplash();
+ waylandServer()->createDummyQtWindow();
}
);
eglInitWatcher->setFuture(QtConcurrent::run([] {
diff --git a/wayland_server.cpp b/wayland_server.cpp
index 237200f7ee..e33f278278 100644
--- a/wayland_server.cpp
+++ b/wayland_server.cpp
@@ -27,6 +27,7 @@ along with this program. If not, see .
// Client
#include
#include
+#include
// Server
#include
#include
@@ -35,6 +36,9 @@ along with this program. If not, see .
#include
#include
+// Qt
+#include
+
// system
#include
#include
@@ -94,6 +98,13 @@ void WaylandServer::init(const QByteArray &socketName)
// skip Xwayland clients, those are created using standard X11 way
return;
}
+ if (surface->client() == m_qtConnection) {
+ // one of Qt's windows
+ if (m_dummyWindowSurface && (m_dummyWindowSurface->id() == surface->surface()->id())) {
+ fakeDummyQtWindowInput();
+ return;
+ }
+ }
auto client = new ShellClient(surface);
if (auto c = Compositor::self()) {
connect(client, &Toplevel::needsRepaint, c, &Compositor::scheduleRepaint);
@@ -194,4 +205,37 @@ void WaylandServer::removeClient(ShellClient *c)
emit shellClientRemoved(c);
}
+void WaylandServer::createDummyQtWindow()
+{
+ if (m_dummyWindow) {
+ return;
+ }
+ m_dummyWindow.reset(new QWindow());
+ m_dummyWindow->setSurfaceType(QSurface::RasterSurface);
+ m_dummyWindow->show();
+ m_dummyWindowSurface = KWayland::Client::Surface::fromWindow(m_dummyWindow.data());
+}
+
+void WaylandServer::fakeDummyQtWindowInput()
+{
+#if (QT_VERSION >= QT_VERSION_CHECK(5, 5, 0))
+ // we need to fake Qt into believing it has got any seat events
+ // this is done only when receiving either a key press or button.
+ // we simulate by sending a button press and release
+ auto surface = KWayland::Server::SurfaceInterface::get(m_dummyWindowSurface->id(), m_qtConnection);
+ if (!surface) {
+ return;
+ }
+ const auto oldSeatSurface = m_seat->focusedPointerSurface();
+ const auto oldPos = m_seat->focusedPointerSurfacePosition();
+ m_seat->setFocusedPointerSurface(surface, QPoint(0, 0));
+ m_seat->setPointerPos(QPointF(0, 0));
+ m_seat->pointerButtonPressed(Qt::LeftButton);
+ m_seat->pointerButtonReleased(Qt::LeftButton);
+ m_qtConnection->flush();
+ m_dummyWindow->hide();
+ m_seat->setFocusedPointerSurface(oldSeatSurface, oldPos);
+#endif
+}
+
}
diff --git a/wayland_server.h b/wayland_server.h
index e408496959..f18b7c893e 100644
--- a/wayland_server.h
+++ b/wayland_server.h
@@ -24,12 +24,15 @@ along with this program. If not, see .
#include
+class QWindow;
+
namespace KWayland
{
namespace Client
{
class ConnectionThread;
class ShmPool;
+class Surface;
}
namespace Server
{
@@ -89,6 +92,7 @@ public:
**/
int createQtConnection();
void createInternalConnection();
+ void createDummyQtWindow();
KWayland::Server::ClientConnection *xWaylandConnection() const {
return m_xwaylandConnection;
@@ -108,6 +112,7 @@ Q_SIGNALS:
void shellClientRemoved(ShellClient*);
private:
+ void fakeDummyQtWindowInput();
KWayland::Server::Display *m_display = nullptr;
KWayland::Server::CompositorInterface *m_compositor = nullptr;
KWayland::Server::SeatInterface *m_seat = nullptr;
@@ -122,6 +127,8 @@ private:
} m_internalConnection;
AbstractBackend *m_backend = nullptr;
QList m_clients;
+ QScopedPointer m_dummyWindow;
+ KWayland::Client::Surface *m_dummyWindowSurface = nullptr;
KWIN_SINGLETON(WaylandServer)
};