Merge "Add copySurfaceTye argument to copySurface function." into tizen_2.1
[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 clientMessageCallback(void* data, int type, void* event);
105 #endif
106
107 ClipboardHelper::ClipboardHelper(EwkViewImpl* viewImpl)
108     : m_viewImpl(viewImpl)
109 #if ENABLE(TIZEN_WEBKIT2_CONTEXT_MENU_CLIPBOARD)
110     , m_selectionClearHandler(0)
111     , m_selectionNotifyHandler(0)
112     , m_clientMessageHandler(0)
113 #endif
114 {
115 #if ENABLE(TIZEN_WEBKIT2_CONTEXT_MENU_CLIPBOARD)
116     m_clientMessageHandler = ecore_event_handler_add(ECORE_X_EVENT_CLIENT_MESSAGE, clientMessageCallback, this);
117 #endif
118 }
119
120 ClipboardHelper::~ClipboardHelper()
121 {
122 #if ENABLE(TIZEN_WEBKIT2_CONTEXT_MENU_CLIPBOARD)
123     ecore_event_handler_del(m_clientMessageHandler);
124     m_clientMessageHandler = 0;
125     clearClipboardSelectionHandler();
126 #endif
127 }
128
129 // This function references from elementary's cbhm_helper.c
130 int ClipboardHelper::numberOfItems()
131 {
132     // 1. Get CBHM Ecore_X_Window.
133     Ecore_X_Atom xAtom;
134     xAtom = ecore_x_atom_get("CBHM_XWIN");
135     if (!xAtom)
136         return 0;
137
138     unsigned char* data = 0;
139     int numberOfWindow = 0;
140     int result = ecore_x_window_prop_property_get(0, xAtom, XA_WINDOW, 0, &data, &numberOfWindow);
141
142     Ecore_X_Window xWindow = 0;
143     if (result && numberOfWindow)
144         memcpy(&xWindow, data, sizeof(Ecore_X_Window));
145
146     if (data)
147         free(data);
148
149     if (!xWindow)
150         return 0;
151
152     ecore_x_sync();
153
154     // 2. Get number of clipboard items.
155     xAtom = ecore_x_atom_get("CBHM_cCOUNT");
156     if (!xAtom)
157         return 0;
158
159     Display* display = static_cast<Display*>(ecore_x_display_get());
160
161     Ecore_X_Atom type;
162     int format;
163     long unsigned numberOfItems = 0;
164     long unsigned bytes = 0;
165     unsigned char* dataInFormat = 0;
166     result = XGetWindowProperty(display, xWindow, xAtom, 0, LONG_MAX, False, ecore_x_window_prop_any_type(),
167                                 reinterpret_cast<Atom*>(&type), &format, &numberOfItems, &bytes, &dataInFormat);
168     if (result != Success)
169         return 0;
170
171     if (!numberOfItems) {
172         XFree(dataInFormat);
173         return 0;
174     }
175
176     if (!(data = static_cast<unsigned char*>(malloc(numberOfItems * format / 8)))) {
177         XFree(dataInFormat);
178         return 0;
179     }
180
181     switch (format) {
182     case 8:
183         for (long unsigned i = 0; i < numberOfItems; i++)
184             (data)[i] = dataInFormat[i];
185         break;
186     case 16:
187         for (long unsigned i = 0; i < numberOfItems; i++)
188             (reinterpret_cast<unsigned short*>(data))[i] = (reinterpret_cast<unsigned short*>(dataInFormat))[i];
189         break;
190     case 32:
191         for (long unsigned i = 0; i < numberOfItems; i++)
192             (reinterpret_cast<unsigned int*>(data))[i] = (reinterpret_cast<unsigned long*>(dataInFormat))[i];
193         break;
194     }
195
196     XFree(dataInFormat);
197
198     if (data) {
199         char count = atoi(reinterpret_cast<const char*>(data));
200         free(data);
201         return count;
202     }
203
204     return 0;
205 }
206
207 void ClipboardHelper::setData(const String& data, const String& type)
208 {
209     Ecore_X_Atom dataType = 0;
210
211     if (type == "PlainText" || type == "URIList" || type == "URL")
212         dataType = ecore_x_atom_get("UTF8_STRING");
213     else if (type == "Markup")
214         dataType = ecore_x_atom_get("text/html;charset=utf-8");
215     else if (type == "Image") {
216         elm_cnp_selection_set(elm_object_parent_widget_get(m_viewImpl->view()), ELM_SEL_TYPE_CLIPBOARD,
217                               ELM_SEL_FORMAT_IMAGE, data.utf8().data(), data.length() + 1);
218         return;
219     }
220
221     setClipboardItem(dataType, data);
222 }
223
224 void ClipboardHelper::clear()
225 {
226     elm_object_cnp_selection_clear(elm_object_parent_widget_get(m_viewImpl->view()), ELM_SEL_TYPE_CLIPBOARD);
227 }
228
229 void ClipboardHelper::processResult(const String& data, const String& type)
230 {
231     MutexLocker locker(m_callbackQueueLock);
232     while(!m_callbackQueue.isEmpty()) {
233         RefPtr<ClipboardCallback> callback = m_callbackQueue.takeFirst();
234         callback->performCallback(data, type);
235     }
236 }
237
238 #if ENABLE(TIZEN_WEBKIT2_CONTEXT_MENU_CLIPBOARD)
239 Eina_Bool clientMessageCallback(void* data, int type, void* event)
240 {
241     //This callback function is support for open CBHM window from IME clipboard button
242     ClipboardHelper *clipboardHelper = static_cast<ClipboardHelper*>(data);
243     Ecore_X_Event_Client_Message *ev = (Ecore_X_Event_Client_Message*) event;
244
245     if (ev->message_type != ecore_x_atom_get("CBHM_MSG"))
246         return ECORE_CALLBACK_PASS_ON;
247
248     if (!strcmp("SET_OWNER", ev->data.b)) {
249         clipboardHelper->openClipboardWindow(clipboardHelper->page()->editorState().isContentRichlyEditable);
250     }
251
252     return ECORE_CALLBACK_PASS_ON;
253 }
254
255 static void pasteSelectedClipboardItem(const String& data, const String& type, ClipboardHelper* clipboardHelper)
256 {
257     clipboardHelper->page()->executePasteFromClipboardItem(data, type);
258
259     clipboardHelper->connectClipboardWindow();
260 }
261
262 static Eina_Bool clearClip(void* data, int type, void* event)
263 {
264     Ecore_X_Event_Selection_Clear* clearEvent = (Ecore_X_Event_Selection_Clear*) event;
265     Ecore_X_Window window = clearEvent->win;
266
267     ClipType clipType = CLIP_TYPE_SECONDARY;
268     clipList[clipType].requestedFormat = static_cast<Elm_Sel_Format>(ELM_SEL_FORMAT_TEXT | ELM_SEL_FORMAT_IMAGE);
269
270     ecore_x_selection_secondary_request(window, ECORE_X_SELECTION_TARGET_TARGETS);
271
272     return ECORE_CALLBACK_PASS_ON;
273 }
274
275 static Eina_Bool notifyClip(void* data , int type, void* event)
276 {
277     Ecore_X_Event_Selection_Notify* notifytEvent = (Ecore_X_Event_Selection_Notify*) event;
278
279     int i = 0;
280     for (i = 0; i < CLIP_TYPE_MAX; i++) {
281         if (clipList[i].selection == notifytEvent->selection) {
282             break;
283         }
284     }
285
286     ClipData* clipData = clipList + i;
287
288     clipData->clipboardHelper= static_cast<ClipboardHelper*>(data);
289
290     for (i = 0; i < ATOM_MAX; i++) {
291         if (!strcmp(notifytEvent->target, atomList[i].pName)) {
292             if (atomList[i].notify) {
293                 atomList[i].notify(clipData, notifytEvent);
294             }
295         }
296     }
297
298     return ECORE_CALLBACK_PASS_ON;
299 }
300
301 static int notifyTarget(ClipData* clipData, Ecore_X_Event_Selection_Notify* notifyData)
302 {
303     Ecore_X_Atom dataType = 0;
304
305     if (clipData->clipboardHelper->getSelectedCbhmItem(&dataType)) {
306         const char* pHtmlAtomName = "text/html;charset=utf-8";
307         Ecore_X_Atom htmlType = ecore_x_atom_get(pHtmlAtomName);
308
309         if (dataType == htmlType) {
310             clipData->request(notifyData->win, pHtmlAtomName);
311             return ECORE_CALLBACK_PASS_ON;
312         }
313     }
314
315     Ecore_X_Selection_Data_Targets* pTargets = (Ecore_X_Selection_Data_Targets*) (notifyData->data);
316     Ecore_X_Atom* pAtomList = (Ecore_X_Atom*) (pTargets->data.data);
317
318     int i, j = 0;
319     for (j = (ATOM_LISTING_ATOMS+1); j < ATOM_MAX; j++) {
320
321         if (!(atomList[j].formats & clipData->requestedFormat))
322             continue;
323
324         for (i = 0; i < pTargets->data.length; i++) {
325             if ((atomList[j].atom == pAtomList[i]) && (atomList[j].notify)) {
326                 if ((j == ATOM_XELM) && (!(clipData->requestedFormat & ELM_SEL_FORMAT_MARKUP)))
327                     continue;
328
329                 goto FOUND;
330             }
331         }
332     }
333
334     return ECORE_CALLBACK_PASS_ON;
335
336     FOUND:
337     clipData->request(notifyData->win, atomList[j].pName);
338     return ECORE_CALLBACK_PASS_ON;
339 }
340
341 static int notifyText(ClipData* clipData, Ecore_X_Event_Selection_Notify* notifyData)
342 {
343     Ecore_X_Selection_Data* pData = (Ecore_X_Selection_Data*) notifyData->data;
344     pasteSelectedClipboardItem(String::fromUTF8(pData->data, (int)pData->length), String("PlainText"), clipData->clipboardHelper);
345
346     return 0;
347 }
348
349 static int notifyImage(ClipData* clipData, Ecore_X_Event_Selection_Notify* notifyData)
350 {
351     Ecore_X_Selection_Data* pData = (Ecore_X_Selection_Data*) notifyData->data;
352     pasteSelectedClipboardItem(String::fromUTF8(pData->data, (int)pData->length), String("Image"), clipData->clipboardHelper);
353
354     return 0;
355 }
356
357 static int notifyUri(ClipData* clipData, Ecore_X_Event_Selection_Notify* notifyData)
358 {
359     Ecore_X_Selection_Data* pData = (Ecore_X_Selection_Data*) notifyData->data;
360     pasteSelectedClipboardItem(String::fromUTF8(pData->data, (int)pData->length), String("Image"), clipData->clipboardHelper);
361
362     return 0;
363 }
364
365 static int notifyEdje(ClipData* clipData, Ecore_X_Event_Selection_Notify* notifyData)
366 {
367     Ecore_X_Selection_Data* pData = (Ecore_X_Selection_Data*) notifyData->data;
368     pasteSelectedClipboardItem(String::fromUTF8(pData->data, (int)pData->length), String("PlainText"), clipData->clipboardHelper);
369
370     return 0;
371 }
372
373 static int notifyHtml(ClipData* clipData, Ecore_X_Event_Selection_Notify* notifyData)
374 {
375     Ecore_X_Selection_Data* pData = (Ecore_X_Selection_Data*) notifyData->data;
376     pasteSelectedClipboardItem(String::fromUTF8(pData->data, (int)pData->length), String("Markup"), clipData->clipboardHelper);
377
378     return 0;
379 }
380
381 void ClipboardHelper::initializeAtomList()
382 {
383     atomList[ATOM_TARGETS].pName = "TARGETS";
384     atomList[ATOM_TARGETS].formats = ELM_SEL_FORMAT_TARGETS;
385     atomList[ATOM_TARGETS].notify = notifyTarget;
386     atomList[ATOM_TARGETS].atom = 0;
387
388     atomList[ATOM_ATOM].pName = "ATOM";
389     atomList[ATOM_ATOM].formats = ELM_SEL_FORMAT_TARGETS;
390     atomList[ATOM_ATOM].notify = notifyTarget;
391     atomList[ATOM_ATOM].atom = 0;
392
393     atomList[ATOM_XELM].pName = "application/x-elementary-markup";
394     atomList[ATOM_XELM].formats = ELM_SEL_FORMAT_MARKUP;
395     atomList[ATOM_XELM].notify = notifyEdje;
396     atomList[ATOM_XELM].atom = 0;
397
398     atomList[ATOM_TEXT_URI].pName = "text/uri";
399     atomList[ATOM_TEXT_URI].formats = ELM_SEL_FORMAT_IMAGE;
400     atomList[ATOM_TEXT_URI].notify = notifyUri;
401     atomList[ATOM_TEXT_URI].atom = 0;
402
403     atomList[ATOM_TEXT_URILIST].pName = "text/uri-list";
404     atomList[ATOM_TEXT_URILIST].formats = ELM_SEL_FORMAT_IMAGE;
405     atomList[ATOM_TEXT_URILIST].notify = notifyUri;
406     atomList[ATOM_TEXT_URILIST].atom = 0;
407
408     atomList[ATOM_TEXT_X_VCARD].pName = "text/x-vcard";
409     atomList[ATOM_TEXT_X_VCARD].formats = ELM_SEL_FORMAT_VCARD;
410     atomList[ATOM_TEXT_X_VCARD].notify = 0;
411     atomList[ATOM_TEXT_X_VCARD].atom = 0;
412
413     atomList[ATOM_IMAGE_PNG].pName = "image/png";
414     atomList[ATOM_IMAGE_PNG].formats = ELM_SEL_FORMAT_IMAGE;
415     atomList[ATOM_IMAGE_PNG].notify = notifyImage;
416     atomList[ATOM_IMAGE_PNG].atom = 0;
417
418     atomList[ATOM_IMAGE_JPEG].pName = "image/jpeg";
419     atomList[ATOM_IMAGE_JPEG].formats = ELM_SEL_FORMAT_IMAGE;
420     atomList[ATOM_IMAGE_JPEG].notify = notifyImage;
421     atomList[ATOM_IMAGE_JPEG].atom = 0;
422
423     atomList[ATOM_IMAGE_BMP].pName = "image/x-ms-bmp";
424     atomList[ATOM_IMAGE_BMP].formats = ELM_SEL_FORMAT_IMAGE;
425     atomList[ATOM_IMAGE_BMP].notify = notifyImage;
426     atomList[ATOM_IMAGE_BMP].atom = 0;
427
428     atomList[ATOM_IMAGE_GIF].pName = "image/gif";
429     atomList[ATOM_IMAGE_GIF].formats = ELM_SEL_FORMAT_IMAGE;
430     atomList[ATOM_IMAGE_GIF].notify = notifyImage;
431     atomList[ATOM_IMAGE_GIF].atom = 0;
432
433     atomList[ATOM_IMAGE_TIFF].pName = "image/tiff";
434     atomList[ATOM_IMAGE_TIFF].formats = ELM_SEL_FORMAT_IMAGE;
435     atomList[ATOM_IMAGE_TIFF].notify = notifyImage;
436     atomList[ATOM_IMAGE_TIFF].atom = 0;
437
438     atomList[ATOM_IMAGE_SVG].pName = "image/svg+xml";
439     atomList[ATOM_IMAGE_SVG].formats = ELM_SEL_FORMAT_IMAGE;
440     atomList[ATOM_IMAGE_SVG].notify = notifyImage;
441     atomList[ATOM_IMAGE_SVG].atom = 0;
442
443     atomList[ATOM_IMAGE_XPM].pName = "image/x-xpixmap";
444     atomList[ATOM_IMAGE_XPM].formats = ELM_SEL_FORMAT_IMAGE;
445     atomList[ATOM_IMAGE_XPM].notify = notifyImage;
446     atomList[ATOM_IMAGE_XPM].atom = 0;
447
448     atomList[ATOM_IMAGE_TGA].pName = "image/x-tga";
449     atomList[ATOM_IMAGE_TGA].formats = ELM_SEL_FORMAT_IMAGE;
450     atomList[ATOM_IMAGE_TGA].notify = notifyImage;
451     atomList[ATOM_IMAGE_TGA].atom = 0;
452
453     atomList[ATOM_IMAGE_PPM].pName = "image/x-portable-pixmap";
454     atomList[ATOM_IMAGE_PPM].formats = ELM_SEL_FORMAT_IMAGE;
455     atomList[ATOM_IMAGE_PPM].notify = notifyImage;
456     atomList[ATOM_IMAGE_PPM].atom = 0;
457
458     atomList[ATOM_TEXT_HTML_UTF8].pName = "text/html;charset=utf-8";
459     atomList[ATOM_TEXT_HTML_UTF8].formats = ELM_SEL_FORMAT_HTML;
460     atomList[ATOM_TEXT_HTML_UTF8].notify = notifyHtml;
461     atomList[ATOM_TEXT_HTML_UTF8].atom = 0;
462
463     atomList[ATOM_TEXT_HTML].pName = "text/html";
464     atomList[ATOM_TEXT_HTML].formats = ELM_SEL_FORMAT_HTML;
465     atomList[ATOM_TEXT_HTML].notify = notifyHtml;
466     atomList[ATOM_TEXT_HTML].atom = 0;
467
468     atomList[ATOM_STRING_UTF8].pName = "UTF8_STRING";
469     atomList[ATOM_STRING_UTF8].formats = static_cast<Elm_Sel_Format> (ELM_SEL_FORMAT_TEXT| ELM_SEL_FORMAT_MARKUP| ELM_SEL_FORMAT_HTML);
470     atomList[ATOM_STRING_UTF8].notify = notifyText;
471     atomList[ATOM_STRING_UTF8].atom = 0;
472
473     atomList[ATOM_STRING].pName = "STRING";
474     atomList[ATOM_STRING].formats = static_cast<Elm_Sel_Format> (ELM_SEL_FORMAT_TEXT| ELM_SEL_FORMAT_MARKUP| ELM_SEL_FORMAT_HTML);
475     atomList[ATOM_STRING].notify = notifyText;
476     atomList[ATOM_STRING].atom = 0;
477
478     atomList[ATOM_TEXT].pName = "TEXT";
479     atomList[ATOM_TEXT].formats = static_cast<Elm_Sel_Format> (ELM_SEL_FORMAT_TEXT| ELM_SEL_FORMAT_MARKUP| ELM_SEL_FORMAT_HTML);
480     atomList[ATOM_TEXT].notify = 0;
481     atomList[ATOM_TEXT].atom = 0;
482
483     atomList[ATOM_TEXT_PLAIN_UTF8].pName = "text/plain;charset=utf-8";
484     atomList[ATOM_TEXT_PLAIN_UTF8].formats = static_cast<Elm_Sel_Format> (ELM_SEL_FORMAT_TEXT| ELM_SEL_FORMAT_MARKUP| ELM_SEL_FORMAT_HTML);
485     atomList[ATOM_TEXT_PLAIN_UTF8].notify = 0;
486     atomList[ATOM_TEXT_PLAIN_UTF8].atom = 0;
487
488     atomList[ATOM_TEXT_PLAIN].pName = "text/plain";
489     atomList[ATOM_TEXT_PLAIN].formats = static_cast<Elm_Sel_Format> (ELM_SEL_FORMAT_TEXT| ELM_SEL_FORMAT_MARKUP| ELM_SEL_FORMAT_HTML);
490     atomList[ATOM_TEXT_PLAIN].notify = 0;
491     atomList[ATOM_TEXT_PLAIN].atom = 0;
492
493     clipList[CLIP_TYPE_PRIMARY].selection = ECORE_X_SELECTION_PRIMARY;
494     clipList[CLIP_TYPE_PRIMARY].request = ecore_x_selection_primary_request;
495     clipList[CLIP_TYPE_PRIMARY].bufferLength = 0;
496
497     clipList[CLIP_TYPE_SECONDARY].selection = ECORE_X_SELECTION_SECONDARY;
498     clipList[CLIP_TYPE_SECONDARY].request = ecore_x_selection_secondary_request;
499     clipList[CLIP_TYPE_SECONDARY].bufferLength = 0;
500
501     clipList[CLIP_TYPE_CLIPBOARD].selection = ECORE_X_SELECTION_CLIPBOARD;
502     clipList[CLIP_TYPE_CLIPBOARD].request = ecore_x_selection_clipboard_request;
503     clipList[CLIP_TYPE_CLIPBOARD].bufferLength = 0;
504
505     clipList[CLIP_TYPE_XDND].selection = ECORE_X_SELECTION_XDND;
506     clipList[CLIP_TYPE_XDND].request = ecore_x_selection_xdnd_request;
507     clipList[CLIP_TYPE_XDND].bufferLength = 0;
508
509     for (int i = 0; i < ATOM_MAX; i++)
510         atomList[i].atom = ecore_x_atom_get(atomList[i].pName);
511
512     m_selectionClearHandler = ecore_event_handler_add(ECORE_X_EVENT_SELECTION_CLEAR, clearClip, this);
513     m_selectionNotifyHandler = ecore_event_handler_add(ECORE_X_EVENT_SELECTION_NOTIFY, notifyClip, this);
514 }
515
516 Ecore_X_Window ClipboardHelper::getCbhmWindow()
517 {
518     Ecore_X_Atom xAtomCbhm = ecore_x_atom_get("CBHM_XWIN");
519     Ecore_X_Window xCbhmWin = 0;
520
521     unsigned char* buf = 0;
522     int num = 0;
523     int ret = ecore_x_window_prop_property_get(0, xAtomCbhm, XA_WINDOW, 0, &buf, &num);
524
525     if (ret && num)
526         memcpy(&xCbhmWin, buf, sizeof(Ecore_X_Window));
527
528     if (buf)
529         free(buf);
530
531     return xCbhmWin;
532 }
533
534 bool ClipboardHelper::sendCbhmMessage(String message)
535 {
536     Ecore_X_Window xCbhmWin = getCbhmWindow();
537     Ecore_X_Atom xAtomCbhmMsg = ecore_x_atom_get("CBHM_MSG");
538
539     Evas_Object* parent = elm_object_parent_widget_get(m_viewImpl->view());
540     Ecore_X_Window xWin = ecore_evas_gl_x11_window_get(ecore_evas_ecore_evas_get(evas_object_evas_get(parent)));
541     if (!xWin)
542         xWin = ecore_evas_software_x11_window_get(ecore_evas_ecore_evas_get(evas_object_evas_get(parent)));
543
544     if (!xCbhmWin || !xAtomCbhmMsg)
545         return false;
546
547     XClientMessageEvent messageEvent;
548     memset(&messageEvent, 0, sizeof(messageEvent));
549     messageEvent.type = ClientMessage;
550     messageEvent.display = static_cast<Display *> (ecore_x_display_get());
551     messageEvent.window = xWin;
552     messageEvent.message_type = xAtomCbhmMsg;
553     messageEvent.format = 8;
554     snprintf(messageEvent.data.b, 20, "%s", message.utf8().data());
555
556     XSendEvent(static_cast<Display *> (ecore_x_display_get()), xCbhmWin, false, NoEventMask, (XEvent*)&messageEvent);
557
558     ecore_x_sync();
559
560     return true;
561 }
562
563 bool ClipboardHelper::setClipboardItem(Ecore_X_Atom dataType,const String& data)
564 {
565     Ecore_X_Window cbhmWin = getCbhmWindow();
566     Ecore_X_Atom atomCbhmItem = ecore_x_atom_get("CBHM_ITEM");
567
568     CString utfData = data.utf8();
569
570     ecore_x_sync();
571     ecore_x_window_prop_property_set(cbhmWin, atomCbhmItem, dataType, 8, const_cast<char*>(utfData.data()), utfData.length() + 1);
572     ecore_x_sync();
573
574     if (sendCbhmMessage(String::fromUTF8(static_cast<const char*>("SET_ITEM"))))
575         return true;
576
577     return false;
578 }
579
580 void ClipboardHelper::openClipboardWindow(bool isContentRichlyEditable)
581 {
582     clearClipboardSelectionHandler();
583
584     initializeAtomList();
585     if (isContentRichlyEditable)
586         sendCbhmMessage(String::fromUTF8(static_cast<const char*>("show1")));
587     else
588         sendCbhmMessage(String::fromUTF8(static_cast<const char*>("show0")));
589
590     connectClipboardWindow();
591
592     evas_object_smart_callback_call(m_viewImpl->view(), "clipboard,opened", 0);
593
594 #if ENABLE(TIZEN_WEBKIT2_TEXT_SELECTION)
595     m_viewImpl->pageClient->updateTextSelectionHandlesAndContextMenu(false);
596 #endif
597 }
598
599 bool ClipboardHelper::isClipboardWindowOpened()
600 {
601     char* windowTitle = ecore_x_icccm_title_get(ecore_x_window_focus_get());
602
603     if (!windowTitle)
604          return false;
605
606     if (!(strcmp("Clipboard History Manager", windowTitle)))
607         return true;
608
609     return false;
610 }
611
612 void ClipboardHelper::connectClipboardWindow()
613 {
614     ecore_x_selection_secondary_set(elm_win_xwindow_get(elm_object_parent_widget_get(m_viewImpl->view())), "",1);
615 }
616
617 void ClipboardHelper::clearClipboardSelectionHandler()
618 {
619     if (m_selectionClearHandler) {
620         ecore_event_handler_del(m_selectionClearHandler);
621         m_selectionClearHandler = 0;
622     }
623     if (m_selectionNotifyHandler) {
624         ecore_event_handler_del(m_selectionNotifyHandler);
625         m_selectionNotifyHandler = 0;
626     }
627 }
628
629 bool ClipboardHelper::getSelectedCbhmItem(Ecore_X_Atom* pDataType)
630 {
631     Ecore_X_Window cbhmWin = getCbhmWindow();
632     Ecore_X_Atom atomCbhmItem = ecore_x_atom_get("CBHM_SELECTED_ITEM");
633     Ecore_X_Atom atomItemType = 0;
634
635     String result = getCbhmReply(cbhmWin, atomCbhmItem, &atomItemType);
636
637     if(result.isNull())
638         return false;
639
640     if (atomItemType == ecore_x_atom_get("CBHM_ERROR"))
641         return false;
642
643     if (pDataType)
644         *pDataType = atomItemType;
645
646     return true;
647 }
648
649 String ClipboardHelper::getCbhmReply(Ecore_X_Window xwin, Ecore_X_Atom property, Ecore_X_Atom* pDataType)
650 {
651     if (!property)
652         return String();
653
654     ecore_x_sync();
655
656     Ecore_X_Atom type;
657     int dataUnitSize = 0;
658     long unsigned int dataLength = 0;
659     long unsigned int bytes = 0;
660     unsigned char* pData = 0;
661
662     int result = XGetWindowProperty((Display*)ecore_x_display_get(), xwin, property, 0, LONG_MAX, False,
663                                  ecore_x_window_prop_any_type(), (Atom*)&type, &dataUnitSize, &dataLength, &bytes, &pData);
664     if (result != Success)
665         return String();
666
667     if (!dataLength) {
668         XFree(pData);
669         return String();
670     }
671
672     String chbmData;
673
674     switch (dataUnitSize) {
675     case 8:
676         chbmData = String::fromUTF8(pData, dataLength);
677         break;
678     case 16:
679         chbmData = String(reinterpret_cast<UChar*>(pData), dataLength);
680         LOG_ERROR("case 16");
681         break;
682     case 32:
683         LOG_ERROR("case 32");
684         break;
685     default:
686         LOG_ERROR("case %d", dataUnitSize);
687     }
688
689     XFree(pData);
690
691     if (pDataType)
692         *pDataType = type;
693
694     return chbmData;
695 }
696
697 bool ClipboardHelper::retrieveClipboardItem(int index, int* format, String* pData)
698 {
699     if (!pData)
700         return false;
701
702     Ecore_X_Window cbhmWin = getCbhmWindow();
703
704     Ecore_X_Atom atomCbhmItem = ecore_x_atom_get(String::format("CBHM_ITEM%d", index).utf8().data());
705     Ecore_X_Atom atomItemType = 0;
706
707     String result = getCbhmReply(cbhmWin, atomCbhmItem, &atomItemType);
708     if (result.isNull())
709         return false;
710
711     *pData = result;
712
713     Ecore_X_Atom dataType = atomItemType;
714
715     if (atomItemType == ecore_x_atom_get("CBHM_ERROR"))
716         return false;
717
718     if ((dataType == ecore_x_atom_get("UTF8_STRING")) || (dataType == ecore_x_atom_get("application/x-elementary-markup")))
719         *format = ELM_SEL_FORMAT_TEXT;
720     else if (dataType == ecore_x_atom_get("text/uri"))
721         *format = ELM_SEL_FORMAT_IMAGE;
722     else if (dataType == ecore_x_atom_get("text/html;charset=utf-8"))
723         *format = ELM_SEL_FORMAT_HTML;
724     else
725         return false;
726
727     return true;
728 }
729
730 void ClipboardHelper::pasteClipboardLastItem(bool isContentEditable)
731 {
732     int count = numberOfItems();
733
734     // Find the item with dataTypes.
735     int format = ELM_SEL_FORMAT_NONE;
736     String clipboardData;
737
738     for (int i = 0; i < count; i++) {
739         // Get the clip with index.
740         bool ret = retrieveClipboardItem(i, &format, &clipboardData);
741
742         if (!ret)
743             continue;
744
745         if (isContentEditable)
746             break;
747         else {
748             if (format == ELM_SEL_FORMAT_TEXT || format == ELM_SEL_FORMAT_MARKUP || format == ELM_SEL_FORMAT_HTML)
749                 break;
750         }
751     }
752
753     switch(format) {
754     case ELM_SEL_FORMAT_TEXT:
755         page()->didSelectPasteMenuFromContextMenu(clipboardData, String("PlainText"));
756         break;
757     case ELM_SEL_FORMAT_HTML:
758     case ELM_SEL_FORMAT_MARKUP:
759         page()->didSelectPasteMenuFromContextMenu(clipboardData, String("Markup"));
760         break;
761     case ELM_SEL_FORMAT_IMAGE:
762         page()->didSelectPasteMenuFromContextMenu(clipboardData, String("Image"));
763         break;
764     default:
765         page()->didSelectPasteMenuFromContextMenu(String(""), String("PlainText"));
766         break;
767     }
768 }
769 #endif // TIZEN_WEBKIT2_CONTEXT_MENU_CLIPBOARD
770 }// namespace WebKit
771
772 #endif // TIZEN_WEBKIT2_CLIPBOARD_HELPER