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

View File

@ -55,6 +55,19 @@ func (c *cSysData) delete(int) error {
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 (
c_window = iota
c_button

View File

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