Skip to content

fix: window-toggle actions focus when covered (Cmd+Ctrl+R/T, tray click)#114

Merged
grimmerk merged 2 commits intomainfrom
fix/quick-switcher-focus-when-covered
Apr 7, 2026
Merged

fix: window-toggle actions focus when covered (Cmd+Ctrl+R/T, tray click)#114
grimmerk merged 2 commits intomainfrom
fix/quick-switcher-focus-when-covered

Conversation

@grimmerk
Copy link
Copy Markdown
Owner

@grimmerk grimmerk commented Apr 7, 2026

Summary

Fix window-toggle actions in Normal App mode when the CodeV window is visible but covered by another app.

Affected actions

Action Callback Before After
Cmd+Ctrl+R quickSwitcherCallback hides brings to front
Tray left-click trayToggleEvtHandler hides brings to front
Cmd+Ctrl+T terminalCallback hides (or no-op tab switch) brings to front + switches to Terminal tab

Three-state logic

State Action
Hidden / minimized show + focus (unchanged)
Visible AND focused hide / toggle (unchanged)
Visible but unfocused (covered) app.focus({ steal: true }) + window.show() + window.focus() (new)

For Cmd+Ctrl+T, the visible-but-unfocused branch also sends switch-to-terminal so the user lands on the Terminal tab after the window comes to front (matches the user intent of "I want to use the terminal"). The visible-and-focused branch keeps the existing renderer-side toggle (check-terminal-and-hide).

Also adds the missing !window.isMinimized() check to both trayToggleEvtHandler and terminalCallback for consistency with quickSwitcherCallback.

Why menu bar mode is unaffected

In menu bar mode, onBlur auto-hides the window the moment focus is lost (src/main.ts:267-271), so the "visible but unfocused" state can't occur. The new app.focus({ steal: true }) call is also gated to appMode === 'normal' as a safeguard — accessory apps shouldn't steal app-level focus.

Test plan

Normal mode

  • Cmd+Ctrl+R: cover with another app → single press brings CodeV to front
  • Cmd+Ctrl+R: on top + focused → hides
  • Cmd+Ctrl+R: hidden → shows + focuses
  • Tray left-click: cover with another app → single click brings CodeV to front
  • Tray left-click: on top + focused → hides
  • Cmd+Ctrl+T: cover with another app → brings to front + lands on Terminal tab
  • Cmd+Ctrl+T: on top + focused + already on Terminal tab → hides
  • Cmd+Ctrl+T: on top + focused + on other tab → switches to Terminal tab

Menu bar mode

  • Cmd+Ctrl+R: behavior unchanged (visible → hide, hidden → show)
  • Tray left-click: behavior unchanged
  • Cmd+Ctrl+T: behavior unchanged

🤖 On behalf of @grimmerk — generated with Claude Code

Summary by CodeRabbit

  • Bug Fixes
    • Window-toggle actions (Quick Switcher, Terminal, and tray left-click) now bring windows to the front when visible but unfocused, instead of hiding them on the first press
    • Windows hide as expected when already visible and focused
    • Menu Bar mode behavior remains unchanged

In Normal App mode, if the CodeV window was visible but covered
by another app (unfocused), pressing Cmd+Ctrl+R would hide it
instead of bringing it to the front. Required two presses to
reach top-most.

Now the three states are:
- Hidden/minimized → show + focus
- Visible but unfocused → app.focus({ steal: true }) + focus
- Visible AND focused → hide

Menu bar mode is unaffected: onBlur auto-hides the window, so
the visible-but-unfocused state can't occur there. The new
app.focus call is also gated to normal mode as a safeguard.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issues found across 3 files

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Apr 7, 2026

📝 Walkthrough

Walkthrough

This PR updates the application to version 1.0.72 with a behavior fix for window toggle actions. In Normal mode, toggle actions now bring unfocused but visible windows to the front instead of immediately hiding them; focused windows continue to hide as before. Menu Bar mode behavior remains unchanged.

Changes

Cohort / File(s) Summary
Version Bump
CHANGELOG.md, package.json
Updated version to 1.0.72 with changelog entry documenting the window toggle behavior fix for Normal mode.
Window Toggle Logic
src/main.ts
Modified tray-toggle and shortcut toggle behavior to distinguish between "visible but unfocused" and "visible and focused" states. When a window is visible but unfocused, toggle actions now bring it to the front (using app.focus({ steal: true }) in Normal mode) instead of hiding it. Terminal shortcut and tray toggle also updated to focus/raise unfocused windows and send switch-to-terminal command appropriately.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~28 minutes

Possibly related PRs

Poem

🐰 Hop, hop, windows now obey,
Unfocused panes leap into day,
No more hide-and-seek at first click,
Focus-aware brings windows quick,
In Normal mode, the switcher's spry,
Bringing lost windows to the sky!

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title accurately summarizes the main change: fixing window-toggle actions (Cmd+Ctrl+R/T and tray click) to focus a window when it is visible but unfocused/covered, rather than hiding it.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/quick-switcher-focus-when-covered

Comment @coderabbitai help to get the list of available commands and usage tips.

Apply the same three-state logic to:
- Tray left-click (trayToggleEvtHandler default branch)
- Cmd+Ctrl+T Terminal callback

For Cmd+Ctrl+T, the visible-but-unfocused branch also sends
'switch-to-terminal' so the user lands on the Terminal tab
after the window comes to front (matches the user intent of
"I want to use the terminal").

Also adds the missing !window.isMinimized() check to both
callbacks for consistency with quickSwitcherCallback.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@grimmerk grimmerk changed the title fix: Cmd+Ctrl+R focuses window when covered in Normal App mode fix: window-toggle actions focus when covered (Cmd+Ctrl+R/T, tray click) Apr 7, 2026
Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
src/main.ts (1)

1341-1357: Consider extracting the three-state toggle logic into a helper.

The same visible/focused/unfocused branching pattern is duplicated in trayToggleEvtHandler, quickSwitcherCallback, and terminalCallback. A small helper would reduce duplication and ensure consistent behavior across all toggle actions.

♻️ Optional: Extract helper function
/** 
 * Handles three-state window toggle: hidden→show, visible+unfocused→focus, visible+focused→hide.
 * Returns true if window was brought to front, false if hidden or not applicable.
 */
const bringToFrontOrHide = (window: BrowserWindow | null): 'shown' | 'hidden' | 'focused' | null => {
  if (!window) return null;
  
  if (window.isVisible() && !window.isMinimized()) {
    if (window.isFocused()) {
      hideSwitcherWindow();
      return 'hidden';
    } else {
      if (appMode === 'normal') {
        app.focus({ steal: true });
      }
      window.show();
      window.focus();
      return 'focused';
    }
  }
  return 'shown'; // caller should call showSwitcherWindow()
};

Then in each callback:

const result = bringToFrontOrHide(window);
if (result === 'shown') {
  showSwitcherWindow();
}
// For terminal: if (result === 'focused') window.webContents.send('switch-to-terminal');
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/main.ts` around lines 1341 - 1357, Extract the duplicated three-state
toggle logic (hidden → show, visible+unfocused → focus, visible+focused → hide)
into a helper function (e.g., bringToFrontOrHide) and replace the repeated
branches inside trayToggleEvtHandler, quickSwitcherCallback, and
terminalCallback with calls to that helper; the helper should accept the
BrowserWindow (or null), return a small discriminant ('shown' | 'focused' |
'hidden' | null), call hideSwitcherWindow() when hiding, call
app.focus({steal:true}) + window.show() + window.focus() when bringing to front
(respecting appMode), and return 'shown' when the caller still needs to call
showSwitcherWindow(); update callers to call showSwitcherWindow() when helper
returns 'shown' and send any context-specific messages (e.g.,
switch-to-terminal) when helper returns 'focused'.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@src/main.ts`:
- Around line 1341-1357: Extract the duplicated three-state toggle logic (hidden
→ show, visible+unfocused → focus, visible+focused → hide) into a helper
function (e.g., bringToFrontOrHide) and replace the repeated branches inside
trayToggleEvtHandler, quickSwitcherCallback, and terminalCallback with calls to
that helper; the helper should accept the BrowserWindow (or null), return a
small discriminant ('shown' | 'focused' | 'hidden' | null), call
hideSwitcherWindow() when hiding, call app.focus({steal:true}) + window.show() +
window.focus() when bringing to front (respecting appMode), and return 'shown'
when the caller still needs to call showSwitcherWindow(); update callers to call
showSwitcherWindow() when helper returns 'shown' and send any context-specific
messages (e.g., switch-to-terminal) when helper returns 'focused'.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 1c6b72a6-28a9-4de1-9305-7c23762a1795

📥 Commits

Reviewing files that changed from the base of the PR and between 7272680 and 5933a0a.

📒 Files selected for processing (3)
  • CHANGELOG.md
  • package.json
  • src/main.ts

@grimmerk grimmerk merged commit 654c8e6 into main Apr 7, 2026
2 checks 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.

1 participant