diff options
| author | Pietro Gagliardi <[email protected]> | 2014-08-14 13:05:31 -0400 |
|---|---|---|
| committer | Pietro Gagliardi <[email protected]> | 2014-08-14 13:05:31 -0400 |
| commit | acbe70b4e5688df23e04ac0e55d8515252a52275 (patch) | |
| tree | 4ad3a6cd2cb7e909dbd6437ffa6b852b09f1561b | |
| parent | 2c8bb7bc6d3b5614d53de957b4dca025c53a9cee (diff) | |
Fixed the infinite loop on Tab control dialog message bug(s) on the Windows backend.
| -rw-r--r-- | redo/container_windows.go | 7 | ||||
| -rw-r--r-- | redo/control_windows.go | 5 | ||||
| -rw-r--r-- | redo/label_windows.go | 3 | ||||
| -rw-r--r-- | redo/tab_windows.c | 2 | ||||
| -rw-r--r-- | redo/tab_windows.go | 11 | ||||
| -rw-r--r-- | redo/uitask_windows.c | 20 | ||||
| -rw-r--r-- | redo/winapi_windows.h | 1 | ||||
| -rw-r--r-- | redo/window_windows.go | 2 |
8 files changed, 34 insertions, 17 deletions
diff --git a/redo/container_windows.go b/redo/container_windows.go index 5cd1877..c782c38 100644 --- a/redo/container_windows.go +++ b/redo/container_windows.go @@ -14,6 +14,7 @@ import "C" type container struct { containerbase hwnd C.HWND + nchildren int } type sizing struct { @@ -45,12 +46,12 @@ func newContainer(control Control) *container { panic(fmt.Errorf("inconsistency: hwnd returned by CreateWindowEx() (%p) and hwnd stored in container (%p) differ", hwnd, c.hwnd)) } c.child = control - c.child.setParent(&controlParent{c.hwnd}) + c.child.setParent(&controlParent{c}) return c } -func (c *container) setParent(p *controlParent) { - C.controlSetParent(c.hwnd, p.hwnd) +func (c *container) setParent(hwnd C.HWND) { + C.controlSetParent(c.hwnd, hwnd) } // this is needed because Windows won't move/resize a child window for us diff --git a/redo/control_windows.go b/redo/control_windows.go index 49ac644..564d8d4 100644 --- a/redo/control_windows.go +++ b/redo/control_windows.go @@ -11,11 +11,12 @@ type controlPrivate interface { } type controlParent struct { - hwnd C.HWND + c *container } func basesetParent(c controlPrivate, p *controlParent) { - C.controlSetParent(c.hwnd(), p.hwnd) + C.controlSetParent(c.hwnd(), p.c.hwnd) + p.c.nchildren++ } // don't specify basepreferredSize; it is custom on ALL controls diff --git a/redo/label_windows.go b/redo/label_windows.go index d87f02e..a37bc9d 100644 --- a/redo/label_windows.go +++ b/redo/label_windows.go @@ -57,7 +57,8 @@ func (l *label) settextlen(len C.LONG) { } func (l *label) setParent(p *controlParent) { - basesetParent(l, p) + C.controlSetParent(l.hwnd(), p.c.hwnd) + // don't increment p.c.nchildren here because Labels aren't tab stops } func (l *label) allocate(x int, y int, width int, height int, d *sizing) []*allocation { diff --git a/redo/tab_windows.c b/redo/tab_windows.c index 4958a68..9a9908a 100644 --- a/redo/tab_windows.c +++ b/redo/tab_windows.c @@ -25,6 +25,8 @@ static LRESULT CALLBACK tabSubProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM l return 0; } return (*fv_DefSubclassProc)(hwnd, uMsg, wParam, lParam); + case msgTabCurrentTabHasChildren: + return (LRESULT) tabTabHasChildren((void *) data, SendMessageW(hwnd, TCM_GETCURSEL, 0, 0)); case WM_NCDESTROY: if ((*fv_RemoveWindowSubclass)(hwnd, tabSubProc, id) == FALSE) xpanic("error removing Tab subclass (which was for its own event handler)", GetLastError()); diff --git a/redo/tab_windows.go b/redo/tab_windows.go index 1d22887..371d7bc 100644 --- a/redo/tab_windows.go +++ b/redo/tab_windows.go @@ -34,7 +34,7 @@ func newTab() Tab { func (t *tab) Append(name string, control Control) { c := newContainer(control) - c.setParent(&controlParent{t._hwnd}) + c.setParent(t._hwnd) t.tabs = append(t.tabs, c) // initially hide tab 1..n controls; if we don't, they'll appear over other tabs, resulting in weird behavior if len(t.tabs) != 1 { @@ -55,6 +55,15 @@ func tabChanged(data unsafe.Pointer, new C.LRESULT) { t.tabs[int(new)].show() } +//export tabTabHasChildren +func tabTabHasChildren(data unsafe.Pointer, which C.LRESULT) C.BOOL { + t := (*tab)(data) + if t.tabs[int(which)].nchildren > 0 { + return C.TRUE + } + return C.FALSE +} + func (t *tab) hwnd() C.HWND { return t._hwnd } diff --git a/redo/uitask_windows.c b/redo/uitask_windows.c index 3101452..9ba418e 100644 --- a/redo/uitask_windows.c +++ b/redo/uitask_windows.c @@ -41,17 +41,19 @@ void uimsgloop(void) if (wcscmp(classchk, areaWindowClass) == 0) dodlgmessage = FALSE; else if (wcscmp(classchk, WC_TABCONTROL) == 0) - istab = TRUE; + // THIS BIT IS IMPORTANT + // if the current tab has no children, then there will be no children left in the dialog to tab to, and IsDialogMessageW() will loop forever + istab = (BOOL) SendMessageW(focus, msgTabCurrentTabHasChildren, 0, 0); } - if (istab) - tabEnterChildren(focus); - // TODO this goes into an infinite loop on a blank tab - if (dodlgmessage) + if (dodlgmessage) { + if (istab) + tabEnterChildren(focus); idm = IsDialogMessageW(active, &msg); - if (istab) - tabLeaveChildren(focus); - if (idm != 0) - continue; + if (istab) + tabLeaveChildren(focus); + if (idm != 0) + continue; + } } TranslateMessage(&msg); DispatchMessageW(&msg); diff --git a/redo/winapi_windows.h b/redo/winapi_windows.h index c063679..c5fd4c1 100644 --- a/redo/winapi_windows.h +++ b/redo/winapi_windows.h @@ -29,6 +29,7 @@ enum { msgNOTIFY, // WM_NOTIFY proxy msgAreaSizeChanged, msgAreaRepaintAll, + msgTabCurrentTabHasChildren, }; // uitask_windows.c diff --git a/redo/window_windows.go b/redo/window_windows.go index 3a551c2..60f89d1 100644 --- a/redo/window_windows.go +++ b/redo/window_windows.go @@ -44,7 +44,7 @@ func newWindow(title string, width int, height int, control Control) *window { if hresult != C.S_OK { panic(fmt.Errorf("error setting tab background texture on Window; HRESULT: 0x%X", hresult)) } - w.container.setParent(&controlParent{w.hwnd}) + w.container.setParent(w.hwnd) return w } |
