pinnacle/src/main.rs

154 lines
5.5 KiB
Rust
Raw Normal View History

2023-08-01 11:06:35 -05:00
// SPDX-License-Identifier: GPL-3.0-or-later
2023-06-21 18:58:49 -05:00
//! A very, VERY WIP Smithay-based Wayland compositor.
//!
//! Pinnacle is heavily inspired by the [Awesome Window Manager](https://awesomewm.org),
//! and this is an attempt to make something akin to it for Wayland.
//!
2023-06-21 19:08:29 -05:00
//! While Pinnacle is not a library, this documentation serves to guide those who want to
2023-06-21 18:58:49 -05:00
//! contribute or learn how building something like this works.
// #![deny(unused_imports)] // this has remained commented out for months lol
#![warn(clippy::unwrap_used)]
2023-06-29 12:29:00 -05:00
use anyhow::Context;
2023-12-19 15:09:36 +04:00
use nix::unistd::Uid;
use pinnacle::{
backend::{udev::setup_udev, winit::setup_winit},
cli::{self, Cli},
};
use tracing::{info, level_filters::LevelFilter, warn};
2023-09-14 01:34:20 -05:00
use tracing_appender::rolling::Rotation;
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt, EnvFilter, Layer};
2023-09-11 02:48:33 -05:00
use xdg::BaseDirectories;
2023-09-08 00:21:09 -05:00
2024-01-08 13:43:38 -06:00
#[tokio::main]
2024-01-08 12:51:04 -06:00
async fn main() -> anyhow::Result<()> {
2024-02-17 00:00:25 -06:00
let xdg_state_dir = BaseDirectories::with_prefix("pinnacle")?.get_state_home();
2023-09-11 02:48:33 -05:00
2023-09-14 01:34:20 -05:00
let appender = tracing_appender::rolling::Builder::new()
.rotation(Rotation::HOURLY)
.filename_suffix("pinnacle.log")
.max_log_files(8)
.build(xdg_state_dir)
.context("failed to build file logger")?;
2023-09-11 02:48:33 -05:00
let (appender, _guard) = tracing_appender::non_blocking(appender);
let env_filter = EnvFilter::try_from_default_env();
2023-09-11 02:48:33 -05:00
let file_log_env_filter = match env_filter.as_ref() {
Ok(filter) if filter.max_level_hint() == Some(LevelFilter::TRACE) => {
EnvFilter::new("trace")
}
_ => EnvFilter::new("debug"),
};
let file_log_layer = tracing_subscriber::fmt::layer()
.compact()
.with_writer(appender)
.with_filter(file_log_env_filter);
let stdout_env_filter = env_filter.unwrap_or_else(|_| EnvFilter::new("info"));
let stdout_layer = tracing_subscriber::fmt::layer()
2023-09-11 02:48:33 -05:00
.compact()
.with_writer(std::io::stdout)
.with_filter(stdout_env_filter);
tracing_subscriber::registry()
.with(file_log_layer)
.with(stdout_layer)
2023-09-11 02:48:33 -05:00
.init();
2023-06-15 12:42:34 -05:00
2024-03-03 02:25:19 -06:00
let Some(cli) = Cli::parse_and_prompt() else {
return Ok(());
};
2023-09-08 00:21:09 -05:00
if Uid::effective().is_root() {
2024-03-03 02:25:19 -06:00
if !cli.allow_root {
warn!("You are trying to run Pinnacle as root.");
warn!("This is NOT recommended.");
2024-03-03 02:25:19 -06:00
warn!("To run Pinnacle as root, pass in the `--allow-root` flag.");
warn!("Again, this is NOT recommended.");
return Ok(());
} else {
warn!("Running Pinnacle as root. I hope you know what you're doing 🫡");
}
2023-09-08 00:21:09 -05:00
}
2023-08-08 13:25:47 -05:00
let in_graphical_env =
std::env::var("WAYLAND_DISPLAY").is_ok() || std::env::var("DISPLAY").is_ok();
2024-01-29 20:46:18 -06:00
if !sysinfo::set_open_files_limit(0) {
warn!("Unable to set `sysinfo`'s open files limit to 0.");
warn!("You may see LOTS of file descriptors open under Pinnacle.");
2024-01-29 20:46:18 -06:00
}
2024-03-04 15:54:30 -06:00
let (mut state, mut event_loop) = match (cli.backend, cli.force) {
2024-03-02 01:23:31 -06:00
(None, _) => {
2023-09-08 00:21:09 -05:00
if in_graphical_env {
info!("Starting winit backend");
setup_winit(cli.no_config, cli.config_dir)?
2023-09-08 00:21:09 -05:00
} else {
info!("Starting udev backend");
setup_udev(cli.no_config, cli.config_dir)?
2023-09-08 00:21:09 -05:00
}
}
2024-03-02 01:23:31 -06:00
(Some(cli::Backend::Winit), force) => {
2023-08-08 13:25:47 -05:00
if !in_graphical_env {
2023-09-08 00:21:09 -05:00
if force {
warn!("Starting winit backend with no detected graphical environment");
setup_winit(cli.no_config, cli.config_dir)?
2023-08-08 13:25:47 -05:00
} else {
warn!("Both WAYLAND_DISPLAY and DISPLAY are not set.");
warn!("If you are trying to run the winit backend in a tty, it won't work.");
2024-03-03 02:25:19 -06:00
warn!("If you really want to, additionally pass in the `--force` flag.");
2024-03-04 15:54:30 -06:00
return Ok(());
2023-08-08 13:25:47 -05:00
}
} else {
info!("Starting winit backend");
setup_winit(cli.no_config, cli.config_dir)?
2023-08-08 13:25:47 -05:00
}
}
2024-03-02 01:23:31 -06:00
(Some(cli::Backend::Udev), force) => {
2023-08-08 13:25:47 -05:00
if in_graphical_env {
2023-09-08 00:21:09 -05:00
if force {
warn!("Starting udev backend with a detected graphical environment");
setup_udev(cli.no_config, cli.config_dir)?
2023-08-08 13:25:47 -05:00
} else {
warn!("WAYLAND_DISPLAY and/or DISPLAY are set.");
warn!("If you are trying to run the udev backend in a graphical environment,");
warn!("it won't work and may mess some things up.");
2024-03-03 02:25:19 -06:00
warn!("If you really want to, additionally pass in the `--force` flag.");
2024-03-04 15:54:30 -06:00
return Ok(());
2023-08-08 13:25:47 -05:00
}
} else {
info!("Starting udev backend");
setup_udev(cli.no_config, cli.config_dir)?
2023-08-08 13:25:47 -05:00
}
}
2024-03-04 15:54:30 -06:00
};
event_loop.run(None, &mut state, |state| {
state.update_pointer_focus();
2024-03-04 20:38:20 -06:00
state.fixup_z_layering();
2024-03-04 15:54:30 -06:00
state.space.refresh();
state.popup_manager.cleanup();
2024-03-04 20:38:20 -06:00
2024-03-04 15:54:30 -06:00
state
.display_handle
.flush_clients()
.expect("failed to flush client buffers");
2024-03-04 20:38:20 -06:00
// TODO: couple these or something, this is really error-prone
assert_eq!(
state.windows.len(),
state.z_index_stack.len(),
"Length of `windows` and `z_index_stack` are different. \
If you see this, report it to the developer."
);
2024-03-04 15:54:30 -06:00
})?;
2023-06-19 12:42:49 -05:00
Ok(())
}