Move smooth scroll timers to a separate thread, instead of using SetTimer
#4722
+82
−17
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Potentially addresses #4122
Note. To avoid confusion, I'm going to refer to middle-click scroll as "auto scroll." And I'm going to refer to smoothly animated/interpolated scrolling (enabled by the
SmoothScroll=true
config) as "interpolated scroll." In the code, "auto scroll" is referred to asSMOOTHSCROLL
, while "interpolated scroll" is referred to assmoothScroll
. This could be confusing, which is why I call them "auto scroll" and "interpolated scroll."Discussion #4122 complains that "auto scroll" is too scratchy, and I noticed that this is possibly because it uses
SetTimer()
. Also, "interpolated scroll" usesSetTimer()
as well. An issue is thatSetTimer()
allows a minimum of 10ms/100fps (according to the docs, but it seems the true minimum is closer to 16ms/60fps in my testing). Many displays run at much higher than 100Hz (e.g. mine runs at 144Hz), so this results in a very scratchy appearance.A relatively non-intrusive solution is to replace the timer with a thread (see
ScrollTimerThread()
) which sendsWM_TIMER
messages to the canvas window. Since we use our own thread instead ofSetTimer()
, we can run at the monitor's refresh rate, instead of a capped 10ms/100fps. Note that using this method, not very much code needs changing. We still useWM_TIMER
messages, which can be handled in the exact same way as before. The only difference is that instead ofSetTimer()
/KillTimer()
, we have to callSetEvent()
/ResetEvent()
on an Event object which the thread is waiting on. Also, we have to account for the delta time (Δt) so that scrolling isn't faster/slower depending on refresh rate (i.e. for "auto scroll," a 144Hz monitor and a 60Hz monitor should have the same scroll speed).This is a draft PR because I just wanted to show a proof-of-concept that improves scrolling on high-refresh displays, in case it is helpful at all. It's not perfect, since
WM_TIMER
messages are low-priority. But it's relatively simple and non-intrusive, which is why I wanted to bring it up.