Split shell, settings, and compositor into focused modules
This commit is contained in:
1 parent
2b9f30fa5d
commit
cbf048566a
38 files changed
+9998
-9817
No files matched your search
@@ -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();
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user