sort by output

This commit is contained in:
Henry Hiles 2026-04-21 11:18:03 -04:00
commit bb9fdfa83d
Signed by: Henry-Hiles
SSH key fingerprint: SHA256:VKQUdS31Q90KvX7EkKMHMBpUspcmItAh86a+v7PGiIs
2 changed files with 97 additions and 31 deletions

View file

@ -36,6 +36,7 @@ pub fn listen_workspaces(sink: StreamSink<Vec<Vec<Workspace>>>) -> Result<()> {
let qh = event_queue.handle();
let mut state = AppState {
outputs: HashMap::new(),
workspaces: HashMap::new(),
workspace_groups: HashMap::new(),
workspace_handles: HashMap::new(),

View file

@ -2,7 +2,7 @@ use crate::{frb_generated::StreamSink, workspace_api::Workspace};
use std::collections::HashMap;
use wayland_client::{
self, event_created_child, protocol::wl_registry, Connection, Dispatch, Proxy, QueueHandle,
self, event_created_child, protocol::{wl_registry, wl_output}, Connection, Dispatch, Proxy, QueueHandle,
};
use wayland_protocols::ext::workspace::v1::client::{
@ -14,36 +14,47 @@ pub struct WorkspaceHandles {
pub manager_handle: ext_workspace_manager_v1::ExtWorkspaceManagerV1,
}
pub struct Output {
pub coords: (i32, i32),
}
pub struct WorkspaceGroup {
pub output_id: Option<u32>,
pub children: Vec<u32>,
}
pub struct AppState {
pub outputs: HashMap<u32, Output>,
pub workspaces: HashMap<u32, Workspace>,
pub workspace_groups: HashMap<u32, u32>,
pub workspace_groups: HashMap<u32, WorkspaceGroup>,
pub workspace_handles: HashMap<u32, WorkspaceHandles>,
pub sink: StreamSink<Vec<Vec<Workspace>>>,
}
impl AppState {
fn emit(&self) {
let mut groups: HashMap<u32, Vec<(&u32, &Workspace)>> = HashMap::new();
let mut groups: Vec<_> = self.workspace_groups.values().collect();
for (ws_id, ws) in &self.workspaces {
if let Some(group_id) = self.workspace_groups.get(ws_id) {
groups
.entry(group_id.clone())
.or_insert_with(Vec::new)
.push((ws_id, ws));
}
}
groups.sort_by_key(|group| {
group.output_id.as_ref().and_then(|o| {
self.outputs.get(o).map(|info| info.coords.0)
})
});
let mut grouped: Vec<(u32, Vec<(&u32, &Workspace)>)> = groups.into_iter().collect();
grouped.sort_by_key(|(group_id, _)| group_id.clone());
let result = grouped
let result: Vec<Vec<Workspace>> = groups
.into_iter()
.map(|(_, mut entries)| {
entries.sort_by_key(|(_, value)| value.coords);
.map(|group| {
let mut workspaces: Vec<Workspace> = group
.children
.iter()
.filter_map(|id| self.workspaces.get(id))
.cloned()
.collect();
entries.into_iter().map(|(_, ws)| ws.clone()).collect()
workspaces.sort_by_key(|ws|
ws.coords.as_ref().map(|coords| coords.0)
);
workspaces
})
.collect();
@ -66,7 +77,8 @@ impl Dispatch<wl_registry::WlRegistry, ()> for AppState {
version,
} = event
{
if interface == "ext_workspace_manager_v1" {
match interface.as_str() {
"ext_workspace_manager_v1" => {
registry.bind::<ext_workspace_manager_v1::ExtWorkspaceManagerV1, (), AppState>(
name,
version,
@ -74,6 +86,18 @@ impl Dispatch<wl_registry::WlRegistry, ()> for AppState {
(),
);
}
"wl_output" => {
registry.bind::<wl_output::WlOutput, (), AppState>(
name,
version,
qh,
(),
);
}
_ => {}
}
}
}
}
@ -192,7 +216,25 @@ impl Dispatch<ext_workspace_group_handle_v1::ExtWorkspaceGroupHandleV1, ()> for
ext_workspace_group_handle_v1::Event::WorkspaceEnter { workspace } => {
state
.workspace_groups
.insert(workspace.id().protocol_id(), group_id.protocol_id());
.entry(group_id.protocol_id())
.or_insert_with(|| WorkspaceGroup {
output_id: None,
children: Vec::new(),
})
.children
.push(workspace.id().protocol_id());
state.emit();
}
ext_workspace_group_handle_v1::Event::OutputEnter { output } => {
state
.workspace_groups
.entry(group_id.protocol_id())
.or_insert_with(|| WorkspaceGroup {
output_id: None,
children: Vec::new(),
})
.output_id = Some(output.id().protocol_id());
state.emit();
}
@ -205,3 +247,26 @@ impl Dispatch<ext_workspace_group_handle_v1::ExtWorkspaceGroupHandleV1, ()> for
}
}
}
impl Dispatch<wl_output::WlOutput, ()> for AppState {
fn event(
state: &mut Self,
proxy: &wl_output::WlOutput,
event: wl_output::Event,
_data: &(),
_conn: &Connection,
_qh: &QueueHandle<Self>,
) {
match event {
wl_output::Event::Geometry {
x,
y,
..
} => {
state.outputs.insert(proxy.id().protocol_id(), Output { coords: ( x, y ) });
state.emit();
}
_ => {}
}
}
}