Added Post() and implemented it on Windows.

This commit is contained in:
Pietro Gagliardi 2014-07-03 11:04:07 -04:00
parent f7dedc8cb0
commit 1238936a16
6 changed files with 38 additions and 5 deletions

View File

@ -108,6 +108,10 @@ func stdWndProc(hwnd _HWND, uMsg uint32, wParam _WPARAM, lParam _LPARAM) _LRESUL
return storeSysData(hwnd, uMsg, wParam, lParam)
}
switch uMsg {
case msgPost:
data := (*interface{})(unsafe.Pointer(lParam))
s.post(*data)
return 0
case _WM_COMMAND:
id := _HMENU(wParam.LOWORD())
s.childrenLock.Lock()

View File

@ -9,8 +9,9 @@ type cSysData struct {
spaced bool
alternate bool // editable for Combobox, multi-select for listbox, password for lineedit
handler AreaHandler // for Areas; TODO rename to areahandler
close func() bool // provided by each Window
event func() // provided by each control
close func() bool // provided by each Window
post func(interface{}) // provided by each Window
event func() // provided by each control
}
// this interface is used to make sure all sysDatas are synced

View File

@ -249,12 +249,13 @@ func areaTest() {
layout.SetStretchy(0)
w := NewWindow("Area Test", 100, 100)
w.Closing = die
w.Posted = func(data interface{}) {
timedisp.SetText(data.(string))
}
w.Open(layout)
go func() {
for t := range timechan {
// TODO
_ = t
// timedisp.SetText(t.String())
Post(w, t.String())
}
}()
}

View File

@ -26,6 +26,14 @@ func Go(start func()) error {
return nil
}
// Post issues a request to the given Window to do something on the main thread.
// Note the name of the function: there is no guarantee that the request will be handled immediately.
// Because this can be safely called from any goroutine, it is a package-level function, and not a method on Window.
// TODO garbage collection
func Post(w *Window, data interface{}) {
uipost(w, data)
}
// TODO this needs to be replaced with a function
// Stop should be pulsed when you are ready for Go() to return.
// Pulsing Stop will cause Go() to return immediately; the programmer is responsible for cleaning up (for instance, hiding open Windows) beforehand.

View File

@ -29,6 +29,7 @@ const (
msgQuit = _WM_APP + iota + 1 // + 1 just to be safe
msgSetAreaSize
msgRepaintAll
msgPost
)
func uiinit() error {
@ -66,6 +67,15 @@ func ui() {
msgloop()
}
// we'll use SendMessage() here, which will do a thread switch, call the function immediately, and wait for it to return, so we don't have to worry about the garbage collector collecting data
func uipost(w *Window, data interface{}) {
_sendMessage.Call(
uintptr(w.sysData.hwnd), // note: we pass this directly to the window
msgPost,
0,
uintptr(unsafe.Pointer(&data)))
}
var (
_dispatchMessage = user32.NewProc("DispatchMessageW")
_getActiveWindow = user32.NewProc("GetActiveWindow")

View File

@ -15,6 +15,11 @@ type Window struct {
// If Closing is nil, a default which rejects the close will be used.
Closing func() bool
// Posted is called when Post() is called with the given Window as an argument.
// It receives the data passed to Post() as an argument.
// If Posted is nil, a default handler which does nothing will be used.
Posted func(data interface{})
created bool
sysData *sysData
initTitle string
@ -87,6 +92,10 @@ func (w *Window) Create(control Control) {
return false
}
}
w.sysData.post = w.Posted
if w.sysData.post == nil {
w.sysData.post = func(data interface{}) {}
}
err := w.sysData.make(nil)
if err != nil {
panic(fmt.Errorf("error opening window: %v", err))