Restructure codebase into modular architecture#1
Closed
Conversation
Split monolithic main.rs into focused modules to support: - Multi-compositor backends (Niri, Sway, Hyprland) - Future TUI integration - Cleaner separation of concerns New structure: - src/lib.rs: Library crate with module re-exports - src/bin/nasw.rs: Binary entry point - src/cli.rs: CLI argument definitions - src/config.rs: Configuration loading and validation - src/pipewire.rs: PipeWire types and interface - src/notification.rs: Desktop notifications and icons - src/state.rs: Application state and event processing - src/commands.rs: One-shot CLI commands - src/daemon.rs: Daemon mode event loop - src/compositor/: Compositor abstraction layer - mod.rs: Compositor trait and WindowEvent enum - niri.rs: Niri IPC implementation This enables adding Sway/Hyprland support by implementing the Compositor trait, and prepares for a separate TUI binary that can share the library code.
- Restore checkmark (✓) in config validation output - Use unicode arrow (→) consistently in log messages (state.rs, commands.rs, pipewire.rs)
Implement SwayCompositor using i3-ipc protocol: - Binary protocol: magic + length + type + JSON payload - Subscribe to window events (new, close, title) - Handle both native Wayland (app_id) and XWayland (window class) XWayland handling: - Native Wayland windows use app_id - XWayland windows use window_properties.class as app_id equivalent - Falls back to instance if class unavailable Architecture: - Add AnyCompositor enum for runtime dispatch (async traits not dyn-compatible) - compositor::detect() auto-detects via NIRI_SOCKET or SWAYSOCK env vars - Update daemon to use auto-detection instead of hardcoded Niri Supported compositors: Niri, Sway (Hyprland planned)
Co-authored-by: ledati16 <[email protected]>
…pport Co-authored-by: ledati16 <[email protected]>
Co-authored-by: ledati16 <[email protected]>
Replace compositor-specific IPC with Wayland protocols for broader support
…dead code Co-authored-by: ledati16 <[email protected]>
…ntations Co-authored-by: ledati16 <[email protected]>
Co-authored-by: ledati16 <[email protected]>
Co-authored-by: ledati16 <[email protected]>
Fix channel closure detection, race conditions, and optimize protocol detection
Check if the event channel receiver has been dropped after each dispatch. This allows the Wayland thread to exit cleanly when the daemon shuts down via Ctrl+C, rather than blocking indefinitely in the event loop. Note: The thread will still block until the next Wayland event arrives, but will then exit gracefully rather than continuing to run.
- Rename binary from nasw to pwsw (src/bin/nasw.rs → src/bin/pwsw.rs) - Update package name, description, repository URL in Cargo.toml - Bump version to 0.3.0 for the rename - Update config directory from ~/.config/nasw to ~/.config/pwsw - Update CLI name and description - Update notification app name to PWSW - Update log filter prefix to pwsw= - Update all documentation and README references The name change reflects that the tool now supports multiple Wayland compositors via standard protocols, not just Niri.
…6PGpuKhi7sB5xBALhk
Co-authored-by: ledati16 <[email protected]>
Co-authored-by: ledati16 <[email protected]>
Co-authored-by: ledati16 <[email protected]>
- Created src/ipc.rs with Request/Response types and Unix socket IPC - Restructured src/cli.rs to use subcommands instead of flags - Updated src/bin/pwsw.rs to dispatch to subcommands - Added IPC-based commands to src/commands.rs (status, reload, shutdown, list-windows, test-rule) - Integrated IPC server into daemon event loop in src/daemon.rs - Updated State to track app_id and title for IPC queries - Added tokio time feature for IPC timeouts Co-authored-by: ledati16 <[email protected]>
- Updated project overview to reflect IPC-based daemon commands - Documented daemon management section - Updated running examples with subcommand syntax - Documented IPC socket location - Removed references to old flag-based commands Co-authored-by: ledati16 <[email protected]>
- Use async socket check in cleanup_stale_socket to avoid blocking - Replace std::process::exit with broadcast channel for graceful shutdown - Clarify reload message (config validation only, restart needed for full reload) - Fix duplicate logging initialization issue in bin/pwsw.rs Co-authored-by: ledati16 <[email protected]>
- Use username-based socket path in /tmp fallback (/tmp/pwsw-$USER.sock) - Improve socket cleanup error handling with clearer pattern matching - Remove unused import Co-authored-by: ledati16 <[email protected]>
- Fix protocol detection to properly use GlobalList's with_list() API - Add event_created_child! macro for wlr-foreign-toplevel manager (required for correct wayland-client event dispatching) - Add debug logging for detected globals - Remove unnecessary event handling in registry dispatch These fixes address runtime issues with compositor protocol detection introduced in the IPC infrastructure changes.
- Add early daemon detection with clear error messages - Fix default command: 'pwsw' now shows status instead of starting daemon - Implement proper foreground/background modes for 'pwsw daemon' - Improve status command to show helpful startup instructions when daemon not running - Add CLAUDE.md with project documentation for LLM assistance 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Command Improvements: - test-rule: Now tests against ALL open windows (not just tracked ones) - test-rule: Tests both app_id and title fields with match indicators - list-windows: Shows all windows grouped by tracked vs untracked status - list-windows: Displays which sink tracked windows are using CLI Refinements: - Remove redundant 'reload' command (use 'pwsw shutdown && pwsw daemon') - Update help text for clarity and consistency - Clearly indicate which commands require running daemon - Add helpful first-run message when config is auto-created State Management: - Track all open windows efficiently (HashMap scales with open windows) - Windows automatically removed from tracking on close - Minimal memory overhead (~50-200 bytes per window) User Experience: - First-time users get clear next steps when config is created - Improved help text with better organization and examples - Config restart instructions included in help 🤖 Generated with [Claude Code](https://claude.com/claude-code)
…PWSW_TUI_DEBUG_MOUSE
…edraw implemented)
…ss and next steps
…pipeline - Store compiled regexes as Option<Arc<Regex>> in RuleEditor - Send cloned Arc caches to background preview worker to avoid recompilation - Replace render-time Regex usage to prefer cached Arcs - Update input handlers to eagerly update caches and send previews Co-Authored-By: Automation <no-reply@autobot> 🤖 Generated with CLAUDE.md-guided assistant
…ded displays \nSummary:\n- Cache compiled regexes and prefer cached usage for previews and saves\n- Add padded display cache for Sinks and Settings to avoid per-frame formatting\n- Use sink padded-display lookup in Rules list to align sink column\n- Replace hot-path format! allocations with span-based rendering\n- Update TEMP_TUI_REFACTOR.md to record progress and next steps \n🤖 Generated with [Claude Code](https://claude.com/claude-code)\n\nCo-Authored-By: Claude Sonnet 4.5 <[email protected]>
…MP_TUI_REFACTOR.md requirement
… TEMP_TUI_REFACTOR.md and push policy
Adds grapheme-aware unit tests for SimpleEditor word navigation and Ctrl+Backspace.
… word-nav Update TEMP_TUI_REFACTOR.md and add edge-case tests for word navigation.
Add pub(crate) simulate_key_event and integration tests for Ctrl+Word navigation and Ctrl+Backspace; update TEMP_TUI_REFACTOR.md
Allow Up/Down arrows to move between fields in Add/Edit modals; strengthen focused textfield styling; improve sink selector affordance; update help hints
…pacing Draw thin focus border on focused text fields; use colored spans for checkmarks and notify state; reduce vertical padding in add/edit modals for tighter layout
…n\n- Add left-side focus indicator and tighten field/modal spacing\n- Add focus rectangle and colored indicators for fields and lists\n- Improve modal navigation and keyboard handling across screens\n- Update cached display descriptions and sink selection behavior\n\nSigned-off-by: automated-agent <agent@local>
ledati16
added a commit
that referenced
this pull request
Dec 21, 2025
- Add DEVICE_LOCKS cleanup to prevent memory leak (max 100 devices) - Change Wayland event channel from unbounded to bounded (capacity: 100) - Use blocking_send() to apply backpressure when channel is full - Add 2 tests for device lock cleanup behavior Fixes two high-priority resource management issues: - Issue #1: DEVICE_LOCKS unbounded growth from USB device churn - Issue #3: Unbounded Wayland channel memory growth Test results: 109 tests passing (was 107, added 2) See src_plan.md for implementation details and remaining phases. 🤖 Generated with Claude Code (https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <[email protected]>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This pull request rebrands the project from "NASW" (Niri Audio Switcher) to "PWSW" (PipeWire Switcher), broadening its scope from a Niri-specific tool to a Wayland compositor-agnostic audio switcher. The documentation, configuration, and build files have all been updated to reflect this new focus, including support for multiple compositors via standard Wayland protocols and improved clarity on usage, supported platforms, and architecture. Additionally, a new
CLAUDE.mdfile has been added to provide detailed guidance for contributors and LLMs.Project rebranding and scope expansion:
Documentation and configuration improvements:
wlr-foreign-toplevel-managementandplasma-window-management), and clarified that GNOME/Mutter is not supported.Build system and dependency updates:
Cargo.tomlto reflect the new project name, version, description, keywords, and repository. Added explicit dependencies for Wayland protocol support (wayland-client,wayland-protocols-wlr,wayland-protocols-plasma) and expanded Tokio features.Contributor guidance:
CLAUDE.mdfile with project overview, architecture, build instructions, configuration notes, and common pitfalls to assist contributors and LLMs in understanding and safely modifying the codebase.General improvements and clarifications:
CLAUDE.md) is added, and theCargo.tomlis updated to reflect new dependencies and project metadata.Project rebranding and documentation overhaul:
README.md,Cargo.toml, and configuration examples. The description and keywords are updated to reflect broader Wayland compositor support, not just Niri. [1] [2] [3] [4] [5] [6] [7] [8]Expanded compositor and protocol support:
wlr-foreign-toplevel-managementandplasma-window-management), listing compatible compositors explicitly and noting that GNOME/Mutter is not supported.Improved user and developer guidance:
CLAUDE.mdfile provides a detailed overview of the architecture, threading model, configuration, and testing procedures for developers and advanced users.README.mdis updated with clearer instructions for building, running, and managing the daemon, as well as for using IPC commands and finding relevant configuration fields. [1] [2]Dependency and configuration updates:
Cargo.tomlis updated with new project metadata, repository URL, and additional dependencies for Wayland protocol support (wayland-client,wayland-protocols-wlr,wayland-protocols-plasma). Thetokiodependency is expanded with more features for async support.Configuration and usage improvements:
These changes collectively modernize the project, clarify its scope and usage, and provide both users and contributors with more comprehensive and accurate information.This pull request renames the project from "NASW" (Niri Audio Switcher) to "PWSW" (PipeWire Switcher) and broadens its focus from the Niri compositor to general Wayland compositors using standard window management protocols. The documentation and configuration have been updated to reflect this, and the codebase now includes new modules for CLI argument parsing and command handling. The most important changes are summarized below.
Project-wide rebranding and protocol support:
wlr-foreign-toplevel-managementorplasma-window-managementprotocols, rather than being specific to Niri. The documentation lists supported compositors and explains the use of standard protocols for broader compatibility. [1] [2]Documentation and configuration updates:
README.mdis extensively revised to reflect the new name, supported compositors, updated usage examples, and configuration paths. Instructions and examples now usepwswinstead ofnasw, and references to Niri-specific features are replaced with Wayland protocol-based descriptions. [1] [2] [3] [4] [5] [6]Dependency and build updates:
Cargo.tomlis updated to add dependencies for Wayland protocol support (wayland-client,wayland-protocols-wlr,wayland-protocols-plasma) and to enable thesyncfeature fortokio. The project metadata is updated to match the new name and scope.New and refactored code modules:
src/cli.rsmodule defines the command-line interface usingclap, including detailed help and argument parsing for all supported commands.src/commands.rsmodule implements the logic for one-shot CLI commands such as--list-sinks,--get-sink,--set-sink,--next-sink, and--prev-sink, with improved output formatting and integration with the updated configuration.Split monolithic main.rs into focused modules to support:New structure:
This enables adding Sway/Hyprland support by implementing the
Compositor trait, and prepares for a separate TUI binary that
can share the library code.