diff --git a/README.md b/README.md index b61ef79..a70b484 100644 --- a/README.md +++ b/README.md @@ -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 diff --git a/modules/BarIcon.qml b/modules/BarIcon.qml index ec0d99a..371dd6a 100644 --- a/modules/BarIcon.qml +++ b/modules/BarIcon.qml @@ -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; diff --git a/modules/BarLabel.qml b/modules/BarLabel.qml index fa4bdf8..cdf416f 100644 --- a/modules/BarLabel.qml +++ b/modules/BarLabel.qml @@ -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; diff --git a/modules/BarSection.qml b/modules/BarSection.qml index 0fb07a8..f248b80 100644 --- a/modules/BarSection.qml +++ b/modules/BarSection.qml @@ -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; diff --git a/modules/Flyout.qml b/modules/Flyout.qml index e67c86f..80ad34d 100644 --- a/modules/Flyout.qml +++ b/modules/Flyout.qml @@ -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 diff --git a/modules/FlyoutState.qml b/modules/FlyoutState.qml index 489001e..e2e51b3 100644 --- a/modules/FlyoutState.qml +++ b/modules/FlyoutState.qml @@ -5,4 +5,5 @@ QtObject { property bool visible: false property string text: "" property real itemX: 0 + property var screen: null } diff --git a/modules/Tray.qml b/modules/Tray.qml index 3860620..abe87f2 100644 --- a/modules/Tray.qml +++ b/modules/Tray.qml @@ -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;