Skip to content
This repository was archived by the owner on Jan 30, 2025. It is now read-only.

Commit

Permalink
vm_tools: Add WeakResourcePtr type to sommelier
Browse files Browse the repository at this point in the history
Sommelier uses wl_resource_add_destroy_listener in its zwp_text_input,
wl_seat/wl_pointer/wl_touch support to maintain a weak pointer to
wayland objects. As the logic involved is a bit tricky, this CL moves it
into a new WeakResourcePtr class to make it easier for future clients to
implement similar behaviour and reduce code duplication.

For now we only move the text_input usage. The behaviour for the input
types is a bit more complex as we need to invoke more logic when the
observed object is destroyed. This will require adding a callback to the
WeakResourcePtr type, and will be done in a separate CL.

BUG=b:222629444
TEST=Manually test deleting surfaces associated with text_input objects
and ensure no crashes

Change-Id: Ie75505cdd65e3de5e1336eb840c103f7fa978e0a
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform2/+/3974507
Reviewed-by: Nic Hollingum <[email protected]>
Commit-Queue: Timothy Loh <[email protected]>
Reviewed-by: Lucy Qu <[email protected]>
Tested-by: Timothy Loh <[email protected]>
  • Loading branch information
tim-loh authored and Chromeos LUCI committed Nov 17, 2022
1 parent 5c7d40f commit d165b32
Show file tree
Hide file tree
Showing 2 changed files with 72 additions and 34 deletions.
41 changes: 7 additions & 34 deletions sommelier-text-input.cc
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

#include "sommelier.h" // NOLINT(build/include_directory)
#include "sommelier-transform.h" // NOLINT(build/include_directory)
#include "weak-resource-ptr.h" // NOLINT(build/include_directory)

#include <algorithm>
#include <assert.h>
Expand Down Expand Up @@ -35,12 +36,8 @@ struct sl_host_text_input {
struct sl_context* ctx;
struct wl_resource* resource;
struct zwp_text_input_v1* proxy;
struct sl_host_surface* active_surface;
struct wl_listener surface_destroy_listener;

void SetActiveSurface(sl_host_surface* surface);
void ClearActiveSurface();
static void SurfaceDestroyed(wl_listener* listener, void* data);
WeakResourcePtr<sl_host_surface> active_surface;
};
MAP_STRUCTS(zwp_text_input_v1, sl_host_text_input);

Expand All @@ -58,26 +55,6 @@ struct sl_host_extended_text_input {
};
MAP_STRUCTS(zcr_extended_text_input_v1, sl_host_extended_text_input);

void sl_host_text_input::SetActiveSurface(sl_host_surface* surface) {
ClearActiveSurface();
active_surface = surface;
wl_resource_add_destroy_listener(surface->resource,
&surface_destroy_listener);
}

void sl_host_text_input::ClearActiveSurface() {
active_surface = nullptr;
// Remove the listener
wl_list_remove(&surface_destroy_listener.link);
wl_list_init(&surface_destroy_listener.link);
}

void sl_host_text_input::SurfaceDestroyed(wl_listener* listener, void* data) {
struct sl_host_text_input* host;
host = wl_container_of(listener, host, surface_destroy_listener);
host->ClearActiveSurface();
}

static void sl_text_input_activate(wl_client* client,
wl_resource* resource,
wl_resource* seat,
Expand All @@ -89,7 +66,7 @@ static void sl_text_input_activate(wl_client* client,
struct sl_host_surface* host_surface =
static_cast<sl_host_surface*>(wl_resource_get_user_data(surface));

host->SetActiveSurface(host_surface);
host->active_surface = host_surface;
zwp_text_input_v1_activate(host->proxy, host_seat->proxy,
host_surface->proxy);
}
Expand All @@ -102,7 +79,7 @@ static void sl_text_input_deactivate(wl_client* client,
struct sl_host_seat* host_seat =
static_cast<sl_host_seat*>(wl_resource_get_user_data(seat));

host->ClearActiveSurface();
host->active_surface.Reset();

zwp_text_input_v1_deactivate(host->proxy, host_seat->proxy);
}
Expand All @@ -124,8 +101,8 @@ static void sl_text_input_set_cursor_rectangle(wl_client* client,
int32_t x2 = x + width;
int32_t y2 = y + height;

sl_transform_guest_to_host(host->ctx, host->active_surface, &x1, &y1);
sl_transform_guest_to_host(host->ctx, host->active_surface, &x2, &y2);
sl_transform_guest_to_host(host->ctx, host->active_surface.get(), &x1, &y1);
sl_transform_guest_to_host(host->ctx, host->active_surface.get(), &x2, &y2);

zwp_text_input_v1_set_cursor_rectangle(host->proxy, x1, y1, x2 - x1, y2 - y1);
}
Expand Down Expand Up @@ -307,10 +284,6 @@ static void sl_text_input_manager_create_text_input(
text_input_host->ctx = host->ctx;
text_input_host->proxy =
zwp_text_input_manager_v1_create_text_input(host->proxy);
text_input_host->active_surface = nullptr;
wl_list_init(&text_input_host->surface_destroy_listener.link);
text_input_host->surface_destroy_listener.notify =
sl_host_text_input::SurfaceDestroyed;
wl_resource_set_implementation(text_input_resource,
&sl_text_input_implementation, text_input_host,
sl_destroy_host_text_input);
Expand Down Expand Up @@ -545,7 +518,7 @@ static void sl_text_input_x11_activate(wl_client* client,
return;
sl_host_surface* host_surface = static_cast<sl_host_surface*>(
wl_resource_get_user_data(host_window_resource));
host_text_input->SetActiveSurface(host_surface);
host_text_input->active_surface = host_surface;
zwp_text_input_v1_activate(host_text_input->proxy, host_seat->proxy,
host_surface->proxy);
return;
Expand Down
65 changes: 65 additions & 0 deletions weak-resource-ptr.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
// Copyright 2022 The ChromiumOS Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef VM_TOOLS_SOMMELIER_WEAK_RESOURCE_PTR_H_
#define VM_TOOLS_SOMMELIER_WEAK_RESOURCE_PTR_H_

#include "sommelier.h" // NOLINT(build/include_directory)

#include <algorithm>
#include <functional>
#include <assert.h>
#include <stdlib.h>
#include <string.h>

// WeakResourcePtr is a weak pointer for a proxy object (sl_host_foo). It can
// be useful for objects with events like enter/leave, to keep track of an
// object provided in the enter event and ensure that it is not used if the
// client destroys it.
template <typename SlHostType>
class WeakResourcePtr {
public:
WeakResourcePtr() {
wl_list_init(&destroy_listener_.link);
destroy_listener_.notify = ResourceDestroyed;
}

~WeakResourcePtr() { wl_list_remove(&destroy_listener_.link); }

WeakResourcePtr& operator=(SlHostType* host) {
if (host == host_)
return *this;

Reset();
if (host) {
host_ = host;
wl_resource_add_destroy_listener(host_->resource, &destroy_listener_);
}
return *this;
}

operator bool() const { return host_; }
SlHostType* operator->() const { return host_; }
SlHostType* get() const { return host_; }

void Reset() {
host_ = nullptr;
// Remove the listener
wl_list_remove(&destroy_listener_.link);
wl_list_init(&destroy_listener_.link);
}

private:
SlHostType* host_ = nullptr;
// This is always in an initialized state
wl_listener destroy_listener_;

static void ResourceDestroyed(wl_listener* listener, void* data) {
WeakResourcePtr* ptr;
ptr = wl_container_of(listener, ptr, destroy_listener_);
ptr->Reset();
}
};

#endif // VM_TOOLS_SOMMELIER_WEAK_RESOURCE_PTR_H_

0 comments on commit d165b32

Please sign in to comment.