From fc0482902e22f527024a3585d8ce6ac8c2fb850a Mon Sep 17 00:00:00 2001 From: Ben Buhse Date: Mon, 16 Feb 2026 13:51:02 -0600 Subject: [PATCH] Create config/pointer_binds.zig This moves all of the pointer_binds {} block parsing into its own file --- src/Config.zig | 86 ++------------------------------ src/config/keybinds.zig | 8 +++ src/config/pointer_binds.zig | 97 ++++++++++++++++++++++++++++++++++++ 3 files changed, 110 insertions(+), 81 deletions(-) create mode 100644 src/config/pointer_binds.zig diff --git a/src/Config.zig b/src/Config.zig index 8d8b4fb..ea88191 100644 --- a/src/Config.zig +++ b/src/Config.zig @@ -40,22 +40,9 @@ keybinds: std.ArrayList(Keybind) = .{}, pointer_binds: std.ArrayList(PointerBind) = .{}, input_configs: std.ArrayList(InputConfig) = .{}, -pub const Keybind = struct { - modifiers: river.SeatV1.Modifiers, - command: XkbBindings.Command, - keysym: ?xkbcommon.Keysym, -}; - -pub const PointerBind = struct { - modifiers: river.SeatV1.Modifiers, - button: u32, // Linux button code (BTN_LEFT=0x110, BTN_RIGHT=0x111, BTN_MIDDLE=0x112) - action: PointerAction, -}; - -pub const PointerAction = enum { - move_window, - resize_window, -}; +// Re-exports +pub const Keybind = keybind_helper.Keybind; +pub const PointerBind = pointer_bind_helper.PointerBind; pub const InputConfig = struct { /// Device name to match @@ -103,11 +90,6 @@ const NodeName = enum { tag_overlay, }; -const PointerBindNodeName = enum { - move_window, - resize_window, -}; - const InputConfigNodeName = enum { send_events, tap, @@ -323,7 +305,7 @@ fn load(config: *Config, reader: *Io.Reader) !void { switch (child_block) { .borders => try borders_helper.load(config, &parser, hostname), .keybinds => try keybind_helper.load(config, &parser, hostname), - .pointer_binds => try config.loadPointerBindsChildBlock(&parser, hostname), + .pointer_binds => try pointer_bind_helper.load(config, &parser, hostname), .input => { try config.loadInputChildBlock(&parser, pending_input_name, hostname); pending_input_name = null; // ownership transferred @@ -344,62 +326,6 @@ fn load(config: *Config, reader: *Io.Reader) !void { } } -fn loadPointerBindsChildBlock(config: *Config, parser: *kdl.Parser, hostname: ?[]const u8) !void { - while (try parser.next()) |event| { - switch (event) { - .node => |node| { - const node_name = std.meta.stringToEnum(PointerBindNodeName, node.name); - if (node_name) |name| { - if (!helpers.hostMatches(node, parser, hostname)) { - logDebugHostMismatch(name); - continue; - } - // Parse modifiers (arg 0) - const mod_str = utils.stripQuotes(node.arg(parser, 0) orelse { - logWarnMissingNodeArg(name, "modifier(s)"); - continue; - }); - const modifiers = try utils.parseModifiers(mod_str) orelse { - logWarnInvalidNodeArg(name, mod_str); - continue; - }; - - // Parse button (arg 1) - const button_str = utils.stripQuotes(node.arg(parser, 1) orelse { - logWarnMissingNodeArg(name, "button"); - continue; - }); - const button = helpers.parseButton(button_str) orelse { - logWarnInvalidNodeArg(name, button_str); - continue; - }; - - const action: PointerAction = switch (name) { - .move_window => .move_window, - .resize_window => .resize_window, - }; - - try config.pointer_binds.append(utils.gpa, .{ - .modifiers = modifiers, - .button = button, - .action = action, - }); - - log.debug("pointer_binds.{s}: {s} {s}", .{ @tagName(name), mod_str, button_str }); - } else { - helpers.logWarnInvalidNode(node.name); - } - }, - .child_block_begin => { - try helpers.skipChildBlock(parser); - }, - .child_block_end => { - return; - }, - } - } -} - fn loadInputChildBlock(config: *Config, parser: *kdl.Parser, name: ?[]const u8, hostname: ?[]const u8) !void { var input_config: InputConfig = .{ .name = name }; errdefer if (input_config.name) |n| utils.gpa.free(n); @@ -491,7 +417,6 @@ fn logWarnInvalidNodeArg(node_name: anytype, node_value: []const u8) void { const node_name_type = @TypeOf(node_name); switch (node_name_type) { NodeName => log.warn("Invalid \"{s}\" ({s}). Using default value", .{ @tagName(node_name), node_value }), - PointerBindNodeName => log.warn("Invalid \"pointer_binds.{s}\" ({s}). Ignoring", .{ @tagName(node_name), node_value }), InputConfigNodeName => log.warn("Invalid \"input.{s}\" ({s}). Ignoring", .{ @tagName(node_name), node_value }), else => @compileError("This function does not (yet) support type \"" ++ @typeName(node_name_type) ++ "\""), } @@ -501,7 +426,6 @@ fn logWarnMissingNodeArg(node_name: anytype, comptime arg: []const u8) void { const node_name_type = @TypeOf(node_name); switch (node_name_type) { NodeName => log.warn("\"{s}\" missing " ++ arg ++ " argument. Ignoring", .{@tagName(node_name)}), - PointerBindNodeName => log.warn("\"pointer_binds.{s}\" missing " ++ arg ++ " argument. Ignoring", .{@tagName(node_name)}), InputConfigNodeName => log.warn("\"input.{s}\" missing " ++ arg ++ " argument. Ignoring", .{@tagName(node_name)}), else => @compileError("This function does not (yet) support type \"" ++ @typeName(node_name_type) ++ "\""), } @@ -519,7 +443,6 @@ fn logDebugHostMismatch(node_name: anytype) void { const node_name_type = @TypeOf(node_name); switch (node_name_type) { NodeName => log.debug("Skipping \"{s}\" (host mismatch)", .{@tagName(node_name)}), - PointerBindNodeName => log.debug("Skipping \"pointer_binds.{s}\" (host mismatch)", .{@tagName(node_name)}), InputConfigNodeName => log.debug("Skipping \"input.{s}\" (host mismatch)", .{@tagName(node_name)}), else => @compileError("This function does not (yet) support type \"" ++ @typeName(node_name_type) ++ "\""), } @@ -568,6 +491,7 @@ const XkbBindings = @import("XkbBindings.zig"); const borders_helper = @import("config/borders.zig"); const keybind_helper = @import("config/keybinds.zig"); +const pointer_bind_helper = @import("config/pointer_binds.zig"); const tag_overlay_helper = @import("config/tag_overlay.zig"); const helpers = @import("config/helpers.zig"); const TagOverlayConfig = tag_overlay_helper.TagOverlayConfig; diff --git a/src/config/keybinds.zig b/src/config/keybinds.zig index 57ce6da..5fa9b96 100644 --- a/src/config/keybinds.zig +++ b/src/config/keybinds.zig @@ -5,6 +5,12 @@ // We can just directly use the tag type from Command as our node name const NodeName = @typeInfo(XkbBindings.Command).@"union".tag_type.?; +pub const Keybind = struct { + modifiers: river.SeatV1.Modifiers, + command: XkbBindings.Command, + keysym: ?xkbcommon.Keysym, +}; + pub fn load(config: *Config, parser: *kdl.Parser, hostname: ?[]const u8) !void { while (try parser.next()) |event| { switch (event) { @@ -199,6 +205,8 @@ const std = @import("std"); const fmt = std.fmt; const mem = std.mem; +const wayland = @import("wayland"); +const river = wayland.client.river; const kdl = @import("kdl"); const xkbcommon = @import("xkbcommon"); diff --git a/src/config/pointer_binds.zig b/src/config/pointer_binds.zig new file mode 100644 index 0000000..db8aae1 --- /dev/null +++ b/src/config/pointer_binds.zig @@ -0,0 +1,97 @@ +// SPDX-FileCopyrightText: 2026 Ben Buhse +// +// SPDX-License-Identifier: GPL-3.0-only + +pub const PointerBind = struct { + modifiers: river.SeatV1.Modifiers, + button: u32, // Linux button code (BTN_LEFT=0x110, BTN_RIGHT=0x111, BTN_MIDDLE=0x112) + action: PointerAction, +}; + +pub const PointerAction = enum { + move_window, + resize_window, +}; + +const NodeName = enum { + move_window, + resize_window, +}; + +pub fn load(config: *Config, parser: *kdl.Parser, hostname: ?[]const u8) !void { + while (try parser.next()) |event| { + switch (event) { + .node => |node| { + const node_name = std.meta.stringToEnum(NodeName, node.name); + if (node_name) |name| { + if (!helpers.hostMatches(node, parser, hostname)) { + log.debug("Skipping \"pointer_binds.{s}\" (host mismatch)", .{@tagName(name)}); + continue; + } + // Parse modifiers (arg 0) + const mod_str = utils.stripQuotes(node.arg(parser, 0) orelse { + logWarnMissingNodeArg(name, "modifier(s)"); + continue; + }); + const modifiers = try utils.parseModifiers(mod_str) orelse { + logWarnInvalidNodeArg(name, mod_str); + continue; + }; + + // Parse button (arg 1) + const button_str = utils.stripQuotes(node.arg(parser, 1) orelse { + logWarnMissingNodeArg(name, "button"); + continue; + }); + const button = helpers.parseButton(button_str) orelse { + logWarnInvalidNodeArg(name, button_str); + continue; + }; + + const action: PointerAction = switch (name) { + .move_window => .move_window, + .resize_window => .resize_window, + }; + + try config.pointer_binds.append(utils.gpa, .{ + .modifiers = modifiers, + .button = button, + .action = action, + }); + + log.debug("pointer_binds.{s}: {s} {s}", .{ @tagName(name), mod_str, button_str }); + } else { + helpers.logWarnInvalidNode(node.name); + } + }, + .child_block_begin => { + try helpers.skipChildBlock(parser); + }, + .child_block_end => { + return; + }, + } + } +} + +inline fn logWarnInvalidNodeArg(node_name: NodeName, node_value: []const u8) void { + log.warn("Invalid \"pointer_binds.{s}\" ({s}). Ignoring", .{ @tagName(node_name), node_value }); +} + +inline fn logWarnMissingNodeArg(node_name: NodeName, comptime arg: []const u8) void { + log.warn("\"pointer_binds.{s}\" missing " ++ arg ++ " argument. Ignoring", .{@tagName(node_name)}); +} + +const std = @import("std"); +const fmt = std.fmt; + +const wayland = @import("wayland"); +const river = wayland.client.river; +const kdl = @import("kdl"); + +const utils = @import("../utils.zig"); +const Config = @import("../Config.zig"); + +const helpers = @import("helpers.zig"); + +const log = std.log.scoped(.config_pointer_binds);