fix(ui): sharpen Windows launcher rendering

Present Windows DX12 through DirectComposition while retaining the presentation-system override and existing graphics selection.

Use whole-pixel glyph placement for the bundled fonts and inset the card hover rule within its hairlines.

Refs #339.
This commit is contained in:
Skyfuller authored and GitHub committed 2026-10-13 17:18:31 -06:00
1 parent cbae640688
commit 1579aa8c02
3 files changed
+15 -4

No files matched your search

+8 -1
View File
@@ -161,12 +161,19 @@ fn native_options(hidden: bool) -> eframe::NativeOptions {
/// Adrenalin installer leaves the integrated GPU on the OEM driver) it crashes inside
/// `amdvlk64.dll` before the first frame. `WGPU_BACKEND` still overrides the default, and then
/// wgpu picks the adapter itself. Direct3D 12 shaders compile with FXC ([`pin_dx12_compiler`]).
///
/// Direct3D 12 presents through DirectComposition rather than straight to the window. The
/// borderless window's drop shadow moves its client area down a pixel, and a swapchain made from
/// the window is then stretched over it vertically by the compositor, blurring every horizontal
/// edge and line of text. `WGPU_DX12_PRESENTATION_SYSTEM` still overrides it.
#[cfg(windows)]
fn wgpu_options() -> eframe::WgpuConfiguration {
use eframe::wgpu::{Backends, Dx12Compiler, PowerPreference};
use eframe::wgpu::{Backends, Dx12Compiler, Dx12SwapchainKind, PowerPreference};
let mut config = eframe::WgpuConfiguration::default();
pin_dx12_compiler(&mut config, Dx12Compiler::from_env());
if let eframe::egui_wgpu::WgpuSetup::CreateNew(setup) = &mut config.wgpu_setup {
setup.instance_descriptor.backend_options.dx12.presentation_system =
Dx12SwapchainKind::from_env().unwrap_or(Dx12SwapchainKind::DxgiFromVisual);
if let Some(backends) = Backends::from_env() {
setup.instance_descriptor.backends = backends;
} else {
+3 -1
View File
@@ -287,7 +287,9 @@ pub fn install_fonts(ctx: &egui::Context, cjk: Option<Lang>) {
("GeistMono-Bold", GEIST_MONO, &[(*b"wght", 700.0)], mono_bold()),
];
for (name, bytes, coords, family) in faces {
let tweak = FontTweak { coords: VariationCoords::new(coords.iter().copied()), ..Default::default() };
// No subpixel binning: these fonts carry no hinting instructions, so a glyph drawn at a
// fractional x smears each stem across two pixels, leaving small text blurry at 100 %.
let tweak = FontTweak { coords: VariationCoords::new(coords.iter().copied()), subpixel_binning: Some(false), ..Default::default() };
fonts.font_data.insert(name.to_owned(), Arc::new(FontData::from_static(bytes).tweak(tweak)));
let mut stack = vec![name.to_owned()];
stack.extend(fallback.iter().cloned());
+4 -2
View File
@@ -411,9 +411,11 @@ impl LauncherUi {
// A faint wash in the app's colour fades in under the pointer.
let fill = t.bg.lerp_to_gamma(app_color, 0.05 * lift);
painter.rect(rect, CornerRadius::ZERO, fill, t.hairline(), egui::StrokeKind::Inside);
// On hover, a 2 px rule in the app's colour wipes in from the left along the top.
// On hover, a 2 px rule in the app's colour wipes in from the left along the top, inside the
// hairlines the card shares with its neighbours (the site's rule sits within its grid gaps).
if lift > 0.0 {
painter.rect_filled(Rect::from_min_size(rect.min, vec2(rect.width() * lift, 2.0)), CornerRadius::ZERO, app_color);
let inside = rect.shrink(1.0);
painter.rect_filled(Rect::from_min_size(inside.min, vec2(inside.width() * lift, 2.0)), CornerRadius::ZERO, app_color);
}
// The top strip: the app's number in its colour, and its pages.