From: Po Lu Date: Sat, 6 Nov 2021 07:07:09 +0000 (+0800) Subject: Add functions for performing searches on xwidgets X-Git-Tag: emacs-29.0.90~3671^2~127 X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=286467a6b1bff1d7b7bebe285538fb9a67084f01;p=emacs.git Add functions for performing searches on xwidgets * etc/NEWS: * doc/lispref/display.texi: Document changes. * src/xwidget.c (Fxwidget_webkit_search) (Fxwidget_webkit_next_result) (Fxwidget_webkit_previous_result) (Fxwidget_wenkit_finish_search): New functions. (syms_of_xwidget): Define new built-ins. (kill_buffer_xwidgets): Free search query if present. * src/xwidget.h (struct xwidget): Add field for search query. --- diff --git a/doc/lispref/display.texi b/doc/lispref/display.texi index 2fb89d76b41..b780263fe00 100644 --- a/doc/lispref/display.texi +++ b/doc/lispref/display.texi @@ -6896,6 +6896,46 @@ through Lisp code, and as such shouldn't require this function to be sent. @end defun +@defun xwidget-webkit-search query xwidget &optional case-insensitive backwards wrap-around +Start an incremental search on the WebKit widget @var{xwidget} with +the string @var{query} as a query. @var{case-insensitive} denotes +whether or not the search is case-insensitive, @var{backwards} +determines if the search is performed backwards towards the start of +the document, and @var{wrap-around} determines whether or not the +search terminates at the end of the document. + +If the function is called while a search query is already present, +then the query specified here will replace the existing query. + +To stop a search query, use @code{xwidget-webkit-finish-search}. +@end defun + +@defun xwidget-webkit-next-result xwidget +Display the next search result in @var{xwidget}. This function will +error unless a search query has already been started in @var{xwidget} +through @code{xwidget-webkit-search}. + +If @code{wrap-around} was non-nil when @code{xwidget-webkit-search} +was called, then the search will restart from the beginning of the +document if the end is reached. +@end defun + +@defun xwidget-webkit-previous-result xwidget +Display the previous search result in @var{xwidget}. This function +will error unless a search query has already been started in +@var{xwidget} through @code{xwidget-webkit-search}. + +If @code{wrap-around} was non-nil when @code{xwidget-webkit-search} +was called, then the search will restart from the end of the +document if the beginning is reached. +@end defun + +@defun xwidget-webkit-finish-search xwidget +Finish a search operation started with @code{xwidget-webkit-search} in +@var{xwidget}. If there is no query currently ongoing, then this +function will error. +@end defun + @node Buttons @section Buttons @cindex buttons in buffers diff --git a/etc/NEWS b/etc/NEWS index 9a660edee8d..f5295ddbdd9 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -740,6 +740,11 @@ what the widget will actually receive. On GTK+, only key and function key events are implemented. ++++ +** New functions for performing searches on WebKit xwidgets. +Some new functions, such as `xwidget-webkit-search', have been added +for performing searches on WebKit xwidgets. + +++ ** `load-changed' xwidget events are now more detailed. In particular, they can now have different arguments based on the diff --git a/src/xwidget.c b/src/xwidget.c index 36e8cab08da..10bb4ac8e45 100644 --- a/src/xwidget.c +++ b/src/xwidget.c @@ -142,6 +142,7 @@ Returns the newly constructed xwidget, or nil if construction fails. */) xw->widgetwindow_osr = NULL; xw->widget_osr = NULL; xw->hit_result = 0; + xw->find_text = NULL; if (EQ (xw->type, Qwebkit)) { block_input (); @@ -1759,6 +1760,166 @@ DEFUN ("xwidget-query-on-exit-flag", return (XXWIDGET (xwidget)->kill_without_query ? Qnil : Qt); } +DEFUN ("xwidget-webkit-search", Fxwidget_webkit_search, Sxwidget_webkit_search, + 2, 5, 0, + doc: /* Begin an incremental search operation in an xwidget. +QUERY should be a string containing the text to search for. XWIDGET +should be a WebKit xwidget where the search will take place. When the +search operation is complete, callers should also call +`xwidget-webkit-finish-search' to complete the search operation. + +CASE-INSENSITIVE, when non-nil, will cause the search to ignore the +case of characters inside QUERY. BACKWARDS, when non-nil, will cause +the search to proceed towards the beginning of the widget's contents. +WRAP-AROUND, when nil, will cause the search to stop upon hitting the +end of the widget's contents. + +It is OK to call this function even when a search is already in +progress. In that case, the previous search query will be replaced +with QUERY. */) + (Lisp_Object query, Lisp_Object xwidget, Lisp_Object case_insensitive, + Lisp_Object backwards, Lisp_Object wrap_around) +{ +#ifdef USE_GTK + WebKitWebView *webview; + WebKitFindController *controller; + WebKitFindOptions opt; + struct xwidget *xw; + gchar *g_query; +#endif + + CHECK_STRING (query); + CHECK_XWIDGET (xwidget); + +#ifdef USE_GTK + xw = XXWIDGET (xwidget); + webview = WEBKIT_WEB_VIEW (xw->widget_osr); + query = ENCODE_UTF_8 (query); + opt = WEBKIT_FIND_OPTIONS_NONE; + g_query = xstrdup (SSDATA (query)); + + if (!NILP (case_insensitive)) + opt |= WEBKIT_FIND_OPTIONS_CASE_INSENSITIVE; + if (!NILP (backwards)) + opt |= WEBKIT_FIND_OPTIONS_BACKWARDS; + if (!NILP (wrap_around)) + opt |= WEBKIT_FIND_OPTIONS_WRAP_AROUND; + + if (xw->find_text) + xfree (xw->find_text); + xw->find_text = g_query; + + block_input (); + controller = webkit_web_view_get_find_controller (webview); + webkit_find_controller_search (controller, g_query, opt, G_MAXUINT); + unblock_input (); +#endif + + return Qnil; +} + +DEFUN ("xwidget-webkit-next-result", Fxwidget_webkit_next_result, + Sxwidget_webkit_next_result, 1, 1, 0, + doc: /* Show the next result matching the current search query. + +XWIDGET should be an xwidget that currently has a search query. +Before calling this function, you should start a search operation +using `xwidget-webkit-search'. */) + (Lisp_Object xwidget) +{ + struct xwidget *xw; +#ifdef USE_GTK + WebKitWebView *webview; + WebKitFindController *controller; +#endif + + CHECK_XWIDGET (xwidget); + xw = XXWIDGET (xwidget); + + if (!xw->find_text) + error ("Widget has no ongoing search operation"); + +#ifdef USE_GTK + block_input (); + webview = WEBKIT_WEB_VIEW (xw->widget_osr); + controller = webkit_web_view_get_find_controller (webview); + webkit_find_controller_search_next (controller); + unblock_input (); +#endif + + return Qnil; +} + +DEFUN ("xwidget-webkit-previous-result", Fxwidget_webkit_previous_result, + Sxwidget_webkit_previous_result, 1, 1, 0, + doc: /* Show the previous result matching the current search query. + +XWIDGET should be an xwidget that currently has a search query. +Before calling this function, you should start a search operation +using `xwidget-webkit-search'. */) + (Lisp_Object xwidget) +{ + struct xwidget *xw; +#ifdef USE_GTK + WebKitWebView *webview; + WebKitFindController *controller; +#endif + + CHECK_XWIDGET (xwidget); + xw = XXWIDGET (xwidget); + + if (!xw->find_text) + error ("Widget has no ongoing search operation"); + +#ifdef USE_GTK + block_input (); + webview = WEBKIT_WEB_VIEW (xw->widget_osr); + controller = webkit_web_view_get_find_controller (webview); + webkit_find_controller_search_previous (controller); + + if (xw->find_text) + { + xfree (xw->find_text); + xw->find_text = NULL; + } + unblock_input (); +#endif + + return Qnil; +} + +DEFUN ("xwidget-webkit-finish-search", Fxwidget_webkit_finish_search, + Sxwidget_webkit_finish_search, 1, 1, 0, + doc: /* Finish XWIDGET's search operation. + +XWIDGET should be an xwidget that currently has a search query. +Before calling this function, you should start a search operation +using `xwidget-webkit-search'. */) + (Lisp_Object xwidget) +{ + struct xwidget *xw; +#ifdef USE_GTK + WebKitWebView *webview; + WebKitFindController *controller; +#endif + + CHECK_XWIDGET (xwidget); + xw = XXWIDGET (xwidget); + + if (!xw->find_text) + error ("Widget has no ongoing search operation"); + +#ifdef USE_GTK + block_input (); + webview = WEBKIT_WEB_VIEW (xw->widget_osr); + controller = webkit_web_view_get_find_controller (webview); + webkit_find_controller_search_finish (controller); + unblock_input (); +#endif + + return Qnil; +} + void syms_of_xwidget (void) { @@ -1792,6 +1953,10 @@ syms_of_xwidget (void) defsubr (&Sxwidget_buffer); defsubr (&Sset_xwidget_plist); defsubr (&Sxwidget_perform_lispy_event); + defsubr (&Sxwidget_webkit_search); + defsubr (&Sxwidget_webkit_finish_search); + defsubr (&Sxwidget_webkit_next_result); + defsubr (&Sxwidget_webkit_previous_result); DEFSYM (QCxwidget, ":xwidget"); DEFSYM (QCtitle, ":title"); @@ -2050,6 +2215,8 @@ kill_buffer_xwidgets (Lisp_Object buffer) gtk_widget_destroy (xw->widget_osr); gtk_widget_destroy (xw->widgetwindow_osr); } + if (xw->find_text) + xfree (xw->find_text); if (!NILP (xw->script_callbacks)) for (ptrdiff_t idx = 0; idx < ASIZE (xw->script_callbacks); idx++) { diff --git a/src/xwidget.h b/src/xwidget.h index 8b3aef58d01..3bab6d5b002 100644 --- a/src/xwidget.h +++ b/src/xwidget.h @@ -68,6 +68,7 @@ struct xwidget GtkWidget *widget_osr; GtkWidget *widgetwindow_osr; guint hit_result; + gchar *find_text; #elif defined (NS_IMPL_COCOA) # ifdef __OBJC__ /* For offscreen widgets, unused if not osr. */