use crate::sort::{sort_clients_by_position, sort_clients_by_recent};
use core_lib::{
Active, ClientData, ClientId, FindByFirst, HyprlandData, MonitorData, MonitorId, WorkspaceData,
WorkspaceId,
};
use exec_lib::collect::collect_hypr_data;
use tracing::{Level, span, trace, warn};
#[derive(Debug, Clone, Default)]
pub struct SortConfig {
pub sort_recent: bool,
pub filter_current_workspace: bool,
pub filter_current_monitor: bool,
pub filter_same_class: bool,
}
pub fn collect_data(config: &SortConfig) -> anyhow::Result<(HyprlandData, Active)> {
let _span = span!(Level::TRACE, "collect_data").entered();
let (mut client_data, workspace_data, monitor_data, active_client, active_ws, active_monitor) =
collect_hypr_data()?;
client_data = update_client_position(client_data, &workspace_data, &monitor_data);
if config.sort_recent {
sort_clients_by_recent(&mut client_data);
} else {
client_data = sort_clients_by_position(client_data);
}
trace!(
"active_client: {active_client:?}; active_ws: {active_ws:?}; active_monitor: {active_monitor:?}"
);
for (_, client) in client_data.iter_mut() {
client.enabled = (!config.filter_same_class
|| active_client
.as_ref()
.is_none_or(|active| client.class == *active.0))
&& (!config.filter_current_workspace || client.workspace == active_ws)
&& (!config.filter_current_monitor || client.monitor == active_monitor);
}
trace!("client_data: {:?}", client_data);
trace!("workspace_data: {:?}", workspace_data);
trace!("monitor_data: {:?}", monitor_data);
Ok((
HyprlandData {
clients: client_data,
workspaces: workspace_data,
monitors: monitor_data,
},
Active {
client: active_client.map(|c| c.1),
workspace: active_ws,
monitor: active_monitor,
},
))
}
pub fn update_client_position(
clients: Vec<(ClientId, ClientData)>,
workspace_data: &[(WorkspaceId, WorkspaceData)],
monitor_data: &[(MonitorId, MonitorData)],
) -> Vec<(ClientId, ClientData)> {
clients
.into_iter()
.filter_map(|(a, mut c)| {
let ws = workspace_data
.find_by_first(&c.workspace)
.map(|ws| (ws.x, ws.y))
.or_else(|| {
warn!("Workspace {:?} not found for client: {:?}", c.workspace, c);
None
});
let md = monitor_data
.find_by_first(&c.monitor)
.map(|md| (md.x, md.y))
.or_else(|| {
warn!("Monitor {:?} not found: {:?}", c.monitor, c);
None
});
if let (Some((ws_x, ws_y)), Some((md_x, md_y))) = (ws, md) {
c.x += (ws_x - md_x) as i16; c.y += (ws_y - md_y) as i16; Some((a, c))
} else {
None
}
})
.collect()
}