diff options
-rw-r--r-- | ChangeLog | 21 | ||||
-rw-r--r-- | embed/ephy-embed-find.c | 15 | ||||
-rw-r--r-- | embed/ephy-embed-find.h | 6 | ||||
-rw-r--r-- | embed/mozilla/EphyFind.cpp | 86 | ||||
-rw-r--r-- | embed/mozilla/EphyFind.h | 5 | ||||
-rw-r--r-- | embed/mozilla/mozilla-embed-find.cpp | 11 | ||||
-rw-r--r-- | src/ephy-find-toolbar.c | 38 |
7 files changed, 167 insertions, 15 deletions
@@ -1,3 +1,24 @@ +2005-08-16 Christian Persch <chpe@cvs.gnome.org> + + * embed/ephy-embed-find.c: (ephy_embed_find_activate_link): + * embed/ephy-embed-find.h: + * embed/mozilla/EphyFind.cpp: + * embed/mozilla/EphyFind.h: + * embed/mozilla/mozilla-embed-find.cpp: + + Activate the found link with a faked keypress event. + + * src/ephy-find-toolbar.c: (tab_search_key_press_cb), + (entry_key_press_event_cb), (entry_activate_cb), + (ephy_find_toolbar_set_embed), (ephy_find_toolbar_open), + (ephy_find_toolbar_close): + + On enter, activate the found link instead of finding the next + occurrence. + Always really give focus to the find bar, instead of faking + keypresses in the find bar entry while focusing the embed. + Fixes bug #307216, bug #311985, bug #312419. + 2005-08-15 Christian Persch <chpe@cvs.gnome.org> * data/GNOME_Epiphany_Automation.server.in: diff --git a/embed/ephy-embed-find.c b/embed/ephy-embed-find.c index 596c0b8bc..f5ddb664e 100644 --- a/embed/ephy-embed-find.c +++ b/embed/ephy-embed-find.c @@ -70,6 +70,21 @@ ephy_embed_find_find_again (EphyEmbedFind *find, return iface->find_again (find, forward); } +/** + * ephy_embed_find_activate_link: + * @embed: an #EphyEmbedFind + * @mask: + * + * Activates the currently focused link, if there is any. + **/ +gboolean +ephy_embed_find_activate_link (EphyEmbedFind *find, + GdkModifierType mask) +{ + EphyEmbedFindIface *iface = EPHY_EMBED_FIND_GET_IFACE (find); + return iface->activate_link (find, mask); +} + GType ephy_embed_find_get_type (void) { diff --git a/embed/ephy-embed-find.h b/embed/ephy-embed-find.h index 6dbabe7db..a601c9a4e 100644 --- a/embed/ephy-embed-find.h +++ b/embed/ephy-embed-find.h @@ -25,6 +25,7 @@ #include <glib.h> #include "ephy-embed.h" +#include <gdk/gdktypes.h> G_BEGIN_DECLS @@ -54,6 +55,8 @@ struct _EphyEmbedFindIface gboolean links_only); gboolean (* find_again) (EphyEmbedFind *find, gboolean forward); + gboolean (* activate_link) (EphyEmbedFind *find, + GdkModifierType mask); }; GType ephy_embed_find_get_type (void); @@ -72,6 +75,9 @@ gboolean ephy_embed_find_find (EphyEmbedFind *find, gboolean ephy_embed_find_find_again (EphyEmbedFind *find, gboolean forward); +gboolean ephy_embed_find_activate_link (EphyEmbedFind *find, + GdkModifierType mask); + G_END_DECLS #endif diff --git a/embed/mozilla/EphyFind.cpp b/embed/mozilla/EphyFind.cpp index ace176b23..224e85081 100644 --- a/embed/mozilla/EphyFind.cpp +++ b/embed/mozilla/EphyFind.cpp @@ -37,6 +37,17 @@ #include <nsIInterfaceRequestorUtils.h> #include <nsIDOMWindow.h> #include <nsIWebBrowser.h> +#include <nsIWebBrowserFocus.h> +#include <nsIDOMNode.h> +#include <nsIDOMElement.h> +#include <nsIDOMDocument.h> +#include <nsIDOMDocumentView.h> +#include <nsIDOMAbstractView.h> +#include <nsIDOMDocumentEvent.h> +#include <nsIDOMEvent.h> +#include <nsIDOMKeyEvent.h> +#include <nsIDOMEventTarget.h> +#include <nsIDOMHTMLAnchorElement.h> #ifdef HAVE_TYPEAHEADFIND #include <nsIDocShell.h> @@ -52,6 +63,9 @@ #define NS_TYPEAHEADFIND_CONTRACTID "@mozilla.org/typeaheadfind;1" #endif /* HAVE_TYPEAHEADFIND */ +static const PRUnichar kKeyEvents[] = { 'K', 'e', 'y', 'E', 'v', 'e', 'n', 't', 's', '\0' }; +static const PRUnichar kKeyPress[] = { 'k', 'e', 'y', 'p', 'r', 'e', 's', 's', '\0' }; + EphyFind::EphyFind () : mCurrentEmbed(nsnull) { @@ -70,15 +84,15 @@ EphyFind::SetEmbed (EphyEmbed *aEmbed) if (aEmbed == mCurrentEmbed) return rv; mCurrentEmbed = nsnull; + mWebBrowser = nsnull; rv = NS_ERROR_FAILURE; - nsCOMPtr<nsIWebBrowser> webBrowser; gtk_moz_embed_get_nsIWebBrowser (GTK_MOZ_EMBED (aEmbed), - getter_AddRefs (webBrowser)); - NS_ENSURE_TRUE (webBrowser, rv); + getter_AddRefs (mWebBrowser)); + NS_ENSURE_TRUE (mWebBrowser, rv); #ifdef HAVE_TYPEAHEADFIND - nsCOMPtr<nsIDocShell> docShell (do_GetInterface (webBrowser, &rv)); + nsCOMPtr<nsIDocShell> docShell (do_GetInterface (mWebBrowser, &rv)); NS_ENSURE_SUCCESS (rv, rv); if (!mFinder) { @@ -97,7 +111,7 @@ EphyFind::SetEmbed (EphyEmbed *aEmbed) mFinder->GetSearchString (&string); } - mFinder = do_GetInterface (webBrowser, &rv); + mFinder = do_GetInterface (mWebBrowser, &rv); NS_ENSURE_SUCCESS (rv, rv); mFinder->SetWrapFind (PR_TRUE); @@ -186,3 +200,65 @@ EphyFind::FindAgain (PRBool aForward) return NS_SUCCEEDED (rv) && didFind; #endif /* HAVE_TYPEAHEADFIND */ } + +PRBool +EphyFind::ActivateLink (GdkModifierType aMask) +{ + nsresult rv; + nsCOMPtr<nsIDOMElement> link; +#if defined(HAVE_TYPEAHEADFIND) && defined(HAVE_GECKO_1_8) + rv = mFinder->GetFoundLink (getter_AddRefs (link)); + NS_ENSURE_TRUE (NS_SUCCEEDED (rv) && link, FALSE); +#else + nsCOMPtr<nsIWebBrowserFocus> focus (do_QueryInterface (mWebBrowser)); + NS_ENSURE_TRUE (focus, FALSE); + + rv = focus->GetFocusedElement (getter_AddRefs (link)); + NS_ENSURE_TRUE (NS_SUCCEEDED (rv) && link, FALSE); + + /* ensure this is really a link so we don't accidentally submit if we're on a button or so! */ + nsCOMPtr<nsIDOMHTMLAnchorElement> anchor (do_QueryInterface (link)); + if (!anchor) return FALSE; +#endif /* HAVE_TYPEAHEADFIND && HAVE_GECKO_1_8 */ + + nsCOMPtr<nsIDOMDocument> doc; + rv = link->GetOwnerDocument (getter_AddRefs (doc)); + NS_ENSURE_TRUE (doc, FALSE); + + nsCOMPtr<nsIDOMDocumentView> docView (do_QueryInterface (doc)); + NS_ENSURE_TRUE (docView, FALSE); + + nsCOMPtr<nsIDOMAbstractView> abstractView; + docView->GetDefaultView (getter_AddRefs (abstractView)); + NS_ENSURE_TRUE (abstractView, FALSE); + + nsCOMPtr<nsIDOMDocumentEvent> docEvent (do_QueryInterface (doc)); + NS_ENSURE_TRUE (docEvent, FALSE); + + nsCOMPtr<nsIDOMEvent> event; + rv = docEvent->CreateEvent (nsEmbedString(kKeyEvents), getter_AddRefs (event)); + NS_ENSURE_SUCCESS (rv, FALSE); + + nsCOMPtr<nsIDOMKeyEvent> keyEvent (do_QueryInterface (event)); + NS_ENSURE_TRUE (keyEvent, FALSE); + + rv = keyEvent->InitKeyEvent (nsEmbedString (kKeyPress), + PR_TRUE /* bubble */, + PR_TRUE /* cancelable */, + abstractView, + (aMask & GDK_CONTROL_MASK) != 0, + (aMask & GDK_MOD1_MASK) != 0 /* Alt */, + (aMask & GDK_SHIFT_MASK) != 0, + PR_FALSE /* Meta */, + nsIDOMKeyEvent::DOM_VK_RETURN, + 0); + NS_ENSURE_SUCCESS (rv, FALSE); + + nsCOMPtr<nsIDOMEventTarget> target (do_QueryInterface (link)); + NS_ENSURE_TRUE (target, FALSE); + + PRBool defaultPrevented = PR_FALSE; + rv = target->DispatchEvent (event, &defaultPrevented); + + return NS_SUCCEEDED (rv); +} diff --git a/embed/mozilla/EphyFind.h b/embed/mozilla/EphyFind.h index 7188ffb74..8e85356cb 100644 --- a/embed/mozilla/EphyFind.h +++ b/embed/mozilla/EphyFind.h @@ -24,8 +24,10 @@ #include "ephy-embed.h" #include <nsCOMPtr.h> +#include <gdk/gdktypes.h> class nsITypeAheadFind; +class nsIWebBrowser; class nsIWebBrowserFind; class EphyFind @@ -41,10 +43,13 @@ class EphyFind PRBool Find (const char *aSearchString, PRBool aLinksOnly); PRBool FindAgain (PRBool aForward); + PRBool ActivateLink (GdkModifierType aMask); private: EphyEmbed *mCurrentEmbed; + nsCOMPtr<nsIWebBrowser> mWebBrowser; + #ifdef HAVE_TYPEAHEADFIND nsCOMPtr<nsITypeAheadFind> mFinder; #else diff --git a/embed/mozilla/mozilla-embed-find.cpp b/embed/mozilla/mozilla-embed-find.cpp index d039b4d69..f8f4e6c60 100644 --- a/embed/mozilla/mozilla-embed-find.cpp +++ b/embed/mozilla/mozilla-embed-find.cpp @@ -83,6 +83,16 @@ impl_find_again (EphyEmbedFind *efind, return priv->find->FindAgain (forward); } +static gboolean +impl_activate_link (EphyEmbedFind *efind, + GdkModifierType mask) +{ + MozillaEmbedFind *find = MOZILLA_EMBED_FIND (efind); + MozillaEmbedFindPrivate *priv = find->priv; + + return priv->find->ActivateLink (mask); +} + static void ephy_find_iface_init (EphyEmbedFindIface *iface) { @@ -90,6 +100,7 @@ ephy_find_iface_init (EphyEmbedFindIface *iface) iface->set_properties = impl_set_properties; iface->find = impl_find; iface->find_again = impl_find_again; + iface->activate_link = impl_activate_link; } static void diff --git a/src/ephy-find-toolbar.c b/src/ephy-find-toolbar.c index 2ae7d15ed..59eee34c2 100644 --- a/src/ephy-find-toolbar.c +++ b/src/ephy-find-toolbar.c @@ -40,6 +40,8 @@ #include <gtk/gtkmain.h> #include <string.h> +#undef FIND_WHILE_TYPING_IN_EMBED + #define EPHY_FIND_TOOLBAR_GET_PRIVATE(object) (G_TYPE_INSTANCE_GET_PRIVATE ((object),EPHY_TYPE_FIND_TOOLBAR, EphyFindToolbarPrivate)) struct _EphyFindToolbarPrivate @@ -118,6 +120,8 @@ tab_content_changed_cb (EphyEmbed *embed, #ifdef HAVE_TYPEAHEADFIND +#ifdef FIND_WHILE_TYPING_IN_EMBED + /* Cut and paste from gtkwindow.c */ static void send_focus_change (GtkWidget *widget, @@ -150,6 +154,8 @@ send_focus_change (GtkWidget *widget, gdk_event_free (event); } +#endif /* FIND_WHILE_TYPING_IN_EMBED */ + /* Code adapted from gtktreeview.c:gtk_tree_view_key_press() and * gtk_tree_view_real_start_interactive_seach() */ @@ -160,10 +166,12 @@ tab_search_key_press_cb (EphyEmbed *embed, { EphyFindToolbarPrivate *priv = toolbar->priv; GtkWidget *widget = (GtkWidget *) toolbar; +#ifdef FIND_WHILE_TYPING_IN_EMBED GtkEntry *entry = (GtkEntry *) priv->entry; GdkWindow *event_window; gboolean retval = FALSE; guint oldhash, newhash; +#endif g_return_val_if_fail (event != NULL, FALSE); @@ -184,7 +192,10 @@ tab_search_key_press_cb (EphyEmbed *embed, return TRUE; } } - + + return FALSE; + +#ifdef FIND_WHILE_TYPING_IN_EMBED /* don't do anything if the find toolbar is hidden */ if (GTK_WIDGET_VISIBLE (widget) == FALSE || event->keyval == GDK_Return || @@ -212,8 +223,11 @@ tab_search_key_press_cb (EphyEmbed *embed, /* FIXME: is this correct? */ return retval && (oldhash != newhash || priv->preedit_changed) && !priv->activated; +#endif /* FIND_WHILE_TYPING_IN_EMBED */ } +#ifdef FIND_WHILE_TYPING_IN_EMBED + static gboolean tab_dom_mouse_click_cb (EphyEmbed *embed, gpointer event, @@ -229,6 +243,8 @@ tab_dom_mouse_click_cb (EphyEmbed *embed, return FALSE; } +#endif /* FIND_WHILE_TYPING_IN_EMBED */ + #endif /* HAVE_TYPEAHEADFIND */ static void @@ -289,6 +305,11 @@ entry_key_press_event_cb (GtkEntry *entry, g_signal_emit (toolbar, signals[CLOSE], 0); handled = TRUE; } + else if ((event->state & mask) == GDK_CONTROL_MASK && + (event->keyval == GDK_Return || event->keyval == GDK_KP_Enter)) + { + handled = ephy_embed_find_activate_link (get_find (toolbar), event->state); + } return handled; } @@ -297,12 +318,7 @@ static void entry_activate_cb (GtkWidget *entry, EphyFindToolbar *toolbar) { - EphyFindToolbarPrivate *priv = toolbar->priv; - - priv->activated = TRUE; - if (priv->prevent_activate) return; - - g_signal_emit (toolbar, signals[NEXT], 0); + ephy_embed_find_activate_link (get_find (toolbar), 0); } static void @@ -621,10 +637,12 @@ ephy_find_toolbar_set_embed (EphyFindToolbar *toolbar, g_signal_connect_object (embed, "ge-search-key-press", G_CALLBACK (tab_search_key_press_cb), toolbar, 0); +#ifdef FIND_WHILE_TYPING_IN_EMBED g_signal_connect_object (embed, "dom-mouse-click", G_CALLBACK (tab_dom_mouse_click_cb), toolbar, 0); -#endif +#endif /* FIND_WHILE_TYPING_IN_EMBED */ +#endif /* HAVE_TYPEAHEADFIND */ if (priv->find != NULL) { @@ -676,7 +694,7 @@ ephy_find_toolbar_open (EphyFindToolbar *toolbar, gtk_widget_show (GTK_WIDGET (toolbar)); -#ifdef HAVE_TYPEAHEADFIND +#if defined(HAVE_TYPEAHEADFIND) && defined(FIND_WHILE_TYPING_IN_EMBED) gtk_widget_grab_focus (GTK_WIDGET (priv->embed)); send_focus_change (priv->entry, TRUE); @@ -702,7 +720,7 @@ ephy_find_toolbar_close (EphyFindToolbar *toolbar) /* first unset explicit_focus, else we get infinite recursion */ priv->explicit_focus = FALSE; -#ifndef HAVE_TYPEAHEADFIND +#ifndef FIND_WHILE_TYPING_IN_EMBED gtk_widget_grab_focus (GTK_WIDGET (priv->embed)); #endif } |