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