Skip to content

refactor(track): split FocusTracker::run into FocusRun steps (#477) - #482

Merged
Maxaubert merged 4 commits into
mainfrom
refactor/split-focus-run
Oct 14, 2026
Merged

Maxaubert merged 4 commits into
mainfrom
refactor/split-focus-run

Conversation

@Maxaubert

Copy link
Copy Markdown
Owner

Closes #477

Pure refactor of FocusTracker::run (src/focus_track.cpp, 411 lines) from the 2026-10-13 repo review ("Second-tier oversized functions"). Move-only: same side-effect order, same early returns, same logging and timing (slow resolve, rs0/rs1/fc0/fc1), same thread (everything still runs on the tracker thread).

Shape

run()'s locals become members of a private helper struct FocusRun (same declarations, same order, same comments; h1..h3 now start null and are assigned in setUp). Its five lambdas become member functions with unchanged bodies. The tracker members the moved code uses (tid_, active_, wantCaret_, wantFocus_, log_, publish) are aliased in FocusRun, so the moved lines are byte-identical. FocusTracker gets friend struct FocusRun;.

Functions (line ranges in the new src/focus_track.cpp)

Function Lines Size Was
FocusRun (struct: aliases, state, steps) 307-673 run()'s locals
FocusRun::retune 332-338 7 retune lambda
FocusRun::fixLineWide 387-404 18 lambda
FocusRun::focusClass 423-437 15 lambda
FocusRun::editContextCaret 440-458 19 lambda
FocusRun::findCaret 460-514 55 lambda
FocusRun::readJavaCaret 518-543 26 Java bridge block at the top of resolve
FocusRun::resolve 548-594 47 (was 143) lambda
FocusRun::followCaret 596-672 77 step 2 of resolve (find caret, trim/hold, baseline or publish)
FocusRun::setUp 675-696 22 COM, UIA timeouts, FocusLookup, focus handler, WinEvent hooks, first retune
FocusRun::messageLoop 698-735 38 the GetMessageW loop
FocusRun::tearDown 737-745 9 unhook, release, CoUninitialize
FocusTracker::run 747-758 12 (was 411) queue + thread-id prologue, setUp/messageLoop/tearDown, tid_ = 0

Construction and destruction order are unchanged in effect: FocusRun is built after the stop check and before CoInitializeEx (its members have no side-effecting constructors; JavaBridge has none), and it is destroyed at the end of run() after tid_ = 0, where the locals used to be.

How move-only was checked

Per commit, the diff was taken with --color-moved=plain (moved lines coloured separately) and only the non-moved +/- lines listed. What remained was only: the struct header and aliases, auto x = [&](...) -> R { to R x(...) { (and }; to }), HWINEVENTHOOK hN = SetWinEventHook(...) to hN = SetWinEventHook(...), the new function heads and braces, return java;, and the call sites (const bool java = readJavaCaret(fg, fromPoll);, followCaret(el, b, fg, java, fromPoll, rs0, rs1);, r.setUp(); r.messageLoop(m); r.tearDown();). Review with --color-moved=zebra --color-moved-ws=allow-indentation-change.

Commits: one for the struct move, one per resolve extraction, one for docs (docs/architecture/07-cursor.md now names the steps).

Gates

  • build.bat check: pass (only the existing fopen C4996 warnings)
  • build.bat test: exit 0, 643/643 test cases
  • build.bat: links Wind.exe and WindTray.exe
  • src/config_ui and ui/ untouched, so no config build or Playwright run

Not deployed or run (no runtime change intended).

🤖 Generated with Claude Code

https://claude.ai/code/session_01TdjopXZfsUiesYxYLYHEdH

Maxaubert and others added 4 commits October 14, 2026 01:53
…un (#477)

Move-only. run()'s locals become FocusRun members (same declarations, same
order, same comments), its five lambdas become member functions with
unchanged bodies, and its body is split into setUp (COM, UIA timeouts, focus
lookup, focus handler, WinEvent hooks, first retune), messageLoop and
tearDown. run() keeps the queue/thread-id prologue and the final tid_ = 0.
The tracker members the steps use are aliased so the moved code is
byte-identical. Everything still runs on the tracker thread.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TdjopXZfsUiesYxYLYHEdH
…avaCaret (#477)

Move-only: the java decision and the event-driven bridge read move verbatim;
resolve calls it at the same point and keeps the result in the same const.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TdjopXZfsUiesYxYLYHEdH
…owCaret (#477)

Move-only: step 2 of resolve (find the caret, slow-resolve log, trim/hold,
baseline or publish) moves verbatim; resolve calls it at the same point,
before releasing the focused element.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TdjopXZfsUiesYxYLYHEdH
@Maxaubert
Maxaubert merged commit d5719b9 into main Oct 14, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Split FocusTracker::run into hook set-up, resolve and message loop (refactor)

1 participant