1
0
mirror of https://git.tartarus.org/simon/putty.git synced 2025-01-09 17:38:00 +00:00

Restore missing screen updates from scrollbar buttons.

In commit f69cf86a61, I added a call to term_update that happens
when we receive WM_VSCROLL / SB_THUMBPOSITION in the subsidiary
message loop that Windows creates during the handling of WM_SYSCOMMAND
/ SC_VSCROLL. The effect was that interactive dragging of the
scrollbar now redraws the window at every step, whereas previously it
didn't.

A user just pointed out that if you click on one of the scrollbar end
buttons and hold it down until it begins emulating key repeat, the
same bug occurs: the window isn't redrawn until you release the mouse
button and the subsidiary message loop ends.

This commit extends the previous fix to cover all of the WM_VSCROLL
subtypes, instead of just SB_THUMBPOSITION and SB_THUMBTRACK. Redraws
while holding down those scrollbar buttons now work again.

(cherry picked from commit 2029aa55c2)
This commit is contained in:
Simon Tatham 2021-07-03 11:01:09 +01:00
parent 1dc5659aa6
commit 22d7888b33

View File

@ -3160,57 +3160,54 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message,
if (GetScrollInfo(hwnd, SB_VERT, &si) == 0)
si.nTrackPos = HIWORD(wParam);
term_scroll(term, 1, si.nTrackPos);
if (in_scrollbar_loop) {
/*
* Allow window updates to happen during interactive
* scroll.
*
* When the user takes hold of our window's scrollbar
* and wobbles it interactively back and forth, the
* first thing that happens is that this window
* procedure receives WM_SYSCOMMAND / SC_VSCROLL. [1]
* The default handler for that window message starts
* a subsidiary message loop, which continues to run
* until the user lets go of the scrollbar again. All
* WM_VSCROLL / SB_THUMBTRACK messages are generated
* by the handlers within that subsidiary message
* loop.
*
* So, during that time, _our_ message loop is not
* running, which means toplevel callbacks and timers
* and so forth are not happening, which means that
* when we redraw the window and set a timer to clear
* the cooldown flag 20ms later, that timer never
* fires, and we aren't able to keep redrawing the
* window.
*
* The 'obvious' answer would be to seize that
* SYSCOMMAND ourselves and inhibit the default
* handler, so that our message loop carries on
* running. But that would mean we'd have to
* reimplement the whole of the scrollbar handler!
*
* So instead we apply a bodge: set a static variable
* that indicates that we're _in_ that sub-loop, and
* if so, decide it's OK to manually call
* term_update() proper, bypassing the timer and
* cooldown and rate-limiting systems completely,
* whenever we see an SB_THUMBTRACK. This shouldn't
* cause a rate overload, because we're only doing it
* once per UI event!
*
* [1] Actually, there's an extra oddity where
* SC_HSCROLL and SC_VSCROLL have their documented
* values the wrong way round. Many people on the
* Internet have noticed this, e.g.
* https://stackoverflow.com/q/55528397
*/
term_update(term);
}
break;
}
}
if (in_scrollbar_loop) {
/*
* Allow window updates to happen during interactive
* scroll.
*
* When the user takes hold of our window's scrollbar and
* wobbles it interactively back and forth, or presses on
* one of the arrow buttons at the ends, the first thing
* that happens is that this window procedure receives
* WM_SYSCOMMAND / SC_VSCROLL. [1] The default handler for
* that window message starts a subsidiary message loop,
* which continues to run until the user lets go of the
* scrollbar again. All WM_VSCROLL / SB_THUMBTRACK
* messages are generated by the handlers within that
* subsidiary message loop.
*
* So, during that time, _our_ message loop is not
* running, which means toplevel callbacks and timers and
* so forth are not happening, which means that when we
* redraw the window and set a timer to clear the cooldown
* flag 20ms later, that timer never fires, and we aren't
* able to keep redrawing the window.
*
* The 'obvious' answer would be to seize that SYSCOMMAND
* ourselves and inhibit the default handler, so that our
* message loop carries on running. But that would mean
* we'd have to reimplement the whole of the scrollbar
* handler!
*
* So instead we apply a bodge: set a static variable that
* indicates that we're _in_ that sub-loop, and if so,
* decide it's OK to manually call term_update() proper,
* bypassing the timer and cooldown and rate-limiting
* systems completely, whenever we see an SB_THUMBTRACK.
* This shouldn't cause a rate overload, because we're
* only doing it once per UI event!
*
* [1] Actually, there's an extra oddity where SC_HSCROLL
* and SC_VSCROLL have their documented values the wrong
* way round. Many people on the Internet have noticed
* this, e.g. https://stackoverflow.com/q/55528397
*/
term_update(term);
}
break;
case WM_PALETTECHANGED:
if ((HWND) wParam != hwnd && pal != NULL) {