aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog21
-rw-r--r--embed/ephy-embed-find.c15
-rw-r--r--embed/ephy-embed-find.h6
-rw-r--r--embed/mozilla/EphyFind.cpp86
-rw-r--r--embed/mozilla/EphyFind.h5
-rw-r--r--embed/mozilla/mozilla-embed-find.cpp11
-rw-r--r--src/ephy-find-toolbar.c38
7 files changed, 167 insertions, 15 deletions
diff --git a/ChangeLog b/ChangeLog
index 33119422e..ddbbe3259 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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
}