diff --git a/src/Config.zig b/src/Config.zig index d8e20f8..d76e3c0 100644 --- a/src/Config.zig +++ b/src/Config.zig @@ -38,7 +38,8 @@ bar_config: ?BarConfig = null, /// Tag bind entries parsed from config (tag_bind nodes in keybinds block) tag_binds: std.ArrayList(Keybind) = .{}, -keybinds: std.ArrayList(Keybind) = .{}, +// We use a hash map so that duplicate keybinds can be easily de-duplicated +keybinds: keybind_helper.Map = .{}, pointer_binds: std.ArrayList(PointerBind) = .{}, input_configs: std.ArrayList(InputConfig) = .{}, @@ -90,8 +91,8 @@ pub fn create() !*Config { config.load(&file_reader.interface) catch |err| { log.err("Error while loading config: {s}. Continuing with default config", .{@errorName(err)}); // Free any partially-loaded state and reset to defaults - for (config.keybinds.items) |keybind| { - switch (keybind.command) { + for (config.keybinds.values()) |cmd| { + switch (cmd) { .spawn => |argv| { for (argv) |arg| utils.gpa.free(arg); utils.gpa.free(argv); @@ -120,8 +121,8 @@ pub fn create() !*Config { } pub fn destroy(config: *Config) void { - for (config.keybinds.items) |keybind| { - switch (keybind.command) { + for (config.keybinds.values()) |cmd| { + switch (cmd) { .spawn => |argv| { for (argv) |arg| utils.gpa.free(arg); utils.gpa.free(argv); diff --git a/src/WindowManager.zig b/src/WindowManager.zig index 78a3461..1211aa6 100644 --- a/src/WindowManager.zig +++ b/src/WindowManager.zig @@ -105,10 +105,8 @@ fn manage_start(wm: *WindowManager) void { } } // Rest of the keybinds - for (context.config.keybinds.items) |keybind| { - // Keysyms should only be null in tag_binds (above) - std.debug.assert(keybind.keysym != null); - context.xkb_bindings.addBinding(river_seat_v1, keybind.keysym.?, keybind.modifiers, keybind.command); + for (context.config.keybinds.keys(), context.config.keybinds.values()) |key, command| { + context.xkb_bindings.addBinding(river_seat_v1, key.keysym, key.modifiers, command); } // Pointer bindings diff --git a/src/config/keybinds.zig b/src/config/keybinds.zig index 5fa9b96..a96bfa7 100644 --- a/src/config/keybinds.zig +++ b/src/config/keybinds.zig @@ -11,6 +11,13 @@ pub const Keybind = struct { keysym: ?xkbcommon.Keysym, }; +pub const Key = struct { + modifiers: river.SeatV1.Modifiers, + keysym: xkbcommon.Keysym, +}; + +pub const Map = std.AutoArrayHashMapUnmanaged(Key, XkbBindings.Command); + pub fn load(config: *Config, parser: *kdl.Parser, hostname: ?[]const u8) !void { while (try parser.next()) |event| { switch (event) { @@ -172,11 +179,20 @@ pub fn load(config: *Config, parser: *kdl.Parser, hostname: ?[]const u8) !void { }, }; - try config.keybinds.append(utils.gpa, .{ + const gop = try config.keybinds.getOrPut(utils.gpa, .{ .modifiers = modifiers, - .command = command, .keysym = keysym, }); + if (gop.found_existing) { + switch (gop.value_ptr.*) { + .spawn => |argv| { + for (argv) |arg| utils.gpa.free(arg); + utils.gpa.free(argv); + }, + else => unreachable, + } + } + gop.value_ptr.* = command; } else { helpers.logWarnInvalidNode(node.name); }