Commit Graph
152 Commits
Author SHA1 Message Date
sankalp 5e0337c0d6 fix(spotlight): monitor .desktop dirs for newly installed apps
Replace 1s TTL timer rescan with Gio.FileMonitor on XDG application
directories so spotlight picks up apps installed while running.
2026-07-19 12:03:27 +05:45
sankalp 8f6a040bb7 refactor(dock): replace 300ms occlusion poll with Hyprland events
- Subscribe to openwindow, closewindow, movewindow, workspace, fullscreen
- 50ms debounce to batch rapid successive events
- Event-driven check instead of continuous polling
- Proper cleanup with _disconnect_occlusion_signals()
2026-07-18 21:43:36 +05:45
sankalp 44f1103259 refactor(per_app_volume): remove redundant 2s polling
- stream-added/stream-removed signals already handle app list updates
- Removed _auto_refresh(), _on_map/_on_unmap timer management
- Removed _last_app_names tracking (unused without polling)
2026-07-18 21:43:29 +05:45
sankalp 2482078a3f style: simplify section comments to plain # style in notch.py and keyboard_layout.py 2026-07-18 19:06:32 +05:45
sankalp 82a5ff91af fix(app-capture): make gobject-introspection optional in meson build
CI Arch container doesn't have g-i installed. The GIR/typelib is only
needed for Python bindings — shared library builds fine without it.
Both gir dependency and g-ir-compiler are now required: false.
2026-07-18 14:28:04 +05:45
sankalp 732dd9c0ee fix: formating 2026-07-18 14:21:24 +05:45
sankalp 71c9d30c2c fix(osd): log exception when removing hide timer source
except Exception: pass was hiding stale ID errors.
2026-07-18 14:14:16 +05:45
sankalp 4d90a1ab52 fix(spotlight): log exception when removing stale GLib source IDs
except Exception: pass was hiding errors during pipeline cancellation.
2026-07-18 14:14:09 +05:45
sankalp 50e15db2de fix(controlcenter): move inline GLib/os imports to top-level
GLib was imported inline 4 times in seek-bar handlers that fire on
every user seek. os was imported inline in a fallback path. All moved
to top-level.
2026-07-18 14:13:48 +05:45
sankalp c00236fc69 fix(dock): remove pointless del svg_w, add warning on trash SVG failure
The del was a no-op (GC handles scope exit). The bare except Exception
hid real rendering errors — now logs at warning level.
2026-07-18 14:13:36 +05:45
sankalp 6a75ea84d9 fix(controlcenter): remove duplicate device-ready signal connection
Handler was connected twice — once in __init__ and again in
_initialize_resources. Every device-ready event fired on_network_ready
twice. Removed the __init__ connection (the lazy one is correct).
2026-07-18 14:13:27 +05:45
sankalp ee904cce04 fix(notification): null _spring_timer_id after first remove in on_resolved
on_resolved removed the GLib source but didn't null the ID, causing
double-remove crash when destroy() later tried to clean up the same
stale source.
2026-07-18 14:13:17 +05:45
sankalp ef685ab34a fix(globalmenu): remove shell=True from gcc compilation command
Use list form with shlex.split() for pkg-config flags instead of
shell=True string interpolation. Eliminates command injection vector.
2026-07-18 14:13:03 +05:45
sankalp 476ed7e4fb fix(workspace): replace broken _config_handlers import with off_config_change
Same silent ImportError leak as panel/main.py — callbacks were never
unregistered on widget destroy.
2026-07-18 14:12:44 +05:45
sankalp 6ef48af963 fix(panel): replace broken _config_handlers import with off_config_change
Panel destroy was importing nonexistent _config_handlers from config,
causing silent ImportError and leaked reload callbacks.
2026-07-18 14:12:37 +05:45
sankalp aeccbe3089 fix(osd): show OSD at 100% via fabric-cli exec from keybinds
- Add osd_show_audio/osd_show_brightness methods on OSDWindow
- Register as standalone functions in __main__ for fabric-cli exec
- Keybinds now chain fabric-cli exec after wpctl/brightnessctl
- Emit brightness signal on threshold bypass for small changes
2026-07-17 12:24:34 +05:45
sankalp 4f36ada1c5 fix(controlcenter): flush stale-cache races in toggle UI
- Drop rfkill from bluetooth toggle (redundant with D-Bus Powered,
  was causing stale cache on next read)
- Force toggle switch and icon to target state immediately after
  setting, don't wait for D-Bus callback
- Fix nightlight icon race: flip local is_active instead of
  re-querying async kill state
- Guard wifi on_network_ready against ethernet-first device loop
  (emits device-ready per device; wifi_device None on first)
- Share single NetworkClient between main panel and wifi popup
  (eliminates async-init race of two independent instances)
- Strip connected: prefix from wlan label initial display
- Add _pending_toggle pattern to wifi notify handler to
  suppress stale-cache revert; same for bluetooth switch lock
2026-07-17 11:23:42 +05:45
sankalp 14c00c4504 refactor(window/switcher): make item box height adapt automatically 2026-07-16 17:54:34 +05:45
sankalp 6e9cb8efc8 refactor(src/window/spotlight/plugins): improve emoji annotation download using curl for better error handling 2026-07-16 17:27:52 +05:45
sankalp 41cb9afa07 fix(src/window/notification): stop polling when revealer is closing/destroyed
The callback may execute after _on_notification_finished has fired, causing errors.
2026-07-16 12:13:19 +05:45
sankalp 83af1829c4 refactor(src/window/dock/canvas): reorganize client lookup and tooltip generation to prevent stale references 2026-07-16 12:13:01 +05:45
sankalp e840917621 fix(src/window/controlcenter): add guard for destroyed state and adjust return value 2026-07-16 12:12:43 +05:45
sankalp a47abda55a fix: resolve wifi crashes, shell injections, race conditions, and add debug mode
- Remove transient NEED_AUTH/DISCONNECTED error paths from wifi connect
- Guard double-callback in connect_wifi_bssid/connect_wifi_with_password
- Shell-quote user paths in wallpaper, screenshot, screenrecorder services
- Fix OSD hide-timer use-after-free and applet_window stale source ID
- Fix brightness poll timer leak on read failure
- Fix spotlight search stale idle source removal
- Lock dbusmenu _cache mutation under _registry_lock
- Fix entry.revision written outside _registry_lock scope
- Add fabric-cli exec wrapper for lock screen (lock_screen.lock())
- Replace hyprlock with lock screen in power menu and dropdown
- Add debug mode toggle in settings (controls log verbosity)
- Add diagnostic logging to globalmenu click chain
2026-07-16 11:47:53 +05:45
sankalp 4378959131 fix(controlcenter): refresh player state on resume
When control center hides, PlayerBox.suspend() blocks all signal
handlers. On resume(), clearing the flag wasn't enough — stale
state lingered until next fabricator poll (up to 5s). Now resume()
immediately syncs play/pause icon, metadata, and artwork.
2026-07-15 21:22:51 +05:45
sankalp 42ede60800 refactor: drop unused SettingsRow definitions from SettingsWindow
Removed three SettingsRow widgets that were no longer needed, cleaning up the UI configuration.
2026-07-15 19:37:22 +05:45
sankalp 6442161f40 refactor(src/window/globalmenu): simplify caching logic and remove dynamic menu method selection 2026-07-15 19:37:02 +05:45
sankalp 016d18090d refactor(src/window/spotlight/plugins): increase timeout interval to 50ms for clipboard and emoji paste actions 2026-07-15 11:30:46 +05:45
sankalp e6c471a9f8 fix(src/window/spotlight): add error handling around action invocation
Prevent crashes when result.action() raises exceptions and log warnings.
2026-07-15 11:30:23 +05:45
sankalp 2c9a050bbb fix(spotlight): run immediate search on Enter when debounced results empty
on_entry_changed uses @debounce(300). When user presses Enter before
debounce fires, _current_results is empty so nothing activates.

Now on_entry_accept triggers an immediate search_single when active
plugin has no results, and activates the first result on callback.
2026-07-15 10:52:44 +05:45
sankalp 4503130be3 fix(spotlight): activate first result before on_submit in entry accept
_on_entry_accept checked _active_plugin_entry before _current_results.
Keyword plugins (emoji, clipboard) are always active when prefix typed,
so on_submit (no-op base) swallowed Enter before result.action() fired.

Now results are checked first. on_submit only as fallback when no results.
2026-07-15 10:49:43 +05:45
sankalp 9eb62d7ea3 feat(config): wire up wallpapers_dir, osd, window_switcher, global_menu settings
- wallpapers_dir: read from config, fallback ~/Pictures/Wallpapers
- osd: skip show_audio_osd/show_brightness_osd when disabled
- window_switcher: skip show_switcher when disabled
- global_menu_cache_enabled: bypass GTK class cache when false
- global_menu_method: control discovery strategies (auto/hyprland/dbus)

All keys added to constants.py defaults, settings UI, and config.toml
2026-07-15 10:31:28 +05:45
sankalp e63a2c04a5 refactor: extract reusable utils, remove screencapture facade
- Add ManagedTimer to replace repeated source_remove/timeout_add boilerplate
- Add EvdevLockService base class for numlock/capslock (cut 154→28 lines)
- Add BaseNotchIndicator for 5 near-identical indicator classes (cut 404→171 lines)
- Add load_pixbuf_thumbnail and resolve_monitor to utils
- Delete screencapture.py facade; callers use Screenshot/ScreenRecorder directly
2026-07-15 10:01:40 +05:45
sankalp ebe1238b3d feat(src/window/spotlight/plugins): implement is_active detection and notification handling for caffeine plugin
Add CaptureNotifier import and send notifications when caffeine is enabled or disabled. Introduce is_active() static method to check inhibition status via PID file and process cmdline. Replace previous _read_pid() usage with is_active(). Enhance _humanize to properly format "0s" and hour-only durations. Update activation logic to use the new method and trigger appropriate notifications.
2026-07-15 09:04:00 +05:45
sankalp cdccb9e726 feat(src/window/controlcenter): implement caffeine inhibitor toggling
Add support for managing systemd‑inhibit processes via a PID file; introduce _caffeine_is_active helper; modify _check_initial_states and toggle_caffeine to start/stop inhibition and update UI icons and labels.
2026-07-15 09:03:39 +05:45
sankalp ddacdea3eb refactor(src/window/controlcenter): replace svg_file imports with Image and simplify battery icon handling 2026-07-14 23:26:21 +05:45
sankalp f2517ee9f3 feat(src/window/notification): add action buttons creation and improve UI alignment 2026-07-14 23:11:19 +05:45
sankalp e7c49d7dda refactor(src/window/notification): simplify hover handling and close‑button styling for notifications 2026-07-14 22:46:18 +05:45
sankalp 4df8b93e6c fix(src/window/panel/components/globalmenu): correct active window detection to exclude Modus 2026-07-14 22:00:10 +05:45
sankalp 04ac938dd2 refactor(src/window/dock): replace manual drawing of shadows, borders, and backgrounds with Gtk.render_background and Gtk.render_frame 2026-07-14 21:58:35 +05:45
sankalp 6f2d0bf444 chore: refactor imports and adopt new utils utilities 2026-07-14 18:45:52 +05:45
sankalp 0496100788 feat(spotlight): add Caffeine plugin to inhibit idle/sleep
Uses systemd-inhibit with a pinned sleep process and PID file so
the inhibition survives Spotlight dismiss. Supports on/off and
duration presets (5m/15m/30m/1h) plus free-form parsing.
2026-07-14 13:47:58 +05:45
sankalp 2d22df94ca refactor: drive UI from service signals, drop redundant polling
- bluetooth.py / wifi.py: remove 5s periodic refresh timers; rely on
  service `changed`/`device-added`/`device-removed`/`notify` signals
- expanded_player.py: remove 500ms metadata poll; rely on
  `meta-change`/`artwork-change` signals
- player.py (notch): connect previously dangling `artwork-change` handler
- popup_win.py: silence harmless "nothing connected" warning on destroy()

No behaviour change; eliminates dead timers and log spam.
2026-07-14 13:46:21 +05:45
sankalp 9ff5ebc95c refactor(spotlight): replace raw socket IPC with Fabric Service over DBus
SpotlightWindow now exposed via SpotlightService (fabric Service) on the
session bus (dev.modus.Spotlight /Toggle). On-demand process forwards to
the running instance over DBus instead of a unix socket; still quits on
dismiss. Behaviour unchanged.
2026-07-14 13:02:26 +05:45
sankalp f72542a231 refactor: log swallowed exceptions across src/
Replace silent swallow-excepts (pass/return/continue) with
logger.warning recording the caught error, preserving behaviour.
2026-07-14 13:02:21 +05:45
sankalp c0a4b1b792 refactor(src/window/dock): improve desktop file search matching logic
Check exact desktop file name first and enhance matching algorithm to prioritize exact matches, compute relevance scores, and return the best match.
2026-07-14 02:36:20 +05:45
sankalp 112f4b1039 refactor(services): convert weather + gamemode to Fabric services
Weather: move networking, caching and scheduling out of the Weather widget
into a WeatherService singleton. Reuse one httpx.Client for the app lifetime,
drop the 4-worker pool and the multi-entry dict caches (single-value fields),
query Nominatim only on location change, remove debounce and the /tmp-style
polling. Widget now observes the `updated` signal and never hits the network.

GameMode: turn the standalone CLI script into a GameModeService (Service
singleton) exposing an `enabled` Property and `changed` signal. Drive Hyprland
via `hyprctl eval hl.config(...)` instead of the deprecated `hyprctl keyword`
batch (rejected under the Lua config in Hyprland 0.55+), read state via
`hl.get_config`, and keep `hyprctl reload` for disable. Fix game-mode state
parsing so unrecognized `hl.get_config` output no longer falsely reports
active. BatteryWidget's GameModeButton now subscribes to the service.

Remove now-unused LOCATION_CACHE_TIMEOUT.
2026-07-14 00:37:52 +05:45
sankalp f3f17bb5fc refactor(services): split screen capture into screenshot + recorder services
Split the monolithic ScreenCapture service into focused Screenshot and
ScreenRecorder services behind a pluggable capture backend.

- Add shared/capture.py: CaptureBackend abstraction + HyprlandCaptureBackend
  (hyprshot/grim/slurp/wf-recorder) and reusable CaptureNotifier
- Add services/screenshot.py and services/screenrecorder.py with Fabric
  properties/signals; recording state kept in memory (no /tmp files)
- Keep services/screencapture.py as a backwards-compatible facade so
  existing widgets and signals keep working
- Resolve monitors via Hyprland IPC helpers in services/modus.py instead of
  spawning `hyprctl monitors -j` per capture
- Implement real window recording (slurp window boxes) and split the
  record-window / record-region UI mappings
- Register screenshot_service / screen_recorder_service singletons
- Remove dead src/utils/inhibit.py duplicate; minor modus.lua quoting fix
2026-07-13 23:52:32 +05:45
sankalp 54ff85ffc9 fix(services/spotlight): improve MPRIS artwork handling and scope keyword searches to single plugin
- mpris: native MediaArt cache lookup, dedupe play/pause emission, safe
  cleanup, artwork polling for already-playing browser players, drop
  os.system seek fallback
- spotlight: scope plugin keyword and detect() matches to a single plugin
  via search_single instead of global search; register clipboard keywords
  (clip/clipboard)
2026-07-13 22:20:19 +05:45
sankalp d6efc12ef1 style(switcher): fix trailing whitespace in app-capture C code
Clean up whitespace in app-capture.c and hyprland-toplevel-mapping XML
2026-07-12 20:19:05 +05:45
sankalp b421e39052 refactor(window): cleanup controlcenter and notification imports
Remove unused imports in controlcenter and notification modules
2026-07-12 20:18:10 +05:45