Wayland compositor (wlroots)
git clone https://git.lucas.co/cce-compositor.git
InputDevice: don't advertise if virtual
Currently river incorrectly creates river_input_device_v1 objects
for virtual input devices when a river_input_manager_v1 is bound.
Fix this and add more asserts/cleanup.
river/InputDevice.zig | 16 +++++++++++-----
river/InputManager.zig | 6 +++++-
river/Keyboard.zig | 32 +++++++++++---------------------
river/LibinputDevice.zig | 1 +
4 files changed, 28 insertions(+), 27 deletions(-)
diff --git a/river/InputDevice.zig b/river/InputDevice.zig
index 758d086..0846b71 100644
--- a/river/InputDevice.zig
+++ b/river/InputDevice.zig
@@ -23,6 +23,7 @@ const log = std.log.scoped(.input);
seat: *Seat,
wlr_device: *wlr.InputDevice,
+virtual: bool,
objects: wl.list.Head(river.InputDeviceV1, null),
libinput: LibinputDevice,
@@ -47,6 +48,7 @@ pub fn init(
device.* = .{
.seat = seat,
.wlr_device = wlr_device,
+ .virtual = virtual,
.libinput = undefined,
.objects = undefined,
.link = undefined,
@@ -57,17 +59,20 @@ pub fn init(
wlr_device.data = device;
wlr_device.events.destroy.add(&device.remove);
- log.debug("new input device: {s}-{s}", .{
+ log.debug("new {s}input device: {s}-{s}", .{
+ if (virtual) "virtual " else "",
@tagName(wlr_device.type),
wlr_device.name orelse "unknown",
});
if (!virtual) {
var it = server.input_manager.objects.safeIterator(.forward);
- while (it.next()) |im_v1| device.createObject(im_v1);
- }
- if (wlr_device.getLibinputDevice()) |handle| {
- device.libinput.init(@ptrCast(handle));
+ while (it.next()) |im_v1| {
+ device.createObject(im_v1);
+ }
+ if (wlr_device.getLibinputDevice()) |handle| {
+ device.libinput.init(@ptrCast(handle));
+ }
}
// The wlroots Wayland and X11 backends support multiple outputs
@@ -91,6 +96,7 @@ pub fn init(
}
pub fn createObject(device: *InputDevice, im_v1: *river.InputManagerV1) void {
+ assert(!device.virtual);
const device_type: river.InputDeviceV1.Type = switch (device.wlr_device.type) {
.keyboard => .keyboard,
.pointer => .pointer,
diff --git a/river/InputManager.zig b/river/InputManager.zig
index e3a165b..c7852a1 100644
--- a/river/InputManager.zig
+++ b/river/InputManager.zig
@@ -115,7 +115,11 @@ fn bind(client: *wl.Client, im: *InputManager, version: u32, id: u32) void {
im.objects.append(im_v1);
{
var it = im.devices.iterator(.forward);
- while (it.next()) |device| device.createObject(im_v1);
+ while (it.next()) |device| {
+ if (!device.virtual) {
+ device.createObject(im_v1);
+ }
+ }
}
}
diff --git a/river/Keyboard.zig b/river/Keyboard.zig
index e857e7b..4c59d2c 100644
--- a/river/Keyboard.zig
+++ b/river/Keyboard.zig
@@ -37,7 +37,6 @@ device: InputDevice,
device_destroyed: bool = false,
queued_events: u32 = 0,
-virtual: bool,
config: Config,
/// Only null during initialization or due to allocation failure.
group: ?*KeyboardGroup = null,
@@ -53,7 +52,6 @@ pub fn create(seat: *Seat, wlr_device: *wlr.InputDevice, virtual: bool) !*Keyboa
errdefer util.gpa.destroy(keyboard);
keyboard.* = .{
- .virtual = virtual,
.config = .{
.keymap = if (virtual) wlr_keyboard.keymap else server.config.keymap,
},
@@ -74,35 +72,27 @@ pub fn create(seat: *Seat, wlr_device: *wlr.InputDevice, virtual: bool) !*Keyboa
pub fn setGroup(keyboard: *Keyboard) void {
assert(keyboard.group == null);
const seat = keyboard.device.seat;
- if (keyboard.virtual) {
- // Virtual keyboards set their own keymap and require independent modifier state.
- // Therefore, they are always placed in their own group of one.
- keyboard.group = KeyboardGroup.create(seat, keyboard.config, true) catch |err| switch (err) {
- error.OutOfMemory => blk: {
- log.err("out of memory", .{});
- break :blk null;
- },
- };
- } else {
+ // Virtual keyboards set their own keymap and require independent modifier state.
+ // Therefore, they are always placed in their own group of one.
+ if (!keyboard.device.virtual) {
var it = seat.keyboard_groups.iterator(.forward);
while (it.next()) |group| {
if (keyboard.config.eql(&group.config)) {
keyboard.group = group.ref();
- break;
+ return;
}
- } else {
- keyboard.group = KeyboardGroup.create(seat, keyboard.config, false) catch |err| switch (err) {
- error.OutOfMemory => blk: {
- log.err("out of memory", .{});
- break :blk null;
- },
- };
}
}
+ keyboard.group = KeyboardGroup.create(seat, keyboard.config, keyboard.device.virtual) catch |err| switch (err) {
+ error.OutOfMemory => {
+ log.err("out of memory", .{});
+ return;
+ },
+ };
}
pub fn setRepeatInfo(keyboard: *Keyboard, rate: u31, delay: u31) void {
- assert(!keyboard.virtual);
+ assert(!keyboard.device.virtual);
keyboard.config.repeat_rate = rate;
keyboard.config.repeat_delay = delay;
if (keyboard.group) |group| {
diff --git a/river/LibinputDevice.zig b/river/LibinputDevice.zig
index 2f4b9c4..a2a15ef 100644
--- a/river/LibinputDevice.zig
+++ b/river/LibinputDevice.zig
@@ -50,6 +50,7 @@ pub fn createObject(device: *LibinputDevice, config_v1: *river.LibinputConfigV1)
config_v1.sendLibinputDevice(object);
{
const base: *InputDevice = @fieldParentPtr("libinput", device);
+ assert(!base.virtual);
var it = base.objects.iterator(.forward);
while (it.next()) |input_device_v1| {
if (object.getClient() == input_device_v1.getClient()) {