Skip to content

Fix focus stolen from terminal when commit message prefix is updated#35

Open
thomasrepnik wants to merge 1 commit into
masterfrom
fix/focus-steal-on-branch-change
Open

Fix focus stolen from terminal when commit message prefix is updated#35
thomasrepnik wants to merge 1 commit into
masterfrom
fix/focus-steal-on-branch-change

Conversation

@thomasrepnik

Copy link
Copy Markdown
Owner

Summary

When the branch changes (e.g. git checkout in the IntelliJ terminal), the plugin updates the commit message prefix — but it also stole keyboard focus from the terminal and moved it into the commit message field.

Root cause (verified against IntelliJ 2023.2.4 sources): the plugin called CheckinProjectPanel.setCommitMessage(...), and the platform's CommitProjectPanelAdapter implements that as setText(...) followed by commitMessageUi.focus() — in both the non-modal commit tool window and the modal commit dialog. The write also happened unconditionally on every GIT_REPO_CHANGE event (fetch, ticket-less branches), stealing focus even when nothing changed.

Fix (only CommitPrefixCheckinHandler.java):

  • New pure static calculateNewCommitMessage(...) returning Optional.empty() when the branch has no ticket or the computed message is unchanged (compared right-trimmed, since CommitMessage.getText() trims trailing whitespace). No-op repo events now do nothing at all.
  • New setCommitMessageWithoutFocus(...): finds the CommitMessage component via UIUtil.findComponentOfType(panel.getComponent(), ...) and calls its setCommitMessage(...), which only sets text and never requests focus. Falls back to panel.setCommitMessage(...) for unknown panel implementations.

All prefix/ticket logic (updatePrefix, getTicket, settings, listener wiring) is untouched. Manually verified: prefix still updates on terminal checkout, focus stays in the terminal.

Note: bypassing the adapter also skips its VcsConfiguration.saveCommitMessage(oldText) call, so intermediate prefix rewrites no longer pollute the "recent commit messages" history; the final message is still saved on commit.

Test Coverage

10 new parameterized tests for calculateNewCommitMessage (TDD: written first, confirmed failing, then implemented). Tests: 133 → 143 (+10 new), all passing.

calculateNewCommitMessage(ticketSystem, branchName, currentMessage, wrapL, wrapR, pos)
 +-- no ticket in branch --> empty                    [TESTED]
 +-- ticket, message unchanged (incl. rTrim) --> empty [TESTED: START/END, JIRA/OTHER]
 +-- ticket, message changed --> new message           [TESTED: null current, START/END, JIRA/OTHER]

UI layer (no platform test fixtures in project):
 setCommitMessageWithoutFocus / updateCommitMessage    [manually verified in IDE]

Coverage audit: 9/11 testable paths (82%). Remaining gaps are low-risk Optional-plumbing combinations (OTHER system with no-digit branch; blank-but-non-null current message) whose underlying logic is covered by existing getTicket/updatePrefix tests.

Pre-Landing Review

  • Adversarial review recommendation: land it. Confirmed the fix mechanism is correct for both stock commit UIs and the rTrim guard is required (prevents rewrite-per-event caret jumps) and loop-free.
  • Informational: two cases in calculateNewCommitMessage_messageUnchanged_returnsEmpty (main/develop) exercise the no-ticket branch rather than message equality — cosmetic naming only.
  • Pre-existing issues noted for future work (not introduced or worsened here): message-bus connection is never disposed (stale handler leak), repositoryChanged ignores its repository argument in multi-root projects.

Test plan

  • ./gradlew test — 143/143 pass (fresh run on merged state)
  • ./gradlew buildPlugin — builds successfully
  • Manual: git checkout <ticket-branch> in the IDE terminal updates the prefix without stealing focus

🤖 Generated with Claude Code

panel.setCommitMessage() calls CommitMessageUi.focus() in the platform's
CommitProjectPanelAdapter, yanking focus into the commit message field on
every branch change (e.g. git checkout in the terminal). Set the message
directly on the CommitMessage component instead (no focus request) and
skip the update entirely when the computed message is unchanged.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
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.

1 participant