Rolled back all those changes; I'm stupid.

This commit is contained in:
Pietro Gagliardi 2014-06-30 22:42:48 -04:00
parent e8a7dd0b87
commit 990d50e9a1
6 changed files with 300 additions and 157 deletions

View File

@ -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 { func _msgBox(parent *Window, primarytext string, secondarytext string, style uintptr) chan int {
ret := make(chan int) ret := make(chan int)
uitask(func() { uitask <- func() {
var pwin C.id = nil var pwin C.id = nil
if parent != dialogWindow { if parent != dialogWindow {
@ -36,7 +36,7 @@ func _msgBox(parent *Window, primarytext string, secondarytext string, style uin
case 1: // error case 1: // error
C.msgBoxError(pwin, primary, secondary, unsafe.Pointer(&ret)) C.msgBoxError(pwin, primary, secondary, unsafe.Pointer(&ret))
} }
}) }
return ret return ret
} }

View File

@ -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) 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) retchan := make(chan int)
_,_,_,_=parenthwnd,ptext,ptitle,fmt.Printf/* TODO
go func() { go func() {
ret := make(chan uiret) ret := make(chan uiret)
defer close(ret) defer close(ret)
@ -47,7 +46,6 @@ _,_,_,_=parenthwnd,ptext,ptitle,fmt.Printf/* TODO
} }
retchan <- int(r.ret) retchan <- int(r.ret)
}() }()
*/
return retchan return retchan
} }

View File

@ -225,14 +225,20 @@ func (s *sysData) make(window *sysData) error {
if window != nil { if window != nil {
parentWindow = window.id parentWindow = window.id
} }
uitask(func() { ret := make(chan C.id)
s.id = ct.make(parentWindow, s.alternate, s) defer close(ret)
if ct.getinside != nil { uitask <- func() {
addSysData(ct.getinside(s.id), s) ret <- ct.make(parentWindow, s.alternate, s)
} else { }
addSysData(s.id, 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 return nil
} }
@ -243,21 +249,33 @@ func (s *sysData) firstShow() error {
} }
func (s *sysData) show() { func (s *sysData) show() {
uitask(func() { ret := make(chan struct{})
defer close(ret)
uitask <- func() {
classTypes[s.ctype].show(s.id) classTypes[s.ctype].show(s.id)
}) ret <- struct{}{}
}
<-ret
} }
func (s *sysData) hide() { func (s *sysData) hide() {
uitask(func() { ret := make(chan struct{})
defer close(ret)
uitask <- func() {
classTypes[s.ctype].hide(s.id) classTypes[s.ctype].hide(s.id)
}) ret <- struct{}{}
}
<-ret
} }
func (s *sysData) setText(text string) { 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)) 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 { 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 { func (s *sysData) isChecked() bool {
var b bool ret := make(chan bool)
defer close(ret)
uitask(func() { uitask <- func() {
b = C.isCheckboxChecked(s.id) != C.NO ret <- C.isCheckboxChecked(s.id) != C.NO
}) }
return b return <-ret
} }
func (s *sysData) text() string { func (s *sysData) text() string {
var text string ret := make(chan string)
defer close(ret)
uitask(func() { uitask <- func() {
str := classTypes[s.ctype].text(s.id, s.alternate) str := classTypes[s.ctype].text(s.id, s.alternate)
text = fromNSString(str) ret <- fromNSString(str)
}) }
return text return <-ret
} }
func (s *sysData) append(what string) { 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) classTypes[s.ctype].append(s.id, what, s.alternate)
}) ret <- struct{}{}
}
<-ret
} }
func (s *sysData) insertBefore(what string, before int) { 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) classTypes[s.ctype].insertBefore(s.id, what, before, s.alternate)
}) ret <- struct{}{}
}
<-ret
} }
func (s *sysData) selectedIndex() int { func (s *sysData) selectedIndex() int {
var i int ret := make(chan int)
defer close(ret)
uitask(func() { uitask <- func() {
i = classTypes[s.ctype].selIndex(s.id) ret <- classTypes[s.ctype].selIndex(s.id)
}) }
return i return <-ret
} }
func (s *sysData) selectedIndices() []int { func (s *sysData) selectedIndices() []int {
var i []int ret := make(chan []int)
defer close(ret)
uitask(func() { uitask <- func() {
i = classTypes[s.ctype].selIndices(s.id) ret <- classTypes[s.ctype].selIndices(s.id)
}) }
return i return <-ret
} }
func (s *sysData) selectedTexts() []string { func (s *sysData) selectedTexts() []string {
var texts []string ret := make(chan []string)
defer close(ret)
uitask(func() { uitask <- func() {
texts = classTypes[s.ctype].selTexts(s.id) ret <- classTypes[s.ctype].selTexts(s.id)
}) }
return texts return <-ret
} }
func (s *sysData) setWindowSize(width int, height int) error { 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)) C.windowSetContentSize(s.id, C.intptr_t(width), C.intptr_t(height))
}) ret <- struct{}{}
}
<-ret
return nil return nil
} }
func (s *sysData) delete(index int) { func (s *sysData) delete(index int) {
uitask(func() { ret := make(chan struct{})
defer close(ret)
uitask <- func() {
classTypes[s.ctype].delete(s.id, index) classTypes[s.ctype].delete(s.id, index)
}) ret <- struct{}{}
}
<-ret
} }
func (s *sysData) setProgress(percent int) { 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)) C.setProgress(s.id, C.intptr_t(percent))
}) ret <- struct{}{}
}
<-ret
} }
func (s *sysData) len() int { func (s *sysData) len() int {
var i int ret := make(chan int)
defer close(ret)
uitask(func() { uitask <- func() {
i = classTypes[s.ctype].len(s.id) ret <- classTypes[s.ctype].len(s.id)
}) }
return i return <-ret
} }
func (s *sysData) setAreaSize(width int, height int) { 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)) C.setAreaSize(s.id, C.intptr_t(width), C.intptr_t(height))
}) ret <- struct{}{}
}
<-ret
} }
func (s *sysData) repaintAll() { func (s *sysData) repaintAll() {
uitask(func() { ret := make(chan struct{})
defer close(ret)
uitask <- func() {
C.display(s.id) C.display(s.id)
}) ret <- struct{}{}
}
<-ret
} }
func (s *sysData) center() { func (s *sysData) center() {
uitask(func() { ret := make(chan struct{})
defer close(ret)
uitask <- func() {
C.center(s.id) C.center(s.id)
}) ret <- struct{}{}
}
<-ret
} }
func (s *sysData) setChecked(checked bool) { func (s *sysData) setChecked(checked bool) {
uitask(func() { ret := make(chan struct{})
defer close(ret)
uitask <- func() {
C.setCheckboxChecked(s.id, toBOOL(checked)) C.setCheckboxChecked(s.id, toBOOL(checked))
}) ret <- struct{}{}
}
<-ret
} }

View File

@ -148,7 +148,9 @@ var (
) )
func (s *sysData) make(window *sysData) (err error) { func (s *sysData) make(window *sysData) (err error) {
uitask(func() { ret := make(chan struct{})
defer close(ret)
uitask <- func() {
ct := classTypes[s.ctype] ct := classTypes[s.ctype]
cid := _HMENU(0) cid := _HMENU(0)
pwin := uintptr(_NULL) pwin := uintptr(_NULL)
@ -195,7 +197,9 @@ func (s *sysData) make(window *sysData) (err error) {
uintptr(_WPARAM(controlFont)), uintptr(_WPARAM(controlFont)),
uintptr(_LPARAM(_TRUE))) uintptr(_LPARAM(_TRUE)))
} }
}) ret <- struct{}{}
}
<-ret
return nil return nil
} }
@ -207,7 +211,9 @@ var (
// ShowWindow(hwnd, nCmdShow); // ShowWindow(hwnd, nCmdShow);
// UpdateWindow(hwnd); // UpdateWindow(hwnd);
func (s *sysData) firstShow() error { func (s *sysData) firstShow() error {
uitask(func() { ret := make(chan struct{})
defer close(ret)
uitask <- func() {
_showWindow.Call( _showWindow.Call(
uintptr(s.hwnd), uintptr(s.hwnd),
uintptr(nCmdShow)) uintptr(nCmdShow))
@ -215,28 +221,40 @@ func (s *sysData) firstShow() error {
if r1 == 0 { // failure if r1 == 0 { // failure
panic(fmt.Errorf("error updating window for the first time: %v", err)) panic(fmt.Errorf("error updating window for the first time: %v", err))
} }
}) ret <- struct{}{}
}
<-ret
return nil return nil
} }
func (s *sysData) show() { func (s *sysData) show() {
uitask(func() { ret := make(chan struct{})
defer close(ret)
uitask <- func() {
_showWindow.Call( _showWindow.Call(
uintptr(s.hwnd), uintptr(s.hwnd),
uintptr(_SW_SHOW)) uintptr(_SW_SHOW))
}) ret <- struct{}{}
}
<-ret
} }
func (s *sysData) hide() { func (s *sysData) hide() {
uitask(func() { ret := make(chan struct{})
defer close(ret)
uitask <- func() {
_showWindow.Call( _showWindow.Call(
uintptr(s.hwnd), uintptr(s.hwnd),
uintptr(_SW_HIDE)) uintptr(_SW_HIDE))
}) ret <- struct{}{}
}
<-ret
} }
func (s *sysData) setText(text string) { func (s *sysData) setText(text string) {
uitask(func() { ret := make(chan struct{})
defer close(ret)
uitask <- func() {
ptext := toUTF16(text) ptext := toUTF16(text)
r1, _, err := _setWindowText.Call( r1, _, err := _setWindowText.Call(
uintptr(s.hwnd), uintptr(s.hwnd),
@ -244,7 +262,9 @@ func (s *sysData) setText(text string) {
if r1 == 0 { // failure if r1 == 0 { // failure
panic(fmt.Errorf("error setting window/control text: %v", err)) panic(fmt.Errorf("error setting window/control text: %v", err))
} }
}) ret <- struct{}{}
}
<-ret
} }
// runs on uitask // 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 { func (s *sysData) isChecked() bool {
var b bool ret := make(chan bool)
defer close(ret)
uitask(func() { uitask <- func() {
r1, _, _ := _sendMessage.Call( r1, _, _ := _sendMessage.Call(
uintptr(s.hwnd), uintptr(s.hwnd),
uintptr(_BM_GETCHECK), uintptr(_BM_GETCHECK),
uintptr(0), uintptr(0),
uintptr(0)) uintptr(0))
b = r1 == _BST_CHECKED ret <- r1 == _BST_CHECKED
}) }
return b return <-ret
} }
func (s *sysData) text() string { func (s *sysData) text() (str string) {
var str string ret := make(chan string)
defer close(ret)
uitask(func() { uitask <- func() {
var tc []uint16 var tc []uint16
r1, _, _ := _sendMessage.Call( r1, _, _ := _sendMessage.Call(
@ -294,13 +314,15 @@ func (s *sysData) text() string {
uintptr(_WM_GETTEXT), uintptr(_WM_GETTEXT),
uintptr(_WPARAM(length)), uintptr(_WPARAM(length)),
uintptr(_LPARAM(unsafe.Pointer(&tc[0])))) uintptr(_LPARAM(unsafe.Pointer(&tc[0]))))
str = syscall.UTF16ToString(tc) ret <- syscall.UTF16ToString(tc)
}) }
return str return <-ret
} }
func (s *sysData) append(what string) { func (s *sysData) append(what string) {
uitask(func() { ret := make(chan struct{})
defer close(ret)
uitask <- func() {
pwhat := toUTF16(what) pwhat := toUTF16(what)
r1, _, err := _sendMessage.Call( r1, _, err := _sendMessage.Call(
uintptr(s.hwnd), uintptr(s.hwnd),
@ -312,11 +334,15 @@ func (s *sysData) append(what string) {
} else if r1 == uintptr(classTypes[s.ctype].selectedIndexErr) { } else if r1 == uintptr(classTypes[s.ctype].selectedIndexErr) {
panic(fmt.Errorf("failed to add item to combobox/listbox (last error: %v)", err)) 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) { func (s *sysData) insertBefore(what string, index int) {
uitask(func() { ret := make(chan struct{})
defer close(ret)
uitask <- func() {
pwhat := toUTF16(what) pwhat := toUTF16(what)
r1, _, err := _sendMessage.Call( r1, _, err := _sendMessage.Call(
uintptr(s.hwnd), uintptr(s.hwnd),
@ -328,7 +354,9 @@ func (s *sysData) insertBefore(what string, index int) {
} else if r1 == uintptr(classTypes[s.ctype].selectedIndexErr) { } else if r1 == uintptr(classTypes[s.ctype].selectedIndexErr) {
panic(fmt.Errorf("failed to add item to combobox/listbox (last error: %v)", err)) panic(fmt.Errorf("failed to add item to combobox/listbox (last error: %v)", err))
} }
}) ret <- struct{}{}
}
<-ret
} }
// runs on uitask // runs on uitask
@ -345,12 +373,12 @@ func (s *sysData) doSelectedIndex() int {
} }
func (s *sysData) selectedIndex() int { func (s *sysData) selectedIndex() int {
var i int ret := make(chan int)
defer close(ret)
uitask(func() { uitask <- func() {
i = s.doSelectedIndex() ret <- s.doSelectedIndex()
}) }
return i return <-ret
} }
// runs on uitask // runs on uitask
@ -387,20 +415,20 @@ func (s *sysData) doSelectedIndices() []int {
} }
func (s *sysData) selectedIndices() []int { func (s *sysData) selectedIndices() []int {
var i []int ret := make(chan []int)
defer close(ret)
uitask(func() { uitask <- func() {
i = s.doSelectedIndices() ret <- s.doSelectedIndices()
}) }
return i return <-ret
} }
func (s *sysData) selectedTexts() []string { func (s *sysData) selectedTexts() []string {
var strings []string ret := make(chan []string)
defer close(ret)
uitask(func() { uitask <- func() {
indices := s.doSelectedIndices() indices := s.doSelectedIndices()
strings = make([]string, len(indices)) strings := make([]string, len(indices))
for i, v := range indices { for i, v := range indices {
r1, _, err := _sendMessage.Call( r1, _, err := _sendMessage.Call(
uintptr(s.hwnd), uintptr(s.hwnd),
@ -421,12 +449,15 @@ func (s *sysData) selectedTexts() []string {
} }
strings[i] = syscall.UTF16ToString(str) strings[i] = syscall.UTF16ToString(str)
} }
}) ret <- strings
return strings }
return <-ret
} }
func (s *sysData) setWindowSize(width int, height int) error { func (s *sysData) setWindowSize(width int, height int) error {
uitask(func() { ret := make(chan struct{})
defer close(ret)
uitask <- func() {
var rect _RECT var rect _RECT
r1, _, err := _getClientRect.Call( r1, _, err := _getClientRect.Call(
@ -441,12 +472,16 @@ func (s *sysData) setWindowSize(width int, height int) error {
if err != nil { if err != nil {
panic(fmt.Errorf("error actually resizing window: %v", err)) panic(fmt.Errorf("error actually resizing window: %v", err))
} }
}) ret <- struct{}{}
}
<-ret
return nil return nil
} }
func (s *sysData) delete(index int) { func (s *sysData) delete(index int) {
uitask(func() { ret := make(chan struct{})
defer close(ret)
uitask <- func() {
r1, _, err := _sendMessage.Call( r1, _, err := _sendMessage.Call(
uintptr(s.hwnd), uintptr(s.hwnd),
uintptr(classTypes[s.ctype].deleteMsg), uintptr(classTypes[s.ctype].deleteMsg),
@ -455,11 +490,15 @@ func (s *sysData) delete(index int) {
if r1 == uintptr(classTypes[s.ctype].selectedIndexErr) { if r1 == uintptr(classTypes[s.ctype].selectedIndexErr) {
panic(fmt.Errorf("failed to delete item from combobox/listbox (last error: %v)", err)) panic(fmt.Errorf("failed to delete item from combobox/listbox (last error: %v)", err))
} }
}) ret <- struct{}{}
}
<-ret
} }
func (s *sysData) setIndeterminate() { func (s *sysData) setIndeterminate() {
uitask(func() { ret := make(chan struct{})
defer close(ret)
uitask <- func() {
r1, _, err := _setWindowLongPtr.Call( r1, _, err := _setWindowLongPtr.Call(
uintptr(s.hwnd), uintptr(s.hwnd),
negConst(_GWL_STYLE), negConst(_GWL_STYLE),
@ -473,7 +512,9 @@ func (s *sysData) setIndeterminate() {
uintptr(_WPARAM(_TRUE)), uintptr(_WPARAM(_TRUE)),
uintptr(0)) uintptr(0))
s.isMarquee = true s.isMarquee = true
}) ret <- struct{}{}
}
<-ret
} }
func (s *sysData) setProgress(percent int) { func (s *sysData) setProgress(percent int) {
@ -481,7 +522,9 @@ func (s *sysData) setProgress(percent int) {
s.setIndeterminate() s.setIndeterminate()
return return
} }
uitask(func() { ret := make(chan struct{})
defer close(ret)
uitask <- func() {
if s.isMarquee { if s.isMarquee {
// turn off marquee before switching back // turn off marquee before switching back
_sendMessage.Call( _sendMessage.Call(
@ -517,13 +560,15 @@ func (s *sysData) setProgress(percent int) {
if percent == 100 { if percent == 100 {
send(_PBM_SETRANGE32, 0, 100) send(_PBM_SETRANGE32, 0, 100)
} }
}) ret <- struct{}{}
}
<-ret
} }
func (s *sysData) len() int { func (s *sysData) len() int {
var i int ret := make(chan int)
defer close(ret)
uitask(func() { uitask <- func() {
r1, _, err := _sendMessage.Call( r1, _, err := _sendMessage.Call(
uintptr(s.hwnd), uintptr(s.hwnd),
uintptr(classTypes[s.ctype].lenMsg), uintptr(classTypes[s.ctype].lenMsg),
@ -532,33 +577,43 @@ func (s *sysData) len() int {
if r1 == uintptr(classTypes[s.ctype].selectedIndexErr) { if r1 == uintptr(classTypes[s.ctype].selectedIndexErr) {
panic(fmt.Errorf("unexpected error return from sysData.len(); GetLastError() says %v", err)) panic(fmt.Errorf("unexpected error return from sysData.len(); GetLastError() says %v", err))
} }
i = int(r1) ret <- int(r1)
}) }
return i return <-ret
} }
func (s *sysData) setAreaSize(width int, height int) { func (s *sysData) setAreaSize(width int, height int) {
uitask(func() { ret := make(chan struct{})
defer close(ret)
uitask <- func() {
_sendMessage.Call( _sendMessage.Call(
uintptr(s.hwnd), uintptr(s.hwnd),
uintptr(msgSetAreaSize), uintptr(msgSetAreaSize),
uintptr(width), // WPARAM is UINT_PTR on Windows XP and newer at least, so we're good with this uintptr(width), // WPARAM is UINT_PTR on Windows XP and newer at least, so we're good with this
uintptr(height)) uintptr(height))
}) ret <- struct{}{}
}
<-ret
} }
func (s *sysData) repaintAll() { func (s *sysData) repaintAll() {
uitask(func() { ret := make(chan struct{})
defer close(ret)
uitask <- func() {
_sendMessage.Call( _sendMessage.Call(
uintptr(s.hwnd), uintptr(s.hwnd),
uintptr(msgRepaintAll), uintptr(msgRepaintAll),
uintptr(0), uintptr(0),
uintptr(0)) uintptr(0))
}) ret <- struct{}{}
}
<-ret
} }
func (s *sysData) center() { func (s *sysData) center() {
uitask(func() { ret := make(chan struct{})
defer close(ret)
uitask <- func() {
var ws _RECT var ws _RECT
r1, _, err := _getWindowRect.Call( r1, _, err := _getWindowRect.Call(
@ -576,11 +631,15 @@ func (s *sysData) center() {
wx := (int32(dw) / 2) - (ww / 2) wx := (int32(dw) / 2) - (ww / 2)
wy := (int32(dh) / 2) - (wh / 2) wy := (int32(dh) / 2) - (wh / 2)
s.setRect(int(wx), int(wy), int(ww), int(wh), 0) s.setRect(int(wx), int(wy), int(ww), int(wh), 0)
}) ret <- struct{}{}
}
<-ret
} }
func (s *sysData) setChecked(checked bool) { func (s *sysData) setChecked(checked bool) {
uitask(func() { ret := make(chan struct{})
defer close(ret)
uitask <- func() {
c := uintptr(_BST_CHECKED) c := uintptr(_BST_CHECKED)
if !checked { if !checked {
c = uintptr(_BST_UNCHECKED) c = uintptr(_BST_UNCHECKED)
@ -590,5 +649,7 @@ func (s *sysData) setChecked(checked bool) {
uintptr(_BM_SETCHECK), uintptr(_BM_SETCHECK),
c, c,
uintptr(0)) uintptr(0))
}) ret <- struct{}{}
}
<-ret
} }

View File

@ -14,25 +14,30 @@ import (
// #include "objc_darwin.h" // #include "objc_darwin.h"
import "C" import "C"
// can be run from any thread var uitask chan func()
// will wait for return; see delegateuitask_darwin.m
func uitask(f func()) {
C.douitask(appDelegate, unsafe.Pointer(&f))
}
func ui(main func()) error { func ui(main func()) error {
runtime.LockOSThread() runtime.LockOSThread()
uitask = make(chan func())
err := initCocoa() err := initCocoa()
if err != nil { if err != nil {
return err 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() { go func() {
main() main()
uitask(func() { uitask <- func() {
C.breakMainLoop() C.breakMainLoop()
}) }
}() }()
C.cocoaMainLoop() C.cocoaMainLoop()

View File

@ -22,15 +22,17 @@ the only recourse, and the one both Microsoft (http://support.microsoft.com/kb/1
yay. yay.
*/ */
var uimsgwin _HWND var uitask chan interface{}
// works from any thread; waits for the function to finish before returning type uimsg struct {
func uitask(f func()) { call *syscall.LazyProc
_sendMessage.Call( p []uintptr
uintptr(uimsgwin), ret chan uiret
msgRequested, }
uintptr(0),
uintptr(unsafe.Pointer(&f))) type uiret struct {
ret uintptr
err error
} }
const ( const (
@ -47,20 +49,34 @@ var (
func ui(main func()) error { func ui(main func()) error {
runtime.LockOSThread() runtime.LockOSThread()
uitask = make(chan interface{})
err := doWindowsInit() err := doWindowsInit()
if err != nil { if err != nil {
return fmt.Errorf("error doing general Windows initialization: %v", err) return fmt.Errorf("error doing general Windows initialization: %v", err)
} }
uimsgwin, err = makeMessageHandler() hwnd, err := makeMessageHandler()
if err != nil { if err != nil {
return fmt.Errorf("error making invisible window for handling events: %v", err) 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() { go func() {
main() main()
r1, _, err := _postMessage.Call( r1, _, err := _postMessage.Call(
uintptr(uimsgwin), uintptr(hwnd),
msgQuit, msgQuit,
uintptr(0), uintptr(0),
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 { func messageHandlerWndProc(hwnd _HWND, uMsg uint32, wParam _WPARAM, lParam _LPARAM) _LRESULT {
switch uMsg { switch uMsg {
case msgRequested: case msgRequested:
f := (*func())(unsafe.Pointer(lParam)) mt := (*interface{})(unsafe.Pointer(lParam))
(*f)() 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 return 0
case msgQuit: case msgQuit:
// does not return a value according to MSDN // does not return a value according to MSDN