From af2e8c4b1315ece9737cb206b2f158f2759e53e9 Mon Sep 17 00:00:00 2001 From: Pietro Gagliardi Date: Thu, 12 Jun 2014 11:46:51 -0400 Subject: [PATCH] Made sysdata_windows.go send func()s to uitask and not uimsgs. This is also more correct, as multi-step processes happen in one homogenous blob instead of in steps spread across two goroutines. --- sysdata_windows.go | 646 +++++++++++++++++++-------------------------- 1 file changed, 275 insertions(+), 371 deletions(-) diff --git a/sysdata_windows.go b/sysdata_windows.go index 99dbad8..317840a 100644 --- a/sysdata_windows.go +++ b/sysdata_windows.go @@ -144,26 +144,25 @@ var ( ) func (s *sysData) make(window *sysData) (err error) { - ret := make(chan uiret) + ret := make(chan struct{}) defer close(ret) - ct := classTypes[s.ctype] - cid := _HMENU(0) - pwin := uintptr(_NULL) - if window != nil { // this is a child control - cid = window.addChild(s) - pwin = uintptr(window.hwnd) - } - style := uintptr(ct.style) - if s.alternate { - style = uintptr(ct.altStyle) - } - lpParam := uintptr(_NULL) - if ct.storeSysData { - lpParam = uintptr(unsafe.Pointer(s)) - } - uitask <- &uimsg{ - call: _createWindowEx, - p: []uintptr{ + uitask <- func() { + ct := classTypes[s.ctype] + cid := _HMENU(0) + pwin := uintptr(_NULL) + if window != nil { // this is a child control + cid = window.addChild(s) + pwin = uintptr(window.hwnd) + } + style := uintptr(ct.style) + if s.alternate { + style = uintptr(ct.altStyle) + } + lpParam := uintptr(_NULL) + if ct.storeSysData { + lpParam = uintptr(unsafe.Pointer(s)) + } + r1, _, err := _createWindowEx.Call( uintptr(ct.xstyle), utf16ToArg(ct.name), blankString, // we set the window text later @@ -175,35 +174,28 @@ func (s *sysData) make(window *sysData) (err error) { pwin, uintptr(cid), uintptr(hInstance), - lpParam, - }, - ret: ret, - } - r := <-ret - if r.ret == 0 { // failure - if window != nil { - window.delChild(cid) + lpParam) + if r1 == 0 { // failure + if window != nil { + window.delChild(cid) + } + panic(fmt.Errorf("error actually creating window/control: %v", err)) } - return fmt.Errorf("error actually creating window/control: %v", r.err) - } - if !ct.storeSysData { // regular control; store s.hwnd ourselves - s.hwnd = _HWND(r.ret) - } else if s.hwnd != _HWND(r.ret) { // we store sysData in storeSysData(); sanity check - panic(fmt.Errorf("hwnd mismatch creating window/control: storeSysData() stored 0x%X but CreateWindowEx() returned 0x%X", s.hwnd, ret)) - } - if !ct.doNotLoadFont { - uitask <- &uimsg{ - call: _sendMessage, - p: []uintptr{ + if !ct.storeSysData { // regular control; store s.hwnd ourselves + s.hwnd = _HWND(r1) + } else if s.hwnd != _HWND(r1) { // we store sysData in storeSysData(); sanity check + panic(fmt.Errorf("hwnd mismatch creating window/control: storeSysData() stored 0x%X but CreateWindowEx() returned 0x%X", s.hwnd, r1)) + } + if !ct.doNotLoadFont { + _sendMessage.Call( uintptr(s.hwnd), uintptr(_WM_SETFONT), uintptr(_WPARAM(controlFont)), - uintptr(_LPARAM(_TRUE)), - }, - ret: ret, + uintptr(_LPARAM(_TRUE))) } - <-ret + ret <- struct{}{} } + <-ret return nil } @@ -215,75 +207,63 @@ var ( // ShowWindow(hwnd, nCmdShow); // UpdateWindow(hwnd); func (s *sysData) firstShow() error { - ret := make(chan uiret) + ret := make(chan struct{}) defer close(ret) - uitask <- &uimsg{ - call: _showWindow, - p: []uintptr{ + uitask <- func() { + _showWindow.Call( uintptr(s.hwnd), - uintptr(nCmdShow), - }, - ret: ret, + uintptr(nCmdShow)) + r1, _, err := _updateWindow.Call(uintptr(s.hwnd)) + if r1 == 0 { // failure + panic(fmt.Errorf("error updating window for the first time: %v", err)) + } + ret <- struct{}{} } <-ret - uitask <- &uimsg{ - call: _updateWindow, - p: []uintptr{uintptr(s.hwnd)}, - ret: ret, - } - r := <-ret - if r.ret == 0 { // failure - return fmt.Errorf("error updating window for the first time: %v", r.err) - } return nil } func (s *sysData) show() { - ret := make(chan uiret) + ret := make(chan struct{}) defer close(ret) - uitask <- &uimsg{ - call: _showWindow, - p: []uintptr{ + uitask <- func() { + _showWindow.Call( uintptr(s.hwnd), - uintptr(_SW_SHOW), - }, - ret: ret, + uintptr(_SW_SHOW)) + ret <- struct{}{} } <-ret } func (s *sysData) hide() { - ret := make(chan uiret) + ret := make(chan struct{}) defer close(ret) - uitask <- &uimsg{ - call: _showWindow, - p: []uintptr{ + uitask <- func() { + _showWindow.Call( uintptr(s.hwnd), - uintptr(_SW_HIDE), - }, - ret: ret, + uintptr(_SW_HIDE)) + ret <- struct{}{} } <-ret } func (s *sysData) setText(text string) { - ptext := toUTF16(text) - ret := make(chan uiret) + ret := make(chan struct{}) defer close(ret) - uitask <- &uimsg{ - call: _setWindowText, - p: []uintptr{ + uitask <- func() { + ptext := toUTF16(text) + r1, _, err := _setWindowText.Call( uintptr(s.hwnd), - utf16ToArg(ptext), - }, - ret: ret, - } - r := <-ret - if r.ret == 0 { // failure - panic(fmt.Errorf("error setting window/control text: %v", r.err)) + utf16ToArg(ptext)) + if r1 == 0 { // failure + panic(fmt.Errorf("error setting window/control text: %v", err)) + } + ret <- struct{}{} } + <-ret } +// runs on uitask func (s *sysData) setRect(x int, y int, width int, height int, winheight int) error { r1, _, err := _moveWindow.Call( uintptr(s.hwnd), @@ -299,277 +279,238 @@ func (s *sysData) setRect(x int, y int, width int, height int, winheight int) er } func (s *sysData) isChecked() bool { - ret := make(chan uiret) + ret := make(chan bool) defer close(ret) - uitask <- &uimsg{ - call: _sendMessage, - p: []uintptr{ + uitask <- func() { + r1, _, _ := _sendMessage.Call( uintptr(s.hwnd), uintptr(_BM_GETCHECK), uintptr(0), - uintptr(0), - }, - ret: ret, + uintptr(0)) + ret <- r1 == _BST_CHECKED } - r := <-ret - return r.ret == _BST_CHECKED + return <-ret } func (s *sysData) text() (str string) { - var tc []uint16 - - ret := make(chan uiret) + ret := make(chan string) defer close(ret) - uitask <- &uimsg{ - call: _sendMessage, - p: []uintptr{ + uitask <- func() { + var tc []uint16 + + r1, _, _ := _sendMessage.Call( uintptr(s.hwnd), uintptr(_WM_GETTEXTLENGTH), uintptr(0), - uintptr(0), - }, - ret: ret, - } - r := <-ret - length := r.ret + 1 // terminating null - tc = make([]uint16, length) - uitask <- &uimsg{ - call: _sendMessage, - p: []uintptr{ + uintptr(0)) + length := r1 + 1 // terminating null + tc = make([]uint16, length) + _sendMessage.Call( uintptr(s.hwnd), uintptr(_WM_GETTEXT), uintptr(_WPARAM(length)), - uintptr(_LPARAM(unsafe.Pointer(&tc[0]))), - }, - ret: ret, + uintptr(_LPARAM(unsafe.Pointer(&tc[0])))) + ret <- syscall.UTF16ToString(tc) } - <-ret - return syscall.UTF16ToString(tc) + return <-ret } func (s *sysData) append(what string) { - pwhat := toUTF16(what) - ret := make(chan uiret) + ret := make(chan struct{}) defer close(ret) - uitask <- &uimsg{ - call: _sendMessage, - p: []uintptr{ + uitask <- func() { + pwhat := toUTF16(what) + r1, _, err := _sendMessage.Call( uintptr(s.hwnd), uintptr(classTypes[s.ctype].appendMsg), uintptr(_WPARAM(0)), - utf16ToLPARAM(pwhat), - }, - ret: ret, - } - r := <-ret - if r.ret == uintptr(classTypes[s.ctype].addSpaceErr) { - panic(fmt.Errorf("out of space adding item to combobox/listbox (last error: %v)", r.err)) - } else if r.ret == uintptr(classTypes[s.ctype].selectedIndexErr) { - panic(fmt.Errorf("failed to add item to combobox/listbox (last error: %v)", r.err)) + utf16ToLPARAM(pwhat)) + if r1 == uintptr(classTypes[s.ctype].addSpaceErr) { + panic(fmt.Errorf("out of space adding item to combobox/listbox (last error: %v)", err)) + } 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) { - pwhat := toUTF16(what) - ret := make(chan uiret) + ret := make(chan struct{}) defer close(ret) - uitask <- &uimsg{ - call: _sendMessage, - p: []uintptr{ + uitask <- func() { + pwhat := toUTF16(what) + r1, _, err := _sendMessage.Call( uintptr(s.hwnd), uintptr(classTypes[s.ctype].insertBeforeMsg), uintptr(_WPARAM(index)), - utf16ToLPARAM(pwhat), - }, - ret: ret, + utf16ToLPARAM(pwhat)) + if r1 == uintptr(classTypes[s.ctype].addSpaceErr) { + panic(fmt.Errorf("out of space adding item to combobox/listbox (last error: %v)", err)) + } else if r1 == uintptr(classTypes[s.ctype].selectedIndexErr) { + panic(fmt.Errorf("failed to add item to combobox/listbox (last error: %v)", err)) + } + ret <- struct{}{} } - r := <-ret - if r.ret == uintptr(classTypes[s.ctype].addSpaceErr) { - panic(fmt.Errorf("out of space adding item to combobox/listbox (last error: %v)", r.err)) - } else if r.ret == uintptr(classTypes[s.ctype].selectedIndexErr) { - panic(fmt.Errorf("failed to add item to combobox/listbox (last error: %v)", r.err)) + <-ret +} + +// runs on uitask +func (s *sysData) doSelectedIndex() int { + r1, _, _ := _sendMessage.Call( + uintptr(s.hwnd), + uintptr(classTypes[s.ctype].selectedIndexMsg), + uintptr(_WPARAM(0)), + uintptr(_LPARAM(0))) + if r1 == uintptr(classTypes[s.ctype].selectedIndexErr) { // no selection or manually entered text (apparently, for the latter) + return -1 } + return int(r1) } func (s *sysData) selectedIndex() int { - ret := make(chan uiret) + ret := make(chan int) defer close(ret) - uitask <- &uimsg{ - call: _sendMessage, - p: []uintptr{ - uintptr(s.hwnd), - uintptr(classTypes[s.ctype].selectedIndexMsg), - uintptr(_WPARAM(0)), - uintptr(_LPARAM(0)), - }, - ret: ret, + uitask <- func() { + ret <- s.doSelectedIndex() } - r := <-ret - if r.ret == uintptr(classTypes[s.ctype].selectedIndexErr) { // no selection or manually entered text (apparently, for the latter) - return -1 - } - return int(r.ret) + return <-ret } -func (s *sysData) selectedIndices() []int { +// runs on uitask +func (s *sysData) doSelectedIndices() []int { if !s.alternate { // single-selection list box; use single-selection method - index := s.selectedIndex() + index := s.doSelectedIndex() if index == -1 { return nil } return []int{index} } - ret := make(chan uiret) - defer close(ret) - uitask <- &uimsg{ - call: _sendMessage, - p: []uintptr{ - uintptr(s.hwnd), - uintptr(_LB_GETSELCOUNT), - uintptr(0), - uintptr(0), - }, - ret: ret, + r1, _, err := _sendMessage.Call( + uintptr(s.hwnd), + uintptr(_LB_GETSELCOUNT), + uintptr(0), + uintptr(0)) + if r1 == negConst(_LB_ERR) { + panic(fmt.Errorf("error: LB_ERR from LB_GETSELCOUNT in what we know is a multi-selection listbox: %v", err)) } - r := <-ret - if r.ret == negConst(_LB_ERR) { - panic("UI library internal error: LB_ERR from LB_GETSELCOUNT in what we know is a multi-selection listbox") - } - if r.ret == 0 { // nothing selected + if r1 == 0 { // nothing selected return nil } - indices := make([]int, r.ret) - uitask <- &uimsg{ - call: _sendMessage, - p: []uintptr{ - uintptr(s.hwnd), - uintptr(_LB_GETSELITEMS), - uintptr(_WPARAM(r.ret)), - uintptr(_LPARAM(unsafe.Pointer(&indices[0]))), - }, - ret: ret, - } - r = <-ret - if r.ret == negConst(_LB_ERR) { - panic("UI library internal error: LB_ERR from LB_GETSELITEMS in what we know is a multi-selection listbox") + indices := make([]int, r1) + r1, _, err = _sendMessage.Call( + uintptr(s.hwnd), + uintptr(_LB_GETSELITEMS), + uintptr(_WPARAM(r1)), + uintptr(_LPARAM(unsafe.Pointer(&indices[0])))) + if r1 == negConst(_LB_ERR) { + panic(fmt.Errorf("error: LB_ERR from LB_GETSELITEMS in what we know is a multi-selection listbox: %v", err)) } return indices } -func (s *sysData) selectedTexts() []string { - indices := s.selectedIndices() - ret := make(chan uiret) +func (s *sysData) selectedIndices() []int { + ret := make(chan []int) defer close(ret) - strings := make([]string, len(indices)) - for i, v := range indices { - uitask <- &uimsg{ - call: _sendMessage, - p: []uintptr{ + uitask <- func() { + ret <- s.doSelectedIndices() + } + return <-ret +} + +func (s *sysData) selectedTexts() []string { + ret := make(chan []string) + defer close(ret) + uitask <- func() { + indices := s.doSelectedIndices() + strings := make([]string, len(indices)) + for i, v := range indices { + r1, _, err := _sendMessage.Call( uintptr(s.hwnd), uintptr(_LB_GETTEXTLEN), uintptr(_WPARAM(v)), - uintptr(0), - }, - ret: ret, - } - r := <-ret - if r.ret == negConst(_LB_ERR) { - panic("UI library internal error: LB_ERR from LB_GETTEXTLEN in what we know is a valid listbox index (came from LB_GETSELITEMS)") - } - str := make([]uint16, r.ret) - uitask <- &uimsg{ - call: _sendMessage, - p: []uintptr{ + uintptr(0)) + if r1 == negConst(_LB_ERR) { + panic(fmt.Errorf("error: LB_ERR from LB_GETTEXTLEN in what we know is a valid listbox index (came from LB_GETSELITEMS): %v", err)) + } + str := make([]uint16, r1) + r1, _, err = _sendMessage.Call( uintptr(s.hwnd), uintptr(_LB_GETTEXT), uintptr(_WPARAM(v)), - uintptr(_LPARAM(unsafe.Pointer(&str[0]))), - }, - ret: ret, + uintptr(_LPARAM(unsafe.Pointer(&str[0])))) + if r1 == negConst(_LB_ERR) { + panic(fmt.Errorf("error: LB_ERR from LB_GETTEXT in what we know is a valid listbox index (came from LB_GETSELITEMS): %v", err)) + } + strings[i] = syscall.UTF16ToString(str) } - r = <-ret - if r.ret == negConst(_LB_ERR) { - panic("UI library internal error: LB_ERR from LB_GETTEXT in what we know is a valid listbox index (came from LB_GETSELITEMS)") - } - strings[i] = syscall.UTF16ToString(str) + ret <- strings } - return strings + return <-ret } func (s *sysData) setWindowSize(width int, height int) error { - var rect _RECT - - ret := make(chan uiret) + ret := make(chan struct{}) defer close(ret) - uitask <- &uimsg{ - call: _getClientRect, - p: []uintptr{ + uitask <- func() { + var rect _RECT + + r1, _, err := _getClientRect.Call( uintptr(s.hwnd), - uintptr(unsafe.Pointer(&rect)), - }, - ret: ret, - } - r := <-ret - if r.ret == 0 { - return fmt.Errorf("error getting upper-left of window for resize: %v", r.err) - } - // 0 because (0,0) is top-left so no winheight - // TODO this needs to be run on uitask! - err := s.setRect(int(rect.left), int(rect.top), width, height, 0) - if err != nil { - return fmt.Errorf("error actually resizing window: %v", err) + uintptr(unsafe.Pointer(&rect))) + if r1 == 0 { + panic(fmt.Errorf("error getting upper-left of window for resize: %v", err)) + } + // TODO AdjustWindowRect() on the result + // 0 because (0,0) is top-left so no winheight + err = s.setRect(int(rect.left), int(rect.top), width, height, 0) + 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 uiret) + ret := make(chan struct{}) defer close(ret) - uitask <- &uimsg{ - call: _sendMessage, - p: []uintptr{ + uitask <- func() { + r1, _, err := _sendMessage.Call( uintptr(s.hwnd), uintptr(classTypes[s.ctype].deleteMsg), uintptr(_WPARAM(index)), - uintptr(0), - }, - ret: ret, - } - r := <-ret - if r.ret == uintptr(classTypes[s.ctype].selectedIndexErr) { - panic(fmt.Errorf("failed to delete item from combobox/listbox (last error: %v)", r.err)) + uintptr(0)) + 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 uiret) + ret := make(chan struct{}) defer close(ret) - uitask <- &uimsg{ - call: _setWindowLongPtr, - p: []uintptr{ + uitask <- func() { + r1, _, err := _setWindowLongPtr.Call( uintptr(s.hwnd), negConst(_GWL_STYLE), - uintptr(classTypes[s.ctype].style | _PBS_MARQUEE), - }, - ret: ret, - } - r := <-ret - if r.ret == 0 { - panic(fmt.Errorf("error setting progress bar style to enter indeterminate mode: %v", r.err)) - } - uitask <- &uimsg{ - call: _sendMessage, - p: []uintptr{ + uintptr(classTypes[s.ctype].style | _PBS_MARQUEE)) + if r1 == 0 { + panic(fmt.Errorf("error setting progress bar style to enter indeterminate mode: %v", err)) + } + _sendMessage.Call( uintptr(s.hwnd), uintptr(_PBM_SETMARQUEE), uintptr(_WPARAM(_TRUE)), - uintptr(0), - }, - ret: ret, + uintptr(0)) + s.isMarquee = true + ret <- struct{}{} } <-ret - s.isMarquee = true } func (s *sysData) setProgress(percent int) { @@ -577,153 +518,116 @@ func (s *sysData) setProgress(percent int) { s.setIndeterminate() return } - ret := make(chan uiret) + ret := make(chan struct{}) defer close(ret) - if s.isMarquee { - // turn off marquee before switching back - uitask <- &uimsg{ - call: _sendMessage, - p: []uintptr{ + uitask <- func() { + if s.isMarquee { + // turn off marquee before switching back + _sendMessage.Call( uintptr(s.hwnd), uintptr(_PBM_SETMARQUEE), uintptr(_WPARAM(_FALSE)), - uintptr(0), - }, - ret: ret, - } - <-ret - uitask <- &uimsg{ - call: _setWindowLongPtr, - p: []uintptr{ + uintptr(0)) + r1, _, err := _setWindowLongPtr.Call( uintptr(s.hwnd), negConst(_GWL_STYLE), - uintptr(classTypes[s.ctype].style), - }, - ret: ret, + uintptr(classTypes[s.ctype].style)) + if r1 == 0 { + panic(fmt.Errorf("error setting progress bar style to leave indeterminate mode (percent %d): %v", percent, err)) + } + s.isMarquee = false } - r := <-ret - if r.ret == 0 { - panic(fmt.Errorf("error setting progress bar style to leave indeterminate mode (percent %d): %v", percent, r.err)) - } - s.isMarquee = false - } - send := func(msg uintptr, n int, l _LPARAM) { - uitask <- &uimsg{ - call: _sendMessage, - p: []uintptr{ + send := func(msg uintptr, n int, l _LPARAM) { + _sendMessage.Call( uintptr(s.hwnd), msg, uintptr(_WPARAM(n)), - uintptr(l), - }, - ret: ret, + uintptr(l)) } - <-ret - } - // Windows 7 has a non-disableable slowly-animating progress bar increment - // there isn't one for decrement, so we'll work around by going one higher and then lower again - // for the case where percent == 100, we need to increase the range temporarily - // this kind of thing is why I want to move away from uimsg and toward having uitask take func()s like on the other platforms - // sources: http://social.msdn.microsoft.com/Forums/en-US/61350dc7-6584-4c4e-91b0-69d642c03dae/progressbar-disable-smooth-animation http://stackoverflow.com/questions/2217688/windows-7-aero-theme-progress-bar-bug http://discuss.joelonsoftware.com/default.asp?dotnet.12.600456.2 http://stackoverflow.com/questions/22469876/progressbar-lag-when-setting-position-with-pbm-setpos http://stackoverflow.com/questions/6128287/tprogressbar-never-fills-up-all-the-way-seems-to-be-updating-too-fast - if percent == 100 { - send(_PBM_SETRANGE32, 0, 101) - } - send(_PBM_SETPOS, percent+1, 0) - send(_PBM_SETPOS, percent, 0) - if percent == 100 { - send(_PBM_SETRANGE32, 0, 100) + // Windows 7 has a non-disableable slowly-animating progress bar increment + // there isn't one for decrement, so we'll work around by going one higher and then lower again + // for the case where percent == 100, we need to increase the range temporarily + // sources: http://social.msdn.microsoft.com/Forums/en-US/61350dc7-6584-4c4e-91b0-69d642c03dae/progressbar-disable-smooth-animation http://stackoverflow.com/questions/2217688/windows-7-aero-theme-progress-bar-bug http://discuss.joelonsoftware.com/default.asp?dotnet.12.600456.2 http://stackoverflow.com/questions/22469876/progressbar-lag-when-setting-position-with-pbm-setpos http://stackoverflow.com/questions/6128287/tprogressbar-never-fills-up-all-the-way-seems-to-be-updating-too-fast + if percent == 100 { + send(_PBM_SETRANGE32, 0, 101) + } + send(_PBM_SETPOS, percent+1, 0) + send(_PBM_SETPOS, percent, 0) + if percent == 100 { + send(_PBM_SETRANGE32, 0, 100) + } + ret <- struct{}{} } + <-ret } func (s *sysData) len() int { - ret := make(chan uiret) + ret := make(chan int) defer close(ret) - uitask <- &uimsg{ - call: _sendMessage, - p: []uintptr{ + uitask <- func() { + r1, _, err := _sendMessage.Call( uintptr(s.hwnd), uintptr(classTypes[s.ctype].lenMsg), uintptr(_WPARAM(0)), - uintptr(_LPARAM(0)), - }, - ret: ret, + uintptr(_LPARAM(0))) + if r1 == uintptr(classTypes[s.ctype].selectedIndexErr) { + panic(fmt.Errorf("unexpected error return from sysData.len(); GetLastError() says %v", err)) + } + ret <- int(r1) } - r := <-ret - if r.ret == uintptr(classTypes[s.ctype].selectedIndexErr) { - panic(fmt.Errorf("unexpected error return from sysData.len(); GetLastError() says %v", r.err)) - } - return int(r.ret) + return <-ret } func (s *sysData) setAreaSize(width int, height int) { - ret := make(chan uiret) + ret := make(chan struct{}) defer close(ret) - uitask <- &uimsg{ - call: _sendMessage, - p: []uintptr{ + 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: ret, + uintptr(height)) + ret <- struct{}{} } <-ret } func (s *sysData) repaintAll() { - ret := make(chan uiret) + ret := make(chan struct{}) defer close(ret) - uitask <- &uimsg{ - call: _sendMessage, - p: []uintptr{ + uitask <- func() { + _sendMessage.Call( uintptr(s.hwnd), uintptr(msgRepaintAll), uintptr(0), - uintptr(0), - }, - ret: ret, + uintptr(0)) + ret <- struct{}{} } <-ret } func (s *sysData) center() { - var ws _RECT - - ret := make(chan uiret) + ret := make(chan struct{}) defer close(ret) - uitask <- &uimsg{ - call: _getWindowRect, - p: []uintptr{ + uitask <- func() { + var ws _RECT + + r1, _, err := _getWindowRect.Call( uintptr(s.hwnd), - uintptr(unsafe.Pointer(&ws)), - }, - ret: ret, + uintptr(unsafe.Pointer(&ws))) + if r1 == 0 { + panic(fmt.Errorf("error getting window rect for sysData.center(): %v", err)) + } + // TODO should this be using the monitor functions instead? http://blogs.msdn.com/b/oldnewthing/archive/2005/05/05/414910.aspx + // error returns from GetSystemMetrics() is meaningless because the return value, 0, is still valid + dw, _, _ := _getSystemMetrics.Call(uintptr(_SM_CXFULLSCREEN)) + dh, _, _ := _getSystemMetrics.Call(uintptr(_SM_CYFULLSCREEN)) + ww := ws.right - ws.left + wh := ws.bottom - ws.top + 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{}{} } - r := <-ret - if r.ret == 0 { - panic(fmt.Errorf("error getting window rect for sysData.center(): %v", r.err)) - } - // TODO should this be using the monitor functions instead? http://blogs.msdn.com/b/oldnewthing/archive/2005/05/05/414910.aspx - // error returns from GetSystemMetrics() is meaningless because the return value, 0, is still valid - uitask <- &uimsg{ - call: _getSystemMetrics, - p: []uintptr{uintptr(_SM_CXFULLSCREEN)}, - ret: ret, - } - r = <-ret - dw := r.ret - uitask <- &uimsg{ - call: _getSystemMetrics, - p: []uintptr{uintptr(_SM_CYFULLSCREEN)}, - ret: ret, - } - r = <-ret - dh := r.ret - ww := ws.right - ws.left - wh := ws.bottom - ws.top - wx := (int32(dw) / 2) - (ww / 2) - wy := (int32(dh) / 2) - (wh / 2) - // TODO this needs to be run on uitask! - s.setRect(int(wx), int(wy), int(ww), int(wh), 0) + <-ret }