New switch-output command

timeout_old
Tassilo Horn 3 years ago
parent 4c17f110f4
commit b6fc87901a
  1. 3
      NEWS.md
  2. 15
      src/cmds.rs
  3. 24
      src/config.rs
  4. 9
      src/tree.rs

@ -1,6 +1,9 @@
swayr v0.11.0 swayr v0.11.0
============= =============
- New command: `switch-output` shows all outputs in the menu and focuses the
selected one. Since outputs must now be printable in the menu program,
there's a new `format.output_format` spec.
- New command: `configure-outputs` lets you repeatedly issue output commands - New command: `configure-outputs` lets you repeatedly issue output commands
until you abort the menu program. until you abort the menu program.
- Formats can now include a `{output_name}` placeholder which is replaced by - Formats can now include a `{output_name}` placeholder which is replaced by

@ -71,6 +71,8 @@ pub enum SwayrCommand {
SwitchWindow, SwitchWindow,
/// Switch to the selected workspace. /// Switch to the selected workspace.
SwitchWorkspace, SwitchWorkspace,
/// Switch to the selected workspace.
SwitchOutput,
/// Switch to the selected workspace or focus the selected window. /// Switch to the selected workspace or focus the selected window.
SwitchWorkspaceOrWindow, SwitchWorkspaceOrWindow,
/// Switch to the selected workspace or focus the selected container, or /// Switch to the selected workspace or focus the selected container, or
@ -241,6 +243,7 @@ pub fn exec_swayr_cmd(args: ExecSwayrCmdArgs) {
SwayrCommand::SwitchWorkspace => { SwayrCommand::SwitchWorkspace => {
switch_workspace(&*props.read().unwrap()) switch_workspace(&*props.read().unwrap())
} }
SwayrCommand::SwitchOutput => switch_output(&*props.read().unwrap()),
SwayrCommand::SwitchWorkspaceOrWindow => { SwayrCommand::SwitchWorkspaceOrWindow => {
switch_workspace_or_window(&*props.read().unwrap()) switch_workspace_or_window(&*props.read().unwrap())
} }
@ -370,6 +373,7 @@ pub fn exec_swayr_cmd(args: ExecSwayrCmdArgs) {
SwayrCommand::QuitWorkspaceOrWindow, SwayrCommand::QuitWorkspaceOrWindow,
SwayrCommand::SwitchWindow, SwayrCommand::SwitchWindow,
SwayrCommand::SwitchWorkspace, SwayrCommand::SwitchWorkspace,
SwayrCommand::SwitchOutput,
SwayrCommand::SwitchWorkspaceOrWindow, SwayrCommand::SwitchWorkspaceOrWindow,
SwayrCommand::SwitchToUrgentOrLRUWindow, SwayrCommand::SwitchToUrgentOrLRUWindow,
SwayrCommand::ConfigureOutputs, SwayrCommand::ConfigureOutputs,
@ -515,6 +519,11 @@ fn handle_non_matching_input(input: &str) {
fn select_and_focus(prompt: &str, choices: &[t::DisplayNode]) { fn select_and_focus(prompt: &str, choices: &[t::DisplayNode]) {
match util::select_from_menu(prompt, choices) { match util::select_from_menu(prompt, choices) {
Ok(tn) => match tn.node.get_type() { Ok(tn) => match tn.node.get_type() {
t::Type::Output => {
if !tn.node.is_scratchpad() {
run_sway_command(&["focus output", tn.node.get_name()]);
}
}
t::Type::Workspace => { t::Type::Workspace => {
if !tn.node.is_scratchpad() { if !tn.node.is_scratchpad() {
run_sway_command(&["workspace", tn.node.get_name()]); run_sway_command(&["workspace", tn.node.get_name()]);
@ -545,6 +554,12 @@ pub fn switch_workspace(extra_props: &HashMap<i64, t::ExtraProps>) {
select_and_focus("Select workspace", &tree.get_workspaces()); select_and_focus("Select workspace", &tree.get_workspaces());
} }
pub fn switch_output(extra_props: &HashMap<i64, t::ExtraProps>) {
let root = get_tree(false);
let tree = t::get_tree(&root, extra_props);
select_and_focus("Select output", &tree.get_outputs());
}
pub fn switch_workspace_or_window(extra_props: &HashMap<i64, t::ExtraProps>) { pub fn switch_workspace_or_window(extra_props: &HashMap<i64, t::ExtraProps>) {
let root = get_tree(true); let root = get_tree(true);
let tree = t::get_tree(&root, extra_props); let tree = t::get_tree(&root, extra_props);

@ -63,12 +63,12 @@ impl Config {
.expect("No menu.args defined.") .expect("No menu.args defined.")
} }
pub fn get_format_window_format(&self) -> String { pub fn get_format_output_format(&self) -> String {
self.format self.format
.as_ref() .as_ref()
.and_then(|f| f.window_format.clone()) .and_then(|f| f.output_format.clone())
.or_else(|| Format::default().window_format) .or_else(|| Format::default().output_format)
.expect("No format.window_format defined.") .expect("No format.output_format defined.")
} }
pub fn get_format_workspace_format(&self) -> String { pub fn get_format_workspace_format(&self) -> String {
@ -87,6 +87,14 @@ impl Config {
.expect("No format.container_format defined.") .expect("No format.container_format defined.")
} }
pub fn get_format_window_format(&self) -> String {
self.format
.as_ref()
.and_then(|f| f.window_format.clone())
.or_else(|| Format::default().window_format)
.expect("No format.window_format defined.")
}
pub fn get_format_indent(&self) -> String { pub fn get_format_indent(&self) -> String {
self.format self.format
.as_ref() .as_ref()
@ -161,9 +169,10 @@ pub struct Menu {
#[derive(Debug, Serialize, Deserialize)] #[derive(Debug, Serialize, Deserialize)]
pub struct Format { pub struct Format {
window_format: Option<String>, output_format: Option<String>,
workspace_format: Option<String>, workspace_format: Option<String>,
container_format: Option<String>, container_format: Option<String>,
window_format: Option<String>,
indent: Option<String>, indent: Option<String>,
urgency_start: Option<String>, urgency_start: Option<String>,
urgency_end: Option<String>, urgency_end: Option<String>,
@ -215,6 +224,11 @@ impl Default for Menu {
impl Default for Format { impl Default for Format {
fn default() -> Self { fn default() -> Self {
Format { Format {
output_format: Some(
"{indent}<b>Output {name}</b> \
<span alpha=\"20000\">({id})</span>"
.to_string(),
),
workspace_format: Some( workspace_format: Some(
"{indent}<b>Workspace {name} [{layout}]</b> \ "{indent}<b>Workspace {name} [{layout}]</b> \
on output {output_name} \ on output {output_name} \

@ -257,8 +257,11 @@ impl<'a> Tree<'a> {
} }
pub fn get_outputs(&self) -> Vec<DisplayNode> { pub fn get_outputs(&self) -> Vec<DisplayNode> {
let outputs: Vec<&s::Node> = let outputs: Vec<&s::Node> = self
self.root.iter().filter(|n| !n.is_scratchpad()).collect(); .root
.iter()
.filter(|n| n.get_type() == Type::Output && !n.is_scratchpad())
.collect();
self.as_display_nodes(&outputs, IndentLevel::Fixed(0)) self.as_display_nodes(&outputs, IndentLevel::Fixed(0))
} }
@ -450,7 +453,7 @@ impl DisplayFormat for DisplayNode<'_> {
let fmt = match self.node.get_type() { let fmt = match self.node.get_type() {
Type::Root => String::from("Cannot format Root"), Type::Root => String::from("Cannot format Root"),
Type::Output => String::from("Cannot format Output"), Type::Output => cfg.get_format_output_format(),
Type::Workspace => cfg.get_format_workspace_format(), Type::Workspace => cfg.get_format_workspace_format(),
Type::Container => cfg.get_format_container_format(), Type::Container => cfg.get_format_container_format(),
Type::Window => cfg.get_format_window_format(), Type::Window => cfg.get_format_window_format(),

Loading…
Cancel
Save