The session loads its own copy of the plugin from the Hyprland config, a separate dlopen with its own decorations - so iterating with a dev build on top of it drew two frames on every window. Grep the path back out of $XDG_CONFIG_HOME/hypr rather than hardcoding it: a home-manager-installed copy lives at a /nix/store path that changes on every rebuild. -R, since those config files are symlinks into the store. hyprctl plugin list reports no path, so the config is the only place to read it from. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
95 lines
3.8 KiB
Markdown
95 lines
3.8 KiB
Markdown
# hypr-chrome
|
|
|
|
A Hyprland plugin that draws a chamfered HUD-style border frame behind each
|
|
window, expanded past the window's own edges, with a floating title bar
|
|
hanging off the top-left corner. The frame's corners are chamfered by an
|
|
amount inferred from the window's own border rounding, so the border peeking
|
|
out around a rounded window's corners reads as a matching diagonal cut rather
|
|
than a hard rectangular corner. Border color tracks Hyprland's own
|
|
active/inactive border color live, gradients included.
|
|
|
|
## Config
|
|
|
|
```
|
|
plugin {
|
|
hyprchrome {
|
|
enabled = true # bool
|
|
extent = 12 # int, px the border extends past the window edge
|
|
follow_hyprland_border_color = true # bool, use Hyprland's own active/inactive border color instead of active_color/inactive_color below
|
|
active_color = 0xFFD063FF # focused-window border color, used when follow_hyprland_border_color is false
|
|
inactive_color = 0xFF6C6C6C # unfocused-window border color, used when follow_hyprland_border_color is false
|
|
titlebar_height = 8 # int, px height of the floating title bar
|
|
titlebar_text_size = 12 # int, px font size of the title bar's text
|
|
titlebar_font = sans-serif # string, passed to cairo_select_font_face
|
|
}
|
|
}
|
|
```
|
|
|
|
`active_color`/`inactive_color` take the same syntax as Hyprland's own
|
|
`general:col.active_border` — a single color, or several plus an optional
|
|
angle for a gradient:
|
|
|
|
```
|
|
active_color = rgba(ff0000ff) rgba(00ff00ff) 45deg
|
|
```
|
|
|
|
## Installing
|
|
|
|
```sh
|
|
hyprpm add https://git.mgaction.town/darman/hypr-chrome.git
|
|
hyprpm enable hypr-chrome
|
|
```
|
|
|
|
`hyprpm` builds the plugin from source against your own installed Hyprland,
|
|
using the `build` commands declared in `hyprpm.toml` (the same `cmake`
|
|
invocations as below).
|
|
|
|
### NixOS
|
|
|
|
`flake.nix` exposes `packages.x86_64-linux.default`, built against
|
|
`pkgs.hyprland` from this flake's own `nixpkgs` input (with Hyprland's own
|
|
compiler/stdenv, for ABI correctness). Add this repo as a flake input and
|
|
set `inputs.hypr-chrome.inputs.nixpkgs.follows = "nixpkgs"` (your own
|
|
system's nixpkgs input) so it's built against the exact Hyprland your
|
|
system runs - then add `inputs.hypr-chrome.packages.${system}.default`
|
|
directly to your `wayland.windowManager.hyprland.plugins`
|
|
(NixOS/home-manager) list. The package installs as `lib/libhypr-chrome.so`
|
|
(the `lib<pname>.so` convention that module derives its path from
|
|
automatically) even though the plain `hyprctl`/`hyprpm` path above uses
|
|
the unprefixed `hypr-chrome.so`.
|
|
|
|
## Building
|
|
|
|
Requires the Hyprland headers/libs (`hyprland`, `libdrm`, `libinput`,
|
|
`libudev`, `wayland-server`, `xkbcommon`, `pixman-1`, cairo, etc.), ABI-locked
|
|
to the exact Hyprland build you'll load the plugin into. A pinned Nix flake
|
|
dev shell provides all of it:
|
|
|
|
```sh
|
|
nix develop
|
|
cmake -B build -S .
|
|
cmake --build build
|
|
```
|
|
|
|
This produces `hypr-chrome.so` at the repo root (not inside `build/`, so the
|
|
`hyprctl`/`buildAndLoad.sh` commands below can find it directly).
|
|
|
|
## Developing
|
|
|
|
Load/reload the plugin into a running Hyprland session:
|
|
|
|
```sh
|
|
hyprctl plugin load "$(pwd)/hypr-chrome.so"
|
|
hyprctl plugin unload "$(pwd)/hypr-chrome.so"
|
|
```
|
|
|
|
`buildAndLoad.sh` chains build + reload for iteration. Hyprland's plugin
|
|
loader never fully unmaps a `.so` once `dlopen`'d, so reloading the same path
|
|
just re-serves the old (possibly stale) mapping — the script works around
|
|
this by copying each build to a uniquely-suffixed filename before loading it
|
|
and cleaning up prior copies. It also unloads any copy your own Hyprland
|
|
config loads (found by grepping `$XDG_CONFIG_HOME/hypr` for a `hypr-chrome`
|
|
`.so` path), since that one is a separate `dlopen` that would draw a second
|
|
frame on every window. It hardcodes an absolute checkout path at the top;
|
|
check it matches your checkout before running it.
|