cmux-next: background and Chief picture settings (video playback, battery, keep clear of panes, picture motion)
Phase 5 of the backgrounds plan: the settings Leo approved (through the coordinator). It's one schema PR, so the Air Blue coordinator clears WINDOW once.
Stacked: this branch is next-batch/leo-backgrounds (feat-cmux-next plus #21743, which carries #21709 and #21731, plus #21720 and #21740/#21737) with two commits on top. Review only fb08d69c804 (background video and framing) and 9d8f72c2ab3 (Chief picture motion). It needs #21709's framing and #21720's video players.
What changes
| Key | Choices | Default |
|---|---|---|
appearance.backgroundVideo | Play / Only While cmux Is Active / Still Picture | Play |
appearance.backgroundVideoOnBattery | Keep Playing / Pause | Keep Playing (Low Power Mode already pauses) |
appearance.backgroundAvoidPanes | on/off | on |
home.chiefPictureMotion | Always / On Hover / Never | On Hover (Never under Reduce Motion) |
- Rows sit under Appearance > Window Background (
BackdropPlaybackSettingsSchema). They're agent-settable likeappearance.background. - Parsing:
BackdropPlaybackConfigParserusesConfigFieldReader, so a bad value keeps the default and adds a diagnostic.SettingsAppliercopies the result intoDesignSettings.backdropPlayback. - Video (
BackdropVideoView):- Still Picture never plays. It counts as unseen, so its decoder is given back after the phase 2 minute and the first frame stays.
- Only While cmux Is Active follows
NSApp.isActive(didBecome/ResignActive). - Pause on battery follows
BackdropPower, a small IOKit power-source watcher on the main run loop. - Settings changes apply live through
ObservationStream.
- Framing (
WindowMaterialView): with Keep Paintings Clear of Panes off, art frames itself in the whole window. The toggle applies live. - Chief pictures (
home.chiefPictureMotion, a Home > Chief Pictures row, agent-settable):- Pages get the motion as
data-picture-motionon<html>, carried with the theme (WebTheme.pictureMotion), the same waydata-status-indicatorsis.ChiefPictureMotion.effectivemakes it Never under Reduce Motion. - The web
Avatarshows a GIF or animated WebP as its first frame, drawn once to a still. It moves only when the setting is Always, or while the pointer is over it when it's On Hover. - The native Home header shows the first frame unless the setting is Always. It follows the setting and Reduce Motion live.
- The sidebar tile is always a still square copy (
squared()now covers animated pictures too), so a non-square GIF is no longer stretched there. The tile is a 20 pt icon, where motion is only noise. - Native hover animation in the header isn't wired: the header view is vendored MessagesLab, so On Hover shows the still there.
- Pages get the motion as
- CmuxNextApp: 4 source lines down against base (no App changes in this commit).
WINDOW (settings schema)
Settings schema: 4 new keys. Air Blue coordinator, please clear.
- Exports not hand-edited:
schemas/settings/settings-schema.json, the MDM docs and the defaults snapshot are regenerated by the base-autofix bot (regenerate-settings-exports.sh), per that script. - Not in this PR:
- built-in video ids in
appearance.background, because there are no built-in videos yet; the value grammar change waits for the first one - the "Adjust Background…" catalog action, which needs an App handler, and the App is at its cap; phase 6's Settings button covers it for now
- built-in video ids in
Strings
14 new keys, all 21 locales, in CmuxNextSettings/Localizable.xcstrings. It reuses the existing settings.group.windowBackground and settings.choice.always, onHover and never.
Tests
CmuxNextSettingsTests/BackdropPlaybackSettingTests:- defaults
- every value parses
- bad values keep the default and add a diagnostic
- the rows offer every choice with the right defaults, and agents may set them
CmuxNextAppTests/VideoWallpaperTests.thePlaybackSettingsHoldTheVideo:- Still holds the video and gives back the decoder
- Only While Active follows the app
- Pause follows battery and power
CmuxNextAppTests/BackdropArtFramingTests: with avoidPanes off, the art frames to the whole window, and back.chiefPictureMotionParsesAndHasItsRow: parse, a bad value, the row and agent-settable.ChiefPictureMotionTests:- first-frame stills for an animated picture
- a still picture is left untouched
- Reduce Motion makes it never move
ChiefPictureFilesTests.anAnimatedPictureGetsAStillTile: square and non-square GIFs both get a still square PNG.- Web
test/home-chief-picture-motion.test.tsx(3/3 pass): always, never, hover in and out, and a PNG is never held back.
Verification
lint-ios-package-conventions.sh: clean.- Swift: not built locally. The parent heads are in the next-batch swift-test run (https://github.com/manaflow-ai/cmux/actions/runs/39142433675). This commit will go in the next one.
- Not dogfooded.
Changelog
Added: Settings for video backgrounds (play, only while cmux is active, or a still picture; pause on battery), for keeping paintings clear of the panes, and for when animated Chief pictures move.
🤖 Generated with Claude Code