mirror of
https://github.com/outbackdingo/hyprcosmic.git
synced 2026-08-25 14:53:21 +00:00
The hyprcosmic profile disables cosmic-panel, and COSMIC's power applet lives in that panel. Nothing replaced it, so the session had no logout, reboot or shutdown anywhere in it: the only way out was `systemctl reboot` typed into a terminal, which also meant every login-time change cost a reboot to test. hyprcosmic-powermenu is a rofi menu offering lock, suspend, log out, reboot and shut down. It is reached two ways -- $mainMod SHIFT E and a button at the right end of waybar -- and both run the same script, so a click cannot bypass the confirmation a keypress gets. Logging out calls com.system76.CosmicSession.Exit, which is the method the panel applet used and the only one that stops the session's clients in order rather than pulling the compositor out from under them. Reboot and poweroff go straight to systemd; polkit already authorises both for an active local session without a prompt, verified with pkcheck, so no pkexec is involved. Lock uses loginctl, which cosmic-greeter is listening for. Confirmation is asked only for the three that end the session. Lock and suspend undo themselves with a keypress, so a prompt there is pure friction; the other three throw away everything unsaved and are one keystroke away at all times. "No" is listed first so it is the row already selected. The menu entries are plain words rather than Nerd Font glyphs. The bar icon is the only glyph involved, and it comes through generate-config.py, whose whole purpose is that no Private Use Area character is ever typed by hand -- U+F011, confirmed present in the installed JetBrainsMono Nerd Font. rules.css names every module id explicitly, so #custom-power had to be added there too or the button would have rendered with no pill behind it. The script sits under config/bin/ rather than a new top-level directory so that install-assets.sh's audit still covers it: that check refuses to run unless every file under config/ is classified, which is what stops a new file from being silently left uninstalled.
290 lines
11 KiB
JSON
290 lines
11 KiB
JSON
// Waybar configuration for a HyprCosmic session.
|
|
//
|
|
// Waybar's shipped default (/etc/xdg/waybar/config.jsonc) is built entirely
|
|
// around sway/* modules and shows nothing at all under cosmic-comp, so this
|
|
// exists rather than a handful of overrides.
|
|
//
|
|
// Module choices are constrained by what cosmic-comp actually advertises on the
|
|
// Wayland registry, which was checked against a live session:
|
|
//
|
|
// ext/workspaces ext_workspace_manager_v1 -- advertised by stock cosmic-comp.
|
|
// wlr/taskbar zwlr_foreign_toplevel_management_v1 -- NOT in stock
|
|
// cosmic-comp; provided by the HyprCosmic fork's Patch A.
|
|
// Under a stock compositor this module stays empty and the
|
|
// rest of the bar still works.
|
|
// tray Needs a StatusNotifierWatcher. cosmic-panel normally
|
|
// supplies one via cosmic-applet-status-area, and the
|
|
// hyprcosmic profile disables the panel, so waybar hosts the
|
|
// watcher itself here.
|
|
//
|
|
// ICONS. Every glyph below is a \uXXXX escape, never a literal character, and
|
|
// this file is generated from config.jsonc.in for exactly that reason:
|
|
//
|
|
// - These are Private Use Area codepoints. They survive being copied, but
|
|
// anything that re-types rather than copies them silently flattens them to
|
|
// spaces or drops them next to a neighbour, and the damage is invisible in
|
|
// a diff and indistinguishable from a font problem at runtime.
|
|
// - An escape is plain ASCII, so it cannot be damaged that way, and it names
|
|
// the intended glyph instead of leaving a box you have to identify.
|
|
//
|
|
// Every codepoint was checked against the installed JetBrainsMono Nerd Font
|
|
// with `fc-list :charset=<cp>` before use. That check is worth doing rather
|
|
// than copying HyDE's values: HyDE's pulseaudio module uses U+FA80 for the
|
|
// muted state, an old Material Design Icons codepoint that Nerd Fonts v3
|
|
// moved. It is absent from the installed font and would render as tofu, so
|
|
// U+F075F is used instead.
|
|
//
|
|
// NOT INCLUDED, deliberately:
|
|
//
|
|
// backlight The only device is acpi_video0, a firmware stub reporting
|
|
// brightness 49 of max 49 -- permanently 100% -- whose sysfs
|
|
// node is not writable by this user, with brightnessctl absent.
|
|
// The module would render a readout that never changes and a
|
|
// scroll action that never works: visible, plausible, and dead.
|
|
// That is the same failure class as the `pavucontrol` click this
|
|
// file used to carry, and it is not worth re-introducing for a
|
|
// percentage that is always the same number.
|
|
{
|
|
"layer": "top",
|
|
"position": "top",
|
|
"height": 34,
|
|
"spacing": 4,
|
|
|
|
"modules-left": ["ext/workspaces", "wlr/taskbar"],
|
|
"modules-center": ["mpris", "clock", "privacy"],
|
|
"modules-right": [
|
|
"idle_inhibitor",
|
|
"custom/swaync",
|
|
"bluetooth",
|
|
"pulseaudio",
|
|
"network",
|
|
"temperature",
|
|
"cpu",
|
|
"memory",
|
|
"power-profiles-daemon",
|
|
"battery",
|
|
"tray",
|
|
"custom/power"
|
|
],
|
|
|
|
"ext/workspaces": {
|
|
"format": "{name}",
|
|
"on-click": "activate"
|
|
},
|
|
|
|
"wlr/taskbar": {
|
|
"format": "{icon}",
|
|
"icon-size": 18,
|
|
"tooltip-format": "{title}",
|
|
"on-click": "activate",
|
|
"on-click-middle": "close"
|
|
},
|
|
|
|
// Renders nothing at all when no player is running, which is what we want
|
|
// from a centre module: it takes no space until there is something to say.
|
|
// playerctl backs every action here and is installed.
|
|
"mpris": {
|
|
"format": "{player_icon} {dynamic}",
|
|
"format-paused": "{status_icon} <i>{dynamic}</i>",
|
|
"dynamic-order": ["title", "artist"],
|
|
"dynamic-separator": " ",
|
|
"max-length": 40,
|
|
"interval": 1,
|
|
"player-icons": { "default": "\uf001" },
|
|
"status-icons": {
|
|
"playing": "\uf04b",
|
|
"paused": "\uf04c",
|
|
"stopped": "\uf04d"
|
|
},
|
|
"on-click": "playerctl play-pause",
|
|
"on-click-middle": "playerctl previous",
|
|
"on-click-right": "playerctl next",
|
|
"on-scroll-up": "playerctl position 5+",
|
|
"on-scroll-down": "playerctl position 5-",
|
|
"tooltip-format": "{title}\nby {artist}\n{position} / {length}\n\nplayer: {player}"
|
|
},
|
|
|
|
"clock": {
|
|
"format": "{:%a %d %b %H:%M}",
|
|
"tooltip-format": "<tt><small>{calendar}</small></tt>"
|
|
},
|
|
|
|
// Only appears while something is actually capturing. Nothing is ignored:
|
|
// an exception list is how a privacy indicator stops being one.
|
|
"privacy": {
|
|
"icon-spacing": 6,
|
|
"transition-duration": 200,
|
|
"modules": [
|
|
{ "type": "screenshare", "tooltip": true },
|
|
{ "type": "audio-in", "tooltip": true }
|
|
]
|
|
},
|
|
|
|
"idle_inhibitor": {
|
|
"format": "{icon}",
|
|
"format-icons": {
|
|
"activated": "\udb80\udd76",
|
|
"deactivated": "\udb81\udeca"
|
|
},
|
|
"tooltip-format-activated": "Caffeine on -- idling and blanking suppressed",
|
|
"tooltip-format-deactivated": "Caffeine off -- normal power settings apply"
|
|
},
|
|
|
|
// swaync is this session's notification daemon: it owns
|
|
// org.freedesktop.Notifications and is D-Bus activated through
|
|
// swaync.service, so it needs no autostart entry and this module starts it
|
|
// on first contact if nothing else has.
|
|
//
|
|
// It is here because the hyprcosmic profile disables cosmic-panel and
|
|
// COSMIC's notification applet lives in that panel. Without this there is
|
|
// no way to reach notification history at all.
|
|
"custom/swaync": {
|
|
"format": "{icon}",
|
|
"format-icons": {
|
|
"none": "\uf0f3",
|
|
"notification": "\udb80\udc9a",
|
|
"dnd-none": "\uf1f6",
|
|
"dnd-notification": "\uf1f6",
|
|
"inhibited-none": "\uf0f3",
|
|
"inhibited-notification": "\udb80\udc9a",
|
|
"dnd-inhibited-none": "\uf1f6",
|
|
"dnd-inhibited-notification": "\uf1f6"
|
|
},
|
|
"return-type": "json",
|
|
"exec": "swaync-client -swb",
|
|
"on-click": "swaync-client -t -sw",
|
|
"on-click-right": "swaync-client -d -sw",
|
|
"tooltip": true,
|
|
"escape": true
|
|
},
|
|
|
|
// bluez is running with an unblocked hci0. The click target is COSMIC's own
|
|
// settings page rather than blueman or overskride, neither of which is
|
|
// installed here.
|
|
"bluetooth": {
|
|
"format": "\uf293",
|
|
"format-disabled": "\uf294",
|
|
"format-off": "\udb80\udcb2",
|
|
"format-connected": "\uf293 {num_connections}",
|
|
"tooltip-format": "{controller_alias}\n{num_connections} connected",
|
|
"tooltip-format-connected": "{controller_alias}\n\n{device_enumerate}",
|
|
"tooltip-format-enumerate-connected": "{device_alias}",
|
|
"on-click": "cosmic-settings bluetooth"
|
|
},
|
|
|
|
// The click used to be `pavucontrol`, which is not installed here: a button
|
|
// that looked live and did nothing. cosmic-settings ships with the desktop,
|
|
// so it cannot go missing the same way. Scroll and middle-click need no
|
|
// helper -- waybar changes volume itself and wpctl comes with pipewire.
|
|
"pulseaudio": {
|
|
"format": "{icon} {volume}%",
|
|
"format-muted": "\udb81\udf5f",
|
|
"format-bluetooth": "{icon} {volume}%",
|
|
"format-bluetooth-muted": "\udb81\udf5f",
|
|
"format-icons": {
|
|
"headphone": "\uf025",
|
|
"headset": "\uf025",
|
|
"hands-free": "\uf025",
|
|
"phone": "\uf095",
|
|
"car": "\uf1b9",
|
|
"default": ["\uf026", "\uf027", "\uf028"]
|
|
},
|
|
"scroll-step": 5,
|
|
"tooltip-format": "{desc}\n{icon} {volume}%",
|
|
"on-click": "cosmic-settings sound",
|
|
"on-click-middle": "wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle"
|
|
},
|
|
|
|
"network": {
|
|
"format-wifi": "\uf1eb {signalStrength}%",
|
|
"format-ethernet": "\udb80\ude00 wired",
|
|
"format-linked": "\udb80\ude00 {ifname}",
|
|
"format-disconnected": "\udb82\udd2f offline",
|
|
"tooltip-format": "{ifname}: {ipaddr}",
|
|
"tooltip-format-wifi": "{essid} ({signalStrength}%)\n{ifname}: {ipaddr}",
|
|
"on-click": "cosmic-settings network"
|
|
},
|
|
|
|
// Tctl from k10temp, not thermal_zone0. The two read within a degree of
|
|
// each other here, but the hwmon path names the CPU sensor explicitly.
|
|
//
|
|
// It is given as the PCI device's hwmon directory rather than
|
|
// /sys/class/hwmon/hwmon6 because hwmonN numbering is assigned in probe
|
|
// order and is not stable across boots. The PCI address is.
|
|
"temperature": {
|
|
"hwmon-path-abs": "/sys/devices/pci0000:00/0000:00:18.3/hwmon",
|
|
"input-filename": "temp1_input",
|
|
"format": "\uf2ca {temperatureC} C",
|
|
"critical-threshold": 90,
|
|
"interval": 5,
|
|
"tooltip-format": "CPU package: {temperatureC} C"
|
|
},
|
|
|
|
"cpu": {
|
|
"format": "\udb80\udf5b {usage}%",
|
|
"interval": 5
|
|
},
|
|
|
|
"memory": {
|
|
"format": "\udb83\udee0 {percentage}%",
|
|
"interval": 5,
|
|
"tooltip-format": "{used:0.1f}G of {total:0.1f}G"
|
|
},
|
|
|
|
// Backed by tuned-ppd, which owns net.hadess.PowerProfiles on this system.
|
|
"power-profiles-daemon": {
|
|
"format": "{icon}",
|
|
"format-icons": {
|
|
"default": "\uf0e7",
|
|
"performance": "\uf135",
|
|
"balanced": "\uf24e",
|
|
"power-saver": "\uf06c"
|
|
},
|
|
"tooltip-format": "power profile: {profile}",
|
|
"tooltip": true
|
|
},
|
|
|
|
"battery": {
|
|
"states": { "warning": 30, "critical": 15 },
|
|
"format": "{icon} {capacity}%",
|
|
"format-charging": "\uf1e6 {capacity}%",
|
|
"format-plugged": "\uf1e6 {capacity}%",
|
|
"format-icons": [
|
|
"\udb80\udc8e",
|
|
"\udb80\udc7a",
|
|
"\udb80\udc7b",
|
|
"\udb80\udc7c",
|
|
"\udb80\udc7d",
|
|
"\udb80\udc7e",
|
|
"\udb80\udc7f",
|
|
"\udb80\udc80",
|
|
"\udb80\udc81",
|
|
"\udb80\udc82",
|
|
"\udb80\udc79"
|
|
],
|
|
"tooltip-format": "{timeTo}\n{power:0.1f}W",
|
|
"on-click": "cosmic-settings power"
|
|
},
|
|
|
|
"tray": { "icon-size": 18, "spacing": 8 },
|
|
|
|
// Last on the bar, because it is the one button here that can end the
|
|
// session or the uptime and the far corner is the hardest place to hit by
|
|
// accident.
|
|
//
|
|
// It is here for the same reason "custom/swaync" is: the hyprcosmic profile
|
|
// disables cosmic-panel, and COSMIC's power applet lives in that panel.
|
|
// Without this there is no logout, reboot or shutdown anywhere in the
|
|
// session -- the only way out was `systemctl reboot` from a terminal.
|
|
//
|
|
// The click runs the same script as the $mainMod SHIFT E binding rather
|
|
// than calling systemctl here, so the confirmation step cannot be bypassed
|
|
// by using the mouse.
|
|
"custom/power": {
|
|
"format": "\uf011",
|
|
"tooltip": true,
|
|
"tooltip-format": "Lock, suspend, log out, reboot or shut down",
|
|
"on-click": "hyprcosmic-powermenu"
|
|
}
|
|
}
|