diff --git a/callbacks_unix.go b/callbacks_unix.go index b9ed870..2de1656 100644 --- a/callbacks_unix.go +++ b/callbacks_unix.go @@ -89,7 +89,7 @@ func our_idle_callback(what C.gpointer) C.gboolean { return C.FALSE // remove this idle function; we're finished } -func gdk_threads_add_idle(idleop *gtkIdleOp) { +func gdk_threads_add_idle_op(idleop *gtkIdleOp) { C.gdk_threads_add_idle(C.GCallback(C.our_idle_callback), C.gpointer(unsafe.Pointer(idleop))) } diff --git a/sysdata_unix.go b/sysdata_unix.go index b39df50..ae0e2a0 100644 --- a/sysdata_unix.go +++ b/sysdata_unix.go @@ -220,9 +220,10 @@ func (s *sysData) delete(index int) { func (s *sysData) progressPulse() { // TODO this could probably be done differently... pulse := func() { - touitask(func() { - gtk_progress_bar_pulse(s.widget) - }) + // TODO +// touitask(func() { +// gtk_progress_bar_pulse(s.widget) +// }) } var ticker *time.Ticker diff --git a/uitask_unix.go b/uitask_unix.go index a8cabd2..74bd83e 100644 --- a/uitask_unix.go +++ b/uitask_unix.go @@ -6,13 +6,52 @@ package ui import ( "fmt" + "unsafe" ) // #cgo pkg-config: gtk+-3.0 // #include "gtk_unix.h" +// /* unfortunately, there's no way to differentiate between the main thread and other threads; in fact, doing what we do on other platforms is discouraged by the GTK+ devs! +// but I can't avoid this any other way... so we have structures defined on the C side to skirt the garbage collector */ +// struct uitaskParams { +// void *window; /* createWindow */ +// void *control; /* createWindow */ +// gboolean show; /* createWindow */ +// }; +// static struct uitaskParams *mkParams(void) +// { +// /* g_malloc0() will abort on not enough memory */ +// return (struct uitaskParams *) g_malloc0(sizeof (struct uitaskParams)); +// } +// static void freeParams(struct uitaskParams *p) +// { +// g_free(p); +// } +// extern gboolean our_createWindow_callback(gpointer); import "C" -var uitask chan func() +//export our_createWindow_callback +func our_createWindow_callback(what C.gpointer) C.gboolean { + uc := (*C.struct_uitaskParams)(unsafe.Pointer(what)) + w := (*Window)(unsafe.Pointer(uc.window)) + c := *(*Control)(unsafe.Pointer(uc.control)) + s := fromgbool(uc.show) + w.create(c, s) + C.freeParams(uc) + return C.FALSE // remove this idle function; we're finished +} + +func (_uitask) createWindow(w *Window, c Control, s bool) { + uc := C.mkParams() + uc.window = unsafe.Pointer(w) + uc.control = unsafe.Pointer(&c) + uc.show = togbool(s) + gdk_threads_add_idle(C.our_createWindow_callback, unsafe.Pointer(uc)) +} + +func gdk_threads_add_idle(f unsafe.Pointer, what unsafe.Pointer) { + C.gdk_threads_add_idle(C.GCallback(f), C.gpointer(what)) +} func uiinit() error { err := gtk_init() @@ -20,8 +59,6 @@ func uiinit() error { return fmt.Errorf("gtk_init() failed: %v", err) } - // do this only on success, just to be safe - uitask = make(chan func()) return nil } @@ -29,25 +66,19 @@ func ui() { // thanks to tristan and Daniel_S in irc.gimp.net/#gtk // see our_idle_callback in callbacks_unix.go for details go func() { - for { - var f func() - - select { - case f = <-uitask: - // do nothing - case <-Stop: - f = func() { - C.gtk_main_quit() - } - } - done := make(chan struct{}) - gdk_threads_add_idle(>kIdleOp{ - what: f, - done: done, - }) - <-done - close(done) + // TODO do differently + <-Stop + // using gdk_threads_add_idle() will make sure it gets run when any events currently being handled finish running + f := func() { + C.gtk_main_quit() } + done := make(chan struct{}) + gdk_threads_add_idle_op(>kIdleOp{ + what: f, + done: done, + }) + <-done + close(done) }() C.gtk_main()