summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorClaudio Saavedra <csaavedra@igalia.com>2015-06-04 17:48:25 +0300
committerClaudio Saavedra <csaavedra@igalia.com>2015-06-09 15:03:03 +0300
commit9fdf920fd0ce664c1cb82f2deceb01d57e2709e9 (patch)
treee9fa37c52982a2bab9f4183ee4801f33d07aa97f
parentb516557124a4372e47418cfc51692c2d75e89aec (diff)
downloadepiphany-9fdf920fd0ce664c1cb82f2deceb01d57e2709e9.tar.gz
Add context-sensitive menu option to search the web for selected text
When building the context menu in the web process, use the web extension to find out whether there is text selected and pass it as custom data to the UI process. Let the UI process use the selection to build a new menu item that, when activated, will launch a new tab and search the selected text in the user-preferred search engine. https://bugzilla.gnome.org/show_bug.cgi?id=663545
-rw-r--r--embed/web-extension/ephy-web-extension.c41
-rw-r--r--src/ephy-window.c67
-rw-r--r--src/popup-commands.c20
-rw-r--r--src/popup-commands.h3
4 files changed, 131 insertions, 0 deletions
diff --git a/embed/web-extension/ephy-web-extension.c b/embed/web-extension/ephy-web-extension.c
index 86e600a2c..11ed2c151 100644
--- a/embed/web-extension/ephy-web-extension.c
+++ b/embed/web-extension/ephy-web-extension.c
@@ -38,6 +38,8 @@
#include <libsoup/soup.h>
#include <string.h>
#include <webkit2/webkit-web-extension.h>
+#define WEBKIT_DOM_USE_UNSTABLE_API
+#include <webkitdom/WebKitDOMDOMWindowUnstable.h>
#include <JavaScriptCore/JavaScript.h>
struct _EphyWebExtensionPrivate
@@ -994,6 +996,42 @@ web_page_uri_changed (WebKitWebPage *web_page,
g_object_set_data_full (G_OBJECT (web_page), "ephy-web-overview", overview, g_object_unref);
}
+static gboolean
+web_page_context_menu (WebKitWebPage *web_page,
+ WebKitContextMenu *context_menu,
+ WebKitWebHitTestResult *hit_test_result,
+ gpointer user_data)
+{
+ char *string;
+ GVariantBuilder builder;
+ WebKitDOMDocument *document = webkit_web_page_get_dom_document (web_page);
+ WebKitDOMDOMWindow *window = webkit_dom_document_get_default_view (document);
+ WebKitDOMDOMSelection *selection = webkit_dom_dom_window_get_selection (window);
+
+ g_object_unref (window);
+
+ if (!selection)
+ return FALSE;
+
+ string = ephy_web_dom_utils_get_selection_as_string (selection);
+ g_object_unref (selection);
+
+ if (!string || *string == '\0')
+ {
+ g_free (string);
+ return FALSE;
+ }
+
+ g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{sv}"));
+ g_variant_builder_add (&builder, "{sv}", "SelectedText", g_variant_new_string (g_strstrip (string)));
+ webkit_context_menu_set_user_data (context_menu,
+ g_variant_builder_end (&builder));
+
+ g_free (string);
+
+ return TRUE;
+}
+
static void
ephy_web_extension_emit_page_created (EphyWebExtension *extension,
guint64 page_id)
@@ -1062,6 +1100,9 @@ ephy_web_extension_page_created_cb (EphyWebExtension *extension,
g_signal_connect (web_page, "notify::uri",
G_CALLBACK (web_page_uri_changed),
extension);
+ g_signal_connect (web_page, "context-menu",
+ G_CALLBACK (web_page_context_menu),
+ extension);
}
static WebKitWebPage *
diff --git a/src/ephy-window.c b/src/ephy-window.c
index 1e4198f5e..093f5d319 100644
--- a/src/ephy-window.c
+++ b/src/ephy-window.c
@@ -260,6 +260,10 @@ static const GtkActionEntry ephy_popups_entries [] = {
NULL, G_CALLBACK (popup_cmd_save_media_as) },
{ "CopyAudioLocation", NULL, N_("_Copy Audio Address"), NULL,
NULL, G_CALLBACK (popup_cmd_copy_media_location) },
+
+ /* Selection */
+ { "SearchSelection", NULL, "_Search Selection", NULL, NULL,
+ G_CALLBACK (popup_cmd_search_selection) },
};
static const struct
@@ -1628,6 +1632,39 @@ find_spelling_guess_context_menu_items (WebKitContextMenu *context_menu)
return g_list_reverse (retval);
}
+static char *
+ellipsize_string (const char *string,
+ glong max_length)
+{
+ char *ellipsized;
+ glong length = g_utf8_strlen (string, -1);
+
+ if (length == 0)
+ return NULL;
+
+ if (length < max_length)
+ {
+ ellipsized = g_strdup (string);
+ }
+ else
+ {
+ char *str = g_utf8_substring (string, 0, max_length);
+ ellipsized = g_strconcat (str, "…", NULL);
+ g_free (str);
+ }
+ return ellipsized;
+}
+
+static void
+parse_context_menu_user_data (WebKitContextMenu *context_menu,
+ const char** selected_text)
+{
+ GVariantDict dict;
+
+ g_variant_dict_init (&dict, webkit_context_menu_get_user_data (context_menu));
+ g_variant_dict_lookup (&dict, "SelectedText", "&s", selected_text);
+}
+
static gboolean
populate_context_menu (WebKitWebView *web_view,
WebKitContextMenu *context_menu,
@@ -1651,6 +1688,8 @@ populate_context_menu (WebKitWebView *web_view,
gboolean is_media = FALSE;
gboolean is_video = FALSE;
gboolean is_audio = FALSE;
+ gboolean can_search_selection = FALSE;
+ const char *selected_text;
is_image = webkit_hit_test_result_context_is_image (hit_test_result);
@@ -1690,6 +1729,28 @@ populate_context_menu (WebKitWebView *web_view,
}
}
+ parse_context_menu_user_data (context_menu, &selected_text);
+ if (selected_text)
+ {
+ char* ellipsized = ellipsize_string (selected_text, 32);
+ if (ellipsized)
+ {
+ char* label;
+ GtkAction *action;
+
+ can_search_selection = TRUE;
+ action = gtk_action_group_get_action (priv->popups_action_group,
+ "SearchSelection");
+ label = g_strdup_printf (_("Search the Web for '%s'"), ellipsized);
+ gtk_action_set_label (action, label);
+ g_object_set_data_full (G_OBJECT (action), "selection", g_strdup (selected_text),
+ (GDestroyNotify)g_free);
+ g_free (ellipsized);
+ g_free (label);
+ can_search_selection = TRUE;
+ }
+ }
+
webkit_context_menu_remove_all (context_menu);
embed_event = ephy_embed_event_new ((GdkEventButton *)event, hit_test_result);
@@ -1726,6 +1787,9 @@ populate_context_menu (WebKitWebView *web_view,
}
add_action_to_context_menu (context_menu,
priv->action_group, "EditCopy");
+ if (can_search_selection)
+ add_action_to_context_menu (context_menu,
+ priv->popups_action_group, "SearchSelection");
webkit_context_menu_append (context_menu,
webkit_context_menu_item_new_separator ());
add_action_to_context_menu (context_menu,
@@ -1807,6 +1871,9 @@ populate_context_menu (WebKitWebView *web_view,
add_action_to_context_menu (context_menu,
priv->action_group, "EditCopy");
+ if (can_search_selection)
+ add_action_to_context_menu (context_menu,
+ priv->popups_action_group, "SearchSelection");
if (!app_mode && !is_image && !is_media)
{
diff --git a/src/popup-commands.c b/src/popup-commands.c
index 37cf424d2..ab6538a07 100644
--- a/src/popup-commands.c
+++ b/src/popup-commands.c
@@ -382,3 +382,23 @@ popup_cmd_link_in_incognito_window (GtkAction *action,
ephy_open_incognito_window (g_value_get_string (&value));
g_value_unset (&value);
}
+
+void
+popup_cmd_search_selection (GtkAction *action,
+ EphyWindow *window)
+{
+ EphyEmbed *embed, *new_embed;
+ const char *text;
+ char *search_url;
+
+ embed = ephy_embed_container_get_active_child
+ (EPHY_EMBED_CONTAINER (window));
+ g_assert (EPHY_IS_EMBED (embed));
+
+ text = g_object_get_data (G_OBJECT (action), "selection");
+ search_url = ephy_embed_utils_autosearch_address (text);
+ new_embed = ephy_shell_new_tab (ephy_shell_get_default (),
+ window, embed, EPHY_NEW_TAB_APPEND_AFTER);
+ ephy_web_view_load_url (ephy_embed_get_web_view (new_embed), search_url);
+ g_free (search_url);
+}
diff --git a/src/popup-commands.h b/src/popup-commands.h
index a701ca13b..ae33759eb 100644
--- a/src/popup-commands.h
+++ b/src/popup-commands.h
@@ -77,6 +77,9 @@ void popup_cmd_copy_media_location (GtkAction *action,
void popup_cmd_save_media_as (GtkAction *action,
EphyWindow *window);
+void popup_cmd_search_selection (GtkAction *action,
+ EphyWindow *window);
+
G_END_DECLS
#endif