A center-anchored module is mounted twice: the copy that is drawn, and a
zero-size placeholder holding its place in the flow beside the anchor.
findPanelWidget returned whichever registered first, and that order is
not stable across a live bar reconfiguration, so a panel could open
anchored to the invisible copy -- mispositioned, with the drawn slot
never lighting up and switchPanelFrom unable to find it again.
The mark was also always 55% of the slot, which fits an icon but
underlines only a fraction of a text label, and runs the full height of a
multi-line module on a vertical bar. Modules can now say how long the
mark should be along the bar; anything that does not answer keeps the old
proportion.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
A bar surface is built per monitor, so a widget in the layout is live once
per screen — but an IPC target only ever routes to the handler that
registered first. `omarchy.indicators refresh` therefore reached a single
bar, and since indicators only re-read their state on that signal, the
other screens kept showing a stale reminder count, tmux alert, or DND
state until the next reload. Clock and system-update refreshes had the
same reach.
Let the bar resolve every live instance of a widget id and relay the call
to all of them.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Each `bash -lc` starts a login shell that re-sources the profile
(mise activation, /etc/profile.d) on every invocation — ~16 forks per
call versus ~2 for `bash -c` — which taxes every menu/panel/launcher
action the shell shells out for. The session already exports PATH and
env to the shell, so omarchy commands resolve fine under `bash -c`.
Switch the internal/omarchy-owned spawns (theme+background switches,
brightness, monitor scaling, DNS, lock/fingerprint, keyboard-layout
probe, voxtype status, and the `:`/printf state-file writes) to
`bash -c`. Leave `bash -lc` on the sites that run user-configurable
commands (custom bar-widget exec, menu provider/guard scripts,
launcher scan commands, configurable idle/screensaver command), where
a user's command may rely on their login environment.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
With initial workspace tracking disabled, windows naturally open on the active workspace. Remove the explicit Hyprland workspace dispatch and let shell actions, shell restarts, and presentation terminals launch directly.
Position the bar by dragging (or click-and-holding) empty bar space
toward a screen edge, with a ghost slab previewing the target edge.
With drag for position and double-click for transparency, the bar
config panel, its inline gear button, and the omarchy-launch-bar-settings
CLI are no longer needed.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The bar supports switching between transparent and opaque. That means we
can't use an opaque surface for it; if we did, it would be unable to
reliably render as transparent when needed.
This fixes a visual glitch where the background of a transparent bar
would flicker, particularly during mouse hover.
Bar-widget panels (audio, bluetooth, network, power, monitor) used to be
toggled via their own per-plugin IpcHandler targets. Quickshell resolves
duplicate targets first-handler-wins, so after a plugin or bar reload the
stale handler of the destroyed widget instance kept claiming the target
and the hotkeys went dead.
The shell root's IpcHandler lives outside the reload cycle, so summon,
hide, and toggle now go through `omarchy-shell shell toggle <plugin>`
and the shell routes to the live widget instance via the bar's slot
registry. Panel plugins that are also panel/overlay/menu kinds keep
using the panel loader path. Failures to find a live widget are logged
so a widget missing from the bar layout stays diagnosable.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The slot registry is about to become the routing table for panel
hotkeys, so it has outgrown its debug-only name.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Clock and daytime were near-duplicates with different click semantics
(clock toggles between formats on left-click and opens the timezone
selector on right-click; daytime was non-pressable with a hover tooltip).
Standardize on clock, since it's the more capable of the two.
- Delete widgets/daytime.qml and its FirstPartyWidgets entry.
- Migrate shell-defaults.json, shell.qml's builtin fallback, Bar.qml's
fallback bar config, and the settings panel's builtin defaults so the
center anchor and center-section entry both reference "clock".
- Rename the daytimeSettings form to clockSettings and rephrase
"Tooltip format" → "Alternate format (click to toggle)" so the field
label matches clock's actual behavior.
- Update the gallery dropdown options and bar/README docs.
ModuleButton was a near-duplicate of WidgetButton with the same text /
active / keepSpace / tooltip / fontSize / fixedWidth / fixedHeight /
pressed signal surface, only differing in that it closed over the
enclosing root via QML's scoping rules instead of taking `bar` as a
property. Switch CustomCommandModule onto WidgetButton with
`bar: root` so we have one bar button component to maintain.
CustomCommandModule.update() in Bar.qml called root.parseModuleJson(raw)
but the function was removed in 3b970068 (the indicator split). Any
custom command module emitting waybar-style JSON would have crashed on
first poll.
Hoist the helper into Util so both call sites — the bar's custom command
module and BarIndicator.extractData — share one definition.