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 #if ENABLE(TIZEN_WEBKIT2_CONTEXT_MENU_CLIPBOARD)
53 Ecore_X_Selection selection;
54 void (* request)(Ecore_X_Window window, const char* pTarget);
56 Elm_Sel_Format format;
58 Elm_Sel_Format requestedFormat;
61 ClipboardHelper* clipboardHelper;
64 typedef int (*ClipNotifyHandler)(ClipData* clipData, Ecore_X_Event_Selection_Notify* notifyData);
70 ATOM_LISTING_ATOMS = ATOM_ATOM,
96 Elm_Sel_Format formats;
97 ClipNotifyHandler notify;
101 AtomData atomList[ATOM_MAX];
102 ClipData clipList[CLIP_TYPE_MAX];
104 static Eina_Bool cbhmPropertyChangeCallback(void* data, int type, void* event);
105 static Eina_Bool clientMessageCallback(void* data, int type, void* event);
108 ClipboardHelper::ClipboardHelper(EwkViewImpl* viewImpl)
109 : m_viewImpl(viewImpl)
110 #if ENABLE(TIZEN_WEBKIT2_CONTEXT_MENU_CLIPBOARD)
111 , m_clipboardWindowOpened(false)
112 , m_cbhmPropertyChangeHandler(0)
113 , m_selectionClearHandler(0)
114 , m_selectionNotifyHandler(0)
115 , m_clientMessageHandler(0)
118 #if ENABLE(TIZEN_WEBKIT2_CONTEXT_MENU_CLIPBOARD)
119 m_clientMessageHandler = ecore_event_handler_add(ECORE_X_EVENT_CLIENT_MESSAGE, clientMessageCallback, this);
123 ClipboardHelper::~ClipboardHelper()
125 #if ENABLE(TIZEN_WEBKIT2_CONTEXT_MENU_CLIPBOARD)
126 ecore_event_handler_del(m_clientMessageHandler);
127 m_clientMessageHandler = 0;
128 clearClipboardSelectionHandler();
132 // This function references from elementary's cbhm_helper.c
133 int ClipboardHelper::numberOfItems()
135 // 1. Get CBHM Ecore_X_Window.
137 xAtom = ecore_x_atom_get("CBHM_XWIN");
141 unsigned char* data = 0;
142 int numberOfWindow = 0;
143 int result = ecore_x_window_prop_property_get(0, xAtom, XA_WINDOW, 0, &data, &numberOfWindow);
145 Ecore_X_Window xWindow = 0;
146 if (result && numberOfWindow)
147 memcpy(&xWindow, data, sizeof(Ecore_X_Window));
157 // 2. Get number of clipboard items.
158 xAtom = ecore_x_atom_get("CBHM_cCOUNT");
162 Display* display = static_cast<Display*>(ecore_x_display_get());
166 long unsigned numberOfItems = 0;
167 long unsigned bytes = 0;
168 unsigned char* dataInFormat = 0;
169 result = XGetWindowProperty(display, xWindow, xAtom, 0, LONG_MAX, False, ecore_x_window_prop_any_type(),
170 reinterpret_cast<Atom*>(&type), &format, &numberOfItems, &bytes, &dataInFormat);
171 if (result != Success)
174 if (!numberOfItems) {
179 if (!(data = static_cast<unsigned char*>(malloc(numberOfItems * format / 8)))) {
186 for (long unsigned i = 0; i < numberOfItems; i++)
187 (data)[i] = dataInFormat[i];
190 for (long unsigned i = 0; i < numberOfItems; i++)
191 (reinterpret_cast<unsigned short*>(data))[i] = (reinterpret_cast<unsigned short*>(dataInFormat))[i];
194 for (long unsigned i = 0; i < numberOfItems; i++)
195 (reinterpret_cast<unsigned int*>(data))[i] = (reinterpret_cast<unsigned long*>(dataInFormat))[i];
202 char count = atoi(reinterpret_cast<const char*>(data));
210 void ClipboardHelper::setData(const String& data, const String& type)
212 Ecore_X_Atom dataType = 0;
214 showSavedNotiPopup();
216 if (type == "PlainText" || type == "URIList" || type == "URL")
217 dataType = ecore_x_atom_get("UTF8_STRING");
218 else if (type == "Markup")
219 dataType = ecore_x_atom_get("text/html;charset=utf-8");
220 else if (type == "Image") {
221 elm_cnp_selection_set(elm_object_parent_widget_get(m_viewImpl->view()), ELM_SEL_TYPE_CLIPBOARD,
222 ELM_SEL_FORMAT_IMAGE, data.utf8().data(), data.length() + 1);
226 setClipboardItem(dataType, data);
229 void ClipboardHelper::clear()
231 elm_object_cnp_selection_clear(elm_object_parent_widget_get(m_viewImpl->view()), ELM_SEL_TYPE_CLIPBOARD);
234 void ClipboardHelper::processResult(const String& data, const String& type)
236 MutexLocker locker(m_callbackQueueLock);
237 while(!m_callbackQueue.isEmpty()) {
238 RefPtr<ClipboardCallback> callback = m_callbackQueue.takeFirst();
239 callback->performCallback(data, type);
243 #if ENABLE(TIZEN_WEBKIT2_CONTEXT_MENU_CLIPBOARD)
244 Eina_Bool cbhmPropertyChangeCallback(void* data, int type, void* event)
246 ClipboardHelper *clipboardHelper = static_cast<ClipboardHelper*>(data);
247 Ecore_X_Event_Window_Property *ev = (Ecore_X_Event_Window_Property*) event;
249 if (ev->atom != ECORE_X_ATOM_E_ILLUME_CLIPBOARD_STATE)
250 return ECORE_CALLBACK_PASS_ON;
252 clipboardHelper->updateClipboardWindowState(ev);
254 return ECORE_CALLBACK_PASS_ON;
257 Eina_Bool clientMessageCallback(void* data, int type, void* event)
259 //This callback function is support for open CBHM window from IME clipboard button
260 ClipboardHelper *clipboardHelper = static_cast<ClipboardHelper*>(data);
261 Ecore_X_Event_Client_Message *ev = (Ecore_X_Event_Client_Message*) event;
263 if (ev->message_type != ecore_x_atom_get("CBHM_MSG"))
264 return ECORE_CALLBACK_PASS_ON;
266 if (!strcmp("SET_OWNER", ev->data.b)) {
267 clipboardHelper->openClipboardWindow(clipboardHelper->page()->editorState().isContentRichlyEditable);
270 return ECORE_CALLBACK_PASS_ON;
273 static void pasteSelectedClipboardItem(const String& data, const String& type, ClipboardHelper* clipboardHelper)
275 clipboardHelper->page()->executePasteFromClipboardItem(data, type);
277 clipboardHelper->connectClipboardWindow();
280 static Eina_Bool clearClip(void* data, int type, void* event)
282 Ecore_X_Event_Selection_Clear* clearEvent = (Ecore_X_Event_Selection_Clear*) event;
283 Ecore_X_Window window = clearEvent->win;
285 ClipType clipType = CLIP_TYPE_SECONDARY;
286 clipList[clipType].requestedFormat = static_cast<Elm_Sel_Format>(ELM_SEL_FORMAT_TEXT | ELM_SEL_FORMAT_IMAGE);
288 ecore_x_selection_secondary_request(window, ECORE_X_SELECTION_TARGET_TARGETS);
290 return ECORE_CALLBACK_PASS_ON;
293 static Eina_Bool notifyClip(void* data , int type, void* event)
295 Ecore_X_Event_Selection_Notify* notifytEvent = (Ecore_X_Event_Selection_Notify*) event;
298 for (i = 0; i < CLIP_TYPE_MAX; i++) {
299 if (clipList[i].selection == notifytEvent->selection) {
304 ClipData* clipData = clipList + i;
306 clipData->clipboardHelper= static_cast<ClipboardHelper*>(data);
308 for (i = 0; i < ATOM_MAX; i++) {
309 if (!strcmp(notifytEvent->target, atomList[i].pName)) {
310 if (atomList[i].notify) {
311 atomList[i].notify(clipData, notifytEvent);
316 return ECORE_CALLBACK_PASS_ON;
319 static int notifyTarget(ClipData* clipData, Ecore_X_Event_Selection_Notify* notifyData)
321 Ecore_X_Atom dataType = 0;
323 if (clipData->clipboardHelper->getSelectedCbhmItem(&dataType)) {
324 const char* pHtmlAtomName = "text/html;charset=utf-8";
325 Ecore_X_Atom htmlType = ecore_x_atom_get(pHtmlAtomName);
327 if (dataType == htmlType) {
328 clipData->request(notifyData->win, pHtmlAtomName);
329 return ECORE_CALLBACK_PASS_ON;
333 Ecore_X_Selection_Data_Targets* pTargets = (Ecore_X_Selection_Data_Targets*) (notifyData->data);
334 Ecore_X_Atom* pAtomList = (Ecore_X_Atom*) (pTargets->data.data);
337 for (j = (ATOM_LISTING_ATOMS+1); j < ATOM_MAX; j++) {
339 if (!(atomList[j].formats & clipData->requestedFormat))
342 for (i = 0; i < pTargets->data.length; i++) {
343 if ((atomList[j].atom == pAtomList[i]) && (atomList[j].notify)) {
344 if ((j == ATOM_XELM) && (!(clipData->requestedFormat & ELM_SEL_FORMAT_MARKUP)))
352 return ECORE_CALLBACK_PASS_ON;
355 clipData->request(notifyData->win, atomList[j].pName);
356 return ECORE_CALLBACK_PASS_ON;
359 static int notifyText(ClipData* clipData, Ecore_X_Event_Selection_Notify* notifyData)
361 Ecore_X_Selection_Data* pData = (Ecore_X_Selection_Data*) notifyData->data;
362 pasteSelectedClipboardItem(String::fromUTF8(pData->data, (int)pData->length), String("PlainText"), clipData->clipboardHelper);
367 static int notifyImage(ClipData* clipData, Ecore_X_Event_Selection_Notify* notifyData)
369 Ecore_X_Selection_Data* pData = (Ecore_X_Selection_Data*) notifyData->data;
370 pasteSelectedClipboardItem(String::fromUTF8(pData->data, (int)pData->length), String("Image"), clipData->clipboardHelper);
375 static int notifyUri(ClipData* clipData, Ecore_X_Event_Selection_Notify* notifyData)
377 Ecore_X_Selection_Data* pData = (Ecore_X_Selection_Data*) notifyData->data;
378 pasteSelectedClipboardItem(String::fromUTF8(pData->data, (int)pData->length), String("Image"), clipData->clipboardHelper);
383 static int notifyEdje(ClipData* clipData, Ecore_X_Event_Selection_Notify* notifyData)
385 Ecore_X_Selection_Data* pData = (Ecore_X_Selection_Data*) notifyData->data;
386 pasteSelectedClipboardItem(String::fromUTF8(pData->data, (int)pData->length), String("PlainText"), clipData->clipboardHelper);
391 static int notifyHtml(ClipData* clipData, Ecore_X_Event_Selection_Notify* notifyData)
393 Ecore_X_Selection_Data* pData = (Ecore_X_Selection_Data*) notifyData->data;
394 pasteSelectedClipboardItem(String::fromUTF8(pData->data, (int)pData->length), String("Markup"), clipData->clipboardHelper);
399 void ClipboardHelper::initializeAtomList()
401 atomList[ATOM_TARGETS].pName = "TARGETS";
402 atomList[ATOM_TARGETS].formats = ELM_SEL_FORMAT_TARGETS;
403 atomList[ATOM_TARGETS].notify = notifyTarget;
404 atomList[ATOM_TARGETS].atom = 0;
406 atomList[ATOM_ATOM].pName = "ATOM";
407 atomList[ATOM_ATOM].formats = ELM_SEL_FORMAT_TARGETS;
408 atomList[ATOM_ATOM].notify = notifyTarget;
409 atomList[ATOM_ATOM].atom = 0;
411 atomList[ATOM_XELM].pName = "application/x-elementary-markup";
412 atomList[ATOM_XELM].formats = ELM_SEL_FORMAT_MARKUP;
413 atomList[ATOM_XELM].notify = notifyEdje;
414 atomList[ATOM_XELM].atom = 0;
416 atomList[ATOM_TEXT_URI].pName = "text/uri";
417 atomList[ATOM_TEXT_URI].formats = ELM_SEL_FORMAT_IMAGE;
418 atomList[ATOM_TEXT_URI].notify = notifyUri;
419 atomList[ATOM_TEXT_URI].atom = 0;
421 atomList[ATOM_TEXT_URILIST].pName = "text/uri-list";
422 atomList[ATOM_TEXT_URILIST].formats = ELM_SEL_FORMAT_IMAGE;
423 atomList[ATOM_TEXT_URILIST].notify = notifyUri;
424 atomList[ATOM_TEXT_URILIST].atom = 0;
426 atomList[ATOM_TEXT_X_VCARD].pName = "text/x-vcard";
427 atomList[ATOM_TEXT_X_VCARD].formats = ELM_SEL_FORMAT_VCARD;
428 atomList[ATOM_TEXT_X_VCARD].notify = 0;
429 atomList[ATOM_TEXT_X_VCARD].atom = 0;
431 atomList[ATOM_IMAGE_PNG].pName = "image/png";
432 atomList[ATOM_IMAGE_PNG].formats = ELM_SEL_FORMAT_IMAGE;
433 atomList[ATOM_IMAGE_PNG].notify = notifyImage;
434 atomList[ATOM_IMAGE_PNG].atom = 0;
436 atomList[ATOM_IMAGE_JPEG].pName = "image/jpeg";
437 atomList[ATOM_IMAGE_JPEG].formats = ELM_SEL_FORMAT_IMAGE;
438 atomList[ATOM_IMAGE_JPEG].notify = notifyImage;
439 atomList[ATOM_IMAGE_JPEG].atom = 0;
441 atomList[ATOM_IMAGE_BMP].pName = "image/x-ms-bmp";
442 atomList[ATOM_IMAGE_BMP].formats = ELM_SEL_FORMAT_IMAGE;
443 atomList[ATOM_IMAGE_BMP].notify = notifyImage;
444 atomList[ATOM_IMAGE_BMP].atom = 0;
446 atomList[ATOM_IMAGE_GIF].pName = "image/gif";
447 atomList[ATOM_IMAGE_GIF].formats = ELM_SEL_FORMAT_IMAGE;
448 atomList[ATOM_IMAGE_GIF].notify = notifyImage;
449 atomList[ATOM_IMAGE_GIF].atom = 0;
451 atomList[ATOM_IMAGE_TIFF].pName = "image/tiff";
452 atomList[ATOM_IMAGE_TIFF].formats = ELM_SEL_FORMAT_IMAGE;
453 atomList[ATOM_IMAGE_TIFF].notify = notifyImage;
454 atomList[ATOM_IMAGE_TIFF].atom = 0;
456 atomList[ATOM_IMAGE_SVG].pName = "image/svg+xml";
457 atomList[ATOM_IMAGE_SVG].formats = ELM_SEL_FORMAT_IMAGE;
458 atomList[ATOM_IMAGE_SVG].notify = notifyImage;
459 atomList[ATOM_IMAGE_SVG].atom = 0;
461 atomList[ATOM_IMAGE_XPM].pName = "image/x-xpixmap";
462 atomList[ATOM_IMAGE_XPM].formats = ELM_SEL_FORMAT_IMAGE;
463 atomList[ATOM_IMAGE_XPM].notify = notifyImage;
464 atomList[ATOM_IMAGE_XPM].atom = 0;
466 atomList[ATOM_IMAGE_TGA].pName = "image/x-tga";
467 atomList[ATOM_IMAGE_TGA].formats = ELM_SEL_FORMAT_IMAGE;
468 atomList[ATOM_IMAGE_TGA].notify = notifyImage;
469 atomList[ATOM_IMAGE_TGA].atom = 0;
471 atomList[ATOM_IMAGE_PPM].pName = "image/x-portable-pixmap";
472 atomList[ATOM_IMAGE_PPM].formats = ELM_SEL_FORMAT_IMAGE;
473 atomList[ATOM_IMAGE_PPM].notify = notifyImage;
474 atomList[ATOM_IMAGE_PPM].atom = 0;
476 atomList[ATOM_TEXT_HTML_UTF8].pName = "text/html;charset=utf-8";
477 atomList[ATOM_TEXT_HTML_UTF8].formats = ELM_SEL_FORMAT_HTML;
478 atomList[ATOM_TEXT_HTML_UTF8].notify = notifyHtml;
479 atomList[ATOM_TEXT_HTML_UTF8].atom = 0;
481 atomList[ATOM_TEXT_HTML].pName = "text/html";
482 atomList[ATOM_TEXT_HTML].formats = ELM_SEL_FORMAT_HTML;
483 atomList[ATOM_TEXT_HTML].notify = notifyHtml;
484 atomList[ATOM_TEXT_HTML].atom = 0;
486 atomList[ATOM_STRING_UTF8].pName = "UTF8_STRING";
487 atomList[ATOM_STRING_UTF8].formats = static_cast<Elm_Sel_Format> (ELM_SEL_FORMAT_TEXT| ELM_SEL_FORMAT_MARKUP| ELM_SEL_FORMAT_HTML);
488 atomList[ATOM_STRING_UTF8].notify = notifyText;
489 atomList[ATOM_STRING_UTF8].atom = 0;
491 atomList[ATOM_STRING].pName = "STRING";
492 atomList[ATOM_STRING].formats = static_cast<Elm_Sel_Format> (ELM_SEL_FORMAT_TEXT| ELM_SEL_FORMAT_MARKUP| ELM_SEL_FORMAT_HTML);
493 atomList[ATOM_STRING].notify = notifyText;
494 atomList[ATOM_STRING].atom = 0;
496 atomList[ATOM_TEXT].pName = "TEXT";
497 atomList[ATOM_TEXT].formats = static_cast<Elm_Sel_Format> (ELM_SEL_FORMAT_TEXT| ELM_SEL_FORMAT_MARKUP| ELM_SEL_FORMAT_HTML);
498 atomList[ATOM_TEXT].notify = 0;
499 atomList[ATOM_TEXT].atom = 0;
501 atomList[ATOM_TEXT_PLAIN_UTF8].pName = "text/plain;charset=utf-8";
502 atomList[ATOM_TEXT_PLAIN_UTF8].formats = static_cast<Elm_Sel_Format> (ELM_SEL_FORMAT_TEXT| ELM_SEL_FORMAT_MARKUP| ELM_SEL_FORMAT_HTML);
503 atomList[ATOM_TEXT_PLAIN_UTF8].notify = 0;
504 atomList[ATOM_TEXT_PLAIN_UTF8].atom = 0;
506 atomList[ATOM_TEXT_PLAIN].pName = "text/plain";
507 atomList[ATOM_TEXT_PLAIN].formats = static_cast<Elm_Sel_Format> (ELM_SEL_FORMAT_TEXT| ELM_SEL_FORMAT_MARKUP| ELM_SEL_FORMAT_HTML);
508 atomList[ATOM_TEXT_PLAIN].notify = 0;
509 atomList[ATOM_TEXT_PLAIN].atom = 0;
511 clipList[CLIP_TYPE_PRIMARY].selection = ECORE_X_SELECTION_PRIMARY;
512 clipList[CLIP_TYPE_PRIMARY].request = ecore_x_selection_primary_request;
513 clipList[CLIP_TYPE_PRIMARY].bufferLength = 0;
515 clipList[CLIP_TYPE_SECONDARY].selection = ECORE_X_SELECTION_SECONDARY;
516 clipList[CLIP_TYPE_SECONDARY].request = ecore_x_selection_secondary_request;
517 clipList[CLIP_TYPE_SECONDARY].bufferLength = 0;
519 clipList[CLIP_TYPE_CLIPBOARD].selection = ECORE_X_SELECTION_CLIPBOARD;
520 clipList[CLIP_TYPE_CLIPBOARD].request = ecore_x_selection_clipboard_request;
521 clipList[CLIP_TYPE_CLIPBOARD].bufferLength = 0;
523 clipList[CLIP_TYPE_XDND].selection = ECORE_X_SELECTION_XDND;
524 clipList[CLIP_TYPE_XDND].request = ecore_x_selection_xdnd_request;
525 clipList[CLIP_TYPE_XDND].bufferLength = 0;
527 for (int i = 0; i < ATOM_MAX; i++)
528 atomList[i].atom = ecore_x_atom_get(atomList[i].pName);
530 m_cbhmPropertyChangeHandler = ecore_event_handler_add(ECORE_X_EVENT_WINDOW_PROPERTY, cbhmPropertyChangeCallback, this);
531 m_selectionClearHandler = ecore_event_handler_add(ECORE_X_EVENT_SELECTION_CLEAR, clearClip, this);
532 m_selectionNotifyHandler = ecore_event_handler_add(ECORE_X_EVENT_SELECTION_NOTIFY, notifyClip, this);
535 Ecore_X_Window ClipboardHelper::getCbhmWindow()
537 Ecore_X_Atom xAtomCbhm = ecore_x_atom_get("CBHM_XWIN");
538 Ecore_X_Window xCbhmWin = 0;
540 unsigned char* buf = 0;
542 int ret = ecore_x_window_prop_property_get(0, xAtomCbhm, XA_WINDOW, 0, &buf, &num);
545 memcpy(&xCbhmWin, buf, sizeof(Ecore_X_Window));
553 bool ClipboardHelper::sendCbhmMessage(String message)
555 Ecore_X_Window xCbhmWin = getCbhmWindow();
556 Ecore_X_Atom xAtomCbhmMsg = ecore_x_atom_get("CBHM_MSG");
558 if (!m_viewImpl->view())
561 Evas_Object* parent = elm_object_parent_widget_get(m_viewImpl->view());
566 Ecore_X_Window xWin = ecore_evas_gl_x11_window_get(ecore_evas_ecore_evas_get(evas_object_evas_get(parent)));
568 xWin = ecore_evas_software_x11_window_get(ecore_evas_ecore_evas_get(evas_object_evas_get(parent)));
570 if (!xCbhmWin || !xAtomCbhmMsg)
573 XClientMessageEvent messageEvent;
574 memset(&messageEvent, 0, sizeof(messageEvent));
575 messageEvent.type = ClientMessage;
576 messageEvent.display = static_cast<Display *> (ecore_x_display_get());
577 messageEvent.window = xWin;
578 messageEvent.message_type = xAtomCbhmMsg;
579 messageEvent.format = 8;
580 snprintf(messageEvent.data.b, 20, "%s", message.utf8().data());
582 XSendEvent(static_cast<Display *> (ecore_x_display_get()), xCbhmWin, false, NoEventMask, (XEvent*)&messageEvent);
589 bool ClipboardHelper::setClipboardItem(Ecore_X_Atom dataType,const String& data)
591 Ecore_X_Window cbhmWin = getCbhmWindow();
592 Ecore_X_Atom atomCbhmItem = ecore_x_atom_get("CBHM_ITEM");
594 CString utfData = data.utf8();
597 ecore_x_window_prop_property_set(cbhmWin, atomCbhmItem, dataType, 8, const_cast<char*>(utfData.data()), utfData.length() + 1);
600 if (sendCbhmMessage(String::fromUTF8(static_cast<const char*>("SET_ITEM"))))
606 void ClipboardHelper::openClipboardWindow(bool isContentRichlyEditable)
608 clearClipboardSelectionHandler();
610 initializeAtomList();
611 if (isContentRichlyEditable)
612 sendCbhmMessage(String::fromUTF8(static_cast<const char*>("show1")));
614 sendCbhmMessage(String::fromUTF8(static_cast<const char*>("show0")));
616 connectClipboardWindow();
618 evas_object_smart_callback_call(m_viewImpl->view(), "clipboard,opened", 0);
620 #if ENABLE(TIZEN_WEBKIT2_TEXT_SELECTION)
621 m_viewImpl->pageClient->updateTextSelectionHandlesAndContextMenu(false);
625 void ClipboardHelper::closeClipboardWindow()
627 sendCbhmMessage(String::fromUTF8(static_cast<const char*>("cbhm_hide")));
630 bool ClipboardHelper::isClipboardWindowOpened()
632 return m_clipboardWindowOpened;
635 void ClipboardHelper::connectClipboardWindow()
637 ecore_x_selection_secondary_set(elm_win_xwindow_get(elm_object_parent_widget_get(m_viewImpl->view())), "",1);
640 void ClipboardHelper::clearClipboardSelectionHandler()
642 if (m_selectionClearHandler) {
643 ecore_event_handler_del(m_selectionClearHandler);
644 m_selectionClearHandler = 0;
646 if (m_selectionNotifyHandler) {
647 ecore_event_handler_del(m_selectionNotifyHandler);
648 m_selectionNotifyHandler = 0;
650 if (m_cbhmPropertyChangeHandler) {
651 ecore_event_handler_del(m_cbhmPropertyChangeHandler);
652 m_cbhmPropertyChangeHandler = 0;
654 m_clipboardWindowOpened = false;
657 bool ClipboardHelper::getSelectedCbhmItem(Ecore_X_Atom* pDataType)
659 Ecore_X_Window cbhmWin = getCbhmWindow();
660 Ecore_X_Atom atomCbhmItem = ecore_x_atom_get("CBHM_SELECTED_ITEM");
661 Ecore_X_Atom atomItemType = 0;
663 String result = getCbhmReply(cbhmWin, atomCbhmItem, &atomItemType);
668 if (atomItemType == ecore_x_atom_get("CBHM_ERROR"))
672 *pDataType = atomItemType;
677 String ClipboardHelper::getCbhmReply(Ecore_X_Window xwin, Ecore_X_Atom property, Ecore_X_Atom* pDataType)
685 int dataUnitSize = 0;
686 long unsigned int dataLength = 0;
687 long unsigned int bytes = 0;
688 unsigned char* pData = 0;
690 int result = XGetWindowProperty((Display*)ecore_x_display_get(), xwin, property, 0, LONG_MAX, False,
691 ecore_x_window_prop_any_type(), (Atom*)&type, &dataUnitSize, &dataLength, &bytes, &pData);
692 if (result != Success)
702 switch (dataUnitSize) {
704 chbmData = String::fromUTF8(pData, dataLength);
707 chbmData = String(reinterpret_cast<UChar*>(pData), dataLength);
708 LOG_ERROR("case 16");
711 LOG_ERROR("case 32");
714 LOG_ERROR("case %d", dataUnitSize);
725 bool ClipboardHelper::retrieveClipboardItem(int index, int* format, String* pData)
730 Ecore_X_Window cbhmWin = getCbhmWindow();
732 Ecore_X_Atom atomCbhmItem = ecore_x_atom_get(String::format("CBHM_ITEM%d", index).utf8().data());
733 Ecore_X_Atom atomItemType = 0;
735 String result = getCbhmReply(cbhmWin, atomCbhmItem, &atomItemType);
741 Ecore_X_Atom dataType = atomItemType;
743 if (atomItemType == ecore_x_atom_get("CBHM_ERROR"))
746 if ((dataType == ecore_x_atom_get("UTF8_STRING")) || (dataType == ecore_x_atom_get("application/x-elementary-markup")))
747 *format = ELM_SEL_FORMAT_TEXT;
748 else if (dataType == ecore_x_atom_get("text/uri"))
749 *format = ELM_SEL_FORMAT_IMAGE;
750 else if (dataType == ecore_x_atom_get("text/html;charset=utf-8"))
751 *format = ELM_SEL_FORMAT_HTML;
758 void ClipboardHelper::pasteClipboardLastItem(bool isContentEditable)
760 int count = numberOfItems();
762 // Find the item with dataTypes.
763 int format = ELM_SEL_FORMAT_NONE;
764 String clipboardData;
766 for (int i = 0; i < count; i++) {
767 // Get the clip with index.
768 bool ret = retrieveClipboardItem(i, &format, &clipboardData);
773 if (isContentEditable)
776 if (format == ELM_SEL_FORMAT_TEXT || format == ELM_SEL_FORMAT_MARKUP || format == ELM_SEL_FORMAT_HTML)
782 case ELM_SEL_FORMAT_TEXT:
783 case ELM_SEL_FORMAT_MARKUP:
784 page()->didSelectPasteMenuFromContextMenu(clipboardData, String("PlainText"));
786 case ELM_SEL_FORMAT_HTML:
787 page()->didSelectPasteMenuFromContextMenu(clipboardData, String("Markup"));
789 case ELM_SEL_FORMAT_IMAGE:
790 page()->didSelectPasteMenuFromContextMenu(clipboardData, String("Image"));
793 page()->didSelectPasteMenuFromContextMenu(String(""), String("PlainText"));
798 void ClipboardHelper::updateClipboardWindowState(Ecore_X_Event_Window_Property* ev)
800 Ecore_X_Illume_Clipboard_State state = ecore_x_e_illume_clipboard_state_get(ev->win);
802 if (state == ECORE_X_ILLUME_CLIPBOARD_STATE_UNKNOWN)
803 state = ecore_x_e_illume_clipboard_state_get(ev->win);
805 if (state == ECORE_X_ILLUME_CLIPBOARD_STATE_OFF)
806 clearClipboardSelectionHandler();
807 else if (state == ECORE_X_ILLUME_CLIPBOARD_STATE_ON)
808 m_clipboardWindowOpened = true;
811 void ClipboardHelper::showSavedNotiPopup()
813 bindtextdomain("WebKit", WEBKIT_TEXT_DIR);
815 Evas_Object* parent = elm_object_parent_widget_get(m_viewImpl->view());
816 Evas_Object* notify = elm_notify_add(parent);
818 TIZEN_LOGE("elm_notify_add failed");
821 elm_notify_align_set(notify, 0.5, 1.0);
822 evas_object_size_hint_weight_set(notify, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
823 evas_object_size_hint_align_set(notify, EVAS_HINT_FILL, EVAS_HINT_FILL);
825 Evas_Object* notifyLayout = elm_layout_add(notify);
827 TIZEN_LOGE("elm_layout_add failed");
831 if (elm_win_rotation_get(parent) % 180)
832 elm_layout_theme_set(notifyLayout, "standard", "selectioninfo", "horizontal/bottom_64");
834 elm_layout_theme_set(notifyLayout, "standard", "selectioninfo", "vertical/bottom_64");
835 evas_object_size_hint_weight_set(notifyLayout, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
836 evas_object_size_hint_align_set(notifyLayout, EVAS_HINT_FILL, EVAS_HINT_FILL);
837 elm_object_content_set(notify, notifyLayout);
838 edje_object_part_text_set(elm_layout_edje_get(notifyLayout), "elm.text", dgettext("WebKit","IDS_COM_POP_COPIED_TO_CLIPBOARD"));
839 elm_notify_timeout_set(notify, 2);
841 evas_object_show(notify);
843 #endif // TIZEN_WEBKIT2_CONTEXT_MENU_CLIPBOARD
846 #endif // TIZEN_WEBKIT2_CLIPBOARD_HELPER