diff --git a/README.md b/README.md index 7fcf303..3088c3c 100644 --- a/README.md +++ b/README.md @@ -35,6 +35,14 @@ Pinnacle is a Wayland compositor built in Rust using [Smithay](https://github.co It's my attempt at creating something like [AwesomeWM](https://github.com/awesomeWM/awesome) for Wayland. +### What is Snowcap? +You will see references to Snowcap throughout this README. [Snowcap](https://github.com/pinnacle-comp/snowcap) is the +very, *very* WIP widget system for Pinnacle. Currently it's only being used for the builtin quit prompt and keybind overlay. +In the future, Snowcap will be used for everything Awesome uses its widget system for: a taskbar, system tray, etc. + +> [!NOTE] +> Only the Rust API has implemented Snowcap integration currently. Lua support soon™️ + ### Features - Tag system - Customizable layouts, including most of the ones from Awesome @@ -42,6 +50,7 @@ for Wayland. - wlr-layer-shell support - Configurable in Lua or Rust - wlr-screencopy support +- A really *really* WIP widget system - Is very cool :thumbsup: ### Roadmap @@ -51,57 +60,63 @@ for Wayland. You will need: - [Rust](https://www.rust-lang.org/) 1.75 or newer -- Packages for [Smithay](https://github.com/Smithay/smithay): - `libwayland libxkbcommon libudev libinput libgdm libseat`, as well as `xwayland` - - Arch: - ```sh - sudo pacman -S wayland wayland-protocols libxkbcommon systemd-libs libinput mesa seatd xorg-xwayland - ``` - - Debian/Ubuntu: - ```sh - sudo apt install libwayland-dev libxkbcommon-dev libudev-dev libinput-dev libgdm-dev libseat-dev xwayland - ``` - - NixOS: There is flake [`flake.nix`](flake.nix) with a devShell. It also +- The following external dependencies: + - `libwayland` + - `libxkbcommon` + - `libudev` + - `libinput` + - `libgbm` + - `libseat` + - `libEGL` + - `libsystemd` + - `libdisplay-info` for monitor display information + - `xwayland` for Xwayland support + - [`protoc`](https://grpc.io/docs/protoc-installation/) for the API + +The following are optional dependencies: + +- [`just`](https://github.com/casey/just) to automate installation of libraries and files +- The following are required to use the Lua API: + - `just` as mentioned above + - [`lua`](https://www.lua.org/) 5.2 or newer + - [`luarocks`](https://luarocks.org/) for API installation + - You must run `eval $(luarocks path --lua-version )` so that your config can find the API + library files. It is recommended to place this command in your shell's startup script. + +- Arch and derivatives: + ```sh + sudo pacman -S wayland libxkbcommon libinput mesa seatd systemd-libs libdisplay-info xorg-xwayland protobuf + # And optionally + sudo pacman -S just lua luarocks + ``` +- Debian and derivatives: + ```sh + sudo apt install libwayland-dev libxkbcommon-dev libudev-dev libinput-dev libgbm-dev libseat-dev libsystemd-dev protobuf-compiler xwayland libegl-dev libdisplay-info-dev + # And optionally + sudo apt install just lua5.4 luarocks + ``` + - Note: `just` is only available in apt from Debian 13. +- Nix and NixOS: + - Use the provided [`flake.nix`](flake.nix) with a devShell. It also includes the other tools needed for the build and sets up the `LD_LIBRARY_PATH` so the dynamically loaded libraries are found. > Luarocks currently doesn't install the Lua library and its dependencies due to openssh directory > shenanigans. Fix soon, hopefully. In the meantime you can use the Rust API. -- `libdisplay-info`, for monitor display information -- [protoc](https://grpc.io/docs/protoc-installation/), the Protocol Buffer Compiler, for configuration - - Arch: - ```sh - sudo pacman -S protobuf - ``` - - Debian/Ubuntu: - ```sh - sudo apt install protobuf-compiler - ``` -- [just](https://github.com/casey/just), to automate installation of libraries and files - - You don't *need* this but without installation you will not be able to run `cargo run -- config gen` or - use the Lua API (it requires the protobuf definitions at runtime) - - Arch: - ```sh - sudo pacman -S just - ``` - -If you would like to use the Lua API, you will additionally need: - -- [Lua](https://www.lua.org/) 5.2 or newer -- [LuaRocks](https://luarocks.org/), the Lua package manager - - Arch: - ```sh - sudo pacman -S luarocks - ``` - - Debian/Ubuntu: - ```sh - sudo apt install luarocks - ``` - - You must run `eval $(luarocks path --lua-version )` so that your config can find the API - library files. It is recommended to place this command in your shell's startup script. TODO: other distros # Building + +Clone this repository and, if building with Snowcap integration, update the `snowcap` submodule: +```sh +git clone https://github.com/pinnacle-comp/pinnacle +git submodule update --init +``` + +> [!NOTE] +> For all following `cargo`/`just` commands, if you would like to build without Snowcap integration, +> run with `--no-default-features`. + Build the project with: ```sh cargo build [--release] @@ -126,6 +141,16 @@ After building, run the executable located in either: ./target/release/pinnacle # with --release ``` +> [!IMPORTANT] +> When compiling with Snowcap integration, if you do not have Vulkan set up properly, +> Pinnacle will crash on startup. +> +> For those using Nix outside of NixOS, you will need to run the built binary +> with [nixGL](https://github.com/nix-community/nixGL) using *both* GL and Vulkan wrappers, nested inside one another: +> ``` +> nix run --impure github:nix-community/nixGL -- nix run --impure github:nix-community/nixGL#nixVulkanIntel -- ./target/debug/pinnacle +> ``` + Or, run the project directly with ```sh cargo run [--release] @@ -145,12 +170,16 @@ the Lua or Rust default configs standalone, run one of the following in the crat ```sh # For a Lua configuration -cargo run -- -c "./api/lua/examples/default" just install run -- -c "./api/lua/examples/default" # For a Rust configuration cargo run -- -c "./api/rust/examples/default_config" -just install run -- -c "./api/rust/examples/default_config" +``` + +When running the default Rust config standalone without compiled Snowcap integration, +run the one in the following directory: +```sh +cargo run -- -c "./api/rust/examples/default_config_no_snowcap" ``` ## Custom configuration @@ -161,15 +190,9 @@ just install run -- -c "./api/rust/examples/default_config" ### Generating a config -> [!NOTE] -> The default configs must be installed for them to be copied: -> ```sh -> just install-configs # Or alternatively, `just install` which installs everything -> ``` - Run the following command to open up the interactive config generator: ```sh -cargo run -- config gen +just install-configs run -- config gen ``` This will prompt you to choose a language (Lua or Rust) and directory to put the config in. @@ -232,6 +255,7 @@ Rust: https://pinnacle-comp.github.io/rust-reference/main. The following are the default controls in the [`default_config`](api/rust/examples/default_config/main.rs). | Binding | Action | |----------------------------------------------|------------------------------------| +| Ctrl + s | Show the keybind overlay | | Ctrl + Mouse left drag | Move window | | Ctrl + Mouse right drag| Resize window | | CtrlAlt + q | Quit Pinnacle | diff --git a/flake.nix b/flake.nix index 06052eb..372e82d 100644 --- a/flake.nix +++ b/flake.nix @@ -50,6 +50,7 @@ libinput mesa xwayland + libdisplay-info # winit on x11 xorg.libXcursor diff --git a/snowcap b/snowcap index d2f44f2..3e79a16 160000 --- a/snowcap +++ b/snowcap @@ -1 +1 @@ -Subproject commit d2f44f2ee5755d694822593d0219b9d9304109ab +Subproject commit 3e79a16e1065f07001b08fabdc763bb274cac394 diff --git a/src/main.rs b/src/main.rs index 03ac5ae..26ba9a6 100644 --- a/src/main.rs +++ b/src/main.rs @@ -186,14 +186,21 @@ async fn main() -> anyhow::Result<()> { let (ping, source) = calloop::ping::make_ping()?; let ready_flag = Arc::new(AtomicBool::new(false)); let ready_clone = ready_flag.clone(); - tokio::task::spawn_blocking(move || { + let join_handle = tokio::task::spawn_blocking(move || { + let _span = tracing::error_span!("snowcap"); + let _span = _span.enter(); snowcap::start(Some(source), ready_clone); }); + while !ready_flag.load(Ordering::SeqCst) { - event_loop.dispatch(None, &mut state)?; + if join_handle.is_finished() { + panic!("snowcap failed to start"); + } + event_loop.dispatch(Duration::from_secs(1), &mut state)?; state.on_event_loop_cycle_completion(); } state.pinnacle.snowcap_shutdown_ping = Some(ping); + state.pinnacle.snowcap_join_handle = Some(join_handle); } if !metaconfig.no_xwayland { diff --git a/src/state.rs b/src/state.rs index 9c1da46..5535a22 100644 --- a/src/state.rs +++ b/src/state.rs @@ -158,6 +158,8 @@ pub struct Pinnacle { #[cfg(feature = "snowcap")] pub snowcap_shutdown_ping: Option, + #[cfg(feature = "snowcap")] + pub snowcap_join_handle: Option>, } impl State { @@ -173,6 +175,19 @@ impl State { winit.render_if_scheduled(&mut self.pinnacle); } + #[cfg(feature = "snowcap")] + if self + .pinnacle + .snowcap_join_handle + .as_ref() + .is_some_and(|handle| handle.is_finished()) + { + // If Snowcap is dead, the config has most likely crashed or will crash if it's used. + // The embedded config will also fail to start. + // We'll panic here just so people aren't stuck in the compositor. + panic!("snowcap has exited"); + } + // FIXME: Don't poll this every cycle for output in self.pinnacle.space.outputs().cloned().collect::>() { output.with_state_mut(|state| { @@ -361,6 +376,8 @@ impl Pinnacle { #[cfg(feature = "snowcap")] snowcap_shutdown_ping: None, + #[cfg(feature = "snowcap")] + snowcap_join_handle: None, }; Ok(pinnacle)