c3dc46299f50813b1987285f3c85e1fd37125227
[platform/core/uifw/dali-adaptor.git] / dali / internal / clipboard / tizen-wayland / clipboard-impl-ecore-wl.cpp
1 /*
2  * Copyright (c) 2023 Samsung Electronics Co., Ltd.
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  *
16  */
17
18 // CLASS HEADER
19 #include <dali/devel-api/adaptor-framework/clipboard-event-notifier.h>
20 #include <dali/internal/clipboard/common/clipboard-impl.h>
21
22 // EXTERNAL INCLUDES
23 #include <dali/internal/system/linux/dali-ecore.h>
24
25 #ifdef ECORE_WAYLAND2
26 #include <dali/internal/adaptor/tizen-wayland/dali-ecore-wl2.h>
27 #else
28 #include <dali/internal/adaptor/tizen-wayland/dali-ecore-wayland.h>
29 #endif
30
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>
35 #include <unistd.h>
36
37 #ifdef DALI_ELDBUS_AVAILABLE
38 #include <Eldbus.h>
39 #endif // DALI_ELDBUS_AVAILABLE
40
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
46
47 ///////////////////////////////////////////////////////////////////////////////////////////////////
48 // Clipboard
49 ///////////////////////////////////////////////////////////////////////////////////////////////////
50
51 namespace Dali
52 {
53 namespace Internal
54 {
55 namespace Adaptor
56 {
57 struct Clipboard::Impl
58 {
59   Impl()
60   {
61 #ifdef DALI_ELDBUS_AVAILABLE
62     Eldbus_Object* eldbus_obj;
63     eldbus_init();
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
70     mVisible           = false;
71     mIsFirstTimeHidden = true;
72   }
73
74   ~Impl()
75   {
76 #ifdef DALI_ELDBUS_AVAILABLE
77     if(cbhm_conn)
78       eldbus_connection_unref(cbhm_conn);
79     eldbus_shutdown();
80 #endif // DALI_ELDBUS_AVAILABLE
81   }
82
83 #ifdef DALI_ELDBUS_AVAILABLE
84   Eldbus_Proxy* cbhm_proxy_get()
85   {
86     return eldbus_proxy;
87   }
88
89   Eldbus_Connection* cbhm_connection_get()
90   {
91     return cbhm_conn;
92   }
93 #endif // DALI_ELDBUS_AVAILABLE
94
95   void SetItem(const std::string& itemData)
96   {
97     const char* types[10] = {
98       0,
99     };
100     int i = -1;
101
102     if(itemData.length() == 0)
103     {
104       return;
105     }
106     mSendBuffer = itemData;
107
108     // ELM_SEL_TYPE_CLIPBOARD - To distinguish clipboard selection in cbhm
109     types[++i] = "CLIPBOARD_BEGIN";
110
111     types[++i] = "text/plain;charset=utf-8";
112
113     // ELM_SEL_TYPE_CLIPBOARD - To distinguish clipboard selection in cbhm
114     types[++i] = "CLIPBOARD_END";
115
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);
119 #else
120     mSerial                = ecore_wl_dnd_selection_set(ecore_wl_input_get(), types);
121 #endif
122   }
123
124   void RequestItem()
125   {
126     const char* types[10] = {
127       0,
128     };
129     int i = -1;
130
131     types[++i] = "text/plain;charset=utf-8";
132
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);
137
138     ecore_wl2_offer_receive(offer, const_cast<char*>(*types));
139     ecore_wl2_display_flush(ecore_wl2_input_display_get(input));
140 #else
141     ecore_wl_dnd_selection_get(ecore_wl_input_get(), *types);
142 #endif
143   }
144
145   void ExcuteSend(void* event)
146   {
147 #ifdef ECORE_WAYLAND2
148     Ecore_Wl2_Event_Data_Source_Send* ev = reinterpret_cast<Ecore_Wl2_Event_Data_Source_Send*>(event);
149 #else
150     Ecore_Wl_Event_Data_Source_Send*  ev = reinterpret_cast<Ecore_Wl_Event_Data_Source_Send*>(event);
151 #endif
152
153     if(ev->serial != mSerial)
154     {
155       return;
156     }
157
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
162
163     while(len_written < len_buf)
164     {
165       ret = write(ev->fd, buf, len_remained);
166       if(ret == -1) break;
167       buf += ret;
168       len_written += ret;
169       len_remained -= ret;
170     }
171     close(ev->fd);
172   }
173
174   void ExcuteReceive(void* event, char*& data, int& length)
175   {
176 #ifdef ECORE_WAYLAND2
177     Ecore_Wl2_Event_Offer_Data_Ready* ev = reinterpret_cast<Ecore_Wl2_Event_Offer_Data_Ready*>(event);
178 #else
179     Ecore_Wl_Event_Selection_Data_Ready* ev = reinterpret_cast<Ecore_Wl_Event_Selection_Data_Ready*>(event);
180 #endif
181     data   = reinterpret_cast<char*>(ev->data);
182     length = ev->len;
183   }
184
185   int GetCount()
186   {
187 #ifdef DALI_ELDBUS_AVAILABLE
188     Eldbus_Message *reply, *req;
189     const char *    errname = NULL, *errmsg = NULL;
190 #endif // DALI_ELDBUS_AVAILABLE
191     int count = -1;
192
193 #ifdef DALI_ELDBUS_AVAILABLE
194     if(!(req = eldbus_proxy_method_call_new(eldbus_proxy, "CbhmGetCount")))
195     {
196       DALI_LOG_ERROR("Failed to create method call on org.freedesktop.DBus.Properties.Get");
197       return -1;
198     }
199
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))
204     {
205       DALI_LOG_ERROR("Unable to call method org.freedesktop.DBus.Properties.Get: %s %s",
206                      errname,
207                      errmsg);
208       eldbus_message_unref(req);
209       if(reply)
210       {
211         eldbus_message_unref(reply);
212       }
213       return -1;
214     }
215
216     if(!eldbus_message_arguments_get(reply, "i", &count))
217     {
218       DALI_LOG_ERROR("Cannot get arguments from eldbus");
219       eldbus_message_unref(req);
220       eldbus_message_unref(reply);
221       return -1;
222     }
223
224     eldbus_message_unref(req);
225     eldbus_message_unref(reply);
226     DALI_LOG_ERROR("cbhm item count(%d)", count);
227 #endif // DALI_ELDBUS_AVAILABLE
228     return count;
229   }
230
231   void ShowClipboard()
232   {
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;
237     mVisible           = true;
238   }
239
240   void HideClipboard(bool skipFirstHide)
241   {
242     if(skipFirstHide && mIsFirstTimeHidden)
243     {
244       mIsFirstTimeHidden = false;
245       return;
246     }
247 #ifdef DALI_ELDBUS_AVAILABLE
248     eldbus_proxy_call(cbhm_proxy_get(), "CbhmHide", NULL, NULL, -1, "");
249 #endif // DALI_ELDBUS_AVAILABLE
250     mIsFirstTimeHidden = false;
251     mVisible           = false;
252   }
253
254   bool IsVisible() const
255   {
256     return mVisible;
257   }
258
259 #ifdef DALI_ELDBUS_AVAILABLE
260   static void _on_item_clicked(void* data, const Eldbus_Message* msg EINA_UNUSED)
261   {
262     static_cast<Clipboard::Impl*>(data)->RequestItem();
263   }
264
265   Eldbus_Proxy*      eldbus_proxy;
266   Eldbus_Connection* cbhm_conn;
267 #endif // DALI_ELDBUS_AVAILABLE
268
269   std::string mSendBuffer;
270   bool        mVisible;
271   bool        mIsFirstTimeHidden;
272   uint32_t    mSerial{0u};
273 };
274
275 Clipboard::Clipboard(Impl* impl)
276 : mImpl(impl)
277 {
278 }
279
280 Clipboard::~Clipboard()
281 {
282   delete mImpl;
283 }
284
285 Dali::Clipboard Clipboard::Get()
286 {
287   Dali::Clipboard clipboard;
288
289   Dali::SingletonService service(SingletonService::Get());
290   if(service)
291   {
292     // Check whether the singleton is already created
293     Dali::BaseHandle handle = service.GetSingleton(typeid(Dali::Clipboard));
294     if(handle)
295     {
296       // If so, downcast the handle
297       clipboard = Dali::Clipboard(dynamic_cast<Clipboard*>(handle.GetObjectPtr()));
298     }
299     else
300     {
301       Clipboard::Impl* impl(new Clipboard::Impl());
302       clipboard = Dali::Clipboard(new Clipboard(impl));
303       service.Register(typeid(Dali::Clipboard), clipboard);
304     }
305   }
306
307   return clipboard;
308 }
309
310 bool Clipboard::IsAvailable()
311 {
312   Dali::SingletonService service(SingletonService::Get());
313   if(service)
314   {
315     Dali::BaseHandle handle = service.GetSingleton(typeid(Dali::Clipboard));
316     if(handle)
317     {
318       return true;
319     }
320   }
321   return false;
322 }
323
324 bool Clipboard::SetItem(const std::string& itemData)
325 {
326   mImpl->SetItem(itemData);
327   return true;
328 }
329
330 /*
331  * Request clipboard service to give an item
332  */
333 void Clipboard::RequestItem()
334 {
335   mImpl->RequestItem();
336 }
337
338 /*
339  * Get number of items in clipboard
340  */
341 unsigned int Clipboard::NumberOfItems()
342 {
343   int count = mImpl->GetCount();
344   return (count < 0 ? 0 : count);
345 }
346
347 void Clipboard::ShowClipboard()
348 {
349   mImpl->ShowClipboard();
350 }
351
352 void Clipboard::HideClipboard(bool skipFirstHide)
353 {
354   mImpl->HideClipboard(skipFirstHide);
355 }
356
357 bool Clipboard::IsVisible() const
358 {
359   return mImpl->IsVisible();
360 }
361
362 void Clipboard::ExcuteSend(void* event)
363 {
364   mImpl->ExcuteSend(event);
365 }
366
367 void Clipboard::ExcuteReceive(void* event, char*& data, int& length)
368 {
369   mImpl->ExcuteReceive(event, data, length);
370 }
371
372 } // namespace Adaptor
373
374 } // namespace Internal
375
376 } // namespace Dali