blob: 78b61819225e6b3b00be20e33578946554f0e0b0 [file] [log] [blame]
// Copyright 2021 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
use {
crate::colors::ColorScheme,
anyhow::Error,
carnelian::drawing::DisplayRotation,
fidl_fuchsia_boot::{ArgumentsProxy, BoolPair},
std::str::FromStr,
};
pub const MIN_FONT_SIZE: f32 = 16.0;
pub const MAX_FONT_SIZE: f32 = 160.0;
const DEFAULT_KEYMAP: &'static str = "US_QWERTY";
const DEFAULT_FONT_SIZE: f32 = 16.0;
const DEFAULT_SCROLLBACK_ROWS: u32 = 1024;
const DEFAULT_BUFFER_COUNT: usize = 1;
#[derive(Debug, Default)]
pub struct VirtualConsoleArgs {
pub disable: bool,
pub keep_log_visible: bool,
pub keyrepeat: bool,
pub rounded_corners: bool,
pub boot_animation: bool,
pub color_scheme: ColorScheme,
pub keymap: String,
pub display_rotation: DisplayRotation,
pub font_size: f32,
pub dpi: Vec<u32>,
pub scrollback_rows: u32,
pub buffer_count: usize,
}
impl VirtualConsoleArgs {
pub async fn new_with_proxy(boot_args: ArgumentsProxy) -> Result<VirtualConsoleArgs, Error> {
let bool_keys = &[
BoolPair { key: "virtcon.disable".to_string(), defaultval: false },
BoolPair { key: "virtcon.keep-log-visible".to_string(), defaultval: false },
BoolPair { key: "virtcon.keyrepeat".to_string(), defaultval: true },
BoolPair { key: "virtcon.rounded_corners".to_string(), defaultval: false },
BoolPair { key: "virtcon.boot_animation".to_string(), defaultval: false },
];
let mut disable = false;
let mut keep_log_visible = false;
let mut keyrepeat = true;
let mut rounded_corners = false;
let mut boot_animation = false;
if let Ok(values) = boot_args.get_bools(bool_keys).await {
disable = values[0];
keep_log_visible = values[1];
keyrepeat = values[2];
rounded_corners = values[3];
boot_animation = values[4];
}
let string_keys = &[
"virtcon.colorscheme".to_owned(),
"virtcon.keymap".to_owned(),
"virtcon.display_rotation".to_owned(),
"virtcon.font_size".to_owned(),
"virtcon.dpi".to_owned(),
"virtcon.scrollback_rows".to_owned(),
"virtcon.buffer_count".to_owned(),
];
let mut color_scheme = ColorScheme::default();
let mut keymap = DEFAULT_KEYMAP.to_string();
let mut display_rotation = DisplayRotation::default();
let mut font_size = DEFAULT_FONT_SIZE;
let mut dpi = vec![];
let mut scrollback_rows = DEFAULT_SCROLLBACK_ROWS;
let mut buffer_count = DEFAULT_BUFFER_COUNT;
if let Ok(values) = boot_args.get_strings(string_keys).await {
if let Some(value) = values[0].as_ref() {
color_scheme = ColorScheme::from_str(value)?;
}
if let Some(value) = values[1].as_ref() {
keymap = match value.as_str() {
"qwerty" => "US_QWERTY",
"dvorak" => "US_DVORAK",
_ => value,
}
.to_string();
}
if let Some(value) = values[2].as_ref() {
display_rotation = DisplayRotation::from_str(value)?;
}
if let Some(value) = values[3].as_ref() {
font_size = value.parse::<f32>()?.clamp(MIN_FONT_SIZE, MAX_FONT_SIZE);
}
if let Some(value) = values[4].as_ref() {
let result: Result<Vec<_>, _> =
value.split(",").map(|x| x.parse::<u32>()).collect();
dpi = result?;
}
if let Some(value) = values[5].as_ref() {
scrollback_rows = value.parse::<u32>()?;
}
if let Some(value) = values[6].as_ref() {
buffer_count = value.parse::<usize>()?;
}
}
Ok(VirtualConsoleArgs {
disable,
keep_log_visible,
keyrepeat,
rounded_corners,
boot_animation,
color_scheme,
keymap,
display_rotation,
font_size,
dpi,
scrollback_rows,
buffer_count,
})
}
}
#[cfg(test)]
mod tests {
use {
super::*,
crate::colors::LIGHT_COLOR_SCHEME,
fidl_fuchsia_boot::{ArgumentsMarker, ArgumentsRequest},
fuchsia_async as fasync,
futures::TryStreamExt,
std::collections::HashMap,
};
fn serve_bootargs(env: HashMap<String, String>) -> Result<ArgumentsProxy, Error> {
let (proxy, mut stream) = fidl::endpoints::create_proxy_and_stream::<ArgumentsMarker>()?;
fn get_bool_arg(env: &HashMap<String, String>, name: &String, default: bool) -> bool {
let mut ret = default;
if let Some(val) = env.get(name) {
if val == "0" || val == "false" || val == "off" {
ret = false;
} else {
ret = true;
}
}
ret
}
fasync::Task::local(async move {
while let Ok(Some(req)) = stream.try_next().await {
match req {
ArgumentsRequest::GetStrings { keys, responder } => {
let vec: Vec<_> =
keys.into_iter().map(|key| env.get(&key).map(|s| s.clone())).collect();
responder.send(&vec).unwrap();
}
ArgumentsRequest::GetBools { keys, responder } => {
let vec: Vec<_> = keys
.into_iter()
.map(|key| get_bool_arg(&env, &key.key, key.defaultval))
.collect();
responder.send(&vec).unwrap();
}
_ => assert!(false),
}
}
})
.detach();
Ok(proxy)
}
#[fasync::run_singlethreaded(test)]
async fn check_disable() -> Result<(), Error> {
let vars: HashMap<String, String> = [("virtcon.disable", "true")]
.iter()
.map(|(a, b)| (a.to_string(), b.to_string()))
.collect();
let proxy = serve_bootargs(vars)?;
let args = VirtualConsoleArgs::new_with_proxy(proxy).await?;
assert_eq!(args.disable, true);
let vars: HashMap<String, String> = [("virtcon.disable", "false")]
.iter()
.map(|(a, b)| (a.to_string(), b.to_string()))
.collect();
let proxy = serve_bootargs(vars)?;
let args = VirtualConsoleArgs::new_with_proxy(proxy).await?;
assert_eq!(args.disable, false);
Ok(())
}
#[fasync::run_singlethreaded(test)]
async fn check_keep_log_visible() -> Result<(), Error> {
let vars: HashMap<String, String> = [("virtcon.keep-log-visible", "true")]
.iter()
.map(|(a, b)| (a.to_string(), b.to_string()))
.collect();
let proxy = serve_bootargs(vars)?;
let args = VirtualConsoleArgs::new_with_proxy(proxy).await?;
assert_eq!(args.keep_log_visible, true);
let vars: HashMap<String, String> = [("virtcon.keep-log-visible", "false")]
.iter()
.map(|(a, b)| (a.to_string(), b.to_string()))
.collect();
let proxy = serve_bootargs(vars)?;
let args = VirtualConsoleArgs::new_with_proxy(proxy).await?;
assert_eq!(args.keep_log_visible, false);
Ok(())
}
#[fasync::run_singlethreaded(test)]
async fn check_keyrepeat() -> Result<(), Error> {
let vars: HashMap<String, String> = [("virtcon.keyrepeat", "true")]
.iter()
.map(|(a, b)| (a.to_string(), b.to_string()))
.collect();
let proxy = serve_bootargs(vars)?;
let args = VirtualConsoleArgs::new_with_proxy(proxy).await?;
assert_eq!(args.keyrepeat, true);
let vars: HashMap<String, String> = [("virtcon.keyrepeat", "false")]
.iter()
.map(|(a, b)| (a.to_string(), b.to_string()))
.collect();
let proxy = serve_bootargs(vars)?;
let args = VirtualConsoleArgs::new_with_proxy(proxy).await?;
assert_eq!(args.keyrepeat, false);
Ok(())
}
#[fasync::run_singlethreaded(test)]
async fn check_rounded_corners() -> Result<(), Error> {
let vars: HashMap<String, String> = [("virtcon.rounded_corners", "true")]
.iter()
.map(|(a, b)| (a.to_string(), b.to_string()))
.collect();
let proxy = serve_bootargs(vars)?;
let args = VirtualConsoleArgs::new_with_proxy(proxy).await?;
assert_eq!(args.rounded_corners, true);
let vars: HashMap<String, String> = [("virtcon.rounded_corners", "false")]
.iter()
.map(|(a, b)| (a.to_string(), b.to_string()))
.collect();
let proxy = serve_bootargs(vars)?;
let args = VirtualConsoleArgs::new_with_proxy(proxy).await?;
assert_eq!(args.rounded_corners, false);
Ok(())
}
#[fasync::run_singlethreaded(test)]
async fn check_boot_animation() -> Result<(), Error> {
let vars: HashMap<String, String> = [("virtcon.boot_animation", "true")]
.iter()
.map(|(a, b)| (a.to_string(), b.to_string()))
.collect();
let proxy = serve_bootargs(vars)?;
let args = VirtualConsoleArgs::new_with_proxy(proxy).await?;
assert_eq!(args.boot_animation, true);
let vars: HashMap<String, String> = [("virtcon.boot_animation", "false")]
.iter()
.map(|(a, b)| (a.to_string(), b.to_string()))
.collect();
let proxy = serve_bootargs(vars)?;
let args = VirtualConsoleArgs::new_with_proxy(proxy).await?;
assert_eq!(args.boot_animation, false);
Ok(())
}
#[fasync::run_singlethreaded(test)]
async fn check_color_scheme() -> Result<(), Error> {
let vars: HashMap<String, String> = [("virtcon.colorscheme", "light")]
.iter()
.map(|(a, b)| (a.to_string(), b.to_string()))
.collect();
let proxy = serve_bootargs(vars)?;
let args = VirtualConsoleArgs::new_with_proxy(proxy).await?;
assert_eq!(args.color_scheme, LIGHT_COLOR_SCHEME);
let vars: HashMap<String, String> = HashMap::new();
let proxy = serve_bootargs(vars)?;
let args = VirtualConsoleArgs::new_with_proxy(proxy).await?;
assert_eq!(args.color_scheme, ColorScheme::default());
Ok(())
}
#[fasync::run_singlethreaded(test)]
async fn check_keymap() -> Result<(), Error> {
let vars: HashMap<String, String> = [("virtcon.keymap", "US_DVORAK")]
.iter()
.map(|(a, b)| (a.to_string(), b.to_string()))
.collect();
let proxy = serve_bootargs(vars)?;
let args = VirtualConsoleArgs::new_with_proxy(proxy).await?;
assert_eq!(args.keymap, "US_DVORAK");
let vars: HashMap<String, String> = [("virtcon.keymap", "dvorak")]
.iter()
.map(|(a, b)| (a.to_string(), b.to_string()))
.collect();
let proxy = serve_bootargs(vars)?;
let args = VirtualConsoleArgs::new_with_proxy(proxy).await?;
assert_eq!(args.keymap, "US_DVORAK");
let vars: HashMap<String, String> = HashMap::new();
let proxy = serve_bootargs(vars)?;
let args = VirtualConsoleArgs::new_with_proxy(proxy).await?;
assert_eq!(args.keymap, "US_QWERTY");
Ok(())
}
#[fasync::run_singlethreaded(test)]
async fn check_display_rotation() -> Result<(), Error> {
let vars: HashMap<String, String> = [("virtcon.display_rotation", "90")]
.iter()
.map(|(a, b)| (a.to_string(), b.to_string()))
.collect();
let proxy = serve_bootargs(vars)?;
let args = VirtualConsoleArgs::new_with_proxy(proxy).await?;
assert_eq!(args.display_rotation, DisplayRotation::Deg90);
let vars: HashMap<String, String> = [("virtcon.display_rotation", "0")]
.iter()
.map(|(a, b)| (a.to_string(), b.to_string()))
.collect();
let proxy = serve_bootargs(vars)?;
let args = VirtualConsoleArgs::new_with_proxy(proxy).await?;
assert_eq!(args.display_rotation, DisplayRotation::Deg0);
Ok(())
}
#[fasync::run_singlethreaded(test)]
async fn check_font_size() -> Result<(), Error> {
let vars: HashMap<String, String> = [("virtcon.font_size", "32.0")]
.iter()
.map(|(a, b)| (a.to_string(), b.to_string()))
.collect();
let proxy = serve_bootargs(vars)?;
let args = VirtualConsoleArgs::new_with_proxy(proxy).await?;
assert_eq!(args.font_size, 32.0);
let vars: HashMap<String, String> = [("virtcon.font_size", "1000000.0")]
.iter()
.map(|(a, b)| (a.to_string(), b.to_string()))
.collect();
let proxy = serve_bootargs(vars)?;
let args = VirtualConsoleArgs::new_with_proxy(proxy).await?;
assert_eq!(args.font_size, MAX_FONT_SIZE);
Ok(())
}
#[fasync::run_singlethreaded(test)]
async fn check_dpi() -> Result<(), Error> {
let vars: HashMap<String, String> = [("virtcon.dpi", "160,320,480,640")]
.iter()
.map(|(a, b)| (a.to_string(), b.to_string()))
.collect();
let proxy = serve_bootargs(vars)?;
let args = VirtualConsoleArgs::new_with_proxy(proxy).await?;
assert_eq!(args.dpi, vec![160, 320, 480, 640]);
Ok(())
}
#[fasync::run_singlethreaded(test)]
async fn check_scrollback_rows() -> Result<(), Error> {
let vars: HashMap<String, String> = [("virtcon.scrollback_rows", "10000")]
.iter()
.map(|(a, b)| (a.to_string(), b.to_string()))
.collect();
let proxy = serve_bootargs(vars)?;
let args = VirtualConsoleArgs::new_with_proxy(proxy).await?;
assert_eq!(args.scrollback_rows, 10_000);
Ok(())
}
#[fasync::run_singlethreaded(test)]
async fn check_buffer_count() -> Result<(), Error> {
let vars: HashMap<String, String> = [("virtcon.buffer_count", "2")]
.iter()
.map(|(a, b)| (a.to_string(), b.to_string()))
.collect();
let proxy = serve_bootargs(vars)?;
let args = VirtualConsoleArgs::new_with_proxy(proxy).await?;
assert_eq!(args.buffer_count, 2);
Ok(())
}
}