summaryrefslogtreecommitdiff
path: root/libview
diff options
context:
space:
mode:
authorVictor Kareh <[email protected]>2026-06-05 13:10:13 -0400
committerVictor Kareh <[email protected]>2026-06-09 12:38:12 -0400
commitb1a648b9583b1368b80b988df3aa0bc0db7dc004 (patch)
tree5d46a6740d2a608462fbf52352dd66e357b6bf99 /libview
parent3e7daa36411678717b833eac7866a7efd03f0bdd (diff)
downloadatril-libgepub-support.tar.bz2
atril-libgepub-support.tar.xz
epub: Implement search using WebKit find controllerlibgepub-support
Bypass the threaded EvJobFind for EPUB documents and use WebKit's WebKitFindController directly. The threaded find job was incompatible with GepubDoc's single-threaded design and caused segfaults. The new approach searches within the current page using WebKit's built-in text search and highlighting, which is both simpler and thread-safe. Assisted-by: OpenCode:claude-opus-4-6
Diffstat (limited to 'libview')
-rw-r--r--libview/ev-web-view.c227
-rw-r--r--libview/ev-web-view.h11
2 files changed, 31 insertions, 207 deletions
diff --git a/libview/ev-web-view.c b/libview/ev-web-view.c
index 78b59adf..2c5271ba 100644
--- a/libview/ev-web-view.c
+++ b/libview/ev-web-view.c
@@ -33,20 +33,6 @@
#include "ev-document.h"
#include "ev-jobs.h"
- typedef enum {
- EV_WEB_VIEW_FIND_NEXT,
- EV_WEB_VIEW_FIND_PREV
- } EvWebViewFindDirection;
-
-typedef struct _SearchParams {
- gboolean case_sensitive;
- gchar* search_string;
- EvWebViewFindDirection direction;
- gboolean search_jump;
- gint on_result;
- guint *results;
-}SearchParams;
-
struct _EvWebView
{
WebKitWebView web_view;
@@ -54,13 +40,13 @@ struct _EvWebView
EvDocumentModel *model;
GepubDoc *gepub_doc;
gint current_page;
- gboolean inverted_stylesheet ;
+ gboolean inverted_stylesheet;
gboolean fullscreen;
- SearchParams *search;
WebKitFindController *findcontroller;
WebKitFindOptions findoptions;
gdouble zoom_level;
gchar *hlink;
+ gchar *search_string;
};
struct _EvWebViewClass
@@ -119,9 +105,9 @@ ev_web_view_dispose (GObject *object)
webview->hlink = NULL;
}
- if (webview->search) {
- g_free(webview->search);
- webview->search = NULL;
+ if (webview->search_string) {
+ g_free(webview->search_string);
+ webview->search_string = NULL;
}
G_OBJECT_CLASS (ev_web_view_parent_class)->dispose (object);
@@ -192,17 +178,10 @@ ev_web_view_init (EvWebView *webview)
}
webview->current_page = 0;
-
- webview->search = g_new0(SearchParams, 1);
- webview->search->search_string = NULL;
-
- webview->search->on_result = -1 ;
- webview->search->results = NULL;
- webview->search->search_jump = TRUE ;
-
webview->fullscreen = FALSE;
webview->inverted_stylesheet = FALSE;
webview->hlink = NULL;
+ webview->search_string = NULL;
}
static void
@@ -481,207 +460,57 @@ ev_web_view_handle_link(EvWebView *webview,EvLink *link)
/* Searching */
static void
-results_counted_cb(WebKitFindController *findcontroller,
- guint match_count,
- EvWebView *webview)
-{
- if (match_count > 0 && webview->search->on_result < match_count) {
- webkit_find_controller_search(findcontroller,
- webview->search->search_string,
- webview->findoptions,
- match_count);
- webview->search->search_jump = FALSE;
- }
-}
-
-/*
- * Jump to find results once we have changed the page in the webview.
- */
-static void
-jump_to_find_results(EvWebView *webview,
- WebKitLoadEvent load_event,
- gpointer data)
+ev_web_view_find_restart (EvWebView *webview)
{
- if ( load_event != WEBKIT_LOAD_FINISHED) {
- return;
- }
-
- if (!webview->search->search_string) {
+ if (!webview->search_string || !webview->search_string[0])
return;
- }
- if (webview->search->direction == EV_WEB_VIEW_FIND_NEXT) {
- webview->findoptions &= ~WEBKIT_FIND_OPTIONS_BACKWARDS;
- webview->findoptions &= ~WEBKIT_FIND_OPTIONS_WRAP_AROUND;
- }
- else {
- webview->findoptions |= WEBKIT_FIND_OPTIONS_BACKWARDS;
- webview->findoptions |= WEBKIT_FIND_OPTIONS_WRAP_AROUND;
- }
-
- webkit_find_controller_count_matches (webview->findcontroller,
- webview->search->search_string,
- webview->findoptions,
- G_MAXUINT);
- webview->search->search_jump = FALSE;
-}
-
-static gint
-ev_web_view_find_get_n_results (EvWebView *webview, gint page)
-{
- return webview->search->results[page];
+ webkit_find_controller_search (webview->findcontroller,
+ webview->search_string,
+ webview->findoptions,
+ G_MAXUINT);
}
-/**
- * jump_to_find_page
- * @webview: #EvWebView instance
- * @direction: Direction to look
- * @shift: Shift from current page
- *
- * Jumps to the first page that has occurences of searched word.
- * Uses a direction where to look and a shift from current page.
-**/
-static void
-jump_to_find_page (EvWebView *webview, EvWebViewFindDirection direction, gint shift)
+void
+ev_web_view_find_changed (EvWebView *webview,
+ const gchar *text,
+ gboolean case_sensitive)
{
- int n_pages, i;
-
- n_pages = ev_document_get_n_pages (webview->document);
-
- for (i = 0; i < n_pages; i++) {
- int page;
-
- if (direction == EV_WEB_VIEW_FIND_NEXT)
- page = webview->current_page + i;
- else
- page = webview->current_page - i;
- page += shift;
-
- if (page >= n_pages) {
- page = page - n_pages;
- } else if (page < 0)
- page = page + n_pages;
-
- if (page == webview->current_page && ev_web_view_find_get_n_results(webview,page) > 0) {
- if (direction == EV_WEB_VIEW_FIND_PREV) {
- webview->findoptions |= WEBKIT_FIND_OPTIONS_WRAP_AROUND;
- webview->findoptions |= WEBKIT_FIND_OPTIONS_BACKWARDS;
- }
- else {
- if (webview->search->search_jump)
- webview->findoptions |= WEBKIT_FIND_OPTIONS_WRAP_AROUND;
- else
- webview->findoptions &= ~WEBKIT_FIND_OPTIONS_WRAP_AROUND;
+ g_free (webview->search_string);
+ webview->search_string = g_strdup (text);
- webview->findoptions &= ~WEBKIT_FIND_OPTIONS_BACKWARDS;
- }
-
- webkit_find_controller_search (webview->findcontroller,
- webview->search->search_string,
- webview->findoptions,
- /*Highlight all the results.*/
- G_MAXUINT);
- webview->search->search_jump = FALSE;
- break;
- }
-
- if (ev_web_view_find_get_n_results (webview, page) > 0) {
- webview->search->direction = direction;
- webkit_find_controller_search_finish(webview->findcontroller);
- ev_document_model_set_page (webview->model, page);
- break;
- }
- }
-}
+ webview->findoptions = WEBKIT_FIND_OPTIONS_NONE;
+ if (!case_sensitive)
+ webview->findoptions |= WEBKIT_FIND_OPTIONS_CASE_INSENSITIVE;
+ webview->findoptions |= WEBKIT_FIND_OPTIONS_WRAP_AROUND;
-void
-ev_web_view_find_changed (EvWebView *webview, guint *results, gchar *text,gboolean case_sensitive)
-{
- webview->search->results = results;
- webview->search->on_result = 0;
- webview->search->search_string = g_strdup(text);
- webview->search->case_sensitive = case_sensitive;
- if (webview->search->search_jump == TRUE) {
- if (!case_sensitive) {
- webview->findoptions |= WEBKIT_FIND_OPTIONS_CASE_INSENSITIVE;
- }
- else {
- webview->findoptions &= ~WEBKIT_FIND_OPTIONS_CASE_INSENSITIVE;
- }
- jump_to_find_page (webview, EV_WEB_VIEW_FIND_NEXT, 0);
- }
+ ev_web_view_find_restart (webview);
}
void
ev_web_view_find_next (EvWebView *webview)
{
- gint n_results;
-
- n_results = ev_web_view_find_get_n_results (webview, webview->current_page);
- webview->search->on_result++;
-
- if (webview->search->on_result >= n_results) {
- webview->search->on_result = 0;
- jump_to_find_page (webview, EV_WEB_VIEW_FIND_NEXT, 1);
- }
- else {
- webkit_find_controller_search_next(webview->findcontroller);
- }
+ webkit_find_controller_search_next (webview->findcontroller);
}
void
ev_web_view_find_previous (EvWebView *webview)
{
- webview->search->on_result--;
-
- if (webview->search->on_result < 0) {
- jump_to_find_page (webview, EV_WEB_VIEW_FIND_PREV, -1);
- webview->search->on_result = MAX (0, ev_web_view_find_get_n_results (webview, webview->current_page) - 1);
- } else {
- webkit_find_controller_search_previous(webview->findcontroller);
- }
+ webkit_find_controller_search_previous (webview->findcontroller);
}
void
ev_web_view_find_search_changed (EvWebView *webview)
{
- /* search string has changed, focus on new search result */
- if (webview->search->search_string) {
- g_free(webview->search->search_string);
- webview->search->search_string = NULL;
- }
-
- webkit_find_controller_search_finish(webview->findcontroller);
- webview->search->search_jump = TRUE;
+ webkit_find_controller_search_finish (webview->findcontroller);
}
void
ev_web_view_find_cancel (EvWebView *webview)
{
webkit_find_controller_search_finish (webview->findcontroller);
-}
-
-void
-ev_web_view_set_handler(EvWebView *webview,gboolean visible)
-{
- if (visible) {
- g_signal_connect(webview,
- "load-changed",
- G_CALLBACK(jump_to_find_results),
- NULL);
- g_signal_connect(webview->findcontroller,
- "counted-matches",
- G_CALLBACK(results_counted_cb),
- webview);
- }
- else {
- g_signal_handlers_disconnect_by_func(webview,
- jump_to_find_results,
- NULL);
- g_signal_handlers_disconnect_by_func(webview,
- results_counted_cb,
- NULL);
- }
+ g_free (webview->search_string);
+ webview->search_string = NULL;
}
/* Selection and copying*/
diff --git a/libview/ev-web-view.h b/libview/ev-web-view.h
index 02f7ef64..721560db 100644
--- a/libview/ev-web-view.h
+++ b/libview/ev-web-view.h
@@ -62,18 +62,13 @@ gboolean ev_web_view_previous_page (EvWebView *webview);
void ev_web_view_handle_link (EvWebView *webview, EvLink* link);
/* Searching */
+void ev_web_view_find_changed (EvWebView *webview,
+ const gchar *text,
+ gboolean case_sensitive);
void ev_web_view_find_next (EvWebView *webview);
void ev_web_view_find_previous (EvWebView *webview);
-
-void ev_web_view_find_changed (EvWebView *webview,
- guint *results,
- gchar *text,
- gboolean case_sensitive);
-
void ev_web_view_find_search_changed (EvWebView *webview);
void ev_web_view_find_cancel (EvWebView *webview);
-void ev_web_view_find_set_highlight_search (EvWebView *webview,gboolean visible);
-void ev_web_view_set_handler (EvWebView *webview,gboolean visible);
/* Selection */
gboolean ev_web_view_get_has_selection (EvWebView *webview);
void ev_web_view_select_all (EvWebView *webview);