summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPietro Gagliardi <[email protected]>2014-06-30 20:55:42 -0400
committerPietro Gagliardi <[email protected]>2014-06-30 20:55:42 -0400
commit46ba0049cb80d8b6973c3146b40ceceaead710ed (patch)
tree425bb58415d1d06c15c3b23f592ed686b8c536a2
parent496df12751b029caa7dbbb9480c1a81f242f1c6d (diff)
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...
-rw-r--r--dialog_windows.go4
-rw-r--r--sysdata_windows.go195
-rw-r--r--uitask_windows.go49
3 files changed, 81 insertions, 167 deletions
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