1dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block/*
2dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block * Copyright (C) 2010 Martin Robinson <mrobinson@webkit.org>
321939df44de1705786c545cd1bf519d47250322dBen Murdoch * Copyright (C) Igalia S.L.
4dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block * All rights reserved.
5dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block *
6dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block * This library is free software; you can redistribute it and/or
7dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block * modify it under the terms of the GNU Library General Public
8dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block * License as published by the Free Software Foundation; either
9dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block * version 2 of the License, or (at your option) any later version.
10dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block *
11dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block * This library is distributed in the hope that it will be useful,
12dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block * but WITHOUT ANY WARRANTY; without even the implied warranty of
13dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block * Library General Public License for more details.
15dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block *
16dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block * You should have received a copy of the GNU Library General Public License
17dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block * along with this library; see the file COPYING.LIB.  If not, write to
18dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block * Boston, MA 02110-1301, USA.
20dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block *
21dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block */
22dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block#include "config.h"
23dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block#include "PasteboardHelper.h"
24dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
25dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block#include "Chrome.h"
26dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block#include "DataObjectGtk.h"
27dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block#include "Frame.h"
2806ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen#include "GtkVersioning.h"
29dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block#include "Page.h"
30dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block#include "Pasteboard.h"
3121939df44de1705786c545cd1bf519d47250322dBen Murdoch#include "TextResourceDecoder.h"
32dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block#include <gtk/gtk.h>
33dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block#include <wtf/gobject/GOwnPtr.h>
34dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
35dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blocknamespace WebCore {
36dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
37f05b935882198ccf7d81675736e3aeb089c5113aBen Murdochstatic GdkAtom textPlainAtom;
38f05b935882198ccf7d81675736e3aeb089c5113aBen Murdochstatic GdkAtom markupAtom;
39f05b935882198ccf7d81675736e3aeb089c5113aBen Murdochstatic GdkAtom netscapeURLAtom;
40f05b935882198ccf7d81675736e3aeb089c5113aBen Murdochstatic GdkAtom uriListAtom;
41f05b935882198ccf7d81675736e3aeb089c5113aBen Murdochstatic String gMarkupPrefix;
4228040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu
4328040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhustatic void removeMarkupPrefix(String& markup)
4428040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu{
4528040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu
4628040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu    // The markup prefix is not harmful, but we remove it from the string anyway, so that
4728040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu    // we can have consistent results with other ports during the layout tests.
4828040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu    if (markup.startsWith(gMarkupPrefix))
4928040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu        markup.remove(0, gMarkupPrefix.length());
5028040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu}
51dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
52f05b935882198ccf7d81675736e3aeb089c5113aBen Murdochstatic void initGdkAtoms()
53f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch{
54f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    static gboolean initialized = FALSE;
55f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
56f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    if (initialized)
57f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        return;
58f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
59f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    initialized = TRUE;
60f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
61f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    textPlainAtom = gdk_atom_intern("text/plain;charset=utf-8", FALSE);
62f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    markupAtom = gdk_atom_intern("text/html", FALSE);
63f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    netscapeURLAtom = gdk_atom_intern("_NETSCAPE_URL", FALSE);
64f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    uriListAtom = gdk_atom_intern("text/uri-list", FALSE);
65f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    gMarkupPrefix = "<meta http-equiv=\"content-type\" content=\"text/html; charset=utf-8\">";
66f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch}
67f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
68dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve BlockPasteboardHelper::PasteboardHelper()
69dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    : m_targetList(gtk_target_list_new(0, 0))
70dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block{
71f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    initGdkAtoms();
72dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block}
73dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
74dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve BlockPasteboardHelper::~PasteboardHelper()
75dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block{
76dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    gtk_target_list_unref(m_targetList);
77dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block}
78dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
79dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockvoid PasteboardHelper::initializeTargetList()
80dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block{
81dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    gtk_target_list_add_text_targets(m_targetList, getIdForTargetType(TargetTypeText));
82e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke    gtk_target_list_add(m_targetList, markupAtom, 0, getIdForTargetType(TargetTypeMarkup));
8321939df44de1705786c545cd1bf519d47250322dBen Murdoch    gtk_target_list_add_uri_targets(m_targetList, getIdForTargetType(TargetTypeURIList));
8421939df44de1705786c545cd1bf519d47250322dBen Murdoch    gtk_target_list_add(m_targetList, netscapeURLAtom, 0, getIdForTargetType(TargetTypeNetscapeURL));
85e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke    gtk_target_list_add_image_targets(m_targetList, getIdForTargetType(TargetTypeImage), TRUE);
86dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block}
87dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
88dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockstatic inline GtkWidget* widgetFromFrame(Frame* frame)
89dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block{
90dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    ASSERT(frame);
91dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    Page* page = frame->page();
92dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    ASSERT(page);
93dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    Chrome* chrome = page->chrome();
94dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    ASSERT(chrome);
95dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    PlatformPageClient client = chrome->platformPageClient();
96dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    ASSERT(client);
97dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    return client;
98dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block}
99dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
100dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve BlockGtkClipboard* PasteboardHelper::getCurrentClipboard(Frame* frame)
101dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block{
102dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    if (usePrimarySelectionClipboard(widgetFromFrame(frame)))
103dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        return getPrimarySelectionClipboard(frame);
104dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    return getClipboard(frame);
105dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block}
106dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
107dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve BlockGtkClipboard* PasteboardHelper::getClipboard(Frame* frame) const
108dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block{
109dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    return gtk_widget_get_clipboard(widgetFromFrame(frame), GDK_SELECTION_CLIPBOARD);
110dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block}
111dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
112dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve BlockGtkClipboard* PasteboardHelper::getPrimarySelectionClipboard(Frame* frame) const
113dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block{
114dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    return gtk_widget_get_clipboard(widgetFromFrame(frame), GDK_SELECTION_PRIMARY);
115dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block}
116dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
117dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve BlockGtkTargetList* PasteboardHelper::targetList() const
118dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block{
119dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    return m_targetList;
120dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block}
121dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
122e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarkestatic String selectionDataToUTF8String(GtkSelectionData* data)
123e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke{
124e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke    // g_strndup guards against selection data that is not null-terminated.
125e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke    GOwnPtr<gchar> markupString(g_strndup(reinterpret_cast<const char*>(gtk_selection_data_get_data(data)), gtk_selection_data_get_length(data)));
126e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke    return String::fromUTF8(markupString.get());
127e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke}
128e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke
12921939df44de1705786c545cd1bf519d47250322dBen Murdochvoid PasteboardHelper::getClipboardContents(GtkClipboard* clipboard)
13021939df44de1705786c545cd1bf519d47250322dBen Murdoch{
13121939df44de1705786c545cd1bf519d47250322dBen Murdoch    DataObjectGtk* dataObject = DataObjectGtk::forClipboard(clipboard);
13221939df44de1705786c545cd1bf519d47250322dBen Murdoch    ASSERT(dataObject);
13321939df44de1705786c545cd1bf519d47250322dBen Murdoch
13421939df44de1705786c545cd1bf519d47250322dBen Murdoch    if (gtk_clipboard_wait_is_text_available(clipboard)) {
13521939df44de1705786c545cd1bf519d47250322dBen Murdoch        GOwnPtr<gchar> textData(gtk_clipboard_wait_for_text(clipboard));
13621939df44de1705786c545cd1bf519d47250322dBen Murdoch        if (textData)
13721939df44de1705786c545cd1bf519d47250322dBen Murdoch            dataObject->setText(String::fromUTF8(textData.get()));
13821939df44de1705786c545cd1bf519d47250322dBen Murdoch    }
13921939df44de1705786c545cd1bf519d47250322dBen Murdoch
140e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke    if (gtk_clipboard_wait_is_target_available(clipboard, markupAtom)) {
141e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke        if (GtkSelectionData* data = gtk_clipboard_wait_for_contents(clipboard, markupAtom)) {
14228040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu            String markup(selectionDataToUTF8String(data));
14328040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu            removeMarkupPrefix(markup);
14428040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu            dataObject->setMarkup(markup);
145ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block            gtk_selection_data_free(data);
146ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        }
14721939df44de1705786c545cd1bf519d47250322dBen Murdoch    }
14821939df44de1705786c545cd1bf519d47250322dBen Murdoch
14921939df44de1705786c545cd1bf519d47250322dBen Murdoch    if (gtk_clipboard_wait_is_target_available(clipboard, uriListAtom)) {
15021939df44de1705786c545cd1bf519d47250322dBen Murdoch        if (GtkSelectionData* data = gtk_clipboard_wait_for_contents(clipboard, uriListAtom)) {
151a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            dataObject->setURIList(selectionDataToUTF8String(data));
15221939df44de1705786c545cd1bf519d47250322dBen Murdoch            gtk_selection_data_free(data);
15321939df44de1705786c545cd1bf519d47250322dBen Murdoch        }
15421939df44de1705786c545cd1bf519d47250322dBen Murdoch    }
15521939df44de1705786c545cd1bf519d47250322dBen Murdoch}
15621939df44de1705786c545cd1bf519d47250322dBen Murdoch
157dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockvoid PasteboardHelper::fillSelectionData(GtkSelectionData* selectionData, guint info, DataObjectGtk* dataObject)
158dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block{
159dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    if (info == getIdForTargetType(TargetTypeText))
160dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        gtk_selection_data_set_text(selectionData, dataObject->text().utf8().data(), -1);
16121939df44de1705786c545cd1bf519d47250322dBen Murdoch
162dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    else if (info == getIdForTargetType(TargetTypeMarkup)) {
16328040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu        // Some Linux applications refuse to accept pasted markup unless it is
16428040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu        // prefixed by a content-type meta tag.
16528040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu        CString markup = (gMarkupPrefix + dataObject->markup()).utf8();
166e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke        gtk_selection_data_set(selectionData, markupAtom, 8,
16728040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu            reinterpret_cast<const guchar*>(markup.data()), markup.length() + 1);
16821939df44de1705786c545cd1bf519d47250322dBen Murdoch
16921939df44de1705786c545cd1bf519d47250322dBen Murdoch    } else if (info == getIdForTargetType(TargetTypeURIList)) {
170a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        CString uriList = dataObject->uriList().utf8();
171a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        gtk_selection_data_set(selectionData, uriListAtom, 8,
172a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            reinterpret_cast<const guchar*>(uriList.data()), uriList.length() + 1);
17321939df44de1705786c545cd1bf519d47250322dBen Murdoch
17421939df44de1705786c545cd1bf519d47250322dBen Murdoch    } else if (info == getIdForTargetType(TargetTypeNetscapeURL) && dataObject->hasURL()) {
17521939df44de1705786c545cd1bf519d47250322dBen Murdoch        String url(dataObject->url());
17621939df44de1705786c545cd1bf519d47250322dBen Murdoch        String result(url);
17721939df44de1705786c545cd1bf519d47250322dBen Murdoch        result.append("\n");
17821939df44de1705786c545cd1bf519d47250322dBen Murdoch
17921939df44de1705786c545cd1bf519d47250322dBen Murdoch        if (dataObject->hasText())
18021939df44de1705786c545cd1bf519d47250322dBen Murdoch            result.append(dataObject->text());
18121939df44de1705786c545cd1bf519d47250322dBen Murdoch        else
18221939df44de1705786c545cd1bf519d47250322dBen Murdoch            result.append(url);
18321939df44de1705786c545cd1bf519d47250322dBen Murdoch
18421939df44de1705786c545cd1bf519d47250322dBen Murdoch        GOwnPtr<gchar> resultData(g_strdup(result.utf8().data()));
18506ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen        gtk_selection_data_set(selectionData, netscapeURLAtom, 8,
186ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block            reinterpret_cast<const guchar*>(resultData.get()), strlen(resultData.get()) + 1);
18721939df44de1705786c545cd1bf519d47250322dBen Murdoch
18821939df44de1705786c545cd1bf519d47250322dBen Murdoch    } else if (info == getIdForTargetType(TargetTypeImage))
18921939df44de1705786c545cd1bf519d47250322dBen Murdoch        gtk_selection_data_set_pixbuf(selectionData, dataObject->image());
190dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block}
191dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
192dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve BlockGtkTargetList* PasteboardHelper::targetListForDataObject(DataObjectGtk* dataObject)
193dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block{
194dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    GtkTargetList* list = gtk_target_list_new(0, 0);
195dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
196dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    if (dataObject->hasText())
197dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        gtk_target_list_add_text_targets(list, getIdForTargetType(TargetTypeText));
198dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
199dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    if (dataObject->hasMarkup())
200e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke        gtk_target_list_add(list, markupAtom, 0, getIdForTargetType(TargetTypeMarkup));
201dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
20221939df44de1705786c545cd1bf519d47250322dBen Murdoch    if (dataObject->hasURIList()) {
20321939df44de1705786c545cd1bf519d47250322dBen Murdoch        gtk_target_list_add_uri_targets(list, getIdForTargetType(TargetTypeURIList));
20421939df44de1705786c545cd1bf519d47250322dBen Murdoch        gtk_target_list_add(list, netscapeURLAtom, 0, getIdForTargetType(TargetTypeNetscapeURL));
20521939df44de1705786c545cd1bf519d47250322dBen Murdoch    }
20621939df44de1705786c545cd1bf519d47250322dBen Murdoch
20721939df44de1705786c545cd1bf519d47250322dBen Murdoch    if (dataObject->hasImage())
20821939df44de1705786c545cd1bf519d47250322dBen Murdoch        gtk_target_list_add_image_targets(list, getIdForTargetType(TargetTypeImage), TRUE);
20921939df44de1705786c545cd1bf519d47250322dBen Murdoch
210dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    return list;
211dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block}
212dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
213e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarkevoid PasteboardHelper::fillDataObjectFromDropData(GtkSelectionData* data, guint info, DataObjectGtk* dataObject)
214e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke{
215e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke    if (!gtk_selection_data_get_data(data))
216e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke        return;
217e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke
218e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke    GdkAtom target = gtk_selection_data_get_target(data);
219e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke    if (target == textPlainAtom)
220e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke        dataObject->setText(selectionDataToUTF8String(data));
22128040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu    else if (target == markupAtom) {
22228040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu        String markup(selectionDataToUTF8String(data));
22328040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu        removeMarkupPrefix(markup);
22428040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu        dataObject->setMarkup(markup);
22528040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu    } else if (target == uriListAtom) {
226a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        dataObject->setURIList(selectionDataToUTF8String(data));
227e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke    } else if (target == netscapeURLAtom) {
228e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke        String urlWithLabel(selectionDataToUTF8String(data));
229e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke        Vector<String> pieces;
230e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke        urlWithLabel.split("\n", pieces);
231e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke
232e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke        // Give preference to text/uri-list here, as it can hold more
233e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke        // than one URI but still take  the label if there is one.
234a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        if (!dataObject->hasURIList())
235a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            dataObject->setURIList(pieces[0]);
236e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke        if (pieces.size() > 1)
237e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke            dataObject->setText(pieces[1]);
238e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke    }
239e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke}
240e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke
241e458d70a0d18538346f41b503114c9ebe6b2ce12Leon ClarkeVector<GdkAtom> PasteboardHelper::dropAtomsForContext(GtkWidget* widget, GdkDragContext* context)
242e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke{
243e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke    // Always search for these common atoms.
244e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke    Vector<GdkAtom> dropAtoms;
245e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke    dropAtoms.append(textPlainAtom);
246e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke    dropAtoms.append(markupAtom);
247e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke    dropAtoms.append(uriListAtom);
248e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke    dropAtoms.append(netscapeURLAtom);
249e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke
250e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke    // For images, try to find the most applicable image type.
251cad810f21b803229eb11403f9209855525a25d57Steve Block    GRefPtr<GtkTargetList> list(gtk_target_list_new(0, 0));
252e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke    gtk_target_list_add_image_targets(list.get(), getIdForTargetType(TargetTypeImage), TRUE);
253e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke    GdkAtom atom = gtk_drag_dest_find_target(widget, context, list.get());
254e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke    if (atom != GDK_NONE)
255e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke        dropAtoms.append(atom);
256e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke
257e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke    return dropAtoms;
258e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke}
259e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke
260dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockstatic DataObjectGtk* settingClipboardDataObject = 0;
261dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
262dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockstatic void getClipboardContentsCallback(GtkClipboard* clipboard, GtkSelectionData *selectionData, guint info, gpointer data)
263dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block{
264dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    DataObjectGtk* dataObject = DataObjectGtk::forClipboard(clipboard);
265dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    ASSERT(dataObject);
266dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    Pasteboard::generalPasteboard()->helper()->fillSelectionData(selectionData, info, dataObject);
267dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block}
268dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
269dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockstatic void clearClipboardContentsCallback(GtkClipboard* clipboard, gpointer data)
270dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block{
271dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    DataObjectGtk* dataObject = DataObjectGtk::forClipboard(clipboard);
272dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    ASSERT(dataObject);
273dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
274dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    // Only clear the DataObject for this clipboard if we are not currently setting it.
275dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    if (dataObject != settingClipboardDataObject)
276dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        dataObject->clear();
277dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
278dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    if (!data)
279dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        return;
280dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
281dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    GClosure* callback = static_cast<GClosure*>(data);
282dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    GValue firstArgument = {0, {{0}}};
283dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    g_value_init(&firstArgument, G_TYPE_POINTER);
284dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    g_value_set_pointer(&firstArgument, clipboard);
285dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    g_closure_invoke(callback, 0, 1, &firstArgument, 0);
286dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    g_closure_unref(callback);
287dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block}
288dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
289dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockvoid PasteboardHelper::writeClipboardContents(GtkClipboard* clipboard, GClosure* callback)
290dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block{
291dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    DataObjectGtk* dataObject = DataObjectGtk::forClipboard(clipboard);
292dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    GtkTargetList* list = targetListForDataObject(dataObject);
293dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
294dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    int numberOfTargets;
295dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    GtkTargetEntry* table = gtk_target_table_new_from_list(list, &numberOfTargets);
296dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
297dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    if (numberOfTargets > 0 && table) {
298dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        settingClipboardDataObject = dataObject;
299dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
300dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        gtk_clipboard_set_with_data(clipboard, table, numberOfTargets,
301dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            getClipboardContentsCallback, clearClipboardContentsCallback, callback);
302967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch        gtk_clipboard_set_can_store(clipboard, 0, 0);
303dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
304dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        settingClipboardDataObject = 0;
305dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
306dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    } else
307dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        gtk_clipboard_clear(clipboard);
308dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
309dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    if (table)
310dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        gtk_target_table_free(table, numberOfTargets);
311dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    gtk_target_list_unref(list);
312dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block}
313dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
314dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block}
315dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
316