Split shell, settings, and compositor into focused modules

This commit is contained in:
Samuel Onoja committed 2026-10-01 12:47:26 +01:00
1 parent 2b9f30fa5d
commit cbf048566a
38 files changed
+9998 -9817

No files matched your search

+160
View File
@@ -0,0 +1,160 @@
use super::*;
impl Ferese {
pub fn register_output(&mut self, output: &Output, identity: String) {
if self.session_lock.active {
self.session_lock.output_added(output);
self.lock_input_activity();
}
let Some(geometry) = self.space.output_geometry(output) else {
tracing::error!(output = %output.name(), "cannot register an unmapped output");
return;
};
let output_id = *self.output_identity_ids.entry(identity).or_insert_with(|| {
let id = OutputId(self.next_output_id);
self.next_output_id = self.next_output_id.saturating_add(1);
id
});
let fallback_workspace = (1..)
.find_map(|index| {
let workspace = self.workspaces.ensure_numeric(index).ok()?;
self.output_workspaces
.output_for_workspace(workspace)
.is_none()
.then_some(workspace)
})
.expect("numeric workspaces are inexhaustible");
let geometry = OutputGeometry::new(geometry.loc.x, geometry.loc.y, geometry.size.w, geometry.size.h);
let registration = self.output_workspaces.connect(output_id, geometry, fallback_workspace);
match registration {
Ok(workspace) => {
self.output_ids.insert(output.clone(), output_id);
if self.output_workspaces.focused_output() == Some(output_id) {
self.activate_output_workspace(output_id, workspace);
}
self.send_shell_snapshots();
}
Err(error) => {
tracing::error!(%error, output = %output.name(), "failed to register output");
}
}
}
pub fn unregister_output(&mut self, output: &Output) {
let Some(output_id) = self.output_ids.remove(output) else {
return;
};
self.workspace_slides.remove(&output_id);
self.overview_scrims.remove(&output_id);
self.pending_screencopies.retain(|capture| {
if capture.output == *output {
capture.fail();
false
} else {
true
}
});
self.space.unmap_output(output);
self.session_lock.surfaces.remove(output);
self.session_lock.backgrounds.remove(output);
self.session_lock.output_removed(output);
match self.output_workspaces.disconnect(output_id) {
Ok(Some(target)) => {
if let Some(workspace) = self.output_workspaces.active_workspace(target) {
self.activate_output_workspace(target, workspace);
}
}
Ok(None) => {
self.focused_window = None;
self.restore_keyboard_focus();
}
Err(error) => {
tracing::error!(%error, output = %output.name(), "failed to unregister output")
}
}
self.relayout();
}
pub(crate) fn reposition_output_floats(&mut self, output: OutputId, old: Rect, new: Rect) {
let floats = self
.window_ids
.values()
.filter_map(|id| {
let workspace = self.workspaces.workspace_for_window(*id)?;
if self.output_workspaces.output_for_workspace(workspace) != Some(output) {
return None;
}
match self.workspaces.placement(*id)? {
WindowPlacement::Floating { rect } => Some((*id, moved_floating_rect(rect, old, new))),
_ => None,
}
})
.collect::<Vec<_>>();
for (id, rect) in floats {
let _ = self.workspaces.set_floating_rect(id, rect);
}
}
pub(super) fn activate_output_workspace(&mut self, output: OutputId, workspace: ferese_core::WorkspaceId) {
if let Err(error) = self.output_workspaces.focus_output(output) {
tracing::error!(%error, "failed to focus output");
return;
}
match self.workspaces.activate(workspace) {
Ok(focus) => self.focused_window = focus,
Err(error) => tracing::error!(%error, "failed to activate output workspace"),
}
}
pub(crate) fn focused_output(&self) -> Option<&Output> {
let focused = self.output_workspaces.focused_output()?;
self.output_ids
.iter()
.find_map(|(output, id)| (*id == focused).then_some(output))
}
pub(crate) fn restore_output_focus(&mut self) {
if let Some(output) = self.output_workspaces.focused_output()
&& let Some(workspace) = self.output_workspaces.active_workspace(output)
{
self.activate_output_workspace(output, workspace);
self.restore_keyboard_focus();
}
}
pub(crate) fn output_id(&self, output: &Output) -> Option<OutputId> {
self.output_ids.get(output).copied()
}
pub(crate) fn focus_output_at(&mut self, position: Point<f64, Logical>) {
let output = self.space.outputs().find_map(|output| {
let geometry = self.space.output_geometry(output)?;
(position.x >= f64::from(geometry.loc.x)
&& position.y >= f64::from(geometry.loc.y)
&& position.x < f64::from(geometry.loc.x + geometry.size.w)
&& position.y < f64::from(geometry.loc.y + geometry.size.h))
.then(|| output.clone())
});
let Some(output) = output else {
return;
};
let Some(output_id) = self.output_ids.get(&output).copied() else {
return;
};
let Some(workspace) = self.output_workspaces.active_workspace(output_id) else {
return;
};
if self.output_workspaces.focused_output() == Some(output_id) && self.workspaces.active_id() == workspace {
return;
}
self.activate_output_workspace(output_id, workspace);
self.relayout();
}
}