const std = @import("std"); const c = @cImport({ @cInclude("linux/input.h"); @cInclude("libevdev-1.0/libevdev/libevdev.h"); @cInclude("errno.h"); }); const CapsLockDown = c.input_event{ .type = c.EV_KEY, .code = c.KEY_CAPSLOCK, .value = 1, .time = undefined }; const CapsLockUp = c.input_event{ .type = c.EV_KEY, .code = c.KEY_CAPSLOCK, .value = 0, .time = undefined }; const EscDown = c.input_event{ .type = c.EV_KEY, .code = c.KEY_ESC, .value = 1, .time = undefined }; const EscUp = c.input_event{ .type = c.EV_KEY, .code = c.KEY_ESC, .value = 0, .time = undefined }; const LShiftDown = c.input_event{ .type = c.EV_KEY, .code = c.KEY_LEFTSHIFT, .value = 1, .time = undefined }; const LShiftUp = c.input_event{ .type = c.EV_KEY, .code = c.KEY_LEFTSHIFT, .value = 0, .time = undefined }; const RShiftDown = c.input_event{ .type = c.EV_KEY, .code = c.KEY_RIGHTSHIFT, .value = 1, .time = undefined }; const RShiftUp = c.input_event{ .type = c.EV_KEY, .code = c.KEY_RIGHTSHIFT, .value = 0, .time = undefined }; const Syn = c.input_event{ .type = c.EV_SYN, .code = c.SYN_REPORT, .value = 0, .time = undefined }; fn event_equal(e1: *const c.input_event, e2: *const c.input_event) bool { return (e1.*.type == e2.*.type) and (e1.*.code == e2.*.code) and (e1.*.value == e2.*.value); } //fn event_read(event: *c.input_event) !void { // event.* = try std.io.getStdIn().reader().readStruct(@TypeOf(event.*)); //} fn event_write(event: *const c.input_event) !void { try std.io.getStdOut().writer().writeStruct(event.*); } fn write_esc() !void { std.time.sleep(20000); try event_write(&EscDown); try event_write(&Syn); std.time.sleep(20000); try event_write(&EscUp); } fn device_open() !void {} pub fn main() !void { var gpa = std.heap.GeneralPurposeAllocator(.{}){}; const allocator = gpa.allocator(); defer _ = gpa.deinit(); const args = try std.process.argsAlloc(allocator); if (args.len != 2) { std.debug.print("error: expected one argument", .{}); std.os.exit(1); } const dev_name = args[1]; var dev_fd = try std.fs.openFileAbsolute(dev_name, .{}); const dev = c.libevdev_new(); if (c.libevdev_set_fd(dev, dev_fd.handle) < 0) { std.debug.print("evdev: failed creating device from descriptor", .{}); std.os.exit(1); } if (c.libevdev_grab(dev, c.LIBEVDEV_GRAB) < 0) { std.debug.print("evdev: failed grabbing device", .{}); std.os.exit(1); } var write_esc_lshift: bool = undefined; var write_esc_rshift: bool = undefined; var is_lshift_down: bool = false; var is_rshift_down: bool = false; outer: while (true) { var event: c.input_event = undefined; var rc = c.libevdev_next_event(dev, c.LIBEVDEV_READ_FLAG_NORMAL | c.LIBEVDEV_READ_FLAG_BLOCKING, @ptrCast(&event)); while (rc == c.LIBEVDEV_READ_STATUS_SYNC) { rc = c.libevdev_next_event(dev, c.LIBEVDEV_READ_FLAG_SYNC, @ptrCast(&event)); } if (rc == -c.EAGAIN) { continue :outer; } if (rc != c.LIBEVDEV_READ_STATUS_SUCCESS) { break :outer; } if (event.type == c.EV_MSC and event.type == c.MSC_SCAN) { continue :outer; } if (event.type != c.EV_KEY) { try event_write(&event); continue :outer; } write_esc_lshift = event_equal(&event, &LShiftUp) and is_lshift_down; write_esc_rshift = event_equal(&event, &RShiftUp) and is_rshift_down; is_lshift_down = event_equal(&event, &LShiftDown); is_rshift_down = event_equal(&event, &RShiftDown); if (event_equal(&event, &CapsLockUp) or event_equal(&event, &CapsLockDown)) { event.code = c.KEY_LEFTMETA; } try event_write(&event); if (write_esc_lshift) { write_esc_lshift = false; try write_esc(); } if (write_esc_rshift) { write_esc_rshift = false; try write_esc(); } } }