2 * Copyright (c) 2023 Samsung Electronics Co., Ltd.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 #include <dali/internal/clipboard/common/clipboard-impl.h>
22 #include <dali/integration-api/debug.h>
23 #include <dali/internal/system/linux/dali-ecore-x.h>
24 #include <dali/public-api/object/any.h>
25 #include <dali/public-api/object/type-registry.h>
28 #include <dali/devel-api/common/singleton-service.h>
29 #include <dali/internal/adaptor/common/adaptor-impl.h>
30 #include <dali/internal/clipboard/common/clipboard-event-notifier-impl.h>
31 #include <dali/internal/window-system/ubuntu-x11/window-interface-ecore-x.h>
33 namespace //unnamed namespace
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";
45 ///////////////////////////////////////////////////////////////////////////////////////////////////
47 ///////////////////////////////////////////////////////////////////////////////////////////////////
55 struct Clipboard::Impl
57 Impl(Ecore_X_Window ecoreXwin)
59 mApplicationWindow = ecoreXwin;
62 Ecore_X_Window mApplicationWindow;
65 Clipboard::Clipboard(Impl* impl)
70 Clipboard::~Clipboard()
75 Dali::Clipboard Clipboard::Get()
77 Dali::Clipboard clipboard;
79 Dali::SingletonService service(SingletonService::Get());
82 // Check whether the singleton is already created
83 Dali::BaseHandle handle = service.GetSingleton(typeid(Dali::Clipboard));
86 // If so, downcast the handle
87 clipboard = Dali::Clipboard(dynamic_cast<Clipboard*>(handle.GetObjectPtr()));
91 Adaptor& adaptorImpl(Adaptor::GetImplementation(Adaptor::Get()));
92 Any nativewindow = adaptorImpl.GetNativeWindowHandle();
94 // The Ecore_X_Window needs to use the Clipboard.
95 // Only when the render surface is window, we can get the Ecore_X_Window.
96 Ecore_X_Window ecoreXwin(AnyCast<Ecore_X_Window>(nativewindow));
99 // If we fail to get Ecore_X_Window, we can't use the Clipboard correctly.
100 // Thus you have to call "ecore_imf_context_client_window_set" somewhere.
101 // In EvasPlugIn, this function is called in EvasPlugin::ConnectEcoreEvent().
102 Clipboard::Impl* impl(new Clipboard::Impl(ecoreXwin));
103 clipboard = Dali::Clipboard(new Clipboard(impl));
104 service.Register(typeid(clipboard), clipboard);
112 bool Clipboard::IsAvailable()
114 Dali::SingletonService service(SingletonService::Get());
117 Dali::BaseHandle handle = service.GetSingleton(typeid(Dali::Clipboard));
126 bool Clipboard::SetItem(const std::string& itemData)
128 Ecore_X_Window cbhmWin = ECore::WindowInterface::GetWindow();
129 Ecore_X_Atom atomCbhmItem = ecore_x_atom_get(CBHM_ITEM);
130 Ecore_X_Atom dataType = ECORE_X_ATOM_STRING;
132 // Set item (property) to send
133 ecore_x_window_prop_property_set(cbhmWin, atomCbhmItem, dataType, 8, const_cast<char*>(itemData.c_str()), itemData.length() + 1);
136 // Trigger sending of item (property)
137 Ecore_X_Atom atomCbhmMsg = ecore_x_atom_get(CBHM_MSG);
138 ECore::WindowInterface::SendXEvent(ecore_x_display_get(), cbhmWin, False, NoEventMask, atomCbhmMsg, 8, SET_ITEM);
143 * Request clipboard service to retrieve an item
145 void Clipboard::RequestItem()
149 snprintf(sendBuf, 20, "%s%d", CBHM_ITEM, index);
150 Ecore_X_Atom xAtomCbhmItem = ecore_x_atom_get(sendBuf);
151 Ecore_X_Atom xAtomItemType = 0;
153 std::string clipboardString(ECore::WindowInterface::GetWindowProperty(xAtomCbhmItem, &xAtomItemType, index));
155 // Only return the text string if the Atom type is text (Do not return a text string/URL for images).
156 if(!clipboardString.empty() &&
157 (xAtomItemType == ECORE_X_ATOM_TEXT || xAtomItemType == ECORE_X_ATOM_COMPOUND_TEXT || xAtomItemType == ECORE_X_ATOM_STRING || xAtomItemType == ECORE_X_ATOM_UTF8_STRING))
159 Ecore_X_Atom xAtomCbhmError = ecore_x_atom_get(CBHM_ERROR);
160 if(xAtomItemType != xAtomCbhmError)
162 // Call ClipboardEventNotifier to notify event observe of retrieved string
163 Dali::ClipboardEventNotifier clipboardEventNotifier(ClipboardEventNotifier::Get());
164 if(clipboardEventNotifier)
166 ClipboardEventNotifier& notifierImpl(ClipboardEventNotifier::GetImplementation(clipboardEventNotifier));
168 notifierImpl.SetContent(clipboardString);
169 notifierImpl.EmitContentSelectedSignal();
176 * Get number of items in clipboard
178 unsigned int Clipboard::NumberOfItems()
180 Ecore_X_Atom xAtomCbhmCountGet = ecore_x_atom_get(CBHM_cCOUNT);
182 std::string ret(ECore::WindowInterface::GetWindowProperty(xAtomCbhmCountGet, NULL, 0));
187 count = atoi(ret.c_str());
194 * Show clipboard window
195 * Function to send message to show the Clipboard (cbhm) as no direct API available
196 * Reference elementary/src/modules/ctxpopup_copypasteUI/cbhm_helper.c
198 void Clipboard::ShowClipboard()
200 // Claim the ownership of the SECONDARY selection.
201 ecore_x_selection_secondary_set(mImpl->mApplicationWindow, "", 1);
202 Ecore_X_Window cbhmWin = ECore::WindowInterface::GetWindow();
204 // Launch the clipboard window
205 Ecore_X_Atom atomCbhmMsg = ecore_x_atom_get(CBHM_MSG);
206 ECore::WindowInterface::SendXEvent(ecore_x_display_get(), cbhmWin, False, NoEventMask, atomCbhmMsg, 8, SHOW);
209 void Clipboard::HideClipboard(bool skipFirstHide)
211 Ecore_X_Window cbhmWin = ECore::WindowInterface::GetWindow();
212 // Launch the clipboard window
213 Ecore_X_Atom atomCbhmMsg = ecore_x_atom_get(CBHM_MSG);
214 ECore::WindowInterface::SendXEvent(ecore_x_display_get(), cbhmWin, False, NoEventMask, atomCbhmMsg, 8, HIDE);
216 // release the ownership of SECONDARY selection
217 ecore_x_selection_secondary_clear();
220 bool Clipboard::IsVisible() const
225 void Clipboard::ExcuteSend(void* event)
229 void Clipboard::ExcuteReceive(void* event, char*& data, int& length)
232 Ecore_X_Event_Selection_Notify* selectionNotifyEvent = static_cast<Ecore_X_Event_Selection_Notify*>(event);
234 Ecore_X_Selection_Data* selectionData = static_cast<Ecore_X_Selection_Data*>(selectionNotifyEvent->data);
235 if(selectionData->data)
237 if(selectionNotifyEvent->selection == ECORE_X_SELECTION_SECONDARY)
239 // Claim the ownership of the SECONDARY selection.
240 ecore_x_selection_secondary_set(mImpl->mApplicationWindow, "", 1);
241 data = reinterpret_cast<char*>(selectionData->data);
242 length = selectionData->length;
247 } // namespace Adaptor
249 } // namespace Internal