fix flyouts on multiple monitors, update mds

This commit is contained in:
Damocles 2026-04-12 15:30:35 +02:00
parent ab2eb2578e
commit 75a94628ad
7 changed files with 36 additions and 11 deletions

View file

@ -10,13 +10,18 @@ exactly when you should be most suspicious.
## "Features"
- Bar with workspaces, clock, tray, and a pile of widgets the AI insisted on adding
- Home Manager module (probably works, has not been tested in a controlled environment)
- Bar with workspaces, window title, clock, tray, and a regrettable number of widgets
- Niri IPC integration — workspace indicator, focused window title, power menu with `niri msg action quit`
- Context menus for tray icons with submenu support, because the robot watched celestia-shell do it and got jealous
- Per-module accent colors that change based on state (battery goes red when it's dying, bluetooth goes blue when connected, volume dims when muted — genuinely useful, by accident)
- OSD overlay for volume and brightness changes — works with niri hotkeys, not just the bar
- Screen corner rounding — tiny overlay windows that draw quarter-circle masks, configurable via `screenRadius` (set to 0 if you prefer your corners sharp and your desktop ugly)
- Weather via wttrbar with configurable arguments and rich HTML tooltips
- Power menu with lock, suspend, logout, reboot, shutdown — no more `wlogout` dependency
- Flyout tooltips that actually filter by screen on multi-monitor setups, which only took three attempts to get right
- Home Manager module with stylix integration, per-module enable/disable, and a theme system that hot-reloads
- treefmt + nixfmt for formatting, because even AI slop deserves consistent indentation
- Checks via `nix flake check` (the irony of testing AI garbage is not lost on anyone)
- Context menus for tray icons, implemented in a separate window per icon because the
shared flyout window was "suspected of being less responsive" — a diplomatic way of
saying it was bad
## Installation
@ -70,14 +75,14 @@ programs.nova-shell.modules = {
battery = false; # see above, but for power
temperature = false; # what you don't measure can't alarm you
disk = false; # the number will only make you anxious
wlogout = false; # living on the edge
wlogout = false; # if you enjoy living dangerously without a logout button
};
```
Full list of things you can disable: `tray`, `windowTitle`, `clock`,
`notifications`, `mpris`, `volume`, `bluetooth`, `backlight`, `network`,
`powerProfile`, `idleInhibitor`, `weather`, `temperature`, `cpu`, `memory`,
`disk`, `battery`, `wlogout`.
Full list of things you can disable: `workspaces`, `tray`, `windowTitle`,
`clock`, `notifications`, `mpris`, `volume`, `bluetooth`, `backlight`,
`network`, `powerProfile`, `idleInhibitor`, `weather`, `temperature`, `cpu`,
`memory`, `disk`, `battery`, `wlogout`.
### Theme
@ -117,6 +122,17 @@ Full list of theme keys and their defaults:
| `barSpacing` | `12` | Gap between modules (px) |
| `moduleSpacing` | `4` | Icon-to-label gap within a module (px) |
| `radius` | `4` | Corner radius for flyouts and menus (px) |
| `screenRadius` | `15` | Screen corner rounding, 0 to disable (px) |
### Weather
Wttrbar arguments are configurable. The default is `["--nerd"]` which gives
you nerd font weather icons, which is the only acceptable way to display
meteorological data.
```nix
programs.nova-shell.weatherArgs = [ "--nerd" "--location" "Berlin" ];
```
### Systemd service

View file

@ -1,4 +1,5 @@
import QtQuick
import Quickshell
import "." as M
Text {
@ -17,6 +18,7 @@ Text {
if (hovered && root.tooltip !== "") {
M.FlyoutState.text = root.tooltip;
M.FlyoutState.itemX = root.mapToGlobal(root.width / 2, 0).x;
M.FlyoutState.screen = QsWindow.window?.screen ?? null;
M.FlyoutState.visible = true;
} else if (!hovered && root.tooltip !== "") {
M.FlyoutState.visible = false;

View file

@ -1,4 +1,5 @@
import QtQuick
import Quickshell
import "." as M
Text {
@ -17,6 +18,7 @@ Text {
if (hovered && root.tooltip !== "") {
M.FlyoutState.text = root.tooltip;
M.FlyoutState.itemX = root.mapToGlobal(root.width / 2, 0).x;
M.FlyoutState.screen = QsWindow.window?.screen ?? null;
M.FlyoutState.visible = true;
} else if (!hovered && root.tooltip !== "") {
M.FlyoutState.visible = false;

View file

@ -1,4 +1,5 @@
import QtQuick
import Quickshell
import "." as M
Row {
@ -10,6 +11,7 @@ Row {
if (hovered && root.tooltip !== "") {
M.FlyoutState.text = root.tooltip;
M.FlyoutState.itemX = root.mapToGlobal(root.width / 2, 0).x;
M.FlyoutState.screen = QsWindow.window?.screen ?? null;
M.FlyoutState.visible = true;
} else if (!hovered && root.tooltip !== "") {
M.FlyoutState.visible = false;

View file

@ -8,7 +8,7 @@ PanelWindow {
required property var screen
visible: M.FlyoutState.visible
visible: M.FlyoutState.visible && M.FlyoutState.screen === root.screen
color: "transparent"
WlrLayershell.layer: WlrLayer.Overlay

View file

@ -5,4 +5,5 @@ QtObject {
property bool visible: false
property string text: ""
property real itemX: 0
property var screen: null
}

View file

@ -2,6 +2,7 @@ import QtQuick
import QtQuick.Layouts
import Quickshell
import Quickshell.Services.SystemTray
import "." as M
RowLayout {
@ -34,6 +35,7 @@ RowLayout {
if (hovered && tip) {
M.FlyoutState.text = tip;
M.FlyoutState.itemX = iconItem.mapToGlobal(iconItem.width / 2, 0).x;
M.FlyoutState.screen = QsWindow.window?.screen ?? null;
M.FlyoutState.visible = true;
} else if (!hovered) {
M.FlyoutState.visible = false;