Display can start the server before QCoreApplication is created
Event dispatching in Display requires a QSocketNotifier which requires the QCoreApplication to be created. This requirement renders it impossible to create the server before the QCoreApplication is created. But there are use cases which need this: Let's assume we want to integrate a wayland server into an existing X11 dependent application which uses QApplication and enforces the xcb plugin. This means said application requires that an X Server is up and running before the QApplication is created. If we want said application to connect to an Xwayland server we need to be able to create the Wayland server AND the Xwayland server before creating the QApplication. The solution is to only create the socket notifier if the QCoreApplication exists. For the case that it doesn't exist an additional method is added which needs to be called once the QCoreApplication got created. In addition a manual event dispatch method is added which allows to block for events when we don't have a QSocketNotifier set up yet.
This commit is contained in:
parent
376a2ffac9
commit
9d5d8d0871
2 changed files with 49 additions and 9 deletions
|
@ -43,6 +43,7 @@ public:
|
||||||
Private(Display *q);
|
Private(Display *q);
|
||||||
void flush();
|
void flush();
|
||||||
void setRunning(bool running);
|
void setRunning(bool running);
|
||||||
|
void installSocketNotifier();
|
||||||
|
|
||||||
wl_display *display = nullptr;
|
wl_display *display = nullptr;
|
||||||
wl_event_loop *loop = nullptr;
|
wl_event_loop *loop = nullptr;
|
||||||
|
@ -59,11 +60,26 @@ Display::Private::Private(Display *q)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Display::Private::installSocketNotifier()
|
||||||
|
{
|
||||||
|
if (!QCoreApplication::instance()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
int fd = wl_event_loop_get_fd(loop);
|
||||||
|
if (fd == -1) {
|
||||||
|
qWarning() << "Did not get the file descriptor for the event loop";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
QSocketNotifier *m_notifier = new QSocketNotifier(fd, QSocketNotifier::Read, q);
|
||||||
|
QObject::connect(m_notifier, &QSocketNotifier::activated, q, [this] { flush(); } );
|
||||||
|
QObject::connect(QCoreApplication::eventDispatcher(), &QAbstractEventDispatcher::aboutToBlock, q, [this] { flush(); });
|
||||||
|
setRunning(true);
|
||||||
|
}
|
||||||
|
|
||||||
Display::Display(QObject *parent)
|
Display::Display(QObject *parent)
|
||||||
: QObject(parent)
|
: QObject(parent)
|
||||||
, d(new Private(this))
|
, d(new Private(this))
|
||||||
{
|
{
|
||||||
connect(QCoreApplication::eventDispatcher(), &QAbstractEventDispatcher::aboutToBlock, this, [this] { d->flush(); });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Display::~Display()
|
Display::~Display()
|
||||||
|
@ -106,14 +122,22 @@ void Display::start()
|
||||||
}
|
}
|
||||||
|
|
||||||
d->loop = wl_display_get_event_loop(d->display);
|
d->loop = wl_display_get_event_loop(d->display);
|
||||||
int fd = wl_event_loop_get_fd(d->loop);
|
d->installSocketNotifier();
|
||||||
if (fd == -1) {
|
}
|
||||||
qWarning() << "Did not get the file descriptor for the event loop";
|
|
||||||
return;
|
void Display::startLoop()
|
||||||
}
|
{
|
||||||
QSocketNotifier *m_notifier = new QSocketNotifier(fd, QSocketNotifier::Read, this);
|
Q_ASSERT(!d->running);
|
||||||
connect(m_notifier, &QSocketNotifier::activated, this, [this] { d->flush(); } );
|
Q_ASSERT(d->display);
|
||||||
d->setRunning(true);
|
d->installSocketNotifier();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Display::dispatchEvents(int msecTimeout)
|
||||||
|
{
|
||||||
|
Q_ASSERT(!d->running);
|
||||||
|
Q_ASSERT(d->display);
|
||||||
|
wl_event_loop_dispatch(d->loop, msecTimeout);
|
||||||
|
wl_display_flush_clients(d->display);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Display::terminate()
|
void Display::terminate()
|
||||||
|
|
|
@ -57,6 +57,22 @@ public:
|
||||||
|
|
||||||
void start();
|
void start();
|
||||||
void terminate();
|
void terminate();
|
||||||
|
/**
|
||||||
|
* Starts the event loop for the server socket.
|
||||||
|
* This method should only be used if start() is used before creating the
|
||||||
|
* QCoreApplication. In that case start() cannot fully setup the event processing
|
||||||
|
* and the loop needs to be started after the QCoreApplication got created.
|
||||||
|
* @see start
|
||||||
|
* @see dispatchEvents
|
||||||
|
**/
|
||||||
|
void startLoop();
|
||||||
|
/**
|
||||||
|
* Dispatches pending events in a blocking way. May only be used if the Display is
|
||||||
|
* created and started before the QCoreApplication is created. Once the QCoreApplication
|
||||||
|
* is created and the event loop is started this method may no longer be invoked.
|
||||||
|
* @see startLoop
|
||||||
|
**/
|
||||||
|
void dispatchEvents(int msecTimeout = -1);
|
||||||
|
|
||||||
operator wl_display*();
|
operator wl_display*();
|
||||||
operator wl_display*() const;
|
operator wl_display*() const;
|
||||||
|
|
Loading…
Reference in a new issue