From e04e5f5cad34aba8848bd423f81649dc068a8fc3 Mon Sep 17 00:00:00 2001 From: Pietro Gagliardi Date: Tue, 1 Jul 2014 12:09:31 -0400 Subject: Converted the GTK+ backend to use the new uitask. Indeterminate progressbars no longer work; this will be fixed soon. --- uitask_unix.go | 73 +++++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 52 insertions(+), 21 deletions(-) (limited to 'uitask_unix.go') 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() -- cgit v1.2.3