69 Commits

Author SHA1 Message Date
felixzsh 4e7fae1d43 ci: use github generated release notes 2026-08-28 10:56:09 -05:00
felixzsh 26ee2cf10b ci: use native release contributors 2026-08-28 10:41:01 -05:00
felixzsh 9f75048323 chore: bump to version 1.8.4 2026-08-28 10:20:43 -05:00
felixzsh 3dcc657716 ci: attribute release contributors 2026-08-28 10:18:46 -05:00
felixzsh f3cb662498 fix(ui): correct key visualizer QML syntax 2026-08-28 09:54:26 -05:00
Felix Sanchez 71bc30a0ec Merge pull request #2 from rfmyrick/fix/v1.8.1-key-capture
fix(capture): restore key overlays after hardening
2026-08-28 09:43:43 -05:00
felixzsh 6dda827973 fix(capture): restore key overlay updates 2026-08-28 09:42:46 -05:00
felixzsh 3a1380c59f chore: bump to version 1.8.3 2026-08-26 18:54:43 -05:00
felixzsh 48a8020910 fix(ui): clear stale combo when capture stops updating 2026-08-26 18:47:29 -05:00
felixzsh 48af33c2a7 fix(security): use POSIX-only checks in runtime dir validation 2026-08-26 18:47:29 -05:00
felixzsh 9fbdd2b8cf chore: bump to version 1.8.2 2026-08-26 18:34:35 -05:00
felixzsh 68a75c2ab5 fix(ui): auto-size config panel to content width
The config panel used a fixed contentWidth of Style.space(250), the
narrowest of all omarchy panels. With a wider font the Filter row (label
"Filter" plus the All keys / Bindings buttons) no longer fit and the
label overlapped the buttons. Derive contentWidth from the Filter row's
implicit width (label + gap + buttons) plus padding and borders, capped
to the available screen via fittedContentWidth, so the panel grows or
shrinks with the font.
2026-08-26 18:03:51 -05:00
felixzsh a7357e3840 fix(ui): declare debugFont and debugFontMetrics before use
debugFont was referenced by debugText and debugFontMetrics before its
declaration, causing "ReferenceError: debugFont is not defined" on panel
load. Move both the debugFont property and the debugFontMetrics FontMetrics
block above the debug overlay so all references resolve in declaration
order; qualify the last use as root.debugFont.
2026-08-26 17:06:57 -05:00
Bob Myrick 7b3fa2f0b3 fix(capture): restore key overlays after hardening
Validate the systemd runtime path using the process effective UID instead of shell ownership probes that fail in Hyprland's embedded Lua runtime. Keep Quickshell FileView watchers live by updating their fixed, private state paths in place and seed both state files when the hook loads.
2026-08-25 21:20:05 -04:00
felixzsh ee988956bb ci: detect scoped conventional commits and fix changelog range
Workflow missed commits like fix(security): ... because git log
--pretty=format:"%H %s" without trailing newline truncated the last
commit in RANGE (v1.8.0..HEAD), causing "No relevant conventional
commits" for v1.8.1. Switch to --format="%H %s" which handles
newlines correctly and supports optional scope and breaking ! via
regex ^(feat|fix)(\([^)]+\))?!?:
2026-08-24 14:40:55 -05:00
felixzsh ae917e7351 chore: bump to version 1.8.1 2026-08-24 14:19:30 -05:00
felixzsh 89cd794708 fix(security): fail-closed XDG_RUNTIME_DIR and harden state file writes
Remove predictable /tmp/omarchy-key-visualizer.json fallback that exposed
captured key combinations and allowed symlink redirection when
XDG_RUNTIME_DIR is absent. Introduce fail-closed behaviour: disable
capture if XDG_RUNTIME_DIR is missing, equals /tmp, is not absolute,
not owned or not 0700.

Add secure_write with O_NOFOLLOW mitigation (test ! -L), atomic
tmp+rename and chmod 600 to prevent world-readable leaks and TOCTOU
races. Apply same guard to QML statePath/superPath and Panel nudge
writes (umask 077, chmod 600, symlink check).

Fixes security review at 790b07c0c9:
key-visualizer.lua:15-17,141-145
2026-08-24 14:00:12 -05:00
felixzsh 790b07c0c9 ci: allow manual release dispatch 2026-08-20 10:51:46 -05:00
felixzsh ed387f72b8 ci: auto generate changelog 2026-08-20 10:44:22 -05:00
felixzsh 7c58be5dce chore: bump to version 1.8.0 2026-08-20 10:40:07 -05:00
felixzsh d586678d1d refactor: shared re-position mechanism
complement
2026-08-20 10:39:32 -05:00
felixzsh aa11f5f7a2 feat: drag and drop keyvisualizer 2026-08-20 10:39:32 -05:00
felixzsh deec43c0ff feat: add D-pad fine-tune nudges below the position selector
Add unit-by-unit manual position control via a four-button D-pad
(left, up/down together, right) under the position dropdown. Nudges
persist as offsetX/offsetY in the shared config and are silently
clamped to the screen edges, so a move that would cross a border is
ignored. Selecting a preset position resets the manual offset. While
the display is hidden, a nudge flashes a directional arrow preview so
the move direction is visible even with no keys on screen.

Co-Authored-By: opencode <opencode@anthropic.com>
2026-08-20 10:39:27 -05:00
felixzsh aa038ec49e fix: linger config in seconds, not miliseconds 2026-08-19 12:04:31 -05:00
felixzsh 2ee5f88933 fix: persists config after reboots 2026-08-17 17:56:49 -05:00
felixzsh f4564110f7 docs: point the install section at the published GitHub URL
The README is for people installing the plugin, not for development: use
https://github.com/felixzsh/omarchy-key-visualizer as the add source,
drop the author-only validate tip, and reword the stale-component note
for end users. Adds the update command for good measure.
2026-08-12 13:13:12 -05:00
felixzsh a74372c5c4 docs: update preview image 2026-08-12 11:52:18 -05:00
felixzsh 525b120881 docs: simplify the README
Trim the technical detail (state file paths, reload pipeline internals,
scoring formulas) and move the combo mode GIF next to the preview image.
Also fixes stale references: the bar widget section now says Filter and
six placements, and the How it works table is gone.
2026-08-12 11:45:35 -05:00
felixzsh 44d9185bf9 docs: add combo mode GIF to the README 2026-08-12 11:42:22 -05:00
felixzsh a9ee70391b chore: bump to version 1.7.2 2026-08-12 11:37:06 -05:00
felixzsh 82e60ba360 fix: drop modifier-only chords from the history
Releasing a chord made only of modifiers (Super, Super Ctrl Shift...) is
'mods of nothing': it scores nothing in combo mode and now no longer
lingers or occupies a history row either. The mods still show live while
held, which is the useful feedback; on release the entry is removed
instantly instead of entering its linger window.
2026-08-12 11:31:43 -05:00
felixzsh e447c69817 chore: bump to version 1.7.1 2026-08-12 11:18:19 -05:00
felixzsh fb7266153e docs: remove mouse capture form roadmap 2026-08-12 11:16:51 -05:00
felixzsh f705ccb37f fix: keep only complete combos in the history
The Lua emits on every key-down, so a chord pressed key-by-key without
releasing arrives as growing states (Super, Super Ctrl, Super Ctrl
Shift, Super Ctrl Shift 1). The history treated each one as a separate
combo, filling the stack with partial noise. Now a growing state while
the chord is still held (a strict superset of the current entry) updates
the entry in place instead of pushing a history row; only the complete
combo at release ever enters the history.
2026-08-12 10:59:09 -05:00
felixzsh 0a4aa59ee1 feat: add combo mode with combo counter, score and escalating effects
A 'Combo mode' toggle turns the display into a game-style counter.
Chords containing a modifier (Super/Ctrl/Alt/Shift/Menu/AltGr) are
combos: they build a combo counter, apply a multiplier (x2 at 5, x3 at
10 ... x8 at 50) and escalate the effects. Plain characters and shifted
chars typed alone are hits: +10 score only, they never touch the combo
counter or its window. Scoring: hit = 10, combo = (20 + 15*(mods-1) +
5*(keys-1)) * multiplier.

Counted once per physical chord on the Lua's empty payload (release),
so the intermediate growing emits of a chord never double-count. The
banner (COMBO 12 x3 - 3,450) sits below the history for bottom
positions and above it for top positions, with a floating +N pop per
press. Effects scale with modifiers and chain length: banner pulse,
hue shift, screen shake (up to 5px), continuous hue cycling at 10+
combos and a constant subtle vibration at 20+. The combo resets after
comboWindowMs (2s) without a new combo; the score accumulates for the
shell session.

Also fixes the README Behavior section: the history bullet was never
applied (a failed multi-edit call), now restored alongside the combo
mode docs. Manifest bumped to 1.7.0.
2026-08-12 10:51:01 -05:00
felixzsh 58cca5ec4f chore: rename mode label to filter 2026-08-12 10:27:17 -05:00
felixzsh d6c608374c feat: add stacking history with fading older entries
The last historyCount combos (1-5, default 1) stack on screen instead
of vanishing: each new combo pushes the previous one down the stack and
every older entry fades step by step (entryOpacity gradient). The stack
direction follows the position by default — top positions grow downward
(newest on top), bottom positions grow upward (newest at the bottom
edge) — and is not configurable. The panel gains a History NumberField
for the count.

Middle positions (center-left/center-right/center-center) were removed
from the dropdown and any leftover config value is folded into the
bottom row. With lingerMs 0 entries never expire, so the stack keeps
the last few combos on screen until newer ones push them out.

Manifest bumped to 1.6.0.
2026-08-12 10:06:40 -05:00
felixzsh d1afc68b70 chore: add seconds text to linger label 2026-08-12 08:53:21 -05:00
felixzsh 05e52219c5 change preview image 2026-08-11 18:16:25 -05:00
felixzsh 4b87cac3c8 Add author to the manifest for the Quattro contract
The documented plugin manifest contract (docs/omarchy-shell.md) and every
first-party manifest include author; the publishing validation rejects a
manifest without it.
2026-08-11 17:56:03 -05:00
felixzsh 076bef95f5 Add a Preview section with the screenshot to the README 2026-08-11 17:37:36 -05:00
Felix Sanchez c68d3644f8 add preview 2026-08-11 17:36:41 -05:00
felixzsh 21f9f3fb57 Measure each chip with FontMetrics.advanceWidth
The shared TextMetrics had its text set imperatively inside the width
bindings, which went stale from the third chip on — every container
collapsed to single-char width, so Super/Space/Backspace were illegible
in combos of 3+. FontMetrics.advanceWidth(text) is a stateless method,
so every chip gets its own correct width.
2026-08-11 17:31:36 -05:00
felixzsh 3d42d0e726 Fix the Linger row layout: fixed-size container, stable field
The hint slot is always reserved on the right (fixed width), the field
keeps a constant width, and the row has a fixed height with everything
vertically centered — the hint no longer sits at the top-right corner
and the field no longer resizes when it appears. Hint text is body size
like the other menu labels.

Align the never-hide hint to the SpinBox center

Anchoring the hint to the row container left it offset whenever the
row's implicit height differed from the field's rendered height. Anchor
to lingerField.field (the NumberField exposes the SpinBox) so the hint
always sits exactly beside the field.

Place the never-hide hint right next to the field

Anchor the hint to the SpinBox's right edge with the field's own height
and vertical center, so it reads as part of the control instead of a
floating label at the row edge.

Rebuild the Linger row as a plain RowLayout

NumberField is a Column (label above the field), and anchoring the hint
to its field alias left the text unanchored when the alias did not
resolve, dumping it at (0,0) over the label. A RowLayout puts label,
field, and hint in the flow, vertically centered by Layout.alignment —
no anchors, no aliases. The field comes first, so the hint never moves
it.

Move the Linger label above the field, Position-style

Label above (caption, bold, darkened — identical to the Dropdown label),
the field pinned to the left half, and the never-hide legend on the
right half via a fill-width spacer, so it appears only at 0 without
moving the field.
2026-08-11 17:19:17 -05:00
felixzsh 0e9adf5a6c Show a 'never hide' hint next to Linger when it is 0
When lingerMs is 0 (always show), a muted caption appears on the right of
the field so the opt-in is visible at a glance; the field shrinks to make
room. Config unchanged.
2026-08-11 16:52:37 -05:00
felixzsh e7232840cb Add a Linger NumberField to the menu
Native qs.Ui.NumberField (SpinBox) for lingerMs: mouse wheel, +/- buttons
and typing, 0-10000ms in 500ms steps, writing config.json like Mode and
Position so the display updates live. 0 selects the always-show behavior
from the previous commit.
2026-08-11 16:23:34 -05:00
felixzsh a5c31aaef7 lingerMs 0 keeps the last combo on screen until the next key
The hide timer only starts (and only clears) when lingerMs > 0, so 0
means the last full combo stays visible until the next key replaces it
— the keyviz-video look, as an explicit opt-in rather than the previous
behavior where 0 hid instantly.
2026-08-11 16:23:00 -05:00
felixzsh a22c8eaa78 Replace the position buttons with a native Dropdown (9 placements)
The three Position buttons (Bottom/Top/Center) overlapped the label in
the menu's width. Use qs.Ui.Dropdown with the full 3x3 grid — top /
middle / bottom by left / center / right — the display panel already
positions all of them.
2026-08-11 15:45:40 -05:00
felixzsh 7e079de572 Fix the bar glyph: \uF030C parsed as \uF030 + "C"
JS \u takes exactly 4 hex digits, so \uF030C rendered U+F030 (fa-camera
in the Nerd Font's Font Awesome range) followed by a literal C — a camera
with a trailing c, exactly what was on the bar. U+F030C is in PUA-A and
needs a UTF-16 surrogate pair: \uDB80\uDF0C. Also correct the comment
name (it is md-keyboard, not md-keyboard_outline).
2026-08-11 15:41:22 -05:00
felixzsh 840e7c2e13 Point README folder references at the renamed repo 2026-08-11 15:25:34 -05:00