From b7d1242c61f0197aed3367bcd1699d3396d40653 Mon Sep 17 00:00:00 2001 From: Dustin Kaiser <8209087+mrnicegyu11@users.noreply.github.com> Date: Thu, 17 Apr 2025 21:57:47 +0200 Subject: [PATCH] fix(wayland): release portal input capture when EI_EVENT_DISCONNECT is encountered, refactoring See deskflow issue #8005. --- ...t_stuck_when_inputcapture_reconnect.bugfix | 1 + src/lib/platform/EiScreen.cpp | 24 ++++++++++++------- 2 files changed, 16 insertions(+), 9 deletions(-) create mode 100644 doc/newsfragments/fix_server_input_stuck_when_inputcapture_reconnect.bugfix diff --git a/doc/newsfragments/fix_server_input_stuck_when_inputcapture_reconnect.bugfix b/doc/newsfragments/fix_server_input_stuck_when_inputcapture_reconnect.bugfix new file mode 100644 index 00000000..858db93e --- /dev/null +++ b/doc/newsfragments/fix_server_input_stuck_when_inputcapture_reconnect.bugfix @@ -0,0 +1 @@ +Fix InputLeap server inputs stuck when EIS reconnect to client after invalid EIS protocol. diff --git a/src/lib/platform/EiScreen.cpp b/src/lib/platform/EiScreen.cpp index b320de85..51ff40ce 100644 --- a/src/lib/platform/EiScreen.cpp +++ b/src/lib/platform/EiScreen.cpp @@ -152,7 +152,7 @@ void EiScreen::cleanup_ei() ei_device_set_user_data(ei_abs_, nullptr); ei_abs_ = ei_device_unref(ei_abs_); } - ei_seat_unref(ei_seat_); + ei_seat_ = ei_seat_unref(ei_seat_); for (auto it = ei_devices_.begin(); it != ei_devices_.end(); it++) { free(ei_device_get_user_data(*it)); ei_device_set_user_data(*it, nullptr); @@ -738,7 +738,6 @@ void EiScreen::handle_portal_session_closed(const Event &event) void EiScreen::handle_system_event(const Event& sysevent) { std::lock_guard lock(mutex_); - bool disconnected = false; // Only one ei_dispatch per system event, see the comment in // EiEventQueueBuffer::addEvent @@ -786,10 +785,20 @@ void EiScreen::handle_system_event(const Event& sysevent) // We're using libei which emulates the various seat/device remove events // so by the time we get here our EiScreen should be in a neutral state. // - // We don't do anything here, we let the portal's Session.Closed signal - // handle the rest. - LOG_WARN("disconnected from EIS"); - disconnected = true; + // We must release the xdg-portal InputCapture in case it is still active + // so that the cursor is usable and not stuck on the InputLeap server. + LOG_WARN("disconnected from eis, will afterwards commence attempt to reconnect"); + if (is_primary_) { + LOG_DEBUG("re-allocating portal input capture connection and releasing active captures"); + if (portal_input_capture_) { + if (portal_input_capture_->is_active()) { + portal_input_capture_->release(); + } + delete portal_input_capture_; + portal_input_capture_ = new PortalInputCapture(this, this->events_); + } + } + this->handle_portal_session_closed(sysevent); break; case EI_EVENT_DEVICE_PAUSED: LOG_DEBUG("device %s is paused", ei_device_get_name(device)); @@ -843,9 +852,6 @@ void EiScreen::handle_system_event(const Event& sysevent) } ei_event_unref(event); } - - if (disconnected) - ei_ = ei_unref(ei_); } void EiScreen::updateButtons()