mirror of
https://github.com/YaLTeR/niri.git
synced 2024-09-11 12:35:58 +03:00
ui/exit_confirm_dialog: Make fractional-scaling aware
This commit is contained in:
parent
7019172b67
commit
98aea9579f
10
Cargo.lock
generated
10
Cargo.lock
generated
@ -2185,6 +2185,7 @@ dependencies = [
|
|||||||
"niri-config",
|
"niri-config",
|
||||||
"niri-ipc",
|
"niri-ipc",
|
||||||
"notify-rust",
|
"notify-rust",
|
||||||
|
"ordered-float",
|
||||||
"pangocairo",
|
"pangocairo",
|
||||||
"pipewire",
|
"pipewire",
|
||||||
"png",
|
"png",
|
||||||
@ -2409,6 +2410,15 @@ dependencies = [
|
|||||||
"libredox 0.0.2",
|
"libredox 0.0.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ordered-float"
|
||||||
|
version = "4.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a76df7075c7d4d01fdcb46c912dd17fba5b60c78ea480b475f2b6ab6f666584e"
|
||||||
|
dependencies = [
|
||||||
|
"num-traits",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ordered-stream"
|
name = "ordered-stream"
|
||||||
version = "0.2.0"
|
version = "0.2.0"
|
||||||
|
@ -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-config = { version = "0.1.6", path = "niri-config" }
|
||||||
niri-ipc = { version = "0.1.6", path = "niri-ipc", features = ["clap"] }
|
niri-ipc = { version = "0.1.6", path = "niri-ipc", features = ["clap"] }
|
||||||
notify-rust = { version = "~4.10.0", optional = true }
|
notify-rust = { version = "~4.10.0", optional = true }
|
||||||
|
ordered-float = "4.2.0"
|
||||||
pangocairo = "0.19.2"
|
pangocairo = "0.19.2"
|
||||||
pipewire = { version = "0.8.0", optional = true }
|
pipewire = { version = "0.8.0", optional = true }
|
||||||
png = "0.17.13"
|
png = "0.17.13"
|
||||||
|
@ -1,18 +1,19 @@
|
|||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
use ordered_float::NotNan;
|
||||||
use pangocairo::cairo::{self, ImageSurface};
|
use pangocairo::cairo::{self, ImageSurface};
|
||||||
use pangocairo::pango::{Alignment, FontDescription};
|
use pangocairo::pango::{Alignment, FontDescription};
|
||||||
use smithay::backend::renderer::element::memory::{
|
use smithay::backend::renderer::element::Kind;
|
||||||
MemoryRenderBuffer, MemoryRenderBufferRenderElement,
|
|
||||||
};
|
|
||||||
use smithay::backend::renderer::element::utils::{Relocate, RelocateRenderElement};
|
|
||||||
use smithay::backend::renderer::element::{Element, Kind};
|
|
||||||
use smithay::output::Output;
|
use smithay::output::Output;
|
||||||
use smithay::reexports::gbm::Format as Fourcc;
|
use smithay::reexports::gbm::Format as Fourcc;
|
||||||
use smithay::utils::Transform;
|
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::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\
|
const TEXT: &str = "Are you sure you want to exit niri?\n\n\
|
||||||
Press <span face='mono' bgcolor='#2C2C2C'> Enter </span> to confirm.";
|
Press <span face='mono' bgcolor='#2C2C2C'> Enter </span> to confirm.";
|
||||||
@ -22,17 +23,17 @@ const BORDER: i32 = 8;
|
|||||||
|
|
||||||
pub struct ExitConfirmDialog {
|
pub struct ExitConfirmDialog {
|
||||||
is_open: bool,
|
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 {
|
impl ExitConfirmDialog {
|
||||||
pub fn new() -> anyhow::Result<Self> {
|
pub fn new() -> anyhow::Result<Self> {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
is_open: false,
|
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,
|
&self,
|
||||||
renderer: &mut R,
|
renderer: &mut R,
|
||||||
output: &Output,
|
output: &Output,
|
||||||
) -> Option<ExitConfirmDialogRenderElement<R>> {
|
) -> Option<PrimaryGpuTextureRenderElement> {
|
||||||
if !self.is_open {
|
if !self.is_open {
|
||||||
return None;
|
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 mut buffers = self.buffers.borrow_mut();
|
||||||
let fallback = buffers[&1].clone().unwrap();
|
let fallback = buffers[&NotNan::new(1.).unwrap()].clone().unwrap();
|
||||||
let buffer = buffers.entry(scale).or_insert_with(|| render(scale).ok());
|
let buffer = buffers
|
||||||
|
.entry(NotNan::new(scale).unwrap())
|
||||||
|
.or_insert_with(|| render(scale).ok());
|
||||||
let buffer = buffer.as_ref().unwrap_or(&fallback);
|
let buffer = buffer.as_ref().unwrap_or(&fallback);
|
||||||
|
|
||||||
let elem = MemoryRenderBufferRenderElement::from_buffer(
|
let size = buffer.logical_size();
|
||||||
renderer,
|
let buffer = TextureBuffer::from_memory_buffer(renderer.as_gles_renderer(), buffer).ok()?;
|
||||||
(0., 0.),
|
|
||||||
|
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,
|
buffer,
|
||||||
None,
|
location,
|
||||||
|
1.,
|
||||||
None,
|
None,
|
||||||
None,
|
None,
|
||||||
Kind::Unspecified,
|
Kind::Unspecified,
|
||||||
)
|
);
|
||||||
.ok()?;
|
Some(PrimaryGpuTextureRenderElement(elem))
|
||||||
|
|
||||||
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)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render(scale: i32) -> anyhow::Result<MemoryRenderBuffer> {
|
fn render(scale: f64) -> anyhow::Result<MemoryBuffer> {
|
||||||
let _span = tracy_client::span!("exit_confirm_dialog::render");
|
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);
|
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 surface = ImageSurface::create(cairo::Format::ARgb32, 0, 0)?;
|
||||||
let cr = cairo::Context::new(&surface)?;
|
let cr = cairo::Context::new(&surface)?;
|
||||||
@ -120,10 +119,6 @@ fn render(scale: i32) -> anyhow::Result<MemoryRenderBuffer> {
|
|||||||
width += padding * 2;
|
width += padding * 2;
|
||||||
height += 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 surface = ImageSurface::create(cairo::Format::ARgb32, width, height)?;
|
||||||
let cr = cairo::Context::new(&surface)?;
|
let cr = cairo::Context::new(&surface)?;
|
||||||
cr.set_source_rgb(0.1, 0.1, 0.1);
|
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., height.into());
|
||||||
cr.line_to(0., 0.);
|
cr.line_to(0., 0.);
|
||||||
cr.set_source_rgb(1., 0.3, 0.3);
|
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()?;
|
cr.stroke()?;
|
||||||
drop(cr);
|
drop(cr);
|
||||||
|
|
||||||
let data = surface.take_data().unwrap();
|
let data = surface.take_data().unwrap();
|
||||||
let buffer = MemoryRenderBuffer::from_slice(
|
let buffer = MemoryBuffer::new(
|
||||||
&data,
|
data.to_vec(),
|
||||||
Fourcc::Argb8888,
|
Fourcc::Argb8888,
|
||||||
(width, height),
|
(width, height),
|
||||||
scale,
|
scale,
|
||||||
Transform::Normal,
|
Transform::Normal,
|
||||||
None,
|
|
||||||
);
|
);
|
||||||
|
|
||||||
Ok(buffer)
|
Ok(buffer)
|
||||||
|
Loading…
Reference in New Issue
Block a user