diff --git a/src/apprt/gtk/Surface.zig b/src/apprt/gtk/Surface.zig index 37c5155f0..90df1ff35 100644 --- a/src/apprt/gtk/Surface.zig +++ b/src/apprt/gtk/Surface.zig @@ -20,6 +20,7 @@ const ClipboardConfirmationWindow = @import("ClipboardConfirmationWindow.zig"); const inspector = @import("inspector.zig"); const gtk_key = @import("key.zig"); const c = @import("c.zig"); +const x11 = @import("x11.zig"); const log = std.log.scoped(.gtk_surface); @@ -660,8 +661,28 @@ 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 scale = c.gtk_widget_get_scale_factor(@ptrCast(self.gl_area)); - return .{ .x = @floatFromInt(scale), .y = @floatFromInt(scale) }; + const gtk_scale: f32 = @floatFromInt(c.gtk_widget_get_scale_factor(@ptrCast(self.gl_area))); + + // If we are on X11, we also have to scale using Xft.dpi + const xft_dpi_scale = if (!x11.is_current_display_server()) 1.0 else xft_scale: { + // Here we use GTK to retrieve gtk-xft-dpi, which is Xft.dpi multiplied + // by 1024. See https://docs.gtk.org/gtk4/property.Settings.gtk-xft-dpi.html + const settings = c.gtk_settings_get_default(); + + 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); + + // As noted above Xft.dpi is multiplied by 1024, so we divide by 1024, + // then divide by the default value of Xft.dpi (96) to derive a scale + const xft_dpi: f32 = @floatFromInt(@divExact(gtk_xft_dpi, 1024)); + break :xft_scale xft_dpi / 96; + }; + + const scale = gtk_scale * xft_dpi_scale; + return .{ .x = scale, .y = scale }; } pub fn getSize(self: *const Surface) !apprt.SurfaceSize { diff --git a/src/apprt/gtk/x11.zig b/src/apprt/gtk/x11.zig index 8965a72e0..e2990c7ba 100644 --- a/src/apprt/gtk/x11.zig +++ b/src/apprt/gtk/x11.zig @@ -13,6 +13,12 @@ pub fn is_display(display: ?*c.GdkDisplay) bool { ) != 0; } +/// Returns true if the app is running on X11 +pub fn is_current_display_server() bool { + const display = c.gdk_display_get_default(); + return is_display(display); +} + pub const Xkb = struct { base_event_code: c_int, funcs: Funcs,