diff options
| author | Ivan Molodetskikh <yalterz@gmail.com> | 2024-06-09 10:24:17 +0300 |
|---|---|---|
| committer | Ivan Molodetskikh <yalterz@gmail.com> | 2024-06-10 18:08:01 +0300 |
| commit | 98aea9579f371e85577aa0b04c11eed15686fc6f (patch) | |
| tree | c19c389d957c48e461c1e9a47d1e38ba2996f99e | |
| parent | 7019172b677d6332de53f24471dc2edbab30b2d4 (diff) | |
| download | niri-98aea9579f371e85577aa0b04c11eed15686fc6f.tar.gz niri-98aea9579f371e85577aa0b04c11eed15686fc6f.tar.bz2 niri-98aea9579f371e85577aa0b04c11eed15686fc6f.zip | |
ui/exit_confirm_dialog: Make fractional-scaling aware
| -rw-r--r-- | Cargo.lock | 10 | ||||
| -rw-r--r-- | Cargo.toml | 1 | ||||
| -rw-r--r-- | src/ui/exit_confirm_dialog.rs | 85 |
3 files changed, 51 insertions, 45 deletions
@@ -2185,6 +2185,7 @@ dependencies = [ "niri-config", "niri-ipc", "notify-rust", + "ordered-float", "pangocairo", "pipewire", "png", @@ -2410,6 +2411,15 @@ dependencies = [ ] [[package]] +name = "ordered-float" +version = "4.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a76df7075c7d4d01fdcb46c912dd17fba5b60c78ea480b475f2b6ab6f666584e" +dependencies = [ + "num-traits", +] + +[[package]] name = "ordered-stream" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -63,6 +63,7 @@ log = { version = "0.4.21", features = ["max_level_trace", "release_max_level_de niri-config = { version = "0.1.6", path = "niri-config" } niri-ipc = { version = "0.1.6", path = "niri-ipc", features = ["clap"] } notify-rust = { version = "~4.10.0", optional = true } +ordered-float = "4.2.0" pangocairo = "0.19.2" pipewire = { version = "0.8.0", optional = true } png = "0.17.13" diff --git a/src/ui/exit_confirm_dialog.rs b/src/ui/exit_confirm_dialog.rs index 84eddefe..d58df076 100644 --- a/src/ui/exit_confirm_dialog.rs +++ b/src/ui/exit_confirm_dialog.rs @@ -1,18 +1,19 @@ use std::cell::RefCell; use std::collections::HashMap; +use ordered_float::NotNan; use pangocairo::cairo::{self, ImageSurface}; use pangocairo::pango::{Alignment, FontDescription}; -use smithay::backend::renderer::element::memory::{ - MemoryRenderBuffer, MemoryRenderBufferRenderElement, -}; -use smithay::backend::renderer::element::utils::{Relocate, RelocateRenderElement}; -use smithay::backend::renderer::element::{Element, Kind}; +use smithay::backend::renderer::element::Kind; use smithay::output::Output; use smithay::reexports::gbm::Format as Fourcc; use smithay::utils::Transform; +use crate::render_helpers::memory::MemoryBuffer; +use crate::render_helpers::primary_gpu_texture::PrimaryGpuTextureRenderElement; use crate::render_helpers::renderer::NiriRenderer; +use crate::render_helpers::texture::{TextureBuffer, TextureRenderElement}; +use crate::utils::output_size; const TEXT: &str = "Are you sure you want to exit niri?\n\n\ Press <span face='mono' bgcolor='#2C2C2C'> Enter </span> to confirm."; @@ -22,17 +23,17 @@ const BORDER: i32 = 8; pub struct ExitConfirmDialog { is_open: bool, - buffers: RefCell<HashMap<i32, Option<MemoryRenderBuffer>>>, + buffers: RefCell<HashMap<NotNan<f64>, Option<MemoryBuffer>>>, } -pub type ExitConfirmDialogRenderElement<R> = - RelocateRenderElement<MemoryRenderBufferRenderElement<R>>; - impl ExitConfirmDialog { pub fn new() -> anyhow::Result<Self> { Ok(Self { is_open: false, - buffers: RefCell::new(HashMap::from([(1, Some(render(1)?))])), + buffers: RefCell::new(HashMap::from([( + NotNan::new(1.).unwrap(), + Some(render(1.)?), + )])), }) } @@ -62,52 +63,50 @@ impl ExitConfirmDialog { &self, renderer: &mut R, output: &Output, - ) -> Option<ExitConfirmDialogRenderElement<R>> { + ) -> Option<PrimaryGpuTextureRenderElement> { if !self.is_open { return None; } - let scale = output.current_scale().integer_scale(); + let scale = output.current_scale().fractional_scale(); + let output_size = output_size(output); let mut buffers = self.buffers.borrow_mut(); - let fallback = buffers[&1].clone().unwrap(); - let buffer = buffers.entry(scale).or_insert_with(|| render(scale).ok()); + let fallback = buffers[&NotNan::new(1.).unwrap()].clone().unwrap(); + let buffer = buffers + .entry(NotNan::new(scale).unwrap()) + .or_insert_with(|| render(scale).ok()); let buffer = buffer.as_ref().unwrap_or(&fallback); - let elem = MemoryRenderBufferRenderElement::from_buffer( - renderer, - (0., 0.), + let size = buffer.logical_size(); + let buffer = TextureBuffer::from_memory_buffer(renderer.as_gles_renderer(), buffer).ok()?; + + let location = (output_size.to_f64().to_point() - size.to_point()).downscale(2.); + let mut location = location.to_physical_precise_round(scale).to_logical(scale); + location.x = f64::max(0., location.x); + location.y = f64::max(0., location.y); + + let elem = TextureRenderElement::from_texture_buffer( buffer, - None, + location, + 1., None, None, Kind::Unspecified, - ) - .ok()?; - - let output_transform = output.current_transform(); - let output_mode = output.current_mode().unwrap(); - let output_size = output_transform.transform_size(output_mode.size); - - let buffer_size = elem - .geometry(output.current_scale().fractional_scale().into()) - .size; - - let x = (output_size.w / 2 - buffer_size.w / 2).max(0); - let y = (output_size.h / 2 - buffer_size.h / 2).max(0); - let elem = RelocateRenderElement::from_element(elem, (x, y), Relocate::Absolute); - - Some(elem) + ); + Some(PrimaryGpuTextureRenderElement(elem)) } } -fn render(scale: i32) -> anyhow::Result<MemoryRenderBuffer> { +fn render(scale: f64) -> anyhow::Result<MemoryBuffer> { let _span = tracy_client::span!("exit_confirm_dialog::render"); - let padding = PADDING * scale; + let apply_scale = |val: i32| (f64::from(val) * scale).round() as i32; + + let padding = apply_scale(PADDING); let mut font = FontDescription::from_string(FONT); - font.set_absolute_size((font.size() * scale).into()); + font.set_absolute_size(apply_scale(font.size()).into()); let surface = ImageSurface::create(cairo::Format::ARgb32, 0, 0)?; let cr = cairo::Context::new(&surface)?; @@ -120,10 +119,6 @@ fn render(scale: i32) -> anyhow::Result<MemoryRenderBuffer> { width += padding * 2; height += padding * 2; - // FIXME: fix bug in Smithay that rounds pixel sizes down to scale. - width = (width + scale - 1) / scale * scale; - height = (height + scale - 1) / scale * scale; - let surface = ImageSurface::create(cairo::Format::ARgb32, width, height)?; let cr = cairo::Context::new(&surface)?; cr.set_source_rgb(0.1, 0.1, 0.1); @@ -144,18 +139,18 @@ fn render(scale: i32) -> anyhow::Result<MemoryRenderBuffer> { cr.line_to(0., height.into()); cr.line_to(0., 0.); cr.set_source_rgb(1., 0.3, 0.3); - cr.set_line_width((BORDER * scale).into()); + // Keep the border width even to avoid blurry edges. + cr.set_line_width((f64::from(BORDER) / 2. * scale).round() * 2.); cr.stroke()?; drop(cr); let data = surface.take_data().unwrap(); - let buffer = MemoryRenderBuffer::from_slice( - &data, + let buffer = MemoryBuffer::new( + data.to_vec(), Fourcc::Argb8888, (width, height), scale, Transform::Normal, - None, ); Ok(buffer) |
