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