Asynchronous events in GTK application?

C

Clifford Heath

I have a GTK app with a thread monitoring a COM port for particular
input events. What's the best way to notify the main GTK thread of
these events? Can i hook into the main loop somehow?

Clifford Heath.
 
C

Clifford Heath

Ok, I learnt some more, and I think I'm hung up on a GTK "feature".
This is with the Debian Linux version that calls itself 0.9.1.

My asynchronous device events cause a condition variable to get
set. I've written a main loop that checks the variable, like this:

while true
processEvent if (@device_event)
Gtk.main_iteration
end

(According to the documentation, I should use:
break if Gtk.main_iteration
but in this version, main_iteration always returns true. I guess
that's a change from the 0.9.1 version.)

In case there are no GUI events, I added a timeout which pumps
the loop. If the timeout is set to 1000ms, 500ms, no problem.
As soon as I drop the timeout much more (like 250ms or, what I'd
like, 100ms) the display never gets refreshed.

It seems that Gtk.main_iteration doesn't seem to ever process
paint (expose) events if an event has occurred recently, including
a timeout event(!).

What I'd like is to inject a NULL event into Gtk's queue when
an asynchronous event occurs, instead of using timeouts. But if
I can just get the timeout down to 100ms, that would work also.

Anyone have a solution to this? I wish the Debian packages weren't
always so far behind :-(.

Clifford Heath.
 
M

Masao Mutoh

Hi,

Ok, I learnt some more, and I think I'm hung up on a GTK "feature".
This is with the Debian Linux version that calls itself 0.9.1.

My asynchronous device events cause a condition variable to get
set. I've written a main loop that checks the variable, like this:

while true
processEvent if (@device_event)
Gtk.main_iteration
end

(According to the documentation, I should use:
break if Gtk.main_iteration

Do you mean to call Gtk.events_pending? ?
but in this version, main_iteration always returns true. I guess
that's a change from the 0.9.1 version.)

Hmm. I've not change the behavior of Gtk.main_iteration for long time.

Anyway, if you don't call Gtk.main anywhere, Gtk.main_iteration
doesn't work correctly.
In case there are no GUI events, I added a timeout which pumps
the loop. If the timeout is set to 1000ms, 500ms, no problem.
As soon as I drop the timeout much more (like 250ms or, what I'd
like, 100ms) the display never gets refreshed.
It seems that Gtk.main_iteration doesn't seem to ever process
paint (expose) events if an event has occurred recently, including
a timeout event(!).
Anyone have a solution to this? I wish the Debian packages weren't
always so far behind :-(.

How about to use Gtk.timeout_add ?

P.S.
I think gtk-demo(in Ruby-GNOME2 tar ball) scripts may be helpful.
 
C

Clifford Heath

Masao said:
Do you mean to call Gtk.events_pending? ?

No, I'm happy if it blocks inside main_iteration, as long as the
timeout I added makes main_iteration return - which it does.
Hmm. I've not change the behavior of Gtk.main_iteration for long time.

Well, then either the documentation or the code is wrong, because it
always returns true. I don't see how I can tell when quit has been
called...?
Anyway, if you don't call Gtk.main anywhere, Gtk.main_iteration
doesn't work correctly.

Ouch! I can't do that, I don't think. What is the effect if main
never gets called?
How about to use Gtk.timeout_add ?

That's what I did, I just didn't want to confuse the issue with too
much code. A bigger snippet of what I'm doing follows:

device_change = false
Gtk.timeout_add(500) {
return true if (@busy)
device_change = true if checkDevice
true
}
while true
if device_change
processDeviceChange
device_change = false
end
puts "iteration"
p Gtk.main_iteration
end

If the timeout is set to 500 or more, all works well. If I set it to
250 or less, then the GUI doesn't refresh, even though "iteration" is
printed continuously.

Ok, I see what I need to do. Where I call main_iteration, I have to
continue calling it while events_pending?, before looping to check
for a device_change again. That seems to work better! I should've
realised.

The reason I'm doing all this is because I don't want the "process"
to occur in the middle of a flurry of GUI events, but at the end.

If I add an "idle" callback, I'll have the problem that it will chew
CPU. For an app that uses idle not to busy wait, should it call
main_iteration once to block before returning? What I really want is
a method that says "wait until the next event", but I can't see one
inthe documentation.

Also, I moved my Debian installation to "unstable", from "testing",
and I find I now have ruby-gnome2 version 1.13.0, yaay!
P.S.
I think gtk-demo(in Ruby-GNOME2 tar ball) scripts may be helpful.

I'll check that out, thanks.

Clifford Heath.
 
M

Masao Mutoh

Hi,

That's what I did, I just didn't want to confuse the issue with too
much code. A bigger snippet of what I'm doing follows:

device_change = false
Gtk.timeout_add(500) {
return true if (@busy)
device_change = true if checkDevice
true
}
while true
if device_change
processDeviceChange
device_change = false
end
puts "iteration"
p Gtk.main_iteration
end

Usually, we use Gtk.timeout_add with
Gtk.main something like as:

Gtk.timeout_add(500) {
return true if (@busy)
if checkDevice
processDeviceChange
end
true
}
Gtk.main

It's not good idea to make mainloop by yourself.
If you really need it, you need to learn GLib/GTK mainloops
seriously. Though I don't recommand it.
 
C

Clifford Heath

Masao said:
Usually, we use Gtk.timeout_add with
Gtk.main something like as:

Ok, I considered that, but since the external input will cause
various updates to GUI objects which might not be in a stable
state, I thought it would be better to delay it, which is why
I wrote:

: The reason I'm doing all this is because I don't want the "process"
: to occur in the middle of a flurry of GUI events, but at the end.
It's not good idea to make mainloop by yourself.
If you really need it, you need to learn GLib/GTK mainloops
seriously. Though I don't recommand it.

Ok, I believe you. I've built such things before. There should be
a warning like this in the documentation BTW. It'd be good if some
indication of the possible consequences was offered, too.

Thanks for your help.

Clifford Heath.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,176
Messages
2,570,947
Members
47,501
Latest member
Ledmyplace

Latest Threads

Top