Skip to content

Commit

Permalink
Merge pull request input-leap#1705 from whot/wip/remote-desktop-resto…
Browse files Browse the repository at this point in the history
…re-session

ei: try to restore RemoteDesktop sessions when we lose them
  • Loading branch information
p12tic authored Feb 22, 2024
2 parents 809bb1d + 650ce40 commit a228ba8
Show file tree
Hide file tree
Showing 7 changed files with 146 additions and 110 deletions.
14 changes: 7 additions & 7 deletions .github/workflows/builds.yml
Original file line number Diff line number Diff line change
Expand Up @@ -103,26 +103,26 @@ jobs:
submodules: recursive
set-safe-directory: ${{ github.workspace }}

- name: Get libei v1.0.0 from freedesktop
# Manual checkout of libinput/libei ref 1.0.0 from https://gitlab.freedesktop.org
- name: Get libei v1.2.1 from freedesktop
# Manual checkout of libinput/libei ref 1.2.1 from https://gitlab.freedesktop.org
# because actions/checkout does not support gitlab
if: matrix.wayland
run: |
git clone --depth=1 --branch="$ref" --recurse-submodules -- \
"https://gitlab.freedesktop.org/libinput/libei" libei
env:
ref: 1.0.0
ref: 1.2.1

- name: Get libportal from whot/libportal
- name: Get libportal from upstream
uses: actions/checkout@v4
if: matrix.wayland
with:
repository: whot/libportal
ref: wip/inputcapture
repository: flatpak/libportal
ref: main
path: libportal

- if: matrix.wayland
name: build libei from git tag (1.0.0)
name: build libei from git tag
run: |
meson setup -Dprefix=/usr -Dtests=disabled -Dliboeffis=disabled -Ddocumentation=[] libei _libei_builddir
ninja -C _libei_builddir install
Expand Down
5 changes: 5 additions & 0 deletions src/lib/base/EventTypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,11 @@ enum class EventType : std::uint32_t {
*/
EI_SCREEN_CONNECTED_TO_EIS,

/** This event is sent whenever the portal session managing our EIS connection
is closed.
*/
EI_SESSION_CLOSED,

/// This event is sent whenever a server accepts a client.
CLIENT_LISTENER_ACCEPTED,

Expand Down
6 changes: 1 addition & 5 deletions src/lib/platform/EiKeyState.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,14 +42,10 @@ EiKeyState::EiKeyState(EiScreen* screen, IEventQueue* events) :

void EiKeyState::init_default_keymap()
{
const struct xkb_rule_names names = {
nullptr, nullptr, nullptr, nullptr, nullptr // Use libxkbcommon compile-time defaults/env vars
};

if (xkb_keymap_) {
xkb_keymap_unref(xkb_keymap_);
}
xkb_keymap_ = xkb_keymap_new_from_names(xkb_, &names, XKB_KEYMAP_COMPILE_NO_FLAGS);
xkb_keymap_ = xkb_keymap_new_from_names(xkb_, nullptr, XKB_KEYMAP_COMPILE_NO_FLAGS);

if (xkb_state_) {
xkb_state_unref(xkb_state_);
Expand Down
119 changes: 78 additions & 41 deletions src/lib/platform/EiScreen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,15 +47,7 @@ EiScreen::EiScreen(bool is_primary, IEventQueue* events, bool use_portal) :
events_(events),
is_on_screen_(is_primary)
{
if (is_primary)
ei_ = ei_new_receiver(nullptr); // we receive from the display server
else
ei_ = ei_new_sender(nullptr); // we send to the display server
ei_set_user_data(ei_, this);
ei_log_set_priority(ei_, EI_LOG_PRIORITY_DEBUG);
ei_log_set_handler(ei_, cb_handle_ei_log_event);
ei_configure_name(ei_, "InputLeap client");

init_ei();
key_state_ = new EiKeyState(this, events);
// install event handlers
events_->add_handler(EventType::SYSTEM, events_->getSystemTarget(),
Expand All @@ -71,48 +63,28 @@ EiScreen::EiScreen(bool is_primary, IEventQueue* events, bool use_portal) :
throw std::invalid_argument("Missing libportal InputCapture portal support");
#endif
} else {
events_->add_handler(EventType::EI_SESSION_CLOSED, get_event_target(),
[this](const auto& e){ handle_portal_session_closed(e); });
portal_remote_desktop_ = new PortalRemoteDesktop(this, events_);
}
} else {
// Note: socket backend does not support reconnections
auto rc = ei_setup_backend_socket(ei_, nullptr);
if (rc != 0) {
LOG_DEBUG("ei init error: %s", strerror(-rc));
throw std::runtime_error("Failed to init ei context");
}
}

// install the platform event queue
events_->set_buffer(std::make_unique<EiEventQueueBuffer>(this, ei_, events_));
}

EiScreen::~EiScreen()
{
events_->set_buffer(nullptr);
events_->remove_handler(EventType::SYSTEM, events_->getSystemTarget());

if (ei_pointer_) {
free(ei_device_get_user_data(ei_pointer_));
ei_device_set_user_data(ei_pointer_, nullptr);
ei_device_unref(ei_pointer_);
}
if (ei_keyboard_) {
free(ei_device_get_user_data(ei_keyboard_));
ei_device_set_user_data(ei_keyboard_, nullptr);
ei_device_unref(ei_keyboard_);
}
if (ei_abs_) {
free(ei_device_get_user_data(ei_abs_));
ei_device_set_user_data(ei_abs_, nullptr);
ei_device_unref(ei_abs_);
}
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);
ei_device_unref(*it);
}
ei_devices_.clear();
ei_unref(ei_);
cleanup_ei();

delete key_state_;

delete portal_remote_desktop_;
#if HAVE_LIBPORTAL_INPUTCAPTURE
Expand Down Expand Up @@ -144,6 +116,50 @@ void EiScreen::handle_ei_log_event(ei* ei,
}
}

void EiScreen::init_ei()
{
if (is_primary_) {
ei_ = ei_new_receiver(nullptr); // we receive from the display server
} else {
ei_ = ei_new_sender(nullptr); // we send to the display server
}
ei_set_user_data(ei_, this);
ei_log_set_priority(ei_, EI_LOG_PRIORITY_DEBUG);
ei_log_set_handler(ei_, cb_handle_ei_log_event);
ei_configure_name(ei_, "InputLeap client");

// install the platform event queue
events_->set_buffer(nullptr);
events_->set_buffer(std::make_unique<EiEventQueueBuffer>(this, ei_, events_));
}

void EiScreen::cleanup_ei()
{
if (ei_pointer_) {
free(ei_device_get_user_data(ei_pointer_));
ei_device_set_user_data(ei_pointer_, nullptr);
ei_pointer_ = ei_device_unref(ei_pointer_);
}
if (ei_keyboard_) {
free(ei_device_get_user_data(ei_keyboard_));
ei_device_set_user_data(ei_keyboard_, nullptr);
ei_keyboard_ = ei_device_unref(ei_keyboard_);
}
if (ei_abs_) {
free(ei_device_get_user_data(ei_abs_));
ei_device_set_user_data(ei_abs_, nullptr);
ei_abs_ = ei_device_unref(ei_abs_);
}
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);
ei_device_unref(*it);
}
ei_devices_.clear();
ei_ = ei_unref(ei_);
}

const EventTarget* EiScreen::get_event_target() const
{
return this;
Expand Down Expand Up @@ -301,18 +317,17 @@ void EiScreen::disable()

void EiScreen::enter()
{
static int sequence_number;
is_on_screen_ = true;
if (!is_primary_) {
++sequence_number;
++sequence_number_;
if (ei_pointer_) {
ei_device_start_emulating(ei_pointer_, sequence_number);
ei_device_start_emulating(ei_pointer_, sequence_number_);
}
if (ei_keyboard_) {
ei_device_start_emulating(ei_keyboard_, sequence_number);
ei_device_start_emulating(ei_keyboard_, sequence_number_);
}
if (ei_abs_) {
ei_device_start_emulating(ei_abs_, sequence_number);
ei_device_start_emulating(ei_abs_, sequence_number_);
}
}
#if HAVE_LIBPORTAL_INPUTCAPTURE
Expand Down Expand Up @@ -687,9 +702,18 @@ void EiScreen::handle_connected_to_eis_event(const Event& event)
}
}

void EiScreen::handle_portal_session_closed(const Event &event)
{
// Portal may or may EI_EVENT_DISCONNECT us before sending the DBus Closed signal
// Let's clean up either way.
cleanup_ei();
init_ei();
}

void EiScreen::handle_system_event(const Event& sysevent)
{
std::lock_guard<std::mutex> lock(mutex_);
bool disconnected = false;

// Only one ei_dispatch per system event, see the comment in
// EiEventQueueBuffer::addEvent
Expand Down Expand Up @@ -734,12 +758,22 @@ void EiScreen::handle_system_event(const Event& sysevent)
}
break;
case EI_EVENT_DISCONNECT:
throw std::runtime_error("Oops, EIS didn't like us");
// 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;
break;
case EI_EVENT_DEVICE_PAUSED:
LOG_DEBUG("device %s is paused", ei_device_get_name(device));
break;
case EI_EVENT_DEVICE_RESUMED:
LOG_DEBUG("device %s is resumed", ei_device_get_name(device));
if (is_on_screen_) {
ei_device_start_emulating(device, ++sequence_number_);
}
break;
case EI_EVENT_KEYBOARD_MODIFIERS:
// FIXME
Expand Down Expand Up @@ -784,6 +818,9 @@ void EiScreen::handle_system_event(const Event& sysevent)
}
ei_event_unref(event);
}

if (disconnected)
ei_ = ei_unref(ei_);
}

void EiScreen::updateButtons()
Expand Down
9 changes: 7 additions & 2 deletions src/lib/platform/EiScreen.h
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ class EiScreen : public PlatformScreen {
// IPlatformScreen overrides
void handle_system_event(const Event& event) override;
void handle_connected_to_eis_event(const Event& event);
void handle_portal_session_closed(const Event &event);
void updateButtons() override;
IKeyState* getKeyState() const override;

Expand All @@ -99,6 +100,8 @@ class EiScreen : public PlatformScreen {
void remove_device(ei_device* device);

private:
void init_ei();
void cleanup_ei();
void send_event(EventType type, EventDataBase* data);
ButtonID map_button_from_evdev(ei_event* event) const;
void on_key_event(ei_event *event);
Expand Down Expand Up @@ -140,6 +143,8 @@ class EiScreen : public PlatformScreen {
ei_device* ei_keyboard_ = nullptr;
ei_device* ei_abs_ = nullptr;

std::uint32_t sequence_number_ = 0;

std::uint32_t x_ = 0;
std::uint32_t y_ = 0;
std::uint32_t w_ = 0;
Expand All @@ -154,9 +159,9 @@ class EiScreen : public PlatformScreen {

mutable std::mutex mutex_;

PortalRemoteDesktop* portal_remote_desktop_;
PortalRemoteDesktop* portal_remote_desktop_ = nullptr;
#if HAVE_LIBPORTAL_INPUTCAPTURE
PortalInputCapture* portal_input_capture_;
PortalInputCapture* portal_input_capture_ = nullptr;
#endif

struct HotKeyItem {
Expand Down
Loading

0 comments on commit a228ba8

Please sign in to comment.