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/devel-api/adaptor-framework/text-clipboard-event-notifier.h>
20 #include <dali/internal/text-clipboard/common/text-clipboard-impl.h>
23 #include <dali/internal/system/linux/dali-ecore.h>
26 #include <dali/internal/adaptor/tizen-wayland/dali-ecore-wl2.h>
28 #include <dali/internal/adaptor/tizen-wayland/dali-ecore-wayland.h>
31 #include <dali/devel-api/common/singleton-service.h>
32 #include <dali/integration-api/debug.h>
33 #include <dali/public-api/object/any.h>
34 #include <dali/public-api/object/type-registry.h>
37 #ifdef DALI_ELDBUS_AVAILABLE
39 #endif // DALI_ELDBUS_AVAILABLE
41 #define CBHM_DBUS_OBJPATH "/org/tizen/cbhm/dbus"
42 #ifndef CBHM_DBUS_INTERFACE
43 #define CBHM_DBUS_INTERFACE "org.tizen.cbhm.dbus"
44 #endif /* CBHM_DBUS_INTERFACE */
45 #define CBHM_COUNT_ALL 0 // ATOM_INDEX_CBHM_COUNT_ALL
47 ///////////////////////////////////////////////////////////////////////////////////////////////////
49 ///////////////////////////////////////////////////////////////////////////////////////////////////
57 struct TextClipboard::Impl
61 #ifdef DALI_ELDBUS_AVAILABLE
62 Eldbus_Object* eldbus_obj;
64 cbhm_conn = eldbus_connection_get(ELDBUS_CONNECTION_TYPE_SESSION);
65 eldbus_obj = eldbus_object_get(cbhm_conn, CBHM_DBUS_INTERFACE, CBHM_DBUS_OBJPATH);
66 eldbus_proxy = eldbus_proxy_get(eldbus_obj, CBHM_DBUS_INTERFACE);
67 eldbus_name_owner_changed_callback_add(cbhm_conn, CBHM_DBUS_INTERFACE, NULL, cbhm_conn, EINA_TRUE);
68 eldbus_proxy_signal_handler_add(eldbus_proxy, "ItemClicked", _on_item_clicked, this);
69 #endif // DALI_ELDBUS_AVAILABLE
71 mIsFirstTimeHidden = true;
76 #ifdef DALI_ELDBUS_AVAILABLE
78 eldbus_connection_unref(cbhm_conn);
80 #endif // DALI_ELDBUS_AVAILABLE
83 #ifdef DALI_ELDBUS_AVAILABLE
84 Eldbus_Proxy* cbhm_proxy_get()
89 Eldbus_Connection* cbhm_connection_get()
93 #endif // DALI_ELDBUS_AVAILABLE
95 void SetItem(const std::string& itemData)
97 const char* types[10] = {
102 if(itemData.length() == 0)
106 mSendBuffer = itemData;
108 // ELM_SEL_TYPE_CLIPBOARD - To distinguish clipboard selection in cbhm
109 types[++i] = "CLIPBOARD_BEGIN";
111 types[++i] = "text/plain;charset=utf-8";
113 // ELM_SEL_TYPE_CLIPBOARD - To distinguish clipboard selection in cbhm
114 types[++i] = "CLIPBOARD_END";
116 #ifdef ECORE_WAYLAND2
117 Ecore_Wl2_Input* input = ecore_wl2_input_default_input_get(ecore_wl2_connected_display_get(NULL));
118 mSerial = ecore_wl2_dnd_selection_set(input, types);
120 mSerial = ecore_wl_dnd_selection_set(ecore_wl_input_get(), types);
126 const char* types[10] = {
131 types[++i] = "text/plain;charset=utf-8";
133 #ifdef ECORE_WAYLAND2
134 Ecore_Wl2_Display* display = ecore_wl2_connected_display_get(NULL);
135 Ecore_Wl2_Input* input = ecore_wl2_input_default_input_get(display);
136 Ecore_Wl2_Offer* offer = ecore_wl2_dnd_selection_get(input);
138 ecore_wl2_offer_receive(offer, const_cast<char*>(*types));
139 ecore_wl2_display_flush(ecore_wl2_input_display_get(input));
141 ecore_wl_dnd_selection_get(ecore_wl_input_get(), *types);
145 void ExcuteSend(void* event)
147 #ifdef ECORE_WAYLAND2
148 Ecore_Wl2_Event_Data_Source_Send* ev = reinterpret_cast<Ecore_Wl2_Event_Data_Source_Send*>(event);
150 Ecore_Wl_Event_Data_Source_Send* ev = reinterpret_cast<Ecore_Wl_Event_Data_Source_Send*>(event);
153 if(ev->serial != mSerial)
158 int len_buf = mSendBuffer.length() + 1; // we should consider the char* buffer length
159 int len_remained = len_buf;
160 int len_written = 0, ret;
161 const char* buf = mSendBuffer.c_str(); // last char in the buffer must be \0
163 while(len_written < len_buf)
165 ret = write(ev->fd, buf, len_remained);
174 void ExcuteReceive(void* event, char*& data, int& length)
176 #ifdef ECORE_WAYLAND2
177 Ecore_Wl2_Event_Offer_Data_Ready* ev = reinterpret_cast<Ecore_Wl2_Event_Offer_Data_Ready*>(event);
179 Ecore_Wl_Event_Selection_Data_Ready* ev = reinterpret_cast<Ecore_Wl_Event_Selection_Data_Ready*>(event);
181 data = reinterpret_cast<char*>(ev->data);
187 #ifdef DALI_ELDBUS_AVAILABLE
188 Eldbus_Message *reply, *req;
189 const char * errname = NULL, *errmsg = NULL;
190 #endif // DALI_ELDBUS_AVAILABLE
193 #ifdef DALI_ELDBUS_AVAILABLE
194 if(!(req = eldbus_proxy_method_call_new(eldbus_proxy, "CbhmGetCount")))
196 DALI_LOG_ERROR("Failed to create method call on org.freedesktop.DBus.Properties.Get");
200 eldbus_message_ref(req);
201 eldbus_message_arguments_append(req, "i", CBHM_COUNT_ALL);
202 reply = eldbus_proxy_send_and_block(eldbus_proxy, req, 100);
203 if(!reply || eldbus_message_error_get(reply, &errname, &errmsg))
205 DALI_LOG_ERROR("Unable to call method org.freedesktop.DBus.Properties.Get: %s %s",
208 eldbus_message_unref(req);
211 eldbus_message_unref(reply);
216 if(!eldbus_message_arguments_get(reply, "i", &count))
218 DALI_LOG_ERROR("Cannot get arguments from eldbus");
219 eldbus_message_unref(req);
220 eldbus_message_unref(reply);
224 eldbus_message_unref(req);
225 eldbus_message_unref(reply);
226 DALI_LOG_ERROR("cbhm item count(%d)", count);
227 #endif // DALI_ELDBUS_AVAILABLE
233 #ifdef DALI_ELDBUS_AVAILABLE
234 eldbus_proxy_call(cbhm_proxy_get(), "CbhmShow", NULL, NULL, -1, "s", "0");
235 #endif // DALI_ELDBUS_AVAILABLE
236 mIsFirstTimeHidden = true;
240 void HideClipboard(bool skipFirstHide)
242 if(skipFirstHide && mIsFirstTimeHidden)
244 mIsFirstTimeHidden = false;
247 #ifdef DALI_ELDBUS_AVAILABLE
248 eldbus_proxy_call(cbhm_proxy_get(), "CbhmHide", NULL, NULL, -1, "");
249 #endif // DALI_ELDBUS_AVAILABLE
250 mIsFirstTimeHidden = false;
254 bool IsVisible() const
259 #ifdef DALI_ELDBUS_AVAILABLE
260 static void _on_item_clicked(void* data, const Eldbus_Message* msg EINA_UNUSED)
262 static_cast<TextClipboard::Impl*>(data)->RequestItem();
265 Eldbus_Proxy* eldbus_proxy;
266 Eldbus_Connection* cbhm_conn;
267 #endif // DALI_ELDBUS_AVAILABLE
269 std::string mSendBuffer;
271 bool mIsFirstTimeHidden;
272 uint32_t mSerial{0u};
275 TextClipboard::TextClipboard(Impl* impl)
280 TextClipboard::~TextClipboard()
285 Dali::TextClipboard TextClipboard::Get()
287 Dali::TextClipboard clipboard;
289 Dali::SingletonService service(SingletonService::Get());
292 // Check whether the singleton is already created
293 Dali::BaseHandle handle = service.GetSingleton(typeid(Dali::TextClipboard));
296 // If so, downcast the handle
297 clipboard = Dali::TextClipboard(dynamic_cast<TextClipboard*>(handle.GetObjectPtr()));
301 TextClipboard::Impl* impl(new TextClipboard::Impl());
302 clipboard = Dali::TextClipboard(new TextClipboard(impl));
303 service.Register(typeid(Dali::TextClipboard), clipboard);
310 bool TextClipboard::IsAvailable()
312 Dali::SingletonService service(SingletonService::Get());
315 Dali::BaseHandle handle = service.GetSingleton(typeid(Dali::TextClipboard));
324 bool TextClipboard::SetItem(const std::string& itemData)
326 mImpl->SetItem(itemData);
331 * Request clipboard service to give an item
333 void TextClipboard::RequestItem()
335 mImpl->RequestItem();
339 * Get number of items in clipboard
341 unsigned int TextClipboard::NumberOfItems()
343 int count = mImpl->GetCount();
344 return (count < 0 ? 0 : count);
347 void TextClipboard::ShowClipboard()
349 mImpl->ShowClipboard();
352 void TextClipboard::HideClipboard(bool skipFirstHide)
354 mImpl->HideClipboard(skipFirstHide);
357 bool TextClipboard::IsVisible() const
359 return mImpl->IsVisible();
362 void TextClipboard::ExcuteSend(void* event)
364 mImpl->ExcuteSend(event);
367 void TextClipboard::ExcuteReceive(void* event, char*& data, int& length)
369 mImpl->ExcuteReceive(event, data, length);
372 } // namespace Adaptor
374 } // namespace Internal