Skip to content

niri: bar hidden for the overview keeps its full input region, making an openOnOverview bar unclickable #3000

Description

@Username2481632

Compositor

Niri

Distribution

Arch Linux

Select your Installation Method

Distro Packaging

Was this your original Installation method?

Yes

dms doctor -vC

Click to expand

 System Health Check
                    
──────────────────────────────────────

  System
    ● Operating System ····· Arch Linux
      └─ ID: arch, Version: rolling, Arch: amd64
    ● Architecture ········· amd64
    ● Display Server ······· Wayland
      └─ WAYLAND_DISPLAY=wayland-1

  Versions
    ● DMS CLI ·············· dms v1.5.0-222-ge54be7d1
      └─ /usr/bin/dms
    ● Quickshell ··········· Quickshell 0.3.0 (revision , distributed by Arch Linux)
      └─ /usr/bin/qs
    ● DMS Shell ············ v1.6-beta
      └─ /run/user/1000/danklinux-shell/dbe768dcd7cf010b

  Installation
    ● DMS Configuration ···· Found
      └─ /run/user/1000/danklinux-shell/dbe768dcd7cf010b
    ● shell.qml ············ Present
      └─ /run/user/1000/danklinux-shell/dbe768dcd7cf010b/shell.qml
    ○ Install Type ········· Unknown
      └─ /run/user/1000/danklinux-shell/dbe768dcd7cf010b

  Compositor
    ● Hyprland ············· 0.56.1
      └─ /usr/bin/hyprland
    ● niri ················· 26.04
      └─ /usr/bin/niri
    ● Sway ················· 1.12
      └─ /usr/bin/sway
    ● labwc ················ 0.20.1
      └─ /usr/bin/labwc
    ○ Active ··············· niri
    ● Background Blur ······ Supported
      └─ Compositor supports ext-background-effect-v1

  Quickshell Features
    ● Polkit ··············· Available
      └─ Authentication prompts
    ● IdleMonitor ·········· Available
      └─ Idle detection
    ● IdleInhibitor ········ Available
      └─ Prevent idle/sleep
    ● ShortcutInhibitor ···· Available
      └─ Allow shortcut management (niri)
    ● BackgroundBlur ······· Available
      └─ Background blur API support in Quickshell

  Optional Features
    ● accountsservice ······ Available
      └─ User accounts
    ● power-profiles-daemon  Available
      └─ Power profile management
    ● logind ··············· Available
      └─ Session management
    ● cups-pk-helper ······· Available
      └─ Printer management
    ○ I2C/DDC ·············· No monitors detected
      └─ External monitor brightness control
    ● qt6-imageformats ····· Installed (5 formats)
      └─ Formats: WebP, TIFF, GIF, JP2, ICNS (/usr/lib/qt6/plugins/imageformats:/usr/lib64/qt6/plugins/imageformats)
    ● kimageformats ········ Installed (4 formats)
      └─ Formats: AVIF, HEIF, JXL, EXR (/usr/lib/qt6/plugins/imageformats:/usr/lib64/qt6/plugins/imageformats)
    ● Terminal ············· ghostty, foot
    ● Network ·············· iwd + systemd-networkd
      └─ iwd + systemd-networkd detected. Using iwd for Wi-Fi association and networkd for IP/DHCP.
    ● matugen ·············· Installed
      └─ Dynamic theming
    ● dgop ················· Installed
      └─ System monitoring
    ● cava ················· Installed
      └─ Audio visualizer
    ○ khal ················· Not installed
      └─ Calendar events
    ○ danksearch ··········· Not installed
      └─ File search
    ○ dankcalendar ········· Not installed
      └─ Calendar app
    ● fprintd ·············· Installed
      └─ Fingerprint auth

  Config Files
    ● settings.json ········ Present
      └─ /home/micha/.config/DankMaterialShell/settings.json
    ○ clsettings.json ······ Not yet created
      └─ /home/micha/.config/DankMaterialShell/clsettings.json
    ● plugin_settings.json · Present
      └─ /home/micha/.config/DankMaterialShell/plugin_settings.json
    ● session.json ········· Present
      └─ /home/micha/.local/state/DankMaterialShell/session.json
    ● dms-colors.json ······ Present
      └─ /home/micha/.cache/DankMaterialShell/dms-colors.json

  Services
    ● dms.service ·········· enabled, active
    ● greetd ··············· enabled

  Environment
    ○ QT_QPA_PLATFORMTHEME · qt6ct
    ○ QS_ICON_THEME ········ Not set
    ● XDG_MENU_PREFIX ······ Not set
      └─ Dolphin file associations and 'Open with…' dialog may be empty. Set XDG_MENU_PREFIX=plasma- in your compositor's environment block.
      → https://danklinux.com/docs/dankmaterialshell/cli-doctor#xdg-menu-prefix

  Fonts
    ● Normal Font ·········· Inter Variable
      └─ Available
    ● Monospace Font ······· Fira Code
      └─ Available

  ──────────────────────────────────────
  1 warning(s), 38 ok

Description

With two bars on the same screen edge — a normal always-visible Main Bar, and a second bar configured visible: false + openOnOverview: true — the second bar renders correctly in the niri overview but receives no pointer input at all. No hover highlight, no clicks, nothing.

Flipping Enable Bar off and back on for the second bar in Settings makes it fully clickable, and it still hides correctly outside the overview. The fix does not survive a dms restart, so it has to be redone every boot.

The cause is not in the overview bar. It is the Main Bar, which keeps a full-size input region while it is hidden for the overview.

Root cause

Modules/DankBar/DankBarBody.qml:772

readonly property bool showing: effectiveVisible && (topBarCore.reveal || inOverviewWithShow || !topBarCore.autoHide)

inputMask.showing drives maskThickness (:774), which is the item the layer surface's mask: Region is built from (DankBarWindow.qml:81) — i.e. the committed wl_surface.set_input_region.

The || !topBarCore.autoHide term makes showing unconditionally true for any non-auto-hide bar, including when topBarCore.reveal is false. There is exactly one situation where a visible non-auto-hide bar has reveal == false — the niri overview hide at :972-973:

if (CompositorService.isNiri && NiriService.inOverview)
    return hoverReveal || popoutPinsReveal || revealSticky || ipcReveal;

So during the overview the Main Bar's content is translated off-surface by topBarSlide (:1056-1057) and draws nothing, while its input region stays the full bar thickness across the whole screen width. An invisible surface that still swallows every click.

Note that || !topBarCore.autoHide is redundant in every other case: :975 already returns true for a visible non-auto-hide bar. It only ever changes the result in the overview case, where it is wrong.

Why the overview bar loses, and why the toggle fixes it

Both bars are WlrLayer.Top, anchored to the same edge, so their input regions overlap exactly. Layer surfaces are hit-tested most-recently-created first — Smithay LayerMap::layer_under (desktop/wayland/layer.rs:156-172) iterates layers_on(layer).rev(), and niri's contents_underlayer_surface_under (src/niri.rs:3327-3366) does the same, with the comment at :3292 that input ordering must match render ordering. The ordering slot is fixed at the get_layer_surface request (src/handlers/layer_shell.rs:44), and destroying + recreating a layer surface re-appends it as the new topmost. niri also hit-tests Top-layer surfaces unconditionally while the overview is open (:3403-3427).

Bar creation order is deterministic — ShellCore.qml:32-39 sorts by String(a.id).localeCompare(String(b.id)). A generated id like bar1777511502650 sorts before default, so the overview bar's surface is created first and the Main Bar's second, putting the Main Bar on top of it.

Toggling Enable Bar flips only barConfig.enabled, which is not part of _barLayoutStateJson (ShellCore.qml:27-31), so only that one Loader.active cycles: the overview bar's layer surface is destroyed and recreated, landing on top of the Main Bar, and clicks start working. Nothing about the bar's own config or mask changed — only when its surface was created. That is why the workaround is a pure no-op on disk and why it is undone by anything that rebuilds the bars in sorted order (a dms restart, or recreateBarSurfaces() on monitor hotplug).

This also predicts the behaviour flips purely on id ordering — a second bar whose id happened to sort after default would work from boot with no toggling.

Suggested fix

Drop the || !topBarCore.autoHide term:

readonly property bool showing: effectiveVisible && (topBarCore.reveal || inOverviewWithShow)

Checked against the four cases: visible non-auto-hide bar outside the overview → reveal true, unchanged; overview bar in the overview → inOverviewWithShow true, unchanged; visible: false bar → effectiveVisible false, unchanged; Main Bar in the overview → now correctly drops to the 1px mask instead of holding the full strip.

One thing worth considering alongside it: the mask should probably shrink only once the slide-out finishes, the way revealSettle (:888) already defers hides for clickThrough, so a fast overview toggle doesn't drop input a frame early.

Also minor, same block: maskThickness: showing ? barThickness : 1 (:774) means a hidden bar still claims the top 1px row of the screen. Once the overview bar is stacked above the Main Bar (i.e. after the workaround), it takes that row's clicks away from the Main Bar.

Expected Behavior

A bar hidden for the niri overview should release its input region while hidden, so an openOnOverview bar underneath it receives clicks. The overview bar should be clickable from a cold start, with no Settings toggling and no dependence on bar-id sort order.

Steps to Reproduce

  1. niri. Keep the default Main Bar as-is (top, visible: true, autoHide: false, openOnOverview: false).
  2. Add a second bar, also on top, set visible: false and openOnOverview: true, and give it at least one clickable widget (e.g. CPU usage, which opens the process list).
  3. Make sure its generated id sorts before default — any bar<timestamp> id does.
  4. Restart dms (or reboot) so the surfaces are built in sorted order.
  5. Open the overview. The second bar renders exactly as configured.
  6. Hover and click one of its widgets → no hover highlight, no popout, nothing.
  7. Settings → Dank Bar → second bar → Enable Bar off, then on.
  8. Open the overview and click the same widget → works. Its config on disk is unchanged.
  9. Restart dms → back to step 6.

Error Messages/Logs

Nothing is logged; both surfaces behave exactly as their bindings specify.

Direct confirmation on a live session, clicking the same pixel each time via wlrctl pointer:

  • Overview open, both bars in their normal config: cursor over the second bar's CPU widget → plain arrow, no hover highlight; click → nothing opens.
  • dms ipc call bar hide id default (Main Bar visible: falseeffectiveVisible false → showing false → mask drops to 1px), nothing about the second bar touched: same pixel → hover highlight appears and the cursor becomes a pointer; click → process list opens.
  • dms ipc call bar reveal id default to restore: back to dead.

So the blocking surface is the Main Bar's input region, not anything about the second bar.

Screenshots/Recordings

Before/after screenshots of the hover state at the identical pixel are available if useful — happy to attach.


Reproduced on Arch with the AUR dms-shell-git package, dms v1.5.0-222-ge54be7d1 (shell v1.6-beta), Quickshell 0.3.0, niri 26.04. DankBarBody.qml:770-774 and :960-976, DankBarWindow.qml:80-81 and ShellCore.qml:23-41 are byte-identical at master adcafbcc, so this is not fixed on current master.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Planned PRTag an open issue or describe your idea before implementationbugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions