diff --git a/ui.h b/ui.h index c5b53272..41ca8c9a 100644 --- a/ui.h +++ b/ui.h @@ -280,7 +280,6 @@ typedef struct uiDrawContext uiDrawContext; struct uiAreaHandler { void (*Draw)(uiAreaHandler *, uiArea *, uiAreaDrawParams *); // TODO document that resizes cause a full redraw for non-scrolling areas; implementation-defined for scrolling areas - // TODO if the scrollbars disappear the histogram example won't recognize points in the correct spot until the area is resized void (*MouseEvent)(uiAreaHandler *, uiArea *, uiAreaMouseEvent *); // TODO document that on first show if the mouse is already in the uiArea then one gets sent with left=0 // TODO what about when the area is hidden and then shown again? diff --git a/windows/area.c b/windows/area.c index 86d88266..38103c58 100644 --- a/windows/area.c +++ b/windows/area.c @@ -7,6 +7,22 @@ uiWindowsDefineControl( uiAreaType // type function ) +// I love COM interfaces that actually only work on C++ +// ID2D1RenderTarget::GetSize is defined as returninig a structure +// with stdcall, this means it's an extra last argument +// the compiler tries to return it directly, and crashes +// I originally thought this was a bug in MinGW-w64, but it turns out it also affects MSVC! https://gcc.gnu.org/bugzilla/show_bug.cgi?id=64384 +// So we have to work around it. +// TODO is the return type correct? or should we just use C++? +void renderTargetGetSize(ID2D1RenderTarget *rt, D2D1_SIZE_F *size) +{ + typedef void (STDMETHODCALLTYPE *fptr)(ID2D1RenderTarget *, D2D1_SIZE_F *); + fptr f; + + f = (fptr) (rt->lpVtbl->GetSize); + (*f)(rt, size); +} + static LRESULT CALLBACK areaWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { uiArea *a; diff --git a/windows/area.h b/windows/area.h index e1f2c1f2..74a65336 100644 --- a/windows/area.h +++ b/windows/area.h @@ -24,6 +24,9 @@ struct uiArea { ID2D1HwndRenderTarget *rt; }; +// area.c +extern void renderTargetGetSize(ID2D1RenderTarget *rt, D2D1_SIZE_F *size); + // areadraw.h extern BOOL areaDoDraw(uiArea *a, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *lResult); extern void areaDrawOnResize(uiArea *, RECT *); diff --git a/windows/areadraw.c b/windows/areadraw.c index 09701499..a6cd3ac8 100644 --- a/windows/areadraw.c +++ b/windows/areadraw.c @@ -15,7 +15,7 @@ static HRESULT doPaint(uiArea *a, ID2D1RenderTarget *rt, RECT *clip) dp.AreaWidth = 0; dp.AreaHeight = 0; if (!a->scrolling) { - size = ID2D1RenderTarget_GetSize(rt); + renderTargetGetSize(rt, &size); dp.AreaWidth = size.width; dp.AreaHeight = size.height; } diff --git a/windows/areaevents.c b/windows/areaevents.c index c4ac0f54..4301e728 100644 --- a/windows/areaevents.c +++ b/windows/areaevents.c @@ -41,7 +41,7 @@ static void areaMouseEvent(uiArea *a, uintmax_t down, uintmax_t up, WPARAM wPar me.AreaWidth = 0; me.AreaHeight = 0; if (!a->scrolling) { - size = ID2D1HwndRenderTarget_GetSize(a->rt); + renderTargetGetSize((ID2D1RenderTarget *) (a->rt), &size); me.AreaWidth = size.width; me.AreaHeight = size.height; }