From 9a2e11620c4a50e0e5c9584f7e1d2dc15858cbb1 Mon Sep 17 00:00:00 2001 From: Marten Ringwelski Date: Sat, 24 Oct 2020 09:19:51 +0200 Subject: [PATCH] Implement unmap-pointer --- doc/riverctl.1.scd | 4 +++ river/command.zig | 1 + river/command/map.zig | 72 ++++++++++++++++++++++++++++++------------- 3 files changed, 55 insertions(+), 22 deletions(-) diff --git a/doc/riverctl.1.scd b/doc/riverctl.1.scd index 044af09..dc268e4 100644 --- a/doc/riverctl.1.scd +++ b/doc/riverctl.1.scd @@ -200,6 +200,10 @@ that tag 1 through 9 are visible. Removes the mapping defined by the arguments *-release*, *modifiers* and *key* from *mode*. See *map* for an explanation of the arguments. +*unmap-pointer* _mode_ _modifiers_ _button_ + Removes the mapping defined by the arguments *modifiers* and *button* from *mode*. + See *map-pointer* for an explanation of the arguments. + *view-padding* _pixels_ Set the padding around the edge of each view to _pixels_. diff --git a/river/command.zig b/river/command.zig index 998a9e0..0867ca7 100644 --- a/river/command.zig +++ b/river/command.zig @@ -76,6 +76,7 @@ const str_to_impl_fn = [_]struct { .{ .name = "toggle-fullscreen", .impl = @import("command/toggle_fullscreen.zig").toggleFullscreen }, .{ .name = "toggle-view-tags", .impl = @import("command/tags.zig").toggleViewTags }, .{ .name = "unmap", .impl = @import("command/map.zig").unmap }, + .{ .name = "unmap-pointer", .impl = @import("command/map.zig").unmapPointer }, .{ .name = "view-padding", .impl = @import("command/config.zig").viewPadding }, .{ .name = "xcursor-theme", .impl = @import("command/xcursor_theme.zig").xcursorTheme }, .{ .name = "zoom", .impl = @import("command/zoom.zig").zoom }, diff --git a/river/command/map.zig b/river/command/map.zig index f97162e..c5b421d 100644 --- a/river/command/map.zig +++ b/river/command/map.zig @@ -89,29 +89,16 @@ pub fn mapPointer( const mode_id = try modeNameToId(allocator, seat, args[1], out); const modifiers = try parseModifiers(allocator, args[2], out); + const event_code = try parseEventCode(allocator, args[3], out); - const event_code = blk: { - const event_code_name = try std.cstr.addNullByte(allocator, args[3]); - defer allocator.free(event_code_name); - const ret = c.libevdev_event_code_from_name(c.EV_KEY, event_code_name); - if (ret < 1) { - out.* = try std.fmt.allocPrint(allocator, "unknown button {}", .{args[3]}); - return Error.Other; - } - break :blk @intCast(u32, ret); - }; - - // Check if the mapping already exists const mode_pointer_mappings = &seat.input_manager.server.config.modes.items[mode_id].pointer_mappings; - for (mode_pointer_mappings.items) |existing| { - if (existing.event_code == event_code and existing.modifiers == modifiers) { - out.* = try std.fmt.allocPrint( - allocator, - "a pointer mapping for modifiers '{}' and button '{}' already exists", - .{ args[2], args[3] }, - ); - return Error.Other; - } + if (pointerMappingExists(mode_pointer_mappings, modifiers, event_code)) |_| { + out.* = try std.fmt.allocPrint( + allocator, + "a pointer mapping for modifiers '{}' and button '{}' already exists", + .{ args[2], args[3] }, + ); + return Error.Other; } const action = if (std.mem.eql(u8, args[4], "move-view")) @@ -139,7 +126,7 @@ fn modeNameToId(allocator: *std.mem.Allocator, seat: *Seat, mode_name: []const u return config.mode_to_id.get(mode_name) orelse { out.* = try std.fmt.allocPrint( allocator, - "cannot add mapping to non-existant mode '{}'", + "cannot add/remove mapping to/from non-existant mode '{}'", .{mode_name}, ); return Error.Other; @@ -157,6 +144,17 @@ fn mappingExists(mappings: *std.ArrayList(Mapping), modifiers: u32, keysym: u32, return null; } +/// Returns the index of the PointerMapping with matching modifiers and event code, if any. +fn pointerMappingExists(pointer_mappings: *std.ArrayList(PointerMapping), modifiers: u32, event_code: u32) ?usize { + for (pointer_mappings.items) |mapping, i| { + if (mapping.modifiers == modifiers and mapping.event_code == event_code) { + return i; + } + } + + return null; +} + fn parseEventCode(allocator: *std.mem.Allocator, event_code_str: []const u8, out: *?[]const u8) !u32 { const event_code_name = try std.cstr.addNullByte(allocator, event_code_str); defer allocator.free(event_code_name); @@ -270,3 +268,33 @@ pub fn unmap( var mapping = mode_mappings.swapRemove(mapping_idx); mapping.deinit(); } + +/// Remove a pointer mapping for a given mode +/// +/// Example: +/// unmap-pointer normal Mod4 BTN_LEFT +pub fn unmapPointer( + allocator: *std.mem.Allocator, + seat: *Seat, + args: []const []const u8, + out: *?[]const u8, +) Error!void { + if (args.len < 4) return Error.NotEnoughArguments; + if (args.len > 4) return Error.TooManyArguments; + + const mode_id = try modeNameToId(allocator, seat, args[1], out); + const modifiers = try parseModifiers(allocator, args[2], out); + const event_code = try parseEventCode(allocator, args[3], out); + + const mode_pointer_mappings = &seat.input_manager.server.config.modes.items[mode_id].pointer_mappings; + const mapping_idx = pointerMappingExists(mode_pointer_mappings, modifiers, event_code) orelse { + out.* = try std.fmt.allocPrint( + allocator, + "there is no mapping for modifiers '{}' and button '{}'", + .{ args[2], args[3] }, + ); + return Error.Other; + }; + + _ = mode_pointer_mappings.swapRemove(mapping_idx); +}