mirror of
https://github.com/niri-wm/niri.git
synced 2026-06-21 02:01:55 +07:00
Make LayoutElement more visual-geometry-based
This commit is contained in:
+76
-9
@@ -33,19 +33,23 @@ use std::mem;
|
||||
use std::rc::Rc;
|
||||
use std::time::Duration;
|
||||
|
||||
use smithay::backend::renderer::element::AsRenderElements;
|
||||
use smithay::backend::renderer::{ImportAll, Renderer};
|
||||
use smithay::desktop::space::SpaceElement;
|
||||
use smithay::desktop::Window;
|
||||
use smithay::output::Output;
|
||||
use smithay::reexports::wayland_protocols::xdg::decoration::zv1::server::zxdg_toplevel_decoration_v1;
|
||||
use smithay::reexports::wayland_protocols::xdg::shell::server::xdg_toplevel;
|
||||
use smithay::reexports::wayland_server::protocol::wl_surface::WlSurface;
|
||||
use smithay::utils::{Logical, Point, Rectangle, Size, Transform};
|
||||
use smithay::utils::{Logical, Point, Rectangle, Scale, Size, Transform};
|
||||
use smithay::wayland::compositor::{send_surface_state, with_states};
|
||||
use smithay::wayland::shell::xdg::SurfaceCachedState;
|
||||
|
||||
pub use self::monitor::MonitorRenderElement;
|
||||
use self::monitor::{Monitor, WorkspaceSwitch, WorkspaceSwitchGesture};
|
||||
use self::workspace::{compute_working_area, ColumnWidth, OutputId, Workspace};
|
||||
use self::workspace::{
|
||||
compute_working_area, ColumnWidth, OutputId, Workspace, WorkspaceRenderElement,
|
||||
};
|
||||
use crate::animation::Animation;
|
||||
use crate::config::{self, Config, SizeChange, Struts};
|
||||
use crate::utils::output_size;
|
||||
@@ -55,8 +59,35 @@ mod monitor;
|
||||
mod workspace;
|
||||
|
||||
pub trait LayoutElement: PartialEq {
|
||||
fn geometry(&self) -> Rectangle<i32, Logical>;
|
||||
/// Visual size of the element.
|
||||
///
|
||||
/// This is what the user would consider the size, i.e. excluding CSD shadows and whatnot.
|
||||
/// Corresponds to the Wayland window geometry size.
|
||||
fn size(&self) -> Size<i32, Logical>;
|
||||
|
||||
/// Returns the location of the element's buffer relative to the element's visual geometry.
|
||||
///
|
||||
/// I.e. if the element has CSD shadows, its buffer location will have negative coordinates.
|
||||
fn buf_loc(&self) -> Point<i32, Logical>;
|
||||
|
||||
/// Checks whether a point is in the element's input region.
|
||||
///
|
||||
/// The point is relative to the element's visual geometry.
|
||||
fn is_in_input_region(&self, point: Point<f64, Logical>) -> bool;
|
||||
|
||||
/// Renders the element at the given visual location.
|
||||
///
|
||||
/// The element should be rendered in such a way that its visual geometry ends up at the given
|
||||
/// location.
|
||||
fn render<R: Renderer + ImportAll>(
|
||||
&self,
|
||||
renderer: &mut R,
|
||||
location: Point<i32, Logical>,
|
||||
scale: Scale<f64>,
|
||||
) -> Vec<WorkspaceRenderElement<R>>
|
||||
where
|
||||
<R as Renderer>::TextureId: 'static;
|
||||
|
||||
fn request_size(&self, size: Size<i32, Logical>);
|
||||
fn request_fullscreen(&self, size: Size<i32, Logical>);
|
||||
fn min_size(&self) -> Size<i32, Logical>;
|
||||
@@ -156,12 +187,35 @@ impl Options {
|
||||
}
|
||||
|
||||
impl LayoutElement for Window {
|
||||
fn geometry(&self) -> Rectangle<i32, Logical> {
|
||||
SpaceElement::geometry(self)
|
||||
fn size(&self) -> Size<i32, Logical> {
|
||||
self.geometry().size
|
||||
}
|
||||
|
||||
fn buf_loc(&self) -> Point<i32, Logical> {
|
||||
Point::from((0, 0)) - self.geometry().loc
|
||||
}
|
||||
|
||||
fn is_in_input_region(&self, point: Point<f64, Logical>) -> bool {
|
||||
SpaceElement::is_in_input_region(self, &point)
|
||||
let surace_local = point + self.geometry().loc.to_f64();
|
||||
SpaceElement::is_in_input_region(self, &surace_local)
|
||||
}
|
||||
|
||||
fn render<R: Renderer + ImportAll>(
|
||||
&self,
|
||||
renderer: &mut R,
|
||||
location: Point<i32, Logical>,
|
||||
scale: Scale<f64>,
|
||||
) -> Vec<WorkspaceRenderElement<R>>
|
||||
where
|
||||
<R as Renderer>::TextureId: 'static,
|
||||
{
|
||||
let buf_pos = location - self.geometry().loc;
|
||||
self.render_elements(
|
||||
renderer,
|
||||
buf_pos.to_physical_precise_round(scale),
|
||||
scale,
|
||||
1.,
|
||||
)
|
||||
}
|
||||
|
||||
fn request_size(&self, size: Size<i32, Logical>) {
|
||||
@@ -394,7 +448,7 @@ impl<W: LayoutElement> Layout<W> {
|
||||
) -> Option<&Output> {
|
||||
let width = width
|
||||
.or(self.options.default_width)
|
||||
.unwrap_or_else(|| ColumnWidth::Fixed(window.geometry().size.w));
|
||||
.unwrap_or_else(|| ColumnWidth::Fixed(window.size().w));
|
||||
|
||||
match &mut self.monitor_set {
|
||||
MonitorSet::Normal {
|
||||
@@ -1356,14 +1410,27 @@ mod tests {
|
||||
}
|
||||
|
||||
impl LayoutElement for TestWindow {
|
||||
fn geometry(&self) -> Rectangle<i32, Logical> {
|
||||
self.0.bbox.get()
|
||||
fn size(&self) -> Size<i32, Logical> {
|
||||
self.0.bbox.get().size
|
||||
}
|
||||
|
||||
fn buf_loc(&self) -> Point<i32, Logical> {
|
||||
(0, 0).into()
|
||||
}
|
||||
|
||||
fn is_in_input_region(&self, _point: Point<f64, Logical>) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
fn render<R: Renderer + ImportAll>(
|
||||
&self,
|
||||
_renderer: &mut R,
|
||||
_location: Point<i32, Logical>,
|
||||
_scale: Scale<f64>,
|
||||
) -> Vec<WorkspaceRenderElement<R>> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
fn request_size(&self, size: Size<i32, Logical>) {
|
||||
self.0.requested_size.set(Some(size));
|
||||
}
|
||||
|
||||
+15
-35
@@ -4,7 +4,6 @@ use std::rc::Rc;
|
||||
use std::time::Duration;
|
||||
|
||||
use smithay::backend::renderer::element::surface::WaylandSurfaceRenderElement;
|
||||
use smithay::backend::renderer::element::AsRenderElements;
|
||||
use smithay::backend::renderer::gles::GlesRenderer;
|
||||
use smithay::backend::renderer::ImportAll;
|
||||
use smithay::desktop::space::SpaceElement;
|
||||
@@ -236,7 +235,7 @@ impl<W: LayoutElement> Workspace<W> {
|
||||
if !self.columns.is_empty() {
|
||||
let col = &self.columns[self.active_column_idx];
|
||||
let active_win = &col.windows[col.active_window_idx];
|
||||
let geom = active_win.geometry();
|
||||
let size = active_win.size();
|
||||
let has_ssd = active_win.has_ssd();
|
||||
|
||||
let win_pos = Point::from((
|
||||
@@ -244,7 +243,7 @@ impl<W: LayoutElement> Workspace<W> {
|
||||
col.window_y(col.active_window_idx),
|
||||
));
|
||||
|
||||
self.focus_ring.update(win_pos, geom.size, has_ssd);
|
||||
self.focus_ring.update(win_pos, size, has_ssd);
|
||||
self.focus_ring.set_active(is_active);
|
||||
}
|
||||
}
|
||||
@@ -742,13 +741,12 @@ impl<W: LayoutElement> Workspace<W> {
|
||||
// Prefer the active window since it's drawn on top.
|
||||
let col = &self.columns[self.active_column_idx];
|
||||
let active_win = &col.windows[col.active_window_idx];
|
||||
let geom = active_win.geometry();
|
||||
let buf_pos = Point::from((
|
||||
let win_pos = Point::from((
|
||||
self.column_x(self.active_column_idx) - view_pos,
|
||||
col.window_y(col.active_window_idx),
|
||||
)) - geom.loc;
|
||||
if active_win.is_in_input_region(pos - buf_pos.to_f64()) {
|
||||
return Some((active_win, buf_pos));
|
||||
));
|
||||
if active_win.is_in_input_region(pos - win_pos.to_f64()) {
|
||||
return Some((active_win, win_pos + active_win.buf_loc()));
|
||||
}
|
||||
|
||||
let mut x = -view_pos;
|
||||
@@ -759,10 +757,9 @@ impl<W: LayoutElement> Workspace<W> {
|
||||
continue;
|
||||
}
|
||||
|
||||
let geom = win.geometry();
|
||||
let buf_pos = Point::from((x, y)) - geom.loc;
|
||||
if win.is_in_input_region(pos - buf_pos.to_f64()) {
|
||||
return Some((win, buf_pos));
|
||||
let win_pos = Point::from((x, y));
|
||||
if win.is_in_input_region(pos - win_pos.to_f64()) {
|
||||
return Some((win, win_pos + win.buf_loc()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -917,14 +914,7 @@ impl Workspace<Window> {
|
||||
));
|
||||
|
||||
// Draw the window itself.
|
||||
let geom = active_win.geometry();
|
||||
let buf_pos = win_pos - geom.loc;
|
||||
rv.extend(active_win.render_elements(
|
||||
renderer,
|
||||
buf_pos.to_physical_precise_round(output_scale),
|
||||
output_scale,
|
||||
1.,
|
||||
));
|
||||
rv.extend(active_win.render(renderer, win_pos, output_scale));
|
||||
|
||||
// Draw the focus ring.
|
||||
rv.extend(self.focus_ring.render(output_scale).map(Into::into));
|
||||
@@ -937,14 +927,8 @@ impl Workspace<Window> {
|
||||
continue;
|
||||
}
|
||||
|
||||
let geom = win.geometry();
|
||||
let buf_pos = Point::from((x, y)) - geom.loc;
|
||||
rv.extend(win.render_elements(
|
||||
renderer,
|
||||
buf_pos.to_physical_precise_round(output_scale),
|
||||
output_scale,
|
||||
1.,
|
||||
));
|
||||
let win_pos = Point::from((x, y));
|
||||
rv.extend(win.render(renderer, win_pos, output_scale));
|
||||
}
|
||||
|
||||
x += col.width() + self.options.gaps;
|
||||
@@ -1189,11 +1173,7 @@ impl<W: LayoutElement> Column<W> {
|
||||
}
|
||||
|
||||
fn width(&self) -> i32 {
|
||||
self.windows
|
||||
.iter()
|
||||
.map(|win| win.geometry().size.w)
|
||||
.max()
|
||||
.unwrap()
|
||||
self.windows.iter().map(|win| win.size().w).max().unwrap()
|
||||
}
|
||||
|
||||
fn focus_up(&mut self) {
|
||||
@@ -1312,7 +1292,7 @@ impl<W: LayoutElement> Column<W> {
|
||||
fn set_window_height(&mut self, change: SizeChange) {
|
||||
let current = self.heights[self.active_window_idx];
|
||||
let current_px = match current {
|
||||
WindowHeight::Auto => self.windows[self.active_window_idx].geometry().size.h,
|
||||
WindowHeight::Auto => self.windows[self.active_window_idx].size().h,
|
||||
WindowHeight::Fixed(height) => height,
|
||||
};
|
||||
let current_prop = (current_px + self.options.gaps) as f64
|
||||
@@ -1372,7 +1352,7 @@ impl<W: LayoutElement> Column<W> {
|
||||
|
||||
self.windows.iter().map(move |win| {
|
||||
let pos = y;
|
||||
y += win.geometry().size.h + self.options.gaps;
|
||||
y += win.size().h + self.options.gaps;
|
||||
pos
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user