From c457d9bf008793182167a1298ac7d93802de1b71 Mon Sep 17 00:00:00 2001 From: Pietro Gagliardi Date: Thu, 28 Apr 2016 16:59:26 -0400 Subject: [PATCH] Started a newer, better system for propagating layout changes. This relies on WM_GETMINMAXINFO, at least... --- ui_windows.h | 33 ++++++++++++++++++++++++--------- windows/area.cpp | 2 +- windows/areadraw.cpp | 2 +- windows/areaevents.cpp | 2 +- windows/areascroll.cpp | 4 ++-- windows/container.cpp | 2 +- windows/control.cpp | 9 +++++++-- windows/draw.cpp | 2 +- windows/fontdialog.cpp | 2 +- windows/parent.cpp | 4 ++-- windows/tab.cpp | 2 +- windows/tabpage.cpp | 2 +- windows/uipriv_windows.hpp | 2 -- windows/window.cpp | 6 +++--- windows/winpublic.cpp | 25 +++++++++++++++++++++++++ windows/winutil.cpp | 25 ------------------------- 16 files changed, 71 insertions(+), 53 deletions(-) diff --git a/ui_windows.h b/ui_windows.h index f848d940..0ea27aa9 100644 --- a/ui_windows.h +++ b/ui_windows.h @@ -22,7 +22,8 @@ struct uiWindowsControl { void (*SyncEnableState)(uiWindowsControl *, int); void (*SetParentHWND)(uiWindowsControl *, HWND); void (*MinimumSize)(uiWindowsControl *, intmax_t *, intmax_t *); - void (*ChildMinimumSizeChanged)(uiWIndowsControl *); + void (*MinimumSizeChanged)(uiWIndowsControl *); + void (*LayoutRect)(uiWindowsControl *c, RECT *r); void (*AssignControlIDZOrder)(uiWindowsControl *, LONG_PTR *, HWND *); }; #define uiWindowsControl(this) ((uiWindowsControl *) (this)) @@ -30,7 +31,8 @@ struct uiWindowsControl { _UI_EXTERN void uiWindowsControlSyncEnableState(uiWindowsControl *, int); _UI_EXTERN void uiWindowsControlSetParentHWND(uiWindowsControl *, HWND); _UI_EXTERN void uiWindowsControlMinimumSize(uiWindowsControl *, intmax_t *, intmax_t *); -_UI_EXTERN void uiWindowsControlChildMinimumSizeChanged(uiWindowsControl *); +_UI_EXTERN void uiWindowsControlMinimumSizeChanged(uiWindowsControl *); +_UI_EXTERN void uiWindowsControlLayoutRect(uiWindowsControl *, RECT *); _UI_EXTERN void uiWindowsControlAssignControlIDZOrder(uiWindowsControl *, LONG_PTR *, HWND *); // TODO document @@ -109,12 +111,20 @@ _UI_EXTERN void uiWindowsControlAssignControlIDZOrder(uiWindowsControl *, LONG_P uiWindowsEnsureSetParentHWND(type(c)->hwnd, parent); \ } // note that there is no uiWindowsControlDefaultMinimumSize(); you MUST define this yourself! -#define uiWindowsDefaultChildMinimumSizeChanged(type) \ - static void type ## ChildMinimumSizeChanged)(uiWIndowsControl *c) \ +#define uiWindowsControlDefaultMinimumSizeChanged(type) \ + static void type ## MinimumSizeChanged)(uiWIndowsControl *c) \ { \ - /* do nothing; default has no children */ \ + if (uiWindowsControlTooSmall(c)) \ + uiWindowsControlMinimumSizeChanged(uiWindowsControl(c->parent)); \ + /* otherwise do nothing; we have no children */ \ } -#define uiWindowsDefaultAssignControlIDZorder(type) \ +#define uiWindowsControlDefaultLayoutRect(type) \ + static void type ## LayoutRect(uiWindowsControl *c, RECT *r) \ + { \ + /* use the window rect as we include the non-client area in the sizes */ \ + uiWindowsEnsureGetWindowRect(type(c)->hwnd, r); \ + } +#define uiWindowsControlDefaultAssignControlIDZorder(type) \ static void type ## AssignControlIDZOrder)(uiWindowsControl *c, LONG_PTR *controlID, HWND *insertAfter) \ { \ uiWindowsEnsureAssignControlIDZOrder(c, controlID, insertAfter); \ @@ -133,8 +143,9 @@ _UI_EXTERN void uiWindowsControlAssignControlIDZOrder(uiWindowsControl *, LONG_P uiWindowsControlDefaultDisable(type) \ uiWindowsControlDefaultSyncEnableState(type) \ uiWindowsControlDefaultSetParentHWND(type) \ - uiWindowsDefaultChildMinimumSizeChanged(type) \ - uiWindowsDefaultAssignControlIDZorder(type) + uiWindowsControlDefaultMinimumSizeChanged(type) \ + uiWindowsControlDefaultLayoutRect(type) \ + uiWindowsControlDefaultAssignControlIDZorder(type) #define uiWindowsControlAllDefaults(type) \ uiWindowsControlDefaultDestroy(type) \ @@ -177,6 +188,10 @@ _UI_EXTERN void uiWindowsEnsureSetParentHWND(HWND hwnd, HWND parent); // TODO document _UI_EXTERN void uiWindowsEnsureAssignControlIDZOrder(HWND hwnd, LONG_PTR *controlID, HWND *insertAfter); +// TODO document +_UI_EXTERN void uiWindowsEnsureGetClientRect(HWND hwnd, RECT *r); +_UI_EXTERN void uiWindowsEnsureGetWindowRect(HWND hwnd, RECT *r); + // TODO document _UI_EXTERN char *uiWindowsWindowText(HWND hwnd); _UI_EXTERN void uiWindowsSetWindowText(HWND hwnd, const char *text); @@ -219,7 +234,7 @@ _UI_EXTERN void uiWindowsSizingStandardPadding(uiWindowsSizing *sizing, int *x, _UI_EXTERN HWND uiWindowsMakeContainer(void (*onResize)(void *data), void *data); // TODO document -_UI_EXTERN void uiWindowsControlNotifyMinimumSizeChanged(uiWindowsControl *); +_UI_EXTERN BOOL uiWindowsControlTooSmall(uiWindowsControl *c); // TODO document _UI_EXTERN void uiWindowsControlAssignSoleControlIDZOrder(uiWindowsControl *); diff --git a/windows/area.cpp b/windows/area.cpp index 38719519..68174d5b 100644 --- a/windows/area.cpp +++ b/windows/area.cpp @@ -36,7 +36,7 @@ static LRESULT CALLBACK areaWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM if (uMsg == WM_WINDOWPOSCHANGED) { if ((wp->flags & SWP_NOSIZE) != 0) return DefWindowProcW(hwnd, uMsg, wParam, lParam); - if (getClientRect(a->hwnd, &client) == 0) + if (uiWindowsEnsureGetClientRect(a->hwnd, &client) == 0) logLastError(L"error getting client rect of uiArea for WM_WINDOWPOSCHANGED handling"); areaDrawOnResize(a, &client); areaScrollOnResize(a, &client); diff --git a/windows/areadraw.cpp b/windows/areadraw.cpp index 29a6fde6..414d23a1 100644 --- a/windows/areadraw.cpp +++ b/windows/areadraw.cpp @@ -94,7 +94,7 @@ static void onWM_PRINTCLIENT(uiArea *a) { RECT client; - if (getClientRect(a->hwnd, &client) == 0) + if (uiWindowsEnsureGetClientRect(a->hwnd, &client) == 0) logLastError(L"error getting client rect"); //TODO doPaint(a, (HDC) wParam, &client); } diff --git a/windows/areaevents.cpp b/windows/areaevents.cpp index ea88e3cc..991a2c86 100644 --- a/windows/areaevents.cpp +++ b/windows/areaevents.cpp @@ -85,7 +85,7 @@ static void areaMouseEvent(uiArea *a, uintmax_t down, uintmax_t up, WPARAM wPar if (a->capturing) { clientpt.x = GET_X_LPARAM(lParam); clientpt.y = GET_Y_LPARAM(lParam); - if (getClientRect(a->hwnd, &client) == 0) + if (uiWindowsEnsureGetClientRect(a->hwnd, &client) == 0) logLastError(L"error getting uiAreaclient rect for mouse crossing on capture on drag"); inClient = PtInRect(&client, clientpt); if (inClient && !a->inside) { diff --git a/windows/areascroll.cpp b/windows/areascroll.cpp index da6f5aa5..48b2c29c 100644 --- a/windows/areascroll.cpp +++ b/windows/areascroll.cpp @@ -128,7 +128,7 @@ static void hscrollParams(uiArea *a, struct scrollParams *p) ZeroMemory(p, sizeof (struct scrollParams)); p->pos = &(a->hscrollpos); // TODO get rid of these and replace with points - if (getClientRect(a->hwnd, &r) == 0) + if (uiWindowsEnsureGetClientRect(a->hwnd, &r) == 0) logLastError(L"error getting area client rect"); p->pagesize = r.right - r.left; p->length = a->scrollWidth; @@ -174,7 +174,7 @@ static void vscrollParams(uiArea *a, struct scrollParams *p) ZeroMemory(p, sizeof (struct scrollParams)); p->pos = &(a->vscrollpos); - if (getClientRect(a->hwnd, &r) == 0) + if (uiWindowsEnsureGetClientRect(a->hwnd, &r) == 0) logLastError(L"error getting area client rect"); p->pagesize = r.bottom - r.top; p->length = a->scrollHeight; diff --git a/windows/container.cpp b/windows/container.cpp index 752bdd0d..1940c9e1 100644 --- a/windows/container.cpp +++ b/windows/container.cpp @@ -50,7 +50,7 @@ static LRESULT CALLBACK containerWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LP return 0; // tab controls use this to draw the background of the tab area case WM_PRINTCLIENT: - if (getClientRect(hwnd, &r) == 0) { + if (uiWindowsEnsureGetClientRect(hwnd, &r) == 0) { logLastError(L"error getting client rect"); // likewise break; diff --git a/windows/control.cpp b/windows/control.cpp index 96f09150..398c0b16 100644 --- a/windows/control.cpp +++ b/windows/control.cpp @@ -16,9 +16,14 @@ void uiWindowsControlMinimumSize(uiWindowsControl *c, intmax_t *width, intmax_t (*(c->MinimumSize))(c, widdth, height); } -void uiWindowsControlChildMinimumSizeChanged(uiWIndowsControl *c) +void uiWindowsControlMinimumSizeChanged(uiWIndowsControl *c) { - (*(c->ChildMinimumSizeChanged))(c); + (*(c->MinimumSizeChanged))(c); +} + +void uiWindowsControlLayoutRect(uiWindowsControl *c, RECT *r) +{ + (*(c->LayoutRect))(c, r); } void uiWindowsControlAssignControlIDZOrder(uiWindowsControl *c, LONG_PTR *controlID, HWND *insertAfter) diff --git a/windows/draw.cpp b/windows/draw.cpp index 0f5f2531..a16dbd93 100644 --- a/windows/draw.cpp +++ b/windows/draw.cpp @@ -51,7 +51,7 @@ ID2D1HwndRenderTarget *makeHWNDRenderTarget(HWND hwnd) if (ReleaseDC(hwnd, dc) == 0) logLastError(L"error releasing DC for finding DPI"); - if (getClientRect(hwnd, &r) == 0) + if (uiWindowsEnsureGetClientRect(hwnd, &r) == 0) logLastError(L"error getting current size of window"); ZeroMemory(&hprops, sizeof (D2D1_HWND_RENDER_TARGET_PROPERTIES)); diff --git a/windows/fontdialog.cpp b/windows/fontdialog.cpp index 7a140b9f..affeba97 100644 --- a/windows/fontdialog.cpp +++ b/windows/fontdialog.cpp @@ -495,7 +495,7 @@ static struct fontDialog *beginFontDialog(HWND hwnd, LPARAM lParam) samplePlacement = GetDlgItem(f->hwnd, rcFontSamplePlacement); if (samplePlacement == NULL) logLastError(L"error getting sample placement static control handle"); - if (getWindowRect(samplePlacement, &(f->sampleRect)) == 0) + if (uiWindowsEnsureGetWindowRect(samplePlacement, &(f->sampleRect)) == 0) logLastError(L"error getting sample placement"); mapWindowRect(NULL, f->hwnd, &(f->sampleRect)); uiWindowsEnsureDestroyWindow(samplePlacement); diff --git a/windows/parent.cpp b/windows/parent.cpp index 40db8edb..bff08f17 100644 --- a/windows/parent.cpp +++ b/windows/parent.cpp @@ -33,7 +33,7 @@ static HRESULT parentDraw(HDC dc, HWND parent, struct parentDraw *pd) { RECT r; - if (getClientRect(parent, &r) == 0) + if (uiWindowsEnsureGetClientRect(parent, &r) == 0) return logLastError(L"error getting parent's client rect"); pd->cdc = CreateCompatibleDC(dc); if (pd->cdc == NULL) @@ -86,7 +86,7 @@ static HBRUSH getControlBackgroundBrush(HWND hwnd, HDC dc) // now figure out where the control is relative to the parent so we can align the brush properly // if anything fails, give up and return the brush as-is - if (getWindowRect(hwnd, &hwndScreenRect) == 0) { + if (uiWindowsEnsureGetWindowRect(hwnd, &hwndScreenRect) == 0) { logLastError(L"error getting control window rect"); return brush; } diff --git a/windows/tab.cpp b/windows/tab.cpp index 152a4ea4..f5c6604e 100644 --- a/windows/tab.cpp +++ b/windows/tab.cpp @@ -32,7 +32,7 @@ static void tabPageRect(uiTab *t, RECT *r) // this rect needs to be in parent window coordinates, but TCM_ADJUSTRECT wants a window rect, which is screen coordinates // because we have each page as a sibling of the tab, use the tab's own rect as the input rect - getWindowRect(t->tabHWND, &r); + uiWindowsEnsureGetWindowRect(t->tabHWND, &r); SendMessageW(t->tabHWND, TCM_ADJUSTRECT, (WPARAM) FALSE, (LPARAM) (&r)); // and get it in terms of the container instead of the screen mapWindowRect(NULL, t->hwnd, &r); diff --git a/windows/tabpage.cpp b/windows/tabpage.cpp index 8b09b9b7..a996ac83 100644 --- a/windows/tabpage.cpp +++ b/windows/tabpage.cpp @@ -28,7 +28,7 @@ static void tabRelayout(struct tabPage *tp) if (tp->child == NULL) return; - getClientRect(tp->hwnd, &r); + uiWindowsEnsureGetClientRect(tp->hwnd, &r); tabPageMargins(tp, &mx, &my); r.left += mx; r.right += my; diff --git a/windows/uipriv_windows.hpp b/windows/uipriv_windows.hpp index a6df7c94..f927d87f 100644 --- a/windows/uipriv_windows.hpp +++ b/windows/uipriv_windows.hpp @@ -67,8 +67,6 @@ extern void clientSizeToWindowSize(HWND hwnd, intmax_t *width, intmax_t *height, extern HWND parentOf(HWND child); extern HWND parentToplevel(HWND child); extern void setWindowInsertAfter(HWND hwnd, HWND insertAfter); -extern void getClientRect(HWND, RECT *); -extern void getWindowRect(HWND, RECT *); // text.cpp extern WCHAR *windowTextAndLen(HWND hwnd, LRESULT *len); diff --git a/windows/window.cpp b/windows/window.cpp index 8292c9d6..b8e2d396 100644 --- a/windows/window.cpp +++ b/windows/window.cpp @@ -46,7 +46,7 @@ static void windowRelayout(uiWindow *w) return; x = 0; y = 0; - getClientRect(w->hwnd, &r); + uiWindowsEnsureGetClientRect(w->hwnd, &r); width = r.right - r.left; height = r.bottom - r.top; windowMargins(w, &mx, &my); @@ -239,7 +239,7 @@ static void uiWindowChildMinimumSizeChanged(uiWindowsControl *c) int mx, my; uiWindowsControlMinimumSize(uiWindowsControl(w->child), &width, &height); - getClientRect(w->hwnd, &r); + uiWindowsEnsureGetClientRect(w->hwnd, &r); windowMargins(w, &mx, &my); needsGrowing = FALSE; // subtract margins so we only care about the area that's used @@ -374,7 +374,7 @@ void ensureMinimumWindowSize(uiWindow *w) RECT r; uiWindowsControlMinimumSize(uiWindowsControl(w), &width, &height); - getClientRect(w->hwnd, &r); + uiWindowsEnsureGetClientRect(w->hwnd, &r); if (width < (r.right - r.left)) // preserve width if larger width = r.right - r.left; if (height < (r.bottom - r.top)) // preserve height if larger diff --git a/windows/winpublic.cpp b/windows/winpublic.cpp index 73ee51ca..1cc9129d 100644 --- a/windows/winpublic.cpp +++ b/windows/winpublic.cpp @@ -34,3 +34,28 @@ void uiWindowsEnsureMoveWindowDuringResize(HWND hwnd, intmax_t x, intmax_t y, in if (SetWindowPos(hwnd, NULL, r.left, r.top, r.right - r.left, r.bottom - r.top, SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOZORDER) == 0) logLastError(L"error moving window"); } + +// do these function even error out in any case other than invalid parameters?! I thought all windows had rects +void uiWindowsEnsureGetClientRect(HWND hwnd, RECT *r) +{ + if (GetClientRect(hwnd, r) == 0) { + logLastError(L"error getting window client rect"); + // zero out the rect on error just to be safe + r->left = 0; + r->top = 0; + r->right = 0; + r->bottom = 0; + } +} + +void uiWindowsEnsureGetWindowRect(HWND hwnd, RECT *r) +{ + if (GetWindowRect(hwnd, r) == 0) { + logLastError(L"error getting window rect"); + // zero out the rect on error just to be safe + r->left = 0; + r->top = 0; + r->right = 0; + r->bottom = 0; + } +} diff --git a/windows/winutil.cpp b/windows/winutil.cpp index 0cbdbc3e..b4fa692e 100644 --- a/windows/winutil.cpp +++ b/windows/winutil.cpp @@ -120,28 +120,3 @@ void setWindowInsertAfter(HWND hwnd, HWND insertAfter) if (SetWindowPos(hwnd, insertAfter, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOOWNERZORDER | SWP_NOSIZE) == 0) logLastError(L"error reordering window"); } - -// do these function even error out in any case other than invalid parameters?! I thought all windows had rects -void getClientRect(HWND hwnd, RECT *r) -{ - if (GetClientRect(hwnd, r) == 0) { - logLastError(L"error getting window client rect"); - // zero out the rect on error just to be safe - r->left = 0; - r->top = 0; - r->right = 0; - r->bottom = 0; - } -} - -void getWindowRect(HWND hwnd, RECT *r) -{ - if (GetWindowRect(hwnd, r) == 0) { - logLastError(L"error getting window rect"); - // zero out the rect on error just to be safe - r->left = 0; - r->top = 0; - r->right = 0; - r->bottom = 0; - } -}