|
|
|
@ -1,9 +1,11 @@ |
|
|
|
|
use crate::ipc; |
|
|
|
|
use std::cmp; |
|
|
|
|
use std::collections::HashMap; |
|
|
|
|
|
|
|
|
|
#[derive(Debug)] |
|
|
|
|
pub struct Window<'a> { |
|
|
|
|
pub node: &'a ipc::Node, |
|
|
|
|
win_props: Option<ipc::WindowProps>, |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
impl Window<'_> { |
|
|
|
@ -31,6 +33,40 @@ impl Window<'_> { |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
impl PartialEq for Window<'_> { |
|
|
|
|
fn eq(&self, other: &Window) -> bool { |
|
|
|
|
self.get_id() == other.get_id() |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
impl Eq for Window<'_> {} |
|
|
|
|
|
|
|
|
|
impl Ord for Window<'_> { |
|
|
|
|
fn cmp(&self, other: &Self) -> cmp::Ordering { |
|
|
|
|
if self == other { |
|
|
|
|
cmp::Ordering::Equal |
|
|
|
|
} else if self.node.urgent && !other.node.urgent { |
|
|
|
|
cmp::Ordering::Less |
|
|
|
|
} else if !self.node.urgent && other.node.urgent { |
|
|
|
|
std::cmp::Ordering::Greater |
|
|
|
|
} else if self.node.focused && !other.node.focused { |
|
|
|
|
std::cmp::Ordering::Greater |
|
|
|
|
} else if !self.node.focused && other.node.focused { |
|
|
|
|
std::cmp::Ordering::Less |
|
|
|
|
} else { |
|
|
|
|
let lru_a = self.win_props.as_ref().map_or(0, |wp| wp.last_focus_time); |
|
|
|
|
let lru_b = other.win_props.as_ref().map_or(0, |wp| wp.last_focus_time); |
|
|
|
|
lru_a.cmp(&lru_b).reverse() |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
impl PartialOrd for Window<'_> { |
|
|
|
|
fn partial_cmp(&self, other: &Window) -> Option<cmp::Ordering> { |
|
|
|
|
Some(self.cmp(other)) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
impl<'a> std::fmt::Display for Window<'a> { |
|
|
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> { |
|
|
|
|
write!( |
|
|
|
@ -49,41 +85,20 @@ impl<'a> std::fmt::Display for Window<'a> { |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/// Gets all application windows of the tree.
|
|
|
|
|
pub fn get_windows(tree: &ipc::Node) -> Vec<Window> { |
|
|
|
|
pub fn get_windows( |
|
|
|
|
tree: &ipc::Node, |
|
|
|
|
mut win_props: HashMap<ipc::Id, ipc::WindowProps>, |
|
|
|
|
) -> Vec<Window> { |
|
|
|
|
let mut v = vec![]; |
|
|
|
|
for n in tree.iter() { |
|
|
|
|
if n.name.is_some() |
|
|
|
|
&& (n.r#type == ipc::NodeType::Con || n.r#type == ipc::NodeType::FloatingCon) |
|
|
|
|
{ |
|
|
|
|
v.push(Window { node: &n }) |
|
|
|
|
v.push(Window { |
|
|
|
|
node: &n, |
|
|
|
|
win_props: win_props.remove(&n.id), |
|
|
|
|
}) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
v |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/// Sorts windows so that urgent windows come first, the currently focused
|
|
|
|
|
/// window comes last, and otherwise windows are sorted in last-recently-used
|
|
|
|
|
/// order.
|
|
|
|
|
pub fn sort_windows(windows: &mut Vec<Window>, win_props: HashMap<ipc::Id, ipc::WindowProps>) { |
|
|
|
|
windows.sort_unstable_by(|a, b| { |
|
|
|
|
if a.node.urgent && !b.node.urgent { |
|
|
|
|
std::cmp::Ordering::Less |
|
|
|
|
} else if !a.node.urgent && b.node.urgent { |
|
|
|
|
std::cmp::Ordering::Greater |
|
|
|
|
} else if a.node.focused && !b.node.focused { |
|
|
|
|
std::cmp::Ordering::Greater |
|
|
|
|
} else if !a.node.focused && 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() |
|
|
|
|
} |
|
|
|
|
}); |
|
|
|
|
} |
|
|
|
|