1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199
|
// Copyright 2019 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "components/exo/wayland/zwp_pointer_constraints.h"
#include <pointer-constraints-unstable-v1-server-protocol.h>
#include <wayland-server-core.h>
#include <wayland-server-protocol-core.h>
#include <cstdarg>
#include <memory>
#include "base/memory/raw_ptr.h"
#include "components/exo/pointer.h"
#include "components/exo/pointer_constraint_delegate.h"
#include "components/exo/wayland/server_util.h"
#include "third_party/skia/include/core/SkRegion.h"
namespace exo {
namespace wayland {
namespace {
// Implements a PointerConstraintDelegate in terms of the zwp_locked_pointer
// Wayland protocol.
//
// Lifetime note: The underlying Wayland protocol gives control over this
// object's lifetime to the client. However, it's possible that its
// dependencies could be destroyed prior to the client destroying it.
// At this point we consider the object "defunct" and its |surface_| member
// to be potentially dangling. |pointer_| is correctly nulled when appropriate.
class WaylandPointerConstraintDelegate : public PointerConstraintDelegate {
public:
WaylandPointerConstraintDelegate(wl_resource* constraint_resource,
Surface* surface,
Pointer* pointer,
SkRegion* region,
uint32_t lifetime)
: constraint_resource_(constraint_resource),
pointer_(pointer),
surface_(surface),
is_persistent_(lifetime ==
ZWP_POINTER_CONSTRAINTS_V1_LIFETIME_PERSISTENT) {
pointer->ConstrainPointer(this);
}
~WaylandPointerConstraintDelegate() override {
if (pointer_) {
pointer_->OnPointerConstraintDelegateDestroying(this);
pointer_ = nullptr;
}
}
// PointerConstraintDelegate::
void OnConstraintActivated() override { SendLocked(); }
void OnAlreadyConstrained() override {
wl_resource_post_error(
constraint_resource_.get(),
ZWP_POINTER_CONSTRAINTS_V1_ERROR_ALREADY_CONSTRAINED,
"A pointer constraint was already requested for this wl_pointer "
"on this wl_surface.");
}
void OnConstraintBroken() override { SendUnlocked(); }
bool IsPersistent() override { return is_persistent_; }
Surface* GetConstrainedSurface() override { return surface_; }
void OnDefunct() override { pointer_ = nullptr; }
private:
// Inform the client of the state of the lock.
void SendLocked() {
VLOG(1) << "send_locked(" << constraint_resource_ << ")";
zwp_locked_pointer_v1_send_locked(constraint_resource_);
}
void SendUnlocked() {
VLOG(1) << "send_unlocked(" << constraint_resource_ << ")";
zwp_locked_pointer_v1_send_unlocked(constraint_resource_);
}
const raw_ptr<wl_resource, ExperimentalAsh> constraint_resource_;
raw_ptr<Pointer, ExperimentalAsh> pointer_;
const raw_ptr<Surface, ExperimentalAsh> surface_;
bool is_persistent_;
};
////////////////////////////////////////////////////////////////////////////////
// zwp_locked_pointer
void locked_pointer_destroy(wl_client* client, wl_resource* resource) {
VLOG(1) << "locked_pointer_destroy(" << client << ", " << resource << ")";
wl_resource_destroy(resource);
}
void locked_pointer_set_cursor_position_hint(wl_client* client,
wl_resource* resource,
wl_fixed_t surface_x,
wl_fixed_t surface_y) {
// Not supported.
}
void locked_pointer_set_region(wl_client* client,
wl_resource* resource,
wl_resource* region_resource) {
// Not supported.
}
const struct zwp_locked_pointer_v1_interface locked_pointer_implementation = {
locked_pointer_destroy, locked_pointer_set_cursor_position_hint,
locked_pointer_set_region};
////////////////////////////////////////////////////////////////////////////////
// zwp_confined_pointer
void confined_pointer_destroy(wl_client* client, wl_resource* resource) {
wl_resource_destroy(resource);
}
void confined_pointer_set_region(wl_client* client,
wl_resource* resource,
wl_resource* region_resource) {
// Not supported.
}
const struct zwp_confined_pointer_v1_interface confined_pointer_implementation =
{
confined_pointer_destroy,
confined_pointer_set_region,
};
////////////////////////////////////////////////////////////////////////////////
// zwp_pointer_constraints
void pointer_constraints_destroy(wl_client* client, wl_resource* resource) {
VLOG(1) << "pointer_constraints_destroy(" << client << ", " << resource
<< ")";
wl_resource_destroy(resource);
}
void pointer_constraints_lock_pointer(wl_client* client,
wl_resource* resource,
uint32_t id,
wl_resource* surface_resource,
wl_resource* pointer_resource,
wl_resource* region_resource,
uint32_t lifetime) {
Surface* surface = GetUserDataAs<Surface>(surface_resource);
Pointer* pointer = GetUserDataAs<Pointer>(pointer_resource);
SkRegion* region =
region_resource ? GetUserDataAs<SkRegion>(region_resource) : nullptr;
VLOG(1) << "lock_pointer(" << client << ", " << resource << "; Surface "
<< surface << " @ window '"
<< (surface && surface->window() ? surface->window()->GetTitle()
: base::EmptyString16())
<< "', "
<< "Pointer " << pointer << ")";
wl_resource* locked_pointer_resource =
wl_resource_create(client, &zwp_locked_pointer_v1_interface, 1, id);
SetImplementation(
locked_pointer_resource, &locked_pointer_implementation,
std::make_unique<WaylandPointerConstraintDelegate>(
locked_pointer_resource, surface, pointer, region, lifetime));
}
void pointer_constraints_confine_pointer(wl_client* client,
wl_resource* resource,
uint32_t id,
wl_resource* surface_resource,
wl_resource* pointer_resource,
wl_resource* region_resource,
uint32_t lifetime) {
// Confined pointer is not currently supported.
wl_resource* confined_pointer_resource =
wl_resource_create(client, &zwp_confined_pointer_v1_interface, 1, id);
SetImplementation<int>(confined_pointer_resource,
&confined_pointer_implementation, nullptr);
}
const struct zwp_pointer_constraints_v1_interface
pointer_constraints_implementation = {pointer_constraints_destroy,
pointer_constraints_lock_pointer,
pointer_constraints_confine_pointer};
} // namespace
void bind_pointer_constraints(wl_client* client,
void* data,
uint32_t version,
uint32_t id) {
wl_resource* resource = wl_resource_create(
client, &zwp_pointer_constraints_v1_interface, version, id);
wl_resource_set_implementation(resource, &pointer_constraints_implementation,
data, nullptr);
}
} // namespace wayland
} // namespace exo
|