-
Notifications
You must be signed in to change notification settings - Fork 1.9k
spec: hide Warp icon from the Dock when using Hotkey window #9349
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,49 @@ | ||
| # Hide Warp icon from the Dock when using Hotkey window | ||
| ## Summary | ||
| Users who primarily access Warp through the dedicated Hotkey window on macOS can choose to hide Warp from the Dock so Warp stays available through the global hotkey without occupying a persistent Dock slot. | ||
| This feature adds an opt-in setting for that workflow while preserving the current visible-Dock behavior by default. | ||
| Related issue: #1154 | ||
| ## Problem | ||
| The dedicated Hotkey window is designed for users who keep Warp running in the background and summon it with a shortcut. For that workflow, a persistent Warp Dock icon can feel unnecessary and add Dock clutter, but removing it must not make Warp hard to recover or change behavior for users who use normal windows. | ||
| ## Goals | ||
| 1. Let macOS users hide the Warp Dock icon when they use the dedicated Hotkey window. | ||
| 2. Preserve current behavior for existing users unless they opt in. | ||
| 3. Keep the user in control from Warp settings and make the recovery path clear. | ||
| 4. Avoid affecting the separate "Show/hide all windows" activation hotkey mode. | ||
| ## Non-goals | ||
| 1. This feature does not add a menu bar extra or status bar item. | ||
| 2. This feature does not change the global hotkey registration model, Quake Mode window sizing, pinning, or auto-hide behavior. | ||
| 3. This feature does not hide Warp from the Dock for normal-window-only workflows. | ||
| 4. This feature does not change how Warp appears on Linux or Windows. | ||
| ## Figma | ||
| Figma: none provided. | ||
| ## Behavior | ||
| 1. On macOS, when the "Global hotkey" setting is set to "Dedicated hotkey window", Settings > Features shows a new switch for hiding Warp from the Dock. | ||
| 2. The setting is off by default for all users, including users who already have the dedicated Hotkey window enabled. | ||
| 3. When the setting is off, Warp behaves exactly as it does today: the Dock icon remains visible whenever Warp is running, and Dock interactions continue to open, focus, or create Warp windows according to existing behavior. | ||
| 4. When the setting is on and a dedicated Hotkey window keybinding is configured, Warp removes its icon from the Dock while remaining running in the background. | ||
| 5. While the Dock icon is hidden, the configured dedicated Hotkey window shortcut remains the primary way to show and hide Warp. Pressing the shortcut opens the dedicated Hotkey window if needed, focuses it when showing, and hides it when toggled away, matching existing Hotkey window behavior. | ||
| 6. Hiding the Dock icon does not close sessions, tabs, panes, or normal windows. Any visible Warp window remains visible, usable, and focusable. | ||
| 7. Hiding the Dock icon does not change Hotkey window layout settings: pinned edge, size percentages, display selection, background blur, and "hide window when unfocused" continue to behave as configured. | ||
| 8. The setting applies only while the effective global hotkey mode is "Dedicated hotkey window". If the user switches the global hotkey mode to "Disabled" or "Show/hide all windows", Warp shows its Dock icon again immediately. | ||
| 9. If the user clears the dedicated Hotkey window keybinding while the Dock-hiding setting is on, Warp shows its Dock icon again so the user is not left without an obvious way to return to the app. | ||
| 10. If the user later restores a dedicated Hotkey window keybinding and the Dock-hiding setting is still on, Warp hides the Dock icon again. | ||
| 11. If the user turns the setting off, Warp restores the Dock icon immediately without requiring an app restart. | ||
| 12. The setting state is persisted with the dedicated Hotkey window settings. Restarting Warp reapplies the effective Dock visibility based on the saved setting, the saved hotkey mode, and whether a dedicated Hotkey window keybinding is configured. | ||
| 13. On non-macOS platforms, the setting is not shown and has no effect if present in synced or imported settings. | ||
| 14. If macOS cannot apply the hidden-Dock state for any reason, Warp leaves the Dock icon visible and continues running normally. | ||
| 15. The setting label or helper text communicates that hiding the Dock icon also removes Warp from normal Dock-based app discovery. If macOS also removes Warp from the app switcher as part of this state, the UI should not imply that Cmd-Tab remains available. | ||
| 16. Dock visibility changes must not interrupt an in-progress terminal session, command execution, AI session, update prompt, modal, or notification flow. | ||
| 17. Users can still open normal Warp windows through existing in-app actions while the Dock icon is hidden. Those normal windows do not by themselves force the Dock icon to return unless the user changes the global hotkey mode, clears the dedicated Hotkey window keybinding, or disables the Dock-hiding setting. | ||
| ## Success criteria | ||
| 1. A macOS user can enable the dedicated Hotkey window, enable Dock hiding, and verify that Warp disappears from the Dock while still opening from the configured hotkey. | ||
| 2. The Dock icon returns immediately when the user disables the setting, changes away from dedicated Hotkey window mode, or removes the dedicated Hotkey window keybinding. | ||
| 3. Existing users and non-macOS users see no behavior change unless they opt into the new macOS setting. | ||
| 4. Session state and window contents survive every Dock visibility transition. | ||
| ## Validation notes | ||
| 1. Validate the behavior against the numbered invariants above on macOS with the dedicated Hotkey window enabled. | ||
| 2. Validate that non-macOS builds ignore the setting and do not expose macOS-specific UI. | ||
| 3. Validate that settings persistence and restart behavior match the effective-state rules in Behavior 8 through 12. | ||
| ## Open questions | ||
| 1. Should this setting be stored only locally on each machine, or should it sync with the existing dedicated Hotkey window settings? The current product expectation is that it persists with the dedicated Hotkey window settings, while non-macOS clients ignore it. | ||
| 2. Should the setting remain visible but disabled when the dedicated Hotkey window mode is selected without a keybinding, or should it remain enabled while the effective Dock-hiding behavior stays inactive until a keybinding exists? | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,108 @@ | ||
| # Hide Warp icon from the Dock when using Hotkey window | ||
| ## Context | ||
| This tech spec implements the behavior in `product.md` for GitHub issue #1154. | ||
| Warp already has two mutually exclusive global hotkey modes: | ||
| 1. `app/src/settings/mod.rs (239-276)` defines `GlobalHotkeyMode`, including "Dedicated hotkey window" for Quake Mode and "Show/hide all windows" for the activation hotkey. | ||
| 2. `app/src/settings/mod.rs (292-329)` defines `QuakeModeSettings`, which already stores the dedicated Hotkey window keybinding, pinning, display, size, and auto-hide options. | ||
| 3. `app/src/terminal/keys_settings.rs (16-65)` persists the dedicated Hotkey window settings at `global_hotkey.dedicated_window.settings`, the dedicated Hotkey window enabled flag at `global_hotkey.dedicated_window.enabled`, and the activation hotkey settings at `global_hotkey.toggle_all_windows.*`. | ||
| 4. `app/src/terminal/keys_settings.rs (89-112)` enforces that Quake Mode and the activation hotkey are mutually exclusive. | ||
| 5. `app/src/settings_view/features_page.rs (5309-5417)` renders the "Global hotkey" settings widget and conditionally renders dedicated Hotkey window controls only when `GlobalHotkeyMode::QuakeMode` is selected. | ||
| 6. `app/src/root_view.rs (440-499)` registers fixed actions for showing and hiding the dedicated Hotkey window and for showing or hiding all non-Quake windows. | ||
| 7. `app/src/root_view.rs (497-531)` registers the saved global hotkey keybindings on startup. | ||
| 8. `app/src/root_view.rs (1342-1499)` owns dedicated Hotkey window state transitions: create the pinned window, show it, focus it, hide it, and move it between screens. | ||
| 9. `app/src/root_view.rs (1499-1538)` owns the activation hotkey behavior for normal windows and should not be affected by Dock hiding. | ||
| 10. macOS global shortcut registration is implemented in `crates/warpui/src/platform/mac/delegate.rs (384-399)` and `crates/warpui/src/platform/mac/objc/app.m (56-83)`. | ||
| 11. macOS window show/hide behavior for the dedicated Hotkey window is implemented in `crates/warpui/src/platform/mac/objc/window.m (923-1009)`. | ||
| 12. macOS Dock reopen behavior currently lives in `crates/warpui/src/platform/mac/objc/app.m (301-311)`, which opens a new window when the Dock icon is clicked and no windows are visible. | ||
| The current code does not expose an app-level API for changing the macOS Dock activation policy at runtime. The implementation should add that platform capability and apply it from the effective hotkey settings. | ||
| ## Proposed changes | ||
| ### Settings model | ||
| 1. Add a new field to `QuakeModeSettings`, for example `hide_dock_icon: bool`, with default `false`. | ||
| 2. Store it inside the existing `global_hotkey.dedicated_window.settings` table so it is versioned with the rest of the dedicated Hotkey window settings. | ||
| 3. Give the schema description macOS-specific wording, such as "Whether Warp should hide its Dock icon while the dedicated hotkey window is active and configured." | ||
| 4. Add `KeysSettings` helpers mirroring the existing Quake Mode helpers: | ||
| - `set_hide_dock_icon_when_using_quake_mode_and_write_to_user_defaults(value, ctx)` | ||
| - optionally `toggle_hide_dock_icon_when_using_quake_mode_and_write_to_user_defaults(ctx)` if the settings UI uses toggle actions consistently. | ||
| 5. Keep the setting value independent from the effective behavior. The stored value may be true while effective behavior is false because the user selected another global hotkey mode, removed the keybinding, or is running on a non-macOS platform. | ||
| ### Effective Dock visibility | ||
| 1. Introduce a small pure helper that computes whether Warp should hide the Dock icon: | ||
| - target OS is macOS, | ||
| - `KeysSettings::global_hotkey_mode(ctx)` is `GlobalHotkeyMode::QuakeMode`, | ||
| - `quake_mode_settings.hide_dock_icon` is true, | ||
| - `quake_mode_settings.keybinding` is `Some`. | ||
| 2. The helper should return "hide Dock icon" rather than "show Dock icon" so non-macOS and unsupported paths naturally default to visible. | ||
| 3. Call this helper whenever hotkey-related settings change and at startup after settings are loaded. | ||
| 4. Suggested application points: | ||
| - after `maybe_register_global_window_shortcuts` in `app/src/root_view.rs`, so startup applies the saved effective state; | ||
| - after `FeaturesPageView::set_global_hotkey_mode`, keybinding save/clear actions, and the new Dock-hiding toggle, or from a shared settings-change helper so changes made through settings files also apply; | ||
| - from `FeaturesPageView::handle_hotkey_settings_update` only as a UI refresh path, not as the only application path, because the settings page may not be open. | ||
| 5. Avoid tying Dock visibility to whether the dedicated Hotkey window is currently visible. The product behavior depends on the configured dedicated-hotkey workflow, not the transient window open/hidden state. | ||
| ### Platform API | ||
| 1. Add an app-level platform method such as `AppContext::set_dock_icon_visible(bool)` backed by `platform::Delegate`. | ||
| 2. Add a default no-op implementation on `platform::Delegate` or update all platform delegates with no-ops so Linux, Windows, web, tests, and integration tests compile without macOS behavior. | ||
| 3. Implement the macOS delegate by setting the NSApplication activation policy on the main thread: | ||
| - visible: `NSApplicationActivationPolicyRegular`, | ||
| - hidden: `NSApplicationActivationPolicyAccessory`. | ||
| 4. Prefer keeping the Objective-C boundary small: | ||
| - either expose a helper in `crates/warpui/src/platform/mac/objc/app.m` and declare it in `app.h`, | ||
| - or call `setActivationPolicy:` from Rust in `crates/warpui/src/platform/mac/delegate.rs` if that matches nearby macOS platform patterns. | ||
| 5. Log and leave the app visible if the policy call fails. Do not panic or block settings persistence. | ||
| 6. When restoring the Dock icon, use `NSApplicationActivationPolicyRegular` even if no windows are visible so Dock-based reopen behavior in `crates/warpui/src/platform/mac/objc/app.m (301-311)` remains available. | ||
| ### Settings UI | ||
| 1. Extend `FeaturesPageAction` with a new action for toggling or setting the Dock-hiding preference. | ||
| 2. In `GlobalHotkeyWidget`, render the new switch only under the `GlobalHotkeyMode::QuakeMode` branch and only on macOS. | ||
| 3. Place it near the existing dedicated Hotkey window controls, after the keybinding row and before or after the existing pin/auto-hide controls. | ||
| 4. Use copy that makes the scope explicit, for example: | ||
| - label: "Hide Dock icon" | ||
| - helper or tooltip: "When a dedicated hotkey is configured, keep Warp running without showing it in the Dock. Use the hotkey to show Warp again." | ||
| 5. If the keybinding is missing, either disable the switch with helper text or allow changing the saved preference while clearly indicating that it applies once a keybinding is configured. The product spec leaves this UX choice open. | ||
| 6. Preserve existing local-only/sync indicator conventions used by nearby settings rows. | ||
| ### Startup and recovery behavior | ||
| 1. Apply the effective Dock visibility after settings are loaded and before or alongside global hotkey registration. | ||
| 2. If a user starts Warp with Dock hiding enabled but no dedicated Hotkey window keybinding, force the effective state to Dock-visible. | ||
| 3. If the user switches from Quake Mode to the activation hotkey or disabled mode, immediately restore the Dock icon before unregistering or replacing shortcuts if possible. This ordering keeps an obvious recovery path if shortcut registration fails. | ||
| 4. If the macOS activation policy transition removes the app from Cmd-Tab, do not attempt to work around it in this feature. Reflect the OS behavior in UI copy. | ||
| ### Telemetry | ||
| 1. If the existing settings telemetry automatically records `FeaturesPageAction` changes, ensure the new action gets a descriptive event value. | ||
| 2. Do not add detailed per-hotkey telemetry for Dock visibility transitions unless product analytics explicitly needs it. | ||
| 3. Never log the user’s actual global hotkey keybinding as part of this feature. | ||
| ## End-to-end flow | ||
| 1. User selects "Dedicated hotkey window" and saves a global keybinding. | ||
| 2. `KeysSettings` stores Quake Mode as enabled and activation hotkey as disabled. | ||
| 3. User enables "Hide Dock icon". | ||
| 4. The settings action stores `quake_mode_settings.hide_dock_icon = true`. | ||
| 5. Shared effective-state code sees macOS + Quake Mode + keybinding + setting enabled. | ||
| 6. `AppContext` calls the platform delegate to set the macOS activation policy to accessory. | ||
| 7. Warp disappears from the Dock but remains running and responding to the registered global hotkey. | ||
| 8. If the user disables the setting, clears the keybinding, or changes global hotkey mode, the same effective-state code restores regular activation policy and the Dock icon returns. | ||
| ## Risks and mitigations | ||
| 1. Risk: Users can lose their obvious app entry point if the Dock icon is hidden without a working hotkey. Mitigation: effective Dock hiding requires a configured dedicated Hotkey window keybinding and restores the Dock icon when the keybinding is removed. | ||
|
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
| 2. Risk: Dock policy changes may behave differently across macOS versions. Mitigation: isolate the policy change behind a macOS platform API, log failures, and keep default behavior visible. | ||
| 3. Risk: Applying Dock visibility only from the settings page misses changes from settings file edits or synced settings. Mitigation: put effective-state application in a shared helper invoked from startup and model/settings change paths, not only from UI event handlers. | ||
| 4. Risk: Hiding the Dock icon could unexpectedly affect Cmd-Tab. Mitigation: document this in product copy and avoid promising Dock-only behavior that macOS cannot provide. | ||
| 5. Risk: Adding a required trait method can break non-macOS builds. Mitigation: provide default no-op behavior or update test, Linux, Windows, web, and integration delegates in the same implementation. | ||
| ## Testing and validation | ||
| 1. Unit-test the pure effective-state helper for product Behavior 2, 4, 8, 9, 10, and 13: | ||
| - default setting false never hides; | ||
| - Quake Mode + setting true + keybinding hides on macOS; | ||
| - disabled mode, activation hotkey mode, missing keybinding, and non-macOS all remain visible. | ||
| 2. Add or update settings serialization tests if this repository has coverage for generated settings schemas or TOML paths, verifying the new field defaults to false and round-trips in `global_hotkey.dedicated_window.settings`. | ||
| 3. Add UI/action tests around `FeaturesPageAction` if nearby settings actions are covered, verifying the switch updates `QuakeModeSettings` without changing the selected global hotkey mode. | ||
| 4. Build or typecheck affected Rust crates on Linux to catch trait and settings-model regressions even though macOS behavior is no-op there. | ||
| 5. Run a macOS manual validation pass: | ||
| - enable dedicated Hotkey window and keybinding; | ||
| - enable Dock hiding and confirm the Dock icon disappears; | ||
| - press the hotkey and confirm the Hotkey window still shows and hides; | ||
| - disable Dock hiding and confirm the Dock icon returns without restart; | ||
| - clear the keybinding and confirm the Dock icon returns; | ||
| - switch to "Show/hide all windows" and confirm the Dock icon returns. | ||
| 6. Validate session preservation by running a long-lived command, toggling Dock hiding on and off, and confirming the command, pane, and tab remain intact. | ||
| 7. Validate restart behavior by quitting and relaunching with the setting enabled and a configured dedicated hotkey, then verifying the effective Dock state matches the saved settings. | ||
| ## Parallelization | ||
| Implementation can split across two agents after spec approval: | ||
| 1. Platform/settings agent: add the setting, effective-state helper, platform API, macOS activation policy, and unit tests. | ||
| 2. UI/validation agent: add the Settings > Features switch, copy, action handling, and UI-focused tests/manual validation. | ||
| The agents should coordinate on the exact setting field name and effective-state helper API before coding to avoid conflicts in `KeysSettings` and `features_page.rs`. | ||
| ## Follow-ups | ||
| 1. Consider whether Warp should offer a menu bar extra for hidden-Dock workflows. That is explicitly out of scope for this issue. | ||
| 2. Consider adding user-facing docs for the macOS dedicated Hotkey window workflow once the setting ships. | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.