diff options
-rw-r--r-- | embed/ephy-embed-shell.c | 24 | ||||
-rw-r--r-- | embed/ephy-embed-shell.h | 3 | ||||
-rw-r--r-- | embed/ephy-embed.c | 101 | ||||
-rw-r--r-- | embed/ephy-embed.h | 3 | ||||
-rw-r--r-- | embed/ephy-web-view.c | 38 | ||||
-rw-r--r-- | embed/ephy-web-view.h | 4 | ||||
-rw-r--r-- | src/ephy-notebook.c | 4 | ||||
-rw-r--r-- | src/ephy-session.c | 23 | ||||
-rw-r--r-- | src/ephy-shell.c | 9 | ||||
-rw-r--r-- | src/ephy-shell.h | 3 |
10 files changed, 197 insertions, 15 deletions
diff --git a/embed/ephy-embed-shell.c b/embed/ephy-embed-shell.c index ea45a1433..b4366b2f4 100644 --- a/embed/ephy-embed-shell.c +++ b/embed/ephy-embed-shell.c @@ -62,6 +62,7 @@ enum DOWNLOAD_ADDED, DOWNLOAD_REMOVED, PREPARE_CLOSE, + RESTORED_WINDOW, LAST_SIGNAL }; @@ -263,6 +264,12 @@ ephy_embed_shell_prepare_close (EphyEmbedShell *shell) g_signal_emit (shell, signals[PREPARE_CLOSE], 0); } +void +ephy_embed_shell_restored_window (EphyEmbedShell *shell) +{ + g_signal_emit (shell, signals[RESTORED_WINDOW], 0); +} + static void ephy_embed_shell_set_property (GObject *object, guint prop_id, @@ -385,6 +392,23 @@ ephy_embed_shell_class_init (EphyEmbedShellClass *klass) g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); +/** + * EphyEmbedShell::finished-restoring-window: + * @shell: the #EphyEmbedShell + * + * The ::finished-restoring-window signal is emitted when the + * session finishes restoring a window. + **/ + signals[RESTORED_WINDOW] = + g_signal_new ("window-restored", + EPHY_TYPE_EMBED_SHELL, + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (EphyEmbedShellClass, restored_window), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, + 0); + g_type_class_add_private (object_class, sizeof (EphyEmbedShellPrivate)); } diff --git a/embed/ephy-embed-shell.h b/embed/ephy-embed-shell.h index e9973a288..45261e93b 100644 --- a/embed/ephy-embed-shell.h +++ b/embed/ephy-embed-shell.h @@ -72,6 +72,8 @@ struct _EphyEmbedShellClass void (* prepare_close) (EphyEmbedShell *shell); + void (* restored_window) (EphyEmbedShell *shell); + /*< private >*/ GObject * (* get_embed_single) (EphyEmbedShell *shell); }; @@ -83,6 +85,7 @@ GObject *ephy_embed_shell_get_encodings (EphyEmbedShell GObject *ephy_embed_shell_get_embed_single (EphyEmbedShell *shell); GObject *ephy_embed_shell_get_adblock_manager (EphyEmbedShell *shell); void ephy_embed_shell_prepare_close (EphyEmbedShell *shell); +void ephy_embed_shell_restored_window (EphyEmbedShell *shell); void ephy_embed_shell_set_page_setup (EphyEmbedShell *shell, GtkPageSetup *page_setup); GtkPageSetup *ephy_embed_shell_get_page_setup (EphyEmbedShell *shell); diff --git a/embed/ephy-embed.c b/embed/ephy-embed.c index 5d9f631bd..8ead506a5 100644 --- a/embed/ephy-embed.c +++ b/embed/ephy-embed.c @@ -43,13 +43,15 @@ #include <webkit/webkit.h> #endif -static void ephy_embed_constructed (GObject *object); +static void ephy_embed_constructed (GObject *object); #ifndef HAVE_WEBKIT2 -static gboolean ephy_embed_inspect_show_cb (WebKitWebInspector *inspector, - EphyEmbed *embed); -static gboolean ephy_embed_inspect_close_cb (WebKitWebInspector *inspector, - EphyEmbed *embed); +static gboolean ephy_embed_inspect_show_cb (WebKitWebInspector *inspector, + EphyEmbed *embed); +static gboolean ephy_embed_inspect_close_cb (WebKitWebInspector *inspector, + EphyEmbed *embed); #endif +static void ephy_embed_restored_window_cb (EphyEmbedShell *shell, + EphyEmbed *embed); #define EPHY_EMBED_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), EPHY_TYPE_EMBED, EphyEmbedPrivate)) @@ -79,6 +81,8 @@ struct _EphyEmbedPrivate GtkWidget *fullscreen_message_label; char *fullscreen_string; + WebKitNetworkRequest *delayed_request; + GtkWidget *overview; guint overview_mode : 1; GSList *messages; @@ -415,6 +419,8 @@ ephy_embed_dispose (GObject *object) priv->adblock_handler_id = 0; } + g_clear_object (&priv->delayed_request); + G_OBJECT_CLASS (ephy_embed_parent_class)->dispose (object); } @@ -423,8 +429,11 @@ ephy_embed_finalize (GObject *object) { EphyEmbed *embed = EPHY_EMBED (object); EphyEmbedPrivate *priv = embed->priv; + EphyEmbedShell *shell = ephy_embed_shell_get_default (); GSList *list; + g_signal_handlers_disconnect_by_func(shell, ephy_embed_restored_window_cb, embed); + list = priv->destroy_on_transition_list; for (; list; list = list->next) { GtkWidget *widget = GTK_WIDGET (list->data); @@ -862,10 +871,50 @@ setup_adblock (GSettings *settings, #endif static void +ephy_embed_maybe_load_delayed_request (EphyEmbed *embed) +{ + EphyEmbedPrivate *priv = embed->priv; + EphyWebView *web_view; + + if (!priv->delayed_request) + return; + + web_view = ephy_embed_get_web_view (embed); + + ephy_web_view_load_request (web_view, priv->delayed_request); + g_clear_object (&priv->delayed_request); + + /* This is to allow UI elements watching load status to show that the page is + * loading as soon as possible. + */ +#ifdef HAVE_WEBKIT2 + g_signal_emit_by_name (web_view, "load-changed", WEBKIT_LOAD_STARTED); +#else + g_object_notify (G_OBJECT (web_view), "load-status"); +#endif +} + +static void +ephy_embed_restored_window_cb (EphyEmbedShell *shell, EphyEmbed *embed) +{ + if (!gtk_widget_get_mapped (GTK_WIDGET (embed))) + return; + + ephy_embed_maybe_load_delayed_request (embed); +} + +static void +ephy_embed_mapped_cb (GtkWidget *widget, gpointer data) +{ + ephy_embed_maybe_load_delayed_request ((EphyEmbed*)widget); +} + +static void ephy_embed_constructed (GObject *object) { EphyEmbed *embed = (EphyEmbed*)object; EphyEmbedPrivate *priv = embed->priv; + EphyEmbedShell *shell = ephy_embed_shell_get_default (); #ifndef HAVE_WEBKIT2 GtkWidget *scrolled_window; #endif @@ -879,6 +928,12 @@ ephy_embed_constructed (GObject *object) WebKitWebInspector *inspector; GtkWidget *overlay; + g_signal_connect (shell, "window-restored", + G_CALLBACK (ephy_embed_restored_window_cb), embed); + + g_signal_connect (embed, "map", + G_CALLBACK (ephy_embed_mapped_cb), NULL); + /* Skeleton */ web_view = WEBKIT_WEB_VIEW (ephy_web_view_new ()); #ifndef HAVE_WEBKIT2 @@ -1161,6 +1216,42 @@ ephy_embed_get_overview_mode (EphyEmbed *embed) } /** + * ephy_embed_set_delayed_load_request: + * @embed: a #EphyEmbed + * @request: a #WebKitNetworkRequest + * + * Sets the #WebKitNetworkRequest that should be loaded when the tab this embed + * is on is switched to. + */ +void +ephy_embed_set_delayed_load_request (EphyEmbed *embed, WebKitNetworkRequest *request) +{ + g_return_if_fail (EPHY_IS_EMBED (embed)); + g_return_if_fail (WEBKIT_IS_NETWORK_REQUEST (request)); + + g_clear_object (&embed->priv->delayed_request); + + g_object_ref (request); + embed->priv->delayed_request = request; +} + +/** + * ephy_embed_has_load_pending: + * @embed: a #EphyEmbed + * + * Checks whether a load has been delayed for this #EphyEmbed. + * + * Returns: %TRUE or %FALSE + */ +gboolean +ephy_embed_has_load_pending (EphyEmbed *embed) +{ + g_return_val_if_fail (EPHY_IS_EMBED (embed), FALSE); + + return !!embed->priv->delayed_request; +} + +/** * ephy_embed_get_overview: * @embed: a #EphyEmbed * diff --git a/embed/ephy-embed.h b/embed/ephy-embed.h index 7820318d8..afa007e60 100644 --- a/embed/ephy-embed.h +++ b/embed/ephy-embed.h @@ -62,6 +62,9 @@ void ephy_embed_auto_download_url (EphyEmbed *embed, const char *url); void ephy_embed_entering_fullscreen (EphyEmbed *embed); void ephy_embed_leaving_fullscreen (EphyEmbed *embed); +void ephy_embed_set_delayed_load_request (EphyEmbed *embed, + WebKitNetworkRequest *request); +gboolean ephy_embed_has_load_pending (EphyEmbed *embed); void ephy_embed_set_overview_mode (EphyEmbed *embed, gboolean overview_mode); gboolean ephy_embed_get_overview_mode (EphyEmbed *embed); diff --git a/embed/ephy-web-view.c b/embed/ephy-web-view.c index 84580d056..c3594ee61 100644 --- a/embed/ephy-web-view.c +++ b/embed/ephy-web-view.c @@ -2370,6 +2370,44 @@ load_status_cb (WebKitWebView *web_view, #endif /** + * ephy_web_view_set_placeholder: + * @view: an #EphyWebView + * @uri: uri that will eventually be loaded + * @title: last-known title of the page that will eventually be loaded + * + * Makes the #EphyWebView pretend a page that will eventually be loaded is + * already there. + * + **/ +void +ephy_web_view_set_placeholder (EphyWebView *view, + const char *uri, + const char *title) +{ + char *html; + + g_return_if_fail (EPHY_IS_WEB_VIEW (view)); + + /* We want only the actual load to be the one recorded in history, but + * doing a load here is the simplest way to replace the loading + * spinner with the favicon. */ + ephy_web_view_freeze_history (view); + + html = g_markup_printf_escaped ("<head><title>%s</title></head>", title); + +#ifdef HAVE_WEBKIT2 + webkit_web_view_load_alternate_html (WEBKIT_WEB_VIEW (view), html, uri, NULL); +#else + webkit_web_frame_load_alternate_string (webkit_web_view_get_main_frame (WEBKIT_WEB_VIEW (view)), + html, uri, uri); +#endif + + g_free (html); + + ephy_web_view_set_address (view, uri); +} + +/** * ephy_web_view_load_error_page: * @view: an #EphyWebView * @uri: uri that caused the failure diff --git a/embed/ephy-web-view.h b/embed/ephy-web-view.h index e3f7161ef..52de7814d 100644 --- a/embed/ephy-web-view.h +++ b/embed/ephy-web-view.h @@ -165,6 +165,10 @@ const char * ephy_web_view_get_title (EphyWebView const char * ephy_web_view_get_address (EphyWebView *view); const char * ephy_web_view_get_title_composite (EphyWebView *view); +void ephy_web_view_set_placeholder (EphyWebView *view, + const char *uri, + const char *title); + void ephy_web_view_load_error_page (EphyWebView *view, const char *uri, EphyWebViewErrorPage page, diff --git a/src/ephy-notebook.c b/src/ephy-notebook.c index 2349af8f9..f9a9007c6 100644 --- a/src/ephy-notebook.c +++ b/src/ephy-notebook.c @@ -467,12 +467,14 @@ static void sync_load_status (EphyWebView *view, GParamSpec *pspec, GtkWidget *proxy) { GtkWidget *spinner, *icon; + EphyEmbed *embed; spinner = GTK_WIDGET (g_object_get_data (G_OBJECT (proxy), "spinner")); icon = GTK_WIDGET (g_object_get_data (G_OBJECT (proxy), "icon")); g_return_if_fail (spinner != NULL && icon != NULL); - if (ephy_web_view_is_loading (view)) + embed = EPHY_GET_EMBED_FROM_EPHY_WEB_VIEW (view); + if (ephy_web_view_is_loading (view) && !ephy_embed_has_load_pending (embed)) { gtk_widget_hide (icon); gtk_widget_show (spinner); diff --git a/src/ephy-session.c b/src/ephy-session.c index 47dfe08bd..82ecf4149 100644 --- a/src/ephy-session.c +++ b/src/ephy-session.c @@ -631,7 +631,7 @@ session_tab_new (EphyEmbed *embed) } session_tab->title = g_strdup (ephy_web_view_get_title (web_view)); - session_tab->loading = ephy_web_view_is_loading (web_view); + session_tab->loading = ephy_web_view_is_loading (web_view) && !ephy_embed_has_load_pending (embed); return session_tab; } @@ -1102,11 +1102,19 @@ session_parse_embed (SessionParserContext *context, */ if (!was_loading || is_blank_page) { - ephy_shell_new_tab (ephy_shell_get_default (), - context->window, NULL, url, - EPHY_NEW_TAB_IN_EXISTING_WINDOW | - EPHY_NEW_TAB_OPEN_PAGE | - EPHY_NEW_TAB_APPEND_LAST); + EphyNewTabFlags flags; + EphyEmbed *embed; + EphyWebView *web_view; + + flags = EPHY_NEW_TAB_IN_EXISTING_WINDOW; + flags |= EPHY_NEW_TAB_APPEND_LAST; + flags |= EPHY_NEW_TAB_DELAYED_OPEN_PAGE; + + embed = ephy_shell_new_tab (ephy_shell_get_default (), + context->window, NULL, url, flags); + + web_view = ephy_embed_get_web_view (embed); + ephy_web_view_set_placeholder (web_view, url, title); } else if (was_loading && url != NULL) { @@ -1150,6 +1158,7 @@ session_end_element (GMarkupParseContext *ctx, if (strcmp (element_name, "window") == 0) { GtkWidget *notebook; + EphyEmbedShell *shell = ephy_embed_shell_get_default (); notebook = ephy_window_get_notebook (context->window); gtk_notebook_set_current_page (GTK_NOTEBOOK (notebook), context->active_tab); @@ -1163,6 +1172,8 @@ session_end_element (GMarkupParseContext *ctx, gtk_widget_show (GTK_WIDGET (context->window)); } + ephy_embed_shell_restored_window (shell); + context->window = NULL; context->active_tab = 0; context->is_first_window = FALSE; diff --git a/src/ephy-shell.c b/src/ephy-shell.c index 7fd01d7de..ebdd48fd0 100644 --- a/src/ephy-shell.c +++ b/src/ephy-shell.c @@ -730,6 +730,7 @@ ephy_shell_new_tab_full (EphyShell *shell, gboolean fullscreen_lockdown = FALSE; gboolean in_new_window = TRUE; gboolean open_page = FALSE; + gboolean delayed_open_page = FALSE; gboolean jump_to = FALSE; gboolean active_is_blank = FALSE; gboolean copy_history = TRUE; @@ -748,6 +749,7 @@ ephy_shell_new_tab_full (EphyShell *shell, embed_shell = EPHY_EMBED_SHELL (shell); if (flags & EPHY_NEW_TAB_OPEN_PAGE) open_page = TRUE; + if (flags & EPHY_NEW_TAB_DELAYED_OPEN_PAGE) delayed_open_page = TRUE; if (flags & EPHY_NEW_TAB_IN_NEW_WINDOW) in_new_window = TRUE; if (flags & EPHY_NEW_TAB_IN_EXISTING_WINDOW) in_new_window = FALSE; if (flags & EPHY_NEW_TAB_DONT_COPY_HISTORY) copy_history = FALSE; @@ -756,7 +758,7 @@ ephy_shell_new_tab_full (EphyShell *shell, fullscreen_lockdown = g_settings_get_boolean (EPHY_SETTINGS_LOCKDOWN, EPHY_PREFS_LOCKDOWN_FULLSCREEN); in_new_window = in_new_window && !fullscreen_lockdown; - g_return_val_if_fail (open_page == (gboolean)(request != NULL), NULL); + g_return_val_if_fail ((open_page || delayed_open_page) == (gboolean)(request != NULL), NULL); LOG ("Opening new tab parent-window %p parent-embed %p in-new-window:%s jump-to:%s", parent_window, previous_embed, in_new_window ? "t" : "f", jump_to ? "t" : "f"); @@ -822,7 +824,7 @@ ephy_shell_new_tab_full (EphyShell *shell, ephy_window_activate_location (window); ephy_web_view_load_homepage (view); is_empty = TRUE; - } else if (flags & EPHY_NEW_TAB_OPEN_PAGE) { + } else if (open_page) { ephy_web_view_load_request (ephy_embed_get_web_view (embed), request); @@ -831,7 +833,8 @@ ephy_shell_new_tab_full (EphyShell *shell, #else is_empty = ephy_embed_utils_url_is_empty (webkit_network_request_get_uri (request)); #endif - } + } else if (delayed_open_page) + ephy_embed_set_delayed_load_request (embed, request); /* Make sure the initial focus is somewhere sensible and not, for * example, on the reload button. diff --git a/src/ephy-shell.h b/src/ephy-shell.h index f65083a7e..7b250fe26 100644 --- a/src/ephy-shell.h +++ b/src/ephy-shell.h @@ -59,6 +59,8 @@ typedef struct _EphyShellPrivate EphyShellPrivate; * @EPHY_NEW_TAB_HOME_PAGE: loads the home page in the new tab. * @EPHY_NEW_TAB_NEW_PAGE: legacy synonym for @EPHY_NEW_TAB_HOME_PAGE. * @EPHY_NEW_TAB_OPEN_PAGE: opens the provided network-request. + * @EPHY_NEW_TAB_DELAYED_OPEN_PAGE: store the provided network-request + * so that it will be opened when the tab is switched to. * @EPHY_NEW_TAB_FULLSCREEN_MODE: calls gtk_window_fullscreen on the * parent window of the new tab. * @EPHY_NEW_TAB_DONT_SHOW_WINDOW: do not show the window where the new @@ -85,6 +87,7 @@ typedef enum { EPHY_NEW_TAB_HOME_PAGE = 1 << 0, EPHY_NEW_TAB_NEW_PAGE = 1 << 1, EPHY_NEW_TAB_OPEN_PAGE = 1 << 2, + EPHY_NEW_TAB_DELAYED_OPEN_PAGE = 1 << 3, /* Page mode */ EPHY_NEW_TAB_FULLSCREEN_MODE = 1 << 4, |