Skip to content

Commit

Permalink
Support HiDPI scaling
Browse files Browse the repository at this point in the history
  • Loading branch information
l4l committed Dec 25, 2020
1 parent aad94b1 commit 79cb8dd
Show file tree
Hide file tree
Showing 6 changed files with 74 additions and 11 deletions.
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ height = 512
font_size = 24
bg_color = 0x272822ee # ~~colors are specified in 0xRRGGBBAA format
# font_color = 0xf8f8f2ff
# HiDPI scaling factor; default is requested from compositor but
# fractional values are truncated, thus need to set it explicitly.
scale = 3

# ~~Block for input field
[input_text]
Expand Down
9 changes: 9 additions & 0 deletions src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ mod params;
pub struct Config {
width: Option<u32>,
height: Option<u32>,
scale: Option<u16>,
window_offsets: Option<(i32, i32)>,
term: Option<String>,
font: Option<String>,
Expand All @@ -30,6 +31,14 @@ impl Config {
pub fn disable_icons(&mut self) {
self.icon = None;
}

fn scale(&self) -> u16 {
self.scale.unwrap_or(1)
}

pub fn update_scale(&mut self, scale: u16) {
self.scale = Some(scale);
}
}

#[derive(Deserialize)]
Expand Down
26 changes: 17 additions & 9 deletions src/config/params.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,17 +29,20 @@ impl<'a> From<&'a Config> for InputTextParams {
font: select_conf!(config, input_text, font)
.map(font_by_name)
.unwrap_or_else(default_font),
font_size: select_conf!(config, input_text, font_size).unwrap_or(DEFAULT_FONT_SIZE),
font_size: select_conf!(config, input_text, font_size).unwrap_or(DEFAULT_FONT_SIZE)
* config.scale(),
bg_color: select_conf!(config, input_text, bg_color)
.map(u32_to_solid_source)
.unwrap_or_else(|| SolidSource::from_unpremultiplied_argb(0xc0, 0x75, 0x71, 0x5e)),
font_color: select_conf!(config, input_text, font_color)
.map(u32_to_solid_source)
.unwrap_or_else(default_font_color),
margin: select_conf!(noglob: config, input_text, margin)
.unwrap_or_else(|| Margin::all(5.0)),
.unwrap_or_else(|| Margin::all(5.0))
* f32::from(config.scale()),
padding: select_conf!(noglob: config, input_text, padding)
.unwrap_or_else(|| Padding::from_pair(1.7, -4.0)),
.unwrap_or_else(|| Padding::from_pair(1.7, -4.0))
* f32::from(config.scale()),
}
}
}
Expand All @@ -50,7 +53,8 @@ impl<'a> From<&'a Config> for ListParams {
font: select_conf!(config, list_items, font)
.map(font_by_name)
.unwrap_or_else(default_font),
font_size: select_conf!(config, list_items, font_size).unwrap_or(DEFAULT_FONT_SIZE),
font_size: select_conf!(config, list_items, font_size).unwrap_or(DEFAULT_FONT_SIZE)
* config.scale(),
font_color: select_conf!(config, list_items, font_color)
.map(u32_to_solid_source)
.unwrap_or_else(default_font_color),
Expand All @@ -63,15 +67,18 @@ impl<'a> From<&'a Config> for ListParams {
.icon
.as_ref()
.map(|c| c.size.unwrap_or(DEFAULT_ICON_SIZE))
.unwrap_or(0),
.unwrap_or(0)
* config.scale(),
fallback_icon: select_conf!(noglob: config, icon, fallback_icon_path)
.map(|path| Icon::load_icon(&path).expect("cannot load fallback icon")),
margin: select_conf!(noglob: config, list_items, margin).unwrap_or_else(|| Margin {
top: 10.0,
..Margin::from_pair(5.0, 15.0)
}),
item_spacing: select_conf!(noglob: config, list_items, item_spacing).unwrap_or(2.0),
icon_spacing: select_conf!(noglob: config, list_items, icon_spacing).unwrap_or(10.0),
}) * f32::from(config.scale()),
item_spacing: select_conf!(noglob: config, list_items, item_spacing).unwrap_or(2.0)
* f32::from(config.scale()),
icon_spacing: select_conf!(noglob: config, list_items, icon_spacing).unwrap_or(10.0)
* f32::from(config.scale()),
}
}
}
Expand All @@ -93,14 +100,15 @@ impl<'a> From<&'a Config> for SurfaceParams {
width: config.width.unwrap_or(400),
height: config.height.unwrap_or(512),
window_offsets: config.window_offsets,
scale: config.scale,
}
}
}

impl<'a> From<&'a Config> for Option<IconConfig> {
fn from(config: &'a Config) -> Option<IconConfig> {
config.icon.as_ref().map(|c| IconConfig {
icon_size: c.size.unwrap_or(DEFAULT_ICON_SIZE),
icon_size: c.size.unwrap_or(DEFAULT_ICON_SIZE) * config.scale(),
theme: c
.theme
.as_ref()
Expand Down
1 change: 1 addition & 0 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ fn main() {
let mut event_loop = calloop::EventLoop::<()>::new().unwrap();

let mut surface = surface::Surface::new(&env, config.param());
config.update_scale(surface.scale());

let (_input, key_stream) = input::InputHandler::new(&env, &event_loop);

Expand Down
27 changes: 27 additions & 0 deletions src/style.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use std::fmt::Display;
use std::marker::PhantomData;
use std::ops::Mul;
use std::str::FromStr;

use serde::de::{Deserializer, Visitor};
Expand Down Expand Up @@ -41,6 +42,19 @@ impl Padding {
}
}

impl Mul<f32> for Padding {
type Output = Self;

fn mul(self, rhs: f32) -> Self {
Self {
top: self.top * rhs,
bottom: self.bottom * rhs,
left: self.left * rhs,
right: self.right * rhs,
}
}
}

impl Margin {
pub const fn all(val: f32) -> Self {
Self {
Expand All @@ -61,6 +75,19 @@ impl Margin {
}
}

impl Mul<f32> for Margin {
type Output = Self;

fn mul(self, rhs: f32) -> Self {
Self {
top: self.top * rhs,
bottom: self.bottom * rhs,
left: self.left * rhs,
right: self.right * rhs,
}
}
}

impl<'de> Deserialize<'de> for Padding {
fn deserialize<D>(d: D) -> Result<Self, D::Error>
where
Expand Down
19 changes: 17 additions & 2 deletions src/surface.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use std::cell::Cell;
use std::convert::TryInto;
use std::rc::Rc;

use sctk::{
Expand All @@ -25,13 +26,15 @@ pub struct Params {
pub width: u32,
pub height: u32,
pub window_offsets: Option<(i32, i32)>,
pub scale: Option<u16>,
}

pub struct Surface {
surface: wl_surface::WlSurface,
layer_surface: Main<zwlr_layer_surface_v1::ZwlrLayerSurfaceV1>,
next_render_event: Rc<Cell<Option<RenderEvent>>>,
pools: DoubleMemPool,
scale: u16,
dimensions: (u32, u32),
}

Expand All @@ -51,6 +54,11 @@ impl Surface {
crate::prog_name!().to_owned(),
);

let scale = params.scale.unwrap_or_else(|| {
sctk::get_surface_scale_factor(&surface)
.try_into()
.expect("invalid surface scale factor")
});
let width = params.width;
let height = params.height;

Expand Down Expand Up @@ -88,16 +96,22 @@ impl Surface {

// Commit so that the server will send a configure event
surface.commit();
surface.set_buffer_scale(scale.into());

Self {
surface,
layer_surface,
next_render_event,
pools,
scale,
dimensions: (width, height),
}
}

pub fn scale(&self) -> u16 {
self.scale
}

/// Handles any events that have occurred since the last call, redrawing if needed.
/// Returns true if the surface should be dropped.
pub fn handle_events(&mut self) -> EventStatus {
Expand All @@ -121,8 +135,9 @@ impl Surface {
return;
};

let width = self.dimensions.0;
let height = self.dimensions.1;
let scale = u32::from(self.scale);
let width = self.dimensions.0 * scale;
let height = self.dimensions.1 * scale;

// First make sure the pool is the right size
pool.resize((4 * width * height) as usize).unwrap();
Expand Down

0 comments on commit 79cb8dd

Please sign in to comment.