In one of my projects in GTK3, I am using custom events for communication between threads. One thread is the main OS thread on which the event loop is running. The other one is a non main thread that is doing some internal application specific initialization. The condition is that the first GTK window shall be created, only after the application is initialized. However, I don’t want to delay the main thread entering the event loop for some design related reasons.
Therefore, the main thread enters the event loop as soon as GTK is initialized and the non main thread needs to intimate the main thread when first window can be created. For this intimations I am using custom events in GTK3 (it can be created although I am not sure it is recommended or not).
The code snippet for the non main thread creating custom event is as below -
GdkEvent * createwinevent;
// Create and post custom event to start GTK Window creation
createwinevent = gdk_event_new ((GdkEventType) CREATE_WINDOW);
// CREATE_WINDOW is an enum defined by the application
In the main thread, I am using g_idle_timeout to check the event queue intermittently and handle the custom events.
In GTK4 however, GdkEvents have been made read-only. Can custom events still be created in GTK4 somehow? If not, is there any other mechanism I can use in GTK4 to pass message between threads?
This is completely unsupported in GTK3, and it’s just working by accident. Creating random GdkEvent structures and sending them through the event loop is emphatically not how this API is supposed to work.
Additionally, you cannot use GTK (and GDK) API from different threads. Only one thread is allowed to use the GTK API, and that’s the same thread that called gtk_init() and is spinning the main loop.
GdkEvent is not an application message passing API: it’s for windowing system events.
No, and your use of GdkEvent is an example of things we didn’t think possible, but luckily we are now plugging that particular misuse of the API.
Use an asynchronous queue and pass your own data types.
Thanks @ebassi for the clarifications. Now I have better understanding of GdkEvent usage.
One more query arises in mind from your reply.
I am developing a multi-platform application that runs on Windows, Linux, MacOS. So intentionally I am trying to keep my code flow as similar as possible for all the OS platforms. For Windows I am using win32 API. Win32 lets the application create & send a private / custom message to the UI Window handle. This custom message can be used to pass any information to the UI Window apart from system generated events that it needs to act upon.
Is there any such custom messaging available in GTK to send information to a specific GTK UI window (in case more than one window is open)?
Other question is, GdkEvents support mouse, keyboard, touch and tablet pad input device events. However, if my application wants to connect to a BarCode Reader for example, will that event be translated to a GdkEvent by the windowing system? If yes, which event will it generate.
Note - I am not sure about what event is generated by OS for a BarCode reader in general. So pardon me if this question was a silly one.
This is not going to work, as every windowing system and platform has very specific functionality. GTK commits to whatever can be implemented in terms of the minimum common denominator between platforms, but everything that is not covered by the GDK API needs to be done with platform-specific API. That’s why, for instance, GTK does not have API that deals with screen-global coordinates: since those are not available in Wayland, we don’t have a platform-agnostic wrapper.
No. If you need to call into your own UI from separate threads you will have to your own message passing mechanism. Alternatively, you could use the GTask API to schedule work in a worker thread, and once that thread is complete, the GTask API will schedule a callback into the main UI thread; see, for instance:
There is no “bar code” event, so it entirely depends on what the platform exposes. For instance, if the bar code reader is a USB device, you will need to poll the USB device file descriptor using a GSource in the main loop. Once there’s data on the file descriptor, you’ll schedule a callback for it. For more information, see:
From old past experience, these devices typically are “keyboard” devices, and burst a series of key presses/releases upon scanning a barcode. There is no special handling that needs to be done, other than focusing the right place before scanning, and having a compatible keymap.
@ebassi I have gone through the links you had shared and to some extent understood the GTask framework. However, could not understand if I want to update and repaint some UI component (running on main thread) based on a non-main thread response, how to use the GTask framework.
For example, if I have a server and a client where the Client is showing the UI based on communication with Server. There is a UI currently the Client is showing (main thread) and on a non-main thread it is communicating with the Server. Now, something has changed in Server and it communicated to the Client to update the UI based on new information. How the GTask can be used for that. Or for this kind of communication I shall use my own messaging?
Note - I am new to GTK so if the question seems a repetition or silly in any way, my advance apologies.
GTask is most suitable for spawning asynchronous tasks from a thread, where the same thread is interested in handling the final result of the task.
If your pattern has things fed from a thread into the main UI thread, it will probably be more useful for you to use GAsyncQueue, or g_idle_source_new()+g_source_attach() to queue up callbacks(plus data) in the UI thread’s GMainContext from your non-main thread.