]> git.0d.be Git - empathy.git/blob - libempathy-gtk/empathy-webkit-utils.c
export empathy_webkit_create_context_menu()
[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
23 #include <glib/gi18n-lib.h>
24
25 #include "empathy-webkit-utils.h"
26 #include "empathy-smiley-manager.h"
27 #include "empathy-ui-utils.h"
28 #include "empathy-theme-adium.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_context_menu_selection_done_cb (GtkMenuShell *menu,
212     gpointer user_data)
213 {
214   WebKitHitTestResult *hit_test_result = WEBKIT_HIT_TEST_RESULT (user_data);
215
216   g_object_unref (hit_test_result);
217 }
218
219 GtkWidget *
220 empathy_webkit_create_context_menu (WebKitWebView *view,
221     WebKitHitTestResult *hit_test_result,
222     EmpathyWebKitMenuFlags flags)
223 {
224   WebKitHitTestResultContext context;
225   GtkWidget *menu;
226   GtkWidget *item;
227
228   g_object_get (G_OBJECT (hit_test_result),
229       "context", &context,
230       NULL);
231
232   /* The menu */
233   menu = empathy_context_menu_new (GTK_WIDGET (view));
234
235   /* Select all item */
236   item = gtk_image_menu_item_new_from_stock (GTK_STOCK_SELECT_ALL, NULL);
237   gtk_menu_shell_prepend (GTK_MENU_SHELL (menu), item);
238
239   g_signal_connect_swapped (item, "activate",
240       G_CALLBACK (webkit_web_view_select_all),
241       view);
242
243   /* Copy menu item */
244   if (webkit_web_view_can_copy_clipboard (view))
245     {
246       item = gtk_image_menu_item_new_from_stock (GTK_STOCK_COPY, NULL);
247       gtk_menu_shell_prepend (GTK_MENU_SHELL (menu), item);
248
249       g_signal_connect_swapped (item, "activate",
250           G_CALLBACK (webkit_web_view_copy_clipboard),
251           view);
252     }
253
254   /* Clear menu item */
255   if (flags & EMPATHY_WEBKIT_MENU_CLEAR)
256     {
257       item = gtk_separator_menu_item_new ();
258       gtk_menu_shell_prepend (GTK_MENU_SHELL (menu), item);
259
260       item = gtk_image_menu_item_new_from_stock (GTK_STOCK_CLEAR, NULL);
261       gtk_menu_shell_prepend (GTK_MENU_SHELL (menu), item);
262
263       g_signal_connect_swapped (item, "activate",
264           G_CALLBACK (empathy_theme_adium_clear),
265           view);
266     }
267
268   /* We will only add the following menu items if we are
269    * right-clicking a link */
270   if (context & WEBKIT_HIT_TEST_RESULT_CONTEXT_LINK)
271     {
272       /* Separator */
273       item = gtk_separator_menu_item_new ();
274       gtk_menu_shell_prepend (GTK_MENU_SHELL (menu), item);
275
276       /* Copy Link Address menu item */
277       item = gtk_menu_item_new_with_mnemonic (_("_Copy Link Address"));
278       g_signal_connect (item, "activate",
279           G_CALLBACK (empathy_webkit_copy_address_cb),
280           hit_test_result);
281       gtk_menu_shell_prepend (GTK_MENU_SHELL (menu), item);
282
283       /* Open Link menu item */
284       item = gtk_menu_item_new_with_mnemonic (_("_Open Link"));
285       g_signal_connect (item, "activate",
286           G_CALLBACK (empathy_webkit_open_address_cb),
287           hit_test_result);
288       gtk_menu_shell_prepend (GTK_MENU_SHELL (menu), item);
289     }
290
291   g_signal_connect (GTK_MENU_SHELL (menu), "selection-done",
292       G_CALLBACK (empathy_webkit_context_menu_selection_done_cb),
293       g_object_ref (hit_test_result));
294
295   return menu;
296 }
297
298 void
299 empathy_webkit_context_menu_for_event (WebKitWebView *view,
300     GdkEventButton *event,
301     EmpathyWebKitMenuFlags flags)
302 {
303   GtkWidget *menu;
304   WebKitHitTestResult *hit_test_result;
305
306   hit_test_result = webkit_web_view_get_hit_test_result (view, event);
307
308   menu = empathy_webkit_create_context_menu (view, hit_test_result, flags);
309
310   gtk_widget_show_all (menu);
311   gtk_menu_popup (GTK_MENU (menu), NULL, NULL, NULL, NULL,
312       event->button, event->time);
313
314   g_object_unref (hit_test_result);
315 }