From 990d50e9a153681a091a23734f8962e728fde1b0 Mon Sep 17 00:00:00 2001 From: Pietro Gagliardi Date: Mon, 30 Jun 2014 22:42:48 -0400 Subject: [PATCH] Rolled back all those changes; I'm stupid. --- dialog_darwin.go | 4 +- dialog_windows.go | 2 - sysdata_darwin.go | 188 +++++++++++++++++++++++++++---------------- sysdata_windows.go | 195 +++++++++++++++++++++++++++++---------------- uitask_darwin.go | 19 +++-- uitask_windows.go | 49 +++++++++--- 6 files changed, 300 insertions(+), 157 deletions(-) diff --git a/dialog_darwin.go b/dialog_darwin.go index fe44d8f..038c640 100644 --- a/dialog_darwin.go +++ b/dialog_darwin.go @@ -19,7 +19,7 @@ func dialog_send(pchan unsafe.Pointer, res C.intptr_t) { func _msgBox(parent *Window, primarytext string, secondarytext string, style uintptr) chan int { ret := make(chan int) - uitask(func() { + uitask <- func() { var pwin C.id = nil if parent != dialogWindow { @@ -36,7 +36,7 @@ func _msgBox(parent *Window, primarytext string, secondarytext string, style uin case 1: // error C.msgBoxError(pwin, primary, secondary, unsafe.Pointer(&ret)) } - }) + } return ret } diff --git a/dialog_windows.go b/dialog_windows.go index 910fb88..c6da94b 100644 --- a/dialog_windows.go +++ b/dialog_windows.go @@ -27,7 +27,6 @@ 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) @@ -47,7 +46,6 @@ _,_,_,_=parenthwnd,ptext,ptitle,fmt.Printf/* TODO } retchan <- int(r.ret) }() -*/ return retchan } diff --git a/sysdata_darwin.go b/sysdata_darwin.go index 06c921e..48b7d44 100644 --- a/sysdata_darwin.go +++ b/sysdata_darwin.go @@ -225,14 +225,20 @@ func (s *sysData) make(window *sysData) error { if window != nil { parentWindow = window.id } - uitask(func() { - s.id = ct.make(parentWindow, s.alternate, s) - if ct.getinside != nil { - addSysData(ct.getinside(s.id), s) - } else { - addSysData(s.id, s) + ret := make(chan C.id) + defer close(ret) + uitask <- func() { + ret <- ct.make(parentWindow, s.alternate, s) + } + s.id = <-ret + if ct.getinside != nil { + uitask <- func() { + ret <- ct.getinside(s.id) } - }) + addSysData(<-ret, s) + } else { + addSysData(s.id, s) + } return nil } @@ -243,21 +249,33 @@ func (s *sysData) firstShow() error { } func (s *sysData) show() { - uitask(func() { + ret := make(chan struct{}) + defer close(ret) + uitask <- func() { classTypes[s.ctype].show(s.id) - }) + ret <- struct{}{} + } + <-ret } func (s *sysData) hide() { - uitask(func() { + ret := make(chan struct{}) + defer close(ret) + uitask <- func() { classTypes[s.ctype].hide(s.id) - }) + ret <- struct{}{} + } + <-ret } func (s *sysData) setText(text string) { - uitask(func() { + ret := make(chan struct{}) + defer close(ret) + uitask <- func() { classTypes[s.ctype].settext(s.id, toNSString(text)) - }) + ret <- struct{}{} + } + <-ret } func (s *sysData) setRect(x int, y int, width int, height int, winheight int) error { @@ -270,111 +288,147 @@ func (s *sysData) setRect(x int, y int, width int, height int, winheight int) er } func (s *sysData) isChecked() bool { - var b bool - - uitask(func() { - b = C.isCheckboxChecked(s.id) != C.NO - }) - return b + ret := make(chan bool) + defer close(ret) + uitask <- func() { + ret <- C.isCheckboxChecked(s.id) != C.NO + } + return <-ret } func (s *sysData) text() string { - var text string - - uitask(func() { + ret := make(chan string) + defer close(ret) + uitask <- func() { str := classTypes[s.ctype].text(s.id, s.alternate) - text = fromNSString(str) - }) - return text + ret <- fromNSString(str) + } + return <-ret } func (s *sysData) append(what string) { - uitask(func() { + ret := make(chan struct{}) + defer close(ret) + uitask <- func() { classTypes[s.ctype].append(s.id, what, s.alternate) - }) + ret <- struct{}{} + } + <-ret } func (s *sysData) insertBefore(what string, before int) { - uitask(func() { + ret := make(chan struct{}) + defer close(ret) + uitask <- func() { classTypes[s.ctype].insertBefore(s.id, what, before, s.alternate) - }) + ret <- struct{}{} + } + <-ret } func (s *sysData) selectedIndex() int { - var i int - - uitask(func() { - i = classTypes[s.ctype].selIndex(s.id) - }) - return i + ret := make(chan int) + defer close(ret) + uitask <- func() { + ret <- classTypes[s.ctype].selIndex(s.id) + } + return <-ret } func (s *sysData) selectedIndices() []int { - var i []int - - uitask(func() { - i = classTypes[s.ctype].selIndices(s.id) - }) - return i + ret := make(chan []int) + defer close(ret) + uitask <- func() { + ret <- classTypes[s.ctype].selIndices(s.id) + } + return <-ret } func (s *sysData) selectedTexts() []string { - var texts []string - - uitask(func() { - texts = classTypes[s.ctype].selTexts(s.id) - }) - return texts + ret := make(chan []string) + defer close(ret) + uitask <- func() { + ret <- classTypes[s.ctype].selTexts(s.id) + } + return <-ret } func (s *sysData) setWindowSize(width int, height int) error { - uitask(func() { + ret := make(chan struct{}) + defer close(ret) + uitask <- func() { C.windowSetContentSize(s.id, C.intptr_t(width), C.intptr_t(height)) - }) + ret <- struct{}{} + } + <-ret return nil } func (s *sysData) delete(index int) { - uitask(func() { + ret := make(chan struct{}) + defer close(ret) + uitask <- func() { classTypes[s.ctype].delete(s.id, index) - }) + ret <- struct{}{} + } + <-ret } func (s *sysData) setProgress(percent int) { - uitask(func() { + ret := make(chan struct{}) + defer close(ret) + uitask <- func() { C.setProgress(s.id, C.intptr_t(percent)) - }) + ret <- struct{}{} + } + <-ret } func (s *sysData) len() int { - var i int - - uitask(func() { - i = classTypes[s.ctype].len(s.id) - }) - return i + ret := make(chan int) + defer close(ret) + uitask <- func() { + ret <- classTypes[s.ctype].len(s.id) + } + return <-ret } func (s *sysData) setAreaSize(width int, height int) { - uitask(func() { + ret := make(chan struct{}) + defer close(ret) + uitask <- func() { C.setAreaSize(s.id, C.intptr_t(width), C.intptr_t(height)) - }) + ret <- struct{}{} + } + <-ret } func (s *sysData) repaintAll() { - uitask(func() { + ret := make(chan struct{}) + defer close(ret) + uitask <- func() { C.display(s.id) - }) + ret <- struct{}{} + } + <-ret } func (s *sysData) center() { - uitask(func() { + ret := make(chan struct{}) + defer close(ret) + uitask <- func() { C.center(s.id) - }) + ret <- struct{}{} + } + <-ret } func (s *sysData) setChecked(checked bool) { - uitask(func() { + ret := make(chan struct{}) + defer close(ret) + uitask <- func() { C.setCheckboxChecked(s.id, toBOOL(checked)) - }) + ret <- struct{}{} + } + <-ret } diff --git a/sysdata_windows.go b/sysdata_windows.go index 3a6fc63..504b715 100644 --- a/sysdata_windows.go +++ b/sysdata_windows.go @@ -148,7 +148,9 @@ var ( ) func (s *sysData) make(window *sysData) (err error) { - uitask(func() { + ret := make(chan struct{}) + defer close(ret) + uitask <- func() { ct := classTypes[s.ctype] cid := _HMENU(0) pwin := uintptr(_NULL) @@ -195,7 +197,9 @@ func (s *sysData) make(window *sysData) (err error) { uintptr(_WPARAM(controlFont)), uintptr(_LPARAM(_TRUE))) } - }) + ret <- struct{}{} + } + <-ret return nil } @@ -207,7 +211,9 @@ var ( // ShowWindow(hwnd, nCmdShow); // UpdateWindow(hwnd); func (s *sysData) firstShow() error { - uitask(func() { + ret := make(chan struct{}) + defer close(ret) + uitask <- func() { _showWindow.Call( uintptr(s.hwnd), uintptr(nCmdShow)) @@ -215,28 +221,40 @@ 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() { - uitask(func() { + ret := make(chan struct{}) + defer close(ret) + uitask <- func() { _showWindow.Call( uintptr(s.hwnd), uintptr(_SW_SHOW)) - }) + ret <- struct{}{} + } + <-ret } func (s *sysData) hide() { - uitask(func() { + ret := make(chan struct{}) + defer close(ret) + uitask <- func() { _showWindow.Call( uintptr(s.hwnd), uintptr(_SW_HIDE)) - }) + ret <- struct{}{} + } + <-ret } func (s *sysData) setText(text string) { - uitask(func() { + ret := make(chan struct{}) + defer close(ret) + uitask <- func() { ptext := toUTF16(text) r1, _, err := _setWindowText.Call( uintptr(s.hwnd), @@ -244,7 +262,9 @@ 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 @@ -263,23 +283,23 @@ func (s *sysData) setRect(x int, y int, width int, height int, winheight int) er } func (s *sysData) isChecked() bool { - var b bool - - uitask(func() { + ret := make(chan bool) + defer close(ret) + uitask <- func() { r1, _, _ := _sendMessage.Call( uintptr(s.hwnd), uintptr(_BM_GETCHECK), uintptr(0), uintptr(0)) - b = r1 == _BST_CHECKED - }) - return b + ret <- r1 == _BST_CHECKED + } + return <-ret } -func (s *sysData) text() string { - var str string - - uitask(func() { +func (s *sysData) text() (str string) { + ret := make(chan string) + defer close(ret) + uitask <- func() { var tc []uint16 r1, _, _ := _sendMessage.Call( @@ -294,13 +314,15 @@ func (s *sysData) text() string { uintptr(_WM_GETTEXT), uintptr(_WPARAM(length)), uintptr(_LPARAM(unsafe.Pointer(&tc[0])))) - str = syscall.UTF16ToString(tc) - }) - return str + ret <- syscall.UTF16ToString(tc) + } + return <-ret } func (s *sysData) append(what string) { - uitask(func() { + ret := make(chan struct{}) + defer close(ret) + uitask <- func() { pwhat := toUTF16(what) r1, _, err := _sendMessage.Call( uintptr(s.hwnd), @@ -312,11 +334,15 @@ 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) { - uitask(func() { + ret := make(chan struct{}) + defer close(ret) + uitask <- func() { pwhat := toUTF16(what) r1, _, err := _sendMessage.Call( uintptr(s.hwnd), @@ -328,7 +354,9 @@ 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 @@ -345,12 +373,12 @@ func (s *sysData) doSelectedIndex() int { } func (s *sysData) selectedIndex() int { - var i int - - uitask(func() { - i = s.doSelectedIndex() - }) - return i + ret := make(chan int) + defer close(ret) + uitask <- func() { + ret <- s.doSelectedIndex() + } + return <-ret } // runs on uitask @@ -387,20 +415,20 @@ func (s *sysData) doSelectedIndices() []int { } func (s *sysData) selectedIndices() []int { - var i []int - - uitask(func() { - i = s.doSelectedIndices() - }) - return i + ret := make(chan []int) + defer close(ret) + uitask <- func() { + ret <- s.doSelectedIndices() + } + return <-ret } func (s *sysData) selectedTexts() []string { - var strings []string - - uitask(func() { + ret := make(chan []string) + defer close(ret) + 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), @@ -421,12 +449,15 @@ func (s *sysData) selectedTexts() []string { } strings[i] = syscall.UTF16ToString(str) } - }) - return strings + ret <- strings + } + return <-ret } func (s *sysData) setWindowSize(width int, height int) error { - uitask(func() { + ret := make(chan struct{}) + defer close(ret) + uitask <- func() { var rect _RECT r1, _, err := _getClientRect.Call( @@ -441,12 +472,16 @@ 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) { - uitask(func() { + ret := make(chan struct{}) + defer close(ret) + uitask <- func() { r1, _, err := _sendMessage.Call( uintptr(s.hwnd), uintptr(classTypes[s.ctype].deleteMsg), @@ -455,11 +490,15 @@ 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() { - uitask(func() { + ret := make(chan struct{}) + defer close(ret) + uitask <- func() { r1, _, err := _setWindowLongPtr.Call( uintptr(s.hwnd), negConst(_GWL_STYLE), @@ -473,7 +512,9 @@ func (s *sysData) setIndeterminate() { uintptr(_WPARAM(_TRUE)), uintptr(0)) s.isMarquee = true - }) + ret <- struct{}{} + } + <-ret } func (s *sysData) setProgress(percent int) { @@ -481,7 +522,9 @@ func (s *sysData) setProgress(percent int) { s.setIndeterminate() return } - uitask(func() { + ret := make(chan struct{}) + defer close(ret) + uitask <- func() { if s.isMarquee { // turn off marquee before switching back _sendMessage.Call( @@ -517,13 +560,15 @@ func (s *sysData) setProgress(percent int) { if percent == 100 { send(_PBM_SETRANGE32, 0, 100) } - }) + ret <- struct{}{} + } + <-ret } func (s *sysData) len() int { - var i int - - uitask(func() { + ret := make(chan int) + defer close(ret) + uitask <- func() { r1, _, err := _sendMessage.Call( uintptr(s.hwnd), uintptr(classTypes[s.ctype].lenMsg), @@ -532,33 +577,43 @@ 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)) } - i = int(r1) - }) - return i + ret <- int(r1) + } + return <-ret } func (s *sysData) setAreaSize(width int, height int) { - uitask(func() { + ret := make(chan struct{}) + defer close(ret) + 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() { - uitask(func() { + ret := make(chan struct{}) + defer close(ret) + uitask <- func() { _sendMessage.Call( uintptr(s.hwnd), uintptr(msgRepaintAll), uintptr(0), uintptr(0)) - }) + ret <- struct{}{} + } + <-ret } func (s *sysData) center() { - uitask(func() { + ret := make(chan struct{}) + defer close(ret) + uitask <- func() { var ws _RECT r1, _, err := _getWindowRect.Call( @@ -576,11 +631,15 @@ 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) { - uitask(func() { + ret := make(chan struct{}) + defer close(ret) + uitask <- func() { c := uintptr(_BST_CHECKED) if !checked { c = uintptr(_BST_UNCHECKED) @@ -590,5 +649,7 @@ func (s *sysData) setChecked(checked bool) { uintptr(_BM_SETCHECK), c, uintptr(0)) - }) + ret <- struct{}{} + } + <-ret } diff --git a/uitask_darwin.go b/uitask_darwin.go index 5932cac..754418c 100644 --- a/uitask_darwin.go +++ b/uitask_darwin.go @@ -14,25 +14,30 @@ import ( // #include "objc_darwin.h" import "C" -// can be run from any thread -// will wait for return; see delegateuitask_darwin.m -func uitask(f func()) { - C.douitask(appDelegate, unsafe.Pointer(&f)) -} +var uitask chan func() func ui(main func()) error { runtime.LockOSThread() + uitask = make(chan func()) + err := initCocoa() if err != nil { return err } + // Cocoa must run on the first thread created by the program, so we run our dispatcher on another thread instead + go func() { + for f := range uitask { + C.douitask(appDelegate, unsafe.Pointer(&f)) + } + }() + go func() { main() - uitask(func() { + uitask <- func() { C.breakMainLoop() - }) + } }() C.cocoaMainLoop() diff --git a/uitask_windows.go b/uitask_windows.go index 772403f..1075b5b 100644 --- a/uitask_windows.go +++ b/uitask_windows.go @@ -22,15 +22,17 @@ the only recourse, and the one both Microsoft (http://support.microsoft.com/kb/1 yay. */ -var uimsgwin _HWND +var uitask chan interface{} -// 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))) +type uimsg struct { + call *syscall.LazyProc + p []uintptr + ret chan uiret +} + +type uiret struct { + ret uintptr + err error } const ( @@ -47,20 +49,34 @@ 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) } - uimsgwin, err = makeMessageHandler() + hwnd, 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(uimsgwin), + uintptr(hwnd), msgQuit, uintptr(0), uintptr(0)) @@ -162,8 +178,17 @@ func makeMessageHandler() (hwnd _HWND, err error) { func messageHandlerWndProc(hwnd _HWND, uMsg uint32, wParam _WPARAM, lParam _LPARAM) _LRESULT { switch uMsg { case msgRequested: - f := (*func())(unsafe.Pointer(lParam)) - (*f)() + 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() + } return 0 case msgQuit: // does not return a value according to MSDN