2 * Copyright (c) 2023 Samsung Electronics Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
19 #include <dali/internal/clipboard/common/clipboard-impl.h>
22 #include <dali/devel-api/common/singleton-service.h>
23 #include <dali/internal/adaptor/tizen-wayland/dali-ecore-wl2.h>
24 #include <dali/integration-api/debug.h>
33 static Eina_Bool EcoreEventDataSend(void* data, int type, void* event);
34 static Eina_Bool EcoreEventOfferDataReady(void* data, int type, void* event);
36 struct Clipboard::Impl
40 mSendHandler = ecore_event_handler_add(ECORE_WL2_EVENT_DATA_SOURCE_SEND, EcoreEventDataSend, this);
41 mReceiveHandler = ecore_event_handler_add(ECORE_WL2_EVENT_OFFER_DATA_READY, EcoreEventOfferDataReady, this);
45 ecore_event_handler_del(mSendHandler);
46 ecore_event_handler_del(mReceiveHandler);
49 bool SetData(const Dali::Clipboard::ClipData& clipData)
51 mMimeType = clipData.GetMimeType();
52 mData = clipData.GetData();
56 DALI_LOG_ERROR("ClipData is empty, return false.\n");
60 const char* mimeTypes[2];
61 mimeTypes[0] = mMimeType.c_str();
62 mimeTypes[1] = nullptr;
64 Ecore_Wl2_Display* display = ecore_wl2_connected_display_get(NULL);
65 Ecore_Wl2_Input* input = ecore_wl2_input_default_input_get(display);
66 mSerial = ecore_wl2_dnd_selection_set(input, mimeTypes);
67 DALI_LOG_RELEASE_INFO("selection_set success, serial:%u, type:%s, data:%s\n", mSerial, mMimeType.c_str(), mData.c_str());
72 uint32_t GetData(const std::string &mimeType)
74 const char* type = mimeType.c_str();
77 DALI_LOG_ERROR("no request type, type is null.\n");
81 Ecore_Wl2_Display* display = ecore_wl2_connected_display_get(NULL);
82 Ecore_Wl2_Input* input = ecore_wl2_input_default_input_get(display);
83 Ecore_Wl2_Offer* offer = ecore_wl2_dnd_selection_get(input);
87 DALI_LOG_ERROR("selection_get fail, request type:%s\n", mimeType.c_str());
91 Eina_Array* availableTypes = ecore_wl2_offer_mimes_get(offer);
92 char* selectedType = nullptr;
93 unsigned int typeCount = (unsigned int)eina_array_count((Eina_Array *)availableTypes);
95 for(unsigned int i = 0; i < typeCount && !selectedType; ++i)
97 char* availableType = (char*)eina_array_data_get((Eina_Array *)availableTypes, i);
98 if(!mimeType.compare(availableType))
100 selectedType = availableType;
107 DALI_LOG_ERROR("no matching type, num of available types:%u, request type:%s\n", typeCount, mimeType.c_str());
108 for(unsigned int i = 0; i < typeCount && !selectedType; ++i)
110 DALI_LOG_ERROR("available type[%u]:%s\n", i, (char*)eina_array_data_get((Eina_Array *)availableTypes, i));
116 mDataRequestIds.push_back(mDataId);
117 mDataRequestItems[mDataId] = std::make_pair(mimeType, offer);
119 ecore_wl2_offer_receive(offer, const_cast<char*>(type));
120 ecore_wl2_display_flush(ecore_wl2_input_display_get(input));
121 DALI_LOG_RELEASE_INFO("offer_receive, id:%u, request type:%s\n", mDataId, mimeType.c_str());
125 void SendData(void* event)
127 Ecore_Wl2_Event_Data_Source_Send* ev = reinterpret_cast<Ecore_Wl2_Event_Data_Source_Send*>(event);
129 if(ev->serial != mSerial)
134 // no matching mime type.
135 if(mMimeType.compare(ev->type))
137 auto it = mDataRequestIds.begin();
138 while(it != mDataRequestIds.end())
140 uint32_t dataRequestId = *it;
141 auto item = mDataRequestItems.find(dataRequestId);
142 if(item != mDataRequestItems.end())
144 std::string mimeType = static_cast<std::string>(item->second.first);
145 if(!mimeType.compare(ev->type))
147 mDataRequestItems.erase(dataRequestId);
148 it = mDataRequestIds.erase(it);
149 DALI_LOG_ERROR("no matching type, empty signal emit, request type:%s, available type:%s\n", ev->type, mMimeType.c_str());
150 mDataReceivedSignal.Emit(dataRequestId, "", "");
161 size_t dataLength = strlen(mData.c_str());
162 size_t bufferSize = dataLength + 1u;
164 char* buffer = new char[bufferSize];
170 memcpy(buffer, mData.c_str(), dataLength);
171 buffer[dataLength] = '\0';
173 auto ret = write(ev->fd, buffer, bufferSize);
174 if(DALI_UNLIKELY(ret != static_cast<ssize_t>(bufferSize)))
176 DALI_LOG_ERROR("write(ev->fd) return %zd\n", ret);
182 DALI_LOG_RELEASE_INFO("send data, type:%s, data:%s \n", mMimeType.c_str(), mData.c_str());
183 mDataSentSignal.Emit(ev->type, mData.c_str());
186 void ReceiveData(void* event)
188 Ecore_Wl2_Event_Offer_Data_Ready* ev = reinterpret_cast<Ecore_Wl2_Event_Offer_Data_Ready*>(event);
190 size_t dataLength = strlen(ev->data);
191 size_t bufferSize = static_cast<size_t>(ev->len);
194 if(dataLength < bufferSize)
196 content.append(ev->data, dataLength);
200 content.append(ev->data, bufferSize);
203 DALI_LOG_RELEASE_INFO("receive data, type:%s, data:%s\n", ev->mimetype, content.c_str());
205 auto it = mDataRequestIds.begin();
206 while(it != mDataRequestIds.end())
208 uint32_t dataRequestId = *it;
209 auto item = mDataRequestItems.find(dataRequestId);
210 if(item != mDataRequestItems.end())
212 Ecore_Wl2_Offer* offer = static_cast<Ecore_Wl2_Offer*>(item->second.second);
213 if(offer == ev->offer)
215 std::string mimeType = static_cast<std::string>(item->second.first);
216 mDataRequestItems.erase(dataRequestId);
217 it = mDataRequestIds.erase(it);
218 DALI_LOG_RELEASE_INFO("receive data, success signal emit, id:%u, type:%s\n", dataRequestId, mimeType.c_str());
219 mDataReceivedSignal.Emit(dataRequestId, mimeType.c_str(), content.c_str());
229 uint32_t mSerial{0u};
230 std::string mMimeType;
232 Ecore_Event_Handler* mSendHandler{nullptr};
233 Ecore_Event_Handler* mReceiveHandler{nullptr};
235 Dali::Clipboard::DataSentSignalType mDataSentSignal;
236 Dali::Clipboard::DataReceivedSignalType mDataReceivedSignal;
239 std::vector<uint32_t> mDataRequestIds;
240 std::unordered_map<uint32_t, std::pair<std::string, Ecore_Wl2_Offer*>> mDataRequestItems;
243 static Eina_Bool EcoreEventDataSend(void* data, int type, void* event)
245 Clipboard::Impl* impl = reinterpret_cast<Clipboard::Impl*>(data);
246 impl->SendData(event);
248 return ECORE_CALLBACK_PASS_ON;
251 static Eina_Bool EcoreEventOfferDataReady(void* data, int type, void* event)
253 Clipboard::Impl* impl = reinterpret_cast<Clipboard::Impl*>(data);
254 impl->ReceiveData(event);
256 return ECORE_CALLBACK_PASS_ON;
259 Clipboard::Clipboard(Impl* impl)
264 Clipboard::~Clipboard()
269 Dali::Clipboard Clipboard::Get()
271 Dali::Clipboard clipboard;
273 Dali::SingletonService service(SingletonService::Get());
276 // Check whether the singleton is already created
277 Dali::BaseHandle handle = service.GetSingleton(typeid(Dali::Clipboard));
280 // If so, downcast the handle
281 clipboard = Dali::Clipboard(dynamic_cast<Clipboard*>(handle.GetObjectPtr()));
285 Clipboard::Impl* impl(new Clipboard::Impl());
286 clipboard = Dali::Clipboard(new Clipboard(impl));
287 service.Register(typeid(Dali::Clipboard), clipboard);
294 bool Clipboard::IsAvailable()
296 Dali::SingletonService service(SingletonService::Get());
299 Dali::BaseHandle handle = service.GetSingleton(typeid(Dali::Clipboard));
308 Dali::Clipboard::DataSentSignalType& Clipboard::DataSentSignal()
310 return mImpl->mDataSentSignal;
313 Dali::Clipboard::DataReceivedSignalType& Clipboard::DataReceivedSignal()
315 return mImpl->mDataReceivedSignal;
318 bool Clipboard::SetData(const Dali::Clipboard::ClipData& clipData)
320 return mImpl->SetData(clipData);
323 uint32_t Clipboard::GetData(const std::string &mimeType)
325 return mImpl->GetData(mimeType);
328 size_t Clipboard::NumberOfItems()
330 // TODO: We should to check if the data is empty in the clipboard service.
334 void Clipboard::ShowClipboard()
338 void Clipboard::HideClipboard(bool skipFirstHide)
342 bool Clipboard::IsVisible() const
347 bool Clipboard::OnReceiveData()
352 } // namespace Adaptor
354 } // namespace Internal