aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIvan Molodetskikh <yalterz@gmail.com>2024-06-17 09:16:28 +0300
committerIvan Molodetskikh <yalterz@gmail.com>2024-06-18 14:01:28 +0300
commit1dae45c58d7eabeda21ef490d712915890bf6cff (patch)
tree62c473ab1662a1161ed522517ea57b7bd8db340c
parent997119c44338ad96a40b4a1d6e958f77062a37ef (diff)
downloadniri-1dae45c58d7eabeda21ef490d712915890bf6cff.tar.gz
niri-1dae45c58d7eabeda21ef490d712915890bf6cff.tar.bz2
niri-1dae45c58d7eabeda21ef490d712915890bf6cff.zip
Refactor layout to fractional-logical
Lets borders, gaps, and everything else stay pixel-perfect even with fractional scale. Allows setting fractional border widths, gaps, struts. See the new wiki .md for more details.
-rw-r--r--Cargo.lock16
-rw-r--r--Cargo.toml1
-rw-r--r--niri-config/src/lib.rs114
-rw-r--r--niri-visual-tests/src/cases/gradient_angle.rs6
-rw-r--r--niri-visual-tests/src/cases/gradient_area.rs16
-rw-r--r--niri-visual-tests/src/cases/layout.rs4
-rw-r--r--niri-visual-tests/src/cases/tile.rs21
-rw-r--r--niri-visual-tests/src/cases/window.rs4
-rw-r--r--niri-visual-tests/src/test_window.rs22
-rw-r--r--src/handlers/xdg_shell.rs41
-rw-r--r--src/input/mod.rs8
-rw-r--r--src/input/resize_grab.rs4
-rw-r--r--src/input/view_offset_grab.rs4
-rw-r--r--src/layout/closing_window.rs25
-rw-r--r--src/layout/focus_ring.rs73
-rw-r--r--src/layout/mod.rs204
-rw-r--r--src/layout/monitor.rs56
-rw-r--r--src/layout/opening_window.rs18
-rw-r--r--src/layout/tile.rs221
-rw-r--r--src/layout/workspace.rs560
-rw-r--r--src/niri.rs39
-rw-r--r--src/render_helpers/border.rs20
-rw-r--r--src/render_helpers/clipped_surface.rs16
-rw-r--r--src/render_helpers/damage.rs8
-rw-r--r--src/render_helpers/mod.rs24
-rw-r--r--src/render_helpers/resize.rs16
-rw-r--r--src/render_helpers/shader_element.rs18
-rw-r--r--src/render_helpers/snapshot.rs6
-rw-r--r--src/render_helpers/surface.rs6
-rw-r--r--src/ui/config_error_notification.rs2
-rw-r--r--src/utils/mod.rs20
-rw-r--r--src/window/mapped.rs50
-rw-r--r--wiki/Configuration:-Layout.md24
-rw-r--r--wiki/Fractional-Layout.md34
-rw-r--r--wiki/_Sidebar.md1
35 files changed, 1050 insertions, 652 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 8026862b..54412c8c 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -144,6 +144,15 @@ dependencies = [
]
[[package]]
+name = "approx"
+version = "0.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cab112f0a86d568ea0e627cc1d6be74a1e9cd55214684db5561995f6dad897c6"
+dependencies = [
+ "num-traits",
+]
+
+[[package]]
name = "arrayvec"
version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -604,7 +613,7 @@ version = "0.18.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1a98d30140e3296250832bbaaff83b27dcd6fa3cc70fb6f1f3e5c9c0023b5317"
dependencies = [
- "approx",
+ "approx 0.4.0",
"num-traits",
]
@@ -2163,6 +2172,7 @@ name = "niri"
version = "0.1.6"
dependencies = [
"anyhow",
+ "approx 0.5.1",
"arrayvec",
"async-channel",
"async-io 1.13.0",
@@ -3162,7 +3172,7 @@ checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67"
[[package]]
name = "smithay"
version = "0.3.0"
-source = "git+https://github.com/Smithay/smithay.git#6169b213fb663d85d2e139d3bbe44dfae1ec9328"
+source = "git+https://github.com/Smithay/smithay.git#b4f8120be0fb9b7f038d041efa7f6549e26cd2bc"
dependencies = [
"appendlist",
"bitflags 2.5.0",
@@ -3234,7 +3244,7 @@ dependencies = [
[[package]]
name = "smithay-drm-extras"
version = "0.1.0"
-source = "git+https://github.com/Smithay/smithay.git#6169b213fb663d85d2e139d3bbe44dfae1ec9328"
+source = "git+https://github.com/Smithay/smithay.git#b4f8120be0fb9b7f038d041efa7f6549e26cd2bc"
dependencies = [
"drm",
"edid-rs",
diff --git a/Cargo.toml b/Cargo.toml
index cb15c2cf..dd0f6e05 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -99,6 +99,7 @@ features = [
]
[dev-dependencies]
+approx = "0.5.1"
k9 = "0.12.0"
proptest = "1.4.0"
proptest-derive = "0.4.0"
diff --git a/niri-config/src/lib.rs b/niri-config/src/lib.rs
index 4fbb96e1..a9285fad 100644
--- a/niri-config/src/lib.rs
+++ b/niri-config/src/lib.rs
@@ -331,6 +331,10 @@ pub struct Position {
pub y: i32,
}
+// MIN and MAX generics are only used during parsing to check the value.
+#[derive(Debug, Default, Clone, Copy, PartialEq)]
+pub struct FloatOrInt<const MIN: i32, const MAX: i32>(pub f64);
+
#[derive(knuffel::Decode, Debug, Clone, PartialEq)]
pub struct Layout {
#[knuffel(child, default)]
@@ -344,7 +348,7 @@ pub struct Layout {
#[knuffel(child, unwrap(argument), default)]
pub center_focused_column: CenterFocusedColumn,
#[knuffel(child, unwrap(argument), default = Self::default().gaps)]
- pub gaps: u16,
+ pub gaps: FloatOrInt<0, 65535>,
#[knuffel(child, default)]
pub struts: Struts,
}
@@ -357,7 +361,7 @@ impl Default for Layout {
preset_column_widths: Default::default(),
default_column_width: Default::default(),
center_focused_column: Default::default(),
- gaps: 16,
+ gaps: FloatOrInt(16.),
struts: Default::default(),
}
}
@@ -374,7 +378,7 @@ pub struct FocusRing {
#[knuffel(child)]
pub off: bool,
#[knuffel(child, unwrap(argument), default = Self::default().width)]
- pub width: u16,
+ pub width: FloatOrInt<0, 65535>,
#[knuffel(child, default = Self::default().active_color)]
pub active_color: Color,
#[knuffel(child, default = Self::default().inactive_color)]
@@ -389,7 +393,7 @@ impl Default for FocusRing {
fn default() -> Self {
Self {
off: false,
- width: 4,
+ width: FloatOrInt(4.),
active_color: Color::new(127, 200, 255, 255),
inactive_color: Color::new(80, 80, 80, 255),
active_gradient: None,
@@ -422,7 +426,7 @@ pub struct Border {
#[knuffel(child)]
pub off: bool,
#[knuffel(child, unwrap(argument), default = Self::default().width)]
- pub width: u16,
+ pub width: FloatOrInt<0, 65535>,
#[knuffel(child, default = Self::default().active_color)]
pub active_color: Color,
#[knuffel(child, default = Self::default().inactive_color)]
@@ -437,7 +441,7 @@ impl Default for Border {
fn default() -> Self {
Self {
off: true,
- width: 4,
+ width: FloatOrInt(4.),
active_color: Color::new(255, 200, 127, 255),
inactive_color: Color::new(80, 80, 80, 255),
active_gradient: None,
@@ -519,16 +523,16 @@ pub enum PresetWidth {
#[derive(Debug, Clone, PartialEq)]
pub struct DefaultColumnWidth(pub Option<PresetWidth>);
-#[derive(knuffel::Decode, Debug, Default, Clone, Copy, PartialEq, Eq)]
+#[derive(knuffel::Decode, Debug, Default, Clone, Copy, PartialEq)]
pub struct Struts {
#[knuffel(child, unwrap(argument), default)]
- pub left: u16,
+ pub left: FloatOrInt<0, 65535>,
#[knuffel(child, unwrap(argument), default)]
- pub right: u16,
+ pub right: FloatOrInt<0, 65535>,
#[knuffel(child, unwrap(argument), default)]
- pub top: u16,
+ pub top: FloatOrInt<0, 65535>,
#[knuffel(child, unwrap(argument), default)]
- pub bottom: u16,
+ pub bottom: FloatOrInt<0, 65535>,
}
#[derive(knuffel::Decode, Debug, Default, Clone, Copy, PartialEq, Eq)]
@@ -863,7 +867,7 @@ pub struct BorderRule {
#[knuffel(child)]
pub on: bool,
#[knuffel(child, unwrap(argument))]
- pub width: Option<u16>,
+ pub width: Option<FloatOrInt<0, 65535>>,
#[knuffel(child)]
pub active_color: Option<Color>,
#[knuffel(child)]
@@ -1144,6 +1148,72 @@ impl<S: knuffel::traits::ErrorSpan> knuffel::DecodeScalar<S> for WorkspaceRefere
}
}
+impl<S: knuffel::traits::ErrorSpan, const MIN: i32, const MAX: i32> knuffel::DecodeScalar<S>
+ for FloatOrInt<MIN, MAX>
+{
+ fn type_check(
+ type_name: &Option<knuffel::span::Spanned<knuffel::ast::TypeName, S>>,
+ ctx: &mut knuffel::decode::Context<S>,
+ ) {
+ if let Some(type_name) = &type_name {
+ ctx.emit_error(DecodeError::unexpected(
+ type_name,
+ "type name",
+ "no type name expected for this node",
+ ));
+ }
+ }
+
+ fn raw_decode(
+ val: &knuffel::span::Spanned<knuffel::ast::Literal, S>,
+ ctx: &mut knuffel::decode::Context<S>,
+ ) -> Result<Self, DecodeError<S>> {
+ match &**val {
+ knuffel::ast::Literal::Int(ref value) => match value.try_into() {
+ Ok(v) => {
+ if (MIN..=MAX).contains(&v) {
+ Ok(FloatOrInt(f64::from(v)))
+ } else {
+ ctx.emit_error(DecodeError::conversion(
+ val,
+ format!("value must be between {MIN} and {MAX}"),
+ ));
+ Ok(FloatOrInt::default())
+ }
+ }
+ Err(e) => {
+ ctx.emit_error(DecodeError::conversion(val, e));
+ Ok(FloatOrInt::default())
+ }
+ },
+ knuffel::ast::Literal::Decimal(ref value) => match value.try_into() {
+ Ok(v) => {
+ if (f64::from(MIN)..=f64::from(MAX)).contains(&v) {
+ Ok(FloatOrInt(v))
+ } else {
+ ctx.emit_error(DecodeError::conversion(
+ val,
+ format!("value must be between {MIN} and {MAX}"),
+ ));
+ Ok(FloatOrInt::default())
+ }
+ }
+ Err(e) => {
+ ctx.emit_error(DecodeError::conversion(val, e));
+ Ok(FloatOrInt::default())
+ }
+ },
+ _ => {
+ ctx.emit_error(DecodeError::unsupported(
+ val,
+ "Unsupported value, only numbers are recognized",
+ ));
+ Ok(FloatOrInt::default())
+ }
+ }
+ }
+}
+
#[derive(knuffel::Decode, Debug, Default, PartialEq)]
pub struct DebugConfig {
#[knuffel(child, unwrap(argument))]
@@ -2483,7 +2553,7 @@ mod tests {
border {
on
- width 8
+ width 8.5
}
}
@@ -2579,7 +2649,7 @@ mod tests {
layout: Layout {
focus_ring: FocusRing {
off: false,
- width: 5,
+ width: FloatOrInt(5.),
active_color: Color {
r: 0,
g: 100,
@@ -2602,7 +2672,7 @@ mod tests {
},
border: Border {
off: false,
- width: 3,
+ width: FloatOrInt(3.),
active_color: Color {
r: 255,
g: 200,
@@ -2627,12 +2697,12 @@ mod tests {
default_column_width: Some(DefaultColumnWidth(Some(PresetWidth::Proportion(
0.25,
)))),
- gaps: 8,
+ gaps: FloatOrInt(8.),
struts: Struts {
- left: 1,
- right: 2,
- top: 3,
- bottom: 0,
+ left: FloatOrInt(1.),
+ right: FloatOrInt(2.),
+ top: FloatOrInt(3.),
+ bottom: FloatOrInt(0.),
},
center_focused_column: CenterFocusedColumn::OnOverflow,
},
@@ -2716,12 +2786,12 @@ mod tests {
open_fullscreen: Some(false),
focus_ring: BorderRule {
off: true,
- width: Some(3),
+ width: Some(FloatOrInt(3.)),
..Default::default()
},
border: BorderRule {
on: true,
- width: Some(8),
+ width: Some(FloatOrInt(8.5)),
..Default::default()
},
..Default::default()
diff --git a/niri-visual-tests/src/cases/gradient_angle.rs b/niri-visual-tests/src/cases/gradient_angle.rs
index f9871a93..203f31b1 100644
--- a/niri-visual-tests/src/cases/gradient_angle.rs
+++ b/niri-visual-tests/src/cases/gradient_angle.rs
@@ -59,15 +59,15 @@ impl TestCase for GradientAngle {
) -> Vec<Box<dyn RenderElement<GlesRenderer>>> {
let (a, b) = (size.w / 4, size.h / 4);
let size = (size.w - a * 2, size.h - b * 2);
- let area = Rectangle::from_loc_and_size((a, b), size);
+ let area = Rectangle::from_loc_and_size((a, b), size).to_f64();
[BorderRenderElement::new(
area.size,
- Rectangle::from_loc_and_size((0, 0), area.size),
+ Rectangle::from_loc_and_size((0., 0.), area.size),
[1., 0., 0., 1.],
[0., 1., 0., 1.],
self.angle - FRAC_PI_2,
- Rectangle::from_loc_and_size((0, 0), area.size),
+ Rectangle::from_loc_and_size((0., 0.), area.size),
0.,
CornerRadius::default(),
)
diff --git a/niri-visual-tests/src/cases/gradient_area.rs b/niri-visual-tests/src/cases/gradient_area.rs
index b6741575..e76820fd 100644
--- a/niri-visual-tests/src/cases/gradient_area.rs
+++ b/niri-visual-tests/src/cases/gradient_area.rs
@@ -5,10 +5,10 @@ use std::time::Duration;
use niri::animation::ANIMATION_SLOWDOWN;
use niri::layout::focus_ring::FocusRing;
use niri::render_helpers::border::BorderRenderElement;
-use niri_config::{Color, CornerRadius};
+use niri_config::{Color, CornerRadius, FloatOrInt};
use smithay::backend::renderer::element::RenderElement;
use smithay::backend::renderer::gles::GlesRenderer;
-use smithay::utils::{Logical, Physical, Point, Rectangle, Scale, Size};
+use smithay::utils::{Logical, Physical, Point, Rectangle, Size};
use super::TestCase;
@@ -22,7 +22,7 @@ impl GradientArea {
pub fn new(_size: Size<i32, Logical>) -> Self {
let border = FocusRing::new(niri_config::FocusRing {
off: false,
- width: 1,
+ width: FloatOrInt(1.),
active_color: Color::new(255, 255, 255, 128),
inactive_color: Color::default(),
active_gradient: None,
@@ -75,13 +75,14 @@ impl TestCase for GradientArea {
let (a, b) = (size.w / 4, size.h / 4);
let rect_size = (size.w - a * 2, size.h - b * 2);
- let area = Rectangle::from_loc_and_size((a, b), rect_size);
+ let area = Rectangle::from_loc_and_size((a, b), rect_size).to_f64();
let g_size = Size::from((
(size.w as f32 / 8. + size.w as f32 / 8. * 7. * f).round() as i32,
(size.h as f32 / 8. + size.h as f32 / 8. * 7. * f).round() as i32,
));
- let g_loc = ((size.w - g_size.w) / 2, (size.h - g_size.h) / 2);
+ let g_loc = Point::from(((size.w - g_size.w) / 2, (size.h - g_size.h) / 2)).to_f64();
+ let g_size = g_size.to_f64();
let mut g_area = Rectangle::from_loc_and_size(g_loc, g_size);
g_area.loc -= area.loc;
@@ -91,10 +92,11 @@ impl TestCase for GradientArea {
true,
Rectangle::default(),
CornerRadius::default(),
+ 1.,
);
rv.extend(
self.border
- .render(renderer, Point::from(g_loc), Scale::from(1.))
+ .render(renderer, g_loc)
.map(|elem| Box::new(elem) as _),
);
@@ -105,7 +107,7 @@ impl TestCase for GradientArea {
[1., 0., 0., 1.],
[0., 1., 0., 1.],
FRAC_PI_4,
- Rectangle::from_loc_and_size((0, 0), rect_size),
+ Rectangle::from_loc_and_size((0, 0), rect_size).to_f64(),
0.,
CornerRadius::default(),
)
diff --git a/niri-visual-tests/src/cases/layout.rs b/niri-visual-tests/src/cases/layout.rs
index d7872173..2e730dbe 100644
--- a/niri-visual-tests/src/cases/layout.rs
+++ b/niri-visual-tests/src/cases/layout.rs
@@ -5,7 +5,7 @@ use niri::layout::workspace::ColumnWidth;
use niri::layout::{LayoutElement as _, Options};
use niri::render_helpers::RenderTarget;
use niri::utils::get_monotonic_time;
-use niri_config::Color;
+use niri_config::{Color, FloatOrInt};
use smithay::backend::renderer::element::RenderElement;
use smithay::backend::renderer::gles::GlesRenderer;
use smithay::desktop::layer_map_for_output;
@@ -49,7 +49,7 @@ impl Layout {
},
border: niri_config::Border {
off: false,
- width: 4,
+ width: FloatOrInt(4.),
active_color: Color::new(255, 163, 72, 255),
inactive_color: Color::new(50, 50, 50, 255),
active_gradient: None,
diff --git a/niri-visual-tests/src/cases/tile.rs b/niri-visual-tests/src/cases/tile.rs
index 301fc19f..95261877 100644
--- a/niri-visual-tests/src/cases/tile.rs
+++ b/niri-visual-tests/src/cases/tile.rs
@@ -3,7 +3,7 @@ use std::time::Duration;
use niri::layout::Options;
use niri::render_helpers::RenderTarget;
-use niri_config::Color;
+use niri_config::{Color, FloatOrInt};
use smithay::backend::renderer::element::RenderElement;
use smithay::backend::renderer::gles::GlesRenderer;
use smithay::utils::{Logical, Physical, Point, Rectangle, Scale, Size};
@@ -20,7 +20,7 @@ impl Tile {
pub fn freeform(size: Size<i32, Logical>) -> Self {
let window = TestWindow::freeform(0);
let mut rv = Self::with_window(window);
- rv.tile.request_tile_size(size, false);
+ rv.tile.request_tile_size(size.to_f64(), false);
rv.window.communicate();
rv
}
@@ -28,7 +28,7 @@ impl Tile {
pub fn fixed_size(size: Size<i32, Logical>) -> Self {
let window = TestWindow::fixed_size(0);
let mut rv = Self::with_window(window);
- rv.tile.request_tile_size(size, false);
+ rv.tile.request_tile_size(size.to_f64(), false);
rv.window.communicate();
rv
}
@@ -37,7 +37,7 @@ impl Tile {
let window = TestWindow::fixed_size(0);
window.set_csd_shadow_width(64);
let mut rv = Self::with_window(window);
- rv.tile.request_tile_size(size, false);
+ rv.tile.request_tile_size(size.to_f64(), false);
rv.window.communicate();
rv
}
@@ -71,13 +71,13 @@ impl Tile {
},
border: niri_config::Border {
off: false,
- width: 32,
+ width: FloatOrInt(32.),
active_color: Color::new(255, 163, 72, 255),
..Default::default()
},
..Default::default()
};
- let tile = niri::layout::tile::Tile::new(window.clone(), Rc::new(options));
+ let tile = niri::layout::tile::Tile::new(window.clone(), 1., Rc::new(options));
Self { window, tile }
}
}
@@ -85,7 +85,7 @@ impl Tile {
impl TestCase for Tile {
fn resize(&mut self, width: i32, height: i32) {
self.tile
- .request_tile_size(Size::from((width, height)), false);
+ .request_tile_size(Size::from((width, height)).to_f64(), false);
self.window.communicate();
}
@@ -102,12 +102,13 @@ impl TestCase for Tile {
renderer: &mut GlesRenderer,
size: Size<i32, Physical>,
) -> Vec<Box<dyn RenderElement<GlesRenderer>>> {
- let tile_size = self.tile.tile_size().to_physical(1);
- let location = Point::from(((size.w - tile_size.w) / 2, (size.h - tile_size.h) / 2));
+ let size = size.to_f64();
+ let tile_size = self.tile.tile_size().to_physical(1.);
+ let location = Point::from((size.w - tile_size.w, size.h - tile_size.h)).downscale(2.);
self.tile.update(
true,
- Rectangle::from_loc_and_size((-location.x, -location.y), size.to_logical(1)),
+ Rectangle::from_loc_and_size((-location.x, -location.y), size.to_logical(1.)),
);
self.tile
.render(
diff --git a/niri-visual-tests/src/cases/window.rs b/niri-visual-tests/src/cases/window.rs
index f19ec5ba..be6150d4 100644
--- a/niri-visual-tests/src/cases/window.rs
+++ b/niri-visual-tests/src/cases/window.rs
@@ -47,7 +47,9 @@ impl TestCase for Window {
size: Size<i32, Physical>,
) -> Vec<Box<dyn RenderElement<GlesRenderer>>> {
let win_size = self.window.size().to_physical(1);
- let location = Point::from(((size.w - win_size.w) / 2, (size.h - win_size.h) / 2));
+ let location = Point::from((size.w - win_size.w, size.h - win_size.h))
+ .to_f64()
+ .downscale(2.);
self.window
.render(
diff --git a/niri-visual-tests/src/test_window.rs b/niri-visual-tests/src/test_window.rs
index 1ce770bd..dbba5192 100644
--- a/niri-visual-tests/src/test_window.rs
+++ b/niri-visual-tests/src/test_window.rs
@@ -6,9 +6,9 @@ use niri::layout::{
InteractiveResizeData, LayoutElement, LayoutElementRenderElement, LayoutElementRenderSnapshot,
};
use niri::render_helpers::renderer::NiriRenderer;
+use niri::render_helpers::solid_color::{SolidColorBuffer, SolidColorRenderElement};
use niri::render_helpers::{RenderTarget, SplitElements};
use niri::window::ResolvedWindowRules;
-use smithay::backend::renderer::element::solid::{SolidColorBuffer, SolidColorRenderElement};
use smithay::backend::renderer::element::{Id, Kind};
use smithay::output::{self, Output};
use smithay::reexports::wayland_server::protocol::wl_surface::WlSurface;
@@ -37,7 +37,7 @@ impl TestWindow {
let size = Size::from((100, 200));
let min_size = Size::from((0, 0));
let max_size = Size::from((0, 0));
- let buffer = SolidColorBuffer::new(size, [0.15, 0.64, 0.41, 1.]);
+ let buffer = SolidColorBuffer::new(size.to_f64(), [0.15, 0.64, 0.41, 1.]);
Self {
id,
@@ -49,7 +49,7 @@ impl TestWindow {
buffer,
pending_fullscreen: false,
csd_shadow_width: 0,
- csd_shadow_buffer: SolidColorBuffer::new((0, 0), [0., 0., 0., 0.3]),
+ csd_shadow_buffer: SolidColorBuffer::new((0., 0.), [0., 0., 0., 0.3]),
})),
}
}
@@ -112,14 +112,14 @@ impl TestWindow {
if inner.size != new_size {
inner.size = new_size;
- inner.buffer.resize(new_size);
+ inner.buffer.resize(new_size.to_f64());
rv = true;
}
let mut csd_shadow_size = new_size;
csd_shadow_size.w += inner.csd_shadow_width * 2;
csd_shadow_size.h += inner.csd_shadow_width * 2;
- inner.csd_shadow_buffer.resize(csd_shadow_size);
+ inner.csd_shadow_buffer.resize(csd_shadow_size.to_f64());
rv
}
@@ -147,8 +147,8 @@ impl LayoutElement for TestWindow {
fn render<R: NiriRenderer>(
&self,
_renderer: &mut R,
- location: Point<i32, Logical>,
- scale: Scale<f64>,
+ location: Point<f64, Logical>,
+ _scale: Scale<f64>,
alpha: f32,
_target: RenderTarget,
) -> SplitElements<LayoutElementRenderElement<R>> {
@@ -158,17 +158,15 @@ impl LayoutElement for TestWindow {
normal: vec![
SolidColorRenderElement::from_buffer(
&inner.buffer,
- location.to_physical_precise_round(scale),
- scale,
+ location,
alpha,
Kind::Unspecified,
)
.into(),
SolidColorRenderElement::from_buffer(
&inner.csd_shadow_buffer,
- (location - Point::from((inner.csd_shadow_width, inner.csd_shadow_width)))
- .to_physical_precise_round(scale),
- scale,
+ location
+ - Point::from((inner.csd_shadow_width, inner.csd_shadow_width)).to_f64(),
alpha,
Kind::Unspecified,
)
diff --git a/src/handlers/xdg_shell.rs b/src/handlers/xdg_shell.rs
index c1e29ea4..3e6234fa 100644
--- a/src/handlers/xdg_shell.rs
+++ b/src/handlers/xdg_shell.rs
@@ -788,9 +788,9 @@ impl State {
// window can be scrolled to both edges of the screen), but within the whole monitor's
// height.
let mut target =
- Rectangle::from_loc_and_size((0, 0), (window_geo.size.w, output_geo.size.h));
+ Rectangle::from_loc_and_size((0, 0), (window_geo.size.w, output_geo.size.h)).to_f64();
target.loc -= self.niri.layout.window_loc(window).unwrap();
- target.loc -= get_popup_toplevel_coords(popup);
+ target.loc -= get_popup_toplevel_coords(popup).to_f64();
self.position_popup_within_rect(popup, target);
}
@@ -813,10 +813,10 @@ impl State {
target.loc -= layer_geo.loc;
target.loc -= get_popup_toplevel_coords(popup);
- self.position_popup_within_rect(popup, target);
+ self.position_popup_within_rect(popup, target.to_f64());
}
- fn position_popup_within_rect(&self, popup: &PopupKind, target: Rectangle<i32, Logical>) {
+ fn position_popup_within_rect(&self, popup: &PopupKind, target: Rectangle<f64, Logical>) {
match popup {
PopupKind::Xdg(popup) => {
popup.with_pending_state(|state| {
@@ -826,28 +826,29 @@ impl State {
PopupKind::InputMethod(popup) => {
let text_input_rectangle = popup.text_input_rectangle();
let mut bbox =
- utils::bbox_from_surface_tree(popup.wl_surface(), text_input_rectangle.loc);
+ utils::bbox_from_surface_tree(popup.wl_surface(), text_input_rectangle.loc)
+ .to_f64();
// Position bbox horizontally first.
let overflow_x = (bbox.loc.x + bbox.size.w) - (target.loc.x + target.size.w);
- if overflow_x > 0 {
+ if overflow_x > 0. {
bbox.loc.x -= overflow_x;
}
// Ensure that the popup starts within the window.
- bbox.loc.x = bbox.loc.x.max(target.loc.x);
+ bbox.loc.x = f64::max(bbox.loc.x, target.loc.x);
// Try to position IME popup below the text input rectangle.
let mut below = bbox;
- below.loc.y += text_input_rectangle.size.h;
+ below.loc.y += f64::from(text_input_rectangle.size.h);
let mut above = bbox;
above.loc.y -= bbox.size.h;
if target.loc.y + target.size.h >= below.loc.y + below.size.h {
- popup.set_location(below.loc);
+ popup.set_location(below.loc.to_i32_round());
} else {
- popup.set_location(above.loc);
+ popup.set_location(above.loc.to_i32_round());
}
}
}
@@ -907,25 +908,25 @@ impl State {
fn unconstrain_with_padding(
positioner: PositionerState,
- target: Rectangle<i32, Logical>,
+ target: Rectangle<f64, Logical>,
) -> Rectangle<i32, Logical> {
// Try unconstraining with a small padding first which looks nicer, then if it doesn't fit try
// unconstraining without padding.
- const PADDING: i32 = 8;
+ const PADDING: f64 = 8.;
let mut padded = target;
- if PADDING * 2 < padded.size.w {
+ if PADDING * 2. < padded.size.w {
padded.loc.x += PADDING;
- padded.size.w -= PADDING * 2;
+ padded.size.w -= PADDING * 2.;
}
- if PADDING * 2 < padded.size.h {
+ if PADDING * 2. < padded.size.h {
padded.loc.y += PADDING;
- padded.size.h -= PADDING * 2;
+ padded.size.h -= PADDING * 2.;
}
// No padding, so just unconstrain with the original target.
if padded == target {
- return positioner.get_unconstrained_geometry(target);
+ return positioner.get_unconstrained_geometry(target.to_i32_round());
}
// Do not try to resize to fit the padded target rectangle.
@@ -937,13 +938,13 @@ fn unconstrain_with_padding(
.constraint_adjustment
.remove(ConstraintAdjustment::ResizeY);
- let geo = no_resize.get_unconstrained_geometry(padded);
- if padded.contains_rect(geo) {
+ let geo = no_resize.get_unconstrained_geometry(padded.to_i32_round());
+ if padded.contains_rect(geo.to_f64()) {
return geo;
}
// Could not unconstrain into the