3

My app is waiting on a thread to finish. When the thread finishes its thing, I want to update the GUI. The GUI thread is blocked in xcb_wait_for_event().

Is this possible with XCB? How does Qt, GTK, FLTK etc. implement this basic GUI problem in terms of the XCB API?

3 Answers3

2

In Qt, you should connect a (queued) signal emitted by your thread to a slot on a GUI thread object. The slot invocation is then processed by the event loop, just like the spontaneous events from e.g. user input.

From Maya Posch's excellent article on using QThread:

class Worker : public QObject {
    Q_OBJECT

public:
    Worker();
    ~Worker();

public slots:
    void process();

signals:
    void finished();
    void error(QString err);

private:
    // add your variables here
};

void Worker::process() {
    // allocate resources using new here
    qDebug("Hello World!");
    emit finished();
}

In the GUI thread:

QThread* thread = new QThread;
Worker* worker = new Worker();
worker->moveToThread(thread);
connect(worker, SIGNAL(error(QString)), this, SLOT(errorString(QString)));
connect(thread, SIGNAL(started()), worker, SLOT(process()));
connect(worker, SIGNAL(finished()), thread, SLOT(quit()));
connect(worker, SIGNAL(finished()), worker, SLOT(deleteLater()));
connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
thread->start();

The line you are interested in is

connect(worker, SIGNAL(error(QString)), this, SLOT(errorString(QString)));

Now go and read How To Really, Truly Use QThreads; The Full Explanation.

Toby Speight
  • 27,591
  • 48
  • 66
  • 103
  • Sorry, I was interested in how the various toolkits _implement_ this on top of XCB, not how to do it _with_ the toolkit APIs. I want to do this without any toolkit. I changed the question, hopefully it's more clear now. –  May 19 '15 at 12:16
  • Ah, I see. I'll write a different answer for that, but leave this here in case it's useful to future readers. – Toby Speight May 19 '15 at 12:37
2

The way it works in Qt appears to be that the xcb_wait_for_event() runs repeatedly in a thread of its own. Each time it receives an event, it posts a message on the QApplication's shared message queue. User threads may also add messages to the QApplication's shared message queue, by means of queued signals (see my other answer).

The user application can now read events from the shared message queue (e.g. using qApp->exec()) and receive a mixture of spontaneous UI events and internal signals from other threads.

For more reading, I suggest the Qt5 sources, beginning with src/plugins/platforms/xcb/qxcbconnection.cpp - look at QXcbEventReader::run.

Toby Speight
  • 27,591
  • 48
  • 66
  • 103
  • Thanks. It does seem like implementing my own queue and putting the XCB loop on another thread is the only way to go (bummer). I still have a faint hope for a simpler solution, so I'm gonna wait for more answers a little while longer. –  May 19 '15 at 13:32
0

stackoverflow.com/questions/8794089/how-to-send-key-event-to-application-using-xcb

Note the warning of a potential security how, and a way to use xtest to avoid it. I wonder if you might rather wait on a signal? They aren't as scary and mysterious they seem to the uniniated. There's a great book by Michael Kerrisk:The Linux Programming Interface A Linux and UNIX System Programming Handbook which explains about it.

DeeDeeK
  • 56
  • 7