|
Post by newguiguy on Sept 25, 2019 17:00:55 GMT 1
The challenge is that I have a non-complete interval of integers. Therefore, a GTK spin button is not possible. Also a toggle button is not an option.
At the moment I get a signal when the button is pressed and another when released. But as soon as I count up the integers in a while loop after receiving the pressed signal, I can not recognize the released signal anymore or don't know how to do that.
I tried functions like "gtk_main_iteration" and "gtk_events_pending" but have no clue how to achieve my goal. There is no state to check like with a toggle button ("gtk_toggle_button_get_active")
Is there a way in GTK-server to realize that?
KR Tino
|
|
|
Post by Peter on Sept 25, 2019 18:56:24 GMT 1
I am not really sure what you want to achieve but it sounds like you need asynchronous events.
By nature, GTK is event-driven and waits for an event to happen, blocking the mainloop ("wait"). In GTK-server you could try to use the "update" argument for "gtk_server_callback" instead, but then you must make sure to avoid 100%CPU load by adding a sleep somewhere.
Alternatively you can connect the "button-press" event and "button-release" event to separate callback functions, storing the state in a global variable.
HTH Peter
|
|
|
Post by newguiguy on Sept 25, 2019 22:35:07 GMT 1
I have an interval from say 1 till 1000. But 5, 10, 89, 111 and other numbers are missing. I need to run through this interval like 1 -> 2 -> 3 -> 4 -> 6 -> and so on. So a gtk_spin_button is not useable.
My idea was to have a GtkTextEntry field and besides a plus and minus button. The interval is stored in an array. So I have to increase the index by one when the plus button is pressed and
than update the entry with the assigned value.
All this is working flawlessly.
Now the interval is much bigger. So I'd like to hold the button depressed and the value in the entry field is updated much faster.
This is exactly what I was doing till now.
while [[ "$gtk_result" == "signal_pressed" ]];do ((i++)) gtk "gtk_entry_set_text $entry_field ${interval[$i]} gtk "gtk_server_callback UPDATE" sleep 0.05 done
But if I release the button, the signal is "lost"?! OR I cannot get it. Normally, if I allow only one step, GTK-server is already waiting for the next event and I receive the "signal_released" in $gtk_result.
As I menioned I tried to check if other events are pending with "gtk_events_pending" but it has not the desired effect. Can you see how to get the released signal anyway?
I did not understood what you mean by your suggestion.
But it lead me to a solution anyway ;-)
Even if I could not get the "released_signal", the value of
gtk "gtk_server_callback_value 1 INT"
changes and therefore is a proofable condition.
Did you mean this by "to separate callback functions"?
Or could you explain your solution a bit more detailed, please?
KR Tino
|
|
|
Post by Peter on Sept 26, 2019 18:17:06 GMT 1
Or could you explain your solution a bit more detailed, please? I meant to connect the "pressed" signal and the "released" signal separately to the button: gtk_server_connect my_button pressed my-press-event 1 gtk_server_connect my_button released my-release-event 1
Then, in your mainloop, catch the signal and carry out your code: while true do gtk "gtk_server_callback WAIT";res=$GTK
case "$res" in "my-press-event") echo "button was pressed" "my-release-event") echo "button was released" esac done
HTH Peter
|
|
|
Post by newguiguy on Sept 27, 2019 17:18:40 GMT 1
At the moment I get a signal when the button is pressed and another when released.
gtk_server_connect my_button pressed my-press-event 1 gtk_server_connect my_button released my-release-event 1
This is exactly what I was doing. But if I use a while loop like this one in main
while true do gtk "gtk_server_callback WAIT";res=$GTK
case "$res" in "my-press-event") echo "button was pressed" while [[ "$res" == "my-press-event" ]];do ((i++)) gtk "gtk_entry_set_text $entry_field ${interval[$i]} gtk "gtk_server_callback UPDATE" sleep 0.05 done "my-release-event") echo "button was released" esac done
I am not able to catch the release event. As long as the button is pressed, I stay in the loop. Maybe the released signal is "to fast" emittted and therefore not catchable??? So Peter, please could you explain the behavior behind this if GTK-server relevant So as written before with
|
|
|
Post by newguiguy on Sept 27, 2019 17:25:10 GMT 1
a different value is shown when the button was released.
KR Tino
P.S. Also I have no idea why some of my posts look that ugly and incomplete?!
|
|
|
Post by Peter on Sept 27, 2019 20:29:22 GMT 1
Ok, now I think I understand what you want to do. You want to find out if a mouse button remains in a pressed state, and while this is the case, take an action like increasing a counter or so, right?
In my understanding there is no direct way to do this in GTK, but there is a trick.
You can set a state flag to identify the state of the mouse button and use this flag in your async main loop:
while true do gtk "gtk_server_callback UPDATE";res=$GTK
case "$res" in "my-press-event") echo "button was pressed" state=1 "my-release-event") echo "button was released" state=0 esac
# use state flag to take action if [[ $state -eq 1 ]] then echo "increasing counter" fi
# prevent CPU load of 100% usleep 100 done
But this is not the best code. It might be better to use an event-driven approach using the WAIT argument for "gtk_server_callback". However, this will block the program waiting for the next event to happen.
So to prevent endless waiting, it is possible to forcefully emit an event for the mainloop using a timeout. The timeout can be set to the main window or an invisible widget.
# connect 'show' signal to the main window gtk_server_connect $mymainwindow "show" "my-time-out"
# set timeout to 50 milliseconds forcefully emitting 'show' signal gtk_server_timeout 50 $mymainwindow "show"
# mainloop while true do gtk "gtk_server_callback WAIT";res=$GTK
case "$res" in "my-press-event") echo "button was pressed" state=1 "my-release-event") echo "button was released" state=0 "my-time-out") if [[ $state -eq 1 ]] then echo "increasing counter" fi esac done
HTH Peter
|
|
|
Post by newguiguy on Oct 1, 2019 9:53:28 GMT 1
Yes, correct. I did some test with your examples and changed the loop that no CPU is consumed when no action is done.
gtk_server_connect $mymainwindow "show" "my-time-out"
# mainloop while true do gtk "gtk_server_callback WAIT";res=$GTK
case "$res" in "my-press-event") gtk_server_timeout 50 $mymainwindow "show"; destroy_timeout=$GTK "my-release-event") gtk_server_timeout_remove $destroy_timeout" "my-time-out") echo "increasing counter" esac done
And now, I think it will turn into a really interesting post and also a more GTK-server relevant too. The code above works in general but is not reliable if the timeout is set very low.
Even with 50 ms the release event is not always catched up by GTK-server in that way,
that $res becomes "my-release-event" and therefor the counter increases endless because "gtk_server_timeout_remove" is not executed.
To produce almost always that failure set timeout to 1 ms. It would be good to know where the limits are. Why I think it is related to GTK-server? My method mentioned in this thread earlier is stable but also need the release event to stop. So at least the event is recognized.
KR Tino
|
|
|
Post by newguiguy on Oct 1, 2019 10:13:20 GMT 1
Another question to the concept of signals is, if it is possible to create an own signal name?
In the examples above we used the 'show' signal. But as a newbee I have no overview if that signal could be emitted by any other process/code for example if another GtkBox is shown up or so and starts therefor my counter code.
|
|
|
Post by Peter on Oct 3, 2019 17:32:34 GMT 1
Theoretically you could create your own widgets with your own signals - it is explained here and also other websites (Google is your friend). I never tried to create my own widget though. Your mileage may vary. In the GTK documentation each widget shows it particular signals, and the parents of that widget also have signals which the widget listens to. Please refer to this documentation for further information on available signals. Regarding gtk_server_timeout, I do not see why you have changed the mainloop. In my programs I am actually using the demonstrated code a lot of times and it always works for me. But if your solution works better then please stick to it Best regards Peter
|
|
|
Post by newguiguy on Oct 10, 2019 19:58:55 GMT 1
Simply, because in your loop the signal is emmitted everytime ... # connect 'show' signal to the main window gtk_server_connect $mymainwindow "show" "my-time-out"
# set timeout to 50 milliseconds forcefully emitting 'show' signal gtk_server_timeout 50 $mymainwindow "show"
# mainloop while true ... and in my loop example it is started and destroyed when needed
In case of a spin button what is often only a small fraction of a GTK application I think this is more efficient in terms of CPU usage.
This is the more interessting part of this thread and I'd like to understand why one works better over the other.
Maybe asking a bit more clearly, why can it happen sometimes/often that the $RESULT did not get the release-signal-event if the timeout is set very low?
I add a minimal working example which shows a GtkEntry besides a button. If pressed down the button the number in entry rises and should stop if the button is released. Often the last one failed.
KR Tino
#!/bin/bash # Stop any open gtk-server process stop-gtk-server -all &>/dev/null
# Name of GTK-server PIPE file declare PIPE=/tmp/bash.gtk.$$
# Start gtk-server gtk-server-gtk3 -fifo=$PIPE -detach -log=/tmp/gtk-server.log
# Make sure the PIPE file is available while [ ! -p $PIPE ]; do continue; done
function gtk() { echo "$@" > $PIPE read RESULT < $PIPE } export -f gtk
# Make GUI gtk "gtk_init NULL NULL"
# make main Win gtk "gtk_window_new 0"; win=$RESULT gtk "gtk_window_set_title $win \"spinbutton simulation\"" gtk "gtk_window_set_default_size $win 200 200"
# implement main layout gtk "gtk_vbox_new 0 0"; vbox=$RESULT gtk "gtk_button_new_with_label 'press to increase'"; button=$RESULT gtk "gtk_entry_new"; entry=$RESULT
# arrange layout gtk "gtk_container_add $win $vbox" gtk "gtk_container_add $vbox $button" gtk "gtk_container_add $vbox $entry"
# make win visible gtk "gtk_widget_show_all $win"
# connect signals gtk "gtk_server_connect ${win} show 'increase' 1" gtk "gtk_server_connect ${button} pressed 'pressed' 1" gtk "gtk_server_connect ${button} released 'released' 1"
# main loop while true;do gtk "gtk_server_callback WAIT";res=$RESULT case "$res" in "pressed") gtk "gtk_server_timeout 10 $win show";signal_handle=$RESULT echo "started" ;; "released") gtk "gtk_server_timeout_remove $signal_handle" echo "stopped" ;; "increase") ((i++)) gtk "gtk_entry_set_text $entry \"$i\"" ;; *) gtk "gtk_widget_destroy $win" gtk "gtk_server_exit" break ;; esac done exit
|
|
|
Post by Peter on Oct 11, 2019 18:00:45 GMT 1
Simply, because in your loop the signal is emmitted everytime ... and in my loop example it is started and destroyed when needed That is because you're not following what I am proposing: using a state variable I add a minimal working example which shows a GtkEntry besides a button. If pressed down the button the number in entry rises and should stop if the button is released. Often the last one failed. Now I see what you mean, but the reason is simple: as soon the signal occurs, BASH will start performing its interpretation of the mainloop, and while BASH is doing so, GTK-server cannot catch any signals. You have to realize that signals only are observed by GTK-server as long as it is in its 'WAIT' status. This is a status where it 'waits' for a signal. When the 'show' signal occurs then GTK-server will hand over control to the client script, and the client interpreter will then execute the statements in the mainloop. Obviously, when the interpreter is busy doing so, any signals occurring will be missed by GTK-server, Note that BASH in particular is infamous for its slow performance. The BASH shell has nice features for user interaction, but when it comes to script interpretation it performs 30% or more slower compared to shell interpreters like KSH or ZSH, especially in case of regular expressions. So the faster your interpreter, the faster the mainloop will be executed and the less signals will be missed by GTK-server. Best regards Peter
|
|