diff --git a/Cargo.lock b/Cargo.lock index 883566598..66aee854b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -501,6 +501,12 @@ version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" +[[package]] +name = "atomic_float" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "628d228f918ac3b82fe590352cc719d30664a0c13ca3a60266fe02c7132d480a" + [[package]] name = "atspi" version = "0.19.0" @@ -2705,6 +2711,7 @@ dependencies = [ name = "komorebi-bar" version = "0.1.30" dependencies = [ + "atomic_float", "chrono", "clap", "color-eyre", diff --git a/komorebi-bar/Cargo.toml b/komorebi-bar/Cargo.toml index 802e79fc6..98a564fba 100644 --- a/komorebi-bar/Cargo.toml +++ b/komorebi-bar/Cargo.toml @@ -9,6 +9,7 @@ edition = "2021" komorebi-client = { path = "../komorebi-client" } komorebi-themes = { path = "../komorebi-themes" } +atomic_float = "1" chrono = { workspace = true } clap = { workspace = true } color-eyre = { workspace = true } diff --git a/komorebi-bar/src/bar.rs b/komorebi-bar/src/bar.rs index ee6e61bd9..d9c0a967c 100644 --- a/komorebi-bar/src/bar.rs +++ b/komorebi-bar/src/bar.rs @@ -4,6 +4,7 @@ use crate::komorebi::Komorebi; use crate::komorebi::KomorebiNotificationState; use crate::widget::BarWidget; use crate::widget::WidgetConfig; +use crate::DPI; use crate::MAX_LABEL_WIDTH; use crossbeam_channel::Receiver; use eframe::egui::Align; @@ -17,6 +18,7 @@ use eframe::egui::FontId; use eframe::egui::Frame; use eframe::egui::Layout; use eframe::egui::Margin; +use eframe::egui::Pos2; use eframe::egui::Style; use eframe::egui::TextStyle; use eframe::egui::Vec2; @@ -145,12 +147,14 @@ impl Komobar { } if let Some(viewport) = &config.viewport { - if let Some(inner_size) = viewport.inner_size { - let mut vec2 = Vec2::new(inner_size.x, inner_size.y * 2.0); - if self.scale_factor != 1.0 { - vec2 = Vec2::new(inner_size.x / self.scale_factor, inner_size.y * 2.0); - } + let dpi = DPI.load(Ordering::SeqCst); + if let Some(position) = viewport.position { + let pos2 = Pos2::new(position.x / dpi, position.y / dpi); + ctx.send_viewport_cmd(ViewportCommand::OuterPosition(pos2)); + } + if let Some(position) = viewport.inner_size { + let vec2 = Vec2::new(position.x / dpi, position.y / dpi); ctx.send_viewport_cmd(ViewportCommand::InnerSize(vec2)); } } diff --git a/komorebi-bar/src/main.rs b/komorebi-bar/src/main.rs index 6b350cf3d..7474a651f 100644 --- a/komorebi-bar/src/main.rs +++ b/komorebi-bar/src/main.rs @@ -14,7 +14,9 @@ mod widget; use crate::bar::Komobar; use crate::config::KomobarConfig; use crate::config::Position; +use atomic_float::AtomicF32; use clap::Parser; +use color_eyre::eyre::bail; use eframe::egui::ViewportBuilder; use font_loader::system_fonts; use hotwatch::EventKind; @@ -25,12 +27,16 @@ use std::io::BufReader; use std::io::Read; use std::path::PathBuf; use std::sync::atomic::AtomicI32; +use std::sync::atomic::Ordering; use std::sync::Arc; use std::time::Duration; use tracing_subscriber::EnvFilter; +use windows::Win32::UI::HiDpi::SetProcessDpiAwarenessContext; +use windows::Win32::UI::HiDpi::DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2; pub static WIDGET_SPACING: f32 = 10.0; pub static MAX_LABEL_WIDTH: AtomicI32 = AtomicI32::new(400); +pub static DPI: AtomicF32 = AtomicF32::new(1.0); #[derive(Parser)] #[clap(author, about, version)] @@ -49,7 +55,39 @@ struct Opts { quickstart: bool, } +macro_rules! as_ptr { + ($value:expr) => { + $value as *mut core::ffi::c_void + }; +} + +pub fn dpi_for_monitor(hmonitor: isize) -> color_eyre::Result { + use windows::Win32::Graphics::Gdi::HMONITOR; + use windows::Win32::UI::HiDpi::GetDpiForMonitor; + use windows::Win32::UI::HiDpi::MDT_EFFECTIVE_DPI; + + let mut dpi_x = u32::default(); + let mut dpi_y = u32::default(); + + unsafe { + match GetDpiForMonitor( + HMONITOR(as_ptr!(hmonitor)), + MDT_EFFECTIVE_DPI, + std::ptr::addr_of_mut!(dpi_x), + std::ptr::addr_of_mut!(dpi_y), + ) { + Ok(_) => {} + Err(error) => bail!(error), + } + } + + #[allow(clippy::cast_precision_loss)] + Ok(dpi_y as f32 / 96.0) +} + fn main() -> color_eyre::Result<()> { + unsafe { SetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2) }?; + let opts: Opts = Opts::parse(); if opts.schema { @@ -157,30 +195,39 @@ fn main() -> color_eyre::Result<()> { &SocketMessage::State, )?)?; + let dpi = dpi_for_monitor(state.monitors.elements()[config.monitor.index].id())?; + DPI.store(dpi, Ordering::SeqCst); + let mut viewport_builder = ViewportBuilder::default() .with_decorations(false) // .with_transparent(config.transparent) .with_taskbar(false) .with_position(Position { - x: state.monitors.elements()[config.monitor.index].size().left as f32, - y: state.monitors.elements()[config.monitor.index].size().top as f32, + x: state.monitors.elements()[config.monitor.index].size().left as f32 / dpi, + y: state.monitors.elements()[config.monitor.index].size().top as f32 / dpi, }) .with_inner_size({ Position { - x: state.monitors.elements()[config.monitor.index].size().right as f32, - y: 20.0, + x: state.monitors.elements()[config.monitor.index].size().right as f32 / dpi, + y: 50.0 / dpi, } }); if let Some(viewport) = &config.viewport { - if let Some(position) = &viewport.position { + if let Some(mut position) = &viewport.position { + position.x /= dpi; + position.y /= dpi; + let b = viewport_builder.clone(); - viewport_builder = b.with_position(*position); + viewport_builder = b.with_position(position); } - if let Some(inner_size) = &viewport.inner_size { + if let Some(mut inner_size) = &viewport.inner_size { + inner_size.x /= dpi; + inner_size.y /= dpi; + let b = viewport_builder.clone(); - viewport_builder = b.with_inner_size(*inner_size); + viewport_builder = b.with_inner_size(inner_size); } }