diff --git a/src/core/PortalManager.cpp b/src/core/PortalManager.cpp index 5eccfbb..365b97a 100644 --- a/src/core/PortalManager.cpp +++ b/src/core/PortalManager.cpp @@ -3,7 +3,6 @@ #include "../helpers/MiscFunctions.hpp" #include -#include #include #include #include @@ -19,18 +18,18 @@ SOutput::SOutput(SP output_) : output(output_) { Debug::log(LOG, "Found output name {}", name); }); - output->setMode([this](CCWlOutput* r, uint32_t flags, int32_t width, int32_t height, int32_t refresh) { - refreshRate = refresh; - this->width = width; - this->height = height; + output->setMode([this](CCWlOutput* r, uint32_t flags, int32_t width_, int32_t height_, int32_t refresh) { + refreshRate = refresh; + width = width_; + height = height_; }); output->setGeometry( - [this](CCWlOutput* r, int32_t x, int32_t y, int32_t physical_width, int32_t physical_height, int32_t subpixel, const char* make, const char* model, int32_t transform_) { + [this](CCWlOutput* r, int32_t x_, int32_t y_, int32_t physical_width, int32_t physical_height, int32_t subpixel, const char* make, const char* model, int32_t transform_) { transform = (wl_output_transform)transform_; - this->x = x; - this->y = y; + x = x_; + y = y_; }); - output->setScale([this](CCWlOutput* r, uint32_t factor) { this->scale = factor; }); + output->setScale([this](CCWlOutput* r, uint32_t factor_) { scale = factor_; }); output->setDone([](CCWlOutput* r) { g_pPortalManager->m_sPortals.inputCapture->zonesChanged(); }); } @@ -277,32 +276,21 @@ void CPortalManager::init() { } void CPortalManager::startEventLoop() { + addFdToEventLoop(m_pConnection->getEventLoopPollData().fd, POLLIN, nullptr); + addFdToEventLoop(wl_display_get_fd(m_sWaylandConnection.display), POLLIN, nullptr); + addFdToEventLoop(pw_loop_get_fd(m_sPipewire.loop), POLLIN, nullptr); - pollfd pollfds[] = { - { - .fd = m_pConnection->getEventLoopPollData().fd, - .events = POLLIN, - }, - { - .fd = wl_display_get_fd(m_sWaylandConnection.display), - .events = POLLIN, - }, - { - .fd = pw_loop_get_fd(m_sPipewire.loop), - .events = POLLIN, - }, - }; - - std::thread pollThr([this, &pollfds]() { + std::thread pollThr([this]() { while (1) { - int ret = poll(pollfds, 3, 5000 /* 5 seconds, reasonable. It's because we might need to terminate */); + + int ret = poll(m_sEventLoopInternals.pollFds.data(), m_sEventLoopInternals.pollFds.size(), 5000 /* 5 seconds, reasonable. It's because we might need to terminate */); if (ret < 0) { Debug::log(CRIT, "[core] Polling fds failed with {}", strerror(errno)); g_pPortalManager->terminate(); } for (size_t i = 0; i < 3; ++i) { - if (pollfds[i].revents & POLLHUP) { + if (m_sEventLoopInternals.pollFds.data()->revents & POLLHUP) { Debug::log(CRIT, "[core] Disconnected from pollfd id {}", i); g_pPortalManager->terminate(); } @@ -375,13 +363,13 @@ void CPortalManager::startEventLoop() { m_mEventLock.lock(); - if (pollfds[0].revents & POLLIN /* dbus */) { - while (m_pConnection->processPendingEvent()) { + if (m_sEventLoopInternals.pollFds[0].revents & POLLIN /* dbus */) { + while (m_pConnection->processPendingRequest()) { ; } } - if (pollfds[1].revents & POLLIN /* wl */) { + if (m_sEventLoopInternals.pollFds[1].revents & POLLIN /* wl */) { wl_display_flush(m_sWaylandConnection.display); if (wl_display_prepare_read(m_sWaylandConnection.display) == 0) { wl_display_read_events(m_sWaylandConnection.display); @@ -391,12 +379,18 @@ void CPortalManager::startEventLoop() { } } - if (pollfds[2].revents & POLLIN /* pw */) { + if (m_sEventLoopInternals.pollFds[2].revents & POLLIN /* pw */) { while (pw_loop_iterate(m_sPipewire.loop, 0) != 0) { ; } } + for (pollfd p : m_sEventLoopInternals.pollFds) { + if (p.revents & POLLIN && m_sEventLoopInternals.pollCallbacks.contains(p.fd)) { + m_sEventLoopInternals.pollCallbacks[p.fd](); + } + } + std::vector toRemove; for (auto& t : m_sTimersThread.timers) { if (t->passed()) { @@ -500,6 +494,20 @@ void CPortalManager::addTimer(const CTimer& timer) { m_sTimersThread.loopSignal.notify_all(); } +void CPortalManager::addFdToEventLoop(int fd, short events, std::function callback) { + m_sEventLoopInternals.pollFds.emplace_back(pollfd{.fd = fd, .events = POLLIN}); + + if (callback == nullptr) + return; + + m_sEventLoopInternals.pollCallbacks[fd] = callback; +} + +void CPortalManager::removeFdFromEventLoop(int fd) { + std::erase_if(m_sEventLoopInternals.pollFds, [fd](const pollfd& p) { return p.fd == fd; }); + m_sEventLoopInternals.pollCallbacks.erase(fd); +} + void CPortalManager::terminate() { m_bTerminate = true; diff --git a/src/core/PortalManager.hpp b/src/core/PortalManager.hpp index a2c34e4..c10e121 100644 --- a/src/core/PortalManager.hpp +++ b/src/core/PortalManager.hpp @@ -12,6 +12,7 @@ #include "../helpers/Timer.hpp" #include "../shared/ToplevelManager.hpp" #include +#include #include #include "hyprland-toplevel-export-v1.hpp" @@ -34,9 +35,11 @@ struct SOutput { uint32_t id = 0; float refreshRate = 60.0; wl_output_transform transform = WL_OUTPUT_TRANSFORM_NORMAL; - uint32_t width, height; - int32_t x, y; - int32_t scale; + uint32_t width = 0; + uint32_t height = 0; + int32_t x = 0; + int32_t y = 0; + int32_t scale = 1; }; struct SDMABUFModifier { @@ -50,8 +53,8 @@ class CPortalManager { void init(); - void onGlobal(uint32_t name, const char* interface, uint32_t version); - void onGlobalRemoved(uint32_t name); + void onGlobal(uint32_t name, const char* interface, uint32_t version); + void onGlobalRemoved(uint32_t name); sdbus::IConnection* getConnection(); SOutput* getOutputFromName(const std::string& name); @@ -98,6 +101,9 @@ class CPortalManager { gbm_device* createGBMDevice(drmDevice* dev); + void addFdToEventLoop(int fd, short events, std::function callback); + void removeFdFromEventLoop(int fd); + // terminate after the event loop has been created. Before we can exit() void terminate(); @@ -108,10 +114,12 @@ class CPortalManager { pid_t m_iPID = 0; struct { - std::condition_variable loopSignal; - std::mutex loopMutex; - std::atomic shouldProcess = false; - std::mutex loopRequestMutex; + std::condition_variable loopSignal; + std::mutex loopMutex; + std::atomic shouldProcess = false; + std::mutex loopRequestMutex; + std::vector pollFds; + std::map> pollCallbacks; } m_sEventLoopInternals; struct { diff --git a/src/portals/InputCapture.cpp b/src/portals/InputCapture.cpp index 8dcd8ee..c3030b2 100644 --- a/src/portals/InputCapture.cpp +++ b/src/portals/InputCapture.cpp @@ -13,14 +13,11 @@ #include #include -CInputCapturePortal::CInputCapturePortal(SP mgr) { +CInputCapturePortal::CInputCapturePortal(SP mgr) : m_sState(mgr) { Debug::log(LOG, "[input-capture] initializing input capture portal"); - m_sState.manager = mgr; - sessionCounter = 0; - lastZoneSet = 0; - mgr->setAbsoluteMotion([this](CCHyprlandInputCaptureManagerV1* r, wl_fixed_t x, wl_fixed_t y, wl_fixed_t dx, wl_fixed_t dy) { - onAbsoluteMotion(wl_fixed_to_double(x), wl_fixed_to_double(y), wl_fixed_to_double(dx), wl_fixed_to_double(dy)); + mgr->setMotion([this](CCHyprlandInputCaptureManagerV1* r, wl_fixed_t x, wl_fixed_t y, wl_fixed_t dx, wl_fixed_t dy) { + onMotion(wl_fixed_to_double(x), wl_fixed_to_double(y), wl_fixed_to_double(dx), wl_fixed_to_double(dy)); }); mgr->setKey([this](CCHyprlandInputCaptureManagerV1* r, uint32_t key, hyprlandInputCaptureManagerV1KeyState state) { onKey(key, state); }); @@ -46,13 +43,12 @@ CInputCapturePortal::CInputCapturePortal(SP mgr m_pObject->registerMethod(INTERFACE_NAME, "ConnectToEIS", "osa{sv}", "h", [&](sdbus::MethodCall c) { onConnectToEIS(c); }); m_pObject->registerProperty(INTERFACE_NAME, "SupportedCapabilities", "u", [](sdbus::PropertyGetReply& reply) { reply << (uint)(1 | 2); }); - m_pObject->registerProperty(INTERFACE_NAME, "version", "u", [](sdbus::PropertyGetReply& reply) { reply << (uint)1; }); + m_pObject->registerProperty(INTERFACE_NAME, "version", "u", [](sdbus::PropertyGetReply& reply) { reply << (uint32_t)1; }); m_pObject->finishRegistration(); - for (auto& o : g_pPortalManager->getAllOutputs()) { + for (auto& o : g_pPortalManager->getAllOutputs()) Debug::log(LOG, "{} {}x{}", o->name, o->width, o->height); - } Debug::log(LOG, "[input-capture] init successful"); } @@ -91,22 +87,20 @@ void CInputCapturePortal::onCreateSession(sdbus::MethodCall& call) { std::string sessionId = "input-capture-" + std::to_string(sessionCounter++); Debug::log(LOG, "[input-capture] | sessionId : {}", sessionId); - const std::shared_ptr session = std::make_shared(); + const std::shared_ptr session = std::make_shared(); session->appid = appID; session->requestHandle = requestHandle; session->sessionHandle = sessionHandle; session->sessionId = sessionId; session->capabilities = capabilities; - session->activationId = 0; - session->status = CREATED; session->session = createDBusSession(sessionHandle); session->session->onDestroy = [session, this]() { - if (session->status == ACTIVATED) { - disable(session->sessionHandle); - } + disable(session->sessionHandle); + session->eis->stopServer(); + session->eis = nullptr; Debug::log(LOG, "[input-capture] Session {} destroyed", session->sessionHandle.c_str()); session->session.release(); @@ -351,64 +345,56 @@ bool get_line_intersection(double p0_x, double p0_y, double p1_x, double p1_y, d return 0; // No collision } -bool testCollision(Barrier barrier, double px, double py, double nx, double ny) { +bool testCollision(SBarrier barrier, double px, double py, double nx, double ny) { return get_line_intersection(barrier.x1, barrier.y1, barrier.x2, barrier.y2, px, py, nx, ny, nullptr, nullptr); } -uint32_t CInputCapturePortal::Session::isColliding(double px, double py, double nx, double ny) { - for (const auto& [key, value] : barriers) { - if (testCollision(value, px, py, nx, ny)) { +uint32_t CInputCapturePortal::SSession::isColliding(double px, double py, double nx, double ny) { + for (const auto& [key, value] : barriers) + if (testCollision(value, px, py, nx, ny)) return key; - } - } return 0; } -void CInputCapturePortal::onAbsoluteMotion(double x, double y, double dx, double dy) { +void CInputCapturePortal::onMotion(double x, double y, double dx, double dy) { for (const auto& [key, session] : sessions) { int matched = session->isColliding(x, y, x - dx, y - dy); - if (matched != 0) { + if (matched != 0) activate(key, x, y, matched); - } + session->motion(dx, dy); } } -void CInputCapturePortal::onKey(uint32_t key, bool pressed) { - for (const auto& [_, value] : sessions) { - value->key(key, pressed); - } +void CInputCapturePortal::onKey(uint32_t id, bool pressed) { + for (const auto& [key, value] : sessions) + value->key(id, pressed); } void CInputCapturePortal::onButton(uint32_t button, bool pressed) { - for (const auto& [_, session] : sessions) { + for (const auto& [key, session] : sessions) session->button(button, pressed); - } } void CInputCapturePortal::onAxis(bool axis, double value) { - for (const auto& [_, session] : sessions) { + for (const auto& [key, session] : sessions) session->axis(axis, value); - } } void CInputCapturePortal::onAxisValue120(bool axis, int32_t value120) { - for (const auto& [_, session] : sessions) { + for (const auto& [key, session] : sessions) session->axisValue120(axis, value120); - } } void CInputCapturePortal::onAxisStop(bool axis) { - for (const auto& [_, session] : sessions) { + for (const auto& [_, session] : sessions) session->axisStop(axis); - } } void CInputCapturePortal::onFrame() { - for (const auto& [_, session] : sessions) { + for (const auto& [_, session] : sessions) session->frame(); - } } void CInputCapturePortal::activate(sdbus::ObjectPath sessionHandle, double x, double y, uint32_t borderId) { @@ -435,7 +421,7 @@ void CInputCapturePortal::activate(sdbus::ObjectPath sessionHandle, double x, do m_pObject->emitSignal(signal); } -bool CInputCapturePortal::Session::activate(double x, double y, uint32_t borderId) { +bool CInputCapturePortal::SSession::activate(double x, double y, uint32_t borderId) { if (status != ENABLED) { return false; } @@ -467,10 +453,9 @@ void CInputCapturePortal::deactivate(sdbus::ObjectPath sessionHandle) { m_pObject->emitSignal(signal); } -bool CInputCapturePortal::Session::deactivate() { - if (status != ACTIVATED) { +bool CInputCapturePortal::SSession::deactivate() { + if (status != ACTIVATED) return false; - } Debug::log(LOG, "[input-capture] Input released for {}", sessionHandle.c_str()); eis->stopEmulating(); @@ -500,7 +485,7 @@ void CInputCapturePortal::zonesChanged() { } } -bool CInputCapturePortal::Session::zoneChanged() { +bool CInputCapturePortal::SSession::zoneChanged() { //TODO: notify EIS return true; } @@ -510,12 +495,13 @@ void CInputCapturePortal::disable(sdbus::ObjectPath sessionHandle) { return; auto session = sessions[sessionHandle]; - if (!session->disable()) - return; if (session->status == ACTIVATED) deactivate(sessionHandle); + if (!session->disable()) + return; + auto signal = m_pObject->createSignal(INTERFACE_NAME, "Disable"); signal << sessionHandle; @@ -525,70 +511,74 @@ void CInputCapturePortal::disable(sdbus::ObjectPath sessionHandle) { m_pObject->emitSignal(signal); } -bool CInputCapturePortal::Session::disable() { +bool CInputCapturePortal::SSession::disable() { status = STOPPED; Debug::log(LOG, "[input-capture] Session {} disabled", sessionHandle.c_str()); return true; } -void CInputCapturePortal::Session::motion(double dx, double dy) { +void CInputCapturePortal::SSession::motion(double dx, double dy) { if (status != ACTIVATED) return; eis->sendMotion(dx, dy); } -void CInputCapturePortal::Session::key(uint32_t key, bool pressed) { +void CInputCapturePortal::SSession::key(uint32_t key, bool pressed) { if (status != ACTIVATED) return; eis->sendKey(key, pressed); } -void CInputCapturePortal::Session::button(uint32_t button, bool pressed) { +void CInputCapturePortal::SSession::button(uint32_t button, bool pressed) { if (status != ACTIVATED) return; eis->sendButton(button, pressed); } -void CInputCapturePortal::Session::axis(bool axis, double value) { +void CInputCapturePortal::SSession::axis(bool axis, double value) { if (status != ACTIVATED) return; double x = 0; double y = 0; - if (axis) { + if (axis) x = value; - } else { + else y = value; - } eis->sendScrollDelta(x, y); } -void CInputCapturePortal::Session::axisValue120(bool axis, int32_t value) { +void CInputCapturePortal::SSession::axisValue120(bool axis, int32_t value) { if (status != ACTIVATED) return; int32_t x = 0; int32_t y = 0; - if (axis) { + if (axis) x = value; - } else { + else y = value; - } eis->sendScrollDiscrete(x, y); } -void CInputCapturePortal::Session::axisStop(bool axis) { +void CInputCapturePortal::SSession::axisStop(bool axis) { + if (status != ACTIVATED) + return; + eis->sendScrollStop(axis, !axis); } -void CInputCapturePortal::Session::frame() { +void CInputCapturePortal::SSession::frame() { + if (status != ACTIVATED) + return; + eis->sendPointerFrame(); } diff --git a/src/portals/InputCapture.hpp b/src/portals/InputCapture.hpp index 5e7a880..31e5c80 100644 --- a/src/portals/InputCapture.hpp +++ b/src/portals/InputCapture.hpp @@ -5,13 +5,14 @@ #include "../shared/Session.hpp" #include -typedef int ClientStatus; -const ClientStatus CREATED = 0; //Is ready to be activated -const ClientStatus ENABLED = 1; //Is ready for receiving inputs -const ClientStatus ACTIVATED = 2; //Currently receiving inputs -const ClientStatus STOPPED = 3; //Can no longer be activated +enum ClientStatus { + CREATED, //Is ready to be activated + ENABLED, //Is ready for receiving inputs + ACTIVATED, //Currently receiving inputs + STOPPED //Can no longer be activated +}; -struct Barrier { +struct SBarrier { uint id; int x1, y1, x2, y2; }; @@ -28,7 +29,7 @@ class CInputCapturePortal { void onRelease(sdbus::MethodCall& methodCall); void onConnectToEIS(sdbus::MethodCall& methodCall); - void onAbsoluteMotion(double x, double y, double dx, double dy); + void onMotion(double x, double y, double dx, double dy); void onKey(uint32_t key, bool pressed); void onButton(uint32_t button, bool pressed); void onAxis(bool axis, double value); @@ -38,19 +39,19 @@ class CInputCapturePortal { void zonesChanged(); - struct Session { - std::string appid; - sdbus::ObjectPath requestHandle, sessionHandle; - std::string sessionId; - uint32_t capabilities; + struct SSession { + std::string appid; + sdbus::ObjectPath requestHandle, sessionHandle; + std::string sessionId; + uint32_t capabilities = 0; - std::unique_ptr request; - std::unique_ptr session; - std::unique_ptr eis; + std::unique_ptr request; + std::unique_ptr session; + std::unique_ptr eis; - std::unordered_map barriers; - uint32_t activationId; - ClientStatus status; + std::unordered_map barriers; + uint32_t activationId = 0; + ClientStatus status = CREATED; // bool activate(double x, double y, uint32_t borderId); @@ -74,11 +75,11 @@ class CInputCapturePortal { SP manager; } m_sState; - std::unordered_map> sessions; + std::unordered_map> sessions; // std::unique_ptr m_pObject; - uint sessionCounter; - uint lastZoneSet; + uint sessionCounter = 0; + uint lastZoneSet = 0; const std::string INTERFACE_NAME = "org.freedesktop.impl.portal.InputCapture"; const std::string OBJECT_PATH = "/org/freedesktop/portal/desktop"; diff --git a/src/shared/Eis.cpp b/src/shared/Eis.cpp index b950de9..46fbd93 100644 --- a/src/shared/Eis.cpp +++ b/src/shared/Eis.cpp @@ -2,11 +2,9 @@ #include "../core/PortalManager.hpp" #include "src/helpers/Log.hpp" #include -#include -#include EmulatedInputServer::EmulatedInputServer(std::string socketName) { - Debug::log(LOG, "[EIS] init socket: {}", socketName); + Debug::log(LOG, "[EIS] Init socket: {}", socketName); const char* xdg = getenv("XDG_RUNTIME_DIR"); if (xdg) @@ -17,95 +15,80 @@ EmulatedInputServer::EmulatedInputServer(std::string socketName) { return; } - client.handle = NULL; - client.seat = NULL; - client.pointer = NULL; - client.keyboard = NULL; - eis = eis_new(NULL); + eisCtx = eis_new(nullptr); - if (eis_setup_backend_socket(eis, socketPath.c_str())) { + if (eis_setup_backend_socket(eisCtx, socketPath.c_str())) { Debug::log(ERR, "[EIS] Cannot init eis socket on {}", socketPath); return; } Debug::log(LOG, "[EIS] Listening on {}", socketPath); - stop = false; - std::thread thread(&EmulatedInputServer::listen, this); - thread.detach(); + g_pPortalManager->addFdToEventLoop(eis_get_fd(eisCtx), POLLIN, std::bind(&EmulatedInputServer::pollEvents, this)); } -void EmulatedInputServer::listen() { - struct pollfd fds = { - .fd = eis_get_fd(eis), - .events = POLLIN, - .revents = 0, - }; - int nevents; - //Pull foverer events - while (!stop && (nevents = poll(&fds, 1, 1000)) > -1) { - eis_dispatch(eis); +void EmulatedInputServer::pollEvents() { + eis_dispatch(eisCtx); - //Pull every availaible events - while (true) { - eis_event* e = eis_get_event(eis); + //Pull every availaible events + while (true) { + eis_event* e = eis_get_event(eisCtx); - if (!e) { - eis_event_unref(e); - break; - } - - int rc = onEvent(e); + if (!e) { eis_event_unref(e); - if (rc != 0) - break; + break; } + + int rc = onEvent(e); + eis_event_unref(e); + if (rc != 0) + break; } } int EmulatedInputServer::onEvent(eis_event* e) { - eis_client* client; - eis_seat* seat; - eis_device* device; + eis_client* eisClient = nullptr; + eis_seat* seat = nullptr; + eis_device* device = nullptr; switch (eis_event_get_type(e)) { case EIS_EVENT_CLIENT_CONNECT: - client = eis_event_get_client(e); - Debug::log(LOG, "[EIS] {} client connected: {}", eis_client_is_sender(client) ? "sender" : "receiver", eis_client_get_name(client)); + eisClient = eis_event_get_client(e); + Debug::log(LOG, "[EIS] {} client connected: {}", eis_client_is_sender(eisClient) ? "Sender" : "Receiver", eis_client_get_name(eisClient)); - if (eis_client_is_sender(client)) { - Debug::log(WARN, "[EIS] Unexpected sender client {} connected to input capture session", eis_client_get_name(client)); - eis_client_disconnect(client); + if (eis_client_is_sender(eisClient)) { + Debug::log(WARN, "[EIS] Unexpected sender client {} connected to input capture session", eis_client_get_name(eisClient)); + eis_client_disconnect(eisClient); return 0; } - if (this->client.handle != nullptr) { - Debug::log(WARN, "[EIS] Unexpected additional client {} connected to input capture session", eis_client_get_name(client)); - eis_client_disconnect(client); + if (client.handle) { + Debug::log(WARN, "[EIS] Unexpected additional client {} connected to input capture session", eis_client_get_name(eisClient)); + eis_client_disconnect(eisClient); return 0; } - this->client.handle = client; + client.handle = eisClient; - eis_client_connect(client); - Debug::log(LOG, "[EIS] creating new default seat"); - seat = eis_client_new_seat(client, "default"); + eis_client_connect(eisClient); + Debug::log(LOG, "[EIS] Creating new default seat"); + seat = eis_client_new_seat(eisClient, "default"); eis_seat_configure_capability(seat, EIS_DEVICE_CAP_POINTER); eis_seat_configure_capability(seat, EIS_DEVICE_CAP_BUTTON); eis_seat_configure_capability(seat, EIS_DEVICE_CAP_SCROLL); eis_seat_configure_capability(seat, EIS_DEVICE_CAP_KEYBOARD); eis_seat_add(seat); - this->client.seat = seat; + client.seat = seat; break; case EIS_EVENT_CLIENT_DISCONNECT: - client = eis_event_get_client(e); - Debug::log(LOG, "[EIS] {} disconnected", eis_client_get_name(client)); - eis_client_disconnect(client); + eisClient = eis_event_get_client(e); + Debug::log(LOG, "[EIS] {} disconnected", eis_client_get_name(eisClient)); + eis_client_disconnect(eisClient); - eis_seat_unref(this->client.seat); + eis_seat_unref(client.seat); clearPointer(); clearKeyboard(); - this->client.handle = NULL; + client.handle = nullptr; break; case EIS_EVENT_SEAT_BIND: Debug::log(LOG, "[EIS] Binding seats..."); @@ -123,45 +106,31 @@ int EmulatedInputServer::onEvent(eis_event* e) { break; case EIS_EVENT_DEVICE_CLOSED: device = eis_event_get_device(e); - if (device == this->client.pointer) { + if (device == client.pointer) clearPointer(); - } else if (device == this->client.keyboard) { + else if (device == client.keyboard) { Debug::log(LOG, "[EIS] Clearing keyboard"); clearKeyboard(); - } else { + } else Debug::log(WARN, "[EIS] Unknown device to close"); - } break; - case EIS_EVENT_FRAME: Debug::log(LOG, "[EIS] Got event EIS_EVENT_FRAME"); break; - case EIS_EVENT_DEVICE_START_EMULATING: Debug::log(LOG, "[EIS] Got event EIS_EVENT_DEVICE_START_EMULATING"); break; - case EIS_EVENT_DEVICE_STOP_EMULATING: Debug::log(LOG, "[EIS] Got event EIS_EVENT_DEVICE_STOP_EMULATING"); break; - case EIS_EVENT_POINTER_MOTION: Debug::log(LOG, "[EIS] Got event EIS_EVENT_POINTER_MOTION"); break; - case EIS_EVENT_POINTER_MOTION_ABSOLUTE: Debug::log(LOG, "[EIS] Got event EIS_EVENT_POINTER_MOTION_ABSOLUTE"); break; - case EIS_EVENT_BUTTON_BUTTON: Debug::log(LOG, "[EIS] Got event EIS_EVENT_BUTTON_BUTTON"); break; - case EIS_EVENT_SCROLL_DELTA: Debug::log(LOG, "[EIS] Got event EIS_EVENT_SCROLL_DELTA"); break; - case EIS_EVENT_SCROLL_STOP: Debug::log(LOG, "[EIS] Got event EIS_EVENT_SCROLL_STOP"); break; - case EIS_EVENT_SCROLL_CANCEL: Debug::log(LOG, "[EIS] Got event EIS_EVENT_SCROLL_CANCEL"); break; - case EIS_EVENT_SCROLL_DISCRETE: Debug::log(LOG, "[EIS] Got event EIS_EVENT_SCROLL_DISCRETE"); break; - case EIS_EVENT_KEYBOARD_KEY: Debug::log(LOG, "[EIS] Got event EIS_EVENT_KEYBOARD_KEY"); break; - case EIS_EVENT_TOUCH_DOWN: Debug::log(LOG, "[EIS] Got event EIS_EVENT_TOUCH_DOWN"); break; - case EIS_EVENT_TOUCH_UP: Debug::log(LOG, "[EIS] Got event EIS_EVENT_TOUCH_UP"); break; - case EIS_EVENT_TOUCH_MOTION: Debug::log(LOG, "[EIS] Got event EIS_EVENT_TOUCH_MOTION"); break; + default: return 0; } return 0; } void EmulatedInputServer::ensurePointer(eis_event* event) { - if (client.pointer != nullptr) + if (client.pointer) return; - struct eis_device* pointer = eis_seat_new_device(client.seat); + eis_device* pointer = eis_seat_new_device(client.seat); eis_device_configure_name(pointer, "captured relative pointer"); eis_device_configure_capability(pointer, EIS_DEVICE_CAP_POINTER); eis_device_configure_capability(pointer, EIS_DEVICE_CAP_BUTTON); eis_device_configure_capability(pointer, EIS_DEVICE_CAP_SCROLL); for (auto& o : g_pPortalManager->getAllOutputs()) { - struct eis_region* r = eis_device_new_region(pointer); + eis_region* r = eis_device_new_region(pointer); eis_region_set_offset(r, o->x, o->y); eis_region_set_size(r, o->width, o->height); @@ -177,10 +146,10 @@ void EmulatedInputServer::ensurePointer(eis_event* event) { } void EmulatedInputServer::ensureKeyboard(eis_event* event) { - if (client.keyboard != nullptr) + if (client.keyboard) return; - struct eis_device* keyboard = eis_seat_new_device(client.seat); + eis_device* keyboard = eis_seat_new_device(client.seat); eis_device_configure_name(keyboard, "captured keyboard"); eis_device_configure_capability(keyboard, EIS_DEVICE_CAP_KEYBOARD); // TODO: layout @@ -193,7 +162,7 @@ void EmulatedInputServer::ensureKeyboard(eis_event* event) { //TODO: remove and re-add devices when monitors change (see: mutter/meta-input-capture-session.c:1107) void EmulatedInputServer::clearPointer() { - if (client.pointer == nullptr) + if (!client.pointer) return; Debug::log(LOG, "[EIS] Clearing pointer"); @@ -203,7 +172,7 @@ void EmulatedInputServer::clearPointer() { } void EmulatedInputServer::clearKeyboard() { - if (client.keyboard == nullptr) + if (!client.keyboard) return; Debug::log(LOG, "[EIS] Clearing keyboard"); @@ -213,74 +182,77 @@ void EmulatedInputServer::clearKeyboard() { } int EmulatedInputServer::getFileDescriptor() { - return eis_backend_fd_add_client(eis); + return eis_backend_fd_add_client(eisCtx); } void EmulatedInputServer::startEmulating(int sequence) { Debug::log(LOG, "[EIS] Start Emulating"); - if (client.pointer != nullptr) + if (client.pointer) eis_device_start_emulating(client.pointer, sequence); - if (client.keyboard != nullptr) + if (client.keyboard) eis_device_start_emulating(client.keyboard, sequence); } void EmulatedInputServer::stopEmulating() { Debug::log(LOG, "[EIS] Stop Emulating"); - if (client.pointer != nullptr) + if (client.pointer) eis_device_stop_emulating(client.pointer); - if (client.keyboard != nullptr) + if (client.keyboard) eis_device_stop_emulating(client.keyboard); } void EmulatedInputServer::sendMotion(double x, double y) { - if (client.pointer == nullptr) + if (!client.pointer) return; eis_device_pointer_motion(client.pointer, x, y); } void EmulatedInputServer::sendKey(uint32_t key, bool pressed) { - if (client.keyboard == nullptr) + if (!client.keyboard) return; - uint64_t now = eis_now(eis); + uint64_t now = eis_now(eisCtx); eis_device_keyboard_key(client.keyboard, key, pressed); eis_device_frame(client.keyboard, now); } void EmulatedInputServer::sendButton(uint32_t button, bool pressed) { - if (client.pointer == nullptr) + if (!client.pointer) return; eis_device_button_button(client.pointer, button, pressed); } void EmulatedInputServer::sendScrollDiscrete(int32_t x, int32_t y) { - if (client.pointer == nullptr) + if (!client.pointer) return; eis_device_scroll_discrete(client.pointer, x, y); } void EmulatedInputServer::sendScrollDelta(double x, double y) { - if (client.pointer == nullptr) + if (!client.pointer) return; eis_device_scroll_delta(client.pointer, x, y); } void EmulatedInputServer::sendScrollStop(bool x, bool y) { - if (client.pointer == nullptr) + if (!client.pointer) return; eis_device_scroll_stop(client.pointer, x, y); } void EmulatedInputServer::sendPointerFrame() { - if (client.pointer == nullptr) + if (!client.pointer) return; - uint64_t now = eis_now(eis); + uint64_t now = eis_now(eisCtx); eis_device_frame(client.pointer, now); } void EmulatedInputServer::stopServer() { - stop = true; + g_pPortalManager->removeFdFromEventLoop(eis_get_fd(eisCtx)); + Debug::log(LOG, "[EIS] Server fd {} destroyed", eis_get_fd(eisCtx)); + eis_unref(eisCtx); + eisCtx = nullptr; } diff --git a/src/shared/Eis.hpp b/src/shared/Eis.hpp index 9c35bbd..2df8946 100644 --- a/src/shared/Eis.hpp +++ b/src/shared/Eis.hpp @@ -3,14 +3,6 @@ #include #include -struct EisClient { - struct eis_client* handle; - struct eis_seat* seat; - - struct eis_device* pointer; - struct eis_device* keyboard; -}; - /* * Responsible to creating a socket for input communication */ @@ -35,14 +27,21 @@ class EmulatedInputServer { void stopServer(); private: - bool stop; - struct eis* eis; - EisClient client; + bool stop = false; + eis* eisCtx = nullptr; - int onEvent(eis_event* e); - void listen(); - void ensurePointer(eis_event* event); - void ensureKeyboard(eis_event* event); - void clearPointer(); - void clearKeyboard(); + struct Client { + eis_client* handle = nullptr; + eis_seat* seat = nullptr; + + eis_device* pointer = nullptr; + eis_device* keyboard = nullptr; + } client; + + int onEvent(eis_event* e); + void pollEvents(); + void ensurePointer(eis_event* event); + void ensureKeyboard(eis_event* event); + void clearPointer(); + void clearKeyboard(); }; diff --git a/subprojects/hyprland-protocols b/subprojects/hyprland-protocols index 53a994b..479cc22 160000 --- a/subprojects/hyprland-protocols +++ b/subprojects/hyprland-protocols @@ -1 +1 @@ -Subproject commit 53a994b2efbcc19862125fc9a8d5a752a24a0f20 +Subproject commit 479cc226451c264396a4c442710d6b56dce2fa46