Fixed the infinite loop on Tab control dialog message bug(s) on the Windows backend.
This commit is contained in:
parent
2c8bb7bc6d
commit
acbe70b4e5
|
@ -14,6 +14,7 @@ import "C"
|
||||||
type container struct {
|
type container struct {
|
||||||
containerbase
|
containerbase
|
||||||
hwnd C.HWND
|
hwnd C.HWND
|
||||||
|
nchildren int
|
||||||
}
|
}
|
||||||
|
|
||||||
type sizing struct {
|
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))
|
panic(fmt.Errorf("inconsistency: hwnd returned by CreateWindowEx() (%p) and hwnd stored in container (%p) differ", hwnd, c.hwnd))
|
||||||
}
|
}
|
||||||
c.child = control
|
c.child = control
|
||||||
c.child.setParent(&controlParent{c.hwnd})
|
c.child.setParent(&controlParent{c})
|
||||||
return c
|
return c
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *container) setParent(p *controlParent) {
|
func (c *container) setParent(hwnd C.HWND) {
|
||||||
C.controlSetParent(c.hwnd, p.hwnd)
|
C.controlSetParent(c.hwnd, hwnd)
|
||||||
}
|
}
|
||||||
|
|
||||||
// this is needed because Windows won't move/resize a child window for us
|
// this is needed because Windows won't move/resize a child window for us
|
||||||
|
|
|
@ -11,11 +11,12 @@ type controlPrivate interface {
|
||||||
}
|
}
|
||||||
|
|
||||||
type controlParent struct {
|
type controlParent struct {
|
||||||
hwnd C.HWND
|
c *container
|
||||||
}
|
}
|
||||||
|
|
||||||
func basesetParent(c controlPrivate, p *controlParent) {
|
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
|
// don't specify basepreferredSize; it is custom on ALL controls
|
||||||
|
|
|
@ -57,7 +57,8 @@ func (l *label) settextlen(len C.LONG) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *label) setParent(p *controlParent) {
|
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 {
|
func (l *label) allocate(x int, y int, width int, height int, d *sizing) []*allocation {
|
||||||
|
|
|
@ -25,6 +25,8 @@ static LRESULT CALLBACK tabSubProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM l
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return (*fv_DefSubclassProc)(hwnd, uMsg, wParam, lParam);
|
return (*fv_DefSubclassProc)(hwnd, uMsg, wParam, lParam);
|
||||||
|
case msgTabCurrentTabHasChildren:
|
||||||
|
return (LRESULT) tabTabHasChildren((void *) data, SendMessageW(hwnd, TCM_GETCURSEL, 0, 0));
|
||||||
case WM_NCDESTROY:
|
case WM_NCDESTROY:
|
||||||
if ((*fv_RemoveWindowSubclass)(hwnd, tabSubProc, id) == FALSE)
|
if ((*fv_RemoveWindowSubclass)(hwnd, tabSubProc, id) == FALSE)
|
||||||
xpanic("error removing Tab subclass (which was for its own event handler)", GetLastError());
|
xpanic("error removing Tab subclass (which was for its own event handler)", GetLastError());
|
||||||
|
|
|
@ -34,7 +34,7 @@ func newTab() Tab {
|
||||||
|
|
||||||
func (t *tab) Append(name string, control Control) {
|
func (t *tab) Append(name string, control Control) {
|
||||||
c := newContainer(control)
|
c := newContainer(control)
|
||||||
c.setParent(&controlParent{t._hwnd})
|
c.setParent(t._hwnd)
|
||||||
t.tabs = append(t.tabs, c)
|
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
|
// 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 {
|
if len(t.tabs) != 1 {
|
||||||
|
@ -55,6 +55,15 @@ func tabChanged(data unsafe.Pointer, new C.LRESULT) {
|
||||||
t.tabs[int(new)].show()
|
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 {
|
func (t *tab) hwnd() C.HWND {
|
||||||
return t._hwnd
|
return t._hwnd
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,17 +41,19 @@ void uimsgloop(void)
|
||||||
if (wcscmp(classchk, areaWindowClass) == 0)
|
if (wcscmp(classchk, areaWindowClass) == 0)
|
||||||
dodlgmessage = FALSE;
|
dodlgmessage = FALSE;
|
||||||
else if (wcscmp(classchk, WC_TABCONTROL) == 0)
|
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)
|
if (dodlgmessage) {
|
||||||
tabEnterChildren(focus);
|
if (istab)
|
||||||
// TODO this goes into an infinite loop on a blank tab
|
tabEnterChildren(focus);
|
||||||
if (dodlgmessage)
|
|
||||||
idm = IsDialogMessageW(active, &msg);
|
idm = IsDialogMessageW(active, &msg);
|
||||||
if (istab)
|
if (istab)
|
||||||
tabLeaveChildren(focus);
|
tabLeaveChildren(focus);
|
||||||
if (idm != 0)
|
if (idm != 0)
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
TranslateMessage(&msg);
|
TranslateMessage(&msg);
|
||||||
DispatchMessageW(&msg);
|
DispatchMessageW(&msg);
|
||||||
|
|
|
@ -29,6 +29,7 @@ enum {
|
||||||
msgNOTIFY, // WM_NOTIFY proxy
|
msgNOTIFY, // WM_NOTIFY proxy
|
||||||
msgAreaSizeChanged,
|
msgAreaSizeChanged,
|
||||||
msgAreaRepaintAll,
|
msgAreaRepaintAll,
|
||||||
|
msgTabCurrentTabHasChildren,
|
||||||
};
|
};
|
||||||
|
|
||||||
// uitask_windows.c
|
// uitask_windows.c
|
||||||
|
|
|
@ -44,7 +44,7 @@ func newWindow(title string, width int, height int, control Control) *window {
|
||||||
if hresult != C.S_OK {
|
if hresult != C.S_OK {
|
||||||
panic(fmt.Errorf("error setting tab background texture on Window; HRESULT: 0x%X", hresult))
|
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
|
return w
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue