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