[balsa] Initial support for webkit search-text
- From: Peter Bloomfield <PeterB src gnome org>
- To: svn-commits-list gnome org
- Cc:
- Subject: [balsa] Initial support for webkit search-text
- Date: Fri, 4 Dec 2009 00:08:49 +0000 (UTC)
commit d4dc82623a32c521c01604f3d0486c1c4e7cd043
Author: Peter Bloomfield <PeterBloomfield bellsouth net>
Date: Thu Dec 3 19:08:37 2009 -0500
Initial support for webkit search-text
ChangeLog | 17 ++++++
libbalsa/html.c | 142 ++++++++++++++++++++++++++++++++-------------------
libbalsa/html.h | 2 +
src/balsa-message.c | 83 +++++++++++++++++++++--------
4 files changed, 169 insertions(+), 75 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index 86177ad..1011ee8 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,20 @@
+2009-12-03 Peter Bloomfield
+
+ * src/balsa-message.c (bm_find_set_status),
+ (bm_find_scroll_to_rectangle), (bm_find_scroll_to_selection),
+ (bm_find_entry_changed_cb), (bm_find_again): implement
+ search-text for HTML parts; desensitize find-next and
+ find-previous when find-entry is empty.
+
+2009-12-03 Peter Bloomfield
+
+ * libbalsa/html.c (lbh_navigation_policy_decision_requested_cb),
+ (libbalsa_html_new), (libbalsa_html_search_text),
+ (libbalsa_html_get_selection_bounds),
+ (libbalsa_html_can_search): implement search-text for webkit
+ backend, but only if we can scroll to the text.
+ * libbalsa/html.h: implement libbalsa_html_search_text.
+
2009-11-16 Peter Bloomfield
* src/balsa-message.c (balsa_message_find_in_message): grab
diff --git a/libbalsa/html.c b/libbalsa/html.c
index c8e6c28..ecbe65b 100644
--- a/libbalsa/html.c
+++ b/libbalsa/html.c
@@ -65,18 +65,14 @@
* "request-url" signal; WebKit does not have one. We turn off its
* "auto-load-images" setting, which seems to mean that <img src="...">
* tags are ignored. However, that is apparently intended to save
- * bandwidth rather than to protect privacy. The server in a <frame
- * src="..."> is known to be contacted; whether "src=" attributes on
+ * bandwidth rather than to protect privacy. The WebView attempts to
+ * contact the server named in <frame src="...">, but we detect it
+ * because of the new frame, and block it; whether "src=" attributes on
* other tags are followed is unknown.
*
* We do disable scripts, so the server in a <script src="..."> should
* not be contacted.
*
- * The action taken on a <frame src="..."> tag seems buggy: it results
- * in a "navigation-requested" signal, which is otherwise emitted when
- * the user clicks on a link. Consequently, we pass it to the Gnome
- * browser without verifying that the user wants it.
- *
* https://bugs.webkit.org/show_bug.cgi?id=17147 discusses these issues.
*/
@@ -84,10 +80,13 @@
typedef struct {
WebKitWebView *web_view;
+ WebKitWebFrame *frame;
LibBalsaHtmlCallback hover_cb;
LibBalsaHtmlCallback clicked_cb;
+#if !WEBKIT_CHECK_VERSION(1, 12, 0)
GtkAdjustment *hadj;
GtkAdjustment *vadj;
+#endif /* !WEBKIT_CHECK_VERSION(1, 12, 0) */
} LibBalsaWebKitInfo;
static void
@@ -101,6 +100,7 @@ lbh_hovering_over_link_cb(GtkWidget * web_view,
(*info->hover_cb)(uri);
}
+#if !WEBKIT_CHECK_VERSION(1, 12, 0)
static void
lbh_size_request_cb(GtkWidget * widget,
GtkRequisition * requisition,
@@ -116,6 +116,7 @@ lbh_size_request_cb(GtkWidget * widget,
if (upper > requisition->height)
requisition->height = upper;
}
+#endif /* !WEBKIT_CHECK_VERSION(1, 12, 0) */
static gboolean
lbh_navigation_policy_decision_requested_cb(WebKitWebView * web_view,
@@ -130,15 +131,24 @@ lbh_navigation_policy_decision_requested_cb(WebKitWebView * web_view
g_object_get(action, "reason", &reason, NULL);
+ /* First request is for "about:blank"; we must allow it, but first
+ * we store the main frame, so we can detect a new frame later. */
+ if (!info->frame)
+ info->frame = frame;
+ else if (web_view == info->web_view
+ && frame != info->frame
+ && reason == WEBKIT_WEB_NAVIGATION_REASON_OTHER) {
+ g_message("%s new frame ignored:\n URI=\"%s\"", __func__,
+ webkit_network_request_get_uri(request));
+ webkit_web_policy_decision_ignore(decision);
+ return TRUE;
+ }
+
if (reason == WEBKIT_WEB_NAVIGATION_REASON_LINK_CLICKED ||
(web_view != info->web_view
&& reason == WEBKIT_WEB_NAVIGATION_REASON_OTHER)) {
- const gchar *uri = webkit_network_request_get_uri(request);
-
- (*info->clicked_cb) (uri);
-
+ (*info->clicked_cb) (webkit_network_request_get_uri(request));
webkit_web_policy_decision_ignore(decision);
-
return TRUE;
}
@@ -222,6 +232,7 @@ libbalsa_html_new(const gchar * text,
info = g_new(LibBalsaWebKitInfo, 1);
info->web_view = web_view = WEBKIT_WEB_VIEW(widget);
+ info->frame = NULL;
g_object_weak_ref(G_OBJECT(web_view), (GWeakNotify) g_free, info);
g_object_set(webkit_web_view_get_settings(web_view),
@@ -230,6 +241,7 @@ libbalsa_html_new(const gchar * text,
"enable-plugins", FALSE,
NULL);
+#if !WEBKIT_CHECK_VERSION(1, 12, 0)
info->hadj =
GTK_ADJUSTMENT(gtk_adjustment_new(0.0, 0.0, 0.0, 0.0, 0.0, 0.0));
info->vadj =
@@ -240,6 +252,7 @@ libbalsa_html_new(const gchar * text,
g_signal_connect(web_view, "size-request",
G_CALLBACK(lbh_size_request_cb), info);
+#endif /* !WEBKIT_CHECK_VERSION(1, 12, 0) */
info->hover_cb = hover_cb;
g_signal_connect(web_view, "hovering-over-link",
G_CALLBACK(lbh_hovering_over_link_cb), info);
@@ -325,6 +338,8 @@ libbalsa_html_copy(GtkWidget * widget)
webkit_web_view_copy_clipboard(WEBKIT_WEB_VIEW(widget));
}
+#define WEBKIT_WEB_VIEW_CAN_MANAGE_SELECTION FALSE
+#if WEBKIT_WEB_VIEW_CAN_MANAGE_SELECTION
/*
* Does the widget support searching text?
*/
@@ -335,17 +350,55 @@ libbalsa_html_can_search(GtkWidget * widget)
}
/*
- * Search for the text.
+ * Search for the text; if text is empty, return TRUE (for consistency
+ * with GtkTextIter methods).
*/
gboolean
libbalsa_html_search_text(GtkWidget * widget, const gchar * text,
gboolean find_forward, gboolean wrap)
{
+ if (!*text) {
+ webkit_web_view_clear_selection(WEBKIT_WEB_VIEW(widget));
+ return TRUE;
+ }
+
return webkit_web_view_search_text(WEBKIT_WEB_VIEW(widget), text,
- FALSE, /* case-insensitive */
+ FALSE, /* case-insensitive */
find_forward, wrap);
}
+/*
+ * Get the rectangle containing the currently selected text, for
+ * scrolling.
+ */
+void
+libbalsa_html_get_selection_bounds(GtkWidget * widget,
+ GdkRectangle * selection_bounds)
+{
+ webkit_web_view_get_selection_bounds(WEBKIT_WEB_VIEW(widget),
+ selection_bounds);
+}
+#else /* WEBKIT_WEB_VIEW_CAN_MANAGE_SELECTION */
+gboolean
+libbalsa_html_can_search(GtkWidget * widget)
+{
+ return FALSE;
+}
+
+gboolean
+libbalsa_html_search_text(GtkWidget * widget, const gchar * text,
+ gboolean find_forward, gboolean wrap)
+{
+ return FALSE;
+}
+
+void
+libbalsa_html_get_selection_bounds(GtkWidget * widget,
+ GdkRectangle * selection_bounds)
+{
+}
+#endif /* WEBKIT_WEB_VIEW_CAN_MANAGE_SELECTION */
+
# else /* defined(HAVE_WEBKIT) */
/* Common code for both GtkHtml widgets. */
@@ -601,25 +654,6 @@ libbalsa_html_copy(GtkWidget * widget)
gtk_html_copy(GTK_HTML(widget));
}
-/*
- * GtkHTML doesn't support searching text.
- */
-gboolean
-libbalsa_html_can_search(GtkWidget * widget)
-{
- return FALSE;
-}
-
-/*
- * GtkHTML doesn't support searching text.
- */
-gboolean
-libbalsa_html_search_text(GtkWidget * widget, const gchar * text,
- gboolean find_forward, gboolean wrap)
-{
- return FALSE;
-}
-
# else /* HAVE_GTKHTML3 */
/* Code for GtkHtml-2 */
@@ -755,25 +789,6 @@ libbalsa_html_copy(GtkWidget * widget)
{
}
-/*
- * HtmlView doesn't support searching text.
- */
-gboolean
-libbalsa_html_can_search(GtkWidget * widget)
-{
- return FALSE;
-}
-
-/*
- * HtmlView doesn't support searching text.
- */
-gboolean
-libbalsa_html_search_text(GtkWidget * widget, const gchar * text,
- gboolean find_forward, gboolean wrap)
-{
- return FALSE;
-}
-
# endif /* HAVE_GTKHTML3 */
/* Common code for both widgets. */
@@ -810,6 +825,29 @@ libbalsa_html_url_requested(GtkWidget * html, const gchar * url,
return TRUE;
}
+
+/*
+ * Neither widget supports searching text
+ */
+gboolean
+libbalsa_html_can_search(GtkWidget * widget)
+{
+ return FALSE;
+}
+
+gboolean
+libbalsa_html_search_text(GtkWidget * widget, const gchar * text,
+ gboolean find_forward, gboolean wrap)
+{
+ return FALSE;
+}
+
+void
+libbalsa_html_get_selection_bounds(GtkWidget * widget,
+ GdkRectangle * selection_bounds)
+{
+}
+
# endif /* defined(HAVE_WEBKIT) */
/* Filter text/enriched or text/richtext to text/html, if we have GMime
diff --git a/libbalsa/html.h b/libbalsa/html.h
index bd09382..23125ef 100644
--- a/libbalsa/html.h
+++ b/libbalsa/html.h
@@ -63,6 +63,8 @@ guint libbalsa_html_filter(LibBalsaHTMLType html_type, gchar ** text,
gboolean libbalsa_html_can_search(GtkWidget * widget);
gboolean libbalsa_html_search_text(GtkWidget * widget, const gchar * text,
gboolean find_forward, gboolean wrap);
+void libbalsa_html_get_selection_bounds(GtkWidget * widget,
+ GdkRectangle * selection_bounds);
# endif /* HAVE_GTKHTML */
diff --git a/src/balsa-message.c b/src/balsa-message.c
index 85d1b73..705380c 100644
--- a/src/balsa-message.c
+++ b/src/balsa-message.c
@@ -401,7 +401,11 @@ bm_find_set_status(BalsaMessage * bm, BalsaMessageFindStatus status)
case BM_FIND_STATUS_INIT:
break;
case BM_FIND_STATUS_FOUND:
- sensitive = TRUE;
+ /* The widget returned "found"; if it really found a string,
+ * we sensitize the "next" and "previous" buttons, but if
+ * the find-entry was empty, we desensitize them. */
+ if (gtk_entry_get_text(GTK_ENTRY(bm->find_entry))[0])
+ sensitive = TRUE;
break;
case BM_FIND_STATUS_WRAPPED:
text = _("Wrapped");
@@ -420,27 +424,46 @@ bm_find_set_status(BalsaMessage * bm, BalsaMessageFindStatus status)
}
static void
-bm_find_scroll_to_iter(BalsaMessage * bm,
- GtkTextView * text_view,
- GtkTextIter * iter)
+bm_find_scroll_to_rectangle(BalsaMessage * bm,
+ GtkWidget * widget,
+ GdkRectangle * rectangle)
{
- GtkAdjustment *adj =
- gtk_viewport_get_vadjustment(GTK_VIEWPORT(bm->cont_viewport));
- GdkRectangle location;
- gdouble y;
+ gint x, y;
+ GtkAdjustment *adj;
+
+ gtk_widget_translate_coordinates(widget, bm->bm_widget->widget,
+ rectangle->x, rectangle->y,
+ &x, &y);
- gtk_text_view_get_iter_location(text_view, iter, &location);
+ adj = gtk_viewport_get_hadjustment(GTK_VIEWPORT(bm->cont_viewport));
+ gtk_adjustment_clamp_page(adj, x, x + rectangle->width);
+
+ adj = gtk_viewport_get_vadjustment(GTK_VIEWPORT(bm->cont_viewport));
+ gtk_adjustment_clamp_page(adj, y, y + rectangle->height);
+}
+
+static void
+bm_find_scroll_to_selection(BalsaMessage * bm,
+ GtkTextView * text_view,
+ GtkTextIter * begin_iter,
+ GtkTextIter * end_iter)
+{
+ GdkRectangle begin_location, end_location;
+
+ gtk_text_view_get_iter_location(text_view, begin_iter,
+ &begin_location);
+ gtk_text_view_get_iter_location(text_view, end_iter,
+ &end_location);
+ end_location.width = 0;
+ gdk_rectangle_union(&begin_location, &end_location, &begin_location);
gtk_text_view_buffer_to_window_coords(text_view,
GTK_TEXT_WINDOW_WIDGET,
- location.x, location.y,
- NULL, &location.y);
- gtk_widget_translate_coordinates(GTK_WIDGET(text_view),
- bm->bm_widget->widget,
- location.x, location.y,
- NULL, &location.y);
+ begin_location.x,
+ begin_location.y,
+ &begin_location.x,
+ &begin_location.y);
- y = location.y;
- gtk_adjustment_clamp_page(adj, y, y + location.height);
+ bm_find_scroll_to_rectangle(bm, GTK_WIDGET(text_view), &begin_location);
}
static void
@@ -478,12 +501,21 @@ bm_find_entry_changed_cb(GtkEditable * editable, gpointer data)
if (found) {
gtk_text_buffer_select_range(buffer, &match_begin, &match_end);
- bm_find_scroll_to_iter(bm, text_view, &match_begin);
+ bm_find_scroll_to_selection(bm, text_view,
+ &match_begin, &match_end);
bm->find_iter = match_begin;
}
- } else if (libbalsa_html_can_search(widget))
- found = libbalsa_html_search_text(widget, text, bm->find_forward, TRUE);
- else
+ } else if (libbalsa_html_can_search(widget)) {
+ found = libbalsa_html_search_text(widget, text,
+ bm->find_forward, TRUE);
+ if (found && *text) {
+ GdkRectangle selection_bounds;
+
+ libbalsa_html_get_selection_bounds(widget,
+ &selection_bounds);
+ bm_find_scroll_to_rectangle(bm, widget, &selection_bounds);
+ }
+ } else
g_assert_not_reached();
bm_find_set_status(bm, found ?
@@ -523,12 +555,17 @@ bm_find_again(BalsaMessage * bm, gboolean find_forward)
}
gtk_text_buffer_select_range(buffer, &match_begin, &match_end);
- bm_find_scroll_to_iter(bm, text_view, &match_begin);
+ bm_find_scroll_to_selection(bm, text_view,
+ &match_begin, &match_end);
bm->find_iter = match_begin;
} else if (libbalsa_html_can_search(widget)) {
+ GdkRectangle selection_bounds;
+
found = libbalsa_html_search_text(widget, text, find_forward, FALSE);
if (!found)
libbalsa_html_search_text(widget, text, find_forward, TRUE);
+ libbalsa_html_get_selection_bounds(widget, &selection_bounds);
+ bm_find_scroll_to_rectangle(bm, widget, &selection_bounds);
} else
g_assert_not_reached();
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]