tags 294152 + fixed-upstream upstream retitle 294152 focus problem with new tabs thanks
Hi, Sanjoy Mahajan <[EMAIL PROTECTED]> - Mon, Feb 07, 2005: > After loading a link in a new tab with ctrl-left button (but not > switching to the new page), I need to click on a non-active area in > the creating page before PageUp and PageDown will scroll up and down. > I'd prefer that galeon preserve the user-interface context of the > creating page, so that ctrl-left button does not affect the user's > interaction with the creating page. The bug you reported should be fixed in upstream source code. The fix will be available with next release. I could not easily backport a patch for 1.3.19, I attach the upstream patch though. Regards, -- Loïc Minier <[EMAIL PROTECTED]> "Neutral President: I have no strong feelings one way or the other."
--- orig/mozilla/GaleonWrapper.cpp +++ mod/mozilla/GaleonWrapper.cpp @@ -383,6 +383,27 @@ nsresult GaleonWrapper::GetZoom (float * return mdv->GetTextZoom (aZoom); } +nsresult GaleonWrapper::FocusActivate () +{ + g_return_val_if_fail (mWebBrowser, NS_ERROR_FAILURE); + + nsCOMPtr<nsIWebBrowserFocus> focus = do_GetInterface(mWebBrowser); + NS_ENSURE_TRUE (focus, NS_ERROR_FAILURE); + + return focus->Activate(); +} + +nsresult GaleonWrapper::FocusDeactivate () +{ + g_return_val_if_fail (mWebBrowser, NS_ERROR_FAILURE); + + nsCOMPtr<nsIWebBrowserFocus> focus = do_GetInterface(mWebBrowser); + NS_ENSURE_TRUE (focus, NS_ERROR_FAILURE); + + return focus->Deactivate(); +} + + nsresult GaleonWrapper::GetFocusedDOMWindow (nsIDOMWindow **aDOMWindow) { nsresult rv; --- orig/mozilla/GaleonWrapper.h +++ mod/mozilla/GaleonWrapper.h @@ -117,6 +117,8 @@ class GaleonWrapper nsresult GetMainDocumentUrl (nsACString &url); nsresult GetDocumentUrl (nsACString &url); + nsresult FocusActivate (); + nsresult FocusDeactivate (); #ifdef HAVE_GTKMOZEMBED_BROKEN_RELOAD nsresult ReloadPage (GtkMozEmbedReloadFlags reloadFlags); --- orig/mozilla/mozilla-embed.cpp +++ mod/mozilla/mozilla-embed.cpp @@ -76,7 +76,8 @@ struct MozillaEmbedPrivate { MozillaEmbedPrivate() : wrapper(NULL), security_state(-1), load_state (MOZILLA_EMBED_LOAD_STARTED), - loaded_url (FALSE), loading_url(0) + loaded_url (FALSE), loading_url(0), + focus_timeout(0) { /* nothing */ } GaleonWrapper *wrapper; @@ -94,6 +95,10 @@ struct MozillaEmbedPrivate */ gboolean loaded_url; //!< Has a web page been loaded gchar *loading_url; //!< The URL we are trying to load + + + // Timeout for the focus hack + guint focus_timeout; }; static GObjectClass *parent_class = NULL; @@ -151,6 +156,44 @@ mozilla_embed_child_event_after_cb (GtkW return FALSE; } + +/** + * Timeout so that the focus is set correctly for the Mozilla Embed + * this needs to be in a timeout, otherwise for some reason it doesn't seem + * to work correctly + */ +static gboolean +activate_focus_timeout_cb (gpointer pointer) +{ + MozillaEmbed *embed = MOZILLA_EMBED (pointer); + + embed->priv->focus_timeout = 0; + + if (embed->priv->wrapper) + { + embed->priv->wrapper->FocusActivate(); + } + + return FALSE; +} + + +static gboolean +deactivate_focus_timeout_cb (gpointer pointer) +{ + MozillaEmbed *embed = MOZILLA_EMBED (pointer); + + embed->priv->focus_timeout = 0; + + if (embed->priv->wrapper) + { + embed->priv->wrapper->FocusDeactivate(); + } + + return FALSE; +} + + /** * Hack: Whenever the *user* wants the focus on the embed there's always going * to be an associated GdkEvent (click on embed, enter on location entry, etc...) @@ -165,16 +208,54 @@ static void mozilla_embed_child_grab_focus_cb (GtkWidget *widget, MozillaEmbed *embed) { GdkEvent *event; + GtkWidget *focused, *toplevel; event = gtk_get_current_event (); - if (!event) + if (event) { - g_signal_stop_emission_by_name (widget, "grab-focus"); + gdk_event_free (event); + return; } - else + + /* Find the GtkWidget that currently has focus, and if it + * is the MozContainer, find the corresponding MozillaEmbed */ + toplevel = gtk_widget_get_toplevel (widget); + focused = gtk_window_get_focus (GTK_WINDOW (toplevel)); + + if (focused && !strcmp ("MozContainer", G_OBJECT_TYPE_NAME (focused))) { - gdk_event_free (event); + focused = gtk_widget_get_parent (focused); + } + + if (focused && GTK_WIDGET (embed) != focused) + { + g_signal_stop_emission_by_name (widget, "grab-focus"); + + /* Focus was trying to move, so deactivate embed which + * attempted to grab it */ + if (embed->priv->focus_timeout) + { + g_source_remove (embed->priv->focus_timeout); + } + embed->priv->focus_timeout = + g_timeout_add (0, deactivate_focus_timeout_cb, embed); + + + if (MOZILLA_IS_EMBED (focused)) + { + MozillaEmbed *membed = MOZILLA_EMBED (focused); + + if (membed->priv->focus_timeout) + { + g_source_remove (membed->priv->focus_timeout); + } + + /* And if the old widget was a mozille embed, + * let it grab the focus back again */ + membed->priv->focus_timeout = + g_timeout_add (0, activate_focus_timeout_cb, membed); + } } } @@ -278,6 +359,11 @@ mozilla_embed_finalize (GObject *object) embed->priv->wrapper = NULL; } + if (embed->priv->focus_timeout) + { + g_source_remove (embed->priv->focus_timeout); + } + g_free (embed->priv->loading_url); delete embed->priv; --- orig/src/galeon-shell.c +++ mod/src/galeon-shell.c @@ -714,17 +714,21 @@ galeon_shell_new_tab_from_embed_full (Ga /* Make sure the initial focus is somewhere sensible and not, for * example, on the reload button. */ - if (galeon_tab_is_empty (tab)) + if (in_new_window || jump_to) { - /* empty page, focus location entry */ - galeon_window_edit_location (window); - } - else if (in_new_window || jump_to) - { - /* non-empty page, focus the page (using bin->child directly as - * I'm too lazy to implement grab_focus in GaleonTab) - */ - gtk_widget_grab_focus (GTK_BIN(tab)->child); + /* If the location entry is blank, focus that, except if the + * page was a copy */ + if (galeon_tab_is_empty (tab) && + !(flags & GALEON_NEW_TAB_IS_A_COPY)) + { + /* empty page, focus location entry */ + galeon_window_edit_location (window); + } + else + { + /* non-empty page, focus the page */ + gtk_widget_grab_focus (GTK_WIDGET (embed)); + } } return tab; --- orig/src/galeon-tab.c +++ mod/src/galeon-tab.c @@ -1953,12 +1953,23 @@ galeon_tab_gesture_performed_cb (GulGest gboolean galeon_tab_is_empty (GaleonTab *tab) { - const char *location; - + char *location; + gboolean is_empty = FALSE; + GaleonEmbed *embed; + g_return_val_if_fail (GALEON_IS_TAB (tab), FALSE); - location = galeon_tab_get_location (tab); - return location == NULL || - location[0] == '\0' || - strcmp (location, "about:blank") == 0; + embed = galeon_tab_get_embed (GALEON_TAB (tab)); + location = galeon_embed_get_location (embed, TRUE, TRUE); + + if (location == NULL || + location[0] == '\0' || + strcmp (location, "about:blank") == 0) + { + is_empty = TRUE; + } + + g_free (location); + + return is_empty; } --- orig/src/window-commands.c +++ mod/src/window-commands.c @@ -259,11 +259,7 @@ open_new_tab (GaleonWindow *window, Gale tab = galeon_window_get_active_tab (window); - tab = galeon_shell_new_tab (galeon_shell, window, tab, NULL, flags); - - window = galeon_tab_get_window (tab); - galeon_window_set_location_entry_location (window, ""); - galeon_window_edit_location (window); + galeon_shell_new_tab (galeon_shell, window, tab, NULL, flags); } void