uttrflow / uttrflow/uttrflow-swift
The floating button stays on the display it first appeared on and isn't re-placed when displays or the Dock change
- Dominant language
- Swift
- Stars
- 4
- Forks
- 17
- Avg merge
- 3h 32m
- Merged PRs (30d)
- 277
Description
## What happens
The floating button is placed against one screen's visible frame:
```swift
// Sources/Uttrflow/Dock/DockPanelController.swift:169-172
private var visibleFrame: CGRect {
// With no screen to place against, staying put beats moving somewhere arbitrary.
(panel.screen ?? NSScreen.main ?? NSScreen.screens.first)?.visibleFrame ?? panel.frame
}
```
`panel.screen` is whichever display the panel is already on, so after its first placement the button stays on that display for the life of the process. `NSScreen.main` is consulted only before it has a screen. Settings offers four anchors (bottom left, bottom centre, bottom right, right edge; `Sources/Uttrflow/Dock/DockAnchor.swift`) and no choice of display.
The button is also repositioned only from `init`, `show()`, `setAnchor(_:)` and a size change (`DockPanelController.swift:95-98`, `:140-144`, `:155-167`). Nothing observes `NSApplication.didChangeScreenParametersNotification` (the main window does, `Sources/Uttrflow/Main/WindowVisibility.swift:93`), so when the Dock is shown or hidden, the Dock moves side, a display's resolution changes, or a display is unplugged, the button keeps its old frame until its size next changes (a hover, a dictation, or any settings change, which calls `show()`, `Sources/Uttrflow/AppDelegate.swift:1747-1749`).
## Why it matters
- With a laptop and an external display, the button sits on whichever display was main at launch. Someone working on the other display never sees the listening, working or failure states it exists to show, including the failure messages with recovery buttons.
- After unplugging the display the button was on, it sits wherever macOS put the window rather than at the chosen anchor, until its next size change.
- Turning on Dock auto-hide leaves the resting grip floating where the Dock used to be until the pointer or a dictation next changes its size.
## How to reproduce
1. With two displays, launch Uttrflow with the built-in display as main, then work on the external display and dictate: the button's states appear on the other display.
2. With the button anchored bottom-centre, toggle Dock auto-hide in System Settings: the button does not move down until it changes size (hover it).
3. Unplug the external display while the button is on it and note where it lands.
## Acceptance criteria
- Decide on the issue which display the button belongs to: the one with the menu bar, the one with the pointer or key window when a dictation starts, or a Settings choice (hence `needs-info`).
- The button is repositioned on `didChangeScreenParametersNotification`, so Dock, resolution and display changes put it back at its anchor on a display that exists.
- The placement rule is covered by a test on `DockPlacement` with two screen frames, and described in `Docs/app-dock.md`.
Contributor guide
Research direction
Start with Sources/Uttrflow/Dock/DockPanelController.swift, DockAnchor.swift, DockPlacement, and the screen-change handling in Sources/Uttrflow/Main/WindowVisibility.swift. Decide which display owns the button, then trace the existing placement and notification entry points. Done means placement is tested with two screen frames, screen-parameter changes restore the chosen anchor, and Docs/app-dock.md describes the rule.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- macos, swift
- Domain
- desktop
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 52/100