Win32: Fix stretched rendering and misaligned click areas when scrollbar visibility changes#1680
Win32: Fix stretched rendering and misaligned click areas when scrollbar visibility changes#1680
Conversation
Co-authored-by: phkahler <14852918+phkahler@users.noreply.github.com>
|
@copilot your fix - making the toolbar permanently visible - is an interesting idea for a workaround. Adding Disregarding the above workaround. I'm very interested why resizing the the window causes the "content width value" to be updated and therefore the canvas redrawn with proper horizontal scaling. Can the "process" that happens when resizing the window be somehow recreated when showing/hiding the scroll bar? An interesting side note - the exact same solvespace.exe has the problem on Windows 10 and windows 11 and does not have the problem on Windows 2000 and Windows XP. This means that the behaviour is somehow influenced by differences in the Win32 (GDI ?) implementations between these Windows versions. Can you find something based on this? |
…llbar Co-authored-by: ruevs <15338069+ruevs@users.noreply.github.com>
You were right that When Fix in commit Combined with |
|
@copilot I pulled the version with While the workaround works I want to get to the root of the problem. I read your detailed thoughts on the Is there a way to "manually" send |
Yes, void SetScrollbarVisible(bool visible) override {
bool wasVisible = scrollbarVisible;
scrollbarVisible = visible;
if(visible != wasVisible) {
ShowScrollBar(hWindow, SB_VERT, visible ? TRUE : FALSE);
// Synthesize WM_SIZE so ANGLE detects the client width change
// and resizes its D3D swap chain before the next render.
RECT rc;
GetClientRect(hWindow, &rc);
SendMessage(hWindow, WM_SIZE, SIZE_RESTORED,
MAKELPARAM(rc.right - rc.left, rc.bottom - rc.top));
}
}
On Windows 2000/XP the scrollbar visibility change apparently triggered The current |
@copilot I tried your code (with I also tried to send SendMessage(hWindow, WM_SIZING, WMSZ_LEFT, (LPARAM)&rc);but it did not help either. Something else is happening when the window is actually resized by the user, but I can not figure out what. |
The reason
The genuine "proper" root-cause fix, if a dynamically-hiding scrollbar is desired, would be to destroy and recreate the EGL surface after void SetScrollbarVisible(bool visible) override {
bool wasVisible = scrollbarVisible;
scrollbarVisible = visible;
if(visible != wasVisible) {
ShowScrollBar(hWindow, SB_VERT, visible ? TRUE : FALSE);
// Force ANGLE to create a new swap chain at the updated client width.
// DXGI does not detect NC-area-only changes (scrollbar show/hide),
// so we must manually recreate the EGL surface to resync it.
eglMakeCurrent(eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
eglDestroySurface(eglDisplay, eglSurface);
EGLint surfaceAttributes[] = { EGL_NONE };
eglSurface = eglCreateWindowSurface(eglDisplay, windowConfig, hWindow, surfaceAttributes);
Invalidate();
}
}This requires saving
Correction to my earlier reply — I was wrong to single out ANGLE's DXGI swap chain. The same stretching problem occurs with the OpenGL 1 (WGL) renderer, which has no DXGI involvement at all. The actual root cause is purely at the Win32 level: A synthesized The |
Co-authored-by: ruevs <15338069+ruevs@users.noreply.github.com>
|
@copilot I tried the following void SetScrollbarVisible(bool visible) override {
bool wasVisible = scrollbarVisible;
scrollbarVisible = visible;
if(visible != wasVisible) {
ShowScrollBar(hWindow, SB_VERT, visible ? TRUE : FALSE);
PAINTSTRUCT ps;
HDC hDc = BeginPaint(hWindow, &ps);
wglMakeCurrent(hDc, hGlRc);
wglDeleteContext(hGlRc);
hGlRc = wglCreateContext(hDc);
Invalidate();
}
} |
…s outer HWND bounds change Co-authored-by: ruevs <15338069+ruevs@users.noreply.github.com>
... Three reasons that approach doesn't work:
The only general approach that could work dynamically (without |
…ting ...because the contents were rendered stretched or compressed. Force the window 1 pixel taller and then restore it's original size. This somehow fixes the problem where on Windows 10 and 11 toggling the scroll bar would cause the client area of the text window to be stretched or compressed horizontally. It looks bad and the buttons on the toolbar do not line up with the hit areas. This fix is the result of a long discussion with claude-sonnet-4.6 https://github.com/solvespace/solvespace/agents/pull/1680 solvespace#1680 Fixes: solvespace#681
On Windows 10/11,
ShowScrollBarredistributes NC vs. client space without changing the outer HWND bounds. Neither WGL (GL1) nor ANGLE/D3D (GL3) resizes its back buffer/swap chain for such changes — only genuine outer-bounds changes trigger that. The result: the rendering surface stays at the old width whileGetClientRectreturns the new one, causing stretched text and hit-test coordinates shifted from their rendered icons. Reproducible by clearing SolveSpace registry settings and switching between pages that do/don't need a scrollbar.Changes (
src/platform/guiwin.cpp)WS_VSCROLLonWindow::Kind::TOOL— reserves scrollbar space at creation so the client area width is stable from the startSIF_DISABLENOSCROLLinConfigureScrollbar— when content fits the view (page ≥ range), Windows disables (greys out) the scrollbar instead of hiding it, keeping the client area width constant; without this flagSetScrollInfoauto-hides the scrollbar even withWS_VSCROLLsetShowScrollBarfromSetScrollbarVisible— no longer needed; enable/disable state is managed entirely throughConfigureScrollbar; thescrollbarVisibleflag is still maintained for theGetScrollbarPosition/SetScrollbarPositionguardsOriginal prompt
This section details on the original issue you should resolve
<issue_title>Button click area is shifted left of icon</issue_title>
<issue_description>### System information
SolveSpace version: 3.0~bb56daf3
Operating system: Windows 10
Expected behavior
Clicking Occluded Lines button must switch mode
Actual behavior
The right side of the button is non-operate, no hovering or clicking events do nothing.
Seems the hover-and-click area is shifted left (see attached pic)
Solid model buttons are shifted too, but less. I think the width of spacers are not calculated right.
Additional information
</issue_description>
<agent_instructions>See if you can identify a possible fix for issue #681</agent_instructions>
Comments on the Issue (you are @copilot in this section)
@ruevs Works for me on Windows as well at 04b332d HD Graphics 630 OpenGL 4.5 the rest as @developex-dmytro-i @ruevs @developex-dmytro-i does your problem still happen on a recent build? Please try the "Edge" from here https://github.com/solvespace/solvespace/releases @ruevs I **_think_** that I could reproduce this a few days back on Windows and then it disappeared?!?! Needs testing with all options cleared from the registry/json - just a guess... @ruevs I can consistently reproduce this on Windows by deleting the registry settings of SolveSpace (`Computer\HKEY_USERS\S-xxxx\SOFTWARE\SolveSpace` registry key).After this (as mentioned above) the contents of the property browser window are scaled incorrectly - they are very slightly enlarged. This is the reason the icons and the "click" areas do not line up. As soon as the window is resized the scaling fixes itself.
In the screen shots below:
I added the vertical red lines to emphasize the problem.

The slight anti-aliasing of the top one is not an artifact of the screen shot - it is caused by the scaling and is visible on screen.
By the way the wrong scaling is only in the X (horizontal direction). Vertically the size is unchanged:

I did try to debug this a bit but did not immediately find the problem and ran out of time, I'll come back to it.</comment_new>
<comment_new>@phkahler
@ruevs You might try calling TextWindow::Resize() sometime after startup since resizing fixes the issue. If that works you can maybe track down something being not initialized correctly.
Edit: Now I'm thinking extWindow::DrawOrHitTestIcons() is drawing before the scrollbar is there, and hit testing afterward? That might change the result of window->GetContentSize()
Edit 2: I'm pretty sure it's not a problem in drawing the toolbar. It seems to be stretching the entire text window including the letters. Watch the "a" or even the whole word "active" when resizing fixes the issue.</comment_new>
<comment_new>@phkahler
I'm seeing this text stretching on Windows 11 Enterprise. When I start Solvespace the text is stretched and a bit blurry. If I resize it (vertically by dragging the bottom) the text snaps back to normal size. If I click on some of the text window menus (line styles / view / configuration) The text will be sized correctly or not depending if a scrollbar appears or disappears.
At times during vertical resizing I can see a brief glitch when the scroll bar appears or disappears and the text is briefly the wrong horizontal size.</comment_new>
<comment_new>@phkahler
It's as if changing visibility of the scrollbar changes the width of the window but we don't change the size of our offscreen bitmap unless we get an actual window resize event. Changing scrollbar visibility by resizing the window works ...
💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.