From 369ffebb728149110f2e22b373fa8515c19a77ce Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Thu, 31 Aug 2023 13:08:33 -0700 Subject: [PATCH] input: when overwriting a binding, we must update the reverse map --- src/input/Binding.zig | 43 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 42 insertions(+), 1 deletion(-) diff --git a/src/input/Binding.zig b/src/input/Binding.zig index 5de868d1a..143f217d9 100644 --- a/src/input/Binding.zig +++ b/src/input/Binding.zig @@ -393,7 +393,23 @@ pub const Set = struct { ) !void { // unbind should never go into the set, it should be handled prior assert(action != .unbind); - try self.bindings.put(alloc, t, action); + + const gop = try self.bindings.getOrPut(alloc, t); + + // If we have an existing binding for this trigger, we have to + // update the reverse mapping to remove the old action. + if (gop.found_existing) { + const t_hash = t.hash(); + var it = self.reverse.iterator(); + while (it.next()) |reverse_entry| it: { + if (t_hash == reverse_entry.value_ptr.hash()) { + self.reverse.removeByPtr(reverse_entry.key_ptr); + break :it; + } + } + } + + gop.value_ptr.* = action; errdefer _ = self.bindings.remove(t); try self.reverse.put(alloc, action, t); errdefer _ = self.reverse.remove(action); @@ -426,6 +442,10 @@ pub const Set = struct { self.reverse.putAssumeCapacity(action, entry.key_ptr.*); break; } + } else { + // No over trigger points to this action so we remove + // the reverse mapping completely. + _ = self.reverse.remove(action); } } @@ -610,3 +630,24 @@ test "set: maintains reverse mapping" { try testing.expect(trigger.key == .a); } } + +test "set: overriding a mapping updates reverse" { + const testing = std.testing; + const alloc = testing.allocator; + + var s: Set = .{}; + defer s.deinit(alloc); + + try s.put(alloc, .{ .key = .a }, .{ .new_window = {} }); + { + const trigger = s.getTrigger(.{ .new_window = {} }).?; + try testing.expect(trigger.key == .a); + } + + // should be most recent + try s.put(alloc, .{ .key = .a }, .{ .new_tab = {} }); + { + const trigger = s.getTrigger(.{ .new_window = {} }); + try testing.expect(trigger == null); + } +}