From 4bc938a7896ee670cd281025c6ceb1c2b22ca03f Mon Sep 17 00:00:00 2001 From: Ivan Duran Date: Thu, 7 Nov 2024 23:38:58 +0300 Subject: [PATCH] Change Percentage to f32 --- src/Surface.zig | 6 +----- src/apprt/action.zig | 2 +- src/apprt/gtk/App.zig | 8 ++++---- src/apprt/gtk/Split.zig | 9 ++++----- src/apprt/gtk/Window.zig | 8 ++++---- src/config/Config.zig | 8 ++++---- src/input/Binding.zig | 41 +++++++++++++++++++++++++--------------- 7 files changed, 44 insertions(+), 38 deletions(-) diff --git a/src/Surface.zig b/src/Surface.zig index 661ae0b3e..800655a3f 100644 --- a/src/Surface.zig +++ b/src/Surface.zig @@ -3971,11 +3971,7 @@ pub fn performBindingAction(self: *Surface, action: input.Binding.Action) !bool .{ .surface = self }, .new_split, .{ - .percent = std.fmt.parseInt( - u16, - value[1], - 10, - ) catch return error.InvalidType, + .percent = value[1], .direction = switch (value[0]) { .right => .right, .left => .left, diff --git a/src/apprt/action.zig b/src/apprt/action.zig index f4d9cfb20..e96da8081 100644 --- a/src/apprt/action.zig +++ b/src/apprt/action.zig @@ -289,7 +289,7 @@ pub const Action = union(Key) { /// The percentage and direction to create the split pub const SplitDirection = extern struct { - percent: u16, + percent: f32, direction: Direction, // This is made extern (c_int) to make interop easier with our embedded diff --git a/src/apprt/gtk/App.zig b/src/apprt/gtk/App.zig index 8620de57d..618a4b5b3 100644 --- a/src/apprt/gtk/App.zig +++ b/src/apprt/gtk/App.zig @@ -864,10 +864,10 @@ fn syncActionAccelerators(self: *App) !void { try self.syncActionAccelerator("win.close", .{ .close_surface = {} }); try self.syncActionAccelerator("win.new_window", .{ .new_window = {} }); try self.syncActionAccelerator("win.new_tab", .{ .new_tab = {} }); - try self.syncActionAccelerator("win.split_right", .{ .new_split = .{ .right, "50%" } }); - try self.syncActionAccelerator("win.split_down", .{ .new_split = .{ .down, "50%" } }); - try self.syncActionAccelerator("win.split_left", .{ .new_split = .{ .left, "50%" } }); - try self.syncActionAccelerator("win.split_up", .{ .new_split = .{ .up, "50%" } }); + try self.syncActionAccelerator("win.split_right", .{ .new_split = .{ .right, 0.5 } }); + try self.syncActionAccelerator("win.split_down", .{ .new_split = .{ .down, 0.5 } }); + try self.syncActionAccelerator("win.split_left", .{ .new_split = .{ .left, 0.5 } }); + try self.syncActionAccelerator("win.split_up", .{ .new_split = .{ .up, 0.5 } }); try self.syncActionAccelerator("win.copy", .{ .copy_to_clipboard = {} }); try self.syncActionAccelerator("win.paste", .{ .paste_from_clipboard = {} }); try self.syncActionAccelerator("win.reset", .{ .reset = {} }); diff --git a/src/apprt/gtk/Split.zig b/src/apprt/gtk/Split.zig index 305edb8d9..db1888308 100644 --- a/src/apprt/gtk/Split.zig +++ b/src/apprt/gtk/Split.zig @@ -125,10 +125,9 @@ pub fn init( // added to the paned. self.updateChildren(); - // Skip resize logic if percentage is 50 (this is the default behavior) - if (new_split.percent != 50) { + // Skip resize logic if percent is 0.5 (this is the default behavior) + if (new_split.percent != 0.5) { const allocation = sibling.size; - const split_percentage: f32 = @as(f32, @floatFromInt(new_split.percent)) / 100; const total_surface_size: f32 = switch (self.orientation) { .horizontal => @floatFromInt(allocation.width), .vertical => @floatFromInt(allocation.height), @@ -136,8 +135,8 @@ pub fn init( // percentage to apply based on direction const pct = switch (new_split.direction) { - .right, .down => 1 - split_percentage, - .left, .up => split_percentage, + .right, .down => 1 - new_split.percent, + .left, .up => new_split.percent, }; const divider_position = @as(c_int, @intFromFloat(total_surface_size * pct)); diff --git a/src/apprt/gtk/Window.zig b/src/apprt/gtk/Window.zig index 63a71768f..971e3cc8f 100644 --- a/src/apprt/gtk/Window.zig +++ b/src/apprt/gtk/Window.zig @@ -807,7 +807,7 @@ fn gtkActionSplitRight( ) callconv(.C) void { const self: *Window = @ptrCast(@alignCast(ud orelse return)); const surface = self.actionSurface() orelse return; - _ = surface.performBindingAction(.{ .new_split = .{ .right, "50%" } }) catch |err| { + _ = surface.performBindingAction(.{ .new_split = .{ .right, 0.5 } }) catch |err| { log.warn("error performing binding action error={}", .{err}); return; }; @@ -820,7 +820,7 @@ fn gtkActionSplitDown( ) callconv(.C) void { const self: *Window = @ptrCast(@alignCast(ud orelse return)); const surface = self.actionSurface() orelse return; - _ = surface.performBindingAction(.{ .new_split = .{ .down, "50%" } }) catch |err| { + _ = surface.performBindingAction(.{ .new_split = .{ .down, 0.5 } }) catch |err| { log.warn("error performing binding action error={}", .{err}); return; }; @@ -833,7 +833,7 @@ fn gtkActionSplitLeft( ) callconv(.C) void { const self: *Window = @ptrCast(@alignCast(ud orelse return)); const surface = self.actionSurface() orelse return; - _ = surface.performBindingAction(.{ .new_split = .{ .left, "50%" } }) catch |err| { + _ = surface.performBindingAction(.{ .new_split = .{ .left, 0.5 } }) catch |err| { log.warn("error performing binding action error={}", .{err}); return; }; @@ -846,7 +846,7 @@ fn gtkActionSplitUp( ) callconv(.C) void { const self: *Window = @ptrCast(@alignCast(ud orelse return)); const surface = self.actionSurface() orelse return; - _ = surface.performBindingAction(.{ .new_split = .{ .up, "50%" } }) catch |err| { + _ = surface.performBindingAction(.{ .new_split = .{ .up, 0.5 } }) catch |err| { log.warn("error performing binding action error={}", .{err}); return; }; diff --git a/src/config/Config.zig b/src/config/Config.zig index 6d35f1b4e..e4dadd9c8 100644 --- a/src/config/Config.zig +++ b/src/config/Config.zig @@ -1927,12 +1927,12 @@ pub fn default(alloc_gpa: Allocator) Allocator.Error!Config { try result.keybind.set.put( alloc, .{ .key = .{ .translated = .o }, .mods = .{ .ctrl = true, .shift = true } }, - .{ .new_split = .{ .right, "50%" } }, + .{ .new_split = .{ .right, 0.5 } }, ); try result.keybind.set.put( alloc, .{ .key = .{ .translated = .e }, .mods = .{ .ctrl = true, .shift = true } }, - .{ .new_split = .{ .down, "50%" } }, + .{ .new_split = .{ .down, 0.5 } }, ); try result.keybind.set.put( alloc, @@ -2190,12 +2190,12 @@ pub fn default(alloc_gpa: Allocator) Allocator.Error!Config { try result.keybind.set.put( alloc, .{ .key = .{ .translated = .d }, .mods = .{ .super = true } }, - .{ .new_split = .{ .right, "50%" } }, + .{ .new_split = .{ .right, 0.5 } }, ); try result.keybind.set.put( alloc, .{ .key = .{ .translated = .d }, .mods = .{ .super = true, .shift = true } }, - .{ .new_split = .{ .down, "50%" } }, + .{ .new_split = .{ .down, 0.5 } }, ); try result.keybind.set.put( alloc, diff --git a/src/input/Binding.zig b/src/input/Binding.zig index 92080a113..c6982d84a 100644 --- a/src/input/Binding.zig +++ b/src/input/Binding.zig @@ -454,7 +454,7 @@ pub const Action = union(enum) { auto, // splits along the larger direction }; - pub const Percentage = []const u8; + pub const Percentage = f32; pub const SplitParameter = struct { SplitDirection, @@ -504,15 +504,17 @@ pub const Action = union(enum) { } fn parseFloat(comptime T: type, value: []const u8) !T { - return std.fmt.parseFloat(T, value) catch return Error.InvalidFormat; - } - - fn parsePercentage(value: []const u8) !Percentage { - if (value.len < 2) return Error.InvalidFormat; - if (value[value.len - 1] != '%') return Error.InvalidFormat; - const percent = value[0 .. value.len - 1]; - _ = std.fmt.parseInt(u16, percent, 10) catch return Error.InvalidFormat; - return percent; + return switch (T) { + Action.Percentage => blk: { + if (value.len < 2) return Error.InvalidFormat; + if (value[value.len - 1] != '%') return Error.InvalidFormat; + const percent = value[0 .. value.len - 1]; + const parsed_percent = std.fmt.parseFloat(f32, percent) catch return Error.InvalidFormat; + const clamped_percent: f32 = @min(@max(parsed_percent / 100.0, 0.0), 1.0); + break :blk clamped_percent; + }, + else => std.fmt.parseFloat(T, value) catch return Error.InvalidFormat, + }; } fn parseParameter( @@ -536,7 +538,6 @@ pub const Action = union(enum) { .Enum => try parseEnum(field_.type, next), .Int => try parseInt(field_.type, next), .Float => try parseFloat(field_.type, next), - .Pointer => if (field_.type == Percentage) try parsePercentage(next), else => unreachable, }; } @@ -825,6 +826,12 @@ pub const Action = union(enum) { @as(u64, @bitCast(field)), ), + // Handle SplitParameter specifically + Action.SplitParameter => { + const bits = @as(u32, @bitCast(field[1])); + std.hash.autoHash(hasher, bits); + }, + // Everything else automatically handle. else => std.hash.autoHashStrat( hasher, @@ -1704,11 +1711,10 @@ test "parse: action with enum" { // parameter { - // Note: The "50%" in the binding string gets parsed to just "50" const binding = try parseSingle("a=new_split:right,50%"); try testing.expect(binding.action == .new_split); try testing.expectEqual(Action.SplitDirection.right, binding.action.new_split[0]); - try testing.expectEqualSlices(u8, "50", binding.action.new_split[1]); + try testing.expectEqual(@as(f32, 0.5), binding.action.new_split[1]); } // missing unit % @@ -1717,8 +1723,13 @@ test "parse: action with enum" { // too many try testing.expectError(Error.InvalidFormat, parseSingle("a=new_split:right,30%,50%")); - // invalid type - try testing.expectError(Error.InvalidFormat, parseSingle("a=new_split:right,0.5%")); + // clamping value + { + var binding = try parseSingle("a=new_split:right,150%"); + try testing.expectEqual(@as(f32, 1.0), binding.action.new_split[1]); + binding = try parseSingle("a=new_split:right,-50%"); + try testing.expectEqual(@as(f32, 0.0), binding.action.new_split[1]); + } } test "parse: action with int" {