Skip to content

dbar: animate hiding the top bar on fullscreen in niri - #3335

Closed
steven12138 wants to merge 2 commits into
duxlabs-dev:masterfrom
steven12138:feat/niri-fullscreen-bar-policy
Closed

steven12138 wants to merge 2 commits into
duxlabs-dev:masterfrom
steven12138:feat/niri-fullscreen-bar-policy

Conversation

@steven12138

@steven12138 steven12138 commented Sep 6, 2026 •

Copy link
Copy Markdown

What this does

On niri, an optional per-bar Hide bar on fullscreen setting slides the top bar out of view when the active window on that output enters fullscreen. It slides back when fullscreen ends. Both transitions use DBar's existing auto-hide animation and the theme's animation duration (including disabled animations). Moving the pointer to the screen edge can reveal the bar while fullscreen.

The option requires Use overlay layer, defaults to off, and does not turn on global auto-hide or change the bar's layer. It preserves the configured exclusive zone, so other windows do not resize during the transition. Frame-hosted bars, islands, and other compositors are unaffected.

This revision ports the feature to the Dux 2.0 DBar layout and current master. It also clears the IPC reveal state when effective auto-hide ends, as requested in the latest review; otherwise a previous bar toggleReveal could prevent hiding on the next fullscreen. The earlier edge-hover and test-embedding review findings remain addressed.

The subsequent review found that fullscreen-only hiding released the bar's exclusive zone. The fix keeps the configured zone when only the fullscreen option is active, while preserving the existing global auto-hide behavior. A regression test covers both cases.

Niri IPC and Wayland toplevels have no shared window ID. Matching uses exact app ID/title on the output, with keyboard focus to disambiguate where possible. Ambiguous matches leave the bar visible. See docs/fullscreen-bar.md for usage and limits.

Validation

  • node --test quickshell/tests/*.test.mjs: 398 passed.
  • make test-qml: Qt 31 passed, lock 38 passed, logic passed.
  • make build: passed; embedded shell excludes tests.
  • git diff --check: passed.
  • make lint-qml could not run in this fresh worktree because Quickshell's VFS .qmlls.ini had not been generated. No new lint result is claimed.
  • Installed the matching patch in local dux-shell 2.0.0-3. A plain dms restart loads the embedded patch, and fullscreen entry hides the top bar while exit restores it in a live single-monitor niri session. The user also confirmed the fullscreen behavior works on their machine.
  • Live pointer-edge behavior and physical multi-monitor behavior on Dux 2.0 have not been checked separately. Exclusive-zone preservation is covered by the new regression test; it has not been measured live.

Checklist

  • Feature is opt-in and documented.
  • Settings search index regenerated.
  • Tests and build pass on current master.
  • Live Dux 2.0 single-monitor fullscreen entry/exit validation.
  • Live Dux 2.0 multi-monitor and pointer-edge validation.

Comment thread quickshell/tests/niri-fullscreen.test.mjs
@bbedward

Copy link
Copy Markdown
Member

/claude review

Comment thread quickshell/Modules/DBar/DBarBody.qml
Comment thread quickshell/tests/niri-fullscreen.test.mjs
@claude

claude Bot commented Sep 15, 2026

Copy link
Copy Markdown
Contributor

Claude review

Two issues: the documented edge-hover reveal is dead in the fullscreen-only path, and the new test files ship inside the dms binary.

  • Edge-hover reveal never fires when only hideOnFullscreen is on — topBarMouseArea.hoverEnabled/enabled still gate on barConfig.autoHide instead of topBarCore.autoHide, quickshell/Modules/DankBar/DankBarBody.qml:1075
  • New scripts/test-*.mjs are not in sync-shell's strip list, so they are embedded into the shipped binary, quickshell/scripts/test-niri-fullscreen.mjs:1

Checked: niri workspace/active-window state fixes (string-vs-numeric key lookups, stale active_window_id preservation, unfocused-output focus flags) all look correct; NiriFullscreen.js matching and its binding dependencies; exclusive-zone preservation; overlay-layer and frame-host gating; toggleReveal IPC guard; settings spec/defaults and regenerated search index; catalogs untouched. Model: claude-opus-5.

@steven12138
steven12138 force-pushed the feat/niri-fullscreen-bar-policy branch from e1a5b67 to ba5842b Compare September 20, 2026 21:04
@steven12138

Copy link
Copy Markdown
Author

Addressed the requested changes and rebased onto the current master:

  • Moved the Node tests to quickshell/tests/*.test.mjs; the current sync-shell staging excludes the entire tests directory, and the embed exclusion test passes.
  • Fullscreen-only hiding now uses the effective topBarCore.autoHide state for edge hover and click-through input, so the pointer edge can reveal the bar when global auto-hide is off.
  • Updated the bar IPC regression fixture and added coverage for toggleReveal during fullscreen auto-hide.
  • Resolved the upstream settings, bar, compositor, and niri service conflicts while preserving the current APIs.

Validation: 19 focused tests pass, the full logic suite passes, Qt tests pass (26/26), settings search index and i18n variant checks pass, git diff --check passes, embed staging contains no tests, and make build succeeds.

@bbedward

Copy link
Copy Markdown
Member

/claude review


property bool autoHide: !barWindow.isIsland && (barConfig?.autoHide ?? false)
readonly property bool autoHide: !barWindow.isIsland && ((barConfig?.autoHide ?? false) || barWindow.fullscreenAutoHide)
onAutoHideChanged: evaluateReveal()

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The IPC reveal state can get stuck after fullscreen ends. With global auto-hide off, run bar toggleReveal while fullscreen and barIpcRevealStates[id] becomes true. When fullscreen ends, autoHide goes false, but nothing clears that state. SettingsData.updateBarConfig only clears it when autoHide: false is written to the config. The next time a window goes fullscreen, ipcReveal is still true, so the bar doesn't hide. Outside fullscreen, toggleReveal also returns BAR_AUTO_HIDE_DISABLED, so IPC can't reset it; only hovering the bar can.

Fix: clear the state when the effective auto-hide turns off.

Suggested change
onAutoHideChanged: evaluateReveal()
onAutoHideChanged: {
if (!autoHide)
SettingsData.setBarIpcReveal(barConfig?.id ?? "", false);
evaluateReveal();
}

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Fixed in 6f84847. The Dux 2.0 DBar now clears barIpcRevealStates when effective auto-hide turns off, before evaluating reveal again. Added a regression test for the fullscreen exit/re-entry transition; the full Node and QML suites pass.

@claude

claude Bot commented Sep 25, 2026

Copy link
Copy Markdown
Contributor

Claude review

Both earlier findings are fixed (edge hover now gates on topBarCore.autoHide, and the tests moved to quickshell/tests). One new issue:

  • The IPC reveal state isn't cleared when fullscreen auto-hide ends, so the next fullscreen window doesn't hide the bar, quickshell/Modules/DankBar/DankBarBody.qml:659

Checked: NiriFullscreen.js matching and missing-data guards, NiriService active-window/snapshot fixes, the fullscreenAutoHide gating (overlay layer, frame, island, overview), exclusive-zone preservation, the toggleReveal IPC guard and dankBarItems lookup, the settings toggle and I18n strings, and the search index. Catalogs are untouched. Model: claude-opus-5-5.

@steven12138
steven12138 force-pushed the feat/niri-fullscreen-bar-policy branch from ba5842b to 6f84847 Compare October 29, 2026 04:43
@steven12138 steven12138 changed the title dankbar: add opt-in fullscreen auto-hide on niri dbar: animate hiding the top bar on fullscreen in niri Oct 29, 2026
@purian23

Copy link
Copy Markdown
Collaborator

/claude review

layer.enabled: false

property bool autoHide: (!barWindow.isIsland || barWindow.islandOverlay) && (barConfig?.autoHide ?? false)
readonly property bool autoHide: ((!barWindow.isIsland || barWindow.islandOverlay) && (barConfig?.autoHide ?? false)) || barWindow.fullscreenAutoHide

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

With fullscreenAutoHide ORed into autoHide, surfaceExclusiveZone (line 805) drops to -1 whenever a fullscreen window shows up. It already does that for topBarCore.autoHide && !reserveExclusiveWhenAutoHidden, and that guard is only true for frame-hosted bars, which this feature excludes. So every fullscreen enter/exit releases and then re-reserves the bar's zone. The other windows on that output relayout both times. That contradicts the PR description and docs/fullscreen-bar.md ("preserves the configured exclusive zone, so other windows do not resize").

Fix: keep the zone while hiding for fullscreen. In the line 805 condition, use (barConfig?.autoHide ?? false) (the effective global auto-hide) instead of topBarCore.autoHide, or add && !barWindow.fullscreenAutoHide.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Fixed in bd9f7a8. Fullscreen-only hiding now preserves the bar exclusive zone; the prior global auto-hide behavior is unchanged. Added a regression test for both cases. The matching Dux 2.0 package is installed locally, and fullscreen entry/exit works after a plain dms restart. Node: 398 passed; QML and package build passed.

@claude

claude Bot commented Oct 29, 2026

Copy link
Copy Markdown
Contributor

Claude review

The port to DBar fixes the earlier findings: IPC reveal is cleared, edge hover uses the effective auto-hide, and the tests are in quickshell/tests. One new issue:

  • Fullscreen hiding drops the exclusive zone to -1, so windows on that output resize on every fullscreen enter and exit, against the PR's stated behavior, quickshell/Modules/DBar/DBarBody.qml:917

Checked: the fullscreenAutoHide gating (island, frame, overlay layer, overview), NiriFullscreen.js matching and its binding dependencies, NiriService active-window/focus changes, the toggleReveal IPC guard through dankBarItems, onAutoHideChanged IPC reset, the settings toggle and I18n strings, and the search index. Catalogs are untouched. Model: claude-opus-5-5.

@steven12138

Copy link
Copy Markdown
Author

Superseded by #4000, which carries the Dux 2.0 DBar port and addresses the review findings, including the exclusive-zone regression. Continuing review there; keeping this PR closed for its review history.

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.

3 participants