38a488e20a4d8e0ed1cf5cb4d9a14641c4b97bcd
[platform/core/uifw/dali-adaptor.git] / dali / internal / clipboard / ubuntu-x11 / clipboard-impl-x.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-x.h>
23 #include <dali/public-api/object/any.h>
24 #include <dali/public-api/object/type-registry.h>
25 #include <dali/integration-api/debug.h>
26
27 // INTERNAL INCLUDES
28 #include <dali/internal/adaptor/common/adaptor-impl.h>
29 #include <dali/internal/window-system/ubuntu-x11/window-interface-ecore-x.h>
30 #include <dali/internal/system/common/singleton-service-impl.h>
31 #include <dali/internal/clipboard/common/clipboard-event-notifier-impl.h>
32
33 namespace //unnamed namespace
34 {
35 const char* const CBHM_WINDOW = "CBHM_XWIN";
36 const char* const CBHM_MSG = "CBHM_MSG";
37 const char* const CBHM_ITEM = "CBHM_ITEM";
38 const char* const CBHM_cCOUNT = "CBHM_cCOUNT";
39 const char* const CBHM_ERROR = "CBHM_ERROR";
40 const char* const SET_ITEM = "SET_ITEM";
41 const char* const SHOW = "show0";
42 const char* const HIDE = "cbhm_hide";
43 }
44
45 ///////////////////////////////////////////////////////////////////////////////////////////////////
46 // Clipboard
47 ///////////////////////////////////////////////////////////////////////////////////////////////////
48
49 namespace Dali
50 {
51
52 namespace Internal
53 {
54
55 namespace Adaptor
56 {
57
58 struct Clipboard::Impl
59 {
60   Impl( Ecore_X_Window ecoreXwin )
61   {
62     mApplicationWindow = ecoreXwin;
63   }
64
65   Ecore_X_Window mApplicationWindow;
66 };
67
68 Clipboard::Clipboard(Impl* impl)
69 : mImpl( impl )
70 {
71 }
72
73 Clipboard::~Clipboard()
74 {
75   delete mImpl;
76 }
77
78 Dali::Clipboard Clipboard::Get()
79 {
80   Dali::Clipboard clipboard;
81
82   Dali::SingletonService service( SingletonService::Get() );
83   if ( service )
84   {
85     // Check whether the singleton is already created
86     Dali::BaseHandle handle = service.GetSingleton( typeid( Dali::Clipboard ) );
87     if(handle)
88     {
89       // If so, downcast the handle
90       clipboard = Dali::Clipboard( dynamic_cast< Clipboard* >( handle.GetObjectPtr() ) );
91     }
92     else
93     {
94       Adaptor& adaptorImpl( Adaptor::GetImplementation( Adaptor::Get() ) );
95       Any nativewindow = adaptorImpl.GetNativeWindowHandle();
96
97       // The Ecore_X_Window needs to use the Clipboard.
98       // Only when the render surface is window, we can get the Ecore_X_Window.
99       Ecore_X_Window ecoreXwin( AnyCast<Ecore_X_Window>(nativewindow) );
100       if (ecoreXwin)
101       {
102         // If we fail to get Ecore_X_Window, we can't use the Clipboard correctly.
103         // Thus you have to call "ecore_imf_context_client_window_set" somewhere.
104         // In EvasPlugIn, this function is called in EvasPlugin::ConnectEcoreEvent().
105         Clipboard::Impl* impl( new Clipboard::Impl( ecoreXwin ) );
106         clipboard = Dali::Clipboard( new Clipboard( impl ) );
107         service.Register( typeid( clipboard ), clipboard );
108       }
109     }
110   }
111
112   return clipboard;
113 }
114 bool Clipboard::SetItem(const std::string &itemData )
115 {
116   Ecore_X_Window cbhmWin = ECore::WindowInterface::GetWindow();
117   Ecore_X_Atom atomCbhmItem = ecore_x_atom_get( CBHM_ITEM );
118   Ecore_X_Atom dataType = ECORE_X_ATOM_STRING;
119
120   // Set item (property) to send
121   ecore_x_window_prop_property_set( cbhmWin, atomCbhmItem, dataType, 8, const_cast<char*>( itemData.c_str() ), itemData.length() + 1 );
122   ecore_x_sync();
123
124   // Trigger sending of item (property)
125   Ecore_X_Atom atomCbhmMsg = ecore_x_atom_get( CBHM_MSG );
126   ECore::WindowInterface::SendXEvent(ecore_x_display_get(), cbhmWin, False, NoEventMask, atomCbhmMsg, 8, SET_ITEM );
127   return true;
128 }
129
130 /*
131  * Request clipboard service to retrieve an item
132  */
133 void Clipboard::RequestItem()
134 {
135   int index = 0;
136   char sendBuf[20];
137   snprintf( sendBuf, 20,  "%s%d", CBHM_ITEM, index );
138   Ecore_X_Atom xAtomCbhmItem = ecore_x_atom_get( sendBuf );
139   Ecore_X_Atom xAtomItemType = 0;
140
141   std::string clipboardString( ECore::WindowInterface::GetWindowProperty(xAtomCbhmItem, &xAtomItemType, index ) );
142
143   // Only return the text string if the Atom type is text (Do not return a text string/URL for images).
144   if( !clipboardString.empty() &&
145       ( xAtomItemType == ECORE_X_ATOM_TEXT || xAtomItemType == ECORE_X_ATOM_COMPOUND_TEXT || xAtomItemType == ECORE_X_ATOM_STRING || xAtomItemType == ECORE_X_ATOM_UTF8_STRING ) )
146   {
147     Ecore_X_Atom xAtomCbhmError = ecore_x_atom_get( CBHM_ERROR );
148     if ( xAtomItemType != xAtomCbhmError )
149     {
150       // Call ClipboardEventNotifier to notify event observe of retrieved string
151       Dali::ClipboardEventNotifier clipboardEventNotifier(ClipboardEventNotifier::Get());
152       if ( clipboardEventNotifier )
153       {
154         ClipboardEventNotifier& notifierImpl( ClipboardEventNotifier::GetImplementation( clipboardEventNotifier ) );
155
156         notifierImpl.SetContent( clipboardString );
157         notifierImpl.EmitContentSelectedSignal();
158       }
159     }
160   }
161 }
162
163 /*
164  * Get number of items in clipboard
165  */
166 unsigned int Clipboard::NumberOfItems()
167 {
168   Ecore_X_Atom xAtomCbhmCountGet = ecore_x_atom_get( CBHM_cCOUNT );
169
170   std::string ret( ECore::WindowInterface::GetWindowProperty( xAtomCbhmCountGet, NULL, 0 ) );
171   int count = 0;
172
173   if ( !ret.empty() )
174   {
175     count = atoi( ret.c_str() );
176   }
177
178   return count;
179 }
180
181 /**
182  * Show clipboard window
183  * Function to send message to show the Clipboard (cbhm) as no direct API available
184  * Reference elementary/src/modules/ctxpopup_copypasteUI/cbhm_helper.c
185  */
186 void Clipboard::ShowClipboard()
187 {
188   // Claim the ownership of the SECONDARY selection.
189   ecore_x_selection_secondary_set(mImpl->mApplicationWindow, "", 1);
190   Ecore_X_Window cbhmWin = ECore::WindowInterface::GetWindow();
191
192   // Launch the clipboard window
193   Ecore_X_Atom atomCbhmMsg = ecore_x_atom_get( CBHM_MSG );
194   ECore::WindowInterface::SendXEvent( ecore_x_display_get(), cbhmWin, False, NoEventMask, atomCbhmMsg, 8, SHOW );
195 }
196
197 void Clipboard::HideClipboard(bool skipFirstHide)
198 {
199   Ecore_X_Window cbhmWin = ECore::WindowInterface::GetWindow();
200   // Launch the clipboard window
201   Ecore_X_Atom atomCbhmMsg = ecore_x_atom_get( CBHM_MSG );
202   ECore::WindowInterface::SendXEvent( ecore_x_display_get(), cbhmWin, False, NoEventMask, atomCbhmMsg, 8, HIDE );
203
204   // release the ownership of SECONDARY selection
205   ecore_x_selection_secondary_clear();
206 }
207
208 bool Clipboard::IsVisible() const
209 {
210   return false;
211 }
212
213 char* Clipboard::ExcuteBuffered( bool type, void *event )
214 {
215   if( !type )
216   {
217     // Receive
218     Ecore_X_Event_Selection_Notify* selectionNotifyEvent = static_cast< Ecore_X_Event_Selection_Notify* >( event );
219
220     Ecore_X_Selection_Data* selectionData = static_cast< Ecore_X_Selection_Data* >( selectionNotifyEvent->data );
221     if( selectionData->data )
222     {
223       if( selectionNotifyEvent->selection == ECORE_X_SELECTION_SECONDARY )
224       {
225         // Claim the ownership of the SECONDARY selection.
226         ecore_x_selection_secondary_set( mImpl->mApplicationWindow, "", 1 );
227
228         return ( reinterpret_cast< char* >( selectionData->data ) );
229       }
230     }
231   }
232   return NULL;
233 }
234
235 } // namespace Adaptor
236
237 } // namespace Internal
238
239 } // namespace Dali