[wayland] Add positional arguments to be programs to starts

This allows to start applications once kwin_wayland is started. E.g.
kwin_wayland --libinput --xwayland --framebuffer /usr/bin/startkde

Thus it would start startkde once both Wayland Server and Xwayland
are up and running and ready for connection. This resolves the problem
that prior to startup it is not known which will be the X11 display
variable. By passing the environment to the process by KWin this problem
is resolved.
This commit is contained in:
Martin Gräßlin 2015-04-21 11:21:28 +02:00
parent 8ec3f55ff4
commit db34ddda53
2 changed files with 26 additions and 0 deletions

View file

@ -39,6 +39,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <QFile> #include <QFile>
#include <QFutureWatcher> #include <QFutureWatcher>
#include <QtCore/private/qeventdispatcher_unix_p.h> #include <QtCore/private/qeventdispatcher_unix_p.h>
#include <QProcess>
#include <QSocketNotifier> #include <QSocketNotifier>
#include <QThread> #include <QThread>
#include <QDebug> #include <QDebug>
@ -214,6 +215,23 @@ void ApplicationWayland::continueStartupWithX()
::exit(1); ::exit(1);
} }
// start the applications passed to us as command line arguments
if (!m_applicationsToStart.isEmpty()) {
QProcessEnvironment environment = QProcessEnvironment::systemEnvironment();
environment.remove(QStringLiteral("WAYLAND_SOCKET"));
environment.remove(QStringLiteral("QT_QPA_PLATFORM"));
environment.insert(QStringLiteral("DISPLAY"), QString::fromUtf8(qgetenv("DISPLAY")));
// TODO: maybe create a socket per process?
environment.insert(QStringLiteral("WAYLAND_DISPLAY"), waylandServer()->display()->socketName());
for (const QString &application: m_applicationsToStart) {
// note: this will kill the started process when we exit
// this is going to happen anyway as we are the wayland and X server the app connects to
QProcess *p = new QProcess(this);
p->setProcessEnvironment(environment);
p->start(application);
}
}
// HACK: create a QWindow in a thread to force QtWayland to create the client buffer integration // HACK: create a QWindow in a thread to force QtWayland to create the client buffer integration
// this performs an eglInitialize which would block as it does a roundtrip to the Wayland server // this performs an eglInitialize which would block as it does a roundtrip to the Wayland server
// in the main thread. By moving into a thread we get the initialize without hitting the problem // in the main thread. By moving into a thread we get the initialize without hitting the problem
@ -425,6 +443,9 @@ KWIN_EXPORT int kdemain(int argc, char * argv[])
i18n("Enable libinput support for input events processing. Note: never use in a nested session.")); i18n("Enable libinput support for input events processing. Note: never use in a nested session."));
parser.addOption(libinputOption); parser.addOption(libinputOption);
#endif #endif
parser.addPositionalArgument(QStringLiteral("applications"),
i18n("Applications to start once Wayland and Xwayland server are started"),
QStringLiteral("[/path/to/application...]"));
parser.process(a); parser.process(a);
a.processCommandLine(&parser); a.processCommandLine(&parser);
@ -468,6 +489,7 @@ KWIN_EXPORT int kdemain(int argc, char * argv[])
} }
a.setStartXwayland(parser.isSet(xwaylandOption)); a.setStartXwayland(parser.isSet(xwaylandOption));
a.setApplicationsToStart(parser.positionalArguments());
a.start(); a.start();
return a.exec(); return a.exec();

View file

@ -49,6 +49,9 @@ public:
void setFramebuffer(const QString &fbdev) { void setFramebuffer(const QString &fbdev) {
m_framebuffer = fbdev; m_framebuffer = fbdev;
} }
void setApplicationsToStart(const QStringList &applications) {
m_applicationsToStart = applications;
}
protected: protected:
void performStartup() override; void performStartup() override;
@ -66,6 +69,7 @@ private:
QByteArray m_x11Display; QByteArray m_x11Display;
QByteArray m_waylandDisplay; QByteArray m_waylandDisplay;
QString m_framebuffer; QString m_framebuffer;
QStringList m_applicationsToStart;
}; };
} }