Use existing callback ID for recurring callbacks
[platform/core/uifw/dali-adaptor.git] / dali / internal / clipboard / tizen-wayland / clipboard-impl-ecore-wl.cpp
1 /*
2  * Copyright (c) 2019 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/internal/clipboard/common/clipboard-impl.h>
20 #include <dali/devel-api/adaptor-framework/clipboard-event-notifier.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/public-api/object/any.h>
32 #include <dali/public-api/object/type-registry.h>
33 #include <dali/devel-api/common/singleton-service.h>
34 #include <dali/integration-api/debug.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
54 namespace Internal
55 {
56
57 namespace Adaptor
58 {
59
60 struct Clipboard::Impl
61 {
62   Impl()
63   {
64     Eldbus_Object *eldbus_obj;
65     cbhm_conn = eldbus_connection_get(ELDBUS_CONNECTION_TYPE_SESSION);
66     eldbus_obj = eldbus_object_get(cbhm_conn, CBHM_DBUS_INTERFACE, CBHM_DBUS_OBJPATH);
67     eldbus_proxy = eldbus_proxy_get(eldbus_obj, CBHM_DBUS_INTERFACE);
68     eldbus_name_owner_changed_callback_add(cbhm_conn, CBHM_DBUS_INTERFACE, NULL, cbhm_conn, EINA_TRUE);
69     eldbus_proxy_signal_handler_add(eldbus_proxy, "ItemClicked", _on_item_clicked, this);
70     mVisible = false;
71     mIsFirstTimeHidden = true;
72   }
73
74   ~Impl()
75   {
76     if (cbhm_conn)
77       eldbus_connection_unref(cbhm_conn);
78   }
79
80   Eldbus_Proxy* cbhm_proxy_get()
81   {
82     return eldbus_proxy;
83   }
84
85   Eldbus_Connection* cbhm_connection_get()
86   {
87     return cbhm_conn;
88   }
89
90   void SetItem( const std::string &itemData )
91   {
92     const char *types[10] = {0, };
93     int i = -1;
94
95     if (itemData.length() == 0)
96     {
97       return;
98     }
99     mSendBuffer = itemData;
100
101     // ELM_SEL_TYPE_CLIPBOARD - To distinguish clipboard selection in cbhm
102     types[++i] = "CLIPBOARD_BEGIN";
103
104     types[++i] = "text/plain;charset=utf-8";
105
106     // ELM_SEL_TYPE_CLIPBOARD - To distinguish clipboard selection in cbhm
107     types[++i] = "CLIPBOARD_END";
108
109 #ifdef ECORE_WAYLAND2
110     Ecore_Wl2_Input* input = ecore_wl2_input_default_input_get( ecore_wl2_connected_display_get( NULL ) );
111     ecore_wl2_dnd_selection_set( input, types );
112 #else
113     ecore_wl_dnd_selection_set( ecore_wl_input_get(), types );
114 #endif
115   }
116
117   void RequestItem()
118   {
119 #ifdef ECORE_WAYLAND2
120     Ecore_Wl2_Input* input = ecore_wl2_input_default_input_get( ecore_wl2_connected_display_get( NULL ) );
121     ecore_wl2_dnd_selection_get( input );
122 #else
123     const char *types[10] = {0, };
124     int i = -1;
125
126     types[++i] = "text/plain;charset=utf-8";
127     ecore_wl_dnd_selection_get(ecore_wl_input_get(), *types);
128 #endif
129
130     Dali::ClipboardEventNotifier clipboardEventNotifier(Dali::ClipboardEventNotifier::Get());
131     if ( clipboardEventNotifier )
132     {
133       clipboardEventNotifier.SetContent( mSendBuffer );
134       clipboardEventNotifier.EmitContentSelectedSignal();
135     }
136   }
137
138   char *ExcuteSend( void *event )
139   {
140 #ifdef ECORE_WAYLAND2
141     Ecore_Wl2_Event_Data_Source_Send *ev = reinterpret_cast<Ecore_Wl2_Event_Data_Source_Send *>( event );
142 #else
143     Ecore_Wl_Event_Data_Source_Send *ev = reinterpret_cast<Ecore_Wl_Event_Data_Source_Send *>( event );
144 #endif
145
146     int len_buf = mSendBuffer.length();
147     int len_remained = len_buf;
148     int len_written = 0, ret;
149     const char *buf = mSendBuffer.c_str();
150
151     while (len_written < len_buf)
152     {
153        ret = write(ev->fd, buf, len_remained);
154        if (ret == -1) break;
155        buf += ret;
156        len_written += ret;
157        len_remained -= ret;
158     }
159     close(ev->fd);
160     return NULL;
161   }
162
163   char *ExcuteReceive( void *event )
164   {
165 #ifdef ECORE_WAYLAND2
166     Ecore_Wl2_Event_Selection_Data_Ready *ev = reinterpret_cast<Ecore_Wl2_Event_Selection_Data_Ready *>( event );
167 #else
168     Ecore_Wl_Event_Selection_Data_Ready *ev = reinterpret_cast<Ecore_Wl_Event_Selection_Data_Ready *>( event );
169 #endif
170
171     return reinterpret_cast<char *>( ev->data );
172   }
173
174   int GetCount()
175   {
176     Eldbus_Message *reply, *req;
177     const char *errname = NULL, *errmsg = NULL;
178     int count = -1;
179
180     if (!(req = eldbus_proxy_method_call_new(eldbus_proxy, "CbhmGetCount")))
181     {
182       DALI_LOG_ERROR("Failed to create method call on org.freedesktop.DBus.Properties.Get");
183       return -1;
184     }
185
186     eldbus_message_ref(req);
187     eldbus_message_arguments_append(req, "i", CBHM_COUNT_ALL) ;
188     reply = eldbus_proxy_send_and_block(eldbus_proxy, req, 100);
189     if (!reply || eldbus_message_error_get(reply, &errname, &errmsg))
190     {
191       DALI_LOG_ERROR("Unable to call method org.freedesktop.DBus.Properties.Get: %s %s",
192       errname, errmsg);
193       eldbus_message_unref(req);
194       if( reply )
195       {
196         eldbus_message_unref(reply);
197       }
198       return -1;
199     }
200
201     if (!eldbus_message_arguments_get(reply, "i", &count))
202     {
203       DALI_LOG_ERROR("Cannot get arguments from eldbus");
204       eldbus_message_unref(req);
205       eldbus_message_unref(reply);
206       return -1;
207     }
208
209     eldbus_message_unref(req);
210     eldbus_message_unref(reply);
211     DALI_LOG_ERROR("cbhm item count(%d)", count);
212     return count;
213   }
214
215   void ShowClipboard()
216   {
217     eldbus_proxy_call(cbhm_proxy_get(), "CbhmShow", NULL, NULL, -1, "s", "0");
218     mIsFirstTimeHidden = true;
219     mVisible = true;
220   }
221
222   void HideClipboard( bool skipFirstHide )
223   {
224     if ( skipFirstHide && mIsFirstTimeHidden )
225     {
226       mIsFirstTimeHidden = false;
227       return;
228     }
229     eldbus_proxy_call(cbhm_proxy_get(), "CbhmHide", NULL, NULL, -1, "");
230     mIsFirstTimeHidden = false;
231     mVisible = false;
232   }
233
234   bool IsVisible() const
235   {
236     return mVisible;
237   }
238
239   static void _on_item_clicked(void *data, const Eldbus_Message *msg EINA_UNUSED)
240   {
241     static_cast<Clipboard::Impl*>(data)->RequestItem();
242   }
243
244   Eldbus_Proxy *eldbus_proxy;
245   Eldbus_Connection *cbhm_conn;
246
247   std::string mSendBuffer;
248   bool mVisible;
249   bool mIsFirstTimeHidden;
250 };
251
252 Clipboard::Clipboard(Impl* impl)
253 : mImpl(impl)
254 {
255 }
256
257 Clipboard::~Clipboard()
258 {
259   delete mImpl;
260 }
261
262 Dali::Clipboard Clipboard::Get()
263 {
264   Dali::Clipboard clipboard;
265
266   Dali::SingletonService service( SingletonService::Get() );
267   if ( service )
268   {
269     // Check whether the singleton is already created
270     Dali::BaseHandle handle = service.GetSingleton( typeid( Dali::Clipboard ) );
271     if(handle)
272     {
273       // If so, downcast the handle
274       clipboard = Dali::Clipboard( dynamic_cast< Clipboard* >( handle.GetObjectPtr() ) );
275     }
276     else
277     {
278       Clipboard::Impl* impl( new Clipboard::Impl() );
279       clipboard = Dali::Clipboard( new Clipboard(impl) );
280       service.Register( typeid(Dali::Clipboard), clipboard );
281     }
282   }
283
284   return clipboard;
285 }
286
287 bool Clipboard::SetItem(const std::string &itemData )
288 {
289   mImpl->SetItem( itemData );
290   return true;
291 }
292
293 /*
294  * Request clipboard service to give an item
295  */
296 void Clipboard::RequestItem()
297 {
298   mImpl->RequestItem();
299 }
300
301 /*
302  * Get number of items in clipboard
303  */
304 unsigned int Clipboard::NumberOfItems()
305 {
306   return mImpl->GetCount();
307 }
308
309 void Clipboard::ShowClipboard()
310 {
311   mImpl->ShowClipboard();
312 }
313
314 void Clipboard::HideClipboard(bool skipFirstHide)
315 {
316   mImpl->HideClipboard(skipFirstHide);
317 }
318
319 bool Clipboard::IsVisible() const
320 {
321   return mImpl->IsVisible();
322 }
323
324 char* Clipboard::ExcuteBuffered( bool type, void *event )
325 {
326   return (type ?  mImpl->ExcuteSend( event ) : mImpl->ExcuteReceive( event ));
327 }
328
329 } // namespace Adaptor
330
331 } // namespace Internal
332
333 } // namespace Dali