[wayland] Improve decision which backend to create

Both Wayland and X11 backend are bound to the --windowed flag. Which
one to create is decided whether DISPLAY or WAYLAND_DISPLAY env variables
are set with Wayland having precedence over X11. Passing the display as
command line argument overwrites the env variable and takes further
precedence. E.g. if WAYLAND_DISPLAY is exported and --x11-display
argument is provided, it will create X11 backend. Similarly there is now
a --wayland-display command line argument.

If no backend got created, kwin_wayland will exit.

The singleton variant of WaylandBackend is adjusted to take the display
as argument and pass it to the Connection.
This commit is contained in:
Martin Gräßlin 2015-03-23 12:45:21 +01:00
parent ed504d0c50
commit ee186a68c4
6 changed files with 86 additions and 31 deletions

View file

@ -73,7 +73,6 @@ ApplicationWayland::ApplicationWayland(int &argc, char **argv)
ApplicationWayland::~ApplicationWayland()
{
destroyWorkspace();
delete Wayland::WaylandBackend::self();
if (x11Connection()) {
Xcb::setInputFocus(XCB_INPUT_FOCUS_POINTER_ROOT);
xcb_disconnect(x11Connection());
@ -88,21 +87,45 @@ void ApplicationWayland::performStartup()
// try creating the Wayland Backend
createInput();
if (!X11WindowedBackend::self()) {
// only create WaylandBackend if we do not use X11WindowedBackend
Wayland::WaylandBackend *backend = Wayland::WaylandBackend::create();
connect(backend, &Wayland::WaylandBackend::connectionFailed, this,
[] () {
fputs(i18n("kwin_wayland: could not connect to Wayland Server, ensure WAYLAND_DISPLAY is set.\n").toLocal8Bit().constData(), stderr);
::exit(1);
}
);
connect(backend, &Wayland::WaylandBackend::outputsChanged, this, &ApplicationWayland::continueStartupWithScreens);
} else {
createBackend();
if (X11WindowedBackend::self()) {
continueStartupWithScreens();
}
}
void ApplicationWayland::createBackend()
{
AbstractBackend *backend = nullptr;
if (m_windowed) {
if (!m_waylandDisplay.isEmpty()) {
Wayland::WaylandBackend *b = Wayland::WaylandBackend::create(m_waylandDisplay, this);
connect(b, &Wayland::WaylandBackend::connectionFailed, this,
[] () {
fputs(i18n("kwin_wayland: could not connect to Wayland Server, ensure WAYLAND_DISPLAY is set.\n").toLocal8Bit().constData(), stderr);
::exit(1);
}
);
connect(b, &Wayland::WaylandBackend::outputsChanged, this, &ApplicationWayland::continueStartupWithScreens);
backend = b;
}
if (!backend && !m_x11Display.isEmpty()) {
KWin::X11WindowedBackend *x11Backend = KWin::X11WindowedBackend::create(m_x11Display, m_backendSize, this);
if (x11Backend->isValid()) {
backend = x11Backend;
waylandServer()->seat()->setHasPointer(true);
waylandServer()->seat()->setHasKeyboard(true);
} else {
delete x11Backend;
}
}
}
if (!backend) {
std::cerr << "FATAL ERROR: could not create a backend, exiting now" << std::endl;
::exit(1);
}
}
void ApplicationWayland::continueStartupWithScreens()
{
if (Wayland::WaylandBackend::self()) {
@ -352,6 +375,9 @@ KWIN_EXPORT int kdemain(int argc, char * argv[])
QCommandLineOption x11DisplayOption(QStringLiteral("x11-display"),
i18n("The X11 Display to use in windowed mode on platform X11."),
QStringLiteral("display"));
QCommandLineOption waylandDisplayOption(QStringLiteral("wayland-display"),
i18n("The Wayland Display to use in windowed mode on platform Wayland."),
QStringLiteral("display"));
QCommandLineOption widthOption(QStringLiteral("width"),
i18n("The width for windowed mode. Default width is 1024."),
QStringLiteral("width"));
@ -367,6 +393,7 @@ KWIN_EXPORT int kdemain(int argc, char * argv[])
parser.addOption(waylandSocketOption);
parser.addOption(windowedOption);
parser.addOption(x11DisplayOption);
parser.addOption(waylandDisplayOption);
parser.addOption(widthOption);
parser.addOption(heightOption);
#if HAVE_INPUT
@ -382,6 +409,7 @@ KWIN_EXPORT int kdemain(int argc, char * argv[])
KWin::Application::setUseLibinput(parser.isSet(libinputOption));
#endif
a.setWindowed(parser.isSet(windowedOption));
if (parser.isSet(windowedOption)) {
bool ok = false;
const int width = parser.value(widthOption).toInt(&ok);
@ -394,13 +422,17 @@ KWIN_EXPORT int kdemain(int argc, char * argv[])
std::cerr << "FATAL ERROR incorrect value for height" << std::endl;
return 1;
}
KWin::X11WindowedBackend *x11Backend = KWin::X11WindowedBackend::create(parser.value(x11DisplayOption), QSize(width, height), &a);
if (!x11Backend->isValid()) {
std::cerr << "FATAL ERROR failed to connet to X Server" << std::endl;
return 1;
a.setBackendSize(QSize(width, height));
if (parser.isSet(x11DisplayOption)) {
a.setX11Display(parser.value(x11DisplayOption).toUtf8());
} else if (!parser.isSet(waylandDisplayOption)) {
a.setX11Display(qgetenv("DISPLAY"));
}
if (parser.isSet(waylandDisplayOption)) {
a.setWaylandDisplay(parser.value(waylandDisplayOption).toUtf8());
} else if (!parser.isSet(x11DisplayOption)) {
a.setWaylandDisplay(qgetenv("WAYLAND_DISPLAY"));
}
server->seat()->setHasPointer(true);
server->seat()->setHasKeyboard(true);
}
a.setStartXwayland(parser.isSet(xwaylandOption));

View file

@ -34,17 +34,34 @@ public:
void setStartXwayland(bool start) {
m_startXWayland = start;
}
void setBackendSize(const QSize &size) {
m_backendSize = size;
}
void setWindowed(bool set) {
m_windowed = set;
}
void setX11Display(const QByteArray &display) {
m_x11Display = display;
}
void setWaylandDisplay(const QByteArray &display) {
m_waylandDisplay = display;
}
protected:
void performStartup() override;
private:
void createBackend();
void createX11Connection();
void continueStartupWithScreens();
void continueStartupWithX();
bool m_startXWayland = false;
int m_xcbConnectionFd = -1;
QSize m_backendSize;
bool m_windowed = false;
QByteArray m_x11Display;
QByteArray m_waylandDisplay;
};
}

View file

@ -356,14 +356,14 @@ void WaylandCursor::setCursorImage(Qt::CursorShape shape)
}
WaylandBackend *WaylandBackend::s_self = 0;
WaylandBackend *WaylandBackend::create(QObject *parent)
WaylandBackend *WaylandBackend::create(const QByteArray &display, QObject *parent)
{
Q_ASSERT(!s_self);
s_self = new WaylandBackend(parent);
s_self = new WaylandBackend(display, parent);
return s_self;
}
WaylandBackend::WaylandBackend(QObject *parent)
WaylandBackend::WaylandBackend(const QByteArray &display, QObject *parent)
: AbstractBackend(parent)
, m_display(nullptr)
, m_eventQueue(new EventQueue(this))
@ -374,7 +374,7 @@ WaylandBackend::WaylandBackend(QObject *parent)
, m_shellSurface(NULL)
, m_seat()
, m_shm(new ShmPool(this))
, m_connectionThreadObject(nullptr)
, m_connectionThreadObject(new ConnectionThread(nullptr))
, m_connectionThread(nullptr)
, m_fullscreenShell(new FullscreenShell(this))
, m_subCompositor(new SubCompositor(this))
@ -423,6 +423,7 @@ WaylandBackend::WaylandBackend(QObject *parent)
}
);
connect(m_registry, &Registry::interfacesAnnounced, this, &WaylandBackend::createSurface);
m_connectionThreadObject->setSocketName(display);
initConnection();
}
@ -459,7 +460,6 @@ void WaylandBackend::destroyOutputs()
void WaylandBackend::initConnection()
{
m_connectionThreadObject = new ConnectionThread(nullptr);
connect(m_connectionThreadObject, &ConnectionThread::connected, this,
[this]() {
// create the event queue for the main gui thread

View file

@ -165,6 +165,11 @@ public:
void installCursorImage(Qt::CursorShape shape) override;
void installCursorFromServer() override;
static WaylandBackend *create(const QByteArray &display, QObject *parent = nullptr);
static WaylandBackend *self() {
return s_self;
}
protected:
void connectNotify(const QMetaMethod &signal) override;
@ -175,6 +180,7 @@ Q_SIGNALS:
void outputsChanged();
void connectionFailed();
private:
explicit WaylandBackend(const QByteArray &display, QObject *parent = nullptr);
void initConnection();
void createSurface();
void destroyOutputs();
@ -195,8 +201,7 @@ private:
KWayland::Client::SubCompositor *m_subCompositor;
WaylandCursor *m_cursor;
bool m_ready = false;
KWIN_SINGLETON(WaylandBackend)
static WaylandBackend *s_self;
};
inline

View file

@ -43,28 +43,28 @@ namespace KWin
X11WindowedBackend *X11WindowedBackend::s_self = nullptr;
X11WindowedBackend *X11WindowedBackend::create(const QString &display, const QSize &size, QObject *parent)
X11WindowedBackend *X11WindowedBackend::create(const QByteArray &display, const QSize &size, QObject *parent)
{
Q_ASSERT(!s_self);
s_self = new X11WindowedBackend(display, size, parent);
return s_self;
}
X11WindowedBackend::X11WindowedBackend(const QString &display, const QSize &size, QObject *parent)
X11WindowedBackend::X11WindowedBackend(const QByteArray &display, const QSize &size, QObject *parent)
: AbstractBackend(parent)
, m_size(size)
{
int screen = 0;
xcb_connection_t *c = nullptr;
#if HAVE_X11_XCB
Display *xDisplay = XOpenDisplay(display.toUtf8().constData());
Display *xDisplay = XOpenDisplay(display.constData());
if (xDisplay) {
c = XGetXCBConnection(xDisplay);
XSetEventQueueOwner(xDisplay, XCBOwnsEventQueue);
screen = XDefaultScreen(xDisplay);
}
#else
c = xcb_connect(display.toUtf8().constData(), &screen);
c = xcb_connect(display.constData(), &screen);
#endif
if (c && !xcb_connection_has_error(c)) {
m_connection = c;
@ -97,6 +97,7 @@ X11WindowedBackend::~X11WindowedBackend()
}
xcb_disconnect(m_connection);
}
s_self = nullptr;
}
void X11WindowedBackend::createWindow()

View file

@ -66,13 +66,13 @@ public:
void installCursorFromServer() override;
static X11WindowedBackend *self();
static X11WindowedBackend *create(const QString &display, const QSize &size, QObject *parent);
static X11WindowedBackend *create(const QByteArray &display, const QSize &size, QObject *parent);
Q_SIGNALS:
void sizeChanged();
private:
X11WindowedBackend(const QString &display, const QSize &size, QObject *parent);
X11WindowedBackend(const QByteArray &display, const QSize &size, QObject *parent);
void createWindow();
void startEventReading();
void handleEvent(xcb_generic_event_t *event);