]> git.0d.be Git - empathy.git/blob - libempathy-gtk/empathy-webkit-utils.c
Merge remote-tracking branch 'origin/gnome-3-8'
[empathy.git] / libempathy-gtk / empathy-webkit-utils.c
1 /*
2  * Copyright (C) 2008-2009 Collabora Ltd.
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
17  *
18  * Authors: Xavier Claessens <xclaesse@gmail.com>
19  */
20
21 #include "config.h"
22 #include "empathy-webkit-utils.h"
23
24 #include <glib/gi18n-lib.h>
25
26 #include "empathy-smiley-manager.h"
27 #include "empathy-theme-adium.h"
28 #include "empathy-ui-utils.h"
29
30 #define BORING_DPI_DEFAULT 96
31
32 static void
33 empathy_webkit_match_newline (const gchar *text,
34     gssize len,
35     EmpathyStringReplace replace_func,
36     EmpathyStringParser *sub_parsers,
37     gpointer user_data)
38 {
39   GString *string = user_data;
40   gint i;
41   gint prev = 0;
42
43   if (len < 0)
44     len = G_MAXSSIZE;
45
46   /* Replace \n by <br/> */
47   for (i = 0; i < len && text[i] != '\0'; i++)
48     {
49       if (text[i] == '\n')
50         {
51           empathy_string_parser_substr (text + prev, i - prev,
52               sub_parsers, user_data);
53           g_string_append (string, "<br/>");
54           prev = i + 1;
55         }
56     }
57
58   empathy_string_parser_substr (text + prev, i - prev,
59               sub_parsers, user_data);
60 }
61
62 static void
63 empathy_webkit_replace_smiley (const gchar *text,
64     gssize len,
65     gpointer match_data,
66     gpointer user_data)
67 {
68   EmpathySmileyHit *hit = match_data;
69   GString *string = user_data;
70
71   /* Replace smiley by a <img/> tag */
72   g_string_append_printf (string,
73       "<img src=\"%s\" alt=\"%.*s\" title=\"%.*s\"/>",
74       hit->path, (int)len, text, (int)len, text);
75 }
76
77 static EmpathyStringParser string_parsers[] = {
78   { empathy_string_match_link, empathy_string_replace_link },
79   { empathy_webkit_match_newline, NULL },
80   { empathy_string_match_all, empathy_string_replace_escaped },
81   { NULL, NULL}
82 };
83
84 static EmpathyStringParser string_parsers_with_smiley[] = {
85   { empathy_string_match_link, empathy_string_replace_link },
86   { empathy_string_match_smiley, empathy_webkit_replace_smiley },
87   { empathy_webkit_match_newline, NULL },
88   { empathy_string_match_all, empathy_string_replace_escaped },
89   { NULL, NULL }
90 };
91
92 EmpathyStringParser *
93 empathy_webkit_get_string_parser (gboolean smileys)
94 {
95   if (smileys)
96     return string_parsers_with_smiley;
97   else
98     return string_parsers;
99 }
100
101 static gboolean
102 webkit_get_font_family (GValue *value,
103     GVariant *variant,
104     gpointer user_data)
105 {
106   PangoFontDescription *font = pango_font_description_from_string (
107       g_variant_get_string (variant, NULL));
108
109   if (font == NULL)
110     return FALSE;
111
112   g_value_set_string (value, pango_font_description_get_family (font));
113   pango_font_description_free (font);
114
115   return TRUE;
116 }
117
118 static gboolean
119 webkit_get_font_size (GValue *value,
120     GVariant *variant,
121     gpointer user_data)
122 {
123   PangoFontDescription *font = pango_font_description_from_string (
124       g_variant_get_string (variant, NULL));
125   int size;
126
127   if (font == NULL)
128     return FALSE;
129
130   size = pango_font_description_get_size (font) / PANGO_SCALE;
131
132   if (pango_font_description_get_size_is_absolute (font))
133     {
134       GdkScreen *screen = gdk_screen_get_default ();
135       double dpi;
136
137       if (screen != NULL)
138         dpi = gdk_screen_get_resolution (screen);
139       else
140         dpi = BORING_DPI_DEFAULT;
141
142       size = (gint) (size / (dpi / 72));
143     }
144
145   g_value_set_int (value, size);
146   pango_font_description_free (font);
147
148   return TRUE;
149 }
150
151 void
152 empathy_webkit_bind_font_setting (WebKitWebView *webview,
153     GSettings *gsettings,
154     const char *key)
155 {
156   WebKitWebSettings *settings = webkit_web_view_get_settings (webview);
157
158   g_settings_bind_with_mapping (gsettings, key,
159       settings, "default-font-family",
160       G_SETTINGS_BIND_GET,
161       webkit_get_font_family,
162       NULL,
163       NULL, NULL);
164
165   g_settings_bind_with_mapping (gsettings, key,
166       settings, "default-font-size",
167       G_SETTINGS_BIND_GET,
168       webkit_get_font_size,
169       NULL,
170       NULL, NULL);
171 }
172
173 static void
174 empathy_webkit_copy_address_cb (GtkMenuItem *menuitem,
175     gpointer user_data)
176 {
177   WebKitHitTestResult *hit_test_result = WEBKIT_HIT_TEST_RESULT (user_data);
178   gchar *uri;
179   GtkClipboard *clipboard;
180
181   g_object_get (G_OBJECT (hit_test_result),
182       "link-uri", &uri,
183       NULL);
184
185   clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
186   gtk_clipboard_set_text (clipboard, uri, -1);
187
188   clipboard = gtk_clipboard_get (GDK_SELECTION_PRIMARY);
189   gtk_clipboard_set_text (clipboard, uri, -1);
190
191   g_free (uri);
192 }
193
194 static void
195 empathy_webkit_open_address_cb (GtkMenuItem *menuitem,
196     gpointer     user_data)
197 {
198   WebKitHitTestResult *hit_test_result = WEBKIT_HIT_TEST_RESULT (user_data);
199   gchar *uri;
200
201   g_object_get (G_OBJECT (hit_test_result),
202       "link-uri", &uri,
203       NULL);
204
205   empathy_url_show (GTK_WIDGET (menuitem), uri);
206
207   g_free (uri);
208 }
209
210 static void
211 empathy_webkit_inspect_cb (GtkMenuItem *menuitem,
212     WebKitWebView *view)
213 {
214   empathy_webkit_show_inspector (view);
215 }
216
217 static void
218 empathy_webkit_context_menu_selection_done_cb (GtkMenuShell *menu,
219     gpointer user_data)
220 {
221   WebKitHitTestResult *hit_test_result = WEBKIT_HIT_TEST_RESULT (user_data);
222
223   g_object_unref (hit_test_result);
224 }
225
226 GtkWidget *
227 empathy_webkit_create_context_menu (WebKitWebView *view,
228     WebKitHitTestResult *hit_test_result,
229     EmpathyWebKitMenuFlags flags)
230 {
231   WebKitHitTestResultContext context;
232   GtkWidget *menu;
233   GtkWidget *item;
234
235   g_object_get (G_OBJECT (hit_test_result),
236       "context", &context,
237       NULL);
238
239   /* The menu */
240   menu = empathy_context_menu_new (GTK_WIDGET (view));
241
242   /* Select all item */
243   item = gtk_image_menu_item_new_from_stock (GTK_STOCK_SELECT_ALL, NULL);
244   gtk_menu_shell_prepend (GTK_MENU_SHELL (menu), item);
245
246   g_signal_connect_swapped (item, "activate",
247       G_CALLBACK (webkit_web_view_select_all),
248       view);
249
250   /* Copy menu item */
251   if (webkit_web_view_can_copy_clipboard (view))
252     {
253       item = gtk_image_menu_item_new_from_stock (GTK_STOCK_COPY, NULL);
254       gtk_menu_shell_prepend (GTK_MENU_SHELL (menu), item);
255
256       g_signal_connect_swapped (item, "activate",
257           G_CALLBACK (webkit_web_view_copy_clipboard),
258           view);
259     }
260
261   /* Clear menu item */
262   if (flags & EMPATHY_WEBKIT_MENU_CLEAR)
263     {
264       item = gtk_separator_menu_item_new ();
265       gtk_menu_shell_prepend (GTK_MENU_SHELL (menu), item);
266
267       item = gtk_image_menu_item_new_from_stock (GTK_STOCK_CLEAR, NULL);
268       gtk_menu_shell_prepend (GTK_MENU_SHELL (menu), item);
269
270       g_signal_connect_swapped (item, "activate",
271           G_CALLBACK (empathy_theme_adium_clear),
272           view);
273     }
274
275   /* We will only add the following menu items if we are
276    * right-clicking a link */
277   if (context & WEBKIT_HIT_TEST_RESULT_CONTEXT_LINK)
278     {
279       /* Separator */
280       item = gtk_separator_menu_item_new ();
281       gtk_menu_shell_prepend (GTK_MENU_SHELL (menu), item);
282
283       /* Copy Link Address menu item */
284       item = gtk_menu_item_new_with_mnemonic (_("_Copy Link Address"));
285       g_signal_connect (item, "activate",
286           G_CALLBACK (empathy_webkit_copy_address_cb),
287           hit_test_result);
288       gtk_menu_shell_prepend (GTK_MENU_SHELL (menu), item);
289
290       /* Open Link menu item */
291       item = gtk_menu_item_new_with_mnemonic (_("_Open Link"));
292       g_signal_connect (item, "activate",
293           G_CALLBACK (empathy_webkit_open_address_cb),
294           hit_test_result);
295       gtk_menu_shell_prepend (GTK_MENU_SHELL (menu), item);
296     }
297
298   if ((flags & EMPATHY_WEBKIT_MENU_INSPECT) != 0)
299     {
300       /* Separator */
301       item = gtk_separator_menu_item_new ();
302       gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
303
304       /* Inspector */
305       item = gtk_menu_item_new_with_mnemonic (_("Inspect HTML"));
306       g_signal_connect (item, "activate",
307           G_CALLBACK (empathy_webkit_inspect_cb), view);
308       gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
309     }
310
311   g_signal_connect (GTK_MENU_SHELL (menu), "selection-done",
312       G_CALLBACK (empathy_webkit_context_menu_selection_done_cb),
313       g_object_ref (hit_test_result));
314
315   return menu;
316 }
317
318 void
319 empathy_webkit_context_menu_for_event (WebKitWebView *view,
320     GdkEventButton *event,
321     EmpathyWebKitMenuFlags flags)
322 {
323   GtkWidget *menu;
324   WebKitHitTestResult *hit_test_result;
325
326   hit_test_result = webkit_web_view_get_hit_test_result (view, event);
327
328   menu = empathy_webkit_create_context_menu (view, hit_test_result, flags);
329
330   gtk_widget_show_all (menu);
331   gtk_menu_popup (GTK_MENU (menu), NULL, NULL, NULL, NULL,
332       event->button, event->time);
333
334   g_object_unref (hit_test_result);
335 }
336
337 void
338 empathy_webkit_show_inspector (WebKitWebView *view)
339 {
340   WebKitWebInspector *inspector;
341
342   g_object_set (G_OBJECT (webkit_web_view_get_settings (view)),
343       "enable-developer-extras", TRUE, NULL);
344
345   inspector = webkit_web_view_get_inspector (view);
346   webkit_web_inspector_show (inspector);
347 }