Made event dispatch asynchronous to avoid deadlocks; right now events that cannot be dispatched get dropped.

This commit is contained in:
Pietro Gagliardi 2014-02-18 09:57:19 -05:00
parent 16ab1763ba
commit 1f08c874e0
3 changed files with 23 additions and 16 deletions

View File

@ -32,7 +32,7 @@ func stdWndProc(s *sysData) func(hwnd _HWND, uMsg uint32, wParam _WPARAM, lParam
switch ss.ctype { switch ss.ctype {
case c_button: case c_button:
if wParam.HIWORD() == _BN_CLICKED { if wParam.HIWORD() == _BN_CLICKED {
ss.event <- struct{}{} ss.signal()
} }
} }
return 0 return 0
@ -58,9 +58,7 @@ func stdWndProc(s *sysData) func(hwnd _HWND, uMsg uint32, wParam _WPARAM, lParam
} }
return 0 return 0
case _WM_CLOSE: case _WM_CLOSE:
if s.event != nil { s.signal()
s.event <- struct{}{}
}
return 0 return 0
default: default:
r1, _, _ := defWindowProc.Call( r1, _, _ := defWindowProc.Call(

View File

@ -55,6 +55,19 @@ func (c *cSysData) delete(int) error {
panic(runtime.GOOS + " sysData does not define delete()") panic(runtime.GOOS + " sysData does not define delete()")
} }
// signal sends the event signal. This raise is done asynchronously to avoid deadlocking the UI task.
// Thanks skelterjohn for this techinque: if we can't queue any more events, drop them; TODO this would be best if the channel is buffered
func (s *cSysData) signal() {
if s.event != nil {
go func() {
select {
case s.event <- struct{}{}:
default:
}
}()
}
}
const ( const (
c_window = iota c_window = iota
c_button c_button

View File

@ -35,19 +35,17 @@ var classTypes = [nctypes]*classData{
setText: gtk_window_set_title, setText: gtk_window_set_title,
text: gtk_window_get_title, text: gtk_window_get_title,
signals: map[string]func(*sysData) func() bool{ signals: map[string]func(*sysData) func() bool{
"delete-event": func(w *sysData) func() bool { "delete-event": func(s *sysData) func() bool {
return func() bool { return func() bool {
if w.event != nil { s.signal()
w.event <- struct{}{}
}
return true // do not close the window return true // do not close the window
} }
}, },
"configure-event": func(w *sysData) func() bool { "configure-event": func(s *sysData) func() bool {
return func() bool { return func() bool {
if w.container != nil && w.resize != nil { // wait for init if s.container != nil && s.resize != nil { // wait for init
width, height := gtk_window_get_size(w.widget) width, height := gtk_window_get_size(s.widget)
err := w.resize(0, 0, width, height) err := s.resize(0, 0, width, height)
if err != nil { if err != nil {
panic("child resize failed: " + err.Error()) panic("child resize failed: " + err.Error())
} }
@ -64,11 +62,9 @@ var classTypes = [nctypes]*classData{
setText: gtk_button_set_label, setText: gtk_button_set_label,
text: gtk_button_get_label, text: gtk_button_get_label,
signals: map[string]func(*sysData) func() bool{ signals: map[string]func(*sysData) func() bool{
"clicked": func(w *sysData) func() bool { "clicked": func(s *sysData) func() bool {
return func() bool { return func() bool {
if w.event != nil { s.signal()
w.event <- struct{}{}
}
return true // do not close the window return true // do not close the window
} }
}, },