From 8703bbbf19a1c013e3f3b014024fe06886859719 Mon Sep 17 00:00:00 2001 From: Mike Dilger Date: Mon, 16 Jan 2023 20:24:58 +1300 Subject: [PATCH] DPI work --- src/globals.rs | 5 ++++- src/main.rs | 4 ++-- src/people.rs | 7 ++++--- src/settings.rs | 17 ++++++++++++++++- src/ui/feed.rs | 7 +++++-- src/ui/mod.rs | 28 +++++++++++++++++++++++++++- src/ui/people/mod.rs | 7 +++++-- src/ui/settings.rs | 19 +++++++++++++++++++ 8 files changed, 82 insertions(+), 12 deletions(-) diff --git a/src/globals.rs b/src/globals.rs index 1a8dbba0..5ee7d4d4 100644 --- a/src/globals.rs +++ b/src/globals.rs @@ -10,7 +10,7 @@ use crate::signer::Signer; use nostr_types::{Event, Id, PublicKeyHex, Url}; use rusqlite::Connection; use std::collections::{HashMap, HashSet}; -use std::sync::atomic::AtomicBool; +use std::sync::atomic::{AtomicBool, AtomicU32}; use tokio::sync::{broadcast, mpsc, Mutex, RwLock}; /// Only one of these is ever created, via lazy_static!, and represents @@ -73,6 +73,8 @@ pub struct Globals { /// Failed Avatar Fetches pub failed_avatars: RwLock>, + pub pixels_per_point_times_100: AtomicU32, + /// UI status message pub status_message: RwLock, @@ -106,6 +108,7 @@ lazy_static! { feed: Feed::new(), fetcher: Fetcher::new(), failed_avatars: RwLock::new(HashSet::new()), + pixels_per_point_times_100: AtomicU32::new(139), // 100 dpi, 1/72th inch => 1.38888 status_message: RwLock::new("Welcome to Gossip. Status messages will appear here. Click them to dismiss them.".to_owned()), pull_following_merge: AtomicBool::new(true), } diff --git a/src/main.rs b/src/main.rs index 3ab21274..cd495211 100644 --- a/src/main.rs +++ b/src/main.rs @@ -28,8 +28,8 @@ use std::ops::DerefMut; use std::{env, mem, thread}; use tracing_subscriber::filter::EnvFilter; -pub const AVATAR_SIZE: u32 = 48; -pub const AVATAR_SIZE_F32: f32 = 48.0; +pub const AVATAR_SIZE: u32 = 64; // points, not pixels +pub const AVATAR_SIZE_F32: f32 = 64.0; // points, not pixels fn main() -> Result<(), Error> { if env::var("RUST_LOG").is_err() { diff --git a/src/people.rs b/src/people.rs index a0f4d97f..9b88a926 100644 --- a/src/people.rs +++ b/src/people.rs @@ -310,12 +310,13 @@ impl People { // Finish this later (spawn) let apubkeyhex = pubkeyhex.to_owned(); tokio::spawn(async move { + let size = AVATAR_SIZE * GLOBALS.pixels_per_point_times_100.load(std::sync::atomic::Ordering::Relaxed) / 100; if let Ok(image) = image::load_from_memory(&bytes) { // Note: we can't use egui_extras::image::load_image_bytes because we // need to force a resize let image = image.resize( - AVATAR_SIZE, - AVATAR_SIZE, + size, + size, image::imageops::FilterType::Nearest, ); // DynamicImage let image_buffer = image.into_rgba8(); // RgbaImage (ImageBuffer) @@ -326,7 +327,7 @@ impl People { GLOBALS.people.avatars_temp.insert(apubkeyhex, color_image); } else if let Ok(color_image) = egui_extras::image::load_svg_bytes_with_size( &bytes, - FitTo::Size(AVATAR_SIZE, AVATAR_SIZE), + FitTo::Size(size, size), ) { GLOBALS.people.avatars_temp.insert(apubkeyhex, color_image); } else { diff --git a/src/settings.rs b/src/settings.rs index a837a9f8..faefcdc3 100644 --- a/src/settings.rs +++ b/src/settings.rs @@ -15,6 +15,7 @@ pub const DEFAULT_POW: u8 = 0; pub const DEFAULT_OFFLINE: bool = false; pub const DEFAULT_LIGHT_MODE: bool = true; // true = light false = dark pub const DEFAULT_SET_CLIENT_TAG: bool = false; +pub const DEFAULT_OVERRIDE_DPI: Option = None; #[derive(Clone, Debug, Deserialize, Serialize)] pub struct Settings { @@ -32,6 +33,7 @@ pub struct Settings { pub offline: bool, pub light_mode: bool, pub set_client_tag: bool, + pub override_dpi: Option, } impl Default for Settings { @@ -51,6 +53,7 @@ impl Default for Settings { offline: DEFAULT_OFFLINE, light_mode: DEFAULT_LIGHT_MODE, set_client_tag: DEFAULT_SET_CLIENT_TAG, + override_dpi: DEFAULT_OVERRIDE_DPI, } } } @@ -107,6 +110,16 @@ impl Settings { "offline" => settings.offline = numstr_to_bool(row.1), "light_mode" => settings.light_mode = numstr_to_bool(row.1), "set_client_tag" => settings.set_client_tag = numstr_to_bool(row.1), + "override_dpi" => { + if row.1=="" { + settings.override_dpi = DEFAULT_OVERRIDE_DPI; + } else { + settings.override_dpi = match row.1.parse::() { + Ok(number) => Some(number), + _ => DEFAULT_OVERRIDE_DPI + }; + } + }, _ => {} } } @@ -139,7 +152,8 @@ impl Settings { ('pow', ?),\ ('offline', ?),\ ('light_mode', ?),\ - ('set_client_tag', ?)", + ('set_client_tag', ?),\ + ('override_dpi', ?)", )?; stmt.execute(( self.feed_chunk, @@ -154,6 +168,7 @@ impl Settings { bool_to_numstr(self.offline), bool_to_numstr(self.light_mode), bool_to_numstr(self.set_client_tag), + self.override_dpi, ))?; // Save private key identity diff --git a/src/ui/feed.rs b/src/ui/feed.rs index 5b41bce9..ffd27076 100644 --- a/src/ui/feed.rs +++ b/src/ui/feed.rs @@ -1,4 +1,5 @@ use super::{GossipUi, Page}; +use crate::AVATAR_SIZE_F32; use crate::comms::ToOverlordMessage; use crate::feed::FeedKind; use crate::globals::{Globals, GLOBALS}; @@ -10,6 +11,7 @@ use egui::{ }; use linkify::{LinkFinder, LinkKind}; use nostr_types::{Event, EventKind, Id, IdHex, Tag}; +use std::sync::atomic::Ordering; struct FeedPostParams { id: Id, @@ -442,13 +444,14 @@ fn render_post_actual( } else { app.placeholder_avatar.clone() }; + let size = AVATAR_SIZE_F32 * GLOBALS.pixels_per_point_times_100.load(Ordering::Relaxed) as f32 / 100.0; if ui .add( Image::new( &avatar, Vec2 { - x: crate::AVATAR_SIZE_F32, - y: crate::AVATAR_SIZE_F32, + x: size, + y: size, }, ) .sense(Sense::click()), diff --git a/src/ui/mod.rs b/src/ui/mod.rs index ebc038a9..fbf295dc 100644 --- a/src/ui/mod.rs +++ b/src/ui/mod.rs @@ -21,6 +21,7 @@ use egui::{ }; use nostr_types::{Id, IdHex, PublicKey, PublicKeyHex, Tag}; use std::collections::HashMap; +use std::sync::atomic::Ordering; use std::time::{Duration, Instant}; use zeroize::Zeroize; @@ -90,6 +91,8 @@ struct GossipUi { avatars: HashMap, new_relay_url: String, tag_re: regex::Regex, + override_dpi: bool, + override_dpi_value: u32, } impl Drop for GossipUi { @@ -100,9 +103,24 @@ impl Drop for GossipUi { impl GossipUi { fn new(cctx: &eframe::CreationContext<'_>) -> Self { - // grab settings to determine whether to render dark_mode or light_mode + let settings = GLOBALS.settings.blocking_read().clone(); + if let Some(dpi) = settings.override_dpi { + let ppt: f32 = dpi as f32 / 72.0; + cctx.egui_ctx.set_pixels_per_point(ppt); + } else if let Some(ppt) = cctx.integration_info.native_pixels_per_point { + cctx.egui_ctx.set_pixels_per_point(ppt); + } + + tracing::debug!("Pixels per point: {}", cctx.egui_ctx.pixels_per_point()); + + // Set global pixels_per_point_times_100, used for image scaling. + GLOBALS.pixels_per_point_times_100.store( + (cctx.egui_ctx.pixels_per_point() * 100.0) as u32, + Ordering::Relaxed + ); + if !settings.light_mode { cctx.egui_ctx.set_visuals(style::dark_mode_visuals()); } else { @@ -141,6 +159,12 @@ impl GossipUi { ) }; + let current_dpi = (cctx.egui_ctx.pixels_per_point() * 72.0) as u32; + let (override_dpi, override_dpi_value): (bool, u32) = match settings.override_dpi { + Some(v) => (true, v), + None => (false, current_dpi) + }; + GossipUi { next_frame: Instant::now(), page: Page::Feed(FeedKind::General), @@ -164,6 +188,8 @@ impl GossipUi { avatars: HashMap::new(), new_relay_url: "".to_owned(), tag_re: regex::Regex::new(r"(\#\[\d+\])").unwrap(), + override_dpi, + override_dpi_value, } } diff --git a/src/ui/people/mod.rs b/src/ui/people/mod.rs index 76aad4eb..38ce9d1f 100644 --- a/src/ui/people/mod.rs +++ b/src/ui/people/mod.rs @@ -1,9 +1,11 @@ use super::{GossipUi, Page}; +use crate::AVATAR_SIZE_F32; use crate::comms::ToOverlordMessage; use crate::db::DbPerson; use crate::globals::GLOBALS; use eframe::egui; use egui::{Context, Image, RichText, ScrollArea, Sense, Ui, Vec2}; +use std::sync::atomic::Ordering; mod follow; mod person; @@ -71,13 +73,14 @@ pub(super) fn update(app: &mut GossipUi, ctx: &Context, _frame: &mut eframe::Fra } else { app.placeholder_avatar.clone() }; + let size = AVATAR_SIZE_F32 * GLOBALS.pixels_per_point_times_100.load(Ordering::Relaxed) as f32 / 100.0; if ui .add( Image::new( &avatar, Vec2 { - x: crate::AVATAR_SIZE_F32, - y: crate::AVATAR_SIZE_F32, + x: size, + y: size, }, ) .sense(Sense::click()), diff --git a/src/ui/settings.rs b/src/ui/settings.rs index 0c1496ee..998aebbf 100644 --- a/src/ui/settings.rs +++ b/src/ui/settings.rs @@ -134,6 +134,25 @@ pub(super) fn update(app: &mut GossipUi, _ctx: &Context, _frame: &mut eframe::Fr } }); + ui.horizontal(|ui| { + ui.label("Override DPI: ") + .on_hover_text( + "On some systems, DPI is not reported properly. In other cases, people like to zoom in or out. This lets you.", + ); + ui.checkbox( + &mut app.override_dpi, + "Override to "); + ui.add(Slider::new(&mut app.override_dpi_value, 72..=250).text("DPI")); + + // set real setting if changed + app.settings.override_dpi = if app.override_dpi { + Some(app.override_dpi_value) + } else { + None + }; + }); + + ui.add_space(12.0); ui.horizontal(|ui| { ui.label("Maximum FPS: ")