diff --git a/redo/area_windows.c b/redo/area_windows.c index f309049..bb988b3 100644 --- a/redo/area_windows.c +++ b/redo/area_windows.c @@ -5,8 +5,6 @@ #include "winapi_windows.h" #include "_cgo_export.h" -#define areaWindowClass L"gouiarea" - static void getScrollPos(HWND hwnd, int *xpos, int *ypos) { SCROLLINFO si; @@ -412,6 +410,8 @@ static LRESULT CALLBACK areaWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM case msgAreaRepaintAll: repaintArea(hwnd); return 0; + case msgAreaDefocuses: + return (LRESULT) areaDefocuses(data); default: return DefWindowProcW(hwnd, uMsg, wParam, lParam); } @@ -445,7 +445,7 @@ HWND newArea(void *data) hwnd = CreateWindowExW( 0, areaWindowClass, L"", - WS_HSCROLL | WS_VSCROLL | WS_CHILD | WS_VISIBLE, + WS_HSCROLL | WS_VSCROLL | WS_CHILD | WS_VISIBLE | WS_TABSTOP, CW_USEDEFAULT, CW_USEDEFAULT, 100, 100, msgwin, NULL, hInstance, data); diff --git a/redo/area_windows.go b/redo/area_windows.go index 05f0274..de03d10 100644 --- a/redo/area_windows.go +++ b/redo/area_windows.go @@ -280,6 +280,15 @@ func areaResetClickCounter(data unsafe.Pointer) { a.clickCounter.reset() } +//export areaDefocuses +func areaDefocuses(data unsafe.Pointer) C.BOOL { + a := (*area)(data) + if a.handler.Defocuses() { + return C.TRUE + } + return C.FALSE +} + func (a *area) hwnd() C.HWND { return a._hwnd } diff --git a/redo/uitask_windows.c b/redo/uitask_windows.c index 5d5f503..5a64096 100644 --- a/redo/uitask_windows.c +++ b/redo/uitask_windows.c @@ -3,11 +3,16 @@ #include "winapi_windows.h" #include "_cgo_export.h" +/* note that this includes the terminating '\0' */ +#define NAREACLASS (sizeof areaWindowClass / sizeof areaWindowClass[0]) + void uimsgloop(void) { MSG msg; int res; HWND active; + WCHAR classchk[NAREACLASS]; + BOOL dodlgmessage; for (;;) { SetLastError(0); @@ -17,9 +22,24 @@ void uimsgloop(void) if (res == 0) /* WM_QUIT */ break; active = GetActiveWindow(); - // TODO this interferes with Area - if (active != NULL && IsDialogMessageW(active, &msg) != 0) - continue; + if (active != NULL) { + HWND focus; + + dodlgmessage = TRUE; + focus = GetFocus(); + if (focus != NULL) { + // theoretically we could use the class atom to avoid a wcscmp() + // however, raymond chen advises against this - TODO_get_URL + // while I have no idea what could deregister *my* window class from under *me*, better safe than sorry + // we could also theoretically just send msgAreaDefocuses directly, but what DefWindowProc() does to a WM_APP message is undocumented + if (GetClassNameW(focus, classchk, NAREACLASS) == 0) + xpanic("error getting name of focused window class for Area check", GetLastError()); + if (wcscmp(classchk, areaWindowClass) == 0) + dodlgmessage = (BOOL) SendMessageW(focus, msgAreaDefocuses, 0, 0); + } + if (dodlgmessage && IsDialogMessageW(active, &msg) != 0) + continue; + } TranslateMessage(&msg); DispatchMessageW(&msg); } diff --git a/redo/winapi_windows.h b/redo/winapi_windows.h index ca27367..f9e9a9b 100644 --- a/redo/winapi_windows.h +++ b/redo/winapi_windows.h @@ -29,6 +29,7 @@ enum { msgNOTIFY, /* WM_NOTIFY proxy */ msgAreaSizeChanged, msgAreaRepaintAll, + msgAreaDefocuses, }; /* uitask_windows.c */ @@ -104,6 +105,7 @@ extern HWND newContainer(void *); extern void calculateBaseUnits(HWND, int *, int *, LONG *); /* area_window.c */ +#define areaWindowClass L"gouiarea" extern void repaintArea(HWND); extern DWORD makeAreaWindowClass(char **); extern HWND newArea(void *); diff --git a/redo/zz_test.go b/redo/zz_test.go index 46f00e2..edc0e1e 100644 --- a/redo/zz_test.go +++ b/redo/zz_test.go @@ -137,6 +137,7 @@ func (tw *testwin) make(done chan struct{}) { tw.t.Append("Password Field", tw.e2) tw.w.Show() if *smallWindow { + // TODO windows - tab order wrong in wine? tw.wsmall = NewWindow("Small", 80, 80, NewVerticalStack( NewButton("Small"),