]> git.0d.be Git - empathy.git/blob - libempathy-gtk/empathy-webkit-utils.c
use the 48x48 version of the local-xmpp icon
[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.h>
24
25 #include "empathy-webkit-utils.h"
26 #include "empathy-smiley-manager.h"
27 #include "empathy-ui-utils.h"
28
29 #define BORING_DPI_DEFAULT 96
30
31 static void
32 empathy_webkit_match_newline (const gchar *text,
33     gssize len,
34     EmpathyStringReplace replace_func,
35     EmpathyStringParser *sub_parsers,
36     gpointer user_data)
37 {
38   GString *string = user_data;
39   gint i;
40   gint prev = 0;
41
42   if (len < 0)
43     len = G_MAXSSIZE;
44
45   /* Replace \n by <br/> */
46   for (i = 0; i < len && text[i] != '\0'; i++)
47     {
48       if (text[i] == '\n')
49         {
50           empathy_string_parser_substr (text + prev, i - prev,
51               sub_parsers, user_data);
52           g_string_append (string, "<br/>");
53           prev = i + 1;
54         }
55     }
56
57   empathy_string_parser_substr (text + prev, i - prev,
58               sub_parsers, user_data);
59 }
60
61 static void
62 empathy_webkit_replace_smiley (const gchar *text,
63     gssize len,
64     gpointer match_data,
65     gpointer user_data)
66 {
67   EmpathySmileyHit *hit = match_data;
68   GString *string = user_data;
69
70   /* Replace smiley by a <img/> tag */
71   g_string_append_printf (string,
72       "<img src=\"%s\" alt=\"%.*s\" title=\"%.*s\"/>",
73       hit->path, (int)len, text, (int)len, text);
74 }
75
76 static EmpathyStringParser string_parsers[] = {
77   { empathy_string_match_link, empathy_string_replace_link },
78   { empathy_webkit_match_newline, NULL },
79   { empathy_string_match_all, empathy_string_replace_escaped },
80   { NULL, NULL}
81 };
82
83 static EmpathyStringParser string_parsers_with_smiley[] = {
84   { empathy_string_match_link, empathy_string_replace_link },
85   { empathy_string_match_smiley, empathy_webkit_replace_smiley },
86   { empathy_webkit_match_newline, NULL },
87   { empathy_string_match_all, empathy_string_replace_escaped },
88   { NULL, NULL }
89 };
90
91 EmpathyStringParser *
92 empathy_webkit_get_string_parser (gboolean smileys)
93 {
94   if (smileys)
95     return string_parsers_with_smiley;
96   else
97     return string_parsers;
98 }
99
100 static gboolean
101 webkit_get_font_family (GValue *value,
102     GVariant *variant,
103     gpointer user_data)
104 {
105   PangoFontDescription *font = pango_font_description_from_string (
106       g_variant_get_string (variant, NULL));
107
108   if (font == NULL)
109     return FALSE;
110
111   g_value_set_string (value, pango_font_description_get_family (font));
112   pango_font_description_free (font);
113
114   return TRUE;
115 }
116
117 static gboolean
118 webkit_get_font_size (GValue *value,
119     GVariant *variant,
120     gpointer user_data)
121 {
122   PangoFontDescription *font = pango_font_description_from_string (
123       g_variant_get_string (variant, NULL));
124   int size;
125
126   if (font == NULL)
127     return FALSE;
128
129   size = pango_font_description_get_size (font) / PANGO_SCALE;
130
131   if (pango_font_description_get_size_is_absolute (font))
132     {
133       GdkScreen *screen = gdk_screen_get_default ();
134       double dpi;
135
136       if (screen != NULL)
137         dpi = gdk_screen_get_resolution (screen);
138       else
139         dpi = BORING_DPI_DEFAULT;
140
141       size = (gint) (size / (dpi / 72));
142     }
143
144   g_value_set_int (value, size);
145   pango_font_description_free (font);
146
147   return TRUE;
148 }
149
150 void
151 empathy_webkit_bind_font_setting (WebKitWebView *webview,
152     GSettings *gsettings,
153     const char *key)
154 {
155   WebKitWebSettings *settings = webkit_web_view_get_settings (webview);
156
157   g_settings_bind_with_mapping (gsettings, key,
158       settings, "default-font-family",
159       G_SETTINGS_BIND_GET,
160       webkit_get_font_family,
161       NULL,
162       NULL, NULL);
163   g_settings_bind_with_mapping (gsettings, key,
164       settings, "default-font-size",
165       G_SETTINGS_BIND_GET,
166       webkit_get_font_size,
167       NULL,
168       NULL, NULL);
169 }
170
171 static void
172 empathy_webkit_copy_address_cb (GtkMenuItem *menuitem,
173     gpointer     user_data)
174 {
175   WebKitHitTestResult   *hit_test_result = WEBKIT_HIT_TEST_RESULT (user_data);
176   gchar                 *uri;
177   GtkClipboard          *clipboard;
178
179   g_object_get (G_OBJECT (hit_test_result),
180       "link-uri", &uri,
181       NULL);
182
183   clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
184   gtk_clipboard_set_text (clipboard, uri, -1);
185
186   clipboard = gtk_clipboard_get (GDK_SELECTION_PRIMARY);
187   gtk_clipboard_set_text (clipboard, uri, -1);
188
189   g_free (uri);
190 }
191
192 static void
193 empathy_webkit_open_address_cb (GtkMenuItem *menuitem,
194     gpointer     user_data)
195 {
196   WebKitHitTestResult   *hit_test_result = WEBKIT_HIT_TEST_RESULT (user_data);
197   gchar                 *uri;
198
199   g_object_get (G_OBJECT (hit_test_result),
200       "link-uri", &uri,
201       NULL);
202
203   empathy_url_show (GTK_WIDGET (menuitem), uri);
204
205   g_free (uri);
206 }
207
208 static void
209 empathy_webkit_context_menu_selection_done_cb (GtkMenuShell *menu,
210     gpointer user_data)
211 {
212   WebKitHitTestResult *hit_test_result = WEBKIT_HIT_TEST_RESULT (user_data);
213
214   g_object_unref (hit_test_result);
215 }
216
217 void
218 empathy_webkit_context_menu_for_event (WebKitWebView *view,
219     GdkEventButton *event,
220     EmpathyWebKitMenuFlags flags)
221 {
222   WebKitHitTestResult        *hit_test_result;
223   WebKitHitTestResultContext  context;
224   GtkWidget                  *menu;
225   GtkWidget                  *item;
226
227   hit_test_result = webkit_web_view_get_hit_test_result (view, event);
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_chat_view_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       hit_test_result);
294
295   /* Display the menu */
296   gtk_widget_show_all (menu);
297   gtk_menu_popup (GTK_MENU (menu), NULL, NULL, NULL, NULL,
298       event->button, event->time);
299 }
300