diff options
| author | Isaac Freund <mail@isaacfreund.com> | 2022-06-21 16:25:37 +0200 |
|---|---|---|
| committer | Isaac Freund <mail@isaacfreund.com> | 2022-06-21 16:25:37 +0200 |
| commit | 5cce49095aebd89803456bfa57541f6a10618a45 (patch) | |
| tree | 7824fefd83e5fc9cd57d75e059727d05e6d98487 | |
| parent | 67d07e84b01191a5c48d3f2e797a831e75895ce2 (diff) | |
| download | river-5cce49095aebd89803456bfa57541f6a10618a45.tar.gz river-5cce49095aebd89803456bfa57541f6a10618a45.tar.xz | |
Seat: refactor InputDevice handling
- The lifetimes of the Keyboard and Switch structs are now directly
tied to the corresponding InputDevice, which has become a field of
those structs.
- Seat capabilities are now properly updated on removing a keyboard.
These changes align with input device refactoring in upstream wlroots
which will make updating to easier 0.16.0.
| -rw-r--r-- | river/InputConfig.zig | 2 | ||||
| -rw-r--r-- | river/InputDevice.zig | 86 | ||||
| -rw-r--r-- | river/InputManager.zig | 47 | ||||
| -rw-r--r-- | river/Keyboard.zig | 62 | ||||
| -rw-r--r-- | river/Seat.zig | 118 | ||||
| -rw-r--r-- | river/Switch.zig | 41 | ||||
| -rw-r--r-- | river/command/input.zig | 33 | ||||
| -rw-r--r-- | river/command/set_repeat.zig | 10 |
8 files changed, 205 insertions, 194 deletions
diff --git a/river/InputConfig.zig b/river/InputConfig.zig index 92b3974..0467d95 100644 --- a/river/InputConfig.zig +++ b/river/InputConfig.zig @@ -288,7 +288,7 @@ pub fn deinit(self: *Self) void { pub fn apply(self: *Self, device: *InputDevice) void { const libinput_device = @ptrCast( *c.libinput_device, - device.device.getLibinputDevice() orelse return, + device.wlr_device.getLibinputDevice() orelse return, ); log.debug("applying input configuration to device: {s}", .{device.identifier}); if (self.event_state) |setting| setting.apply(libinput_device); diff --git a/river/InputDevice.zig b/river/InputDevice.zig index 413e8f8..69cd3da 100644 --- a/river/InputDevice.zig +++ b/river/InputDevice.zig @@ -25,9 +25,15 @@ const wl = @import("wayland").server.wl; const server = &@import("main.zig").server; const util = @import("util.zig"); +const Seat = @import("Seat.zig"); +const Keyboard = @import("Keyboard.zig"); +const Switch = @import("Switch.zig"); + const log = std.log.scoped(.input_manager); -device: *wlr.InputDevice, +seat: *Seat, +wlr_device: *wlr.InputDevice, + destroy: wl.Listener(*wlr.InputDevice) = wl.Listener(*wlr.InputDevice).init(handleDestroy), /// Careful: The identifier is not unique! A physical input device may have @@ -35,10 +41,13 @@ destroy: wl.Listener(*wlr.InputDevice) = wl.Listener(*wlr.InputDevice).init(hand /// and name. However identifiers of InputConfigs are unique. identifier: []const u8, -pub fn init(self: *InputDevice, device: *wlr.InputDevice) !void { - const device_type: []const u8 = switch (device.type) { +/// InputManager.devices +link: wl.list.Link, + +pub fn init(device: *InputDevice, seat: *Seat, wlr_device: *wlr.InputDevice) !void { + const device_type: []const u8 = switch (wlr_device.type) { .switch_device => "switch", - else => @tagName(device.type), + else => @tagName(wlr_device.type), }; const identifier = try std.fmt.allocPrint( @@ -46,35 +55,72 @@ pub fn init(self: *InputDevice, device: *wlr.InputDevice) !void { "{s}-{}-{}-{s}", .{ device_type, - device.vendor, - device.product, - mem.trim(u8, mem.span(device.name), &ascii.spaces), + wlr_device.vendor, + wlr_device.product, + mem.trim(u8, mem.span(wlr_device.name), &ascii.spaces), }, ); + errdefer util.gpa.free(identifier); + for (identifier) |*char| { if (!ascii.isGraph(char.*)) { char.* = '_'; } } - self.* = .{ - .device = device, + + device.* = .{ + .seat = seat, + .wlr_device = wlr_device, .identifier = identifier, + .link = undefined, }; - log.debug("new input device: {s}", .{self.identifier}); - device.events.destroy.add(&self.destroy); + + wlr_device.events.destroy.add(&device.destroy); + + // Apply any matching input device configuration. + for (server.input_manager.configs.items) |*input_config| { + if (mem.eql(u8, input_config.identifier, identifier)) { + input_config.apply(device); + } + } + + server.input_manager.devices.append(device); + seat.updateCapabilities(); + + log.debug("new input device: {s}", .{identifier}); } -pub fn deinit(self: *InputDevice) void { - util.gpa.free(self.identifier); - self.destroy.link.remove(); +pub fn deinit(device: *InputDevice) void { + device.destroy.link.remove(); + + util.gpa.free(device.identifier); + + device.link.remove(); + device.seat.updateCapabilities(); + + device.* = undefined; } fn handleDestroy(listener: *wl.Listener(*wlr.InputDevice), _: *wlr.InputDevice) void { - const self = @fieldParentPtr(InputDevice, "destroy", listener); - log.debug("removed input device: {s}", .{self.identifier}); - self.deinit(); + const device = @fieldParentPtr(InputDevice, "destroy", listener); + + log.debug("removed input device: {s}", .{device.identifier}); - const node = @fieldParentPtr(std.TailQueue(InputDevice).Node, "data", self); - server.input_manager.input_devices.remove(node); - util.gpa.destroy(node); + switch (device.wlr_device.type) { + .keyboard => { + const keyboard = @fieldParentPtr(Keyboard, "device", device); + keyboard.deinit(); + util.gpa.destroy(keyboard); + }, + .pointer => { + device.deinit(); + util.gpa.destroy(device); + }, + .switch_device => { + const switch_device = @fieldParentPtr(Switch, "device", device); + switch_device.deinit(); + util.gpa.destroy(switch_device); + }, + .touch, .tablet_tool, .tablet_pad => unreachable, + } } diff --git a/river/InputManager.zig b/river/InputManager.zig index f3d68a8..055ccdf 100644 --- a/river/InputManager.zig +++ b/river/InputManager.zig @@ -18,6 +18,7 @@ const Self = @This(); const build_options = @import("build_options"); const std = @import("std"); +const assert = std.debug.assert; const mem = std.mem; const wlr = @import("wlroots"); const wl = @import("wayland").server.wl; @@ -27,8 +28,10 @@ const util = @import("util.zig"); const InputConfig = @import("InputConfig.zig"); const InputDevice = @import("InputDevice.zig"); -const Seat = @import("Seat.zig"); +const Keyboard = @import("Keyboard.zig"); const PointerConstraint = @import("PointerConstraint.zig"); +const Seat = @import("Seat.zig"); +const Switch = @import("Switch.zig"); const default_seat_name = "default"; @@ -43,8 +46,8 @@ relative_pointer_manager: *wlr.RelativePointerManagerV1, virtual_pointer_manager: *wlr.VirtualPointerManagerV1, virtual_keyboard_manager: *wlr.VirtualKeyboardManagerV1, -input_configs: std.ArrayList(InputConfig), -input_devices: std.TailQueue(InputDevice) = .{}, +configs: std.ArrayList(InputConfig), +devices: wl.list.Head(InputDevice, "link"), seats: std.TailQueue(Seat) = .{}, exclusive_client: ?*wl.Client = null, @@ -72,8 +75,11 @@ pub fn init(self: *Self) !void { .relative_pointer_manager = try wlr.RelativePointerManagerV1.create(server.wl_server), .virtual_pointer_manager = try wlr.VirtualPointerManagerV1.create(server.wl_server), .virtual_keyboard_manager = try wlr.VirtualKeyboardManagerV1.create(server.wl_server), - .input_configs = std.ArrayList(InputConfig).init(util.gpa), + .configs = std.ArrayList(InputConfig).init(util.gpa), + + .devices = undefined, }; + self.devices.init(); self.seats.prepend(seat_node); try seat_node.data.init(default_seat_name); @@ -89,20 +95,18 @@ pub fn init(self: *Self) !void { } pub fn deinit(self: *Self) void { + // This function must be called after the backend has been destroyed + assert(self.devices.empty()); + while (self.seats.pop()) |seat_node| { seat_node.data.deinit(); util.gpa.destroy(seat_node); } - while (self.input_devices.pop()) |input_device_node| { - input_device_node.data.deinit(); - util.gpa.destroy(input_device_node); + for (self.configs.items) |*config| { + config.deinit(); } - - for (self.input_configs.items) |*input_config| { - input_config.deinit(); - } - self.input_configs.deinit(); + self.configs.deinit(); } pub fn defaultSeat(self: Self) *Seat { @@ -172,25 +176,10 @@ fn handleInhibitDeactivate( server.root.startTransaction(); } -/// This event is raised by the backend when a new input device becomes available. -fn handleNewInput(listener: *wl.Listener(*wlr.InputDevice), device: *wlr.InputDevice) void { +fn handleNewInput(listener: *wl.Listener(*wlr.InputDevice), wlr_device: *wlr.InputDevice) void { const self = @fieldParentPtr(Self, "new_input", listener); - // TODO: support multiple seats - const input_device_node = util.gpa.create(std.TailQueue(InputDevice).Node) catch return; - input_device_node.data.init(device) catch { - util.gpa.destroy(input_device_node); - return; - }; - self.input_devices.append(input_device_node); - self.defaultSeat().addDevice(device); - - // Apply matching input device configuration, if exists. - for (self.input_configs.items) |*input_config| { - if (mem.eql(u8, input_config.identifier, input_device_node.data.identifier)) { - input_config.apply(&input_device_node.data); - } - } + self.defaultSeat().addDevice(wlr_device); } fn handleNewPointerConstraint( diff --git a/river/Keyboard.zig b/river/Keyboard.zig index c93c7b2..42c3f45 100644 --- a/river/Keyboard.zig +++ b/river/Keyboard.zig @@ -27,41 +27,34 @@ const util = @import("util.zig"); const KeycodeSet = @import("KeycodeSet.zig"); const Seat = @import("Seat.zig"); +const InputDevice = @import("InputDevice.zig"); const log = std.log.scoped(.keyboard); -seat: *Seat, -input_device: *wlr.InputDevice, +device: InputDevice, /// Pressed keys for which a mapping was triggered on press eaten_keycodes: KeycodeSet = .{}, key: wl.Listener(*wlr.Keyboard.event.Key) = wl.Listener(*wlr.Keyboard.event.Key).init(handleKey), modifiers: wl.Listener(*wlr.Keyboard) = wl.Listener(*wlr.Keyboard).init(handleModifiers), -destroy: wl.Listener(*wlr.Keyboard) = wl.Listener(*wlr.Keyboard).init(handleDestroy), -pub fn init(self: *Self, seat: *Seat, input_device: *wlr.InputDevice) !void { +pub fn init(self: *Self, seat: *Seat, wlr_device: *wlr.InputDevice) !void { self.* = .{ - .seat = seat, - .input_device = input_device, + .device = undefined, }; + try self.device.init(seat, wlr_device); + errdefer self.device.deinit(); - // We need to prepare an XKB keymap and assign it to the keyboard. This - // assumes the defaults (e.g. layout = "us"). - const rules = xkb.RuleNames{ - .rules = null, - .model = null, - .layout = null, - .variant = null, - .options = null, - }; const context = xkb.Context.new(.no_flags) orelse return error.XkbContextFailed; defer context.unref(); - const keymap = xkb.Keymap.newFromNames(context, &rules, .no_flags) orelse return error.XkbKeymapFailed; + // Passing null here indicates that defaults from libxkbcommon and + // its XKB_DEFAULT_LAYOUT, XKB_DEFAULT_OPTIONS, etc. should be used. + const keymap = xkb.Keymap.newFromNames(context, null, .no_flags) orelse return error.XkbKeymapFailed; defer keymap.unref(); - const wlr_keyboard = self.input_device.device.keyboard; + const wlr_keyboard = self.device.wlr_device.device.keyboard; wlr_keyboard.data = @ptrToInt(self); if (!wlr_keyboard.setKeymap(keymap)) return error.SetKeymapFailed; @@ -70,23 +63,25 @@ pub fn init(self: *Self, seat: *Seat, input_device: *wlr.InputDevice) !void { wlr_keyboard.events.key.add(&self.key); wlr_keyboard.events.modifiers.add(&self.modifiers); - wlr_keyboard.events.destroy.add(&self.destroy); } pub fn deinit(self: *Self) void { self.key.link.remove(); self.modifiers.link.remove(); - self.destroy.link.remove(); + + self.device.deinit(); + + self.* = undefined; } fn handleKey(listener: *wl.Listener(*wlr.Keyboard.event.Key), event: *wlr.Keyboard.event.Key) void { // This event is raised when a key is pressed or released. const self = @fieldParentPtr(Self, "key", listener); - const wlr_keyboard = self.input_device.device.keyboard; + const wlr_keyboard = self.device.wlr_device.device.keyboard; - self.seat.handleActivity(); + self.device.seat.handleActivity(); - self.seat.clearRepeatingMapping(); + self.device.seat.clearRepeatingMapping(); // Translate libinput keycode -> xkbcommon const keycode = event.keycode + 8; @@ -103,7 +98,7 @@ fn handleKey(listener: *wl.Listener(*wlr.Keyboard.event.Key), event: *wlr.Keyboa !released and !isModifier(sym)) { - self.seat.cursor.hide(); + self.device.seat.cursor.hide(); break; } } @@ -114,11 +109,11 @@ fn handleKey(listener: *wl.Listener(*wlr.Keyboard.event.Key), event: *wlr.Keyboa } // Handle user-defined mappings - const mapped = self.seat.hasMapping(keycode, modifiers, released, xkb_state); + const mapped = self.device.seat.hasMapping(keycode, modifiers, released, xkb_state); if (mapped) { if (!released) self.eaten_keycodes.add(event.keycode); - const handled = self.seat.handleMapping(keycode, modifiers, released, xkb_state); + const handled = self.device.seat.handleMapping(keycode, modifiers, released, xkb_state); assert(handled); } @@ -126,8 +121,8 @@ fn handleKey(listener: *wl.Listener(*wlr.Keyboard.event.Key), event: *wlr.Keyboa if (!eaten) { // If key was not handled, we pass it along to the client. - const wlr_seat = self.seat.wlr_seat; - wlr_seat.setKeyboard(self.input_device); + const wlr_seat = self.device.seat.wlr_seat; + wlr_seat.setKeyboard(self.device.wlr_device); wlr_seat.keyboardNotifyKey(event.time_msec, event.keycode, event.state); } } @@ -140,17 +135,8 @@ fn isModifier(keysym: xkb.Keysym) bool { fn handleModifiers(listener: *wl.Listener(*wlr.Keyboard), _: *wlr.Keyboard) void { const self = @fieldParentPtr(Self, "modifiers", listener); - self.seat.wlr_seat.setKeyboard(self.input_device); - self.seat.wlr_seat.keyboardNotifyModifiers(&self.input_device.device.keyboard.modifiers); -} - -fn handleDestroy(listener: *wl.Listener(*wlr.Keyboard), _: *wlr.Keyboard) void { - const self = @fieldParentPtr(Self, "destroy", listener); - const node = @fieldParentPtr(std.TailQueue(Self).Node, "data", self); - - self.seat.keyboards.remove(node); - self.deinit(); - util.gpa.destroy(node); + self.device.seat.wlr_seat.setKeyboard(self.device.wlr_device); + self.device.seat.wlr_seat.keyboardNotifyModifiers(&self.device.wlr_device.device.keyboard.modifiers); } /// Handle any builtin, harcoded compsitor mappings such as VT switching. diff --git a/river/Seat.zig b/river/Seat.zig index 36d8060..c30bce7 100644 --- a/river/Seat.zig +++ b/river/Seat.zig @@ -27,16 +27,17 @@ const command = @import("command.zig"); const server = &@import("main.zig").server; const util = @import("util.zig"); -const DragIcon = @import("DragIcon.zig"); const Cursor = @import("Cursor.zig"); +const DragIcon = @import("DragIcon.zig"); +const InputDevice = @import("InputDevice.zig"); const InputManager = @import("InputManager.zig"); const Keyboard = @import("Keyboard.zig"); const KeycodeSet = @import("KeycodeSet.zig"); -const Switch = @import("Switch.zig"); -const Mapping = @import("Mapping.zig"); const LayerSurface = @import("LayerSurface.zig"); +const Mapping = @import("Mapping.zig"); const Output = @import("Output.zig"); const SeatStatus = @import("SeatStatus.zig"); +const Switch = @import("Switch.zig"); const View = @import("View.zig"); const ViewStack = @import("view_stack.zig").ViewStack; const XwaylandOverrideRedirect = @import("XwaylandOverrideRedirect.zig"); @@ -56,12 +57,6 @@ wlr_seat: *wlr.Seat, /// Multiple mice are handled by the same Cursor cursor: Cursor = undefined, -/// Mulitple keyboards are handled separately -keyboards: std.TailQueue(Keyboard) = .{}, - -/// There are two kind of switches: lid switches and tablet mode switches -switches: std.TailQueue(Switch) = .{}, - /// ID of the current keymap mode mode_id: u32 = 0, @@ -122,18 +117,13 @@ pub fn init(self: *Self, name: [*:0]const u8) !void { } pub fn deinit(self: *Self) void { - self.cursor.deinit(); - self.mapping_repeat_timer.remove(); - - while (self.keyboards.pop()) |node| { - node.data.deinit(); - util.gpa.destroy(node); + { + var it = server.input_manager.devices.iterator(.forward); + while (it.next()) |device| assert(device.seat != self); } - while (self.switches.pop()) |node| { - node.data.deinit(); - util.gpa.destroy(node); - } + self.cursor.deinit(); + self.mapping_repeat_timer.remove(); while (self.focus_stack.first) |node| { self.focus_stack.remove(node); @@ -464,52 +454,60 @@ fn handleMappingRepeatTimeout(self: *Self) callconv(.C) c_int { return 0; } -/// Add a newly created input device to the seat and update the reported -/// capabilities. -pub fn addDevice(self: *Self, device: *wlr.InputDevice) void { - switch (device.type) { - .keyboard => self.addKeyboard(device) catch return, - .pointer => self.addPointer(device), - .switch_device => self.addSwitch(device) catch return, - else => return, - } - - // We need to let the wlr_seat know what our capabilities are, which is - // communiciated to the client. We always have a cursor, even if - // there are no pointer devices, so we always include that capability. - self.wlr_seat.setCapabilities(.{ - .pointer = true, - .keyboard = self.keyboards.len > 0, - }); -} - -fn addKeyboard(self: *Self, device: *wlr.InputDevice) !void { - const node = try util.gpa.create(std.TailQueue(Keyboard).Node); - node.data.init(self, device) catch |err| { - const log_keyboard = std.log.scoped(.keyboard); - switch (err) { - error.XkbContextFailed => log_keyboard.err("Failed to create XKB context", .{}), - error.XkbKeymapFailed => log_keyboard.err("Failed to create XKB keymap", .{}), - error.SetKeymapFailed => log_keyboard.err("Failed to set wlr keyboard keymap", .{}), - } - return; +pub fn addDevice(self: *Self, wlr_device: *wlr.InputDevice) void { + self.tryAddDevice(wlr_device) catch |err| switch (err) { + error.OutOfMemory => log.err("out of memory", .{}), + error.XkbContextFailed => log.err("failed to create xkbcommon context", .{}), + error.XkbKeymapFailed => log.err("failed to create xkbcommon keymap", .{}), + error.SetKeymapFailed => log.err("failed to set wlroots keymap", .{}), }; - self.keyboards.append(node); - self.wlr_seat.setKeyboard(device); } -fn addPointer(self: Self, device: *wlr.InputDevice) void { - // We don't do anything special with pointers. All of our pointer handling - // is proxied through wlr_cursor. On another compositor, you might take this - // opportunity to do libinput configuration on the device to set - // acceleration, etc. - self.cursor.wlr_cursor.attachInputDevice(device); +fn tryAddDevice(self: *Self, wlr_device: *wlr.InputDevice) !void { + switch (wlr_device.type) { + .keyboard => { + const keyboard = try util.gpa.create(Keyboard); + errdefer util.gpa.destroy(keyboard); + + try keyboard.init(self, wlr_device); + }, + .pointer => { + const device = try util.gpa.create(InputDevice); + errdefer util.gpa.destroy(device); + + try device.init(self, wlr_device); + + self.cursor.wlr_cursor.attachInputDevice(wlr_device); + }, + .switch_device => { + const switch_device = try util.gpa.create(Switch); + errdefer util.gpa.destroy(switch_device); + + try switch_device.init(self, wlr_device); + }, + + // TODO Support these types of input devices. + .touch, .tablet_tool, .tablet_pad => return, + } } -fn addSwitch(self: *Self, device: *wlr.InputDevice) !void { - const node = try util.gpa.create(std.TailQueue(Switch).Node); - node.data.init(self, device); - self.switches.append(node); +pub fn updateCapabilities(self: *Self) void { + // Currently a cursor is always drawn even if there are no pointer input devices. + // TODO Don't draw a cursor if there are no input devices. + var capabilities: wl.Seat.Capability = .{ .pointer = true }; + + var it = server.input_manager.devices.iterator(.forward); + while (it.next()) |device| { + if (device.seat == self) { + switch (device.wlr_device.type) { + .keyboard => capabilities.keyboard = true, + .pointer, .switch_device => {}, + .touch, .tablet_tool, .tablet_pad => unreachable, + } + } + } + + self.wlr_seat.setCapabilities(capabilities); } fn handleRequestSetSelection( diff --git a/river/Switch.zig b/river/Switch.zig index 7e41eb0..157e3bc 100644 --- a/river/Switch.zig +++ b/river/Switch.zig @@ -24,6 +24,7 @@ const server = &@import("main.zig").server; const util = @import("util.zig"); const Seat = @import("Seat.zig"); +const InputDevice = @import("InputDevice.zig"); const log = std.log.scoped(.switch_device); @@ -47,33 +48,32 @@ pub const TabletState = enum { on, }; -seat: *Seat, -input_device: *wlr.InputDevice, +device: InputDevice, -switch_device: wl.Listener(*wlr.Switch.event.Toggle) = wl.Listener(*wlr.Switch.event.Toggle).init(handleToggle), -destroy: wl.Listener(*wlr.InputDevice) = wl.Listener(*wlr.InputDevice).init(handleDestroy), +toggle: wl.Listener(*wlr.Switch.event.Toggle) = wl.Listener(*wlr.Switch.event.Toggle).init(handleToggle), -pub fn init(self: *Self, seat: *Seat, input_device: *wlr.InputDevice) void { +pub fn init(self: *Self, seat: *Seat, wlr_device: *wlr.InputDevice) !void { self.* = .{ - .seat = seat, - .input_device = input_device, + .device = undefined, }; + try self.device.init(seat, wlr_device); + errdefer self.device.deinit(); - const wlr_switch = self.input_device.device.switch_device; - - wlr_switch.events.toggle.add(&self.switch_device); - self.input_device.events.destroy.add(&self.destroy); + wlr_device.device.switch_device.events.toggle.add(&self.toggle); } pub fn deinit(self: *Self) void { - self.destroy.link.remove(); + self.toggle.link.remove(); + + self.device.deinit(); + + self.* = undefined; } fn handleToggle(listener: *wl.Listener(*wlr.Switch.event.Toggle), event: *wlr.Switch.event.Toggle) void { - // This event is raised when the lid witch or the tablet mode switch is toggled. - const self = @fieldParentPtr(Self, "switch_device", listener); + const self = @fieldParentPtr(Self, "toggle", listener); - self.seat.handleActivity(); + self.device.seat.handleActivity(); var switch_type: Type = undefined; var switch_state: State = undefined; @@ -96,14 +96,5 @@ fn handleToggle(listener: *wl.Listener(*wlr.Switch.event.Toggle), event: *wlr.Sw }, } - self.seat.handleSwitchMapping(switch_type, switch_state); -} - -fn handleDestroy(listener: *wl.Listener(*wlr.InputDevice), _: *wlr.InputDevice) void { - const self = @fieldParentPtr(Self, "destroy", listener); - const node = @fieldParentPtr(std.TailQueue(Self).Node, "data", self); - - self.seat.switches.remove(node); - self.deinit(); - util.gpa.destroy(node); + self.device.seat.handleSwitchMapping(switch_type, switch_state); } diff --git a/river/command/input.zig b/river/command/input.zig index e85a661..7023c5a 100644 --- a/river/command/input.zig +++ b/river/command/input.zig @@ -38,10 +38,10 @@ pub fn listInputs( const writer = input_list.writer(); var prev = false; - var it = server.input_manager.input_devices.first; - while (it) |node| : (it = node.next) { - const configured = for (server.input_manager.input_configs.items) |*input_config| { - if (mem.eql(u8, input_config.identifier, node.data.identifier)) { + var it = server.input_manager.devices.iterator(.forward); + while (it.next()) |device| { + const configured = for (server.input_manager.configs.items) |*input_config| { + if (mem.eql(u8, input_config.identifier, device.identifier)) { break true; } } else false; @@ -49,9 +49,8 @@ pub fn listInputs( if (prev) try input_list.appendSlice("\n"); prev = true; - try writer.print("{s}\n\ttype: {s}\n\tconfigured: {s}\n", .{ - node.data.identifier, - @tagName(node.data.device.type), + try writer.print("{s}\n\tconfigured: {s}\n", .{ + device.identifier, configured, }); } @@ -69,7 +68,7 @@ pub fn listInputConfigs( var input_list = std.ArrayList(u8).init(util.gpa); const writer = input_list.writer(); - for (server.input_manager.input_configs.items) |*input_config, i| { + for (server.input_manager.configs.items) |*input_config, i| { if (i > 0) try input_list.appendSlice("\n"); try writer.print("{s}\n", .{input_config.identifier}); @@ -134,19 +133,19 @@ pub fn input( // Try to find an existing InputConfig with matching identifier, or create // a new one if none was found. var new = false; - const input_config = for (server.input_manager.input_configs.items) |*input_config| { + const input_config = for (server.input_manager.configs.items) |*input_config| { if (mem.eql(u8, input_config.identifier, args[1])) break input_config; } else blk: { - try server.input_manager.input_configs.ensureUnusedCapacity(1); - server.input_manager.input_configs.appendAssumeCapacity(.{ + try server.input_manager.configs.ensureUnusedCapacity(1); + server.input_manager.configs.appendAssumeCapacity(.{ .identifier = try util.gpa.dupe(u8, args[1]), }); new = true; - break :blk &server.input_manager.input_configs.items[server.input_manager.input_configs.items.len - 1]; + break :blk &server.input_manager.configs.items[server.input_manager.configs.items.len - 1]; }; errdefer { if (new) { - var cfg = server.input_manager.input_configs.pop(); + var cfg = server.input_manager.configs.pop(); cfg.deinit(); } } @@ -204,10 +203,10 @@ pub fn input( } // Update matching existing input devices. - var it = server.input_manager.input_devices.first; - while (it) |device_node| : (it = device_node.next) { - if (mem.eql(u8, device_node.data.identifier, args[1])) { - input_config.apply(&device_node.data); + var it = server.input_manager.devices.iterator(.forward); + while (it.next()) |device| { + if (mem.eql(u8, device.identifier, args[1])) { + input_config.apply(device); // We don't break here because it is common to have multiple input // devices with the same identifier. } diff --git a/river/command/set_repeat.zig b/river/command/set_repeat.zig index 819eafb..86f8730 100644 --- a/river/command/set_repeat.zig +++ b/river/command/set_repeat.zig @@ -23,7 +23,7 @@ const Seat = @import("../Seat.zig"); /// Set the repeat rate and delay for all keyboards. pub fn setRepeat( - seat: *Seat, + _: *Seat, args: []const [:0]const u8, _: *?[]const u8, ) Error!void { @@ -36,8 +36,10 @@ pub fn setRepeat( server.config.repeat_rate = rate; server.config.repeat_delay = delay; - var it = seat.keyboards.first; - while (it) |node| : (it = node.next) { - node.data.input_device.device.keyboard.setRepeatInfo(rate, delay); + var it = server.input_manager.devices.iterator(.forward); + while (it.next()) |device| { + if (device.wlr_device.type == .keyboard) { + device.wlr_device.device.keyboard.setRepeatInfo(rate, delay); + } } } |
