mirror of
https://git.tartarus.org/simon/putty.git
synced 2025-01-09 17:38:00 +00:00
Merge interactive scrolling fix from 'pre-0.75'.
This commit is contained in:
commit
3c851b2907
@ -2172,6 +2172,7 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message,
|
||||
static bool ignore_clip = false;
|
||||
static bool fullscr_on_max = false;
|
||||
static bool processed_resize = false;
|
||||
static bool in_scrollbar_loop = false;
|
||||
static UINT last_mousemove = 0;
|
||||
int resize_action;
|
||||
|
||||
@ -2226,6 +2227,21 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message,
|
||||
case WM_COMMAND:
|
||||
case WM_SYSCOMMAND:
|
||||
switch (wParam & ~0xF) { /* low 4 bits reserved to Windows */
|
||||
case SC_VSCROLL:
|
||||
case SC_HSCROLL:
|
||||
if (message == WM_SYSCOMMAND) {
|
||||
/* As per the long comment in WM_VSCROLL handler: give
|
||||
* this message the default handling, which starts a
|
||||
* subsidiary message loop, but set a flag so that
|
||||
* when we're re-entered from that loop, scroll events
|
||||
* within an interactive scrollbar-drag can be handled
|
||||
* differently. */
|
||||
in_scrollbar_loop = true;
|
||||
LRESULT result = DefWindowProcW(hwnd, message, wParam, lParam);
|
||||
in_scrollbar_loop = false;
|
||||
return result;
|
||||
}
|
||||
break;
|
||||
case IDM_SHOWLOG:
|
||||
showeventlog(hwnd);
|
||||
break;
|
||||
@ -3138,6 +3154,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;
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user