diff --git a/libs/rMlib/Input.cpp b/libs/rMlib/Input.cpp index 12f8b17..d40d206 100644 --- a/libs/rMlib/Input.cpp +++ b/libs/rMlib/Input.cpp @@ -279,8 +279,6 @@ handeDevice(InputManager& mgr, udev_device& dev) { } const auto* action = udev_device_get_action(&dev); - std::cout << "action: " << (action == nullptr ? "null" : action) << "\n"; - if (action == nullptr || action == std::string_view("add")) { mgr.open(devnode); return; @@ -351,6 +349,7 @@ InputManager::open(std::string_view input) { auto device = makeDevice( std::move(fd), std::move(dev), std::string(input), baseTransform); auto* devicePtr = device.get(); + std::cout << "Got device: " << device->getName() << "\n"; devices.emplace(devicePtr->path, std::move(device)); return devicePtr; } diff --git a/libs/rm2fb/InputDevice.cpp b/libs/rm2fb/InputDevice.cpp index 024bd1b..6e28e67 100644 --- a/libs/rm2fb/InputDevice.cpp +++ b/libs/rm2fb/InputDevice.cpp @@ -4,6 +4,11 @@ #include +namespace { +constexpr auto screen_width = 1404; +constexpr auto screen_height = 1872; +} // namespace + void UinputDeleter::operator()(libevdev_uinput* device) { libevdev_uinput_destroy(device); @@ -119,6 +124,8 @@ makeTouchDevice() { info.maximum = 255; libevdev_enable_event_code(dev, EV_ABS, ABS_MT_PRESSURE, &info); + libevdev_enable_property(dev, INPUT_PROP_DIRECT); + libevdev_uinput* uidev = nullptr; auto err = libevdev_uinput_create_from_device( dev, LIBEVDEV_UINPUT_OPEN_MANAGED, &uidev); @@ -139,7 +146,6 @@ makeButtonDevice() { libevdev_set_name(dev, "30371337.snvs:snvs-powerkey"); libevdev_enable_event_type(dev, EV_SYN); - libevdev_enable_event_type(dev, EV_KEY); libevdev_enable_event_code(dev, EV_KEY, KEY_POWER, nullptr); @@ -169,24 +175,61 @@ makeAllDevices() { } void -sendInput(const Input& input, libevdev_uinput& wacomDevice) { +sendPen(const Input& input, libevdev_uinput& wacomDevice) { constexpr auto wacom_width = 15725; constexpr auto wacom_height = 20967; - constexpr auto screen_width = 1404; - constexpr auto screen_height = 1872; - auto x = int(float(input.x) * wacom_width / screen_width); auto y = int(wacom_height - float(input.y) * wacom_height / screen_height); libevdev_uinput_write_event(&wacomDevice, EV_ABS, ABS_X, y); libevdev_uinput_write_event(&wacomDevice, EV_ABS, ABS_Y, x); - if (input.type != 0) { - const auto value = input.type == 1 ? 1 : 0; + if (input.type != Input::Move) { + const auto value = input.type == Input::Down ? 1 : 0; libevdev_uinput_write_event(&wacomDevice, EV_KEY, BTN_TOOL_PEN, value); libevdev_uinput_write_event(&wacomDevice, EV_KEY, BTN_TOUCH, value); } libevdev_uinput_write_event(&wacomDevice, EV_SYN, SYN_REPORT, 0); } + +void +sendTouch(const Input& input, libevdev_uinput& touchDevice) { + constexpr auto fake_slot = 1; + constexpr auto fake_id = 123; + + switch (input.type) { + case Input::Move: + break; + case Input::Down: + libevdev_uinput_write_event(&touchDevice, EV_ABS, ABS_MT_SLOT, fake_slot); + libevdev_uinput_write_event( + &touchDevice, EV_ABS, ABS_MT_TRACKING_ID, fake_id); + libevdev_uinput_write_event(&touchDevice, EV_ABS, ABS_MT_PRESSURE, 110); + libevdev_uinput_write_event(&touchDevice, EV_ABS, ABS_MT_TOUCH_MAJOR, 26); + libevdev_uinput_write_event(&touchDevice, EV_ABS, ABS_MT_TOUCH_MINOR, 26); + libevdev_uinput_write_event(&touchDevice, EV_ABS, ABS_MT_ORIENTATION, 4); + + break; + case Input::Up: + libevdev_uinput_write_event(&touchDevice, EV_ABS, ABS_MT_PRESSURE, 0); + libevdev_uinput_write_event(&touchDevice, EV_ABS, ABS_MT_TRACKING_ID, -1); + libevdev_uinput_write_event(&touchDevice, EV_ABS, ABS_MT_SLOT, 0); + break; + } + + libevdev_uinput_write_event(&touchDevice, EV_ABS, ABS_MT_POSITION_X, input.x); + libevdev_uinput_write_event( + &touchDevice, EV_ABS, ABS_MT_POSITION_Y, screen_height - input.y); + + libevdev_uinput_write_event(&touchDevice, EV_SYN, SYN_REPORT, 0); +} + +void +sendButton(bool down, libevdev_uinput& buttonDevice) { + const auto value = down ? 1 : 0; + libevdev_uinput_write_event(&buttonDevice, EV_KEY, KEY_POWER, value); + + libevdev_uinput_write_event(&buttonDevice, EV_SYN, SYN_REPORT, 0); +} diff --git a/libs/rm2fb/InputDevice.h b/libs/rm2fb/InputDevice.h index 5f83219..67bb7eb 100644 --- a/libs/rm2fb/InputDevice.h +++ b/libs/rm2fb/InputDevice.h @@ -30,4 +30,10 @@ AllUinputDevices makeAllDevices(); void -sendInput(const Input& input, libevdev_uinput& wacomDevice); +sendPen(const Input& input, libevdev_uinput& wacomDevice); + +void +sendTouch(const Input& input, libevdev_uinput& touchDevice); + +void +sendButton(bool down, libevdev_uinput& buttonDevice); diff --git a/libs/rm2fb/Message.h b/libs/rm2fb/Message.h index df8c7fb..804dab6 100644 --- a/libs/rm2fb/Message.h +++ b/libs/rm2fb/Message.h @@ -30,16 +30,21 @@ operator<<(std::ostream& stream, const UpdateParams& msg) { } struct Input { - int32_t x; - int32_t y; - int32_t type; // 1 = down, 2 = up + int32_t x = 0; + int32_t y = 0; + enum Action { Move, Down, Up } type = Move; + bool touch = false; // True for touch, false for pen }; -static_assert(sizeof(Input) == 3 * 4, "Input message has unexpected size"); +static_assert(sizeof(Input) == 4 * 4, "Input message has unexpected size"); struct GetUpdate {}; -using ClientMsg = std::variant; +struct PowerButton { + bool down; +}; + +using ClientMsg = std::variant; template unistdpp::Result diff --git a/libs/rm2fb/Server.cpp b/libs/rm2fb/Server.cpp index d71b21b..f41ff8a 100644 --- a/libs/rm2fb/Server.cpp +++ b/libs/rm2fb/Server.cpp @@ -172,6 +172,44 @@ readControlMessage(ControlSocket& serverSock, Fn&& fn) { }); } +void +handleMsg(const SharedFB& fb, + unistdpp::FD& fd, + const AllUinputDevices& devs, + GetUpdate msg) { + doTCPUpdate(fd, + fb, + { .y1 = 0, + .x1 = 0, + .y2 = fb_height - 1, + .x2 = fb_width - 1, + .flags = 0, + .waveform = 0 }); +} + +void +handleMsg(const SharedFB& fb, + unistdpp::FD& fd, + const AllUinputDevices& devs, + const Input& msg) { + if (!msg.touch && devs.wacom) { + sendPen(msg, *devs.wacom); + } + if (msg.touch && devs.touch) { + sendTouch(msg, *devs.touch); + } +} + +void +handleMsg(const SharedFB& fb, + unistdpp::FD& fd, + const AllUinputDevices& devs, + const PowerButton& msg) { + if (devs.button) { + sendButton(msg.down, *devs.button); + } +} + int serverMain(int argc, char* argv[], char** envp) { // NOLINT setupExitHandler(); @@ -183,13 +221,7 @@ serverMain(int argc, char* argv[], char** envp) { // NOLINT auto systemdSockets = getSystemdSockets(); // Make uinput devices - AllUinputDevices devices; - if (inQemu) { - devices = makeAllDevices(); - } else { - // Only make the wacom device, used for faking input from tcp clients. - devices.wacom = makeWacomDevice(); - } + auto devices = makeAllDevices(); auto serverSock = [&] { if (systemdSockets.controlSock.has_value()) { @@ -320,20 +352,8 @@ serverMain(int argc, char* argv[], char** envp) { // NOLINT auto& clientSock = tcpClients[idx - fixedFdNum]; recvMessage(clientSock) .map([&](const auto& msg) { - if (std::holds_alternative(msg)) { - doTCPUpdate(tcpClients.back(), - fb, - { .y1 = 0, - .x1 = 0, - .y2 = fb_height - 1, - .x2 = fb_width - 1, - .flags = 0, - .waveform = 0 }); - return; - } - if (devices.wacom) { - sendInput(std::get(msg), *devices.wacom); - } + std::visit([&](auto msg) { handleMsg(fb, clientSock, devices, msg); }, + msg); }) .or_else([&](auto err) { std::cerr << "Reading input: " << to_string(err) << "\n"; diff --git a/libs/unistdpp/include/unistdpp/error.h b/libs/unistdpp/include/unistdpp/error.h index 0aa3d0c..89e9d04 100644 --- a/libs/unistdpp/include/unistdpp/error.h +++ b/libs/unistdpp/include/unistdpp/error.h @@ -50,7 +50,7 @@ fatalOnError(const tl::expected& error, std::string_view msg = "") { if (!error.has_value()) { using namespace std; std::cerr << "FATAL: " << msg << to_string(error.error()) << std::endl; - std::abort(); + std::exit(EXIT_FAILURE); } return *error; @@ -62,7 +62,7 @@ fatalOnError(tl::expected&& error, std::string_view msg = "") { if (!error.has_value()) { using namespace std; std::cerr << "FATAL: " << msg << to_string(error.error()) << std::endl; - std::abort(); + std::exit(EXIT_FAILURE); } if constexpr (std::is_void_v) { diff --git a/tools/rm2fb-emu/rm2fb-emu.cpp b/tools/rm2fb-emu/rm2fb-emu.cpp index 2e22d61..17ab74c 100644 --- a/tools/rm2fb-emu/rm2fb-emu.cpp +++ b/tools/rm2fb-emu/rm2fb-emu.cpp @@ -27,15 +27,15 @@ using namespace rmlib::input; namespace { -int +Input::Action getType(const PenEvent& touchEv) { if (touchEv.isDown()) { - return 1; + return Input::Down; } if (touchEv.isUp()) { - return 2; + return Input::Up; } - return 0; + return Input::Move; } struct UpdateMsg { @@ -197,7 +197,8 @@ class Rm2fbState : public StateBase { std::cout << "Touch @ " << ev.location << "\n"; } - ClientMsg input = Input{ ev.location.x, ev.location.y, type }; + ClientMsg input = + Input{ ev.location.x, ev.location.y, type, /* touch */ true }; auto res = sendMessage(socket, input); if (!res) { std::cerr << "Error writing: " << to_string(res.error()) << "\n"; diff --git a/tools/rm2fb-emu/rm2fb-test.cpp b/tools/rm2fb-emu/rm2fb-test.cpp index f59e7d9..166924e 100644 --- a/tools/rm2fb-emu/rm2fb-test.cpp +++ b/tools/rm2fb-emu/rm2fb-test.cpp @@ -53,6 +53,25 @@ doScreenshot(unistdpp::FD& sock, std::vector args) { return true; } +bool +doInput(unistdpp::FD& sock, int x, int y, bool touch) { + auto input = Input{ + .x = x, + .y = y, + .type = Input::Down, + .touch = touch, + }; + + fatalOnError(sendMessage(sock, ClientMsg(input))); + usleep(tap_wait); + + input.type = Input::Up; + fatalOnError(sendMessage(sock, ClientMsg(input))); + usleep(tap_wait); + + return true; +} + bool doTouch(unistdpp::FD& sock, std::vector args) { if (args.size() != 2) { @@ -60,16 +79,27 @@ doTouch(unistdpp::FD& sock, std::vector args) { return false; } - auto input = Input{ - .x = atoi(args[0].data()), - .y = atoi(args[1].data()), - .type = 1, - }; + return doInput(sock, atoi(args[0].data()), atoi(args[1].data()), true); +} + +bool +doPen(unistdpp::FD& sock, std::vector args) { + if (args.size() != 2) { + std::cerr << "Touch requires 2 args, x and y\n"; + return false; + } + + return doInput(sock, atoi(args[0].data()), atoi(args[1].data()), false); +} + +bool +doPower(unistdpp::FD& sock, std::vector args) { + auto input = PowerButton{ .down = true }; fatalOnError(sendMessage(sock, ClientMsg(input))); usleep(tap_wait); - input.type = 2; + input.down = false; fatalOnError(sendMessage(sock, ClientMsg(input))); usleep(tap_wait); @@ -80,6 +110,8 @@ const std::unordered_map actions = { { { "screenshot", doScreenshot }, { "touch", doTouch }, + { "pen", doPen }, + { "power", doPower }, } }; } // namespace