hyprshell_exec_lib/
collect.rs1use crate::to_client_id;
2use anyhow::Context;
3use core_lib::{
4 ClientData, ClientId, FindByFirst, MonitorData, MonitorId, WorkspaceData, WorkspaceId,
5};
6use hyprland::data::{Client, Clients, Monitor, Monitors, Workspace, Workspaces};
7use hyprland::prelude::*;
8use tracing::{debug_span, warn};
9
10fn get_hypr_data() -> anyhow::Result<(Vec<Monitor>, Vec<Workspace>, Vec<Client>)> {
11 let _span = debug_span!("get_hypr_data").entered();
12 let monitors = Monitors::get().context("monitors failed")?.to_vec();
13 let workspaces = {
15 let mut workspaces = Workspaces::get()
16 .context("workspaces failed")?
17 .into_iter()
18 .filter(|w| w.id != -1) .collect::<Vec<_>>();
20
21 workspaces.sort_by(|a, b| a.id.cmp(&b.id));
22 workspaces
23 };
24 let clients = Clients::get()
25 .context("clients failed")?
26 .into_iter()
27 .filter(|c| c.workspace.id != -1) .collect::<Vec<_>>();
29
30 Ok((monitors, workspaces, clients))
31}
32
33#[allow(clippy::type_complexity)]
34pub fn collect_hypr_data() -> anyhow::Result<(
35 Vec<(ClientId, ClientData)>,
36 Vec<(WorkspaceId, WorkspaceData)>,
37 Vec<(MonitorId, MonitorData)>,
38 Option<(String, ClientId)>,
39 WorkspaceId,
40 MonitorId,
41)> {
42 let _span = debug_span!("convert_hypr_data").entered();
43
44 let (monitors, workspaces, clients) =
45 get_hypr_data().context("loading hyprland data failed")?;
46
47 let mut monitor_data = {
50 let mut md: Vec<(MonitorId, MonitorData)> = Vec::with_capacity(monitors.iter().len());
51
52 for monitor in &monitors {
53 #[allow(clippy::cast_sign_loss)]
54 md.push((
55 monitor.id,
56 MonitorData {
57 x: monitor.x,
58 y: monitor.y,
59 width: (f32::from(monitor.width) / monitor.scale) as u16,
60 height: (f32::from(monitor.height) / monitor.scale) as u16,
61 connector: monitor.name.clone(),
62 },
63 ));
64 }
65 md
66 };
67
68 let mut workspace_data = {
70 let mut wd: Vec<(WorkspaceId, WorkspaceData)> = Vec::with_capacity(workspaces.len());
71
72 for (monitor_id, monitor_data) in &monitor_data {
73 workspaces
74 .iter()
75 .filter(|ws| ws.monitor_id == Some(*monitor_id))
76 .for_each(|workspace| {
77 wd.push((
78 workspace.id,
79 WorkspaceData {
80 name: workspace.name.clone(),
81 monitor: *monitor_id,
82 height: monitor_data.height,
83 width: monitor_data.width,
84 any_client_enabled: true, },
86 ));
87 });
88 }
89 wd
90 };
91
92 let client_data = {
93 let mut cd: Vec<(ClientId, ClientData)> = Vec::with_capacity(clients.len());
94
95 for client in clients {
96 let Some(monitor) = client.monitor else {
97 continue;
98 };
99 if workspace_data.find_by_first(&client.workspace.id).is_some() {
100 cd.push((
101 to_client_id(&client.address),
102 ClientData {
103 x: client.at.0,
104 y: client.at.1,
105 width: client.size.0,
106 height: client.size.1,
107 class: client.class.clone(),
108 workspace: client.workspace.id,
109 monitor,
110 focus_history_id: client.focus_history_id,
111 title: client.title.clone(),
112 floating: client.floating,
113 pid: client.pid,
114 enabled: true, },
116 ));
117 } else {
118 warn!(
119 "workspace {:?} not found for client {client:?}",
120 client.workspace
121 );
122 }
123 }
124 cd
125 };
126
127 workspace_data.sort_by(|a, b| a.0.cmp(&b.0));
128 monitor_data.sort_by(|a, b| a.0.cmp(&b.0));
129
130 let active_ws = Workspace::get_active()
133 .map(|w| w.id)
134 .context("active workspace failed")?;
135 let active_ws = Client::get_active()
136 .context("active client failed")?
137 .map_or(active_ws, |a| a.workspace.id);
138 let active_monitor = Monitor::get_active().context("active monitor failed")?.id;
139 let active_client = Client::get_active()
140 .context("active client failed")?
141 .map(|a| (a.class.clone(), to_client_id(&a.address)));
142
143 Ok((
144 client_data,
145 workspace_data,
146 monitor_data,
147 active_client,
148 active_ws,
149 active_monitor,
150 ))
151}