diff --git a/dialog_windows.go b/dialog_windows.go index 655aa8b..910fb88 100644 --- a/dialog_windows.go +++ b/dialog_windows.go @@ -27,10 +27,10 @@ func _msgBox(parent *Window, primarytext string, secondarytext string, uType uin uType |= _MB_TASKMODAL // make modal to every window in the program (they're all windows of the uitask, which is a single thread) } retchan := make(chan int) +_,_,_,_=parenthwnd,ptext,ptitle,fmt.Printf/* TODO go func() { ret := make(chan uiret) defer close(ret) -/* TODO uitask <- &uimsg{ call: _messageBox, p: []uintptr{ @@ -41,13 +41,13 @@ func _msgBox(parent *Window, primarytext string, secondarytext string, uType uin }, ret: ret, } -*/ r := <-ret if r.ret == 0 { // failure panic(fmt.Sprintf("error displaying message box to user: %v\nstyle: 0x%08X\ntitle: %q\ntext:\n%s", r.err, uType, os.Args[0], text)) } retchan <- int(r.ret) }() +*/ return retchan } diff --git a/sysdata_windows.go b/sysdata_windows.go index 504b715..3a6fc63 100644 --- a/sysdata_windows.go +++ b/sysdata_windows.go @@ -148,9 +148,7 @@ var ( ) func (s *sysData) make(window *sysData) (err error) { - ret := make(chan struct{}) - defer close(ret) - uitask <- func() { + uitask(func() { ct := classTypes[s.ctype] cid := _HMENU(0) pwin := uintptr(_NULL) @@ -197,9 +195,7 @@ func (s *sysData) make(window *sysData) (err error) { uintptr(_WPARAM(controlFont)), uintptr(_LPARAM(_TRUE))) } - ret <- struct{}{} - } - <-ret + }) return nil } @@ -211,9 +207,7 @@ var ( // ShowWindow(hwnd, nCmdShow); // UpdateWindow(hwnd); func (s *sysData) firstShow() error { - ret := make(chan struct{}) - defer close(ret) - uitask <- func() { + uitask(func() { _showWindow.Call( uintptr(s.hwnd), uintptr(nCmdShow)) @@ -221,40 +215,28 @@ func (s *sysData) firstShow() error { if r1 == 0 { // failure panic(fmt.Errorf("error updating window for the first time: %v", err)) } - ret <- struct{}{} - } - <-ret + }) return nil } func (s *sysData) show() { - ret := make(chan struct{}) - defer close(ret) - uitask <- func() { + uitask(func() { _showWindow.Call( uintptr(s.hwnd), uintptr(_SW_SHOW)) - ret <- struct{}{} - } - <-ret + }) } func (s *sysData) hide() { - ret := make(chan struct{}) - defer close(ret) - uitask <- func() { + uitask(func() { _showWindow.Call( uintptr(s.hwnd), uintptr(_SW_HIDE)) - ret <- struct{}{} - } - <-ret + }) } func (s *sysData) setText(text string) { - ret := make(chan struct{}) - defer close(ret) - uitask <- func() { + uitask(func() { ptext := toUTF16(text) r1, _, err := _setWindowText.Call( uintptr(s.hwnd), @@ -262,9 +244,7 @@ func (s *sysData) setText(text string) { if r1 == 0 { // failure panic(fmt.Errorf("error setting window/control text: %v", err)) } - ret <- struct{}{} - } - <-ret + }) } // runs on uitask @@ -283,23 +263,23 @@ func (s *sysData) setRect(x int, y int, width int, height int, winheight int) er } func (s *sysData) isChecked() bool { - ret := make(chan bool) - defer close(ret) - uitask <- func() { + var b bool + + uitask(func() { r1, _, _ := _sendMessage.Call( uintptr(s.hwnd), uintptr(_BM_GETCHECK), uintptr(0), uintptr(0)) - ret <- r1 == _BST_CHECKED - } - return <-ret + b = r1 == _BST_CHECKED + }) + return b } -func (s *sysData) text() (str string) { - ret := make(chan string) - defer close(ret) - uitask <- func() { +func (s *sysData) text() string { + var str string + + uitask(func() { var tc []uint16 r1, _, _ := _sendMessage.Call( @@ -314,15 +294,13 @@ func (s *sysData) text() (str string) { uintptr(_WM_GETTEXT), uintptr(_WPARAM(length)), uintptr(_LPARAM(unsafe.Pointer(&tc[0])))) - ret <- syscall.UTF16ToString(tc) - } - return <-ret + str = syscall.UTF16ToString(tc) + }) + return str } func (s *sysData) append(what string) { - ret := make(chan struct{}) - defer close(ret) - uitask <- func() { + uitask(func() { pwhat := toUTF16(what) r1, _, err := _sendMessage.Call( uintptr(s.hwnd), @@ -334,15 +312,11 @@ func (s *sysData) append(what string) { } else if r1 == uintptr(classTypes[s.ctype].selectedIndexErr) { panic(fmt.Errorf("failed to add item to combobox/listbox (last error: %v)", err)) } - ret <- struct{}{} - } - <-ret + }) } func (s *sysData) insertBefore(what string, index int) { - ret := make(chan struct{}) - defer close(ret) - uitask <- func() { + uitask(func() { pwhat := toUTF16(what) r1, _, err := _sendMessage.Call( uintptr(s.hwnd), @@ -354,9 +328,7 @@ func (s *sysData) insertBefore(what string, index int) { } else if r1 == uintptr(classTypes[s.ctype].selectedIndexErr) { panic(fmt.Errorf("failed to add item to combobox/listbox (last error: %v)", err)) } - ret <- struct{}{} - } - <-ret + }) } // runs on uitask @@ -373,12 +345,12 @@ func (s *sysData) doSelectedIndex() int { } func (s *sysData) selectedIndex() int { - ret := make(chan int) - defer close(ret) - uitask <- func() { - ret <- s.doSelectedIndex() - } - return <-ret + var i int + + uitask(func() { + i = s.doSelectedIndex() + }) + return i } // runs on uitask @@ -415,20 +387,20 @@ func (s *sysData) doSelectedIndices() []int { } func (s *sysData) selectedIndices() []int { - ret := make(chan []int) - defer close(ret) - uitask <- func() { - ret <- s.doSelectedIndices() - } - return <-ret + var i []int + + uitask(func() { + i = s.doSelectedIndices() + }) + return i } func (s *sysData) selectedTexts() []string { - ret := make(chan []string) - defer close(ret) - uitask <- func() { + var strings []string + + uitask(func() { indices := s.doSelectedIndices() - strings := make([]string, len(indices)) + strings = make([]string, len(indices)) for i, v := range indices { r1, _, err := _sendMessage.Call( uintptr(s.hwnd), @@ -449,15 +421,12 @@ func (s *sysData) selectedTexts() []string { } strings[i] = syscall.UTF16ToString(str) } - ret <- strings - } - return <-ret + }) + return strings } func (s *sysData) setWindowSize(width int, height int) error { - ret := make(chan struct{}) - defer close(ret) - uitask <- func() { + uitask(func() { var rect _RECT r1, _, err := _getClientRect.Call( @@ -472,16 +441,12 @@ func (s *sysData) setWindowSize(width int, height int) error { if err != nil { panic(fmt.Errorf("error actually resizing window: %v", err)) } - ret <- struct{}{} - } - <-ret + }) return nil } func (s *sysData) delete(index int) { - ret := make(chan struct{}) - defer close(ret) - uitask <- func() { + uitask(func() { r1, _, err := _sendMessage.Call( uintptr(s.hwnd), uintptr(classTypes[s.ctype].deleteMsg), @@ -490,15 +455,11 @@ func (s *sysData) delete(index int) { if r1 == uintptr(classTypes[s.ctype].selectedIndexErr) { panic(fmt.Errorf("failed to delete item from combobox/listbox (last error: %v)", err)) } - ret <- struct{}{} - } - <-ret + }) } func (s *sysData) setIndeterminate() { - ret := make(chan struct{}) - defer close(ret) - uitask <- func() { + uitask(func() { r1, _, err := _setWindowLongPtr.Call( uintptr(s.hwnd), negConst(_GWL_STYLE), @@ -512,9 +473,7 @@ func (s *sysData) setIndeterminate() { uintptr(_WPARAM(_TRUE)), uintptr(0)) s.isMarquee = true - ret <- struct{}{} - } - <-ret + }) } func (s *sysData) setProgress(percent int) { @@ -522,9 +481,7 @@ func (s *sysData) setProgress(percent int) { s.setIndeterminate() return } - ret := make(chan struct{}) - defer close(ret) - uitask <- func() { + uitask(func() { if s.isMarquee { // turn off marquee before switching back _sendMessage.Call( @@ -560,15 +517,13 @@ func (s *sysData) setProgress(percent int) { if percent == 100 { send(_PBM_SETRANGE32, 0, 100) } - ret <- struct{}{} - } - <-ret + }) } func (s *sysData) len() int { - ret := make(chan int) - defer close(ret) - uitask <- func() { + var i int + + uitask(func() { r1, _, err := _sendMessage.Call( uintptr(s.hwnd), uintptr(classTypes[s.ctype].lenMsg), @@ -577,43 +532,33 @@ func (s *sysData) len() int { if r1 == uintptr(classTypes[s.ctype].selectedIndexErr) { panic(fmt.Errorf("unexpected error return from sysData.len(); GetLastError() says %v", err)) } - ret <- int(r1) - } - return <-ret + i = int(r1) + }) + return i } func (s *sysData) setAreaSize(width int, height int) { - ret := make(chan struct{}) - defer close(ret) - uitask <- func() { + uitask(func() { _sendMessage.Call( uintptr(s.hwnd), uintptr(msgSetAreaSize), uintptr(width), // WPARAM is UINT_PTR on Windows XP and newer at least, so we're good with this uintptr(height)) - ret <- struct{}{} - } - <-ret + }) } func (s *sysData) repaintAll() { - ret := make(chan struct{}) - defer close(ret) - uitask <- func() { + uitask(func() { _sendMessage.Call( uintptr(s.hwnd), uintptr(msgRepaintAll), uintptr(0), uintptr(0)) - ret <- struct{}{} - } - <-ret + }) } func (s *sysData) center() { - ret := make(chan struct{}) - defer close(ret) - uitask <- func() { + uitask(func() { var ws _RECT r1, _, err := _getWindowRect.Call( @@ -631,15 +576,11 @@ func (s *sysData) center() { wx := (int32(dw) / 2) - (ww / 2) wy := (int32(dh) / 2) - (wh / 2) s.setRect(int(wx), int(wy), int(ww), int(wh), 0) - ret <- struct{}{} - } - <-ret + }) } func (s *sysData) setChecked(checked bool) { - ret := make(chan struct{}) - defer close(ret) - uitask <- func() { + uitask(func() { c := uintptr(_BST_CHECKED) if !checked { c = uintptr(_BST_UNCHECKED) @@ -649,7 +590,5 @@ func (s *sysData) setChecked(checked bool) { uintptr(_BM_SETCHECK), c, uintptr(0)) - ret <- struct{}{} - } - <-ret + }) } diff --git a/uitask_windows.go b/uitask_windows.go index 1075b5b..772403f 100644 --- a/uitask_windows.go +++ b/uitask_windows.go @@ -22,17 +22,15 @@ the only recourse, and the one both Microsoft (http://support.microsoft.com/kb/1 yay. */ -var uitask chan interface{} +var uimsgwin _HWND -type uimsg struct { - call *syscall.LazyProc - p []uintptr - ret chan uiret -} - -type uiret struct { - ret uintptr - err error +// works from any thread; waits for the function to finish before returning +func uitask(f func()) { + _sendMessage.Call( + uintptr(uimsgwin), + msgRequested, + uintptr(0), + uintptr(unsafe.Pointer(&f))) } const ( @@ -49,34 +47,20 @@ var ( func ui(main func()) error { runtime.LockOSThread() - uitask = make(chan interface{}) err := doWindowsInit() if err != nil { return fmt.Errorf("error doing general Windows initialization: %v", err) } - hwnd, err := makeMessageHandler() + uimsgwin, err = makeMessageHandler() if err != nil { return fmt.Errorf("error making invisible window for handling events: %v", err) } - go func() { - for m := range uitask { - r1, _, err := _postMessage.Call( - uintptr(hwnd), - msgRequested, - uintptr(0), - uintptr(unsafe.Pointer(&m))) - if r1 == 0 { // failure - panic("error sending message to message loop to call function: " + err.Error()) - } - } - }() - go func() { main() r1, _, err := _postMessage.Call( - uintptr(hwnd), + uintptr(uimsgwin), msgQuit, uintptr(0), uintptr(0)) @@ -178,17 +162,8 @@ func makeMessageHandler() (hwnd _HWND, err error) { func messageHandlerWndProc(hwnd _HWND, uMsg uint32, wParam _WPARAM, lParam _LPARAM) _LRESULT { switch uMsg { case msgRequested: - mt := (*interface{})(unsafe.Pointer(lParam)) - switch m := (*mt).(type) { - case *uimsg: - r1, _, err := m.call.Call(m.p...) - m.ret <- uiret{ - ret: r1, - err: err, - } - case func(): - m() - } + f := (*func())(unsafe.Pointer(lParam)) + (*f)() return 0 case msgQuit: // does not return a value according to MSDN