From 9cca79aa4a49fefc435a32a4a383d4364967dfc6 Mon Sep 17 00:00:00 2001 From: Joshua Yuen Date: Sat, 12 Sep 2026 16:48:54 -0400 Subject: [PATCH] Fix clock layout shift with tabular digits and fixed width --- modules/home/ags/app/style.scss | 1 + modules/home/ags/app/widget/Clock.tsx | 36 ++++++++++++++++++++++++++- 2 files changed, 36 insertions(+), 1 deletion(-) diff --git a/modules/home/ags/app/style.scss b/modules/home/ags/app/style.scss index a45d4aa..e73755b 100644 --- a/modules/home/ags/app/style.scss +++ b/modules/home/ags/app/style.scss @@ -77,6 +77,7 @@ $module-bg: transparentize($base02, 0.4); .clock { font-weight: bold; + font-feature-settings: "tnum"; } .clock icon { diff --git a/modules/home/ags/app/widget/Clock.tsx b/modules/home/ags/app/widget/Clock.tsx index 4074109..69615ed 100644 --- a/modules/home/ags/app/widget/Clock.tsx +++ b/modules/home/ags/app/widget/Clock.tsx @@ -1,4 +1,6 @@ import GLib from "gi://GLib" +import Pango from "gi://Pango" +import Gtk from "gi://Gtk?version=3.0" import { Variable, bind } from "astal" const time = Variable("").poll(1000, () => { @@ -7,11 +9,43 @@ const time = Variable("").poll(1000, () => { return `${now.format("%a, %d %b")}, ${clock}` }) +// widest possible tick: days 1-7 always cover every weekday, sampled across +// all months with a double-digit hour in both meridiems; measured once at +// realize with the label's own font (tnum forced on) so the fixed +// widthRequest stops the bar from shifting every minute +function widestTick(self: Gtk.Label): number { + const layout = self.create_pango_layout("") + const attrs = new Pango.AttrList() + attrs.insert(Pango.attr_font_features_new("tnum")) + layout.set_attributes(attrs) + + let widest = 0 + for (let month = 1; month <= 12; month++) { + for (let day = 1; day <= 7; day++) { + for (const hour of [10, 22]) { + const d = GLib.DateTime.new_local(2026, month, day, hour, 0, 0) + const tick = + `${d.format("%a, %d %b")}, ${d.format("%I:%M %p")!.replace(/^0/, "")}` + layout.set_text(tick, -1) + const [w] = layout.get_pixel_size() + widest = Math.max(widest, w) + } + } + } + return Math.ceil(widest) + 2 +} + export default function Clock() { return ( - ) }