/* * Copyright (C) 2007 Luca Bruno <lethalman88@gmail.com> * Copyright (C) 2009 Holger Hans Peter Freyther * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "config.h" #include "PasteboardHelperGtk.h" #include "DataObjectGtk.h" #include "FocusController.h" #include "Frame.h" #include <gtk/gtk.h> #include "webkitwebframe.h" #include "webkitwebview.h" #include "webkitprivate.h" using namespace WebCore; namespace WebKit { static GdkAtom gdkMarkupAtom = gdk_atom_intern("text/html", FALSE); PasteboardHelperGtk::PasteboardHelperGtk() : m_targetList(gtk_target_list_new(0, 0)) { gtk_target_list_add_text_targets(m_targetList, WEBKIT_WEB_VIEW_TARGET_INFO_TEXT); gtk_target_list_add(m_targetList, gdkMarkupAtom, 0, WEBKIT_WEB_VIEW_TARGET_INFO_HTML); } PasteboardHelperGtk::~PasteboardHelperGtk() { gtk_target_list_unref(m_targetList); } GtkClipboard* PasteboardHelperGtk::getCurrentTarget(Frame* frame) const { WebKitWebView* webView = webkit_web_frame_get_web_view(kit(frame)); if (webkit_web_view_use_primary_for_paste(webView)) return getPrimary(frame); else return getClipboard(frame); } GtkClipboard* PasteboardHelperGtk::getClipboard(Frame* frame) const { WebKitWebView* webView = webkit_web_frame_get_web_view(kit(frame)); return gtk_widget_get_clipboard(GTK_WIDGET (webView), GDK_SELECTION_CLIPBOARD); } GtkClipboard* PasteboardHelperGtk::getPrimary(Frame* frame) const { WebKitWebView* webView = webkit_web_frame_get_web_view(kit(frame)); return gtk_widget_get_clipboard(GTK_WIDGET (webView), GDK_SELECTION_PRIMARY); } GtkTargetList* PasteboardHelperGtk::targetList() const { return m_targetList; } gint PasteboardHelperGtk::getWebViewTargetInfoHtml() const { return WEBKIT_WEB_VIEW_TARGET_INFO_HTML; } static void fillSelectionData(GtkSelectionData* selectionData, guint info, DataObjectGtk* dataObject) { if (info == WEBKIT_WEB_VIEW_TARGET_INFO_TEXT) gtk_selection_data_set_text(selectionData, dataObject->text().utf8().data(), -1); else if (info == WEBKIT_WEB_VIEW_TARGET_INFO_HTML) { GOwnPtr<gchar> markup(g_strdup(dataObject->markup().utf8().data())); gtk_selection_data_set(selectionData, selectionData->target, 8, reinterpret_cast<const guchar*>(markup.get()), strlen(markup.get())); } } static GtkTargetList* targetListForDataObject(DataObjectGtk* dataObject) { GtkTargetList* list = gtk_target_list_new(0, 0); if (dataObject->hasText()) gtk_target_list_add_text_targets(list, WEBKIT_WEB_VIEW_TARGET_INFO_TEXT); if (dataObject->hasMarkup()) gtk_target_list_add(list, gdkMarkupAtom, 0, WEBKIT_WEB_VIEW_TARGET_INFO_HTML); return list; } static DataObjectGtk* settingClipboardDataObject = 0; static gpointer settingClipboardData = 0; static void getClipboardContentsCallback(GtkClipboard* clipboard, GtkSelectionData *selectionData, guint info, gpointer data) { DataObjectGtk* dataObject = DataObjectGtk::forClipboard(clipboard); ASSERT(dataObject); fillSelectionData(selectionData, info, dataObject); } static void clearClipboardContentsCallback(GtkClipboard* clipboard, gpointer data) { DataObjectGtk* dataObject = DataObjectGtk::forClipboard(clipboard); ASSERT(dataObject); // Only clear the DataObject for this clipboard if we are not currently setting it. if (dataObject != settingClipboardDataObject) dataObject->clear(); // Only collapse the selection if this is an X11 primary clipboard // and we aren't currently setting the clipboard for this WebView. if (!data || data == settingClipboardData) return; WebKitWebView* webView = reinterpret_cast<WebKitWebView*>(data); WebCore::Page* corePage = core(webView); if (!corePage || !corePage->focusController()) { g_object_unref(webView); return; } Frame* frame = corePage->focusController()->focusedOrMainFrame(); // Collapse the selection without clearing it ASSERT(frame); frame->selection()->setBase(frame->selection()->extent(), frame->selection()->affinity()); g_object_unref(webView); } void PasteboardHelperGtk::writeClipboardContents(GtkClipboard* clipboard, gpointer data) { DataObjectGtk* dataObject = DataObjectGtk::forClipboard(clipboard); GtkTargetList* list = targetListForDataObject(dataObject); int numberOfTargets; GtkTargetEntry* table = gtk_target_table_new_from_list(list, &numberOfTargets); if (numberOfTargets > 0 && table) { settingClipboardDataObject = dataObject; settingClipboardData = data; // Protect the web view from being destroyed before one of the clipboard callbacks // is called. Balanced in both getClipboardContentsCallback and // clearClipboardContentsCallback. WebKitWebView* webView = static_cast<WebKitWebView*>(data); g_object_ref(webView); gboolean succeeded = gtk_clipboard_set_with_data(clipboard, table, numberOfTargets, getClipboardContentsCallback, clearClipboardContentsCallback, data); if (!succeeded) g_object_unref(webView); settingClipboardDataObject = 0; settingClipboardData = 0; } else gtk_clipboard_clear(clipboard); if (table) gtk_target_table_free(table, numberOfTargets); gtk_target_list_unref(list); } }