From bc2acdd060bf6a10fbe1fa87a0035bd7fa68c260 Mon Sep 17 00:00:00 2001 From: "Jeffrey C. Ollie" Date: Sun, 23 Feb 2025 10:59:59 -0600 Subject: [PATCH 1/3] gtk: ensure that the content scale is always positive Fixes #5927 This doesn't fix the underlying reason that GTK sometimes reports content scales as negative. If GTK reports a negative scale, we ignore that and use 1.0 for the scale. --- src/apprt/gtk/Surface.zig | 35 ++++++++++++++++++++++++----------- 1 file changed, 24 insertions(+), 11 deletions(-) diff --git a/src/apprt/gtk/Surface.zig b/src/apprt/gtk/Surface.zig index 3c94989c2..e25375d98 100644 --- a/src/apprt/gtk/Surface.zig +++ b/src/apprt/gtk/Surface.zig @@ -847,28 +847,41 @@ pub fn shouldClose(self: *const Surface) bool { } pub fn getContentScale(self: *const Surface) !apprt.ContentScale { - // Future: detect GTK version 4.12+ and use gdk_surface_get_scale so we - // can support fractional scaling. - const gtk_scale: f32 = @floatFromInt(c.gtk_widget_get_scale_factor(@ptrCast(self.gl_area))); + const gtk_scale: f32 = scale: { + const widget: *gtk.Widget = @ptrCast(@alignCast(self.gl_area)); + // Future: detect GTK version 4.12+ and use gdk_surface_get_scale so we + // can support fractional scaling. + const scale = widget.getScaleFactor(); + if (scale < 0) { + log.warn("gtk_widget_get_scale_factor returned a negative number: {d:.3}", .{scale}); + break :scale 1.0; + } + break :scale @floatFromInt(scale); + }; // Also scale using font-specific DPI, which is often exposed to the user // via DE accessibility settings (see https://docs.gtk.org/gtk4/class.Settings.html). const xft_dpi_scale = xft_scale: { // gtk-xft-dpi is font DPI multiplied by 1024. See // https://docs.gtk.org/gtk4/property.Settings.gtk-xft-dpi.html - const settings = c.gtk_settings_get_default(); + const settings = gtk.Settings.getDefault() orelse break :xft_scale 1.0; + var value = std.mem.zeroes(gobject.Value); + defer value.unset(); + _ = value.init(gobject.ext.typeFor(c_int)); + settings.as(gobject.Object).getProperty("gtk-xft-dpi", &value); + const gtk_xft_dpi = value.getInt(); - var value: c.GValue = std.mem.zeroes(c.GValue); - defer c.g_value_unset(&value); - _ = c.g_value_init(&value, c.G_TYPE_INT); - c.g_object_get_property(@ptrCast(@alignCast(settings)), "gtk-xft-dpi", &value); - const gtk_xft_dpi = c.g_value_get_int(&value); + // ensure that the scale is never negative + if (gtk_xft_dpi < 0) { + log.warn("gtk-xft-dpi setting was negative: {d:.3}", .{gtk_xft_dpi}); + break :xft_scale 1.0; + } // As noted above gtk-xft-dpi is multiplied by 1024, so we divide by // 1024, then divide by the default value (96) to derive a scale. Note // gtk-xft-dpi can be fractional, so we use floating point math here. - const xft_dpi: f32 = @as(f32, @floatFromInt(gtk_xft_dpi)) / 1024; - break :xft_scale xft_dpi / 96; + const xft_dpi: f32 = @as(f32, @floatFromInt(gtk_xft_dpi)) / 1024.0; + break :xft_scale xft_dpi / 96.0; }; const scale = gtk_scale * xft_dpi_scale; From ac7029256abb21cfeed93abd3d7507fd55a6dd2a Mon Sep 17 00:00:00 2001 From: "Jeffrey C. Ollie" Date: Sun, 23 Feb 2025 13:04:47 -0600 Subject: [PATCH 2/3] gtk: better document what to do if gtk-xft-dpi <= 0 --- src/apprt/gtk/Surface.zig | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/apprt/gtk/Surface.zig b/src/apprt/gtk/Surface.zig index e25375d98..3e5fa45f5 100644 --- a/src/apprt/gtk/Surface.zig +++ b/src/apprt/gtk/Surface.zig @@ -871,9 +871,12 @@ pub fn getContentScale(self: *const Surface) !apprt.ContentScale { settings.as(gobject.Object).getProperty("gtk-xft-dpi", &value); const gtk_xft_dpi = value.getInt(); - // ensure that the scale is never negative - if (gtk_xft_dpi < 0) { - log.warn("gtk-xft-dpi setting was negative: {d:.3}", .{gtk_xft_dpi}); + // Use a value of 1.0 for the XFT DPI scale if the setting is <= 0 + // See: + // https://gitlab.gnome.org/GNOME/libadwaita/-/commit/a7738a4d269bfdf4d8d5429ca73ccdd9b2450421 + // https://gitlab.gnome.org/GNOME/libadwaita/-/commit/9759d3fd81129608dd78116001928f2aed974ead + if (gtk_xft_dpi <= 0) { + log.warn("gtk-xft-dpi was not set, using default value", .{}); break :xft_scale 1.0; } From da10269d3f6d7f3a23ed1e695ff644942f8796d3 Mon Sep 17 00:00:00 2001 From: "Jeffrey C. Ollie" Date: Sun, 23 Feb 2025 13:18:00 -0600 Subject: [PATCH 3/3] gtk: handle other nonsensical values returned by gtk_widget_get_scale_factor --- src/apprt/gtk/Surface.zig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/apprt/gtk/Surface.zig b/src/apprt/gtk/Surface.zig index 3e5fa45f5..09d1c5a90 100644 --- a/src/apprt/gtk/Surface.zig +++ b/src/apprt/gtk/Surface.zig @@ -852,8 +852,8 @@ pub fn getContentScale(self: *const Surface) !apprt.ContentScale { // Future: detect GTK version 4.12+ and use gdk_surface_get_scale so we // can support fractional scaling. const scale = widget.getScaleFactor(); - if (scale < 0) { - log.warn("gtk_widget_get_scale_factor returned a negative number: {d:.3}", .{scale}); + if (scale <= 0) { + log.warn("gtk_widget_get_scale_factor returned a non-positive number: {}", .{scale}); break :scale 1.0; } break :scale @floatFromInt(scale);