mirror of
https://github.com/niri-wm/niri.git
synced 2026-06-23 02:05:33 +07:00
layout/monitor: Extract workspaces_render_geo()
This commit is contained in:
+29
-18
@@ -2601,6 +2601,17 @@ impl<W: LayoutElement> Layout<W> {
|
|||||||
}
|
}
|
||||||
saw_view_offset_gesture = has_view_offset_gesture;
|
saw_view_offset_gesture = has_view_offset_gesture;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let scale = monitor.output.current_scale().fractional_scale();
|
||||||
|
let iter = monitor.workspaces_with_render_geo();
|
||||||
|
for (_ws, ws_geo) in iter {
|
||||||
|
let pos = ws_geo.loc;
|
||||||
|
let rounded_pos = pos.to_physical_precise_round(scale).to_logical(scale);
|
||||||
|
|
||||||
|
// Workspace positions must be rounded to physical pixels.
|
||||||
|
assert_abs_diff_eq!(pos.x, rounded_pos.x, epsilon = 1e-5);
|
||||||
|
assert_abs_diff_eq!(pos.y, rounded_pos.y, epsilon = 1e-5);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2623,14 +2634,14 @@ impl<W: LayoutElement> Layout<W> {
|
|||||||
// Scroll the view if needed.
|
// Scroll the view if needed.
|
||||||
if let Some((output, pos_within_output)) = dnd_scroll {
|
if let Some((output, pos_within_output)) = dnd_scroll {
|
||||||
if let Some(mon) = self.monitor_for_output_mut(&output) {
|
if let Some(mon) = self.monitor_for_output_mut(&output) {
|
||||||
if let Some((ws, offset)) = mon.workspace_under(pos_within_output) {
|
if let Some((ws, geo)) = mon.workspace_under(pos_within_output) {
|
||||||
let ws_id = ws.id();
|
let ws_id = ws.id();
|
||||||
let ws = mon
|
let ws = mon
|
||||||
.workspaces
|
.workspaces
|
||||||
.iter_mut()
|
.iter_mut()
|
||||||
.find(|ws| ws.id() == ws_id)
|
.find(|ws| ws.id() == ws_id)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
ws.dnd_scroll_gesture_scroll(pos_within_output - offset);
|
ws.dnd_scroll_gesture_scroll(pos_within_output - geo.loc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2770,7 +2781,7 @@ impl<W: LayoutElement> Layout<W> {
|
|||||||
let _span = tracy_client::span!("Layout::update_insert_hint::update");
|
let _span = tracy_client::span!("Layout::update_insert_hint::update");
|
||||||
|
|
||||||
if let Some(mon) = self.monitor_for_output_mut(&move_.output) {
|
if let Some(mon) = self.monitor_for_output_mut(&move_.output) {
|
||||||
if let Some((ws, offset)) = mon.workspace_under(move_.pointer_pos_within_output) {
|
if let Some((ws, geo)) = mon.workspace_under(move_.pointer_pos_within_output) {
|
||||||
let ws_id = ws.id();
|
let ws_id = ws.id();
|
||||||
let ws = mon
|
let ws = mon
|
||||||
.workspaces
|
.workspaces
|
||||||
@@ -2778,7 +2789,7 @@ impl<W: LayoutElement> Layout<W> {
|
|||||||
.find(|ws| ws.id() == ws_id)
|
.find(|ws| ws.id() == ws_id)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let position = ws.get_insert_position(move_.pointer_pos_within_output - offset);
|
let position = ws.get_insert_position(move_.pointer_pos_within_output - geo.loc);
|
||||||
|
|
||||||
let rules = move_.tile.window().rules();
|
let rules = move_.tile.window().rules();
|
||||||
let border_width = move_.tile.effective_border_width().unwrap_or(0.);
|
let border_width = move_.tile.effective_border_width().unwrap_or(0.);
|
||||||
@@ -3661,8 +3672,8 @@ impl<W: LayoutElement> Layout<W> {
|
|||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
let Some((mon, (ws, ws_offset))) = monitors.iter().find_map(|mon| {
|
let Some((mon, (ws, ws_geo))) = monitors.iter().find_map(|mon| {
|
||||||
mon.workspaces_with_render_positions()
|
mon.workspaces_with_render_geo()
|
||||||
.find(|(ws, _)| ws.has_window(&window_id))
|
.find(|(ws, _)| ws.has_window(&window_id))
|
||||||
.map(|rv| (mon, rv))
|
.map(|rv| (mon, rv))
|
||||||
}) else {
|
}) else {
|
||||||
@@ -3680,7 +3691,7 @@ impl<W: LayoutElement> Layout<W> {
|
|||||||
.unwrap();
|
.unwrap();
|
||||||
let window_offset = tile.window_loc();
|
let window_offset = tile.window_loc();
|
||||||
|
|
||||||
let tile_pos = ws_offset + tile_offset;
|
let tile_pos = ws_geo.loc + tile_offset;
|
||||||
|
|
||||||
let pointer_offset_within_window = start_pos_within_output - tile_pos - window_offset;
|
let pointer_offset_within_window = start_pos_within_output - tile_pos - window_offset;
|
||||||
let window_size = tile.window_size();
|
let window_size = tile.window_size();
|
||||||
@@ -3776,8 +3787,8 @@ impl<W: LayoutElement> Layout<W> {
|
|||||||
// potentially animatable.
|
// potentially animatable.
|
||||||
let mut tile_pos = None;
|
let mut tile_pos = None;
|
||||||
if let MonitorSet::Normal { monitors, .. } = &self.monitor_set {
|
if let MonitorSet::Normal { monitors, .. } = &self.monitor_set {
|
||||||
if let Some((mon, (ws, ws_offset))) = monitors.iter().find_map(|mon| {
|
if let Some((mon, (ws, ws_geo))) = monitors.iter().find_map(|mon| {
|
||||||
mon.workspaces_with_render_positions()
|
mon.workspaces_with_render_geo()
|
||||||
.find(|(ws, _)| ws.has_window(window))
|
.find(|(ws, _)| ws.has_window(window))
|
||||||
.map(|rv| (mon, rv))
|
.map(|rv| (mon, rv))
|
||||||
}) {
|
}) {
|
||||||
@@ -3787,7 +3798,7 @@ impl<W: LayoutElement> Layout<W> {
|
|||||||
.find(|(tile, _, _)| tile.window().id() == window)
|
.find(|(tile, _, _)| tile.window().id() == window)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
tile_pos = Some(ws_offset + tile_offset);
|
tile_pos = Some(ws_geo.loc + tile_offset);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3979,12 +3990,12 @@ impl<W: LayoutElement> Layout<W> {
|
|||||||
let (mon, ws_idx, position, offset) = if let Some(mon) =
|
let (mon, ws_idx, position, offset) = if let Some(mon) =
|
||||||
monitors.iter_mut().find(|mon| mon.output == move_.output)
|
monitors.iter_mut().find(|mon| mon.output == move_.output)
|
||||||
{
|
{
|
||||||
let (ws, offset) = mon
|
let (ws, ws_geo) = mon
|
||||||
.workspace_under(move_.pointer_pos_within_output)
|
.workspace_under(move_.pointer_pos_within_output)
|
||||||
// If the pointer is somehow outside the move output and a workspace switch
|
// If the pointer is somehow outside the move output and a workspace switch
|
||||||
// is in progress, this won't necessarily do the expected thing, but also
|
// is in progress, this won't necessarily do the expected thing, but also
|
||||||
// that is not really supposed to happen so eh?
|
// that is not really supposed to happen so eh?
|
||||||
.unwrap_or_else(|| mon.workspaces_with_render_positions().next().unwrap());
|
.unwrap_or_else(|| mon.workspaces_with_render_geo().next().unwrap());
|
||||||
|
|
||||||
let ws_id = ws.id();
|
let ws_id = ws.id();
|
||||||
let ws_idx = mon
|
let ws_idx = mon
|
||||||
@@ -3997,14 +4008,14 @@ impl<W: LayoutElement> Layout<W> {
|
|||||||
InsertPosition::Floating
|
InsertPosition::Floating
|
||||||
} else {
|
} else {
|
||||||
let ws = &mut mon.workspaces[ws_idx];
|
let ws = &mut mon.workspaces[ws_idx];
|
||||||
ws.get_insert_position(move_.pointer_pos_within_output - offset)
|
ws.get_insert_position(move_.pointer_pos_within_output - ws_geo.loc)
|
||||||
};
|
};
|
||||||
|
|
||||||
(mon, ws_idx, position, offset)
|
(mon, ws_idx, position, ws_geo.loc)
|
||||||
} else {
|
} else {
|
||||||
let mon = &mut monitors[*active_monitor_idx];
|
let mon = &mut monitors[*active_monitor_idx];
|
||||||
// No point in trying to use the pointer position on the wrong output.
|
// No point in trying to use the pointer position on the wrong output.
|
||||||
let (ws, offset) = mon.workspaces_with_render_positions().next().unwrap();
|
let (ws, ws_geo) = mon.workspaces_with_render_geo().next().unwrap();
|
||||||
|
|
||||||
let position = if move_.is_floating {
|
let position = if move_.is_floating {
|
||||||
InsertPosition::Floating
|
InsertPosition::Floating
|
||||||
@@ -4018,7 +4029,7 @@ impl<W: LayoutElement> Layout<W> {
|
|||||||
.iter_mut()
|
.iter_mut()
|
||||||
.position(|ws| ws.id() == ws_id)
|
.position(|ws| ws.id() == ws_id)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
(mon, ws_idx, position, offset)
|
(mon, ws_idx, position, ws_geo.loc)
|
||||||
};
|
};
|
||||||
|
|
||||||
let win_id = move_.tile.window().id().clone();
|
let win_id = move_.tile.window().id().clone();
|
||||||
@@ -4435,7 +4446,7 @@ impl<W: LayoutElement> Layout<W> {
|
|||||||
let Some(mon) = self.monitor_for_output_mut(&output) else {
|
let Some(mon) = self.monitor_for_output_mut(&output) else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
let Some((ws, offset)) = mon.workspace_under(pointer_pos_within_output) else {
|
let Some((ws, ws_geo)) = mon.workspace_under(pointer_pos_within_output) else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
let ws_id = ws.id();
|
let ws_id = ws.id();
|
||||||
@@ -4445,7 +4456,7 @@ impl<W: LayoutElement> Layout<W> {
|
|||||||
.find(|ws| ws.id() == ws_id)
|
.find(|ws| ws.id() == ws_id)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let tile_pos = tile_pos - offset;
|
let tile_pos = tile_pos - ws_geo.loc;
|
||||||
ws.start_close_animation_for_tile(renderer, snapshot, tile_size, tile_pos, blocker);
|
ws.start_close_animation_for_tile(renderer, snapshot, tile_size, tile_pos, blocker);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
+63
-79
@@ -1,4 +1,5 @@
|
|||||||
use std::cmp::min;
|
use std::cmp::min;
|
||||||
|
use std::iter::zip;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
@@ -20,7 +21,7 @@ use crate::render_helpers::renderer::NiriRenderer;
|
|||||||
use crate::render_helpers::RenderTarget;
|
use crate::render_helpers::RenderTarget;
|
||||||
use crate::rubber_band::RubberBand;
|
use crate::rubber_band::RubberBand;
|
||||||
use crate::utils::transaction::Transaction;
|
use crate::utils::transaction::Transaction;
|
||||||
use crate::utils::{output_size, round_logical_in_physical, ResizeEdge};
|
use crate::utils::{output_size, ResizeEdge};
|
||||||
|
|
||||||
/// Amount of touchpad movement to scroll the height of one workspace.
|
/// Amount of touchpad movement to scroll the height of one workspace.
|
||||||
const WORKSPACE_GESTURE_MOVEMENT: f64 = 300.;
|
const WORKSPACE_GESTURE_MOVEMENT: f64 = 300.;
|
||||||
@@ -680,31 +681,8 @@ impl<W: LayoutElement> Monitor<W> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn update_render_elements(&mut self, is_active: bool) {
|
pub fn update_render_elements(&mut self, is_active: bool) {
|
||||||
match &self.workspace_switch {
|
for (ws, _) in self.workspaces_with_render_geo_mut() {
|
||||||
Some(switch) => {
|
ws.update_render_elements(is_active);
|
||||||
let render_idx = switch.current_idx();
|
|
||||||
let before_idx = render_idx.floor();
|
|
||||||
let after_idx = render_idx.ceil();
|
|
||||||
|
|
||||||
if after_idx < 0. || before_idx as usize >= self.workspaces.len() {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let after_idx = after_idx as usize;
|
|
||||||
if after_idx < self.workspaces.len() {
|
|
||||||
self.workspaces[after_idx].update_render_elements(is_active);
|
|
||||||
|
|
||||||
if before_idx < 0. {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let before_idx = before_idx as usize;
|
|
||||||
self.workspaces[before_idx].update_render_elements(is_active);
|
|
||||||
}
|
|
||||||
None => {
|
|
||||||
self.workspaces[self.active_workspace_idx].update_render_elements(is_active);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -855,72 +833,78 @@ impl<W: LayoutElement> Monitor<W> {
|
|||||||
Some(rect)
|
Some(rect)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn workspaces_with_render_positions(
|
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);
|
||||||
|
|
||||||
|
// Ceil the workspace size in physical pixels.
|
||||||
|
let ws_size = size.to_physical_precise_ceil(scale).to_logical(scale);
|
||||||
|
|
||||||
|
let render_idx = if let Some(switch) = &self.workspace_switch {
|
||||||
|
switch.current_idx()
|
||||||
|
} else {
|
||||||
|
self.active_workspace_idx as f64
|
||||||
|
};
|
||||||
|
|
||||||
|
let first_ws_y = -render_idx * ws_size.h;
|
||||||
|
|
||||||
|
(0..self.workspaces.len()).map(move |idx| {
|
||||||
|
let y = first_ws_y + idx as f64 * ws_size.h;
|
||||||
|
let loc = Point::from((0., y));
|
||||||
|
let loc = loc.to_physical_precise_round(scale).to_logical(scale);
|
||||||
|
Rectangle::new(loc, ws_size)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn workspaces_with_render_geo(
|
||||||
&self,
|
&self,
|
||||||
) -> impl Iterator<Item = (&Workspace<W>, Point<f64, Logical>)> {
|
) -> impl Iterator<Item = (&Workspace<W>, Rectangle<f64, Logical>)> {
|
||||||
let mut first = None;
|
let output_size = output_size(&self.output);
|
||||||
let mut second = None;
|
let output_geo = Rectangle::new(Point::from((0., 0.)), output_size);
|
||||||
|
|
||||||
match &self.workspace_switch {
|
let geo = self.workspaces_render_geo();
|
||||||
Some(switch) => {
|
zip(self.workspaces.iter(), geo)
|
||||||
let render_idx = switch.current_idx();
|
// Cull out workspaces outside the output.
|
||||||
let before_idx = render_idx.floor();
|
.filter(move |(_ws, geo)| geo.intersection(output_geo).is_some())
|
||||||
let after_idx = render_idx.ceil();
|
}
|
||||||
|
|
||||||
if after_idx >= 0. && before_idx < self.workspaces.len() as f64 {
|
pub fn workspaces_with_render_geo_mut(
|
||||||
let scale = self.output.current_scale().fractional_scale();
|
&mut self,
|
||||||
let size = output_size(&self.output);
|
) -> impl Iterator<Item = (&mut Workspace<W>, Rectangle<f64, Logical>)> {
|
||||||
let offset =
|
let output_size = output_size(&self.output);
|
||||||
round_logical_in_physical(scale, (render_idx - before_idx) * size.h);
|
let output_geo = Rectangle::new(Point::from((0., 0.)), output_size);
|
||||||
|
|
||||||
// Ceil the height in physical pixels.
|
let geo = self.workspaces_render_geo();
|
||||||
let height = (size.h * scale).ceil() / scale;
|
zip(self.workspaces.iter_mut(), geo)
|
||||||
|
// Cull out workspaces outside the output.
|
||||||
if before_idx >= 0. {
|
.filter(move |(_ws, geo)| geo.intersection(output_geo).is_some())
|
||||||
let before_idx = before_idx as usize;
|
|
||||||
let before_offset = Point::from((0., -offset));
|
|
||||||
first = Some((&self.workspaces[before_idx], before_offset));
|
|
||||||
}
|
|
||||||
|
|
||||||
let after_idx = after_idx as usize;
|
|
||||||
if after_idx < self.workspaces.len() {
|
|
||||||
let after_offset = Point::from((0., -offset + height));
|
|
||||||
second = Some((&self.workspaces[after_idx], after_offset));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
None => {
|
|
||||||
first = Some((
|
|
||||||
&self.workspaces[self.active_workspace_idx],
|
|
||||||
Point::from((0., 0.)),
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
first.into_iter().chain(second)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn workspace_under(
|
pub fn workspace_under(
|
||||||
&self,
|
&self,
|
||||||
pos_within_output: Point<f64, Logical>,
|
pos_within_output: Point<f64, Logical>,
|
||||||
) -> Option<(&Workspace<W>, Point<f64, Logical>)> {
|
) -> Option<(&Workspace<W>, Rectangle<f64, Logical>)> {
|
||||||
let size = output_size(&self.output);
|
let size = output_size(&self.output);
|
||||||
let (ws, bounds) = self
|
let (ws, geo) = self.workspaces_with_render_geo().find_map(|(ws, geo)| {
|
||||||
.workspaces_with_render_positions()
|
// Extend width to entire output.
|
||||||
.map(|(ws, offset)| (ws, Rectangle::new(offset, size)))
|
let loc = Point::from((0., geo.loc.y));
|
||||||
.find(|(_, bounds)| bounds.contains(pos_within_output))?;
|
let size = Size::from((size.w, geo.size.h));
|
||||||
Some((ws, bounds.loc))
|
let bounds = Rectangle::new(loc, size);
|
||||||
|
|
||||||
|
bounds.contains(pos_within_output).then_some((ws, geo))
|
||||||
|
})?;
|
||||||
|
Some((ws, geo))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn window_under(&self, pos_within_output: Point<f64, Logical>) -> Option<(&W, HitType)> {
|
pub fn window_under(&self, pos_within_output: Point<f64, Logical>) -> Option<(&W, HitType)> {
|
||||||
let (ws, offset) = self.workspace_under(pos_within_output)?;
|
let (ws, geo) = self.workspace_under(pos_within_output)?;
|
||||||
let (win, hit) = ws.window_under(pos_within_output - offset)?;
|
let (win, hit) = ws.window_under(pos_within_output - geo.loc)?;
|
||||||
Some((win, hit.offset_win_pos(offset)))
|
Some((win, hit.offset_win_pos(geo.loc)))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn resize_edges_under(&self, pos_within_output: Point<f64, Logical>) -> Option<ResizeEdge> {
|
pub fn resize_edges_under(&self, pos_within_output: Point<f64, Logical>) -> Option<ResizeEdge> {
|
||||||
let (ws, offset) = self.workspace_under(pos_within_output)?;
|
let (ws, geo) = self.workspace_under(pos_within_output)?;
|
||||||
ws.resize_edges_under(pos_within_output - offset)
|
ws.resize_edges_under(pos_within_output - geo.loc)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn render_above_top_layer(&self) -> bool {
|
pub fn render_above_top_layer(&self) -> bool {
|
||||||
@@ -968,8 +952,8 @@ impl<W: LayoutElement> Monitor<W> {
|
|||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
self.workspaces_with_render_positions()
|
self.workspaces_with_render_geo()
|
||||||
.flat_map(move |(ws, offset)| {
|
.flat_map(move |(ws, geo)| {
|
||||||
ws.render_elements(renderer, target, focus_ring)
|
ws.render_elements(renderer, target, focus_ring)
|
||||||
.filter_map(move |elem| {
|
.filter_map(move |elem| {
|
||||||
CropRenderElement::from_element(elem, scale, crop_bounds)
|
CropRenderElement::from_element(elem, scale, crop_bounds)
|
||||||
@@ -980,7 +964,7 @@ impl<W: LayoutElement> Monitor<W> {
|
|||||||
// The offset we get from workspaces_with_render_positions() is already
|
// The offset we get from workspaces_with_render_positions() is already
|
||||||
// rounded to physical pixels, but it's in the logical coordinate
|
// rounded to physical pixels, but it's in the logical coordinate
|
||||||
// space, so we need to convert it to physical.
|
// space, so we need to convert it to physical.
|
||||||
offset.to_physical_precise_round(scale),
|
geo.loc.to_physical_precise_round(scale),
|
||||||
Relocate::Relative,
|
Relocate::Relative,
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user