[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:
parent
ed504d0c50
commit
ee186a68c4
6 changed files with 86 additions and 31 deletions
|
@ -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));
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue