parent
1d3b83f288
commit
5c348fb7c4
7 changed files with 409 additions and 375 deletions
@ -1,323 +1,13 @@ |
||||
//! Functions and data structures of the swayr client.
|
||||
extern crate serde_json; |
||||
|
||||
use crate::con; |
||||
use crate::ipc; |
||||
use crate::util; |
||||
|
||||
use clap::Clap; |
||||
use std::fmt; |
||||
|
||||
use swayipc as s; |
||||
use swayipc::reply as r; |
||||
|
||||
#[derive(Clap, Debug)] |
||||
pub enum SwayrCommand { |
||||
/// Switch to next urgent window (if any) or to last recently used window.
|
||||
SwitchToUrgentOrLRUWindow, |
||||
/// Focus the selected window
|
||||
SwitchWindow, |
||||
/// Focus the next window.
|
||||
NextWindow, |
||||
/// Focus the previous window.
|
||||
PrevWindow, |
||||
/// Quit the selected window
|
||||
QuitWindow, |
||||
/// Switch to the selected workspace
|
||||
SwitchWorkspace, |
||||
/// Switch to the selected workspace or focus the selected window
|
||||
SwitchWorkspaceOrWindow, |
||||
/// Quit all windows of selected workspace or the selected window
|
||||
QuitWorkspaceOrWindow, |
||||
/// Select and execute a swaymsg command
|
||||
ExecuteSwaymsgCommand, |
||||
/// Select and execute a swayr command
|
||||
ExecuteSwayrCommand, |
||||
} |
||||
|
||||
impl fmt::Display for SwayrCommand { |
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { |
||||
write!(f, "<b>{:?}</b>", self) |
||||
} |
||||
} |
||||
|
||||
pub fn exec_swayr_cmd(cmd: &SwayrCommand) { |
||||
match cmd { |
||||
SwayrCommand::SwitchToUrgentOrLRUWindow => { |
||||
switch_to_urgent_or_lru_window() |
||||
} |
||||
SwayrCommand::SwitchWindow => switch_window(), |
||||
SwayrCommand::NextWindow => { |
||||
focus_next_window_in_direction(Direction::Forward) |
||||
} |
||||
SwayrCommand::PrevWindow => { |
||||
focus_next_window_in_direction(Direction::Backward) |
||||
} |
||||
SwayrCommand::QuitWindow => quit_window(), |
||||
SwayrCommand::SwitchWorkspace => switch_workspace(), |
||||
SwayrCommand::SwitchWorkspaceOrWindow => switch_workspace_or_window(), |
||||
SwayrCommand::QuitWorkspaceOrWindow => quit_workspace_or_window(), |
||||
SwayrCommand::ExecuteSwaymsgCommand => exec_swaymsg_command(), |
||||
SwayrCommand::ExecuteSwayrCommand => { |
||||
if let Some(c) = util::wofi_select( |
||||
"Select swayr command", |
||||
&[ |
||||
SwayrCommand::ExecuteSwaymsgCommand, |
||||
SwayrCommand::QuitWindow, |
||||
SwayrCommand::QuitWorkspaceOrWindow, |
||||
SwayrCommand::SwitchWindow, |
||||
SwayrCommand::SwitchWorkspace, |
||||
SwayrCommand::SwitchWorkspaceOrWindow, |
||||
SwayrCommand::SwitchToUrgentOrLRUWindow, |
||||
SwayrCommand::NextWindow, |
||||
SwayrCommand::PrevWindow, |
||||
], |
||||
) { |
||||
exec_swayr_cmd(c); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
fn focus_window_by_id(id: i64) { |
||||
util::swaymsg(&[format!("[con_id={}]", id).as_str(), "focus"]); |
||||
} |
||||
|
||||
fn quit_window_by_id(id: i64) { |
||||
util::swaymsg(&[format!("[con_id={}]", id).as_str(), "kill"]); |
||||
} |
||||
|
||||
fn get_tree() -> r::Node { |
||||
match s::Connection::new() { |
||||
Ok(mut con) => con.get_tree().expect("Got no root node"), |
||||
Err(err) => panic!(err), |
||||
} |
||||
} |
||||
|
||||
pub fn switch_to_urgent_or_lru_window() { |
||||
let root = get_tree(); |
||||
let windows = con::get_windows(&root, true); |
||||
if let Some(win) = windows |
||||
.iter() |
||||
.find(|w| w.is_urgent()) |
||||
.or_else(|| windows.get(0)) |
||||
{ |
||||
println!("Switching to {}", win); |
||||
focus_window_by_id(win.get_id()) |
||||
} else { |
||||
println!("No window to switch to.") |
||||
} |
||||
} |
||||
|
||||
pub fn switch_window() { |
||||
let root = get_tree(); |
||||
let windows = con::get_windows(&root, true); |
||||
|
||||
if let Some(window) = con::select_window("Switch to window", &windows) { |
||||
focus_window_by_id(window.get_id()) |
||||
} |
||||
} |
||||
|
||||
pub enum Direction { |
||||
Backward, |
||||
Forward, |
||||
} |
||||
|
||||
pub fn focus_next_window_in_direction(dir: Direction) { |
||||
let root = get_tree(); |
||||
let windows = con::get_windows(&root, false); |
||||
|
||||
if windows.len() < 2 { |
||||
return; |
||||
} |
||||
|
||||
let pred: Box<dyn Fn(&con::Window) -> bool> = |
||||
if windows.iter().find(|w| w.is_focused()).is_none() { |
||||
let last_focused_win_id = |
||||
con::get_windows(&root, true).get(0).unwrap().get_id(); |
||||
Box::new(move |w| w.get_id() == last_focused_win_id) |
||||
} else { |
||||
Box::new(|w: &con::Window| w.is_focused()) |
||||
}; |
||||
|
||||
let mut iter: Box<dyn Iterator<Item = &con::Window>> = match dir { |
||||
Direction::Forward => Box::new(windows.iter().rev().cycle()), |
||||
Direction::Backward => Box::new(windows.iter().cycle()), |
||||
}; |
||||
|
||||
loop { |
||||
let win = iter.next().unwrap(); |
||||
if pred(win) { |
||||
let win = iter.next().unwrap(); |
||||
focus_window_by_id(win.get_id()); |
||||
return; |
||||
} |
||||
} |
||||
} |
||||
|
||||
pub fn switch_workspace() { |
||||
let root = get_tree(); |
||||
let workspaces = con::get_workspaces(&root, false); |
||||
|
||||
if let Some(workspace) = |
||||
con::select_workspace("Switch to workspace", &workspaces) |
||||
{ |
||||
util::swaymsg(&["workspace", "number", workspace.get_name()]); |
||||
} |
||||
} |
||||
|
||||
pub fn switch_workspace_or_window() { |
||||
let root = get_tree(); |
||||
let workspaces = con::get_workspaces(&root, false); |
||||
let ws_or_wins = con::WsOrWin::from_workspaces(&workspaces); |
||||
if let Some(ws_or_win) = con::select_workspace_or_window( |
||||
"Select workspace or window", |
||||
&ws_or_wins, |
||||
) { |
||||
match ws_or_win { |
||||
con::WsOrWin::Ws { ws } => { |
||||
util::swaymsg(&["workspace", "number", ws.get_name()]); |
||||
} |
||||
con::WsOrWin::Win { win } => focus_window_by_id(win.get_id()), |
||||
} |
||||
} |
||||
} |
||||
|
||||
pub fn quit_window() { |
||||
let root = get_tree(); |
||||
let windows = con::get_windows(&root, true); |
||||
|
||||
if let Some(window) = con::select_window("Quit window", &windows) { |
||||
quit_window_by_id(window.get_id()) |
||||
} |
||||
} |
||||
|
||||
pub fn quit_workspace_or_window() { |
||||
let root = get_tree(); |
||||
let workspaces = con::get_workspaces(&root, false); |
||||
let ws_or_wins = con::WsOrWin::from_workspaces(&workspaces); |
||||
if let Some(ws_or_win) = |
||||
con::select_workspace_or_window("Quit workspace or window", &ws_or_wins) |
||||
{ |
||||
match ws_or_win { |
||||
con::WsOrWin::Ws { ws } => { |
||||
for win in &ws.windows { |
||||
quit_window_by_id(win.get_id()) |
||||
} |
||||
} |
||||
con::WsOrWin::Win { win } => quit_window_by_id(win.get_id()), |
||||
} |
||||
} |
||||
} |
||||
|
||||
fn get_swaymsg_commands<'a>() -> Vec<SwaymsgCmd<'a>> { |
||||
let mut cmds = vec![]; |
||||
cmds.push(vec!["exit"]); |
||||
cmds.push(vec!["floating", "toggle"]); |
||||
cmds.push(vec!["focus", "child"]); |
||||
cmds.push(vec!["focus", "parent"]); |
||||
|
||||
for b in &["none", "normal", "csd", "pixel"] { |
||||
cmds.push(vec!["border", b]); |
||||
} |
||||
|
||||
cmds.push(vec!["focus", "tiling"]); |
||||
cmds.push(vec!["focus", "floating"]); |
||||
cmds.push(vec!["focus", "mode_toggle"]); |
||||
|
||||
cmds.push(vec!["fullscreen", "toggle"]); |
||||
|
||||
for x in &["focus", "fullscreen", "open", "none", "visible"] { |
||||
cmds.push(vec!["inhibit_idle", x]) |
||||
} |
||||
|
||||
for l in &["default", "splith", "splitv", "stacking", "tiling"] { |
||||
cmds.push(vec!["layout", l]) |
||||
} |
||||
|
||||
cmds.push(vec!["reload"]); |
||||
|
||||
for e in &["enable", "disable"] { |
||||
cmds.push(vec!["shortcuts", "inhibitor", e]) |
||||
} |
||||
|
||||
cmds.push(vec!["sticky", "toggle"]); |
||||
|
||||
for x in &["yes", "no", "always"] { |
||||
cmds.push(vec!["focus_follows_mouse", x]) |
||||
} |
||||
|
||||
for x in &["smart", "urgent", "focus", "none"] { |
||||
cmds.push(vec!["focus_on_window_activation", x]) |
||||
} |
||||
|
||||
for x in &["yes", "no", "force", "workspace"] { |
||||
cmds.push(vec!["focus_wrapping", x]) |
||||
} |
||||
|
||||
for x in &[ |
||||
"none", |
||||
"vertical", |
||||
"horizontal", |
||||
"both", |
||||
"smart", |
||||
"smart_no_gaps", |
||||
] { |
||||
cmds.push(vec!["hide_edge_borders", x]) |
||||
} |
||||
|
||||
cmds.push(vec!["kill"]); |
||||
|
||||
for x in &["on", "no_gaps", "off"] { |
||||
cmds.push(vec!["smart_borders", x]) |
||||
} |
||||
|
||||
for x in &["on", "off"] { |
||||
cmds.push(vec!["smart_gaps", x]) |
||||
} |
||||
|
||||
for x in &["output", "container", "none"] { |
||||
cmds.push(vec!["mouse_warping", x]) |
||||
} |
||||
|
||||
for x in &["smart", "ignore", "leave_fullscreen"] { |
||||
cmds.push(vec!["popup_during_fullscreen", x]) |
||||
} |
||||
|
||||
for x in &["yes", "no"] { |
||||
cmds.push(vec!["show_marks", x]); |
||||
cmds.push(vec!["workspace_auto_back_and_forth", x]); |
||||
} |
||||
|
||||
cmds.push(vec!["tiling_drag", "toggle"]); |
||||
|
||||
for x in &["left", "center", "right"] { |
||||
cmds.push(vec!["title_align", x]); |
||||
} |
||||
|
||||
for x in &["enable", "disable", "allow", "deny"] { |
||||
cmds.push(vec!["urgent", x]) |
||||
} |
||||
|
||||
cmds.sort(); |
||||
|
||||
cmds.iter() |
||||
.map(|v| SwaymsgCmd { cmd: v.to_vec() }) |
||||
.collect() |
||||
} |
||||
|
||||
struct SwaymsgCmd<'a> { |
||||
cmd: Vec<&'a str>, |
||||
} |
||||
|
||||
impl<'a> fmt::Display for SwaymsgCmd<'a> { |
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { |
||||
write!(f, "<b>{}</b>", self.cmd.join(" ")) |
||||
} |
||||
} |
||||
|
||||
pub fn exec_swaymsg_command() { |
||||
let cmds = get_swaymsg_commands(); |
||||
let cmd = util::wofi_select("Execute swaymsg command", &cmds); |
||||
if let Some(cmd) = cmd { |
||||
util::swaymsg(&cmd.cmd); |
||||
} |
||||
use std::io::Write; |
||||
use std::os::unix::net::UnixStream; |
||||
|
||||
pub fn send_swayr_cmd( |
||||
cmd: ipc::SwayrCommand, |
||||
) -> std::result::Result<(), std::io::Error> { |
||||
let mut sock = UnixStream::connect(util::get_swayr_socket_path())?; |
||||
sock.write_all(serde_json::to_string(&cmd).unwrap().as_bytes()) |
||||
} |
||||
|
@ -0,0 +1,329 @@ |
||||
//! Functions and data structures of the swayr client.
|
||||
|
||||
use crate::con; |
||||
use crate::ipc; |
||||
use crate::ipc::SwayrCommand; |
||||
use crate::util; |
||||
|
||||
use std::collections::HashMap; |
||||
use std::fmt; |
||||
use std::sync::Arc; |
||||
use std::sync::RwLock; |
||||
|
||||
use swayipc as s; |
||||
use swayipc::reply as r; |
||||
|
||||
impl fmt::Display for SwayrCommand { |
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { |
||||
write!(f, "<b>{:?}</b>", self) |
||||
} |
||||
} |
||||
|
||||
pub fn exec_swayr_cmd( |
||||
cmd: &SwayrCommand, |
||||
extra_props: Arc<RwLock<HashMap<i64, ipc::ExtraProps>>>, |
||||
) { |
||||
match cmd { |
||||
SwayrCommand::SwitchToUrgentOrLRUWindow => { |
||||
switch_to_urgent_or_lru_window(Some(&*extra_props.read().unwrap())) |
||||
} |
||||
SwayrCommand::SwitchWindow => { |
||||
switch_window(Some(&*extra_props.read().unwrap())) |
||||
} |
||||
SwayrCommand::NextWindow => focus_next_window_in_direction( |
||||
Direction::Forward, |
||||
Some(&*extra_props.read().unwrap()), |
||||
), |
||||
SwayrCommand::PrevWindow => focus_next_window_in_direction( |
||||
Direction::Backward, |
||||
Some(&*extra_props.read().unwrap()), |
||||
), |
||||
SwayrCommand::QuitWindow => { |
||||
quit_window(Some(&*extra_props.read().unwrap())) |
||||
} |
||||
SwayrCommand::SwitchWorkspace => { |
||||
switch_workspace(Some(&*extra_props.read().unwrap())) |
||||
} |
||||
SwayrCommand::SwitchWorkspaceOrWindow => { |
||||
switch_workspace_or_window(Some(&*extra_props.read().unwrap())) |
||||
} |
||||
SwayrCommand::QuitWorkspaceOrWindow => { |
||||
quit_workspace_or_window(Some(&*extra_props.read().unwrap())) |
||||
} |
||||
SwayrCommand::ExecuteSwaymsgCommand => exec_swaymsg_command(), |
||||
SwayrCommand::ExecuteSwayrCommand => { |
||||
if let Some(c) = util::wofi_select( |
||||
"Select swayr command", |
||||
&[ |
||||
SwayrCommand::ExecuteSwaymsgCommand, |
||||
SwayrCommand::QuitWindow, |
||||
SwayrCommand::QuitWorkspaceOrWindow, |
||||
SwayrCommand::SwitchWindow, |
||||
SwayrCommand::SwitchWorkspace, |
||||
SwayrCommand::SwitchWorkspaceOrWindow, |
||||
SwayrCommand::SwitchToUrgentOrLRUWindow, |
||||
SwayrCommand::NextWindow, |
||||
SwayrCommand::PrevWindow, |
||||
], |
||||
) { |
||||
exec_swayr_cmd(c, extra_props); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
fn focus_window_by_id(id: i64) { |
||||
util::swaymsg(&[format!("[con_id={}]", id).as_str(), "focus"]); |
||||
} |
||||
|
||||
fn quit_window_by_id(id: i64) { |
||||
util::swaymsg(&[format!("[con_id={}]", id).as_str(), "kill"]); |
||||
} |
||||
|
||||
fn get_tree() -> r::Node { |
||||
match s::Connection::new() { |
||||
Ok(mut con) => con.get_tree().expect("Got no root node"), |
||||
Err(err) => panic!(err), |
||||
} |
||||
} |
||||
|
||||
pub fn switch_to_urgent_or_lru_window( |
||||
extra_props: Option<&HashMap<i64, ipc::ExtraProps>>, |
||||
) { |
||||
let root = get_tree(); |
||||
let windows = con::get_windows(&root, extra_props); |
||||
if let Some(win) = windows |
||||
.iter() |
||||
.find(|w| w.is_urgent()) |
||||
.or_else(|| windows.get(0)) |
||||
{ |
||||
println!("Switching to {}", win); |
||||
focus_window_by_id(win.get_id()) |
||||
} else { |
||||
println!("No window to switch to.") |
||||
} |
||||
} |
||||
|
||||
pub fn switch_window(extra_props: Option<&HashMap<i64, ipc::ExtraProps>>) { |
||||
let root = get_tree(); |
||||
let windows = con::get_windows(&root, extra_props); |
||||
|
||||
if let Some(window) = con::select_window("Switch to window", &windows) { |
||||
focus_window_by_id(window.get_id()) |
||||
} |
||||
} |
||||
|
||||
pub enum Direction { |
||||
Backward, |
||||
Forward, |
||||
} |
||||
|
||||
pub fn focus_next_window_in_direction( |
||||
dir: Direction, |
||||
extra_props: Option<&HashMap<i64, ipc::ExtraProps>>, |
||||
) { |
||||
let root = get_tree(); |
||||
let windows = con::get_windows(&root, None); |
||||
|
||||
if windows.len() < 2 { |
||||
return; |
||||
} |
||||
|
||||
let pred: Box<dyn Fn(&con::Window) -> bool> = |
||||
if windows.iter().find(|w| w.is_focused()).is_none() { |
||||
let last_focused_win_id = con::get_windows(&root, extra_props) |
||||
.get(0) |
||||
.unwrap() |
||||
.get_id(); |
||||
Box::new(move |w| w.get_id() == last_focused_win_id) |
||||
} else { |
||||
Box::new(|w: &con::Window| w.is_focused()) |
||||
}; |
||||
|
||||
let mut iter: Box<dyn Iterator<Item = &con::Window>> = match dir { |
||||
Direction::Forward => Box::new(windows.iter().rev().cycle()), |
||||
Direction::Backward => Box::new(windows.iter().cycle()), |
||||
}; |
||||
|
||||
loop { |
||||
let win = iter.next().unwrap(); |
||||
if pred(win) { |
||||
let win = iter.next().unwrap(); |
||||
focus_window_by_id(win.get_id()); |
||||
return; |
||||
} |
||||
} |
||||
} |
||||
|
||||
pub fn switch_workspace(extra_props: Option<&HashMap<i64, ipc::ExtraProps>>) { |
||||
let root = get_tree(); |
||||
let workspaces = con::get_workspaces(&root, false, extra_props); |
||||
|
||||
if let Some(workspace) = |
||||
con::select_workspace("Switch to workspace", &workspaces) |
||||
{ |
||||
util::swaymsg(&["workspace", "number", workspace.get_name()]); |
||||
} |
||||
} |
||||
|
||||
pub fn switch_workspace_or_window( |
||||
extra_props: Option<&HashMap<i64, ipc::ExtraProps>>, |
||||
) { |
||||
let root = get_tree(); |
||||
let workspaces = con::get_workspaces(&root, false, extra_props); |
||||
let ws_or_wins = con::WsOrWin::from_workspaces(&workspaces); |
||||
if let Some(ws_or_win) = con::select_workspace_or_window( |
||||
"Select workspace or window", |
||||
&ws_or_wins, |
||||
) { |
||||
match ws_or_win { |
||||
con::WsOrWin::Ws { ws } => { |
||||
util::swaymsg(&["workspace", "number", ws.get_name()]); |
||||
} |
||||
con::WsOrWin::Win { win } => focus_window_by_id(win.get_id()), |
||||
} |
||||
} |
||||
} |
||||
|
||||
pub fn quit_window(extra_props: Option<&HashMap<i64, ipc::ExtraProps>>) { |
||||
let root = get_tree(); |
||||
let windows = con::get_windows(&root, extra_props); |
||||
|
||||
if let Some(window) = con::select_window("Quit window", &windows) { |
||||
quit_window_by_id(window.get_id()) |
||||
} |
||||
} |
||||
|
||||
pub fn quit_workspace_or_window( |
||||
extra_props: Option<&HashMap<i64, ipc::ExtraProps>>, |
||||
) { |
||||
let root = get_tree(); |
||||
let workspaces = con::get_workspaces(&root, false, extra_props); |
||||
let ws_or_wins = con::WsOrWin::from_workspaces(&workspaces); |
||||
if let Some(ws_or_win) = |
||||
con::select_workspace_or_window("Quit workspace or window", &ws_or_wins) |
||||
{ |
||||
match ws_or_win { |
||||
con::WsOrWin::Ws { ws } => { |
||||
for win in &ws.windows { |
||||
quit_window_by_id(win.get_id()) |
||||
} |
||||
} |
||||
con::WsOrWin::Win { win } => quit_window_by_id(win.get_id()), |
||||
} |
||||
} |
||||
} |
||||
|
||||
fn get_swaymsg_commands<'a>() -> Vec<SwaymsgCmd<'a>> { |
||||
let mut cmds = vec![]; |
||||
cmds.push(vec!["exit"]); |
||||
cmds.push(vec!["floating", "toggle"]); |
||||
cmds.push(vec!["focus", "child"]); |
||||
cmds.push(vec!["focus", "parent"]); |
||||
|
||||
for b in &["none", "normal", "csd", "pixel"] { |
||||
cmds.push(vec!["border", b]); |
||||
} |
||||
|
||||
cmds.push(vec!["focus", "tiling"]); |
||||
cmds.push(vec!["focus", "floating"]); |
||||
cmds.push(vec!["focus", "mode_toggle"]); |
||||
|
||||
cmds.push(vec!["fullscreen", "toggle"]); |
||||
|
||||
for x in &["focus", "fullscreen", "open", "none", "visible"] { |
||||
cmds.push(vec!["inhibit_idle", x]) |
||||
} |
||||
|
||||
for l in &["default", "splith", "splitv", "stacking", "tiling"] { |
||||
cmds.push(vec!["layout", l]) |
||||
} |
||||
|
||||
cmds.push(vec!["reload"]); |
||||
|
||||
for e in &["enable", "disable"] { |
||||
cmds.push(vec!["shortcuts", "inhibitor", e]) |
||||
} |
||||
|
||||
cmds.push(vec!["sticky", "toggle"]); |
||||
|
||||
for x in &["yes", "no", "always"] { |
||||
cmds.push(vec!["focus_follows_mouse", x]) |
||||
} |
||||
|
||||
for x in &["smart", "urgent", "focus", "none"] { |
||||
cmds.push(vec!["focus_on_window_activation", x]) |
||||
} |
||||
|
||||
for x in &["yes", "no", "force", "workspace"] { |
||||
cmds.push(vec!["focus_wrapping", x]) |
||||
} |
||||
|
||||
for x in &[ |
||||
"none", |
||||
"vertical", |
||||
"horizontal", |
||||
"both", |
||||
"smart", |
||||
"smart_no_gaps", |
||||
] { |
||||
cmds.push(vec!["hide_edge_borders", x]) |
||||
} |
||||
|
||||
cmds.push(vec!["kill"]); |
||||
|
||||
for x in &["on", "no_gaps", "off"] { |
||||
cmds.push(vec!["smart_borders", x]) |
||||
} |
||||
|
||||
for x in &["on", "off"] { |
||||
cmds.push(vec!["smart_gaps", x]) |
||||
} |
||||
|
||||
for x in &["output", "container", "none"] { |
||||
cmds.push(vec!["mouse_warping", x]) |
||||
} |
||||
|
||||
for x in &["smart", "ignore", "leave_fullscreen"] { |
||||
cmds.push(vec!["popup_during_fullscreen", x]) |
||||
} |
||||
|
||||
for x in &["yes", "no"] { |
||||
cmds.push(vec!["show_marks", x]); |
||||
cmds.push(vec!["workspace_auto_back_and_forth", x]); |
||||
} |
||||
|
||||
cmds.push(vec!["tiling_drag", "toggle"]); |
||||
|
||||
for x in &["left", "center", "right"] { |
||||
cmds.push(vec!["title_align", x]); |
||||
} |
||||
|
||||
for x in &["enable", "disable", "allow", "deny"] { |
||||
cmds.push(vec!["urgent", x]) |
||||
} |
||||
|
||||
cmds.sort(); |
||||
|
||||
cmds.iter() |
||||
.map(|v| SwaymsgCmd { cmd: v.to_vec() }) |
||||
.collect() |
||||
} |
||||
|
||||
struct SwaymsgCmd<'a> { |
||||
cmd: Vec<&'a str>, |
||||
} |
||||
|
||||
impl<'a> fmt::Display for SwaymsgCmd<'a> { |
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { |
||||
write!(f, "<b>{}</b>", self.cmd.join(" ")) |
||||
} |
||||
} |
||||
|
||||
pub fn exec_swaymsg_command() { |
||||
let cmds = get_swaymsg_commands(); |
||||
let cmd = util::wofi_select("Execute swaymsg command", &cmds); |
||||
if let Some(cmd) = cmd { |
||||
util::swaymsg(&cmd.cmd); |
||||
} |
||||
} |
Loading…
Reference in new issue