aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/layout/mod.rs28
-rw-r--r--src/layout/monitor.rs61
-rw-r--r--src/layout/workspace.rs6
3 files changed, 70 insertions, 25 deletions
diff --git a/src/layout/mod.rs b/src/layout/mod.rs
index d4de5693..ceed2f60 100644
--- a/src/layout/mod.rs
+++ b/src/layout/mod.rs
@@ -1432,19 +1432,12 @@ impl<W: LayoutElement> Layout<W> {
pub fn update_output_size(&mut self, output: &Output) {
let _span = tracy_client::span!("Layout::update_output_size");
- let MonitorSet::Normal { monitors, .. } = &mut self.monitor_set else {
- panic!()
+ let Some(mon) = self.monitor_for_output_mut(output) else {
+ error!("monitor missing in update_output_size()");
+ return;
};
- for mon in monitors {
- if &mon.output == output {
- for ws in &mut mon.workspaces {
- ws.update_output_size();
- }
-
- break;
- }
- }
+ mon.update_output_size();
}
pub fn scroll_amount_to_activate(&self, window: &W::Id) -> f64 {
@@ -2551,6 +2544,17 @@ impl<W: LayoutElement> Layout<W> {
assert_eq!(self.clock, workspace.clock);
assert_eq!(
+ monitor.scale().integer_scale(),
+ workspace.scale().integer_scale()
+ );
+ assert_eq!(
+ monitor.scale().fractional_scale(),
+ workspace.scale().fractional_scale()
+ );
+ assert_eq!(monitor.view_size(), workspace.view_size());
+ assert_eq!(monitor.working_area(), workspace.working_area());
+
+ assert_eq!(
workspace.base_options, self.options,
"workspace options must be synchronized with layout"
);
@@ -2602,7 +2606,7 @@ impl<W: LayoutElement> Layout<W> {
saw_view_offset_gesture = has_view_offset_gesture;
}
- let scale = monitor.output.current_scale().fractional_scale();
+ let scale = monitor.scale().fractional_scale();
let iter = monitor.workspaces_with_render_geo();
for (_ws, ws_geo) in iter {
let pos = ws_geo.loc;
diff --git a/src/layout/monitor.rs b/src/layout/monitor.rs
index 07e266be..06a01769 100644
--- a/src/layout/monitor.rs
+++ b/src/layout/monitor.rs
@@ -14,7 +14,8 @@ use super::insert_hint_element::{InsertHintElement, InsertHintRenderElement};
use super::scrolling::{Column, ColumnWidth};
use super::tile::Tile;
use super::workspace::{
- OutputId, Workspace, WorkspaceAddWindowTarget, WorkspaceId, WorkspaceRenderElement,
+ compute_working_area, OutputId, Workspace, WorkspaceAddWindowTarget, WorkspaceId,
+ WorkspaceRenderElement,
};
use super::{ActivateWindow, HitType, LayoutElement, Options};
use crate::animation::{Animation, Clock};
@@ -40,6 +41,17 @@ pub struct Monitor<W: LayoutElement> {
pub(super) output: Output,
/// Cached name of the output.
output_name: String,
+ /// Latest known scale for this output.
+ scale: smithay::output::Scale,
+ /// Latest known size for this output.
+ view_size: Size<f64, Logical>,
+ /// Latest known working area for this output.
+ ///
+ /// Not rounded to physical pixels.
+ // FIXME: since this is used for things like DnD scrolling edges in the overview, ideally this
+ // should only consider overlay and top layer-shell surfaces. However, Smithay doesn't easily
+ // let you do this at the moment.
+ working_area: Rectangle<f64, Logical>,
// Must always contain at least one.
pub(super) workspaces: Vec<Workspace<W>>,
/// Index of the currently active workspace.
@@ -182,9 +194,16 @@ impl<W: LayoutElement> Monitor<W> {
clock: Clock,
options: Rc<Options>,
) -> Self {
+ let scale = output.current_scale();
+ let view_size = output_size(&output);
+ let working_area = compute_working_area(&output);
+
Self {
output_name: output.name(),
output,
+ scale,
+ view_size,
+ working_area,
workspaces,
active_workspace_idx: 0,
previous_workspace_id: None,
@@ -795,6 +814,16 @@ impl<W: LayoutElement> Monitor<W> {
self.insert_hint_element.update_shaders();
}
+ pub fn update_output_size(&mut self) {
+ self.scale = self.output.current_scale();
+ self.view_size = output_size(&self.output);
+ self.working_area = compute_working_area(&self.output);
+
+ for ws in &mut self.workspaces {
+ ws.update_output_size();
+ }
+ }
+
pub fn move_workspace_down(&mut self) {
let mut new_idx = min(self.active_workspace_idx + 1, self.workspaces.len() - 1);
if new_idx == self.active_workspace_idx {
@@ -914,8 +943,8 @@ impl<W: LayoutElement> Monitor<W> {
}
pub fn workspaces_render_geo(&self) -> impl Iterator<Item = Rectangle<f64, Logical>> {
- let scale = self.output.current_scale().fractional_scale();
- let size = output_size(&self.output);
+ let scale = self.scale.fractional_scale();
+ let size = self.view_size;
// Ceil the workspace size in physical pixels.
let ws_size = size.to_physical_precise_ceil(scale).to_logical(scale);
@@ -933,8 +962,7 @@ impl<W: LayoutElement> Monitor<W> {
pub fn workspaces_with_render_geo(
&self,
) -> impl Iterator<Item = (&Workspace<W>, Rectangle<f64, Logical>)> {
- let output_size = output_size(&self.output);
- let output_geo = Rectangle::new(Point::from((0., 0.)), output_size);
+ let output_geo = Rectangle::from_size(self.view_size);
let geo = self.workspaces_render_geo();
zip(self.workspaces.iter(), geo)
@@ -945,8 +973,7 @@ impl<W: LayoutElement> Monitor<W> {
pub fn workspaces_with_render_geo_mut(
&mut self,
) -> impl Iterator<Item = (&mut Workspace<W>, Rectangle<f64, Logical>)> {
- let output_size = output_size(&self.output);
- let output_geo = Rectangle::new(Point::from((0., 0.)), output_size);
+ let output_geo = Rectangle::from_size(self.view_size);
let geo = self.workspaces_render_geo();
zip(self.workspaces.iter_mut(), geo)
@@ -958,11 +985,10 @@ impl<W: LayoutElement> Monitor<W> {
&self,
pos_within_output: Point<f64, Logical>,
) -> Option<(&Workspace<W>, Rectangle<f64, Logical>)> {
- let size = output_size(&self.output);
let (ws, geo) = self.workspaces_with_render_geo().find_map(|(ws, geo)| {
// Extend width to entire output.
let loc = Point::from((0., geo.loc.y));
- let size = Size::from((size.w, geo.size.h));
+ let size = Size::from((self.view_size.w, geo.size.h));
let bounds = Rectangle::new(loc, size);
bounds.contains(pos_within_output).then_some((ws, geo))
@@ -999,10 +1025,9 @@ impl<W: LayoutElement> Monitor<W> {
) -> impl Iterator<Item = MonitorRenderElement<R>> + 'a {
let _span = tracy_client::span!("Monitor::render_elements");
- let scale = self.output.current_scale().fractional_scale();
- let size = output_size(&self.output);
+ let scale = self.scale.fractional_scale();
// Ceil the height in physical pixels.
- let height = (size.h * scale).ceil() as i32;
+ let height = (self.view_size.h * scale).ceil() as i32;
// Crop the elements to prevent them overflowing, currently visible during a workspace
// switch.
@@ -1176,4 +1201,16 @@ impl<W: LayoutElement> Monitor<W> {
true
}
+
+ pub fn scale(&self) -> smithay::output::Scale {
+ self.scale
+ }
+
+ pub fn view_size(&self) -> Size<f64, Logical> {
+ self.view_size
+ }
+
+ pub fn working_area(&self) -> Rectangle<f64, Logical> {
+ self.working_area
+ }
}
diff --git a/src/layout/workspace.rs b/src/layout/workspace.rs
index 70d436c8..da04abed 100644
--- a/src/layout/workspace.rs
+++ b/src/layout/workspace.rs
@@ -1708,6 +1708,10 @@ impl<W: LayoutElement> Workspace<W> {
self.floating.logical_to_size_frac(logical_pos)
}
+ pub fn working_area(&self) -> Rectangle<f64, Logical> {
+ self.working_area
+ }
+
#[cfg(test)]
pub fn scrolling(&self) -> &ScrollingSpace<W> {
&self.scrolling
@@ -1777,6 +1781,6 @@ impl<W: LayoutElement> Workspace<W> {
}
}
-fn compute_working_area(output: &Output) -> Rectangle<f64, Logical> {
+pub(super) fn compute_working_area(output: &Output) -> Rectangle<f64, Logical> {
layer_map_for_output(output).non_exclusive_zone().to_f64()
}