toolbar: --state, --set and --run for the Noctalia plugin
This commit is contained in:
1 parent
3d7a4de10a
commit
c8626dbe3e
2 files changed
+144
-10
No files matched your search
+42
-3
@@ -84,7 +84,17 @@ enum Command {
|
|||||||
file: PathBuf,
|
file: PathBuf,
|
||||||
},
|
},
|
||||||
/// Pick a mode from a floating bar (Cmd+Shift+5).
|
/// Pick a mode from a floating bar (Cmd+Shift+5).
|
||||||
Toolbar,
|
Toolbar {
|
||||||
|
/// Print the remembered choices as one line of JSON (for the Noctalia plugin).
|
||||||
|
#[arg(long, conflicts_with_all = ["set", "run"])]
|
||||||
|
state: bool,
|
||||||
|
/// Change a remembered choice: mode, timer, cursor, preview or sound.
|
||||||
|
#[arg(long, value_name = "KEY=VALUE", conflicts_with = "run")]
|
||||||
|
set: Vec<String>,
|
||||||
|
/// Capture at once with the remembered choices, without the bar.
|
||||||
|
#[arg(long, value_name = "MODE", num_args = 0..=1)]
|
||||||
|
run: Option<Option<toolbar::state::Mode>>,
|
||||||
|
},
|
||||||
/// The paint shader behind niri's overview (keep it running; see the README).
|
/// The paint shader behind niri's overview (keep it running; see the README).
|
||||||
Backdrop,
|
Backdrop,
|
||||||
/// Report what the compositor and system support.
|
/// Report what the compositor and system support.
|
||||||
@@ -218,9 +228,24 @@ fn run(cli: Cli) -> Result<()> {
|
|||||||
// Handled in main, before logging starts.
|
// Handled in main, before logging starts.
|
||||||
Command::CheckConfig { file } => config::check(&file),
|
Command::CheckConfig { file } => config::check(&file),
|
||||||
Command::ComboDemo => sound::demo(&config::load(&config::default_path())?.sound),
|
Command::ComboDemo => sound::demo(&config::load(&config::default_path())?.sound),
|
||||||
Command::Toolbar => {
|
Command::Toolbar { state, set, run } => {
|
||||||
let config = config::load(&config::default_path())?;
|
let config = config::load(&config::default_path())?;
|
||||||
let (mode, common) = from_toolbar(toolbar::run(&config)?);
|
let path = toolbar::state::default_path();
|
||||||
|
if state {
|
||||||
|
println!(
|
||||||
|
"{}",
|
||||||
|
toolbar::state::to_json(&toolbar::state::load(&path, &config))
|
||||||
|
);
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
if !set.is_empty() {
|
||||||
|
return toolbar::state::set(&path, &config, &set);
|
||||||
|
}
|
||||||
|
let picked = match run {
|
||||||
|
Some(mode) => toolbar::run_remembered(&config, mode)?,
|
||||||
|
None => toolbar::run(&config)?,
|
||||||
|
};
|
||||||
|
let (mode, common) = from_toolbar(picked);
|
||||||
capture(mode, common)
|
capture(mode, common)
|
||||||
}
|
}
|
||||||
Command::Clipboard => {
|
Command::Clipboard => {
|
||||||
@@ -473,6 +498,20 @@ mod tests {
|
|||||||
assert!(!parses(&["edit"]));
|
assert!(!parses(&["edit"]));
|
||||||
assert!(parses(&["__clipboard"]));
|
assert!(parses(&["__clipboard"]));
|
||||||
assert!(parses(&["toolbar"]));
|
assert!(parses(&["toolbar"]));
|
||||||
|
assert!(parses(&["toolbar", "--state"]));
|
||||||
|
assert!(parses(&[
|
||||||
|
"toolbar",
|
||||||
|
"--set",
|
||||||
|
"timer=5",
|
||||||
|
"--set",
|
||||||
|
"sound=false"
|
||||||
|
]));
|
||||||
|
assert!(parses(&["toolbar", "--run"]));
|
||||||
|
assert!(parses(&["toolbar", "--run", "zoom"]));
|
||||||
|
assert!(!parses(&["toolbar", "--run", "video"]));
|
||||||
|
assert!(!parses(&["toolbar", "--state", "--run"]));
|
||||||
|
assert!(!parses(&["toolbar", "--state", "--set", "timer=5"]));
|
||||||
|
assert!(!parses(&["toolbar", "--set", "timer=5", "--run", "zoom"]));
|
||||||
assert!(parses(&["backdrop"]));
|
assert!(parses(&["backdrop"]));
|
||||||
assert!(parses(&["window", "--pick"]));
|
assert!(parses(&["window", "--pick"]));
|
||||||
assert!(parses(&["__combo-demo"]));
|
assert!(parses(&["__combo-demo"]));
|
||||||
|
|||||||
+102
-7
@@ -5,6 +5,7 @@ pub mod draw;
|
|||||||
pub mod layout;
|
pub mod layout;
|
||||||
pub mod state;
|
pub mod state;
|
||||||
|
|
||||||
|
use std::path::Path;
|
||||||
use std::time::{Duration, Instant};
|
use std::time::{Duration, Instant};
|
||||||
|
|
||||||
use anyhow::{Context, Result};
|
use anyhow::{Context, Result};
|
||||||
@@ -44,6 +45,17 @@ pub struct Picked {
|
|||||||
pub sound: bool,
|
pub sound: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<ToolbarState> for Picked {
|
||||||
|
fn from(s: ToolbarState) -> Self {
|
||||||
|
Picked {
|
||||||
|
mode: s.mode,
|
||||||
|
cursor: s.cursor,
|
||||||
|
preview: s.preview,
|
||||||
|
sound: s.sound,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Shows the bar, waits for a pick, saves it, runs the countdown.
|
/// Shows the bar, waits for a pick, saves it, runs the countdown.
|
||||||
pub fn run(config: &Config) -> Result<Picked> {
|
pub fn run(config: &Config) -> Result<Picked> {
|
||||||
let path = state::default_path();
|
let path = state::default_path();
|
||||||
@@ -58,13 +70,33 @@ pub fn run(config: &Config) -> Result<Picked> {
|
|||||||
tracing::warn!("could not remember the toolbar choice: {e:#}");
|
tracing::warn!("could not remember the toolbar choice: {e:#}");
|
||||||
}
|
}
|
||||||
countdown(&mut wl, &output, picked.0.timer)?;
|
countdown(&mut wl, &output, picked.0.timer)?;
|
||||||
let s = picked.0;
|
Ok(Picked::from(picked.0))
|
||||||
Ok(Picked {
|
}
|
||||||
mode: picked.1,
|
|
||||||
cursor: s.cursor,
|
/// The remembered state, with `mode` (if given) remembered as the new mode.
|
||||||
preview: s.preview,
|
pub fn remember(path: &Path, config: &Config, mode: Option<Mode>) -> ToolbarState {
|
||||||
sound: s.sound,
|
let mut s = state::load(path, config);
|
||||||
})
|
if let Some(mode) = mode {
|
||||||
|
s.mode = mode;
|
||||||
|
if let Err(e) = state::save(path, &s) {
|
||||||
|
tracing::warn!("could not remember the toolbar choice: {e:#}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
s
|
||||||
|
}
|
||||||
|
|
||||||
|
/// `valw toolbar --run`: the remembered options without the bar (for the
|
||||||
|
/// Noctalia plugin), then the countdown.
|
||||||
|
pub fn run_remembered(config: &Config, mode: Option<Mode>) -> Result<Picked> {
|
||||||
|
let s = remember(&state::default_path(), config, mode);
|
||||||
|
if s.timer > 0 {
|
||||||
|
let mut wl = Wayland::connect()?;
|
||||||
|
let outputs = wl.outputs();
|
||||||
|
anyhow::ensure!(!outputs.is_empty(), "the compositor reported no outputs");
|
||||||
|
let output = outputs[crate::focused_output(&outputs)].clone();
|
||||||
|
countdown(&mut wl, &output, s.timer)?;
|
||||||
|
}
|
||||||
|
Ok(Picked::from(s))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Toolbar {
|
pub struct Toolbar {
|
||||||
@@ -388,3 +420,66 @@ impl Pill {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn a_pick_carries_the_state_options() {
|
||||||
|
let state = ToolbarState {
|
||||||
|
mode: Mode::Window,
|
||||||
|
timer: 5,
|
||||||
|
cursor: true,
|
||||||
|
preview: false,
|
||||||
|
sound: true,
|
||||||
|
};
|
||||||
|
assert_eq!(
|
||||||
|
Picked::from(state),
|
||||||
|
Picked {
|
||||||
|
mode: Mode::Window,
|
||||||
|
cursor: true,
|
||||||
|
preview: false,
|
||||||
|
sound: true,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn run_remembers_a_given_mode() {
|
||||||
|
let dir = tempfile::tempdir().unwrap();
|
||||||
|
let path = dir.path().join("toolbar.toml");
|
||||||
|
let config = Config::default();
|
||||||
|
state::save(
|
||||||
|
&path,
|
||||||
|
&ToolbarState {
|
||||||
|
timer: 5,
|
||||||
|
..state::defaults(&config)
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let state = remember(&path, &config, Some(Mode::Zoom));
|
||||||
|
assert_eq!(
|
||||||
|
(state.mode, state.timer),
|
||||||
|
(Mode::Zoom, 5),
|
||||||
|
"the options stay"
|
||||||
|
);
|
||||||
|
assert_eq!(state::load(&path, &config).mode, Mode::Zoom, "saved");
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
remember(&path, &config, None).mode,
|
||||||
|
Mode::Zoom,
|
||||||
|
"no mode: the remembered one"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn run_without_a_mode_writes_nothing() {
|
||||||
|
let dir = tempfile::tempdir().unwrap();
|
||||||
|
let path = dir.path().join("toolbar.toml");
|
||||||
|
let config = Config::default();
|
||||||
|
assert_eq!(remember(&path, &config, None), state::defaults(&config));
|
||||||
|
assert!(!path.exists());
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in new issue
Block a user