diff options
| author | Pietro Gagliardi <[email protected]> | 2014-02-18 09:57:19 -0500 |
|---|---|---|
| committer | Pietro Gagliardi <[email protected]> | 2014-02-18 09:57:19 -0500 |
| commit | 1f08c874e0c9df9019e994098e1d006a7011e533 (patch) | |
| tree | 7d19b3d64b35e4746d1816b81d0f05e1aadf0f34 | |
| parent | 16ab1763ba7468314972b962440ff80dad2997f5 (diff) | |
Made event dispatch asynchronous to avoid deadlocks; right now events that cannot be dispatched get dropped.
| -rw-r--r-- | stdwndclass_windows.go | 6 | ||||
| -rw-r--r-- | sysdata.go | 13 | ||||
| -rw-r--r-- | sysdata_unix.go | 20 |
3 files changed, 23 insertions, 16 deletions
diff --git a/stdwndclass_windows.go b/stdwndclass_windows.go index 2824746..3c9861f 100644 --- a/stdwndclass_windows.go +++ b/stdwndclass_windows.go @@ -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( @@ -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 diff --git a/sysdata_unix.go b/sysdata_unix.go index 3c13b8c..3250b6d 100644 --- a/sysdata_unix.go +++ b/sysdata_unix.go @@ -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 } }, |
