From 55f46bcc50a2e0ce953e800ea5ff2382d83fb91b Mon Sep 17 00:00:00 2001 From: Thomas Forgione Date: Wed, 26 Sep 2018 14:49:52 +0200 Subject: [PATCH] Disable screen --- src/lib.rs | 89 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- src/tv.rs | 34 +++++++++++++++++++-- 2 files changed, 118 insertions(+), 5 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 53d56c4..fefc106 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,4 +1,5 @@ use std::io; +use std::collections::HashSet; use std::process::Command; use std::num::ParseIntError; use std::string::FromUtf8Error; @@ -65,8 +66,38 @@ impl Screen { } } + /// Finds the best common resolution between two screens. + fn best_common_resolution(&self, other: &Screen) -> Option<(u32, u32)> { + + let self_res: HashSet<(u32, u32)> = self.resolutions.clone().into_iter().collect(); + let other_res: HashSet<(u32, u32)> = other.resolutions.clone().into_iter().collect(); + let intersection = self_res.intersection(&other_res); + + let mut output = None; + + for element in intersection { + if let Some(res) = output { + if element > &res { + output = Some(*element); + } + } + } + + output + } +} + +/// A struct that contains all the screens and allows to manage them. +#[derive(Debug)] +pub struct MultiScreen { + /// All the contained screens. + pub(crate) screens: Vec, +} + +impl MultiScreen { + /// Finds all the screens by spawning and parsing the output of xrandr. - pub fn find_screens() -> Result, Error> { + pub fn detect() -> Result { let mut screens = vec![]; let xrandr = Command::new("xrandr") @@ -108,6 +139,60 @@ impl Screen { screen.resolutions.sort(); } - Ok(screens) + Ok(MultiScreen { screens: screens }) } + + /// Returns the arguments of xrandr that disable all screens except the primary. + pub fn only_primary_args(&self) -> Vec<&str> { + + let mut primary_found = false; + let mut args = vec![]; + + for screen in &self.screens { + + if ! screen.primary || primary_found { + args.push("--output"); + args.push(&screen.name); + args.push("--off"); + } else { + args.push("--output"); + args.push(&screen.name); + args.push("--auto"); + primary_found = true; + } + + } + + args + } + + /// Returns the arguments to duplicate the screens. + pub fn duplicate_args(&self) -> Vec<&str> { + panic!("Not implemented yet"); + vec![] + } + + /// Calls the xrandr program to disable all screens except the primary. + pub fn only_primary(&self) -> Result<(), Error> { + self.run_command(self.only_primary_args()) + } + + /// Calls the xrandr program to duplicate the screens. + pub fn duplicate(&self) -> Result<(), Error> { + self.run_command(self.duplicate_args()) + } + + /// Run an xrandr command with its args. + pub fn run_command(&self, args: Vec<&str>) -> Result<(), Error> { + + Command::new("xrandr") + .args(args) + .spawn()? + .wait()?; + + Ok(()) + } + + + } diff --git a/src/tv.rs b/src/tv.rs index 2145f65..3a6e2b3 100644 --- a/src/tv.rs +++ b/src/tv.rs @@ -1,11 +1,39 @@ extern crate clap; extern crate tvrs; -use tvrs::Screen; +use clap::{Arg, App, SubCommand}; +use tvrs::MultiScreen; fn main() { - let screens = Screen::find_screens() + + let matches = App::new("tvrs") + .author("Thomas Forgione ") + .version("0.1.0") + .arg(Arg::with_name("disable") + .help("Disable all screens except the primary") + .conflicts_with_all(&["enable", "duplicate"])) + .arg(Arg::with_name("duplicate") + .help("Duplicate the primary screen on the second one") + .conflicts_with_all(&["enable", "disable"])) + .arg(Arg::with_name("enable") + .help("Enable the second screen") + .requires("enable") + .conflicts_with_all(&["disable", "duplicate"])) + .arg(Arg::with_name("position") + .help("Specify the position of the second screen") + .possible_values(&["left", "right", "top", "bottom"])) + .get_matches(); + + let screens = MultiScreen::detect() .expect("An error happened while finding screens"); - println!("{:?}", screens); + + if matches.is_present("disable") { + screens.only_primary() + .expect("An error happenned while executing the command"); + } else if matches.is_present("duplicate") { + panic!("Not implemented yet"); + } else if matches.is_present("enable") { + panic!("Not implemented yet"); + } }