aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorIvan Molodetskikh <yalterz@gmail.com>2024-06-09 10:41:07 +0300
committerIvan Molodetskikh <yalterz@gmail.com>2024-06-10 18:08:01 +0300
commita1563b9132c3ba49ed80dbb9011846ea0c825caf (patch)
tree86bb112d7600d212697b341bf09c93c91d09f3b7 /src
parent98aea9579f371e85577aa0b04c11eed15686fc6f (diff)
downloadniri-a1563b9132c3ba49ed80dbb9011846ea0c825caf.tar.gz
niri-a1563b9132c3ba49ed80dbb9011846ea0c825caf.tar.bz2
niri-a1563b9132c3ba49ed80dbb9011846ea0c825caf.zip
ui/config_error_notification: Make fractional-scaling aware
Diffstat (limited to 'src')
-rw-r--r--src/ui/config_error_notification.rs91
1 files changed, 40 insertions, 51 deletions
diff --git a/src/ui/config_error_notification.rs b/src/ui/config_error_notification.rs
index 1331b912..cdef5d6e 100644
--- a/src/ui/config_error_notification.rs
+++ b/src/ui/config_error_notification.rs
@@ -5,19 +5,20 @@ use std::rc::Rc;
use std::time::Duration;
use niri_config::Config;
+use ordered_float::NotNan;
use pangocairo::cairo::{self, ImageSurface};
use pangocairo::pango::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 smithay::utils::{Point, Transform};
use crate::animation::Animation;
+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 = "Failed to parse the config file. \
Please run <span face='monospace' bgcolor='#000000'>niri validate</span> \
@@ -28,7 +29,7 @@ const BORDER: i32 = 4;
pub struct ConfigErrorNotification {
state: State,
- buffers: RefCell<HashMap<i32, Option<MemoryRenderBuffer>>>,
+ buffers: RefCell<HashMap<NotNan<f64>, Option<MemoryBuffer>>>,
// If set, this is a "Created config at {path}" notification. If unset, this is a config error
// notification.
@@ -44,9 +45,6 @@ enum State {
Hiding(Animation),
}
-pub type ConfigErrorNotificationRenderElement<R> =
- RelocateRenderElement<MemoryRenderBufferRenderElement<R>>;
-
impl ConfigErrorNotification {
pub fn new(config: Rc<RefCell<Config>>) -> Self {
Self {
@@ -128,59 +126,54 @@ impl ConfigErrorNotification {
&self,
renderer: &mut R,
output: &Output,
- ) -> Option<ConfigErrorNotificationRenderElement<R>> {
+ ) -> Option<PrimaryGpuTextureRenderElement> {
if matches!(self.state, State::Hidden) {
return None;
}
- let scale = output.current_scale().integer_scale();
+ let scale = output.current_scale().fractional_scale();
+ let output_size = output_size(output);
let path = self.created_path.as_deref();
let mut buffers = self.buffers.borrow_mut();
let buffer = buffers
- .entry(scale)
- .or_insert_with_key(move |&scale| render(scale, path).ok());
+ .entry(NotNan::new(scale).unwrap())
+ .or_insert_with(move || render(scale, path).ok());
let buffer = buffer.as_ref()?;
- let elem = MemoryRenderBufferRenderElement::from_buffer(
- renderer,
- (0., 0.),
- buffer,
- Some(0.9),
- 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 size = buffer.logical_size();
+ let buffer = TextureBuffer::from_memory_buffer(renderer.as_gles_renderer(), buffer).ok()?;
- let buffer_size = elem
- .geometry(output.current_scale().fractional_scale().into())
- .size;
+ let y_range = size.h + f64::from(PADDING) * 2.;
- let y_range = buffer_size.h + PADDING * 2 * scale;
-
- let x = (output_size.w / 2 - buffer_size.w / 2).max(0);
+ let x = (f64::from(output_size.w) - size.w).max(0.) / 2.;
let y = match &self.state {
State::Hidden => unreachable!(),
- State::Showing(anim) | State::Hiding(anim) => {
- (-buffer_size.h as f64 + anim.value() * y_range as f64).round() as i32
- }
- State::Shown(_) => PADDING * 2 * scale,
+ State::Showing(anim) | State::Hiding(anim) => -size.h + anim.value() * y_range,
+ State::Shown(_) => f64::from(PADDING) * 2.,
};
- let elem = RelocateRenderElement::from_element(elem, (x, y), Relocate::Absolute);
- Some(elem)
+ let location = Point::from((x, y));
+ let location = location.to_physical_precise_round(scale).to_logical(scale);
+
+ let elem = TextureRenderElement::from_texture_buffer(
+ buffer,
+ location,
+ 1.,
+ None,
+ None,
+ Kind::Unspecified,
+ );
+ Some(PrimaryGpuTextureRenderElement(elem))
}
}
-fn render(scale: i32, created_path: Option<&Path>) -> anyhow::Result<MemoryRenderBuffer> {
+fn render(scale: f64, created_path: Option<&Path>) -> anyhow::Result<MemoryBuffer> {
let _span = tracy_client::span!("config_error_notification::render");
- let padding = PADDING * scale;
+ let apply_scale = |val: i32| (f64::from(val) * scale).round() as i32;
+
+ let padding = apply_scale(PADDING);
let mut text = String::from(TEXT);
let mut border_color = (1., 0.3, 0.3);
@@ -194,7 +187,7 @@ fn render(scale: i32, created_path: Option<&Path>) -> anyhow::Result<MemoryRende
};
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)?;
@@ -206,10 +199,6 @@ fn render(scale: i32, created_path: Option<&Path>) -> anyhow::Result<MemoryRende
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);
@@ -229,18 +218,18 @@ fn render(scale: i32, created_path: Option<&Path>) -> anyhow::Result<MemoryRende
cr.line_to(0., height.into());
cr.line_to(0., 0.);
cr.set_source_rgb(border_color.0, border_color.1, border_color.2);
- 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)