feat: add "Windowed fullscreen" toggle for borderless on-Space mode#190
Open
koto9x wants to merge 2 commits into
Open
feat: add "Windowed fullscreen" toggle for borderless on-Space mode#190koto9x wants to merge 2 commits into
koto9x wants to merge 2 commits into
Conversation
Adds a per-user preference that, when enabled, opens the Fullscreen window as a
movable/resizable borderless-style window pinned to the current Space's visible
frame instead of macOS native fullscreen (which animates to a new Space and
hides the menubar and Dock).
- New user default `useWindowedFullscreen` (defaults to false → existing native
fullscreen behavior is unchanged).
- New "Windowed fullscreen (stays on current Space)" toggle in the in-fullscreen
settings popover, alongside the existing Blur/Animate toggles.
- LyricFever.swift Fullscreen Window onAppear branches on the flag:
- off: existing `collectionBehavior = .fullScreenPrimary` + `toggleFullScreen`
- on: borderless styleMask (titled/closable/miniaturizable/resizable +
fullSizeContentView, transparent + hidden titlebar), `.managed`
collectionBehavior, `setFrame(screen.visibleFrame)`. Defensively exits
any restored native-fullscreen state first and disables window
restoration so the styleMask change isn't fought by the system.
- `.windowFullScreenBehavior` is bound to the flag so the green traffic-light
button doesn't pull a windowed session back into native fullscreen.
- Drive-by: album art in FullscreenView is now sized from the GeometryReader
container (max(120, min(columnWidth*0.85, height*0.55))) instead of the
hard-coded 550/700 frame. This is what makes the windowed mode usable when
resized; native-fullscreen sizing on a typical display is effectively
unchanged.
Motivation: native fullscreen forcing a new Space breaks multi-window workflows
(e.g. lyrics-while-coding, lyrics-while-browsing). Windowed-fullscreen behaves
like the gaming "windowed fullscreen" idiom — fills the screen visually, stays
on the current Space, can be moved/resized.
…ative fullscreen Two follow-up polish changes on top of the windowed-fullscreen feature: 1. `Cmd+Ctrl+F` (the canonical macOS toggle-fullscreen shortcut) now toggles native fullscreen on the Lyric Fever Fullscreen window. Because the app is `LSUIElement = true` and has no standard View menu, the OS shortcut has nothing to fire by default; we wire it explicitly in the existing `NSEvent.addLocalMonitorForEvents` block. This is the escape hatch that makes "Windowed fullscreen" non-trapping — a user can be in windowed mode by default and still opt into native fullscreen when they want it (e.g. on a second display), and back out again. 2. Esc-blocking is now conditional: blocked only while the window is NOT in native fullscreen. When the user has entered native fullscreen (via Cmd+Ctrl+F or otherwise), Esc passes through so the platform-standard exit gesture works. In windowed mode the original "sticky" behavior is preserved. Also flips: - `.windowFullScreenBehavior` is now unconditionally `.enabled` (was conditional on the user default). Native fullscreen is always a reachable mode. - `collectionBehavior` in the windowed-fullscreen branch is `.fullScreenPrimary` (was `[.managed]`), which is what allows the new Cmd+Ctrl+F path to actually enter native fullscreen from a windowed-mode session. Default-off invariant is unchanged: when `useWindowedFullscreen` is false the window opens via the existing `.fullScreenPrimary` + `toggleFullScreen(true)` path exactly as before.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds a user-toggleable Windowed fullscreen mode to the Fullscreen view. When enabled, the fullscreen window opens as a movable/resizable borderless-style window pinned to the current Space's visible frame, instead of macOS native fullscreen — which animates to a new Space and hides the menubar and Dock.
Default is off, so existing behavior is preserved 1:1 for current users.
Why
Native fullscreen forcing a new Space breaks common multi-window workflows — lyrics-while-coding, lyrics-while-browsing, lyrics on a second display while the primary stays free. "Windowed fullscreen" is the same idiom most games offer: visually fills the screen, but stays on the current Space and can be moved/resized like any other window.
What changed
UserDefaultStorage.swift— addsuseWindowedFullscreen: Bool = false(macOS-only, persisted via the existing@ObservableUserDefaultpattern).LyricFever.swift— the FullscreenWindow'sonAppearnow branches on the flag:collectionBehavior = .fullScreenPrimary+ the existingtoggleFullScreen(true)path..titled, .closable, .miniaturizable, .resizable, .fullSizeContentView) withtitlebarAppearsTransparent+titleVisibility = .hidden,collectionBehavior = [.managed],setFrame(screen.visibleFrame, display: true),isMovableByWindowBackground = true. If macOS restored prior native-fullscreen state, exits it first viatoggleFullScreen(nil)so the styleMask change can actually land; setsisRestorable = falseso subsequent launches start clean..windowFullScreenBehavioris now bound to the flag (.disabledwhen on,.enabledwhen off), so the green traffic-light button can't pull a windowed session back into native fullscreen.FullscreenView.swift— new toggle in the existing in-fullscreen settings popover (next to Blur surrounding lyrics and Animate on startup):Drive-by: responsive album art
The album-art frame in
FullscreenViewwas hard-coded at 550pt / 700pt. That looks fine at 1920×1080 native fullscreen, but in windowed mode the user can resize the window and the fixed-size art overflows the lyrics column. Changed to derive from the GeometryReader container:Min 120pt so it doesn't disappear at tiny sizes. On a typical native-fullscreen display the resulting size matches the previous hard-codes within ~5%, so the existing experience is effectively unchanged.
Test plan
main(xcodebuildDebug,-skipMacroValidation).Notes
MediaController(bundleIdentifier:)change onmainis independent of this PR — same compile state as base.Localizable.xcstringsif preferred).