Implemented the Window OnClosing() event on GTK+. It works!
This commit is contained in:
parent
be56707c51
commit
60d0953fe9
|
@ -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)
|
||||||
|
}
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
}()
|
}()
|
||||||
|
|
Loading…
Reference in New Issue