Fixed indeterminate progress bars on GTK+. This specific fix also avoids any future panics caused by Go and GTK+ racing by doing the pulsing all on GTK+.
This commit is contained in:
parent
e04e5f5cad
commit
2a7152339f
|
@ -5,10 +5,11 @@
|
||||||
package ui
|
package ui
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"time"
|
"unsafe"
|
||||||
)
|
)
|
||||||
|
|
||||||
// #include "gtk_unix.h"
|
// #include "gtk_unix.h"
|
||||||
|
// extern gboolean our_pulse_callback(gpointer);
|
||||||
import "C"
|
import "C"
|
||||||
|
|
||||||
type sysData struct {
|
type sysData struct {
|
||||||
|
@ -16,7 +17,7 @@ type sysData struct {
|
||||||
|
|
||||||
widget *C.GtkWidget
|
widget *C.GtkWidget
|
||||||
container *C.GtkWidget // for moving
|
container *C.GtkWidget // for moving
|
||||||
pulse chan bool // for sysData.progressPulse()
|
pulseTimer C.guint // for indeterminate progress bars
|
||||||
clickCounter clickCounter // for Areas
|
clickCounter clickCounter // for Areas
|
||||||
// we probably don't need to save these, but we'll do so for sysData.preferredSize() just in case
|
// we probably don't need to save these, but we'll do so for sysData.preferredSize() just in case
|
||||||
areawidth int
|
areawidth int
|
||||||
|
@ -216,54 +217,33 @@ func (s *sysData) delete(index int) {
|
||||||
classTypes[s.ctype].delete(s.widget, index)
|
classTypes[s.ctype].delete(s.widget, index)
|
||||||
}
|
}
|
||||||
|
|
||||||
// With GTK+, we must manually pulse the indeterminate progressbar ourselves. This goroutine does that.
|
// With GTK+, we must manually pulse the indeterminate progressbar ourselves.
|
||||||
func (s *sysData) progressPulse() {
|
// To ensure pulsing runs on the main lop and doesn't cause any other weird racy things, we'll use g_timeout_add().
|
||||||
// TODO this could probably be done differently...
|
// Zenity 3.4 does this too (https://git.gnome.org/browse/zenity/tree/src/progress.c?id=3.4.0).
|
||||||
pulse := func() {
|
// The following is Zenity 3.4's pulse rate.
|
||||||
// TODO
|
const pulseRate = 100 // in milliseconds
|
||||||
// touitask(func() {
|
|
||||||
// gtk_progress_bar_pulse(s.widget)
|
|
||||||
// })
|
|
||||||
}
|
|
||||||
|
|
||||||
var ticker *time.Ticker
|
//export our_pulse_callback
|
||||||
var tickchan <-chan time.Time
|
func our_pulse_callback(data C.gpointer) C.gboolean {
|
||||||
|
// TODO this can be called when closing the window
|
||||||
// the pulse rate used by Zenity (https://git.gnome.org/browse/zenity/tree/src/progress.c#n69 for blob cbffe08e8337ba1375a0ac7210eff5a2e4313bb8)
|
s := (*sysData)(unsafe.Pointer(data))
|
||||||
const pulseRate = 100 * time.Millisecond
|
gtk_progress_bar_pulse(s.widget)
|
||||||
|
return C.TRUE // continue processing
|
||||||
for {
|
|
||||||
select {
|
|
||||||
case start := <-s.pulse:
|
|
||||||
if start {
|
|
||||||
ticker = time.NewTicker(pulseRate)
|
|
||||||
tickchan = ticker.C
|
|
||||||
pulse() // start the pulse animation now, not 100ms later
|
|
||||||
} else {
|
|
||||||
if ticker != nil {
|
|
||||||
ticker.Stop()
|
|
||||||
}
|
|
||||||
ticker = nil
|
|
||||||
tickchan = nil
|
|
||||||
s.pulse <- true // notify sysData.setProgress()
|
|
||||||
}
|
|
||||||
case <-tickchan:
|
|
||||||
pulse()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *sysData) setProgress(percent int) {
|
func (s *sysData) setProgress(percent int) {
|
||||||
if s.pulse == nil {
|
if s.pulseTimer != 0 { // kill current timer
|
||||||
s.pulse = make(chan bool)
|
// TODO only if not indeterminate already?
|
||||||
go s.progressPulse()
|
C.g_source_remove(s.pulseTimer)
|
||||||
|
s.pulseTimer = 0
|
||||||
}
|
}
|
||||||
if percent == -1 {
|
if percent == -1 {
|
||||||
s.pulse <- true
|
gtk_progress_bar_pulse(s.widget) // start animation now
|
||||||
|
s.pulseTimer = C.g_timeout_add(pulseRate,
|
||||||
|
C.GSourceFunc(C.our_pulse_callback),
|
||||||
|
C.gpointer(unsafe.Pointer(s)))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
s.pulse <- false
|
|
||||||
<-s.pulse // wait for sysData.progressPulse() to register that
|
|
||||||
gtk_progress_bar_set_fraction(s.widget, percent)
|
gtk_progress_bar_set_fraction(s.widget, percent)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue