Converted the Windows backend to make uitask a function that runs the func() passed into it, rather than a channel that sends the function to another dispatcher. Windows lets us, since SendMessage() will switch threads if called form another thread. This gets rid of one goroutine and makes things cleaner. Mac OS X has the same optimization avaialble (performSelectorOnMainThread:); GTK+... doesn't seem to...
This commit is contained in:
parent
496df12751
commit
46ba0049cb
|
@ -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)
|
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)
|
||||||
/* TODO
|
|
||||||
uitask <- &uimsg{
|
uitask <- &uimsg{
|
||||||
call: _messageBox,
|
call: _messageBox,
|
||||||
p: []uintptr{
|
p: []uintptr{
|
||||||
|
@ -41,13 +41,13 @@ func _msgBox(parent *Window, primarytext string, secondarytext string, uType uin
|
||||||
},
|
},
|
||||||
ret: ret,
|
ret: ret,
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
r := <-ret
|
r := <-ret
|
||||||
if r.ret == 0 { // failure
|
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))
|
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)
|
retchan <- int(r.ret)
|
||||||
}()
|
}()
|
||||||
|
*/
|
||||||
return retchan
|
return retchan
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -148,9 +148,7 @@ var (
|
||||||
)
|
)
|
||||||
|
|
||||||
func (s *sysData) make(window *sysData) (err error) {
|
func (s *sysData) make(window *sysData) (err error) {
|
||||||
ret := make(chan struct{})
|
uitask(func() {
|
||||||
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)
|
||||||
|
@ -197,9 +195,7 @@ 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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -211,9 +207,7 @@ var (
|
||||||
// ShowWindow(hwnd, nCmdShow);
|
// ShowWindow(hwnd, nCmdShow);
|
||||||
// UpdateWindow(hwnd);
|
// UpdateWindow(hwnd);
|
||||||
func (s *sysData) firstShow() error {
|
func (s *sysData) firstShow() error {
|
||||||
ret := make(chan struct{})
|
uitask(func() {
|
||||||
defer close(ret)
|
|
||||||
uitask <- func() {
|
|
||||||
_showWindow.Call(
|
_showWindow.Call(
|
||||||
uintptr(s.hwnd),
|
uintptr(s.hwnd),
|
||||||
uintptr(nCmdShow))
|
uintptr(nCmdShow))
|
||||||
|
@ -221,40 +215,28 @@ 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() {
|
||||||
ret := make(chan struct{})
|
uitask(func() {
|
||||||
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() {
|
||||||
ret := make(chan struct{})
|
uitask(func() {
|
||||||
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) {
|
||||||
ret := make(chan struct{})
|
uitask(func() {
|
||||||
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),
|
||||||
|
@ -262,9 +244,7 @@ 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
|
||||||
|
@ -283,23 +263,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 {
|
||||||
ret := make(chan bool)
|
var b 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))
|
||||||
ret <- r1 == _BST_CHECKED
|
b = r1 == _BST_CHECKED
|
||||||
}
|
})
|
||||||
return <-ret
|
return b
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *sysData) text() (str string) {
|
func (s *sysData) text() string {
|
||||||
ret := make(chan string)
|
var str string
|
||||||
defer close(ret)
|
|
||||||
uitask <- func() {
|
uitask(func() {
|
||||||
var tc []uint16
|
var tc []uint16
|
||||||
|
|
||||||
r1, _, _ := _sendMessage.Call(
|
r1, _, _ := _sendMessage.Call(
|
||||||
|
@ -314,15 +294,13 @@ func (s *sysData) text() (str 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]))))
|
||||||
ret <- syscall.UTF16ToString(tc)
|
str = syscall.UTF16ToString(tc)
|
||||||
}
|
})
|
||||||
return <-ret
|
return str
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *sysData) append(what string) {
|
func (s *sysData) append(what string) {
|
||||||
ret := make(chan struct{})
|
uitask(func() {
|
||||||
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),
|
||||||
|
@ -334,15 +312,11 @@ 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) {
|
||||||
ret := make(chan struct{})
|
uitask(func() {
|
||||||
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),
|
||||||
|
@ -354,9 +328,7 @@ 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
|
||||||
|
@ -373,12 +345,12 @@ func (s *sysData) doSelectedIndex() int {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *sysData) selectedIndex() int {
|
func (s *sysData) selectedIndex() int {
|
||||||
ret := make(chan int)
|
var i int
|
||||||
defer close(ret)
|
|
||||||
uitask <- func() {
|
uitask(func() {
|
||||||
ret <- s.doSelectedIndex()
|
i = s.doSelectedIndex()
|
||||||
}
|
})
|
||||||
return <-ret
|
return i
|
||||||
}
|
}
|
||||||
|
|
||||||
// runs on uitask
|
// runs on uitask
|
||||||
|
@ -415,20 +387,20 @@ func (s *sysData) doSelectedIndices() []int {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *sysData) selectedIndices() []int {
|
func (s *sysData) selectedIndices() []int {
|
||||||
ret := make(chan []int)
|
var i []int
|
||||||
defer close(ret)
|
|
||||||
uitask <- func() {
|
uitask(func() {
|
||||||
ret <- s.doSelectedIndices()
|
i = s.doSelectedIndices()
|
||||||
}
|
})
|
||||||
return <-ret
|
return i
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *sysData) selectedTexts() []string {
|
func (s *sysData) selectedTexts() []string {
|
||||||
ret := make(chan []string)
|
var strings []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),
|
||||||
|
@ -449,15 +421,12 @@ 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 {
|
||||||
ret := make(chan struct{})
|
uitask(func() {
|
||||||
defer close(ret)
|
|
||||||
uitask <- func() {
|
|
||||||
var rect _RECT
|
var rect _RECT
|
||||||
|
|
||||||
r1, _, err := _getClientRect.Call(
|
r1, _, err := _getClientRect.Call(
|
||||||
|
@ -472,16 +441,12 @@ 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) {
|
||||||
ret := make(chan struct{})
|
uitask(func() {
|
||||||
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),
|
||||||
|
@ -490,15 +455,11 @@ 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() {
|
||||||
ret := make(chan struct{})
|
uitask(func() {
|
||||||
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),
|
||||||
|
@ -512,9 +473,7 @@ 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) {
|
||||||
|
@ -522,9 +481,7 @@ func (s *sysData) setProgress(percent int) {
|
||||||
s.setIndeterminate()
|
s.setIndeterminate()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
ret := make(chan struct{})
|
uitask(func() {
|
||||||
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(
|
||||||
|
@ -560,15 +517,13 @@ 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 {
|
||||||
ret := make(chan int)
|
var i 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),
|
||||||
|
@ -577,43 +532,33 @@ 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))
|
||||||
}
|
}
|
||||||
ret <- int(r1)
|
i = int(r1)
|
||||||
}
|
})
|
||||||
return <-ret
|
return i
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *sysData) setAreaSize(width int, height int) {
|
func (s *sysData) setAreaSize(width int, height int) {
|
||||||
ret := make(chan struct{})
|
uitask(func() {
|
||||||
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() {
|
||||||
ret := make(chan struct{})
|
uitask(func() {
|
||||||
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() {
|
||||||
ret := make(chan struct{})
|
uitask(func() {
|
||||||
defer close(ret)
|
|
||||||
uitask <- func() {
|
|
||||||
var ws _RECT
|
var ws _RECT
|
||||||
|
|
||||||
r1, _, err := _getWindowRect.Call(
|
r1, _, err := _getWindowRect.Call(
|
||||||
|
@ -631,15 +576,11 @@ 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) {
|
||||||
ret := make(chan struct{})
|
uitask(func() {
|
||||||
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)
|
||||||
|
@ -649,7 +590,5 @@ func (s *sysData) setChecked(checked bool) {
|
||||||
uintptr(_BM_SETCHECK),
|
uintptr(_BM_SETCHECK),
|
||||||
c,
|
c,
|
||||||
uintptr(0))
|
uintptr(0))
|
||||||
ret <- struct{}{}
|
})
|
||||||
}
|
|
||||||
<-ret
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,17 +22,15 @@ the only recourse, and the one both Microsoft (http://support.microsoft.com/kb/1
|
||||||
yay.
|
yay.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
var uitask chan interface{}
|
var uimsgwin _HWND
|
||||||
|
|
||||||
type uimsg struct {
|
// works from any thread; waits for the function to finish before returning
|
||||||
call *syscall.LazyProc
|
func uitask(f func()) {
|
||||||
p []uintptr
|
_sendMessage.Call(
|
||||||
ret chan uiret
|
uintptr(uimsgwin),
|
||||||
}
|
msgRequested,
|
||||||
|
uintptr(0),
|
||||||
type uiret struct {
|
uintptr(unsafe.Pointer(&f)))
|
||||||
ret uintptr
|
|
||||||
err error
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -49,34 +47,20 @@ 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)
|
||||||
}
|
}
|
||||||
|
|
||||||
hwnd, err := makeMessageHandler()
|
uimsgwin, 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(hwnd),
|
uintptr(uimsgwin),
|
||||||
msgQuit,
|
msgQuit,
|
||||||
uintptr(0),
|
uintptr(0),
|
||||||
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 {
|
func messageHandlerWndProc(hwnd _HWND, uMsg uint32, wParam _WPARAM, lParam _LPARAM) _LRESULT {
|
||||||
switch uMsg {
|
switch uMsg {
|
||||||
case msgRequested:
|
case msgRequested:
|
||||||
mt := (*interface{})(unsafe.Pointer(lParam))
|
f := (*func())(unsafe.Pointer(lParam))
|
||||||
switch m := (*mt).(type) {
|
(*f)()
|
||||||
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
|
||||||
|
|
Loading…
Reference in New Issue