Disable screen

This commit is contained in:
Thomas Forgione 2018-09-26 14:49:52 +02:00
parent 11c399841f
commit 55f46bcc50
No known key found for this signature in database
GPG Key ID: 203DAEA747F48F41
2 changed files with 118 additions and 5 deletions

View File

@ -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<Screen>,
}
impl MultiScreen {
/// Finds all the screens by spawning and parsing the output of xrandr.
pub fn find_screens() -> Result<Vec<Screen>, Error> {
pub fn detect() -> Result<MultiScreen, Error> {
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(())
}
}

View File

@ -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 <thomas@forgione.fr>")
.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");
}
}