• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *  Copyright (C) 2007 Luca Bruno <lethalman88@gmail.com>
3  *  Copyright (C) 2009 Holger Hans Peter Freyther
4  *
5  *  This library is free software; you can redistribute it and/or
6  *  modify it under the terms of the GNU Lesser General Public
7  *  License as published by the Free Software Foundation; either
8  *  version 2 of the License, or (at your option) any later version.
9  *
10  *  This library is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  *  Lesser General Public License for more details.
14  *
15  *  You should have received a copy of the GNU Lesser General Public
16  *  License along with this library; if not, write to the Free Software
17  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
18  */
19 
20 #include "config.h"
21 #include "PasteboardHelperGtk.h"
22 
23 #include "DataObjectGtk.h"
24 #include "FocusController.h"
25 #include "Frame.h"
26 #include <gtk/gtk.h>
27 #include "webkitwebframe.h"
28 #include "webkitwebview.h"
29 #include "webkitprivate.h"
30 
31 using namespace WebCore;
32 
33 namespace WebKit {
34 
35 static GdkAtom gdkMarkupAtom = gdk_atom_intern("text/html", FALSE);
36 
PasteboardHelperGtk()37 PasteboardHelperGtk::PasteboardHelperGtk()
38     : m_targetList(gtk_target_list_new(0, 0))
39 {
40     gtk_target_list_add_text_targets(m_targetList, WEBKIT_WEB_VIEW_TARGET_INFO_TEXT);
41     gtk_target_list_add(m_targetList, gdkMarkupAtom, 0, WEBKIT_WEB_VIEW_TARGET_INFO_HTML);
42 }
43 
~PasteboardHelperGtk()44 PasteboardHelperGtk::~PasteboardHelperGtk()
45 {
46     gtk_target_list_unref(m_targetList);
47 }
48 
getCurrentTarget(Frame * frame) const49 GtkClipboard* PasteboardHelperGtk::getCurrentTarget(Frame* frame) const
50 {
51     WebKitWebView* webView = webkit_web_frame_get_web_view(kit(frame));
52 
53     if (webkit_web_view_use_primary_for_paste(webView))
54         return getPrimary(frame);
55     else
56         return getClipboard(frame);
57 }
58 
getClipboard(Frame * frame) const59 GtkClipboard* PasteboardHelperGtk::getClipboard(Frame* frame) const
60 {
61     WebKitWebView* webView = webkit_web_frame_get_web_view(kit(frame));
62     return gtk_widget_get_clipboard(GTK_WIDGET (webView),
63                                     GDK_SELECTION_CLIPBOARD);
64 }
65 
getPrimary(Frame * frame) const66 GtkClipboard* PasteboardHelperGtk::getPrimary(Frame* frame) const
67 {
68     WebKitWebView* webView = webkit_web_frame_get_web_view(kit(frame));
69     return gtk_widget_get_clipboard(GTK_WIDGET (webView),
70                                     GDK_SELECTION_PRIMARY);
71 }
72 
targetList() const73 GtkTargetList* PasteboardHelperGtk::targetList() const
74 {
75     return m_targetList;
76 }
77 
getWebViewTargetInfoHtml() const78 gint PasteboardHelperGtk::getWebViewTargetInfoHtml() const
79 {
80     return WEBKIT_WEB_VIEW_TARGET_INFO_HTML;
81 }
82 
fillSelectionData(GtkSelectionData * selectionData,guint info,DataObjectGtk * dataObject)83 static void fillSelectionData(GtkSelectionData* selectionData, guint info, DataObjectGtk* dataObject)
84 {
85     if (info == WEBKIT_WEB_VIEW_TARGET_INFO_TEXT)
86         gtk_selection_data_set_text(selectionData, dataObject->text().utf8().data(), -1);
87     else if (info == WEBKIT_WEB_VIEW_TARGET_INFO_HTML) {
88         GOwnPtr<gchar> markup(g_strdup(dataObject->markup().utf8().data()));
89         gtk_selection_data_set(selectionData, selectionData->target, 8,
90                                reinterpret_cast<const guchar*>(markup.get()),
91                                strlen(markup.get()));
92     }
93 }
94 
targetListForDataObject(DataObjectGtk * dataObject)95 static GtkTargetList* targetListForDataObject(DataObjectGtk* dataObject)
96 {
97     GtkTargetList* list = gtk_target_list_new(0, 0);
98 
99     if (dataObject->hasText())
100         gtk_target_list_add_text_targets(list, WEBKIT_WEB_VIEW_TARGET_INFO_TEXT);
101 
102     if (dataObject->hasMarkup())
103         gtk_target_list_add(list, gdkMarkupAtom, 0, WEBKIT_WEB_VIEW_TARGET_INFO_HTML);
104 
105     return list;
106 }
107 
108 static DataObjectGtk* settingClipboardDataObject = 0;
109 static gpointer settingClipboardData = 0;
getClipboardContentsCallback(GtkClipboard * clipboard,GtkSelectionData * selectionData,guint info,gpointer data)110 static void getClipboardContentsCallback(GtkClipboard* clipboard, GtkSelectionData *selectionData, guint info, gpointer data)
111 {
112     DataObjectGtk* dataObject = DataObjectGtk::forClipboard(clipboard);
113     ASSERT(dataObject);
114     fillSelectionData(selectionData, info, dataObject);
115 }
116 
clearClipboardContentsCallback(GtkClipboard * clipboard,gpointer data)117 static void clearClipboardContentsCallback(GtkClipboard* clipboard, gpointer data)
118 {
119     DataObjectGtk* dataObject = DataObjectGtk::forClipboard(clipboard);
120     ASSERT(dataObject);
121 
122     // Only clear the DataObject for this clipboard if we are not currently setting it.
123     if (dataObject != settingClipboardDataObject)
124         dataObject->clear();
125 
126     // Only collapse the selection if this is an X11 primary clipboard
127     // and we aren't currently setting the clipboard for this WebView.
128     if (!data || data == settingClipboardData)
129         return;
130 
131     WebKitWebView* webView = reinterpret_cast<WebKitWebView*>(data);
132     WebCore::Page* corePage = core(webView);
133 
134     if (!corePage || !corePage->focusController()) {
135         g_object_unref(webView);
136         return;
137     }
138 
139     Frame* frame = corePage->focusController()->focusedOrMainFrame();
140 
141     // Collapse the selection without clearing it
142     ASSERT(frame);
143     frame->selection()->setBase(frame->selection()->extent(), frame->selection()->affinity());
144 
145     g_object_unref(webView);
146 }
147 
writeClipboardContents(GtkClipboard * clipboard,gpointer data)148 void PasteboardHelperGtk::writeClipboardContents(GtkClipboard* clipboard, gpointer data)
149 {
150     DataObjectGtk* dataObject = DataObjectGtk::forClipboard(clipboard);
151     GtkTargetList* list = targetListForDataObject(dataObject);
152 
153     int numberOfTargets;
154     GtkTargetEntry* table = gtk_target_table_new_from_list(list, &numberOfTargets);
155 
156     if (numberOfTargets > 0 && table) {
157         settingClipboardDataObject = dataObject;
158         settingClipboardData = data;
159 
160         // Protect the web view from being destroyed before one of the clipboard callbacks
161         // is called. Balanced in both getClipboardContentsCallback and
162         // clearClipboardContentsCallback.
163         WebKitWebView* webView = static_cast<WebKitWebView*>(data);
164         g_object_ref(webView);
165 
166         gboolean succeeded = gtk_clipboard_set_with_data(clipboard, table, numberOfTargets,
167                                                          getClipboardContentsCallback,
168                                                          clearClipboardContentsCallback, data);
169         if (!succeeded)
170             g_object_unref(webView);
171 
172         settingClipboardDataObject = 0;
173         settingClipboardData = 0;
174     } else
175         gtk_clipboard_clear(clipboard);
176 
177     if (table)
178         gtk_target_table_free(table, numberOfTargets);
179 
180     gtk_target_list_unref(list);
181 }
182 
183 }
184