mod clients; mod color; mod color_management; mod config; mod damage_tracking; mod dpms; mod duration; mod generate; mod idle; mod input; mod json; mod log; mod pid; mod quit; mod randr; mod reexec; pub mod screenshot; mod seat_test; mod set_log_level; mod tree; mod unlock; mod version; mod xwayland; use { crate::{ cli::{ clients::ClientsArgs, color_management::ColorManagementArgs, config::ConfigArgs, damage_tracking::DamageTrackingArgs, idle::IdleCmd, input::InputArgs, json::VERBOSE_JSON, randr::RandrArgs, reexec::ReexecArgs, tree::TreeArgs, xwayland::XwaylandArgs, }, compositor::start_compositor, logger::LogLevel, portal, pr_caps::drop_all_pr_caps, }, clap::{Args, Parser, Subcommand, ValueEnum, ValueHint}, clap_complete::Shell, std::sync::atomic::Ordering::Relaxed, }; /// A wayland compositor. #[derive(Parser, Debug)] struct Jay { #[clap(flatten)] global: GlobalArgs, #[clap(subcommand)] command: Cmd, } #[derive(Args, Debug)] pub struct GlobalArgs { /// The log level. #[clap(value_enum, long, default_value_t)] pub log_level: LogLevel, /// Output data as JSONL. #[clap(long)] pub json: bool, /// Print all fields in JSON output. /// /// By default, some fields that are empty arrays, null, or false are omitted. #[clap(long)] pub all_json_fields: bool, } #[derive(Subcommand, Debug)] pub enum Cmd { /// Run the compositor. Run(RunArgs), /// Create/modify the toml config. Config(ConfigArgs), /// Generate shell completion scripts for jay. GenerateCompletion(GenerateArgs), /// Open the log file. Log(LogArgs), /// Sets the log level. SetLogLevel(SetLogArgs), /// Stop the compositor. Quit, /// Unlocks the compositor. Unlock, /// Take a screenshot. Screenshot(ScreenshotArgs), /// Inspect/modify the idle (screensaver) settings. Idle(IdleArgs), /// Turn monitors on or off. Dpms(DpmsArgs), /// Tests the events produced by a seat. SeatTest(SeatTestArgs), /// Run the desktop portal. Portal, /// Inspect/modify graphics card and connector settings. Randr(RandrArgs), /// Inspect/modify input settings. Input(InputArgs), /// Modify damage tracking settings. (Only for debugging.) #[clap(hide = true)] DamageTracking(DamageTrackingArgs), /// Inspect/modify xwayland settings. Xwayland(XwaylandArgs), /// Inspect/modify the color-management settings. ColorManagement(ColorManagementArgs), /// Replace the compositor by another process. (Only for development.) #[clap(hide = true)] Reexec(ReexecArgs), /// Inspect/manipulate the connected clients. Clients(ClientsArgs), /// Inspect the surface tree. Tree(TreeArgs), /// Prints the Jay version and exits. Version, /// Prints the Jay PID and exits. Pid, #[cfg(feature = "it")] RunTests, } #[derive(Args, Debug)] pub struct IdleArgs { /// The filename of the saved screenshot /// /// If no filename is given, the screenshot will be saved under %Y-%m-%d-%H%M%S_jay.qoi /// in the current directory. /// /// The filename can contain the usual strftime parameters. #[clap(subcommand)] pub command: Option, } #[derive(Args, Debug)] pub struct DpmsArgs { /// Whether monitors should be on or off. #[clap(value_enum)] pub state: DpmsState, } #[derive(ValueEnum, Debug, Copy, Clone, Eq, PartialEq)] pub enum DpmsState { On, Off, } #[derive(ValueEnum, Debug, Copy, Clone, Hash, Default, PartialEq)] pub enum ScreenshotFormat { /// The PNG image format. #[default] Png, /// The QOI image format. Qoi, } #[derive(Args, Debug)] pub struct ScreenshotArgs { /// The format to use for the image. #[clap(value_enum, long, default_value_t)] pub format: ScreenshotFormat, /// The filename of the saved screenshot /// /// If no filename is given, the screenshot will be saved under %Y-%m-%d-%H%M%S_jay. /// in the current directory. /// /// The filename can contain the usual strftime parameters. #[clap(value_hint = ValueHint::FilePath)] pub filename: Option, } #[derive(Args, Debug, Default)] pub struct RunArgs { /// The backends to try. /// /// By default, jay will try to start the available backends in this order: x11,metal. /// The first backend that can be started will be used. /// /// Using this option, you can change which backends will be tried and change the order in /// which they will be tried. Multiple backends can be supplied as a comma-separated list. #[clap(value_enum, use_value_delimiter = true, long)] pub backends: Vec, /// Override the config directory. /// /// If not specified, JAY_CONFIG_DIR is checked, then XDG_CONFIG_HOME/jay, then /// ~/.config/jay. #[clap(long, value_hint = ValueHint::DirPath)] pub config_dir: Option, } #[derive(Args, Debug)] pub struct LogArgs { /// Print the path of the log file. #[clap(long)] path: bool, /// Follow the log. #[clap(long, short)] follow: bool, /// Immediately jump to the end in the pager. #[clap(long, short = 'e')] pager_end: bool, } #[derive(Args, Debug)] pub struct SetLogArgs { /// The new log level. #[clap(value_enum)] level: LogLevel, } #[derive(Args, Debug)] pub struct SeatTestArgs { /// Test all seats. #[clap(long, short = 'a')] all: bool, /// The seat to test. seat: Option, } #[derive(ValueEnum, Debug, Copy, Clone, Hash, Eq, PartialEq)] pub enum CliBackend { X11, Metal, Headless, } #[derive(Args, Debug)] pub struct GenerateArgs { /// The shell to generate completions for #[clap(value_enum)] shell: Shell, } pub fn main() { let cli = Jay::parse(); if not_matches!(cli.command, Cmd::Run(_)) { drop_all_pr_caps(); } if cli.global.all_json_fields { VERBOSE_JSON.store(true, Relaxed); } match cli.command { Cmd::Run(a) => start_compositor(cli.global, a), Cmd::GenerateCompletion(g) => generate::main(g), Cmd::Log(a) => log::main(cli.global, a), Cmd::Quit => quit::main(cli.global), Cmd::SetLogLevel(a) => set_log_level::main(cli.global, a), Cmd::Screenshot(a) => screenshot::main(cli.global, a), Cmd::Idle(a) => idle::main(cli.global, a), Cmd::Dpms(a) => dpms::main(cli.global, a), Cmd::Unlock => unlock::main(cli.global), Cmd::SeatTest(a) => seat_test::main(cli.global, a), Cmd::Portal => portal::run_freestanding(cli.global), Cmd::Randr(a) => randr::main(cli.global, a), Cmd::Input(a) => input::main(cli.global, a), Cmd::DamageTracking(a) => damage_tracking::main(cli.global, a), Cmd::Xwayland(a) => xwayland::main(cli.global, a), Cmd::ColorManagement(a) => color_management::main(cli.global, a), Cmd::Clients(a) => clients::main(cli.global, a), Cmd::Tree(a) => tree::main(cli.global, a), Cmd::Version => version::main(cli.global), Cmd::Pid => pid::main(cli.global), #[cfg(feature = "it")] Cmd::RunTests => crate::it::run_tests(), Cmd::Reexec(a) => reexec::main(cli.global, a), Cmd::Config(a) => config::main(cli.global, a), } }