diff --git a/main_wayland.cpp b/main_wayland.cpp index d354736817..4411cb6524 100644 --- a/main_wayland.cpp +++ b/main_wayland.cpp @@ -174,6 +174,22 @@ void ApplicationWayland::continueStartupWithX() ::exit(1); } + if (!m_inputMethodServerToStart.isEmpty()) { + int socket = dup(waylandServer()->createInputMethodConnection()); + if (socket >= 0) { + QProcessEnvironment environment = QProcessEnvironment::systemEnvironment(); + environment.insert(QStringLiteral("WAYLAND_SOCKET"), QByteArray::number(socket)); + environment.insert(QStringLiteral("QT_QPA_PLATFORM"), QStringLiteral("wayland")); + environment.insert(QStringLiteral("QT_IM_MODULE"), QStringLiteral("maliit")); + environment.remove("DISPLAY"); + environment.remove("WAYLAND_DISPLAY"); + QProcess *p = new QProcess(this); + p->setProcessEnvironment(environment); + p->start(m_inputMethodServerToStart); + p->waitForStarted(); + } + } + // start the applications passed to us as command line arguments if (!m_applicationsToStart.isEmpty()) { QProcessEnvironment environment = QProcessEnvironment::systemEnvironment(); @@ -418,6 +434,7 @@ KWIN_EXPORT int kdemain(int argc, char * argv[]) #endif qunsetenv("QT_DEVICE_PIXEL_RATIO"); + qunsetenv("QT_IM_MODULE"); qputenv("WAYLAND_SOCKET", QByteArray::number(server->createQtConnection())); qputenv("QT_WAYLAND_DISABLE_WINDOWDECORATION", "1"); KWin::ApplicationWayland a(argc, argv); @@ -479,6 +496,12 @@ KWIN_EXPORT int kdemain(int argc, char * argv[]) QCommandLineOption drmOption(QStringLiteral("drm"), i18n("Render through drm node.")); parser.addOption(drmOption); #endif + + QCommandLineOption inputMethodOption(QStringLiteral("inputmethod"), + i18n("Input method that KWin starts."), + QStringLiteral("path/to/imserver")); + parser.addOption(inputMethodOption); + parser.addPositionalArgument(QStringLiteral("applications"), i18n("Applications to start once Wayland and Xwayland server are started"), QStringLiteral("[/path/to/application...]")); @@ -576,6 +599,7 @@ KWIN_EXPORT int kdemain(int argc, char * argv[]) a.setStartXwayland(parser.isSet(xwaylandOption)); a.setApplicationsToStart(parser.positionalArguments()); + a.setInputMethodServerToStart(parser.value(inputMethodOption)); a.start(); return a.exec(); diff --git a/main_wayland.h b/main_wayland.h index f77ebd62b1..b6ef584e22 100644 --- a/main_wayland.h +++ b/main_wayland.h @@ -40,6 +40,9 @@ public: void setApplicationsToStart(const QStringList &applications) { m_applicationsToStart = applications; } + void setInputMethodServerToStart(const QString &inputMethodServer) { + m_inputMethodServerToStart = inputMethodServer; + } bool notify(QObject *o, QEvent *e) override; @@ -56,6 +59,7 @@ private: bool m_startXWayland = false; int m_xcbConnectionFd = -1; QStringList m_applicationsToStart; + QString m_inputMethodServerToStart; QProcess *m_xwaylandProcess = nullptr; }; diff --git a/shell_client.cpp b/shell_client.cpp index 805d72bf76..7420ec5fa5 100644 --- a/shell_client.cpp +++ b/shell_client.cpp @@ -62,6 +62,9 @@ ShellClient::ShellClient(ShellSurfaceInterface *surface) setGeometry(QRect(QPoint(0, 0), m_clientSize)); setDesktop(VirtualDesktopManager::self()->current()); } + if (waylandServer()->inputMethodConnection() == m_shellSurface->client()) { + m_windowType = NET::OnScreenDisplay; + } connect(surface->surface(), &SurfaceInterface::sizeChanged, this, [this] { @@ -420,6 +423,9 @@ bool ShellClient::wantsInput() const if (isInternal()) { return false; } + if (waylandServer()->inputMethodConnection() == m_shellSurface->client()) { + return false; + } // if the window is not visible it doesn't get input return isShown(true); } diff --git a/wayland_server.cpp b/wayland_server.cpp index c1172bf232..bb03996c77 100644 --- a/wayland_server.cpp +++ b/wayland_server.cpp @@ -189,6 +189,17 @@ int WaylandServer::createXWaylandConnection() return sx[1]; } +int WaylandServer::createInputMethodConnection() +{ + int sx[2]; + if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, sx) < 0) { + qCWarning(KWIN_CORE) << "Could not create socket"; + return -1; + } + m_inputMethodServerConnection = m_display->createClient(sx[0]); + return sx[1]; +} + int WaylandServer::createQtConnection() { int sx[2]; diff --git a/wayland_server.h b/wayland_server.h index e33ef79b48..8fcd380caa 100644 --- a/wayland_server.h +++ b/wayland_server.h @@ -95,6 +95,11 @@ public: **/ int createXWaylandConnection(); + /** + * @returns file descriptor to the input method server's socket. + **/ + int createInputMethodConnection(); + /** * @returns file descriptor for QtWayland **/ @@ -108,6 +113,9 @@ public: KWayland::Server::ClientConnection *qtConnection() const { return m_qtConnection; } + KWayland::Server::ClientConnection *inputMethodConnection() const { + return m_inputMethodServerConnection; + } KWayland::Server::ClientConnection *internalConnection() const { return m_internalConnection.server; } @@ -134,6 +142,7 @@ private: KWayland::Server::PlasmaShellInterface *m_plasmaShell = nullptr; KWayland::Server::QtSurfaceExtensionInterface *m_qtExtendedSurface = nullptr; KWayland::Server::ClientConnection *m_xwaylandConnection = nullptr; + KWayland::Server::ClientConnection *m_inputMethodServerConnection = nullptr; KWayland::Server::ClientConnection *m_qtConnection = nullptr; KWayland::Client::ConnectionThread *m_qtClientConnection = nullptr; struct {