1 /*
2 SPDX-FileCopyrightText: 2020 Adrien Faveraux <af@brain-networks.fr>
3 SPDX-FileCopyrightText: 2021 Francesco Sorrentino <francesco.sorr@gmail.com>
4
5 SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only
6 */
7 #include "client.h"
8 #include "primary_selection_p.h"
9 #include "seat_p.h"
10 #include "selection_device_p.h"
11 #include "selection_offer_p.h"
12 #include "selection_source_p.h"
13
14 #include <unistd.h>
15
16 namespace Wrapland::Server
17 {
18
19 const struct zwp_primary_selection_device_v1_interface PrimarySelectionDevice::Private::s_interface
20 = {
21 set_selection_callback<Wayland::Resource<PrimarySelectionDevice>>,
22 destroyCallback,
23 };
24
Private(Client * client,uint32_t version,uint32_t id,Seat * seat,PrimarySelectionDevice * qptr)25 PrimarySelectionDevice::Private::Private(Client* client,
26 uint32_t version,
27 uint32_t id,
28 Seat* seat,
29 PrimarySelectionDevice* qptr)
30 : Wayland::Resource<PrimarySelectionDevice>(client,
31 version,
32 id,
33 &zwp_primary_selection_device_v1_interface,
34 &s_interface,
35 qptr)
36 , m_seat(seat)
37 {
38 }
39
40 PrimarySelectionDevice::Private::~Private() = default;
41
sendSelection(PrimarySelectionDevice * device)42 void PrimarySelectionDevice::sendSelection(PrimarySelectionDevice* device)
43 {
44 auto deviceSelection = device->selection();
45 if (!deviceSelection) {
46 sendClearSelection();
47 return;
48 }
49
50 auto offer = d_ptr->sendDataOffer(deviceSelection);
51 if (!offer) {
52 return;
53 }
54
55 d_ptr->send<zwp_primary_selection_device_v1_send_selection>(offer->d_ptr->resource());
56 }
57
sendClearSelection()58 void PrimarySelectionDevice::sendClearSelection()
59 {
60 d_ptr->send<zwp_primary_selection_device_v1_send_selection>(nullptr);
61 }
62
63 PrimarySelectionOffer*
sendDataOffer(PrimarySelectionSource * source)64 PrimarySelectionDevice::Private::sendDataOffer(PrimarySelectionSource* source)
65 {
66 if (!source) {
67 // A data offer can only exist together with a source.
68 return nullptr;
69 }
70
71 auto offer = new PrimarySelectionOffer(client()->handle(), version(), source);
72
73 if (!offer->d_ptr->resource()) {
74 delete offer;
75 return nullptr;
76 }
77
78 send<zwp_primary_selection_device_v1_send_data_offer>(offer->d_ptr->resource());
79 offer->sendOffer();
80 return offer;
81 }
82
PrimarySelectionDevice(Client * client,uint32_t version,uint32_t id,Seat * seat)83 PrimarySelectionDevice::PrimarySelectionDevice(Client* client,
84 uint32_t version,
85 uint32_t id,
86 Seat* seat)
87 : d_ptr(new Private(client, version, id, seat, this))
88 {
89 }
90
91 PrimarySelectionDevice::~PrimarySelectionDevice() = default;
92
selection()93 PrimarySelectionSource* PrimarySelectionDevice::selection()
94 {
95 return d_ptr->selection;
96 }
97
client() const98 Client* PrimarySelectionDevice::client() const
99 {
100 return d_ptr->client()->handle();
101 }
102
seat() const103 Seat* PrimarySelectionDevice::seat() const
104 {
105 return d_ptr->m_seat;
106 }
107
108 const struct zwp_primary_selection_offer_v1_interface PrimarySelectionOffer::Private::s_interface
109 = {
110 receive_selection_offer<Wayland::Resource<PrimarySelectionOffer>>,
111 destroyCallback,
112 };
113
Private(Client * client,uint32_t version,PrimarySelectionSource * source,PrimarySelectionOffer * qptr)114 PrimarySelectionOffer::Private::Private(Client* client,
115 uint32_t version,
116 PrimarySelectionSource* source,
117 PrimarySelectionOffer* qptr)
118 : Wayland::Resource<PrimarySelectionOffer>(client,
119 version,
120 0,
121 &zwp_primary_selection_offer_v1_interface,
122 &s_interface,
123 qptr)
124 , source(source)
125 {
126 }
127
128 PrimarySelectionOffer::Private::~Private() = default;
129
PrimarySelectionOffer(Client * client,uint32_t version,PrimarySelectionSource * source)130 PrimarySelectionOffer::PrimarySelectionOffer(Client* client,
131 uint32_t version,
132 PrimarySelectionSource* source)
133 : d_ptr(new Private(client, version, source, this))
134 {
135 assert(source);
136 QObject::connect(source,
137 &PrimarySelectionSource::mimeTypeOffered,
138 this,
139 [this](std::string const& mimeType) {
140 d_ptr->send<zwp_primary_selection_offer_v1_send_offer>(mimeType.c_str());
141 });
142 QObject::connect(source, &PrimarySelectionSource::resourceDestroyed, this, [this] {
143 d_ptr->source = nullptr;
144 });
145 }
146
147 PrimarySelectionOffer::~PrimarySelectionOffer() = default;
148
sendOffer()149 void PrimarySelectionOffer::sendOffer()
150 {
151 for (auto const& mimeType : d_ptr->source->mimeTypes()) {
152 d_ptr->send<zwp_primary_selection_offer_v1_send_offer>(mimeType.c_str());
153 }
154 }
155
156 const struct zwp_primary_selection_source_v1_interface PrimarySelectionSource::Private::s_interface
157 = {
158 add_offered_mime_type<Wayland::Resource<PrimarySelectionSource>>,
159 destroyCallback,
160 };
161
Private(Client * client,uint32_t version,uint32_t id,PrimarySelectionSource * qptr)162 PrimarySelectionSource::Private::Private(Client* client,
163 uint32_t version,
164 uint32_t id,
165 PrimarySelectionSource* qptr)
166 : Wayland::Resource<PrimarySelectionSource>(client,
167 version,
168 id,
169 &zwp_primary_selection_source_v1_interface,
170 &s_interface,
171 qptr)
172 {
173 }
174
175 PrimarySelectionSource::Private::~Private() = default;
176
PrimarySelectionSource(Client * client,uint32_t version,uint32_t id)177 PrimarySelectionSource::PrimarySelectionSource(Client* client, uint32_t version, uint32_t id)
178 : d_ptr(new Private(client, version, id, this))
179 {
180 }
181
182 PrimarySelectionSource::~PrimarySelectionSource() = default;
183
mimeTypes()184 std::vector<std::string> PrimarySelectionSource::mimeTypes()
185 {
186 return d_ptr->mimeTypes;
187 }
188
cancel()189 void PrimarySelectionSource::cancel()
190 {
191 d_ptr->send<zwp_primary_selection_source_v1_send_cancelled>();
192 d_ptr->client()->flush();
193 }
requestData(std::string const & mimeType,qint32 fd)194 void PrimarySelectionSource::requestData(std::string const& mimeType, qint32 fd)
195 {
196 d_ptr->send<zwp_primary_selection_source_v1_send_send>(mimeType.c_str(), fd);
197 close(fd);
198 }
client() const199 Client* PrimarySelectionSource::client() const
200 {
201 return d_ptr->client()->handle();
202 }
203
204 }
205