Merge "Remove unnecessray ClipBoard creation (2)" into devel/master
[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 #ifdef ECORE_WAYLAND2
127     Ecore_Wl2_Input* input = ecore_wl2_input_default_input_get(ecore_wl2_connected_display_get(NULL));
128     ecore_wl2_dnd_selection_get(input);
129 #else
130     const char* types[10] = {
131       0,
132     };
133     int i = -1;
134
135     types[++i] = "text/plain;charset=utf-8";
136     ecore_wl_dnd_selection_get(ecore_wl_input_get(), *types);
137 #endif
138
139     Dali::ClipboardEventNotifier clipboardEventNotifier(Dali::ClipboardEventNotifier::Get());
140     if(clipboardEventNotifier)
141     {
142       clipboardEventNotifier.SetContent(mSendBuffer);
143       clipboardEventNotifier.EmitContentSelectedSignal();
144     }
145   }
146
147   char* ExcuteSend(void* event)
148   {
149 #ifdef ECORE_WAYLAND2
150     Ecore_Wl2_Event_Data_Source_Send* ev = reinterpret_cast<Ecore_Wl2_Event_Data_Source_Send*>(event);
151 #else
152     Ecore_Wl_Event_Data_Source_Send*     ev = reinterpret_cast<Ecore_Wl_Event_Data_Source_Send*>(event);
153 #endif
154
155     if(ev->serial != mSerial)
156     {
157       return NULL;
158     }
159
160     int         len_buf      = mSendBuffer.length();
161     int         len_remained = len_buf;
162     int         len_written  = 0, ret;
163     const char* buf          = mSendBuffer.c_str();
164
165     while(len_written < len_buf)
166     {
167       ret = write(ev->fd, buf, len_remained);
168       if(ret == -1) break;
169       buf += ret;
170       len_written += ret;
171       len_remained -= ret;
172     }
173     close(ev->fd);
174     return NULL;
175   }
176
177   char* ExcuteReceive(void* event)
178   {
179 #ifdef ECORE_WAYLAND2
180     Ecore_Wl2_Event_Selection_Data_Ready* ev = reinterpret_cast<Ecore_Wl2_Event_Selection_Data_Ready*>(event);
181 #else
182     Ecore_Wl_Event_Selection_Data_Ready* ev = reinterpret_cast<Ecore_Wl_Event_Selection_Data_Ready*>(event);
183 #endif
184
185     return reinterpret_cast<char*>(ev->data);
186   }
187
188   int GetCount()
189   {
190 #ifdef DALI_ELDBUS_AVAILABLE
191     Eldbus_Message *reply, *req;
192     const char *    errname = NULL, *errmsg = NULL;
193 #endif // DALI_ELDBUS_AVAILABLE
194     int count = -1;
195
196 #ifdef DALI_ELDBUS_AVAILABLE
197     if(!(req = eldbus_proxy_method_call_new(eldbus_proxy, "CbhmGetCount")))
198     {
199       DALI_LOG_ERROR("Failed to create method call on org.freedesktop.DBus.Properties.Get");
200       return -1;
201     }
202
203     eldbus_message_ref(req);
204     eldbus_message_arguments_append(req, "i", CBHM_COUNT_ALL);
205     reply = eldbus_proxy_send_and_block(eldbus_proxy, req, 100);
206     if(!reply || eldbus_message_error_get(reply, &errname, &errmsg))
207     {
208       DALI_LOG_ERROR("Unable to call method org.freedesktop.DBus.Properties.Get: %s %s",
209                      errname,
210                      errmsg);
211       eldbus_message_unref(req);
212       if(reply)
213       {
214         eldbus_message_unref(reply);
215       }
216       return -1;
217     }
218
219     if(!eldbus_message_arguments_get(reply, "i", &count))
220     {
221       DALI_LOG_ERROR("Cannot get arguments from eldbus");
222       eldbus_message_unref(req);
223       eldbus_message_unref(reply);
224       return -1;
225     }
226
227     eldbus_message_unref(req);
228     eldbus_message_unref(reply);
229     DALI_LOG_ERROR("cbhm item count(%d)", count);
230 #endif // DALI_ELDBUS_AVAILABLE
231     return count;
232   }
233
234   void ShowClipboard()
235   {
236 #ifdef DALI_ELDBUS_AVAILABLE
237     eldbus_proxy_call(cbhm_proxy_get(), "CbhmShow", NULL, NULL, -1, "s", "0");
238 #endif // DALI_ELDBUS_AVAILABLE
239     mIsFirstTimeHidden = true;
240     mVisible           = true;
241   }
242
243   void HideClipboard(bool skipFirstHide)
244   {
245     if(skipFirstHide && mIsFirstTimeHidden)
246     {
247       mIsFirstTimeHidden = false;
248       return;
249     }
250 #ifdef DALI_ELDBUS_AVAILABLE
251     eldbus_proxy_call(cbhm_proxy_get(), "CbhmHide", NULL, NULL, -1, "");
252 #endif // DALI_ELDBUS_AVAILABLE
253     mIsFirstTimeHidden = false;
254     mVisible           = false;
255   }
256
257   bool IsVisible() const
258   {
259     return mVisible;
260   }
261
262 #ifdef DALI_ELDBUS_AVAILABLE
263   static void _on_item_clicked(void* data, const Eldbus_Message* msg EINA_UNUSED)
264   {
265     static_cast<Clipboard::Impl*>(data)->RequestItem();
266   }
267
268   Eldbus_Proxy*      eldbus_proxy;
269   Eldbus_Connection* cbhm_conn;
270 #endif // DALI_ELDBUS_AVAILABLE
271
272   std::string mSendBuffer;
273   bool        mVisible;
274   bool        mIsFirstTimeHidden;
275   uint32_t    mSerial{0u};
276 };
277
278 Clipboard::Clipboard(Impl* impl)
279 : mImpl(impl)
280 {
281 }
282
283 Clipboard::~Clipboard()
284 {
285   delete mImpl;
286 }
287
288 Dali::Clipboard Clipboard::Get()
289 {
290   Dali::Clipboard clipboard;
291
292   Dali::SingletonService service(SingletonService::Get());
293   if(service)
294   {
295     // Check whether the singleton is already created
296     Dali::BaseHandle handle = service.GetSingleton(typeid(Dali::Clipboard));
297     if(handle)
298     {
299       // If so, downcast the handle
300       clipboard = Dali::Clipboard(dynamic_cast<Clipboard*>(handle.GetObjectPtr()));
301     }
302     else
303     {
304       Clipboard::Impl* impl(new Clipboard::Impl());
305       clipboard = Dali::Clipboard(new Clipboard(impl));
306       service.Register(typeid(Dali::Clipboard), clipboard);
307     }
308   }
309
310   return clipboard;
311 }
312
313 bool Clipboard::IsAvailable()
314 {
315   Dali::SingletonService service(SingletonService::Get());
316   if(service)
317   {
318     Dali::BaseHandle handle = service.GetSingleton(typeid(Dali::Clipboard));
319     if(handle)
320     {
321       return true;
322     }
323   }
324   return false;
325 }
326
327 bool Clipboard::SetItem(const std::string& itemData)
328 {
329   mImpl->SetItem(itemData);
330   return true;
331 }
332
333 /*
334  * Request clipboard service to give an item
335  */
336 void Clipboard::RequestItem()
337 {
338   mImpl->RequestItem();
339 }
340
341 /*
342  * Get number of items in clipboard
343  */
344 unsigned int Clipboard::NumberOfItems()
345 {
346   int count = mImpl->GetCount();
347   return (count < 0 ? 0 : count);
348 }
349
350 void Clipboard::ShowClipboard()
351 {
352   mImpl->ShowClipboard();
353 }
354
355 void Clipboard::HideClipboard(bool skipFirstHide)
356 {
357   mImpl->HideClipboard(skipFirstHide);
358 }
359
360 bool Clipboard::IsVisible() const
361 {
362   return mImpl->IsVisible();
363 }
364
365 char* Clipboard::ExcuteBuffered(bool type, void* event)
366 {
367   return (type ? mImpl->ExcuteSend(event) : mImpl->ExcuteReceive(event));
368 }
369
370 } // namespace Adaptor
371
372 } // namespace Internal
373
374 } // namespace Dali