From 94ed52f4b59362772db30f8b8bd658fa60ac8f4b Mon Sep 17 00:00:00 2001 From: S4NKALP Date: Sun, 12 Jul 2026 20:17:56 +0545 Subject: [PATCH] docs: update architecture, configuration, and FAQs - Expand architecture overview with plugin system details - Update configuration guide with new spotlight settings - Improve FAQs with troubleshooting tips - Remove docs/README.md (content merged into main README) --- docs/README.md | 39 --------------- docs/architecture.md | 112 +++++++++++++++++++++++++++++++----------- docs/configuration.md | 15 +++++- docs/faqs_tips.md | 112 +++++++++++++++++++++++++++++++++--------- 4 files changed, 187 insertions(+), 91 deletions(-) delete mode 100644 docs/README.md diff --git a/docs/README.md b/docs/README.md deleted file mode 100644 index 374c739..0000000 --- a/docs/README.md +++ /dev/null @@ -1,39 +0,0 @@ -# Modus Documentation - -Welcome to the official documentation for Modus! - -Modus is a highly customizable, hackable shell environment designed specifically for Hyprland on Wayland, built using Python and the [Fabric](https://github.com/Fabric-Development/fabric/) framework. - -## Table of Contents - -1. **[Installation Guide](installation.md)** - - Automated installation via `install.sh`. - - Manual installation and compiling C-extensions. - - Post-installation steps and recommended themes. - -2. **[Configuration Guide](configuration.md)** - - How to configure the shell using `config.toml`. - - Setting up custom panel buttons with `mods.toml`. - - Pinning apps to the dock via `dock.toml`. - -3. **[Styling Guide](styling.md)** - - How Matugen dynamically generates colors based on your wallpaper. - - Customizing CSS components in `src/shared/styles/`. - -4. **[Architecture Overview](architecture.md)** - - Deep dive into how Modus is built. - - The Wayland Window Switcher C-Backend (`AppCapture`). - - The Global Menu DBus implementation. - -5. **[FAQs & Tips](faqs_tips.md)** - - Troubleshooting common issues (Dock occlusion, CPU usage, OSD). - - Pro tips for keyboard shortcuts and live-reloading. - ---- - -## Contributing - -Modus is open-source and hackable by design. If you want to contribute to the project: -1. Familiarize yourself with the [Architecture Overview](architecture.md). -2. Write Python code using the Fabric framework widgets. -3. Ensure you test your changes by running `uv run start` before opening a pull request. diff --git a/docs/architecture.md b/docs/architecture.md index 89cabd4..4c1e424 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -1,43 +1,99 @@ # Architecture Overview -Modus is built using **Python** and the **Fabric** framework (a GTK/Wayland wrapper), along with custom C extensions for high-performance Wayland interactions. +Modus is built with Python and the [Fabric](https://github.com/Fabric-Development/fabric/) +framework (GTK/Wayland wrapper), plus custom C extensions for high-performance +Wayland interactions. ## 1. Core Application Loop -The entry point of Modus is `start.py`, which delegates to `src/main.py`. -`main.py` instantiates the `fabric.Application` object. This central application manages the lifecycle of various floating Wayland windows (called "widgets" or "panels" in Modus). +Entry point is `start.py`, delegates to `src/main.py`. `main.py` instantiates +`fabric.Application`, which manages lifecycle of floating Wayland windows: -Key windows include: -- **Panel**: The top bar (`src/window/panel/`) -- **Dock**: The macOS-style bottom dock (`src/window/dock/`) -- **Control Center**: The right-side quick settings panel (`src/window/controlcenter/`) -- **App Switcher**: The Alt-Tab window switcher (`src/window/switcher/`) -- **Lock Screen**: The session lock screen (`src/window/lock.py`) +- **Panel**: Top bar (`src/window/panel/`) +- **Dock**: macOS-style bottom dock (`src/window/dock/`) +- **Control Center**: Right-side quick settings (`src/window/controlcenter/`) +- **App Switcher**: Alt-Tab window switcher (`src/window/switcher/`) +- **Lock Screen**: Session lock (`src/window/lock.py`) +- **Spotlight Search**: Super+D search overlay (`src/window/spotlight/`) -## 2. High-Performance App Switcher (AppCapture) +## 2. Spotlight Search Engine -The App Switcher (`Alt+Tab`) needs to display live video previews of running Wayland windows. Doing this in pure Python via DBus polling would be far too slow and resource-intensive. +The spotlight (`src/window/spotlight/`) is a plugin-powered search overlay. +It has three layers: -To solve this, Modus uses a custom C-extension located in `src/window/switcher/app-capture/`. -- **How it works**: It uses the `hyprland-toplevel-export-v1` Wayland protocol to ask Hyprland for direct memory-mapped buffers (dmabuf/shm) of the window contents. -- **Python Integration**: The C-backend is compiled to `libappcapture.so` and exposed to Python via GObject Introspection. -- **Optimization**: To prevent CPU spikes when capturing 4K windows, the capture framerate is intentionally throttled by Python using `invoke_repeater`, controlled by `switcher_live_preview_delay_ms` in `config.toml`. +### Layer 1: UI (`main.py`) -## 3. Global Menu (DBus) +A GTK window with an entry field and scrollable result list. Renders results +from plugins. Manages keyboard navigation, viewport sizing, and result +selection. Uses a 200ms debounce on the entry field to avoid searching on +every keystroke. -Modus features a macOS-style Global Menu (the application menu bar sits in the top panel instead of inside the app window). +### Layer 2: Search Pipeline (`core/search.py`) -- **How it works**: Apps export their menus over the `com.canonical.dbusmenu` DBus interface. -- **The Shim**: To force GTK apps to export their menus even if they weren't natively designed to, Modus preloads a custom C library (`src/globalmenu/libmenu_button_shim.c`). This shim hooks into GTK's menu generation and forces the export. -- **Python Daemon**: The Python side (`src/globalmenu/service.py`) acts as a DBus server, listens for these exported menus, and dynamically renders them as Fabric widgets in the top panel. +On each keystroke: -## 4. State Management & Services +1. Routes the query — if it starts with a keyword (e.g., `gg ` for Google), + the query goes exclusively to that plugin +2. Otherwise, dispatches to all `searchable` plugins in parallel via daemon + threads +3. Collects results via `GLib.idle_add` (main thread callback) +4. Merges results sorted by plugin priority then result score +5. Cancels previous in-flight searches with `threading.Event` tokens -Modus relies heavily on asynchronous event-driven services located in `src/services/`. -These services monitor system states and emit signals when things change, updating the UI reactively: -- `battery.py`: Uses UPower over DBus to track battery state. -- `bluetooth.py`: Uses BlueZ over DBus. -- `brightness.py`: Uses `brightnessctl` or `ddcutil`. -- `network.py`: Uses NetworkManager over DBus. +### Layer 3: Plugin System (`core/loader.py`, `core/manager.py`, `core/registry.py`) -By using signals (`connect("changed", update_ui)`), Modus ensures that it uses virtually 0% CPU while idle. +- **Loader**: Scans `config/plugins/` for `.py` files and package directories. + Handles per-plugin virtualenvs via `uv` for dependency isolation. Supports + deep reload (re-import from disk without restart). +- **Manager**: Orchestrates lifecycle — instantiate, enable/disable, reload, + release memory. Persists disabled plugin list to `plugins.json`. +- **Registry**: Stores plugin metadata keyed by id. Maintains keyword-to-plugin + map for fast routing. + +### Data flow + +``` +User types → debounce (200ms) → route query + ├─ keyword match → single plugin search → render + └─ global search → dispatch to threads → collect → merge → render + +User selects result → action callback → (copy, launch, etc.) +User presses Escape → cancel searches → release plugin memory → hide +``` + +## 3. High-Performance App Switcher (AppCapture) + +The App Switcher (Alt+Tab) needs live video previews of Wayland windows. Pure +Python DBus polling is too slow, so Modus uses a C-extension at +`src/window/switcher/app-capture/`. + +- Uses `hyprland-toplevel-export-v1` Wayland protocol to get dmabuf/shm buffers + from Hyprland +- Compiled to `libappcapture.so`, exposed to Python via GObject Introspection +- Framerate throttled by Python using `invoke_repeater`, controlled by + `switcher_live_preview_delay_ms` in `config.toml` + +## 4. Global Menu (DBus) + +macOS-style menu bar in the top panel. + +- Apps export menus over `com.canonical.dbusmenu` DBus +- Custom C shim (`src/globalmenu/libmenu_button_shim.c`) forces GTK apps to + export menus even if they weren't designed to +- Python daemon (`src/globalmenu/service.py`) listens for exported menus and + renders them as Fabric widgets in the panel + +## 5. State Management & Services + +Services in `src/services/` monitor system state asynchronously and emit +signals: + +| Service | Source | What it tracks | +|---------|--------|---------------| +| `battery.py` | UPower over DBus | Battery percentage, charging state | +| `bluetooth.py` | BlueZ over DBus | Bluetooth devices | +| `brightness.py` | `brightnessctl` / `ddcutil` | Screen brightness | +| `network.py` | NetworkManager over DBus | WiFi, ethernet state | + +Uses signals (`connect("changed", update_ui)`) for reactive UI — virtually 0% +CPU while idle. diff --git a/docs/configuration.md b/docs/configuration.md index b404cd9..90d0731 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -8,7 +8,6 @@ Modus is highly configurable using TOML files located in the `config/` directory |------|---------| | `config.toml` | Main application configuration (modules, features, toggles). | | `mods.toml` | Custom panel button definitions (menus, shell commands). | -| `launcher.toml` | Settings specific to the application launcher/spotlight. | | `dock.toml` | Pinned applications for the dock. | --- @@ -31,6 +30,20 @@ The `config.toml` file controls which widgets and services are enabled. Most cha - `switcher_live_preview_delay_ms`: Framerate delay for previews (e.g., `200` = ~5fps). Lower is smoother but uses more CPU. - `osd`: Enables on-screen displays for volume and brightness changes. +**Spotlight Search Keybinds** (defined in `config/hypr/modus.lua`): + +| Key | Action | +|-----|--------| +| `Super + D` | Open spotlight search (default) | +| `Super + E` | Open emoji picker | +| `Super + V` | Open clipboard history | +| `Super + W` | Open wallpaper browser | +| `Alt + Shift + W` | Set random wallpaper | + +These can be customized in `config/hypr/modus.lua`. The spotlight `.toggle()` +method accepts optional arguments to pre-fill keywords: `toggle('em')` opens +the emoji picker directly. + --- ## `mods.toml` (Custom Panel Buttons) diff --git a/docs/faqs_tips.md b/docs/faqs_tips.md index 624d908..005b962 100644 --- a/docs/faqs_tips.md +++ b/docs/faqs_tips.md @@ -3,35 +3,101 @@ ## Frequently Asked Questions ### 1. The Global Menu isn't showing up for some apps? -Modus uses a custom `libmenu_button_shim.so` along with `appmenu-gtk-module` to export GTK menus over DBus. -- Ensure `appmenu-gtk-module` is installed. -- Ensure the shim was compiled correctly during installation. -- Note that non-GTK apps (like Electron apps or Qt apps) might need specific flags (like `export QT_QPA_PLATFORMTHEME=appmenu-qt5`) to export their menus. -### 2. High CPU Usage when the Application Switcher is open? -The Modus App Switcher uses a custom Wayland C-Backend (`app-capture`) to generate live video previews of your running windows. -- The previews are software-rendered via Cairo. -- If you have many 4k windows open, generating live thumbnails might cause a CPU spike. -- **Fix:** You can throttle the framerate in `config.toml` by increasing `switcher_live_preview_delay_ms` (e.g., set to `200` for ~5 FPS), or entirely disable live previews by setting `switcher_live_preview = false`. +Modus uses a custom `libmenu_button_shim.so` with `appmenu-gtk-module` to +export GTK menus over DBus. +- Ensure `appmenu-gtk-module` is installed +- Ensure the shim was compiled correctly during installation +- Non-GTK apps (Electron, Qt) may need flags like + `export QT_QPA_PLATFORMTHEME=appmenu-qt5` -### 3. The Dock is covering my fullscreen games/videos? -Ensure you have `dock_auto_hide = true` in your `config.toml`. The dock intelligently hides when a window is maximized or goes fullscreen. +### 2. High CPU usage when App Switcher is open? -### 4. Why isn't my Volume or Brightness OSD showing up? -Ensure that `osd = true` is set in your `config.toml`. The On-Screen Display relies on `brightnessctl` for brightness and standard audio services (like Pipewire/Wireplumber) for volume. Make sure those underlying tools are working correctly on your system. +The App Switcher uses a custom C-backend to capture live window previews. +- 4K windows with many open can spike CPU +- **Fix**: Increase `switcher_live_preview_delay_ms` in `config.toml` (e.g., `200` + for ~5 FPS) or set `switcher_live_preview = false` to disable previews entirely -### 5. The Weather widget is showing the wrong location? -You can easily fix this by updating the `weather_location` setting in your `config.toml`. Simply type your city and country (e.g., `"London, UK"` or `"Patan, Nepal"`), and the widget will fetch the correct local weather. +### 3. Dock covering fullscreen games/videos? + +Set `dock_auto_hide = true` in `config.toml`. The dock hides automatically +when a window is maximized or fullscreen. + +### 4. Volume/Brightness OSD not showing? + +Set `osd = true` in `config.toml`. Requires `brightnessctl` for brightness and +Pipewire/Wireplumber for audio. + +### 5. Weather widget shows wrong location? + +Update `weather_location` in `config.toml` (e.g., `"London, UK"` or +`"Patan, Nepal"`). + +### 6. Spotlight plugin isn't showing up? + +- Check the file is in `config/plugins/` (not `examples/plugins/`) +- Check `config/plugins/` is NOT in `.gitignore` for your own repos +- Run `journalctl --user -f -t modus` and look for `[PluginLoader]` errors +- Make sure the file has `PLUGIN = YourClassName` at the bottom +- If using dependencies, ensure `uv` is installed +- After editing, run `fabric-cli exec modus1 'deep_reload your_plugin_id'` + +### 7. Plugin has dependencies but they aren't installed? + +- Check `uv` is installed (`which uv`) +- Check `requirements.txt` is next to your `.py` file or inside your package dir +- The venv lives at `config/plugins/.venvs//` +- Delete that directory to force re-install on next load --- ## Pro Tips -- **Live Reload for Mods:** The `config/mods.toml` file is actively monitored. Any changes you make to custom panel buttons or dropdown menus are instantly loaded—no shell restart required! -- **Pinning Apps Correctly:** When pinning apps in `dock.toml`, ensure you use the exact `.desktop` file name (excluding the `.desktop` extension). For example, use `"org.gnome.Nautilus"` instead of just `"nautilus"` or `"Files"`. -- **Custom Scripts in Panel:** You aren't limited to simple commands in `mods.toml`. You can point the `on-clicked` actions to complex bash scripts stored in your home directory to create advanced panel utilities. -- **Forcing a Theme Update:** Because Modus uses Matugen for styling, the entire shell's color scheme is tethered to your wallpaper. If you want to completely change the look of your desktop, simply set a new wallpaper! Modus will automatically generate a new palette and hot-reload the UI without dropping your session. -- **Keyboard Shortcuts:** - - `uv run start` — Starts the main shell daemon. - - `uv run lock` — Triggers the session lock screen. -- **Wayland Screencapture:** You can quickly toggle the screen recording/capture widget from the panel or bind it to a key using your Hyprland config (e.g. `bind = SUPER, S, exec, fabric-cli exec modus 'screencapture.toggle()'`). +- **Live Reload for Mods**: `config/mods.toml` is monitored for changes. Edits + apply instantly — no restart needed + +- **Pinning Apps**: Use exact `.desktop` filename in `dock.toml` (e.g., + `"org.gnome.Nautilus"`, not `"Files"`) + +- **Custom Scripts**: `on-clicked` in `mods.toml` can point to bash scripts in + your home directory + +- **Theme Updates**: Modus uses Matugen tied to your wallpaper. Set a new + wallpaper and the shell recolors automatically + +- **Spotlight Keyboard Shortcuts** (from `config/hypr/modus.lua`): + + | Key | Action | + |-----|--------| + | `Super + D` | Open spotlight search | + | `Super + E` | Open emoji picker | + | `Super + V` | Open clipboard history | + | `Super + W` | Open wallpaper browser | + +- **Deep Reload a Plugin**: After editing `config/plugins/hello.py`: + + ```bash + fabric-cli exec modus1 'deep_reload hello' + ``` + + No Modus restart required. Works with all plugins. + +- **Test a Plugin from Terminal**: + + ```bash + fabric-cli exec modus1 'wth london' + ``` + + Routes to the weather plugin's `search()` and prints results to the Modus log. + +- **Check Plugin Load Log**: + + ```bash + journalctl --user -f -t modus + ``` + + Filters to Modus messages only. Shows plugin discovery, load errors, and + search crashes. + +- **Wayland Screencapture**: Toggle from panel or bind in Hyprland: + `bind = SUPER, S, exec, fabric-cli exec modus 'screencapture.toggle()'`