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,232 @@
|
||||
use super::*;
|
||||
|
||||
impl Ferese {
|
||||
pub fn surface_under(&self, position: Point<f64, Logical>) -> Option<(WlSurface, Point<f64, Logical>)> {
|
||||
if self.session_lock.active {
|
||||
return self.lock_surface_under(position);
|
||||
}
|
||||
if self.input_capture.active() {
|
||||
return None;
|
||||
}
|
||||
self.layer_surface_under(position, &[Layer::Overlay, Layer::Top])
|
||||
.map(|(_, surface, origin)| (surface, origin))
|
||||
.or_else(|| self.window_surface_under(position))
|
||||
.or_else(|| {
|
||||
self.layer_surface_under(position, &[Layer::Bottom, Layer::Background])
|
||||
.map(|(_, surface, origin)| (surface, origin))
|
||||
})
|
||||
}
|
||||
|
||||
pub fn layer_under(&self, position: Point<f64, Logical>) -> Option<(LayerSurface, WlSurface, Point<f64, Logical>)> {
|
||||
if self.session_lock.active {
|
||||
return None;
|
||||
}
|
||||
if let Some(layer) = self.layer_surface_under(position, &[Layer::Overlay, Layer::Top]) {
|
||||
return Some(layer);
|
||||
}
|
||||
if self.window_surface_under(position).is_some() {
|
||||
return None;
|
||||
}
|
||||
|
||||
self.layer_surface_under(position, &[Layer::Bottom, Layer::Background])
|
||||
}
|
||||
|
||||
pub(super) fn window_surface_under(
|
||||
&self,
|
||||
position: Point<f64, Logical>,
|
||||
) -> Option<(WlSurface, Point<f64, Logical>)> {
|
||||
if self.overview.is_active() {
|
||||
return None;
|
||||
}
|
||||
|
||||
let workspace = self.workspace_under_pointer(position)?;
|
||||
self.space.elements().rev().find_map(|window| {
|
||||
let id = self.window_ids.get(window)?;
|
||||
if self.workspaces.workspace_for_window(*id) != Some(workspace) {
|
||||
return None;
|
||||
}
|
||||
let visual = self.presented_window_rect(*id)?;
|
||||
let inside_visual = position.x >= visual.x
|
||||
&& position.y >= visual.y
|
||||
&& position.x < visual.x + visual.width
|
||||
&& position.y < visual.y + visual.height;
|
||||
if !inside_visual {
|
||||
return None;
|
||||
}
|
||||
|
||||
let (source_x, source_y) = self.inverse_presented_window_point(*id, position.x, position.y)?;
|
||||
let source_point = Point::from((source_x, source_y)) + window.geometry().loc.to_f64();
|
||||
|
||||
let surface = window.surface_under(source_point, WindowSurfaceType::ALL);
|
||||
let (surface, surface_location) = match surface {
|
||||
Some(hit) => hit,
|
||||
None if self.window_fills_visual_bounds(*id, workspace) => {
|
||||
(window.toplevel()?.wl_surface().clone(), Point::from((0, 0)))
|
||||
}
|
||||
None => return None,
|
||||
};
|
||||
let surface_point = source_point - surface_location.to_f64();
|
||||
Some((surface, position - surface_point))
|
||||
})
|
||||
}
|
||||
|
||||
pub(super) fn window_fills_visual_bounds(&self, id: WindowId, workspace: WorkspaceId) -> bool {
|
||||
self.maximized_windows.contains(&id)
|
||||
|| self
|
||||
.workspaces
|
||||
.workspace(workspace)
|
||||
.is_some_and(|workspace| workspace.fullscreen == Some(id))
|
||||
}
|
||||
|
||||
pub(super) fn layer_surface_under(
|
||||
&self,
|
||||
position: Point<f64, Logical>,
|
||||
layers: &[Layer],
|
||||
) -> Option<(LayerSurface, WlSurface, Point<f64, Logical>)> {
|
||||
let output = self.space.output_under(position).next()?;
|
||||
let output_geometry = self.space.output_geometry(output)?;
|
||||
let output_position = position - output_geometry.loc.to_f64();
|
||||
let map = layer_map_for_output(output);
|
||||
|
||||
for requested in layers {
|
||||
if *requested == Layer::Top && self.output_has_fullscreen(output) {
|
||||
continue;
|
||||
}
|
||||
for layer in map.layers_on(*requested).rev() {
|
||||
let geometry = map.layer_geometry(layer)?;
|
||||
let layer_position = output_position - geometry.loc.to_f64();
|
||||
let Some((surface, surface_location)) = layer.surface_under(layer_position, WindowSurfaceType::ALL)
|
||||
else {
|
||||
continue;
|
||||
};
|
||||
let origin = output_geometry.loc + geometry.loc + surface_location;
|
||||
|
||||
return Some((layer.clone(), surface, origin.to_f64()));
|
||||
}
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
pub fn send_cursor_frame(&self, output: &Output) {
|
||||
let CursorImageStatus::Surface(surface) = &self.cursor_status else {
|
||||
return;
|
||||
};
|
||||
let Some(pointer) = self.seat.get_pointer() else {
|
||||
return;
|
||||
};
|
||||
if self.space.output_under(pointer.current_location()).next() != Some(output) {
|
||||
return;
|
||||
}
|
||||
|
||||
send_frames_surface_tree(
|
||||
surface,
|
||||
output,
|
||||
self.start_time.elapsed(),
|
||||
Some(Duration::ZERO),
|
||||
|_, _| Some(output.clone()),
|
||||
);
|
||||
}
|
||||
|
||||
pub fn window_under_visual(&self, position: Point<f64, Logical>) -> Option<Window> {
|
||||
let overview_active = self.overview.is_active();
|
||||
let workspace = self.workspace_under_pointer(position)?;
|
||||
|
||||
let hit = |window: &Window| -> Option<Window> {
|
||||
if !self.window_content_ready(window) {
|
||||
return None;
|
||||
}
|
||||
|
||||
let id = self.window_ids.get(window)?;
|
||||
if self.workspaces.workspace_for_window(*id) != Some(workspace) {
|
||||
return None;
|
||||
}
|
||||
|
||||
let visual = self.presented_window_rect(*id)?;
|
||||
let caption_height = if overview_active { 34.0 } else { 0.0 };
|
||||
let inside_visual = position.x >= visual.x
|
||||
&& position.y >= visual.y
|
||||
&& position.x < visual.x + visual.width
|
||||
&& position.y < visual.y + visual.height + caption_height;
|
||||
if !inside_visual {
|
||||
return None;
|
||||
}
|
||||
|
||||
if !overview_active {
|
||||
let (source_x, source_y) = self.inverse_presented_window_point(*id, position.x, position.y)?;
|
||||
let source_point = Point::from((source_x, source_y)) + window.geometry().loc.to_f64();
|
||||
if window.surface_under(source_point, WindowSurfaceType::ALL).is_none()
|
||||
&& !self.window_fills_visual_bounds(*id, workspace)
|
||||
{
|
||||
return None;
|
||||
}
|
||||
}
|
||||
|
||||
Some(window.clone())
|
||||
};
|
||||
|
||||
if overview_active {
|
||||
let mut candidates = self.window_ids.keys().cloned().collect::<Vec<_>>();
|
||||
// Match Overview's front-to-back render order during overlapping motion.
|
||||
candidates.sort_by_key(|window| std::cmp::Reverse(self.window_ids.get(window).map_or(0, |id| id.0)));
|
||||
candidates.iter().find_map(hit)
|
||||
} else {
|
||||
self.space.elements().rev().find_map(hit)
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn workspace_under_pointer(&self, position: Point<f64, Logical>) -> Option<WorkspaceId> {
|
||||
let output = self.space.output_under(position).next()?;
|
||||
self.output_workspaces.active_workspace(self.output_id(output)?)
|
||||
}
|
||||
|
||||
pub(crate) fn window_belongs_to_output(&self, window: WindowId, output: &Output) -> bool {
|
||||
let Some(output_id) = self.output_id(output) else {
|
||||
return false;
|
||||
};
|
||||
let workspace = self.workspaces.workspace_for_window(window);
|
||||
workspace == self.output_workspaces.active_workspace(output_id)
|
||||
|| self
|
||||
.workspace_slides
|
||||
.get(&output_id)
|
||||
.is_some_and(|slide| workspace.is_some_and(|workspace| slide.contains(workspace)))
|
||||
}
|
||||
|
||||
pub fn visual_scale_for_window(&self, window: &Window) -> Option<(f64, f64)> {
|
||||
if !self.overview.is_presenting() {
|
||||
return Some((1.0, 1.0));
|
||||
}
|
||||
let id = self.window_ids.get(window)?;
|
||||
let geometry = self.window_geometry.get(id)?;
|
||||
let source = geometry.client.committed_size?;
|
||||
let presented = self.presented_window_rect(*id)?;
|
||||
|
||||
if source.width <= 0 || source.height <= 0 {
|
||||
return None;
|
||||
}
|
||||
|
||||
Some((
|
||||
presented.width / f64::from(source.width),
|
||||
presented.height / f64::from(source.height),
|
||||
))
|
||||
}
|
||||
|
||||
pub(crate) fn visual_rect_for_window(&self, window: &Window) -> Option<Rectangle<i32, Logical>> {
|
||||
let id = self.window_ids.get(window)?;
|
||||
let rect = self.presented_window_rect(*id)?;
|
||||
let size = ClientSize::from_rect(rect);
|
||||
Some(Rectangle::new(
|
||||
(rect.x.round() as i32, rect.y.round() as i32).into(),
|
||||
(size.width, size.height).into(),
|
||||
))
|
||||
}
|
||||
|
||||
pub(crate) fn window_content_ready(&self, window: &Window) -> bool {
|
||||
window_has_buffer(window)
|
||||
&& self
|
||||
.window_ids
|
||||
.get(window)
|
||||
.and_then(|id| self.window_geometry.get(id))
|
||||
.is_some_and(|geometry| geometry.client.committed_size.is_some())
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user