pinnacle/src/main.rs

181 lines
5.9 KiB
Rust
Raw Normal View History

2023-08-01 18:06:35 +02:00
// SPDX-License-Identifier: GPL-3.0-or-later
2023-06-22 01:58:49 +02: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-22 02:08:29 +02:00
//! While Pinnacle is not a library, this documentation serves to guide those who want to
2023-06-22 01:58:49 +02:00
//! contribute or learn how building something like this works.
2023-09-09 05:08:56 +02:00
// #![deny(unused_imports)] // gonna force myself to keep stuff clean
#![warn(clippy::unwrap_used)]
2023-06-29 19:29:00 +02:00
2023-09-11 09:48:33 +02:00
use std::path::Path;
2023-09-08 07:21:09 +02:00
use clap::Parser;
2023-09-11 09:48:33 +02:00
use tracing_subscriber::{fmt::writer::MakeWriterExt, EnvFilter};
use walkdir::WalkDir;
use xdg::BaseDirectories;
2023-09-08 07:21:09 +02:00
2023-06-18 01:55:04 +02:00
mod api;
mod backend;
mod cursor;
2023-06-18 04:02:58 +02:00
mod focus;
mod grab;
mod handlers;
mod input;
mod layout;
2023-08-15 03:19:38 +02:00
mod metaconfig;
2023-06-26 03:26:52 +02:00
mod output;
mod pointer;
mod render;
mod state;
2023-07-01 04:34:07 +02:00
mod tag;
mod window;
2023-09-11 09:48:33 +02:00
lazy_static::lazy_static! {
pub static ref XDG_BASE_DIRS: BaseDirectories =
BaseDirectories::with_prefix("pinnacle").expect("couldn't create xdg BaseDirectories");
}
2023-09-08 07:21:09 +02:00
#[derive(clap::Args, Debug)]
2023-09-09 03:20:00 +02:00
#[group(id = "backend", required = false, multiple = false)]
2023-09-08 07:21:09 +02:00
struct Backends {
#[arg(long, group = "backend")]
/// Run Pinnacle in a window in your graphical environment
winit: bool,
#[arg(long, group = "backend")]
/// Run Pinnacle from a tty
udev: bool,
}
#[derive(clap::Parser, Debug)]
#[command(author, version, about, long_about = None)]
struct Args {
#[command(flatten)]
backend: Backends,
#[arg(long)]
/// Allow running Pinnacle as root (this is NOT recommended)
allow_root: bool,
#[arg(long, requires = "backend")]
/// Force Pinnacle to run with the provided backend
force: bool,
}
2023-09-11 09:48:33 +02:00
const PINNACLE_LOG_PREFIX: &str = "pinnacle.log";
2023-08-16 18:28:35 +02:00
fn main() -> anyhow::Result<()> {
2023-09-11 09:48:33 +02:00
let xdg_state_dir = XDG_BASE_DIRS.get_state_home();
trim_logs(&xdg_state_dir);
2023-09-11 10:05:45 +02:00
let appender = tracing_appender::rolling::hourly(&xdg_state_dir, PINNACLE_LOG_PREFIX);
2023-09-11 09:48:33 +02:00
let (appender, _guard) = tracing_appender::non_blocking(appender);
let writer = appender.and(std::io::stdout);
let env_filter = EnvFilter::try_from_default_env().unwrap_or(EnvFilter::new("debug"));
tracing_subscriber::fmt()
.compact()
.with_env_filter(env_filter)
.with_writer(writer)
.init();
2023-06-15 19:42:34 +02:00
2023-09-08 07:21:09 +02:00
let args = Args::parse();
if smithay::reexports::nix::unistd::Uid::effective().is_root() && !args.allow_root {
println!("You are trying to run Pinnacle as root.\nThis is NOT recommended.\nTo run Pinnacle as root, pass in the --allow-root flag. Again, this is NOT recommended.");
return Ok(());
}
2023-08-08 20:25:47 +02:00
let in_graphical_env =
std::env::var("WAYLAND_DISPLAY").is_ok() || std::env::var("DISPLAY").is_ok();
2023-09-08 07:21:09 +02:00
match (args.backend.winit, args.backend.udev, args.force) {
(false, false, _) => {
if in_graphical_env {
tracing::info!("Starting winit backend");
crate::backend::winit::run_winit()?;
} else {
tracing::info!("Starting udev backend");
crate::backend::udev::run_udev()?;
}
}
(true, false, force) => {
2023-08-08 20:25:47 +02:00
if !in_graphical_env {
2023-09-08 07:21:09 +02:00
if force {
tracing::warn!("Starting winit backend with no detected graphical environment");
2023-08-08 20:25:47 +02:00
crate::backend::winit::run_winit()?;
} else {
2023-09-08 07:21:09 +02:00
println!("Both WAYLAND_DISPLAY and DISPLAY are not set.");
2023-08-08 20:25:47 +02:00
println!("If you are trying to run the winit backend in a tty, it won't work.");
println!("If you really want to, additionally pass in the --force flag.");
}
} else {
tracing::info!("Starting winit backend");
crate::backend::winit::run_winit()?;
}
}
2023-09-08 07:21:09 +02:00
(false, true, force) => {
2023-08-08 20:25:47 +02:00
if in_graphical_env {
2023-09-08 07:21:09 +02:00
if force {
tracing::warn!("Starting udev backend with a detected graphical environment");
2023-08-08 20:25:47 +02:00
crate::backend::udev::run_udev()?;
} else {
2023-09-08 07:21:09 +02:00
println!("WAYLAND_DISPLAY and/or DISPLAY are set.");
2023-08-08 20:25:47 +02:00
println!(
"If you are trying to run the udev backend in a graphical environment,"
);
println!("it won't work and may mess some things up.");
println!("If you really want to, additionally pass in the --force flag.");
}
} else {
tracing::info!("Starting udev backend");
crate::backend::udev::run_udev()?;
}
}
2023-09-08 07:21:09 +02:00
_ => unreachable!(),
2023-06-19 19:42:49 +02:00
}
Ok(())
}
2023-09-11 09:48:33 +02:00
fn trim_logs(log_path: impl AsRef<Path>) {
let logs = WalkDir::new(log_path)
.sort_by(|a, b| {
let a_creation_time = a
.metadata()
.expect("failed to get log metadata")
.created()
.expect("failed to get log creation time");
let b_creation_time = b
.metadata()
.expect("failed to get log metadata")
.created()
.expect("failed to get log creation time");
a_creation_time.cmp(&b_creation_time)
})
2023-09-11 10:05:45 +02:00
.contents_first(true)
2023-09-11 09:48:33 +02:00
.into_iter()
.filter_entry(|entry| {
entry.file_type().is_file()
&& entry
.file_name()
.to_string_lossy()
.starts_with(PINNACLE_LOG_PREFIX)
})
.filter_map(|dir| dir.ok())
.collect::<Vec<_>>();
2023-09-11 10:05:45 +02:00
// If there are more than 4 logs, delete all but 3
if logs.len() > 4 {
let num_to_delete = logs.len().saturating_sub(3);
for entry in logs.into_iter().take(num_to_delete) {
tracing::info!("Deleting {:?}", entry.path());
std::fs::remove_file(entry.path()).expect("failed to remove oldest log file");
}
2023-09-11 09:48:33 +02:00
}
}