Window switcher seems to work

timeout_old
Tassilo Horn 4 years ago
parent 0291efa989
commit aa1fadd6fd
  1. 20
      src/bin/swayr.rs
  2. 44
      src/client.rs
  3. 2
      src/ipc.rs
  4. 1
      src/lib.rs
  5. 21
      src/util.rs
  6. 20
      src/window.rs

@ -1,21 +1,5 @@
use std::collections::HashMap; use swayr::client;
use std::os::unix::net::UnixStream;
use swayr::ipc;
use swayr::util;
use swayr::window;
fn main() { fn main() {
println!("sway here!"); client::switch_window();
let root_node = ipc::get_tree();
for win in window::get_windows(&root_node) {
println!(" {}", win);
}
if let Ok(sock) = UnixStream::connect(util::get_swayr_socket_path()) {
let win_props: Result<HashMap<ipc::Id, ipc::WindowProps>, serde_json::Error> =
serde_json::from_reader(sock);
println!("Here are the window properties:\n{:#?}", win_props)
} else {
panic!("Could not connect to socket!")
}
} }

@ -0,0 +1,44 @@
use crate::ipc;
use crate::util;
use crate::window;
use std::collections::HashMap;
use std::os::unix::net::UnixStream;
fn get_window_props() -> Result<HashMap<ipc::Id, ipc::WindowProps>, serde_json::Error> {
if let Ok(sock) = UnixStream::connect(util::get_swayr_socket_path()) {
serde_json::from_reader(sock)
} else {
panic!("Could not connect to socket!")
}
}
pub fn switch_window() {
let root_node = ipc::get_tree();
let mut windows = window::get_windows(&root_node);
if let Ok(win_props) = get_window_props() {
windows.sort_unstable_by(|a, b| {
if a.node.focused {
std::cmp::Ordering::Greater
} else if b.node.focused {
std::cmp::Ordering::Less
} else {
let lru_a = win_props
.get(&a.node.id)
.map(|p| p.last_focus_time)
.unwrap_or(0);
let lru_b = win_props
.get(&b.node.id)
.map(|p| p.last_focus_time)
.unwrap_or(0);
lru_a.cmp(&lru_b).reverse()
}
});
}
if let Some(window) = util::select_window(&windows) {
util::swaymsg(vec![
format!("[con_id={}]", window.node.id).as_str(),
"focus",
]);
}
}

@ -7,7 +7,7 @@ use std::process as proc;
pub type Id = u32; pub type Id = u32;
pub type Dim = u16; pub type Dim = u16;
pub type Pid = u16; pub type Pid = u32;
#[derive(Deserialize, Debug)] #[derive(Deserialize, Debug)]
#[allow(dead_code)] #[allow(dead_code)]

@ -1,3 +1,4 @@
pub mod client;
pub mod demon; pub mod demon;
pub mod ipc; pub mod ipc;
pub mod util; pub mod util;

@ -1,3 +1,4 @@
use crate::window;
use std::io::Write; use std::io::Write;
use std::process as proc; use std::process as proc;
@ -9,12 +10,26 @@ pub fn get_swayr_socket_path() -> String {
format!("/run/user/{}/swayr-sock", users::get_current_uid()) format!("/run/user/{}/swayr-sock", users::get_current_uid())
} }
pub fn swaymsg(args: Vec<&str>) -> String {
let mut cmd = proc::Command::new("swaymsg");
for a in args {
cmd.arg(a);
}
let output = cmd.output().expect("Error running swaymsg!");
String::from_utf8(output.stdout).unwrap()
}
pub fn select_window<'a>(windows: &'a Vec<window::Window>) -> Option<&'a window::Window<'a>> {
wofi_select("Select window", windows)
}
pub fn wofi_select<'a, 'b, TS>(prompt: &'a str, choices: &'b Vec<TS>) -> Option<&'b TS> pub fn wofi_select<'a, 'b, TS>(prompt: &'a str, choices: &'b Vec<TS>) -> Option<&'b TS>
where where
TS: std::fmt::Display + Sized, TS: std::fmt::Display + Sized,
{ {
let mut map: std::collections::HashMap<String, &TS> = std::collections::HashMap::new(); let mut map: std::collections::HashMap<String, &TS> = std::collections::HashMap::new();
for c in choices.iter() { for c in choices {
map.insert(format!("{}", c), c); map.insert(format!("{}", c), c);
} }
@ -29,9 +44,9 @@ where
{ {
let stdin = wofi.stdin.as_mut().expect("Failed to open wofi stdin"); let stdin = wofi.stdin.as_mut().expect("Failed to open wofi stdin");
for k in map.keys() { for c in choices {
stdin stdin
.write_all(format!("{}\n", k).as_bytes()) .write_all(format!("{}\n", c).as_bytes())
.expect("Failed to write to wofi stdin"); .expect("Failed to write to wofi stdin");
} }
} }

@ -1,15 +1,23 @@
use crate::ipc; use crate::ipc;
#[allow(dead_code)] #[derive(Debug)]
pub struct Window<'a> { pub struct Window<'a> {
// TODO: Drop all fields except for node!
app_id: Option<&'a str>,
name: &'a str, name: &'a str,
id: ipc::Id, id: ipc::Id,
app_id: Option<&'a str>, pub node: &'a ipc::Node,
} }
impl<'a> std::fmt::Display for Window<'a> { impl<'a> std::fmt::Display for Window<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
write!(f, "{} — {}", self.app_id.unwrap_or(""), self.name) write!(
f,
"{} — {} <{}>",
self.app_id.unwrap_or(""),
self.name,
self.id
)
} }
} }
@ -21,16 +29,14 @@ pub fn get_windows(tree: &ipc::Node) -> Vec<Window> {
&& (n.r#type == ipc::NodeType::Con || n.r#type == ipc::NodeType::FloatingCon) && (n.r#type == ipc::NodeType::Con || n.r#type == ipc::NodeType::FloatingCon)
{ {
v.push(Window { v.push(Window {
name: &n name: &n.name.as_ref().unwrap(),
.name
.as_ref()
.unwrap_or_else(|| panic!("Con without name. id = {}", n.id)),
id: n.id, id: n.id,
app_id: match &n.app_id { app_id: match &n.app_id {
Some(s) => Some(s.as_ref()), Some(s) => Some(s.as_ref()),
// TODO: Use n.window_properties.class instead! // TODO: Use n.window_properties.class instead!
None => None, None => None,
}, },
node: &n,
}) })
} }
} }

Loading…
Cancel
Save