diff --git a/src/lib/platform/EiScreen.cpp b/src/lib/platform/EiScreen.cpp index e4f38f986..cac1f5493 100644 --- a/src/lib/platform/EiScreen.cpp +++ b/src/lib/platform/EiScreen.cpp @@ -22,6 +22,7 @@ #include "platform/PortalRemoteDesktop.h" #include +#include #include #include #include @@ -261,9 +262,13 @@ std::int32_t EiScreen::getJumpZoneSize() const return 1; } -bool EiScreen::isAnyMouseButtonDown(uint32_t &) const +bool EiScreen::isAnyMouseButtonDown(uint32_t &buttonID) const { - return false; + if (m_buttons.none()) + return false; + + buttonID = std::countr_zero(m_buttons.to_ulong()); + return true; } void EiScreen::getCursorCenter(int32_t &x, int32_t &y) const @@ -424,6 +429,8 @@ void EiScreen::enter() } else if (m_isPrimary) { LOG_DEBUG("releasing input capture at x=%i y=%i", m_cursorX, m_cursorY); m_portalInputCapture->release(m_cursorX, m_cursorY); + // no more button events once capture is released, so drop any held state + updateButtons(); } } @@ -631,6 +638,8 @@ void EiScreen::removeDevice(struct ei_device *device) if (wasTracked) { m_isEmulating = false; cancelIdleEmulationTimer(); + // same as for a paused device: no release events follow a removal + updateButtons(); } delete static_cast(ei_device_get_user_data(device)); @@ -757,6 +766,8 @@ void EiScreen::onButtonEvent(ei_event *event) return; } + m_buttons.set(buttonID, pressed); + auto eventType = pressed ? EventTypes::PrimaryScreenButtonDown : EventTypes::PrimaryScreenButtonUp; sendEvent(eventType, ButtonInfo::alloc(buttonID, mask)); @@ -968,6 +979,9 @@ void EiScreen::handleSystemEvent(const Event &) case EI_EVENT_DEVICE_PAUSED: LOG_DEBUG("device %s is paused", ei_device_get_name(device)); m_isEmulating = false; + // a paused device is reset to neutral by the EIS side and sends no + // further events, so the releases for held buttons never arrive + updateButtons(); cancelIdleEmulationTimer(); break; case EI_EVENT_DEVICE_RESUMED: @@ -1026,7 +1040,9 @@ void EiScreen::handleSystemEvent(const Event &) void EiScreen::updateButtons() { // libei relies on the EIS implementation to keep our button count correct, - // so there's not much we need to/can do here. + // and the held buttons cannot be polled, so resyncing means assuming that + // everything is released. + m_buttons.reset(); } IKeyState *EiScreen::getKeyState() const diff --git a/src/lib/platform/EiScreen.h b/src/lib/platform/EiScreen.h index ab7b21cd4..4a33cab4c 100644 --- a/src/lib/platform/EiScreen.h +++ b/src/lib/platform/EiScreen.h @@ -11,6 +11,7 @@ #include "deskflow/PlatformScreen.h" #include "platform/XDGPowerManager.h" +#include #include #include #include @@ -144,6 +145,9 @@ private: KeyID m_lastPressed = kKeyNone; + // mouse buttons currently held, indexed by ButtonID + std::bitset m_buttons; + // clipboard stuff EiClipboard *m_clipboard = nullptr; size_t m_maximumClipboardSize = INT_MAX;