Implemented the Window OnClosing() event on GTK+. It works!

This commit is contained in:
Pietro Gagliardi 2014-07-08 12:04:51 -04:00
parent be56707c51
commit 60d0953fe9
4 changed files with 60 additions and 6 deletions

View File

@ -7,6 +7,11 @@ import (
) )
// #include "gtk_unix.h" // #include "gtk_unix.h"
// /* because cgo doesn't like g_signal_connect() */
// void gSignalConnect(gpointer obj, gchar *sig, GCallback callback, gpointer data)
// {
// g_signal_connect(obj, sig, callback, data);
// }
import "C" import "C"
func fromgstr(s *C.gchar) string { func fromgstr(s *C.gchar) string {
@ -20,3 +25,9 @@ func togstr(s string) *C.gchar {
func freegstr(s *C.gchar) { func freegstr(s *C.gchar) {
C.free(unsafe.Pointer(s)) C.free(unsafe.Pointer(s))
} }
func g_signal_connect(object C.gpointer, name string, to C.GCallback, data C.gpointer) {
cname := togstr(name)
defer freegstr(cname)
C.gSignalConnect(object, cname, to, data)
}

View File

@ -45,10 +45,23 @@ type event struct {
lock sync.Mutex lock sync.Mutex
} }
// do should never be nil; TODO should we make setters panic instead?
func newEvent() *event {
return &event{
do: func(c Doer) bool {
return false
},
}
}
func (e *event) set(f func(Doer)) { func (e *event) set(f func(Doer)) {
e.lock.Lock() e.lock.Lock()
defer e.lock.Unlock() defer e.lock.Unlock()
if f == nil {
f = func(c Doer) {}
}
e.do = func(c Doer) bool { e.do = func(c Doer) bool {
f(c) f(c)
return false return false
@ -59,6 +72,11 @@ func (e *event) setbool(f func(Doer) bool) {
e.lock.Lock() e.lock.Lock()
defer e.lock.Unlock() defer e.lock.Unlock()
if f == nil {
f = func(c Doer) bool {
return false
}
}
e.do = f e.do = f
} }

View File

@ -7,6 +7,7 @@ import (
) )
// #include "gtk_unix.h" // #include "gtk_unix.h"
// extern gboolean windowClosing(GtkWidget *, GdkEvent *, gpointer);
import "C" import "C"
type window struct { type window struct {
@ -14,6 +15,8 @@ type window struct {
container *C.GtkContainer container *C.GtkContainer
bin *C.GtkBin bin *C.GtkBin
window *C.GtkWindow window *C.GtkWindow
closing *event
} }
func newWindow(title string, width int, height int) *Request { func newWindow(title string, width int, height int) *Request {
@ -28,8 +31,14 @@ func newWindow(title string, width int, height int) *Request {
container: (*C.GtkContainer)(unsafe.Pointer(widget)), container: (*C.GtkContainer)(unsafe.Pointer(widget)),
bin: (*C.GtkBin)(unsafe.Pointer(widget)), bin: (*C.GtkBin)(unsafe.Pointer(widget)),
window: (*C.GtkWindow)(unsafe.Pointer(widget)), window: (*C.GtkWindow)(unsafe.Pointer(widget)),
closing: newEvent(),
} }
C.gtk_window_set_title(w.window, ctitle) C.gtk_window_set_title(w.window, ctitle)
g_signal_connect(
C.gpointer(unsafe.Pointer(w.window)),
"delete-event",
C.GCallback(C.windowClosing),
C.gpointer(unsafe.Pointer(w)))
// TODO size // TODO size
// TODO content // TODO content
c <- w c <- w
@ -108,6 +117,22 @@ func (w *window) Close() *Request {
} }
func (w *window) OnClosing(e func(c Doer) bool) *Request { func (w *window) OnClosing(e func(c Doer) bool) *Request {
// TODO c := make(chan interface{})
return nil return &Request{
op: func() {
w.closing.setbool(e)
c <- struct{}{}
},
resp: c,
}
}
//export windowClosing
func windowClosing(wid *C.GtkWidget, e *C.GdkEvent, data C.gpointer) C.gboolean {
w := (*window)(unsafe.Pointer(data))
close := w.closing.fire()
if close {
return C.GDK_EVENT_PROPAGATE // will do gtk_widget_destroy(), which is what we want (thanks ebassi in irc.gimp.net/#gtk+)
}
return C.GDK_EVENT_STOP // keeps window alive
} }

View File

@ -12,10 +12,10 @@ func TestPackage(t *testing.T) {
go func() { go func() {
w := GetNewWindow(Do, "Hello", 320, 240) w := GetNewWindow(Do, "Hello", 320, 240)
done := make(chan struct{}) done := make(chan struct{})
// Wait(Do, w.OnClosing(func(Doer) bool { Wait(Do, w.OnClosing(func(Doer) bool {
// done <- struct{}{} done <- struct{}{}
// return true return true
// })) }))
Wait(Do, w.Show()) Wait(Do, w.Show())
<-done <-done
}() }()