Simplify layout ids

This commit is contained in:
Ottatop 2024-05-17 15:56:50 -05:00
parent a8acb82b11
commit ab7e2051b1
2 changed files with 37 additions and 54 deletions

View file

@ -3,6 +3,7 @@ use pinnacle_api_defs::pinnacle::layout::v0alpha1::{
layout_service_server, LayoutRequest, LayoutResponse, layout_service_server, LayoutRequest, LayoutResponse,
}; };
use tonic::{Request, Response, Status, Streaming}; use tonic::{Request, Response, Status, Streaming};
use tracing::debug;
use crate::output::OutputName; use crate::output::OutputName;
@ -37,8 +38,7 @@ impl layout_service_server::LayoutService for LayoutService {
match body { match body {
layout_request::Body::Geometries(geos) => { layout_request::Body::Geometries(geos) => {
if let Err(err) = state.apply_layout(geos) { if let Err(err) = state.apply_layout(geos) {
// TODO: send a Status and handle the error client side debug!("{err}")
tracing::error!("{err}")
} }
} }
layout_request::Body::Layout(ExplicitLayout { output_name }) => { layout_request::Body::Layout(ExplicitLayout { output_name }) => {

View file

@ -1,9 +1,6 @@
// SPDX-License-Identifier: GPL-3.0-or-later // SPDX-License-Identifier: GPL-3.0-or-later
use std::{ use std::{collections::HashMap, time::Duration};
collections::{HashMap, HashSet},
time::Duration,
};
use pinnacle_api_defs::pinnacle::layout::v0alpha1::{layout_request::Geometries, LayoutResponse}; use pinnacle_api_defs::pinnacle::layout::v0alpha1::{layout_request::Geometries, LayoutResponse};
use smithay::{ use smithay::{
@ -165,23 +162,31 @@ impl Pinnacle {
} }
/// A monotonically increasing identifier for layout requests. /// A monotonically increasing identifier for layout requests.
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)] #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord, Default)]
pub struct LayoutRequestId(pub u32); pub struct LayoutRequestId(u32);
#[derive(Debug, Default)] #[derive(Debug, Default)]
pub struct LayoutState { pub struct LayoutState {
pub layout_request_sender: Option<UnboundedSender<Result<LayoutResponse, Status>>>, pub layout_request_sender: Option<UnboundedSender<Result<LayoutResponse, Status>>>,
pub pending_swap: bool, pub pending_swap: bool,
id_maps: HashMap<Output, LayoutRequestId>, pending_requests: HashMap<Output, LayoutRequestId>,
pending_requests: HashMap<Output, Vec<(LayoutRequestId, Vec<WindowElement>)>>, fulfilled_requests: HashMap<Output, LayoutRequestId>,
old_requests: HashMap<Output, HashSet<LayoutRequestId>>, current_id: LayoutRequestId,
}
impl LayoutState {
fn next_id(&mut self) -> LayoutRequestId {
self.current_id.0 += 1;
self.current_id
}
} }
impl Pinnacle { impl Pinnacle {
pub fn request_layout(&mut self, output: &Output) { pub fn request_layout(&mut self, output: &Output) -> Option<LayoutRequestId> {
let id = self.layout_state.next_id();
let Some(sender) = self.layout_state.layout_request_sender.as_ref() else { let Some(sender) = self.layout_state.layout_request_sender.as_ref() else {
warn!("Layout requested but no client has connected to the layout service"); warn!("Layout requested but no client has connected to the layout service");
return; return None;
}; };
let windows_on_foc_tags = output.with_state(|state| { let windows_on_foc_tags = output.with_state(|state| {
@ -220,19 +225,10 @@ impl Pinnacle {
let tag_ids = let tag_ids =
output.with_state(|state| state.focused_tags().map(|tag| tag.id().0).collect()); output.with_state(|state| state.focused_tags().map(|tag| tag.id().0).collect());
let id = self
.layout_state
.id_maps
.entry(output.clone())
.or_insert(LayoutRequestId(0));
self.layout_state self.layout_state
.pending_requests .pending_requests
.entry(output.clone()) .insert(output.clone(), id);
.or_default()
.push((*id, windows));
// TODO: error
let _ = sender.send(Ok(LayoutResponse { let _ = sender.send(Ok(LayoutResponse {
request_id: Some(id.0), request_id: Some(id.0),
output_name: Some(output.name()), output_name: Some(output.name()),
@ -242,7 +238,7 @@ impl Pinnacle {
output_height: Some(output_height as u32), output_height: Some(output_height as u32),
})); }));
*id = LayoutRequestId(id.0 + 1); Some(id)
} }
} }
@ -262,41 +258,22 @@ impl State {
anyhow::bail!("Output was invalid"); anyhow::bail!("Output was invalid");
}; };
let old_requests = self let Some(current_pending) = self
.pinnacle
.layout_state
.old_requests
.entry(output.clone())
.or_default();
if old_requests.contains(&request_id) {
anyhow::bail!("Attempted to layout but the request was already fulfilled");
}
let pending = self
.pinnacle .pinnacle
.layout_state .layout_state
.pending_requests .pending_requests
.entry(output.clone()) .get(&output)
.or_default(); .copied()
else {
let Some(latest) = pending.last().map(|(id, _)| *id) else { anyhow::bail!("attempted to layout without request");
anyhow::bail!("Attempted to layout but the request was nonexistent A");
}; };
if latest == request_id { if current_pending > request_id {
pending.pop(); anyhow::bail!("Attempted to layout but a new request came in");
} else if let Some(pos) = pending }
.split_last() if current_pending < request_id {
.and_then(|(_, rest)| rest.iter().position(|(id, _)| id == &request_id)) anyhow::bail!("Attempted to layout but request is newer");
{ }
// Ignore stale requests
old_requests.insert(request_id);
pending.remove(pos);
return Ok(());
} else {
anyhow::bail!("Attempted to layout but the request was nonexistent B");
};
let geometries = geometries let geometries = geometries
.into_iter() .into_iter()
@ -312,6 +289,12 @@ impl State {
anyhow::bail!("Attempted to layout but one or more dimensions were null"); anyhow::bail!("Attempted to layout but one or more dimensions were null");
}; };
self.pinnacle.layout_state.pending_requests.remove(&output);
self.pinnacle
.layout_state
.fulfilled_requests
.insert(output.clone(), current_pending);
self.pinnacle self.pinnacle
.update_windows_with_geometries(&output, geometries); .update_windows_with_geometries(&output, geometries);