Commit Graph
825 Commits
Author SHA1 Message Date
Ryan Hughes e54648dfd5 Match Omarchy menu border to Walker 2026-05-14 02:25:05 -04:00
Ryan Hughes 0e135bbb75 Integrate omarchy menu into shell 2026-05-14 02:25:05 -04:00
Ryan Hughes 7d2745b6a6 Refine quickshell bar and Noctalia compatibility 2026-05-14 02:21:48 -04:00
Ryan Hughes 5086654d51 Hide Wi-Fi manager button when no Wi-Fi station is present
On ethernet-only machines (no wl* device) the button was offering to
open a tool the user can't usefully act on.
2026-05-14 02:21:48 -04:00
Ryan Hughes ece9267995 Show network connection details and gracefully handle iwd-only setups
Network panel now polls 'ip route get 1.1.1.1' for the active interface
and renders a key/value grid with IP/CIDR, gateway, link speed +
duplex (ethernet) or signal/freq/bitrate (Wi-Fi). One bash script
collects everything in TSV.

Wi-Fi list now works on Omarchy's default iwd+impala stack: when
nmcli isn't installed, falls back to 'iwctl station <dev> get-networks'
and parses the connected/SSID/signal/security columns. The list is
hidden entirely when no Wi-Fi station device exists (ethernet-only
machines).

Right-click on the bar widget and the bottom 'Open Wi-Fi manager
(Impala)' button both run omarchy-launch-wifi directly (was wrapped
in extra OMARCHY_PATH= env that wasn't actually doing anything).
2026-05-14 02:21:48 -04:00
Ryan Hughes 0b271d3ab1 Show row close button on every known bluetooth device
Was gated on isConnected; users with paired-but-disconnected devices
(or devices Quickshell hasn't flagged as connected yet) saw no button
at all. Now shows on every known device. Action follows state:
connected -> disconnect, otherwise -> forget. Tooltip label flips to
match.
2026-05-14 02:21:48 -04:00
Ryan Hughes 6c84bc93da Drop row tooltip; add explicit disconnect button on connected devices
Bluetooth rows no longer hover-show a tooltip — clicking to connect
or pair is self-evident from the layout. Connected rows now ignore
their own click and surface a small × button on the right that
disconnects (with its own tooltip + urgent-color hover affordance).
Right-click still forgets the device.
2026-05-14 02:21:48 -04:00
Ryan Hughes 84e8a42813 Theme tooltips inside popups
PillButton's attached ToolTip is now a styled instance — uses the
widget's foreground color for text + border and a configurable
tooltipBackground (defaults to a near-black, overridable to
bar.background). No more stock OS chrome inside our popups.

Bluetooth panel passes bar.background/foreground through to its
header pills and replaces the row tooltip with the same themed style.
2026-05-14 02:21:48 -04:00
Ryan Hughes ab701f7c49 Show connection state per bluetooth device
Each device row is now a two-line entry: name on top, status on the
bottom (Connected · 80%, Connecting…, Pairing…, Disconnecting…, Failed,
Available · click to pair, or Paired). Status text and the bluetooth
icon both color-code by state — connected/active draws in foreground,
idle in dim, failed in urgent.

Pending click attempts arm a 10s timer; if the device hasn't reached
the expected state by then the row flips to 'Failed' with an urgent
color so you can see the connect attempt didn't take. State change
listeners clear the pending flag the moment the device actually
connects or pairs.

Hover tooltips and right-click-to-forget moved into the row so the
behavior is self-contained.
2026-05-14 02:21:48 -04:00
Ryan Hughes 53f9899d5a Show discovered devices and shrink bluetooth header buttons
- Scan and Manage are now small icon-only buttons in the header beside
  the On/Off pill, with hover tooltips via the new PillButton.tooltipText
  prop (backed by QtQuick.Controls ToolTip).
- New discoveredDevices list pulls everything in Bluetooth.devices that
  isn't paired/connected/bonded/trusted. While scanning, those appear
  under a 'Discovered' header. Click pairs and connects.
- Empty-state text only shows when there are no known and no
  discovered devices, otherwise it would push down real entries.
2026-05-14 02:21:48 -04:00
Ryan Hughes fbe45d517b Improve bluetooth panel layout
- Header now uses anchors so the on/off pill sits cleanly at the right
  instead of relying on a fixed-width spacer that drifted as content
  grew.
- Discovery toggle moved out of the header and into a labeled action
  row alongside a new 'Manage…' button that launches
  omarchy-launch-bluetooth (the Impala TUI).
- Empty-state message tells you what to do based on adapter state
  (off / scanning / no paired devices) instead of one generic line.
2026-05-14 02:21:48 -04:00
Ryan Hughes 3177a396ff Break weather popup info onto separate lines
wttr.in query switched from one-blob format to pipe-delimited fields
(location|condition|temp|feels|wind|humidity). The popup parses each
piece into its own property and renders a clean key/value grid:

  fort lauderdale, florida, us
  Partly cloudy

  Temperature  +82°F (feels +91°F)
  Wind         ↗15mph
  Humidity     82%

  [Refresh] [wttr.in]
2026-05-14 02:21:48 -04:00
Ryan Hughes bfa8e2234e Show weather popup on hover
PopupCard gains a triggerMode property — "click" stays as the default
(focus-grab dismissal), "hover" skips the grab so the cursor can move
freely between the trigger and the card. PopupCard also exposes a
containsMouse alias for widgets that want to coordinate hover state.

Weather widget now shows on hover and hides 220ms after the cursor
leaves both the trigger and the popup. The redundant tooltip is gone —
the popup is the detail view. Click is still wired for refresh
(middle) and notification dump (right).
2026-05-14 02:21:48 -04:00
Ryan Hughes 7425dd74ae Tighten weather popup layout and add outside-click dismiss
PopupCard now uses HyprlandFocusGrab so any popup in the shell closes
when the user clicks outside it (or any other window in the listed set).
Single primitive — every widget gets it for free.

Weather popup rewritten:
- Smaller cloud glyph beside the city name on one row, both vertically
  centered.
- Condition string flows on its own line and wraps inside the popup.
- Refresh and wttr.in pills sit side by side instead of stacked, no
  more dead vertical space.
- contentHeight tracks the actual content height so the popup is no
  taller than it needs to be.
2026-05-14 02:21:48 -04:00
Ryan Hughes 5476b9d13b Drop animated workspacesPro widget; legacy workspaces is the default
The legacy 'workspaces' built-in renders cleaner than the animated
workspacesPro file widget. Removed the widget file, its first-party
registration in Bar.qml, and updated the default layouts and docs.
'workspaces' loses the (legacy) tag in the catalog since there's no
alternative anymore.
2026-05-14 02:21:48 -04:00
Ryan Hughes 14ed2560f9 Hide first-party panels/overlays from bar-settings catalog
omarchy.bar-settings and omarchy.image-picker are shell infrastructure —
the customizer and image picker themselves. Listing them in 'Other
plugins' with move/remove arrows is misleading: removing the panel
plugin doesn't disable anything (it's summoned on demand via IPC), and
adding them never made sense.

Dropped them from shell-defaults.json's plugins[] and from the inline
builtinShellConfig fallback. normalizeDraft and availableToAdd now skip
manifests with __isFirstParty so existing user shell.json files
self-heal on next load.
2026-05-14 02:21:48 -04:00
Ryan Hughes 546f4893ff Fix duplicate onBarWidgetRegistryChanged in bar-settings panel
Two handlers were declared for the same property-change signal — QML
refuses to load the file with 'Property value set multiple times', so
summoning omarchy.bar-settings failed silently. Merged the debug log
into the existing catalogRevision++ handler.
2026-05-14 02:21:48 -04:00
Ryan Hughes bcbe12b075 Unify config into shell.json and add Noctalia plugin support 2026-05-14 02:21:48 -04:00
Ryan Hughes 5c0f5669c9 Switch the image picker to IpcHandler 2026-05-14 02:21:48 -04:00
Ryan Hughes 4e8bf99240 Polish docs and harden plugin loading 2026-05-14 02:21:48 -04:00
Ryan Hughes 714e8a453b Move bar-settings and background-switcher into the shell 2026-05-14 02:21:48 -04:00
Ryan Hughes c72a8756b3 Add omarchy-shell with a plugin registry 2026-05-14 02:21:48 -04:00
Ryan Hughes 619a0d5737 Update GUI state in resetToDefaults
suppressReload was eating the file-watch callback that would have
called loadConfig and refreshed the draft from disk, so the GUI stayed
on the pre-reset layout even though bar.json was already correct.
Apply the reset payload directly to draft (and bump draftRevision) so
section editors re-render in the same frame.
2026-05-14 02:21:48 -04:00
Ryan Hughes 34c645af72 Live-save bar settings as you edit
Every layout mutation (add/remove/reorder, settings dialog Apply,
position or centerAnchor change) now writes ~/.config/omarchy/bar.json
immediately. No more Save button — replaced with an inline 'Auto-saving
to ...' status line next to Reset to defaults.

To stop the FileView feedback loop (write → inotify → reload → set
draft → write again) the shell keeps a one-shot suppressReload flag
that swallows the userFile.onLoaded triggered by our own setText.
2026-05-14 02:21:47 -04:00
Ryan Hughes e9806b093b Reset to defaults: bundle builtin defaults as a guaranteed fallback
Reset previously could zero the bar out when defaultConfig was empty —
either because bar-defaults.json hadn't finished loading or because the
resolved path was wrong. The shell now carries an inline builtinBarConfig
that mirrors bar-defaults.json, and Reset uses it whenever the on-disk
defaults aren't yet populated.

Also: log the resolved omarchyPath / defaultsPath / userConfigPath at
startup, and route FileView load failures through console.warn so the
next time a user hits this they can see why.
2026-05-14 02:21:47 -04:00
Ryan Hughes 66155fff84 Persist full bar config instead of a diff against defaults
The diff serializer would write only the sections the user touched and
rely on the bar merging defaults back in at load time. After a Reset to
Defaults the user file became {}, so the next 'Add widget' diffed
against the section and wrote ONLY the user-added entry, dropping every
default widget the user could see in the GUI.

- Reset to Defaults now writes the merged defaults verbatim so the GUI
  and bar.json agree on the full widget list, and any subsequent edit
  operates on that explicit list.
- Save writes the full draft, not a diff. The user gets a predictable
  what-you-see-is-what-you-save customizer at the cost of Omarchy
  defaults changes not silently propagating after the first save.
2026-05-14 02:21:47 -04:00
Ryan Hughes 9862aeb661 Resolve first-party widgets relative to the shell.qml directory
Quickshell.shellDir points at the directory holding the loaded
shell.qml, so the bar can find its own widgets and bar-defaults.json
without depending on OMARCHY_PATH being set in the environment. The
old behaviour silently fell back to ~/.local/share/omarchy when the
env var was unset, which is fine for the installed shell but caused
'No such file or directory' for every first-party widget when running
quickshell -p straight from the repo.

- firstPartyWidgetSource now uses Qt.resolvedUrl("widgets/<name>.qml")
  so the resolution is anchored to shell.qml itself.
- deriveOmarchyPath() in both bar/shell.qml and bar-settings/shell.qml
  walks back from Quickshell.shellDir to find the omarchy root, with
  OMARCHY_PATH still allowed as an explicit override and the install
  default as a final fallback.
2026-05-14 02:21:47 -04:00
Ryan Hughes af5a71347b Address reviewer findings for bar settings GUI
CRITICAL:
- Re-inject working entry into the settings form every time the dialog
  opens. Previously the Loader's onLoaded only fires when the
  sourceComponent identity changes, so reopening the dialog on the same
  widget id (or on a second instance of the same id, e.g. two spacers)
  showed stale field values.
- 'Add widget' menu and the centerAnchor dropdown both read
  draft.layout[section] without depending on the section array
  identity. Mutating the array in place did not invalidate those
  bindings, so the menu would show a stale availability list and let
  non-spacer widgets be added twice. Layout mutations now replace the
  whole  object so any binding that reads it re-evaluates.

WARNINGS:
- Save now writes only the diff against the merged defaults so future
  bar-defaults changes are not silently shadowed by a stale snapshot.
- FileView onFileChanged handlers simplified to a single reload() —
  the explicit second loader call was duplicating loadConfig and
  bumping barConfigSerial twice per change (visible flicker).
- userFile onLoaded ignores reloads while the user has an unsaved
  working draft so external edits during editing do not clobber the
  in-progress state.
- SpinBox forms switched from onValueChanged to onValueModified so the
  initial-value bind no longer fires fieldChanged.
- Hyprland window-rule sizes aligned with the FloatingWindow
  implicitWidth/Height values (720 main, 380 dialog).
- omarchy-launch-bar-settings falls back to initialTitle when focusing,
  so a dialog that has not yet had its title applied still surfaces
  the existing instance.
2026-05-14 02:21:47 -04:00
Ryan Hughes a03f589258 Add visual bar customizer
Each layout entry is now an object — {id, ...inline settings} — instead
of a (name, separate modules map) pair. Multiple instances of the same
widget are trivially supported (spacer is the main beneficiary). Settings
travel with the entry, so reordering keeps them attached.

shell.qml:
- normalizeLayout converts string entries to {id} and drops invalid ones
- ModuleSlot binds to a full entry; moduleName and moduleSettings derive
  from it via entryId/entrySettings helpers
- centerAnchor lookup walks layoutEntries directly
- builtinBarConfig defaults use the object form
- README + bar-defaults.json updated to the new schema

bar-settings/ (new Quickshell config):
- Top toolbar with Reset / Save and Position / centerAnchor dropdowns
- Three section editors (left/center/right) with current widgets shown
  as cards: name + description + move up/down/settings/remove buttons
- '+ Add widget' menu per section, sorted alphabetically by display name
  (only spacer can repeat; everything else is one per bar)
- Per-widget settings dialog (FloatingWindow) loads an inline schema for
  widgets in the catalog. Initial schemas: spacer (size), calendar
  (formats), brightness (step)
- FileView { atomicWrites } writes to ~/.config/omarchy/bar.json on Save

omarchy-launch-bar-settings + hypr window rules pin the settings window
to a 760px floating square. controlCenter gains a 'Customize bar…' button
that launches it.
2026-05-14 02:21:47 -04:00
Ryan Hughes 9ddf05f230 Add controlCenter widget: one-click quick settings popup
Single bar button (md-tune-vertical glyph) that opens a popup with the
controls most users reach for repeatedly throughout the day:

- Volume slider + mute toggle (Pipewire defaultAudioSink)
- Brightness slider (brightnessctl, coalesced via writeTimer)
- 2x2 tile grid: Do Not Disturb (makoctl mode), Night Light (omarchy-
  toggle-nightlight, temperature probed), Keep Awake (hypridle pid
  detection), Theme (current symlink + opens omarchy menu themes)
- Power-profile row (Saver / Balanced / Performance), hidden when
  power-profiles-daemon is not installed

Polled every 3s via Process + StdioCollector pairs gated by !running
busy checks. Default layout adds it before powerMenu on the right.
2026-05-14 02:21:47 -04:00
Ryan Hughes db13654815 Address review on Noctalia-inspired widgets
- nightLight queries hyprctl hyprsunset temperature to detect state
  instead of pgrep, since omarchy-toggle-nightlight keeps the daemon
  running across toggles. Adds a 'toggling' busy flag so repeated
  clicks do not stack the toggle script.
- lockKeys reads each LED individually and emits 'missing' when the
  class is absent, fixing column-shift mislabels on keyboards that
  only expose a subset of the locks. Hides + stops polling when no
  LEDs are reported. Poll interval relaxed to 2s.
- activeWindow right-click now calls toplevel.close() against the
  captured window instead of dispatching killactive against whatever
  is focused at click time.
- Drop unused Common imports from activeWindow and lockKeys.
2026-05-14 02:21:47 -04:00
Ryan Hughes a901d4a71f Add 5 widgets inspired by Noctalia: activeWindow, nightLight, keyboardLayout, lockKeys, spacer
- activeWindow: shows the focused toplevel title from Quickshell.Wayland
  ToplevelManager. Left-click activates, middle-click closes, right-click
  killactive. Hidden in vertical bars to avoid title rotation noise.
- nightLight: toggles omarchy-toggle-nightlight; status detected via
  pgrep hyprsunset. Hides when hyprsunset isn't installed.
- keyboardLayout: shows current xkb layout short code, click cycles via
  hyprctl switchxkblayout. Refreshes on Hyprland activelayout events.
- lockKeys: caps/num/scroll lock indicators read from /sys/class/leds.
  Uses plain A/1/S letters; hides each indicator when off.
- spacer: configurable blank space (size) for layout tuning.

Defaults add activeWindow to the left section and nightLight to the
right section between audioPanel and brightness.
2026-05-14 02:21:47 -04:00
Ryan Hughes 55a9075415 Address reviewer follow-ups: powerProfile detect, slider live-value, glyphs
- powerProfile now hides on machines without power-profiles-daemon by
  checking against the published profile set rather than a never-undefined
  enum, and uses mdi-scale-balance for Balanced (not battery-charging).
- networkPanel renames the QML-keyword-shadowing 'signal' property to
  'signalStrength'; ethernet glyph corrected to mdi-ethernet (not the
  access-point icon).
- workspacesPro indicator color guards against null bar during construction.
- Common.Slider keeps an internal liveValue so external value bindings
  survive a drag; sliders fed from PipeWire/brightnessctl now follow
  external changes after the user interacts.
- audioPanel drops the redundant default-sink PwObjectTracker since the
  candidate-sinks tracker already covers it.
- networkPanel guards scan/connect commands against re-entry while the
  previous Process is running.
- notificationCenter only instantiates its NotificationServer when the
  module is opted in via settings.replaceMako (default off) so it does
  not collide with mako out of the box.
- PopupCard fully opaque while open (previously 0.98) — removes a
  visible ghost outline on first render.
- Drop dead code: calendar trailing MouseArea, weatherFlyout's unused
  parseForecast/forecast property, idleInhibitor's holdSeconds,
  media's scrollAnim.position; gate media's scroll animation off in
  vertical bar mode.
2026-05-14 02:21:47 -04:00
Ryan Hughes fe73986a01 Address momus review: fix icons, vertical layout, popup coordination
- Replace nerd font glyphs that were stripped during the initial widget
  writes with verified codepoints sourced from the JetBrains Mono Nerd
  Font cmap (cpu-64-bit, scale-balance, notification-clear-all, etc).
- systemStats now switches to a Column layout when the bar is vertical
  so the widget no longer overflows a 28px-wide side bar.
- Remove notificationCenter from defaults: it registers a notification
  server and would collide with the mako daemon Omarchy autostarts.
- PopupCard owns the popout coordinator lifecycle and delegates close to
  its widget owner when provided; calendar and media now pass owner.
- brightness debounces brightnessctl writes through a coalescing timer
  to avoid spawning a process per slider tick.
- audioPanel tracks unfiltered Pipewire sinks/streams via PwObjectTracker
  so audio metadata becomes available before filtering.
- ModuleSlot re-injects bar/moduleName/settings whenever the bar config
  serial changes so widget settings update live with bar.json.
- Guard null bar references in workspacesPro and systemStats components
  that are constructed before bar injection.
2026-05-14 02:21:47 -04:00
Ryan Hughes 221e0e1fcc Add modular interactive widgets to the Quickshell bar
Introduces a widgets/ directory of first-party QML modules and a common/
helpers library. Widgets auto-load by name from
default/quickshell/bar/widgets/<name>.qml — no edits to shell.qml needed
for additions beyond the firstPartyWidgets registry.

New widgets (all orientation-aware, top/bottom/left/right):
- media: MPRIS now-playing with scrolling label, cover art popup,
  play/pause/skip controls
- audioPanel: master volume slider, output device picker, per-app mixer
- networkPanel: Wi-Fi scan + connect, current connection details
- bluetoothPanel: paired device list, connect/disconnect, battery
- calendar: month grid popup keyed to today
- notificationCenter: live notification feed, DND toggle, clear all
- brightness: slider popup with scroll-to-adjust
- powerProfile: power-saver/balanced/performance picker (UPower)
- systemStats: inline CPU + RAM sparklines, expanded popup with btop
- weatherFlyout: weather popup with refresh and full report
- workspacesPro: animated focus indicator that slides between workspaces
- powerMenu: lock/suspend/log out/reboot/shutdown popup
- idleInhibitor: coffee-cup toggle wired to omarchy-toggle-idle
- microphone: mic state + mute toggle + scroll volume

Common helpers (default/quickshell/bar/common/):
- WidgetButton: hover/press scale animation, tooltip integration
- PopupCard: orientation-aware anchor + slide-in opacity transition
- Slider: drag/wheel-able linear slider with knob hover bump
- PillButton: rounded action button with icon + label

Bar root gains requestPopout/releasePopout so only one popup is open at
a time across widgets.

Updates bar-defaults.json to ship the new widgets out of the box while
keeping the legacy modules available.
2026-05-14 02:21:47 -04:00
Ryan Hughes 30dc9fddde Add Quickshell bar 2026-05-14 02:21:47 -04:00
Ryan HughesandGitHub 6b074c7a17 Merge pull request #5804 from bjarneo/tab-themes-and-backgrounds
Enable tab and shift+tab to navigate back and forth the wallpaper/theme selector
2026-05-14 02:02:56 -04:00
Bjarne Øverli d27c1e8346 Enable tab and shift+tab to navigate back and forth 2026-05-13 17:22:15 +02:00
Ryan Hughes 087909714e Add tmux keybindings viewer 2026-05-13 00:20:38 -04:00
Ryan Hughes be55e8048c Prevent modifier keys being stuck on Super + C / V / X 2026-05-12 22:41:27 -04:00
Ryan Hughes d54e8b5429 Use theme colors in image selector 2026-05-11 18:10:58 -04:00
Ryan Hughes f14d82b2f3 Start image selector on demand 2026-05-11 18:02:45 -04:00
Ryan Hughes cb87adfc99 Toggle image selector closed when already open 2026-05-11 17:53:40 -04:00
Ryan Hughes f24dd82181 Add filter typing to theme switcher 2026-05-11 17:10:45 -04:00
Ryan Hughes 903f27fdd1 Tighten image selector request handling 2026-05-11 16:50:26 -04:00
Ryan Hughes 0801209090 Keep selector labels readable 2026-05-11 16:07:37 -04:00
Ryan Hughes 314a7f75c0 Keep image selector preview centered 2026-05-11 16:03:31 -04:00
Ryan Hughes 3aaedd88b1 Remove selector width animation jitter 2026-05-11 15:57:59 -04:00
Ryan Hughes ca0ea7af57 Clamp image selector navigation 2026-05-11 15:52:38 -04:00
Ryan Hughes 693a23c58c Open image selector at selected item immediately 2026-05-11 15:47:01 -04:00