2 * Copyright (C) 2012 Samsung Electronics
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23 * THE POSSIBILITY OF SUCH DAMAGE.
28 #if ENABLE(TIZEN_WEBKIT2_CLIPBOARD_HELPER)
29 #include "ClipboardHelper.h"
31 #include "PageClientImpl.h"
33 #include <Ecore_Evas.h>
35 #include <Elementary.h>
36 #include <X11/Xatom.h>
41 static Eina_Bool clearSelectionCallback(void* context, int type, void* event);
43 ClipboardHelper::~ClipboardHelper()
45 #if ENABLE(TIZEN_WEBKIT2_CONTEXT_MENU_CLIPBOARD)
46 clearClipboardSelectionClearHandler();
50 // This function references from elementary's cbhm_helper.c
51 int ClipboardHelper::numberOfItems()
53 // 1. Get CBHM Ecore_X_Window.
55 xAtom = ecore_x_atom_get("CBHM_XWIN");
59 unsigned char* data = 0;
60 int numberOfWindow = 0;
61 int result = ecore_x_window_prop_property_get(0, xAtom, XA_WINDOW, 0, &data, &numberOfWindow);
63 Ecore_X_Window xWindow = 0;
64 if (result && numberOfWindow)
65 memcpy(&xWindow, data, sizeof(Ecore_X_Window));
75 // 2. Get number of clipboard items.
76 xAtom = ecore_x_atom_get("CBHM_cCOUNT");
80 Display* display = static_cast<Display*>(ecore_x_display_get());
84 long unsigned numberOfItems = 0;
85 long unsigned bytes = 0;
86 unsigned char* dataInFormat = 0;
87 result = XGetWindowProperty(display, xWindow, xAtom, 0, LONG_MAX, False, ecore_x_window_prop_any_type(),
88 reinterpret_cast<Atom*>(&type), &format, &numberOfItems, &bytes, &dataInFormat);
89 if (result != Success)
97 if (!(data = static_cast<unsigned char*>(malloc(numberOfItems * format / 8)))) {
104 for (long unsigned i = 0; i < numberOfItems; i++)
105 (data)[i] = dataInFormat[i];
108 for (long unsigned i = 0; i < numberOfItems; i++)
109 (reinterpret_cast<unsigned short*>(data))[i] = (reinterpret_cast<unsigned short*>(dataInFormat))[i];
112 for (long unsigned i = 0; i < numberOfItems; i++)
113 (reinterpret_cast<unsigned int*>(data))[i] = (reinterpret_cast<unsigned long*>(dataInFormat))[i];
120 char count = atoi(reinterpret_cast<const char*>(data));
128 void ClipboardHelper::setData(const String& data, const String& type)
130 if (type == "PlainText" || type == "URIList" || type == "URL") {
131 elm_cnp_selection_set(elm_object_parent_widget_get(m_ewkView), ELM_SEL_TYPE_CLIPBOARD,
132 ELM_SEL_FORMAT_TEXT, data.utf8().data(), data.length());
133 } else if (type == "Markup") {
134 elm_cnp_selection_set(elm_object_parent_widget_get(m_ewkView), ELM_SEL_TYPE_CLIPBOARD,
135 ELM_SEL_FORMAT_HTML, data.utf8().data(), data.length());
136 } else if (type == "Image") {
137 // FIXME: We pass data.length() + 1 because of a bug in elementary which adds some random characters
138 // to copied image path. '+1' should be removed when the bug will be fixed on elementary side.
139 elm_cnp_selection_set(elm_object_parent_widget_get(m_ewkView), ELM_SEL_TYPE_CLIPBOARD,
140 ELM_SEL_FORMAT_IMAGE, data.utf8().data(), data.length() + 1);
144 void ClipboardHelper::clear()
146 elm_object_cnp_selection_clear(elm_object_parent_widget_get(m_ewkView), ELM_SEL_TYPE_CLIPBOARD);
149 static Eina_Bool requestClipboardDataCallback(void* data, Evas_Object* object, Elm_Selection_Data* selectionData)
151 ClipboardHelper* helper = static_cast<ClipboardHelper*>(data);
153 if (!selectionData || selectionData->len <= 0) {
154 helper->processResult(String(""), String("PlainText"));
158 String clipboardData = String::fromUTF8(static_cast<const char*>(selectionData->data));
159 switch(selectionData->format) {
160 case ELM_SEL_FORMAT_TEXT:
161 helper->processResult(clipboardData, String("PlainText"));
163 case ELM_SEL_FORMAT_HTML:
164 helper->processResult(clipboardData, String("Markup"));
166 case ELM_SEL_FORMAT_IMAGE:
167 helper->processResult(clipboardData, String("Image"));
170 helper->processResult(String(""), String("PlainText"));
177 void ClipboardHelper::requestData(void* context, ClipboardDataResultFunction function, SelectionType type)
182 Elm_Sel_Type selectionType;
184 case SelectionTypePrimary:
185 selectionType = ELM_SEL_TYPE_PRIMARY;
187 case SelectionTypeSecondary:
188 selectionType = ELM_SEL_TYPE_SECONDARY;
190 case SelectionTypeXDND:
191 selectionType = ELM_SEL_TYPE_XDND;
194 selectionType = ELM_SEL_TYPE_CLIPBOARD;
197 Eina_Bool result = elm_cnp_selection_get(elm_object_parent_widget_get(m_ewkView), selectionType,
198 static_cast<Elm_Sel_Format>(ELM_SEL_FORMAT_TEXT | ELM_SEL_FORMAT_HTML | ELM_SEL_FORMAT_IMAGE),
199 requestClipboardDataCallback, this);
202 function(String(""), String("PlainText"), context);
206 MutexLocker locker(m_callbackQueueLock);
207 m_callbackQueue.append(ClipboardCallback::create(context, function));
210 void ClipboardHelper::processResult(const String& data, const String& type)
212 MutexLocker locker(m_callbackQueueLock);
213 while(!m_callbackQueue.isEmpty()) {
214 RefPtr<ClipboardCallback> callback = m_callbackQueue.takeFirst();
215 callback->performCallback(data, type);
219 #if ENABLE(TIZEN_WEBKIT2_CONTEXT_MENU_CLIPBOARD)
220 void ClipboardHelper::openClipboardWindow(bool isRichEditable)
222 clearClipboardSelectionClearHandler();
223 m_selectionClearHandler = ecore_event_handler_add(ECORE_X_EVENT_SELECTION_CLEAR, clearSelectionCallback, this);
225 Ecore_X_Atom xAtomCbhm = ecore_x_atom_get("CBHM_XWIN");
226 unsigned char* buf = 0;
228 int ret = ecore_x_window_prop_property_get(0, xAtomCbhm, XA_WINDOW, 0, &buf, &num);
230 Ecore_X_Window xCbhmWin;
232 memcpy(&xCbhmWin, buf, sizeof(Ecore_X_Window));
236 Ecore_X_Atom xAtomCbhmMsg = ecore_x_atom_get("CBHM_MSG");
237 Evas_Object* parent = elm_object_parent_widget_get(m_ewkView);
238 Ecore_X_Window xWin = ecore_evas_gl_x11_window_get(ecore_evas_ecore_evas_get(evas_object_evas_get(parent)));
240 xWin = ecore_evas_software_x11_window_get(ecore_evas_ecore_evas_get(evas_object_evas_get(parent)));
242 if (!xCbhmWin || !xAtomCbhmMsg)
245 XClientMessageEvent messageEvent;
246 memset(&messageEvent, 0, sizeof(messageEvent));
247 messageEvent.type = ClientMessage;
248 messageEvent.display = static_cast<Display *> (ecore_x_display_get());
249 messageEvent.window = xWin;
250 messageEvent.message_type = xAtomCbhmMsg;
251 messageEvent.format = 8;
254 snprintf(messageEvent.data.b, 20, "%s", "show1");
256 snprintf(messageEvent.data.b, 20, "%s", "show0");
258 XSendEvent(static_cast<Display *> (ecore_x_display_get()), xCbhmWin, false, NoEventMask, (XEvent*)&messageEvent);
260 connectClipboardWindow();
264 evas_object_smart_callback_call(m_ewkView, "clipboard,opened", 0);
265 m_pageClient->updateTextSelectionHandlesAndContextMenu(false);
268 bool ClipboardHelper::isClipboardWindowOpened()
270 char* windowTitle = ecore_x_icccm_title_get(ecore_x_window_focus_get());
275 if (!(strcmp("Clipboard History Manager", windowTitle)))
281 void ClipboardHelper::connectClipboardWindow()
283 ecore_x_selection_secondary_set(elm_win_xwindow_get(elm_object_parent_widget_get(m_ewkView)), "",1);
286 void ClipboardHelper::clearClipboardSelectionClearHandler()
288 if (m_selectionClearHandler) {
289 ecore_event_handler_del(m_selectionClearHandler);
290 m_selectionClearHandler = 0;
294 static void clipboardDataCallbackForClipboardMenu(const String& data, const String& type, void* context)
296 ClipboardHelper* clipboardHelper = static_cast<ClipboardHelper*>(context);
297 clipboardHelper->pageClient()->page()->executePasteFromClipboardItem(data, type);
299 clipboardHelper->connectClipboardWindow();
302 static Eina_Bool clearSelectionCallback(void* context, int type, void* event)
304 ClipboardHelper* clipboardHelper = static_cast<ClipboardHelper*>(context);
306 Ecore_X_Event_Selection_Clear *ev = static_cast<Ecore_X_Event_Selection_Clear*>(event);
307 if (ev->selection != ECORE_X_SELECTION_SECONDARY)
311 clipboardHelper->requestData(clipboardHelper, clipboardDataCallbackForClipboardMenu, ClipboardHelper::SelectionTypeSecondary);
315 #endif // TIZEN_WEBKIT2_CONTEXT_MENU_CLIPBOARD
318 #endif // TIZEN_WEBKIT2_CLIPBOARD_HELPER