Add localized strings for copied to clipboard
[framework/web/webkit-efl.git] / Source / WebKit2 / UIProcess / API / efl / tizen / ClipboardHelper.cpp
1 /*
2  * Copyright (C) 2012 Samsung Electronics
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
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.
12  *
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.
24  */
25
26 #include "config.h"
27
28 #if ENABLE(TIZEN_WEBKIT2_CLIPBOARD_HELPER)
29 #include "ClipboardHelper.h"
30
31 #include "PageClientImpl.h"
32 #include <Evas.h>
33 #include <Ecore_Evas.h>
34 #include <Ecore_X.h>
35 #include <Elementary.h>
36 #include <X11/Xatom.h>
37 #include <X11/Xlib.h>
38
39 namespace WebKit {
40
41 #if ENABLE(TIZEN_WEBKIT2_CONTEXT_MENU_CLIPBOARD)
42 enum ClipType
43 {
44     CLIP_TYPE_PRIMARY,
45     CLIP_TYPE_SECONDARY,
46     CLIP_TYPE_CLIPBOARD,
47     CLIP_TYPE_XDND,
48     CLIP_TYPE_MAX,
49 };
50
51 struct ClipData
52 {
53     Ecore_X_Selection selection;
54     void (* request)(Ecore_X_Window window, const char* pTarget);
55
56     Elm_Sel_Format format;
57
58     Elm_Sel_Format requestedFormat;
59     int bufferLength;
60
61     ClipboardHelper* clipboardHelper;
62 };
63
64 typedef int (*ClipNotifyHandler)(ClipData* clipData, Ecore_X_Event_Selection_Notify* notifyData);
65
66 enum
67 {
68     ATOM_TARGETS = 0,
69     ATOM_ATOM,
70     ATOM_LISTING_ATOMS = ATOM_ATOM,
71     ATOM_TEXT_URI,
72     ATOM_TEXT_URILIST,
73     ATOM_TEXT_X_VCARD,
74     ATOM_IMAGE_PNG,
75     ATOM_IMAGE_JPEG,
76     ATOM_IMAGE_BMP,
77     ATOM_IMAGE_GIF,
78     ATOM_IMAGE_TIFF,
79     ATOM_IMAGE_SVG,
80     ATOM_IMAGE_XPM,
81     ATOM_IMAGE_TGA,
82     ATOM_IMAGE_PPM,
83     ATOM_XELM,
84     ATOM_TEXT_HTML_UTF8,
85     ATOM_TEXT_HTML,
86     ATOM_STRING_UTF8,
87     ATOM_STRING,
88     ATOM_TEXT,
89     ATOM_TEXT_PLAIN_UTF8,
90     ATOM_TEXT_PLAIN,
91     ATOM_MAX,
92 };
93 struct AtomData
94 {
95     const char* pName;
96     Elm_Sel_Format formats;
97     ClipNotifyHandler notify;
98     Ecore_X_Atom atom;
99 };
100
101 AtomData atomList[ATOM_MAX];
102 ClipData clipList[CLIP_TYPE_MAX];
103
104 static Eina_Bool cbhmPropertyChangeCallback(void* data, int type, void* event);
105 static Eina_Bool clientMessageCallback(void* data, int type, void* event);
106 #endif
107
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)
116 #endif
117 {
118 #if ENABLE(TIZEN_WEBKIT2_CONTEXT_MENU_CLIPBOARD)
119     m_clientMessageHandler = ecore_event_handler_add(ECORE_X_EVENT_CLIENT_MESSAGE, clientMessageCallback, this);
120 #endif
121 }
122
123 ClipboardHelper::~ClipboardHelper()
124 {
125 #if ENABLE(TIZEN_WEBKIT2_CONTEXT_MENU_CLIPBOARD)
126     ecore_event_handler_del(m_clientMessageHandler);
127     m_clientMessageHandler = 0;
128     clearClipboardSelectionHandler();
129 #endif
130 }
131
132 // This function references from elementary's cbhm_helper.c
133 int ClipboardHelper::numberOfItems()
134 {
135     // 1. Get CBHM Ecore_X_Window.
136     Ecore_X_Atom xAtom;
137     xAtom = ecore_x_atom_get("CBHM_XWIN");
138     if (!xAtom)
139         return 0;
140
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);
144
145     Ecore_X_Window xWindow = 0;
146     if (result && numberOfWindow)
147         memcpy(&xWindow, data, sizeof(Ecore_X_Window));
148
149     if (data)
150         free(data);
151
152     if (!xWindow)
153         return 0;
154
155     ecore_x_sync();
156
157     // 2. Get number of clipboard items.
158     xAtom = ecore_x_atom_get("CBHM_cCOUNT");
159     if (!xAtom)
160         return 0;
161
162     Display* display = static_cast<Display*>(ecore_x_display_get());
163
164     Ecore_X_Atom type;
165     int format;
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)
172         return 0;
173
174     if (!numberOfItems) {
175         XFree(dataInFormat);
176         return 0;
177     }
178
179     if (!(data = static_cast<unsigned char*>(malloc(numberOfItems * format / 8)))) {
180         XFree(dataInFormat);
181         return 0;
182     }
183
184     switch (format) {
185     case 8:
186         for (long unsigned i = 0; i < numberOfItems; i++)
187             (data)[i] = dataInFormat[i];
188         break;
189     case 16:
190         for (long unsigned i = 0; i < numberOfItems; i++)
191             (reinterpret_cast<unsigned short*>(data))[i] = (reinterpret_cast<unsigned short*>(dataInFormat))[i];
192         break;
193     case 32:
194         for (long unsigned i = 0; i < numberOfItems; i++)
195             (reinterpret_cast<unsigned int*>(data))[i] = (reinterpret_cast<unsigned long*>(dataInFormat))[i];
196         break;
197     }
198
199     XFree(dataInFormat);
200
201     if (data) {
202         char count = atoi(reinterpret_cast<const char*>(data));
203         free(data);
204         return count;
205     }
206
207     return 0;
208 }
209
210 void ClipboardHelper::setData(const String& data, const String& type)
211 {
212     Ecore_X_Atom dataType = 0;
213
214     showSavedNotiPopup();
215
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);
223         return;
224     }
225
226     setClipboardItem(dataType, data);
227 }
228
229 void ClipboardHelper::clear()
230 {
231     elm_object_cnp_selection_clear(elm_object_parent_widget_get(m_viewImpl->view()), ELM_SEL_TYPE_CLIPBOARD);
232 }
233
234 void ClipboardHelper::processResult(const String& data, const String& type)
235 {
236     MutexLocker locker(m_callbackQueueLock);
237     while(!m_callbackQueue.isEmpty()) {
238         RefPtr<ClipboardCallback> callback = m_callbackQueue.takeFirst();
239         callback->performCallback(data, type);
240     }
241 }
242
243 #if ENABLE(TIZEN_WEBKIT2_CONTEXT_MENU_CLIPBOARD)
244 Eina_Bool cbhmPropertyChangeCallback(void* data, int type, void* event)
245 {
246     ClipboardHelper *clipboardHelper = static_cast<ClipboardHelper*>(data);
247     Ecore_X_Event_Window_Property *ev = (Ecore_X_Event_Window_Property*) event;
248
249     if (ev->atom != ECORE_X_ATOM_E_ILLUME_CLIPBOARD_STATE)
250         return ECORE_CALLBACK_PASS_ON;
251
252     clipboardHelper->updateClipboardWindowState(ev);
253
254     return ECORE_CALLBACK_PASS_ON;
255 }
256
257 Eina_Bool clientMessageCallback(void* data, int type, void* event)
258 {
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;
262
263     if (ev->message_type != ecore_x_atom_get("CBHM_MSG"))
264         return ECORE_CALLBACK_PASS_ON;
265
266     if (!strcmp("SET_OWNER", ev->data.b)) {
267         clipboardHelper->openClipboardWindow(clipboardHelper->page()->editorState().isContentRichlyEditable);
268     }
269
270     return ECORE_CALLBACK_PASS_ON;
271 }
272
273 static void pasteSelectedClipboardItem(const String& data, const String& type, ClipboardHelper* clipboardHelper)
274 {
275     clipboardHelper->page()->executePasteFromClipboardItem(data, type);
276
277     clipboardHelper->connectClipboardWindow();
278 }
279
280 static Eina_Bool clearClip(void* data, int type, void* event)
281 {
282     Ecore_X_Event_Selection_Clear* clearEvent = (Ecore_X_Event_Selection_Clear*) event;
283     Ecore_X_Window window = clearEvent->win;
284
285     ClipType clipType = CLIP_TYPE_SECONDARY;
286     clipList[clipType].requestedFormat = static_cast<Elm_Sel_Format>(ELM_SEL_FORMAT_TEXT | ELM_SEL_FORMAT_IMAGE);
287
288     ecore_x_selection_secondary_request(window, ECORE_X_SELECTION_TARGET_TARGETS);
289
290     return ECORE_CALLBACK_PASS_ON;
291 }
292
293 static Eina_Bool notifyClip(void* data , int type, void* event)
294 {
295     Ecore_X_Event_Selection_Notify* notifytEvent = (Ecore_X_Event_Selection_Notify*) event;
296
297     int i = 0;
298     for (i = 0; i < CLIP_TYPE_MAX; i++) {
299         if (clipList[i].selection == notifytEvent->selection) {
300             break;
301         }
302     }
303
304     ClipData* clipData = clipList + i;
305
306     clipData->clipboardHelper= static_cast<ClipboardHelper*>(data);
307
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);
312             }
313         }
314     }
315
316     return ECORE_CALLBACK_PASS_ON;
317 }
318
319 static int notifyTarget(ClipData* clipData, Ecore_X_Event_Selection_Notify* notifyData)
320 {
321     Ecore_X_Atom dataType = 0;
322
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);
326
327         if (dataType == htmlType) {
328             clipData->request(notifyData->win, pHtmlAtomName);
329             return ECORE_CALLBACK_PASS_ON;
330         }
331     }
332
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);
335
336     int i, j = 0;
337     for (j = (ATOM_LISTING_ATOMS+1); j < ATOM_MAX; j++) {
338
339         if (!(atomList[j].formats & clipData->requestedFormat))
340             continue;
341
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)))
345                     continue;
346
347                 goto FOUND;
348             }
349         }
350     }
351
352     return ECORE_CALLBACK_PASS_ON;
353
354     FOUND:
355     clipData->request(notifyData->win, atomList[j].pName);
356     return ECORE_CALLBACK_PASS_ON;
357 }
358
359 static int notifyText(ClipData* clipData, Ecore_X_Event_Selection_Notify* notifyData)
360 {
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);
363
364     return 0;
365 }
366
367 static int notifyImage(ClipData* clipData, Ecore_X_Event_Selection_Notify* notifyData)
368 {
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);
371
372     return 0;
373 }
374
375 static int notifyUri(ClipData* clipData, Ecore_X_Event_Selection_Notify* notifyData)
376 {
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);
379
380     return 0;
381 }
382
383 static int notifyEdje(ClipData* clipData, Ecore_X_Event_Selection_Notify* notifyData)
384 {
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);
387
388     return 0;
389 }
390
391 static int notifyHtml(ClipData* clipData, Ecore_X_Event_Selection_Notify* notifyData)
392 {
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);
395
396     return 0;
397 }
398
399 void ClipboardHelper::initializeAtomList()
400 {
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;
405
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;
410
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;
415
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;
420
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;
425
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;
430
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;
435
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;
440
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;
445
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;
450
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;
455
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;
460
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;
465
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;
470
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;
475
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;
480
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;
485
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;
490
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;
495
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;
500
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;
505
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;
510
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;
514
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;
518
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;
522
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;
526
527     for (int i = 0; i < ATOM_MAX; i++)
528         atomList[i].atom = ecore_x_atom_get(atomList[i].pName);
529
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);
533 }
534
535 Ecore_X_Window ClipboardHelper::getCbhmWindow()
536 {
537     Ecore_X_Atom xAtomCbhm = ecore_x_atom_get("CBHM_XWIN");
538     Ecore_X_Window xCbhmWin = 0;
539
540     unsigned char* buf = 0;
541     int num = 0;
542     int ret = ecore_x_window_prop_property_get(0, xAtomCbhm, XA_WINDOW, 0, &buf, &num);
543
544     if (ret && num)
545         memcpy(&xCbhmWin, buf, sizeof(Ecore_X_Window));
546
547     if (buf)
548         free(buf);
549
550     return xCbhmWin;
551 }
552
553 bool ClipboardHelper::sendCbhmMessage(String message)
554 {
555     Ecore_X_Window xCbhmWin = getCbhmWindow();
556     Ecore_X_Atom xAtomCbhmMsg = ecore_x_atom_get("CBHM_MSG");
557
558     if (!m_viewImpl->view())
559         return false;
560
561     Evas_Object* parent = elm_object_parent_widget_get(m_viewImpl->view());
562
563     if (!parent)
564         return false;
565
566     Ecore_X_Window xWin = ecore_evas_gl_x11_window_get(ecore_evas_ecore_evas_get(evas_object_evas_get(parent)));
567     if (!xWin)
568         xWin = ecore_evas_software_x11_window_get(ecore_evas_ecore_evas_get(evas_object_evas_get(parent)));
569
570     if (!xCbhmWin || !xAtomCbhmMsg)
571         return false;
572
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());
581
582     XSendEvent(static_cast<Display *> (ecore_x_display_get()), xCbhmWin, false, NoEventMask, (XEvent*)&messageEvent);
583
584     ecore_x_sync();
585
586     return true;
587 }
588
589 bool ClipboardHelper::setClipboardItem(Ecore_X_Atom dataType,const String& data)
590 {
591     Ecore_X_Window cbhmWin = getCbhmWindow();
592     Ecore_X_Atom atomCbhmItem = ecore_x_atom_get("CBHM_ITEM");
593
594     CString utfData = data.utf8();
595
596     ecore_x_sync();
597     ecore_x_window_prop_property_set(cbhmWin, atomCbhmItem, dataType, 8, const_cast<char*>(utfData.data()), utfData.length() + 1);
598     ecore_x_sync();
599
600     if (sendCbhmMessage(String::fromUTF8(static_cast<const char*>("SET_ITEM"))))
601         return true;
602
603     return false;
604 }
605
606 void ClipboardHelper::openClipboardWindow(bool isContentRichlyEditable)
607 {
608     clearClipboardSelectionHandler();
609
610     initializeAtomList();
611     if (isContentRichlyEditable)
612         sendCbhmMessage(String::fromUTF8(static_cast<const char*>("show1")));
613     else
614         sendCbhmMessage(String::fromUTF8(static_cast<const char*>("show0")));
615
616     connectClipboardWindow();
617
618     evas_object_smart_callback_call(m_viewImpl->view(), "clipboard,opened", 0);
619
620 #if ENABLE(TIZEN_WEBKIT2_TEXT_SELECTION)
621     m_viewImpl->pageClient->updateTextSelectionHandlesAndContextMenu(false);
622 #endif
623 }
624
625 void ClipboardHelper::closeClipboardWindow()
626 {
627     sendCbhmMessage(String::fromUTF8(static_cast<const char*>("cbhm_hide")));
628 }
629
630 bool ClipboardHelper::isClipboardWindowOpened()
631 {
632     return m_clipboardWindowOpened;
633 }
634
635 void ClipboardHelper::connectClipboardWindow()
636 {
637     ecore_x_selection_secondary_set(elm_win_xwindow_get(elm_object_parent_widget_get(m_viewImpl->view())), "",1);
638 }
639
640 void ClipboardHelper::clearClipboardSelectionHandler()
641 {
642     if (m_selectionClearHandler) {
643         ecore_event_handler_del(m_selectionClearHandler);
644         m_selectionClearHandler = 0;
645     }
646     if (m_selectionNotifyHandler) {
647         ecore_event_handler_del(m_selectionNotifyHandler);
648         m_selectionNotifyHandler = 0;
649     }
650     if (m_cbhmPropertyChangeHandler) {
651         ecore_event_handler_del(m_cbhmPropertyChangeHandler);
652         m_cbhmPropertyChangeHandler = 0;
653     }
654     m_clipboardWindowOpened = false;
655 }
656
657 bool ClipboardHelper::getSelectedCbhmItem(Ecore_X_Atom* pDataType)
658 {
659     Ecore_X_Window cbhmWin = getCbhmWindow();
660     Ecore_X_Atom atomCbhmItem = ecore_x_atom_get("CBHM_SELECTED_ITEM");
661     Ecore_X_Atom atomItemType = 0;
662
663     String result = getCbhmReply(cbhmWin, atomCbhmItem, &atomItemType);
664
665     if(result.isNull())
666         return false;
667
668     if (atomItemType == ecore_x_atom_get("CBHM_ERROR"))
669         return false;
670
671     if (pDataType)
672         *pDataType = atomItemType;
673
674     return true;
675 }
676
677 String ClipboardHelper::getCbhmReply(Ecore_X_Window xwin, Ecore_X_Atom property, Ecore_X_Atom* pDataType)
678 {
679     if (!property)
680         return String();
681
682     ecore_x_sync();
683
684     Ecore_X_Atom type;
685     int dataUnitSize = 0;
686     long unsigned int dataLength = 0;
687     long unsigned int bytes = 0;
688     unsigned char* pData = 0;
689
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)
693         return String();
694
695     if (!dataLength) {
696         XFree(pData);
697         return String();
698     }
699
700     String chbmData;
701
702     switch (dataUnitSize) {
703     case 8:
704         chbmData = String::fromUTF8(pData, dataLength);
705         break;
706     case 16:
707         chbmData = String(reinterpret_cast<UChar*>(pData), dataLength);
708         LOG_ERROR("case 16");
709         break;
710     case 32:
711         LOG_ERROR("case 32");
712         break;
713     default:
714         LOG_ERROR("case %d", dataUnitSize);
715     }
716
717     XFree(pData);
718
719     if (pDataType)
720         *pDataType = type;
721
722     return chbmData;
723 }
724
725 bool ClipboardHelper::retrieveClipboardItem(int index, int* format, String* pData)
726 {
727     if (!pData)
728         return false;
729
730     Ecore_X_Window cbhmWin = getCbhmWindow();
731
732     Ecore_X_Atom atomCbhmItem = ecore_x_atom_get(String::format("CBHM_ITEM%d", index).utf8().data());
733     Ecore_X_Atom atomItemType = 0;
734
735     String result = getCbhmReply(cbhmWin, atomCbhmItem, &atomItemType);
736     if (result.isNull())
737         return false;
738
739     *pData = result;
740
741     Ecore_X_Atom dataType = atomItemType;
742
743     if (atomItemType == ecore_x_atom_get("CBHM_ERROR"))
744         return false;
745
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;
752     else
753         return false;
754
755     return true;
756 }
757
758 void ClipboardHelper::pasteClipboardLastItem(bool isContentEditable)
759 {
760     int count = numberOfItems();
761
762     // Find the item with dataTypes.
763     int format = ELM_SEL_FORMAT_NONE;
764     String clipboardData;
765
766     for (int i = 0; i < count; i++) {
767         // Get the clip with index.
768         bool ret = retrieveClipboardItem(i, &format, &clipboardData);
769
770         if (!ret)
771             continue;
772
773         if (isContentEditable)
774             break;
775         else {
776             if (format == ELM_SEL_FORMAT_TEXT || format == ELM_SEL_FORMAT_MARKUP || format == ELM_SEL_FORMAT_HTML)
777                 break;
778         }
779     }
780
781     switch(format) {
782     case ELM_SEL_FORMAT_TEXT:
783     case ELM_SEL_FORMAT_MARKUP:
784         page()->didSelectPasteMenuFromContextMenu(clipboardData, String("PlainText"));
785         break;
786     case ELM_SEL_FORMAT_HTML:
787         page()->didSelectPasteMenuFromContextMenu(clipboardData, String("Markup"));
788         break;
789     case ELM_SEL_FORMAT_IMAGE:
790         page()->didSelectPasteMenuFromContextMenu(clipboardData, String("Image"));
791         break;
792     default:
793         page()->didSelectPasteMenuFromContextMenu(String(""), String("PlainText"));
794         break;
795     }
796 }
797
798 void ClipboardHelper::updateClipboardWindowState(Ecore_X_Event_Window_Property* ev)
799 {
800     Ecore_X_Illume_Clipboard_State state = ecore_x_e_illume_clipboard_state_get(ev->win);
801
802     if (state == ECORE_X_ILLUME_CLIPBOARD_STATE_UNKNOWN)
803         state = ecore_x_e_illume_clipboard_state_get(ev->win);
804
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;
809 }
810
811 void ClipboardHelper::showSavedNotiPopup()
812 {
813     bindtextdomain("WebKit", WEBKIT_TEXT_DIR);
814
815     Evas_Object* parent = elm_object_parent_widget_get(m_viewImpl->view());
816     Evas_Object* notify = elm_notify_add(parent);
817     if (!notify) {
818         TIZEN_LOGE("elm_notify_add failed");
819         return;
820     }
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);
824
825     Evas_Object* notifyLayout = elm_layout_add(notify);
826     if (!notifyLayout) {
827         TIZEN_LOGE("elm_layout_add failed");
828         return;
829     }
830
831     if (elm_win_rotation_get(parent) % 180)
832         elm_layout_theme_set(notifyLayout, "standard", "selectioninfo", "horizontal/bottom_64");
833     else
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);
840
841     evas_object_show(notify);
842 }
843 #endif // TIZEN_WEBKIT2_CONTEXT_MENU_CLIPBOARD
844 }// namespace WebKit
845
846 #endif // TIZEN_WEBKIT2_CLIPBOARD_HELPER