MCPcopy
hub / github.com/codeaashu/claude-code / computeWheelStep

Function computeWheelStep

src/components/ScrollKeybindingHandler.tsx:176–297  ·  view source on GitHub ↗
(state: WheelAccelState, dir: 1 | -1, now: number)

Source from the content-addressed store, hash-verified

174 * step=0 (scrollBy(0) is a no-op, onScroll(false) is idempotent). Exported
175 * for tests. */
176export function computeWheelStep(state: WheelAccelState, dir: 1 | -1, now: number): number {
177 if (!state.xtermJs) {
178 // Device-switch guard ①: idle disengage. Runs BEFORE pendingFlip resolve
179 // so a pending bounce (28% of last-mouse-events) doesn't bypass it via
180 // the real-reversal early return. state.time is either the last committed
181 // event OR the deferred flip — both count as "last activity".
182 if (state.wheelMode && now - state.time > WHEEL_MODE_IDLE_DISENGAGE_MS) {
183 state.wheelMode = false;
184 state.burstCount = 0;
185 state.mult = state.base;
186 }
187
188 // Resolve any deferred flip BEFORE touching state.time/dir — we need the
189 // pre-flip state.dir to distinguish bounce (flip-back) from real reversal
190 // (flip persisted), and state.time (= bounce timestamp) for the gap check.
191 if (state.pendingFlip) {
192 state.pendingFlip = false;
193 if (dir !== state.dir || now - state.time > WHEEL_BOUNCE_GAP_MAX_MS) {
194 // Real reversal: new dir persisted, OR flip-back arrived too late.
195 // Commit. The deferred event's 1 row is lost (acceptable latency).
196 state.dir = dir;
197 state.time = now;
198 state.mult = state.base;
199 return Math.floor(state.mult);
200 }
201 // Bounce confirmed: flipped back to original dir within the window.
202 // state.dir/mult unchanged from pre-bounce. state.time was advanced to
203 // the bounce below, so gap here = flip-back interval — reflects the
204 // user's actual click cadence (bounce IS a physical click, just noisy).
205 state.wheelMode = true;
206 }
207 const gap = now - state.time;
208 if (dir !== state.dir && state.dir !== 0) {
209 // Flip. Defer — next event decides bounce vs. real reversal. Advance
210 // time (but NOT dir/mult): if this turns out to be a bounce, the
211 // confirm event's gap will be the flip-back interval, which reflects
212 // the user's actual click rate. The bounce IS a physical wheel click,
213 // just misread by the encoder — it should count toward cadence.
214 state.pendingFlip = true;
215 state.time = now;
216 return 0;
217 }
218 state.dir = dir;
219 state.time = now;
220
221 // ─── MOUSE (wheel mode, sticky until device-switch signal) ───
222 if (state.wheelMode) {
223 if (gap < WHEEL_BURST_MS) {
224 // Same-batch burst check (ported from xterm.js): iTerm2 proportional
225 // reporting sends 2+ SGR events for one detent when macOS gives
226 // delta>1. Without this, the 2nd event at gap<1ms has m≈1 → STEP*m=15
227 // → one gentle click gives 1+15=16 rows.
228 //
229 // Device-switch guard ②: trackpad flick produces 100+ events at <5ms
230 // (measured); mouse produces ≤3. 5+ consecutive → trackpad flick.
231 if (++state.burstCount >= 5) {
232 state.wheelMode = false;
233 state.burstCount = 0;

Callers 1

ScrollKeybindingHandlerFunction · 0.85

Calls 1

maxMethod · 0.80

Tested by

no test coverage detected