Converted the Mac OS X backend to use uitask() instead of uitask chan func().

This commit is contained in:
Pietro Gagliardi 2014-06-30 21:21:55 -04:00
parent 46ba0049cb
commit e8a7dd0b87
4 changed files with 77 additions and 136 deletions

View File

@ -127,7 +127,7 @@ void douitask(id appDelegate, void *p)
fp = [NSValue valueWithPointer:p]; fp = [NSValue valueWithPointer:p];
[appDelegate performSelectorOnMainThread:@selector(uitask:) [appDelegate performSelectorOnMainThread:@selector(uitask:)
withObject:fp withObject:fp
waitUntilDone:YES]; // wait so we can properly drain the autorelease pool; on other platforms we wind up waiting anyway (since the main thread can only handle one thing at a time) so waitUntilDone:YES]; // wait since that's what we want the Go uitask() to do
[pool release]; [pool release];
} }

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

@ -225,20 +225,14 @@ func (s *sysData) make(window *sysData) error {
if window != nil { if window != nil {
parentWindow = window.id parentWindow = window.id
} }
ret := make(chan C.id) uitask(func() {
defer close(ret) s.id = ct.make(parentWindow, s.alternate, s)
uitask <- func() { if ct.getinside != nil {
ret <- ct.make(parentWindow, s.alternate, s) addSysData(ct.getinside(s.id), s)
} } else {
s.id = <-ret addSysData(s.id, s)
if ct.getinside != nil {
uitask <- func() {
ret <- ct.getinside(s.id)
} }
addSysData(<-ret, s) })
} else {
addSysData(s.id, s)
}
return nil return nil
} }
@ -249,33 +243,21 @@ func (s *sysData) firstShow() error {
} }
func (s *sysData) show() { func (s *sysData) show() {
ret := make(chan struct{}) uitask(func() {
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() {
ret := make(chan struct{}) uitask(func() {
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) {
ret := make(chan struct{}) uitask(func() {
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 {
@ -288,147 +270,111 @@ 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() {
ret <- C.isCheckboxChecked(s.id) != C.NO b = C.isCheckboxChecked(s.id) != C.NO
} })
return <-ret return b
} }
func (s *sysData) text() string { func (s *sysData) text() string {
ret := make(chan string) var text 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)
ret <- fromNSString(str) text = fromNSString(str)
} })
return <-ret return text
} }
func (s *sysData) append(what string) { func (s *sysData) append(what string) {
ret := make(chan struct{}) uitask(func() {
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) {
ret := make(chan struct{}) uitask(func() {
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 {
ret := make(chan int) var i int
defer close(ret)
uitask <- func() { uitask(func() {
ret <- classTypes[s.ctype].selIndex(s.id) i = classTypes[s.ctype].selIndex(s.id)
} })
return <-ret return i
} }
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 <- classTypes[s.ctype].selIndices(s.id) i = classTypes[s.ctype].selIndices(s.id)
} })
return <-ret return i
} }
func (s *sysData) selectedTexts() []string { func (s *sysData) selectedTexts() []string {
ret := make(chan []string) var texts []string
defer close(ret)
uitask <- func() { uitask(func() {
ret <- classTypes[s.ctype].selTexts(s.id) texts = classTypes[s.ctype].selTexts(s.id)
} })
return <-ret return texts
} }
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() {
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) {
ret := make(chan struct{}) uitask(func() {
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) {
ret := make(chan struct{}) uitask(func() {
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 {
ret := make(chan int) var i int
defer close(ret)
uitask <- func() { uitask(func() {
ret <- classTypes[s.ctype].len(s.id) i = classTypes[s.ctype].len(s.id)
} })
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() {
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() {
ret := make(chan struct{}) uitask(func() {
defer close(ret)
uitask <- func() {
C.display(s.id) C.display(s.id)
ret <- struct{}{} })
}
<-ret
} }
func (s *sysData) center() { func (s *sysData) center() {
ret := make(chan struct{}) uitask(func() {
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) {
ret := make(chan struct{}) uitask(func() {
defer close(ret)
uitask <- func() {
C.setCheckboxChecked(s.id, toBOOL(checked)) C.setCheckboxChecked(s.id, toBOOL(checked))
ret <- struct{}{} })
}
<-ret
} }

View File

@ -14,30 +14,25 @@ import (
// #include "objc_darwin.h" // #include "objc_darwin.h"
import "C" import "C"
var uitask chan func() // can be run from any thread
// 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()