diff options
Diffstat (limited to 'src/seat.zig')
| -rw-r--r-- | src/seat.zig | 71 |
1 files changed, 71 insertions, 0 deletions
diff --git a/src/seat.zig b/src/seat.zig new file mode 100644 index 0000000..7ec9b07 --- /dev/null +++ b/src/seat.zig @@ -0,0 +1,71 @@ +const std = @import("std"); +const c = @import("c.zig").c; + +// TODO: InputManager and multi-seat support +pub const Seat = struct { + server: *Server, + + wlr_seat: *c.wlr_seat, + listen_new_input: c.wl_listener, + + // Multiple mice are handled by the same Cursor + cursor: Cursor, + // Mulitple keyboards are handled separately + keyboards: std.ArrayList(Keyboard), + + pub fn init(server: *Server, allocator: *std.mem.Allocator) @This() { + var seat = @This(){ + .server = server, + // This seems to be the default seat name used by compositors + .wlr_seat = c.wlr_seat_create(server.*.wl_display, "seat0"), + .cursor = undefined, + .keyboards = std.ArrayList(Keyboard).init(allocator), + + .listen_new_input = c.wl_listener{ + .link = undefined, + .notify = handle_new_input, + }, + }; + + seat.cursor = cursor.Cursor.init(server); + + // Set up handler for all new input devices made available. This + // includes keyboards, pointers, touch, etc. + c.wl_signal_add(&server.*.backend.*.events.new_input, &seat.new_input); + } + + fn add_keyboard(self: *@This(), device: *c.wlr_input_device) void { + self.keyboards.append(Keyboard.init(self, device)); + c.wlr_seat_set_keyboard(self, device); + } + + fn add_pointer(self: *@This(), device: *c.struct_wlr_input_device) 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. + c.wlr_cursor_attach_input_device(self.cursor.wlr_cursor, device); + } + + fn handle_new_input(listener: [*c]c.wl_listener, data: ?*c_void) callconv(.C) void { + // This event is raised by the backend when a new input device becomes available. + var seat = @fieldParentPtr(Seat, "listen_new_input", listener); + var device = @ptrCast(*c.wlr_input_device, @alignCast(@alignOf(*c.wlr_input_device), data)); + + switch (device.*.type) { + .WLR_INPUT_DEVICE_KEYBOARD => seat.add_keyboard(device), + .WLR_INPUT_DEVICE_POINTER => seat.add_pointer(device), + else => {}, + } + + // We need to let the wlr_seat know what our capabilities are, which is + // communiciated to the client. In TinyWL we always have a cursor, even if + // there are no pointer devices, so we always include that capability. + var caps: u32 = @intCast(u32, c.WL_SEAT_CAPABILITY_POINTER); + // if list not empty + if (c.wl_list_empty(&server.*.keyboards) == 0) { + caps |= @intCast(u32, c.WL_SEAT_CAPABILITY_KEYBOARD); + } + c.wlr_seat_set_capabilities(server.*.seat, caps); + } +}; |
