commit: a04b3e456f992a763edac7bfbd4ee4a161a92d1c
parent: ba55c293c35cd727259f2d40c5e909ee052a7de3
author: Chris Noxz <chris@noxz.tech>
date: Mon, 20 Mar 2023 14:31:27 +0100
add selection search in ctx menu
This feature requires JavaScript for DOM access, and is tested accordingly
2 files changed, 91 insertions(+), 3 deletions(-)
diff --git a/browser.c b/browser.c
@@ -223,8 +223,12 @@ void
create_context_menu(struct Client *c, WebKitContextMenu *context_menu,
WebKitHitTestResult *hit_test_result)
{
- GAction *a; /* action: freed when quit */
- if (webkit_hit_test_result_context_is_link(hit_test_result)) {
+ GAction *a; /* context menu item action */
+ guint x; /* hit test result context */
+
+ x = webkit_hit_test_result_get_context(hit_test_result);
+
+ if (x & WEBKIT_HIT_TEST_RESULT_CONTEXT_LINK) {
CB(
(a = (GAction*)g_simple_action_new("open-external", NULL)),
"activate",
@@ -234,10 +238,31 @@ create_context_menu(struct Client *c, WebKitContextMenu *context_menu,
webkit_context_menu_insert(
context_menu,
webkit_context_menu_item_new_from_gaction(
- a, "Open link externally", NULL
+ a, "Open Link Externally", NULL
),
2
);
+ g_object_unref(a);
+ }
+
+ if (x & WEBKIT_HIT_TEST_RESULT_CONTEXT_SELECTION) {
+ /* requires javascript for DOM access from here on */
+ if (!webkit_settings_get_enable_javascript(c->settings))
+ return;
+ CB(
+ (a = (GAction*)g_simple_action_new("selection-search", NULL)),
+ "activate",
+ cb_selection_search,
+ c
+ );
+ webkit_context_menu_insert(
+ context_menu,
+ webkit_context_menu_item_new_from_gaction(
+ a, "Search Selection", NULL
+ ),
+ x & WEBKIT_HIT_TEST_RESULT_CONTEXT_LINK ? 3 : 1
+ );
+ g_object_unref(a);
}
}
@@ -948,6 +973,44 @@ search(struct Client *c, enum inpage_search_type type)
}
}
+void
+selection_search(struct Client *c)
+{
+ webkit_web_view_run_javascript(
+ WEBKIT_WEB_VIEW(c->wv),
+ "window.getSelection().toString();",
+ NULL,
+ cb_selection_search_finished,
+ c
+ );
+}
+
+void
+selection_search_finished(struct Client *c, GAsyncResult *result)
+{
+ WebKitJavascriptResult *r;
+ JSCValue *v = NULL;
+ gchar *s,
+ *u;
+
+ if ((r = webkit_web_view_run_javascript_finish(
+ WEBKIT_WEB_VIEW(c->wv), result, NULL
+ )) == NULL)
+ return;
+
+ v = webkit_javascript_result_get_js_value(r);
+
+ if (jsc_value_is_string(v)
+ && strlen(s = jsc_value_to_string(v))
+ && !jsc_context_get_exception(jsc_value_get_context(v))
+ && (u = resolve_uri(s)) != NULL)
+ client_create(u, NULL, TRUE, FALSE);
+
+ webkit_javascript_result_unref(r);
+ g_free(u);
+ g_free(s);
+}
+
void
set_default_web_context(void)
{
diff --git a/browser.h b/browser.h
@@ -215,6 +215,8 @@ static void run_user_scripts(WebKitWebView *);
static void save_history(const gchar *);
static void save_state(void);
static void search(struct Client *, enum inpage_search_type);
+static void selection_search(struct Client *);
+static void selection_search_finished(struct Client *, GAsyncResult *);
static void set_default_web_context(void);
static void set_hover_uri(struct Client *, WebKitHitTestResult *);
static void set_javascript_policy(struct Client *, enum javascript_policy);
@@ -247,6 +249,8 @@ static void cb_notebook_modified(GtkNotebook *, GtkWidget *, guint, gpointer);
static void cb_notebook_switch_page(GtkNotebook *, GtkWidget *, guint,
gpointer);
static gboolean cb_open_external(GSimpleAction *, GVariant *, gpointer);
+static gboolean cb_selection_search(GSimpleAction *, GVariant *, gpointer);
+static void cb_selection_search_finished(GObject *, GAsyncResult *, gpointer);
static void cb_quit(GObject *, gpointer);
static gboolean cb_tab_hid(GtkWidget *, GdkEvent *, gpointer);
static void cb_title_changed(GObject *, GParamSpec *, gpointer);
@@ -405,6 +409,27 @@ cb_quit(GObject *obj, gpointer data)
quit();
}
+gboolean
+cb_selection_search(GSimpleAction *action, GVariant *parameter, gpointer data)
+{
+ (void)action;
+ (void)parameter;
+
+ selection_search((struct Client *)data);
+ return FALSE;
+}
+
+void
+cb_selection_search_finished(GObject *object, GAsyncResult *result,
+ gpointer data)
+{
+ struct Client *c = (struct Client *)data;
+
+ (void)object;
+
+ selection_search_finished(c, result);
+}
+
gboolean
cb_tab_hid(GtkWidget *widget, GdkEvent *event, gpointer data)
{