Commit Graph
350 Commits
Author SHA1 Message Date
David Heinemeier HanssonandClaude Fable 5 f1237e1962 Drive media play-order off MPRIS signals instead of polling
The media service ran a 500ms repeat timer calling syncPlayingOrder() for
the whole session — two CPU wakeups a second even with nothing playing.
syncPlayingOrder only depends on the set of MPRIS players and each
player's isPlaying state, both of which the Mpris service already signals.

Replace the timer with onPlayersChanged (players appearing/disappearing)
plus an Instantiator that connects isPlayingChanged for each live player,
and a Component.onCompleted for the initial sync.

Verified with a test MPRIS player: play/pause and player add/remove all
update the active player with no periodic timer.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-20 08:33:00 -07:00
David Heinemeier HanssonandClaude Fable 5 ad023413c6 Derive the network bar pill from the native Networking service
The pill was populated by polling omarchy-network-status (previously
every 3s, then 10s). Derive kind/signalStrength directly from the
Quickshell.Networking service instead: wired-connected → ethernet
(preferred, matching the default-route device), else a connected Wi-Fi
network → wifi with its signal, else disconnected. The service's
properties are change-notified, so the pill updates on connect/
disconnect and signal changes with no polling and no subprocess.

Removes the last periodic poll from the bar; the label/frequency pill
fields were write-only and are dropped.

Verified live: pill tracks ethernet → disconnected → ethernet in real
time as the wired device goes down and up.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-20 07:56:43 -07:00
David Heinemeier HanssonandClaude Fable 5 a64d895a02 Spawn shell subprocesses with bash -c instead of bash -lc
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>
2026-07-19 22:46:27 -07:00
David Heinemeier HanssonandClaude Fable 5 4d630c9f30 Stop polling monitor/network state on an idle desktop
The monitor panel polled `omarchy-monitor-state` every 5s (26 forks per
call) and the network panel polled `omarchy-network-status` every 3s,
both with `running: true` rather than gating like the sibling panels.

Monitor: gate the poll on `opened` (brightness/scale are only shown in
the open panel, which already refreshes on open) and drive the bar glyph
from Quickshell.screens instead of the polled display list, so monitor
count stays correct without polling.

Network: the bar pill needs live-ish state, so keep polling but at 10s
instead of 3s. (Deriving the pill from the native Networking service
would remove the poll entirely; left as a follow-up since it needs Wi-Fi
state testing.)

Idle fork rate drops ~20/s to ~14/s.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-19 22:46:27 -07:00
David Heinemeier HanssonandClaude Fable 5 f619c397f2 Make status indicators event-driven instead of polling
The indicators widget broadcast a refresh every 2s, fanning out to four
status subprocesses (nightlight, idle, reminder, screen-recording), and
NightLight/StayAwake each ran an additional 5s poll. On an idle desktop
this was the dominant source of process churn (~33 of ~53 forks/sec in a
VM). The state-changing commands already push `omarchy.indicators
refresh` over IPC, so the polling was redundant.

Drop the 2s broadcast and the two 5s timers; indicators now refresh at
startup and on the IPC push. Also fix three callers that pushed to the
wrong target `Indicators` instead of `omarchy.indicators` (screen
recording, notification silencing, and the omarchy-shell help example) —
those pushes silently failed and only appeared to work because the poll
masked them.

Idle fork rate drops ~53/s to ~20/s.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-19 22:46:27 -07:00
David Heinemeier HanssonandClaude Fable 5 ca4b0b3b61 Stop polling the background symlink every 100ms
The background plugin ran a 100ms Timer that spawned a readlink
subprocess ~10x/sec for the life of the shell, purely to notice
wallpaper changes. Wallpaper updates already arrive over IPC
(omarchy-theme-bg-set calls `background set`, omarchy-theme-set calls
`background themeTransition`), and the initial wallpaper is read once
in Component.onCompleted, so the poll was redundant.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-19 22:46:27 -07:00
David Heinemeier HanssonandClaude Fable 5 e96163c075 Give glyph notifications with bodies the large icon slot
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-19 21:17:04 -07:00
David Heinemeier HanssonandClaude Fable 5 54d79d9d16 Fix screen flash when waking from sleep into the unlock screen
The lock service arms a 5s blank timer whenever the screen locks, and
input at the lock screen re-arms it. Closing the lid sprays pointer
noise over the lock surface, so the timer was routinely armed right
before suspend, froze mid-countdown, and fired moments after resume --
blanking the freshly woken unlock screen under the user.

Guard the timer with a wall-clock check: if far more time elapsed than
the interval, the countdown slept through a suspend, so take a fresh
run-up instead of blanking. This also blanks the lock screen 5s after
an untouched resume.

Two accomplices made the flash worse and hid the real bug:

- The clamshell watcher's 2s poll fired an unconditional global DPMS
  enable whenever no external monitor was active, relighting any blank
  within 2 seconds (lock-screen blanking never stuck on undocked
  laptops) and racing the resume modeset. Recovery now only wakes
  displays when it actually re-enables one.

- Every keystroke at the lock screen dispatched a redundant DPMS
  enable via omarchy-system-wake, forcing extra modesets in the
  fragile just-resumed DRM state. Brightness "on" now skips the
  dispatch when every active display is already lit.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-19 19:42:18 -07:00
7721228319 shell: handle CTRL+BACKSPACE to clear filter (#6307)
* emoji panel: handle CTRL+BACKSPACE to clear filter

* shell: handle CTRL+BACKSPACE to clear filter in all search overlays

* Indentation fix for pull request finding

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

* menu filters: align keyboard editing with Qt standard shortcuts

* menu filters: extract shared filter-editing helpers

* Potential fix for pull request finding

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

* potential fix for pull request findings

* Only treat filter edit keys as edits when they change the text

Backspace/Ctrl+U on an empty filter no longer calls setFilter(""),
which was resetting the list selection back to the top. This also lets
the menu's empty-filter Backspace fall through to goBack() with any
modifier held, as it did before the Util extraction.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: David Heinemeier Hansson <david@hey.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-07-19 17:49:16 -07:00
David Heinemeier Hansson d4d1b518e0 Remove redundant Hyprland launch wrapper
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.
2026-07-19 17:36:34 -07:00
David Heinemeier HanssonandClaude Fable 5 12dc7ae558 Shrink lock screen password dots to fit the field
Long passwords used to overflow the input field and clip with no
feedback that typing was still registering. Scale the dot size and
letter spacing down as the password grows, like macOS, so every
keystroke stays visible.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-19 11:03:00 -07:00
David Heinemeier HanssonandClaude Fable 5 0f2f3f11cb Remember power profile choices per power source across reboots
Explicit profile selections from the power panel or menu are now saved
under an ac/battery key in ~/.local/state/omarchy/powerprofiles and
reapplied on boot and on plug/unplug. Only successful, user-made
selections are persisted, so the performance/balanced defaults still
apply when nothing has been chosen.

All entry points key off the same power signal, UPower's OnBattery:
the shell reads it natively and omarchy-powerprofiles-set autodetect
queries it via busctl. This replaces the sysfs online checks, which
disagreed with the shell on desktops without power_supply entries and
lagged behind plug events on some USB-C laptops.

Plug/unplug switching moves from the udev rule into the shell's battery
service, which already receives UPower's debounced state changes, so
the udev rule and its settle-sleep workaround are gone.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-19 09:33:23 -07:00
David Heinemeier Hansson 7b5c915c8c Clear bar move outline on release 2026-07-18 21:23:09 -07:00
David Heinemeier Hansson 6742adce3d Focus weather city input on return 2026-07-18 21:19:14 -07:00
David Heinemeier Hansson be1aab859d Prevent weather icon flicker 2026-07-18 21:19:10 -07:00
David Heinemeier Hansson c7952c980f Synchronize weather hero icon 2026-07-18 21:11:52 -07:00
David Heinemeier HanssonandClaude Fable 5 96bb617a9c Match Mullvad hosts by suffix
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-18 12:56:46 -07:00
David Heinemeier HanssonandClaude Fable 5 9aa1dcd664 Drag the bar to move it, drop the config panel
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>
2026-07-18 11:44:35 -07:00
David Heinemeier Hansson 66cdec78c2 Align bar settings control spacing 2026-07-18 10:56:19 -07:00
David Heinemeier Hansson 73e5968c64 Show context in polkit prompt 2026-07-17 17:45:29 -07:00
David Heinemeier Hansson 182330465a Simplify omarchy-bar into a bar-settings and bar-plugin split
The omarchy-bar command had grown three overlapping ways to inspect the
bar (show/layout/list/options, plus selected/active/available/widgets
aliases) and mixed layout mutation in with bar-level settings. Untangle
it into two focused commands:

- omarchy-bar keeps only the bar-level settings that write shell.json:
  use, reset, position, transparent, and settings. reset now delegates
  to `use omarchy.bar` rather than duplicating the del(.bar.id) write.
- omarchy-bar-plugin owns all layout mutation: add, move, remove, set,
  and replace, with the placement flags and jq resolve/anchor helpers.
  `omarchy bar plugin ...` routes here via the dispatcher.

Drop the inspection commands entirely: the layout is visible on the bar,
the config is shell.json, and widget/option ids come from
`omarchy plugin list`. Nothing consumed the show output programmatically
except tests. This also removes omarchy-bar-position, whose jq write was
a duplicate of `omarchy bar position`.

Strip environment-invariant guards (require_command, require_omarchy_path)
that defended against jq or OMARCHY_PATH being absent — neither happens on
a real system. Keep the user-input validation (--section/--index) and the
atomic shell.json write.

Update callers (service install/remove, refresh-shell, plugin-clone,
plugin enable), keybindings, the menu, tests, and docs to the new split.
2026-07-17 16:28:17 -07:00
David Heinemeier Hansson f8fec7cccf Tighten compact status icon spacing 2026-07-17 16:17:49 -07:00
David Heinemeier Hansson 8211b86ac6 Restore compact status icon spacing 2026-07-17 16:15:01 -07:00
David Heinemeier Hansson 22791803ed Align vertical bar widgets to the icon grid 2026-07-17 16:03:49 -07:00
David Heinemeier Hansson 6e3b69b8da Standardize bar icon geometry 2026-07-17 15:20:55 -07:00
David Heinemeier Hansson fe48e83222 Repair Tailscale authorization flow 2026-07-17 10:20:08 -07:00
David Heinemeier Hansson 39756d485d Synchronize weather location updates 2026-07-16 21:54:57 -07:00
David Heinemeier Hansson 7b824b6e1b Fix saving typed weather locations 2026-07-16 21:23:32 -07:00
David Heinemeier HanssonandClaude Fable 5 5044e711a0 Let the weather panel be pinned to a chosen location
The weather widgets asked wttr.in to geolocate by IP, which lands on
whatever city the ISP registers its address block under -- Downey when
you're in Malibu. Now the location can be set explicitly:

* Click the location in the weather panel to search via open-meteo
  geocoding, pick a suggestion (disambiguated by region), and it sticks.
  The X next to the field returns to IP auto-detect, as does committing
  an empty search.

* State lives in ~/.local/state/omarchy/settings/weather.json as
  {name, latitude, longitude}, owned by the new omarchy-weather-location
  command (bare call prints the current location, --set/--clear write).
  The panel watches the file, so hand edits apply live.

* Stored coordinates make wttr.in and open-meteo exact. Open-meteo also
  now supplies current conditions alongside the daily forecast it
  already served, which fills the panel within a second of a location
  change instead of waiting out wttr.in's multi-second responses; wttr
  results still win once they land. Failed wttr fetches retry instead
  of sitting stale until the next refresh cycle.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-16 14:46:56 -07:00
David Heinemeier Hansson 47f3074e4e Fix launcher application icon resolution 2026-07-15 17:45:27 -07:00
David Heinemeier HanssonandGitHub d25abba046 Merge pull request #6221 from kevinmcconnell/systray-action-fix
Fix bar plugin array guards
2026-07-14 11:05:22 -07:00
Kevin McConnell d5492db404 Fix panel array guards
The `Bar` uses a `Repeater` when building out the models. This has the
effect of marshalling the configuration, and causing JSON arrays to
become sequence wrappers.

A couple of the plugins had been checking for the existence of array
values with `Array.isArray`, which fails for the sequence wrappers,
causing the values to be ignored. This breaks associated functionality
(the "hide" and "pin" actions in the systray had stopped working, as had
exit node selection in Tailscale).

Switching the guards to use `instanceof Array` works correctly for
sequence values (as well as arrays).
2026-07-14 15:36:43 +01:00
Kevin McConnell be595c72ad Prevent using an opaque surface for bar
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.
2026-07-14 10:00:19 +01:00
David Heinemeier Hansson cb8ab2d9f4 Properly render tray icons 2026-07-13 09:56:20 -07:00
David Heinemeier Hansson aabae6fffe Group all the omarchy-bar bins together 2026-07-08 11:49:56 -07:00
David Heinemeier HanssonandClaude Fable 5 c4b1e33669 Route the weather toggle through the shell target too
Weather wraps its panel in a BarWidget that only exposed togglePanel(),
so it couldn't ride the new shell-routed hotkey path and was left on the
stale-prone per-plugin target. Expose open/close/opened on the wrapper
(open maps to the panel's hotkey path so the center hover reveal stays
suppressed) and switch omarchy-notification-weather to the new syntax.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-07 09:18:03 -07:00
David Heinemeier HanssonandClaude Fable 5 e1cdc9005e Route panel hotkeys through the shell IPC target so they survive reloads
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>
2026-07-07 09:17:54 -07:00
David Heinemeier HanssonandClaude Fable 5 6bb3cb666b Rename debugModuleSlots to moduleSlots
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>
2026-07-07 09:17:37 -07:00
David Heinemeier Hansson af828481b9 Give it a little more time
Felt too abrupt at 3s
2026-07-04 12:08:34 -07:00
David Heinemeier HanssonandClaude Fable 5 60e0a2a0cd Simplify clipboard watcher lifecycle with pdeathsig
Replace the three-layer process management (trap cleanup, PPID-polling
watchdog subshell, /proc-scanning reaper) with kernel-level lifetime
binding: each wl-paste watcher is spawned under setpriv --pdeathsig TERM,
so it dies with the shell no matter how the shell exits.

- Delete watch.sh: the shell now spawns both watchers directly as
  declarative Process commands instead of a wrapper script with traps
  and a 1s polling loop
- Delete init.sh: reaping stale watchers from a crashed pre-pdeathsig
  shell is a single pkill at startup
- Collapse capture.sh's dual stream/snapshot modes: wl-paste forwards
  arguments to its watch command, so the mime rides along as $1 instead
  of an env var, letting both modes share one emit_image function
- Turn the six-branch image mime chain into a loop

Net: two fewer files, three fewer runtime processes, and the watch-mode
capture tests now exercise the same argument protocol the shell uses.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-02 21:32:30 -07:00
David Heinemeier Hansson 055ffaccd4 Split omarchy-plugin into siblings and consolidate bar config into omarchy-bar
omarchy-plugin mixed plugin lifecycle, clone/edit, and bar-layout mutation.
The bar layout was mutated by two separate engines (an embedded Python
mutate_bar here and jq in omarchy-config-shell-bar), each with its own
manifest walker.

- omarchy-plugin is now a ~220-line router; clone and edit move to
  omarchy-plugin-clone and omarchy-plugin-edit, matching the existing
  plugin-{source,add,update,remove,available,validate,scan} sibling pattern
- omarchy-config-shell-bar is replaced by omarchy-bar, the single bar engine
  (show/layout/list/options/use/reset/add/move/remove/set/replace/position/
  transparent/settings) with one jq pipeline; the Python mutate_bar and its
  python3 dependency are gone
- omarchy-plugin-catalog is the shared manifest scanner used by omarchy-bar
  (widget/option enumeration, add validation) and omarchy-plugin-clone
  (source enumeration), replacing three find|jq re-implementations
- service install/remove and refresh-shell call omarchy-bar; docs and tests
  updated to the new command surface
2026-07-02 11:10:24 -07:00
David Heinemeier Hansson 738821c3ab Fix clipboard watcher lifecycle 2026-07-02 11:09:42 -07:00
David Heinemeier Hansson beff26d8e0 Replay recent notification history 2026-06-29 15:19:32 -05:00
David Heinemeier Hansson 6ef0c0192b Resolve launcher device icons 2026-06-29 15:04:57 -05:00
David Heinemeier Hansson 89615a526d Render Omarchy menu icon with Omarchy font 2026-06-29 14:12:36 -05:00
David Heinemeier Hansson fed2fd8e3d Fix notification expire timeout being treated as seconds instead of milliseconds 2026-06-29 13:24:04 -05:00
David Heinemeier Hansson b9f2d41e86 Add clipboard history Home End navigation 2026-06-29 12:58:04 -05:00
David Heinemeier Hansson 472b5cd557 Share pointer movement gate across menus 2026-06-29 11:56:21 -05:00
David Heinemeier Hansson a3f8c494e3 Ignore stationary pointer hover in clipboard 2026-06-29 11:44:31 -05:00
David Heinemeier Hansson a0abb1e0d1 Ignore stationary pointer hover in launcher 2026-06-29 11:40:31 -05:00