// SPDX-FileCopyrightText: © 2026 mtmn // // SPDX-License-Identifier: BSD-3-Clause // Module type aliases use PascalCase per Zig convention. // zwanzig-disable: identifier-style const PointerBinding = @This(); const std = @import("std"); const river = @import("wayland").client.river; const Seat = @import("Seat.zig"); const WindowManager = @import("WindowManager.zig"); pub const Action = enum { move, resize, command, }; object: *river.PointerBindingV1, button: u32, modifiers: river.SeatV1.Modifiers, action: Action, /// Borrowed from the mode's pointer binding specification, which outlives /// every live binding made from it. command: [:0]const u8, manager: *WindowManager, seat: *Seat, enabled: bool = false, pub fn init( binding: *PointerBinding, object: *river.PointerBindingV1, button: u32, modifiers: river.SeatV1.Modifiers, action: Action, command: [:0]const u8, manager: *WindowManager, seat: *Seat, ) void { binding.* = .{ .object = object, .button = button, .modifiers = modifiers, .action = action, .command = command, .manager = manager, .seat = seat, }; object.setListener(*PointerBinding, handleEvent, binding); } pub fn deinit(binding: *PointerBinding) void { binding.object.destroy(); } fn handleEvent( _: *river.PointerBindingV1, event: river.PointerBindingV1.Event, binding: *PointerBinding, ) void { switch (event) { .pressed => { if (binding.action == .command) { binding.manager.fireBinding(binding.command); } else { WindowManager.requestPointerOperation(binding.seat, binding); } }, .released => {}, } } pub fn parseButton(text: []const u8) error{InvalidButton}!u32 { inline for (.{ .{ "BTN_LEFT", 0x110 }, .{ "BTN_RIGHT", 0x111 }, .{ "BTN_MIDDLE", 0x112 }, .{ "BTN_SIDE", 0x113 }, .{ "BTN_EXTRA", 0x114 }, .{ "BTN_FORWARD", 0x115 }, .{ "BTN_BACK", 0x116 }, .{ "BTN_TASK", 0x117 }, }) |pair| { if (std.mem.eql(u8, text, pair[0])) return pair[1]; } return std.fmt.parseInt(u32, text, 10) catch return error.InvalidButton; }