summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPietro Gagliardi <[email protected]>2014-07-08 12:04:51 -0400
committerPietro Gagliardi <[email protected]>2014-07-08 12:04:51 -0400
commit60d0953fe9f16726958f709007402ea4c8b89fc6 (patch)
treed3704828dad002c1144626aaec1f3e5cc5560041
parentbe56707c51a411c5e8228a78d663c91df4636128 (diff)
Implemented the Window OnClosing() event on GTK+. It works!
-rw-r--r--redo/common_unix.go11
-rw-r--r--redo/uitask.go18
-rw-r--r--redo/window_unix.go29
-rw-r--r--redo/zz_test.go8
4 files changed, 60 insertions, 6 deletions
diff --git a/redo/common_unix.go b/redo/common_unix.go
index e495063..e2d9261 100644
--- a/redo/common_unix.go
+++ b/redo/common_unix.go
@@ -7,6 +7,11 @@ import (
)
// #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"
func fromgstr(s *C.gchar) string {
@@ -20,3 +25,9 @@ func togstr(s string) *C.gchar {
func freegstr(s *C.gchar) {
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)
+}
diff --git a/redo/uitask.go b/redo/uitask.go
index 76908fb..462a24b 100644
--- a/redo/uitask.go
+++ b/redo/uitask.go
@@ -45,10 +45,23 @@ type event struct {
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)) {
e.lock.Lock()
defer e.lock.Unlock()
+ if f == nil {
+ f = func(c Doer) {}
+ }
e.do = func(c Doer) bool {
f(c)
return false
@@ -59,6 +72,11 @@ func (e *event) setbool(f func(Doer) bool) {
e.lock.Lock()
defer e.lock.Unlock()
+ if f == nil {
+ f = func(c Doer) bool {
+ return false
+ }
+ }
e.do = f
}
diff --git a/redo/window_unix.go b/redo/window_unix.go
index 6e93fa7..c92fba6 100644
--- a/redo/window_unix.go
+++ b/redo/window_unix.go
@@ -7,6 +7,7 @@ import (
)
// #include "gtk_unix.h"
+// extern gboolean windowClosing(GtkWidget *, GdkEvent *, gpointer);
import "C"
type window struct {
@@ -14,6 +15,8 @@ type window struct {
container *C.GtkContainer
bin *C.GtkBin
window *C.GtkWindow
+
+ closing *event
}
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)),
bin: (*C.GtkBin)(unsafe.Pointer(widget)),
window: (*C.GtkWindow)(unsafe.Pointer(widget)),
+ closing: newEvent(),
}
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 content
c <- w
@@ -108,6 +117,22 @@ func (w *window) Close() *Request {
}
func (w *window) OnClosing(e func(c Doer) bool) *Request {
- // TODO
- return nil
+ c := make(chan interface{})
+ 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
}
diff --git a/redo/zz_test.go b/redo/zz_test.go
index a4ff669..122005b 100644
--- a/redo/zz_test.go
+++ b/redo/zz_test.go
@@ -12,10 +12,10 @@ func TestPackage(t *testing.T) {
go func() {
w := GetNewWindow(Do, "Hello", 320, 240)
done := make(chan struct{})
-// Wait(Do, w.OnClosing(func(Doer) bool {
-// done <- struct{}{}
-// return true
-// }))
+ Wait(Do, w.OnClosing(func(Doer) bool {
+ done <- struct{}{}
+ return true
+ }))
Wait(Do, w.Show())
<-done
}()