Refactor primary paste settings handling and documentation for clarity

This commit is contained in:
evertonstz
2026-01-20 14:32:47 -03:00
parent bc067fc782
commit 8c9891b5de
2 changed files with 15 additions and 44 deletions

View File

@@ -675,8 +675,7 @@ pub const Surface = extern struct {
/// The context for this surface (window, tab, or split)
context: apprt.surface.NewSurfaceContext = .window,
/// Whether primary paste (middle-click paste) is enabled via GNOME settings.
/// If true, middle-click paste is enabled. If false, it's disabled.
/// Whether primary paste (middle-click paste) is enabled.
gtk_enable_primary_paste: bool = true,
pub var offset: c_int = 0;
@@ -1770,12 +1769,8 @@ pub const Surface = extern struct {
priv.im_composing = false;
priv.im_len = 0;
// Read GNOME desktop interface settings for primary paste (middle-click)
// This is only relevant on Linux systems with GNOME settings available
priv.gtk_enable_primary_paste = gsettings.get(.@"gtk-enable-primary-paste") orelse blk: {
log.warn("gtk-enable-primary-paste was not set, using default value", .{});
break :blk false;
};
// Read GTK primary paste setting
priv.gtk_enable_primary_paste = gsettings.get(.@"gtk-enable-primary-paste") orelse true;
// Set up to handle items being dropped on our surface. Files can be dropped
// from Nautilus and strings can be dropped from many programs. The order
@@ -2696,8 +2691,6 @@ pub const Surface = extern struct {
// Report the event
const button = translateMouseButton(gesture.as(gtk.GestureSingle).getCurrentButton());
// Check if middle button paste should be disabled based on GNOME settings
// If gtk_enable_primary_paste is explicitly false, skip processing middle button
if (button == .middle and !priv.gtk_enable_primary_paste) {
return;
}
@@ -2753,8 +2746,6 @@ pub const Surface = extern struct {
const gtk_mods = event.getModifierState();
const button = translateMouseButton(gesture.as(gtk.GestureSingle).getCurrentButton());
// Check if middle button paste should be disabled based on GNOME settings
// If gtk_enable_primary_paste is explicitly false, skip processing middle button
if (button == .middle and !priv.gtk_enable_primary_paste) {
return;
}

View File

@@ -18,16 +18,15 @@ pub const Key = enum {
fn GValueType(comptime self: Key) type {
return switch (self.Type()) {
bool => c_int, // Booleans are stored as integers in GTK's internal representation
bool => c_int,
c_int => c_int,
[]const u8 => ?[*:0]const u8, // Strings (returned as null-terminated C strings from GTK)
[]const u8 => ?[*:0]const u8,
else => @compileError("Unsupported type for GTK settings"),
};
}
/// Returns true if this setting type requires memory allocation.
/// this is defensive: types that do not need allocation need to be
/// explicitly marked here
/// Types that do not need allocation must be explicitly marked.
fn requiresAllocation(comptime self: Key) bool {
const T = self.Type();
return switch (T) {
@@ -37,14 +36,9 @@ pub const Key = enum {
}
};
/// Reads a GTK setting using the GTK Settings API for non-allocating types.
/// This automatically uses XDG Desktop Portal in Flatpak environments.
///
/// No allocator is required or used. Returns null if the setting is not available or cannot be read.
///
/// Example usage:
/// const enabled = get(.@"gtk-enable-primary-paste");
/// const dpi = get(.@"gtk-xft-dpi");
/// Reads a GTK setting for non-allocating types.
/// Automatically uses XDG Desktop Portal in Flatpak environments.
/// Returns null if the setting is unavailable.
pub fn get(comptime key: Key) ?key.Type() {
if (comptime key.requiresAllocation()) {
@compileError("Allocating types require an allocator; use getAlloc() instead");
@@ -53,25 +47,15 @@ pub fn get(comptime key: Key) ?key.Type() {
return getImpl(settings, null, key) catch unreachable;
}
/// Reads a GTK setting using the GTK Settings API, allocating if necessary.
/// This automatically uses XDG Desktop Portal in Flatpak environments.
///
/// The caller must free any returned allocated memory with the provided allocator.
/// Returns null if the setting is not available or cannot be read.
/// May return an allocation error if memory allocation fails.
///
/// Example usage:
/// const theme = try getAlloc(allocator, .gtk_theme_name);
/// defer if (theme) |t| allocator.free(t);
/// Reads a GTK setting, allocating memory if necessary.
/// Automatically uses XDG Desktop Portal in Flatpak environments.
/// Caller must free returned memory with the provided allocator.
/// Returns null if the setting is unavailable.
pub fn getAlloc(allocator: std.mem.Allocator, comptime key: Key) !?key.Type() {
const settings = gtk.Settings.getDefault() orelse return null;
return getImpl(settings, allocator, key);
}
/// Shared implementation for reading GTK settings.
/// If allocator is null, only non-allocating types can be used.
/// Note: When adding a new type, research if it requires allocation (strings and boxed types do)
/// if allocation is NOT needed, list it inside the switch statement in the function requiresAllocation()
fn getImpl(settings: *gtk.Settings, allocator: ?std.mem.Allocator, comptime key: Key) !?key.Type() {
const GValType = key.GValueType();
var value = gobject.ext.Value.new(GValType);
@@ -80,13 +64,9 @@ fn getImpl(settings: *gtk.Settings, allocator: ?std.mem.Allocator, comptime key:
settings.as(gobject.Object).getProperty(@tagName(key).ptr, &value);
return switch (key.Type()) {
bool => value.getInt() != 0, // Booleans are stored as integers in GTK, convert to bool
c_int => value.getInt(), // Integer types are returned directly
bool => value.getInt() != 0,
c_int => value.getInt(),
[]const u8 => blk: {
// Strings: GTK owns the GValue's pointer, so we must duplicate it
// before the GValue is destroyed by defer value.unset()
// This is defensive: we have already checked at compile-time that
// an allocator is provided for allocating types
const alloc = allocator.?;
const ptr = value.getString() orelse break :blk null;
const str = std.mem.span(ptr);