From a43d0cec7a1ab98c5264d7881c8d2752f21dc812 Mon Sep 17 00:00:00 2001 From: Daniel Silverstone Date: Wed, 20 Sep 2017 18:58:19 +0100 Subject: Add concept of browser scroll offset saving in local history --- desktop/browser.c | 30 ++++++++++++++++++++++++++++- desktop/browser_history.c | 41 ++++++++++++++++++++++++++++++++++++++-- desktop/browser_private.h | 15 ++++++++++++++- include/netsurf/browser_window.h | 5 ++++- 4 files changed, 86 insertions(+), 5 deletions(-) diff --git a/desktop/browser.c b/desktop/browser.c index 6cadc54ac..c8768b949 100644 --- a/desktop/browser.c +++ b/desktop/browser.c @@ -887,7 +887,7 @@ nserror browser_window_create(enum browser_window_create_flags flags, } if (url != NULL) { - enum browser_window_nav_flags nav_flags = BW_NAVIGATE_NONE; + enum browser_window_nav_flags nav_flags = BW_NAVIGATE_NO_TERMINAL_HISTORY_UPDATE; if (flags & BW_CREATE_UNVERIFIABLE) nav_flags |= BW_NAVIGATE_UNVERIFIABLE; if (flags & BW_CREATE_HISTORY) @@ -1355,6 +1355,7 @@ browser_window_callback(hlcache_handle *c, { struct browser_window *bw = pw; nserror res = NSERROR_OK; + float sx, sy; switch (event->type) { case CONTENT_MSG_DOWNLOAD: @@ -1485,6 +1486,19 @@ browser_window_callback(hlcache_handle *c, browser_window_stop_throbber(bw); browser_window_update_favicon(c, bw, NULL); + if (browser_window_history_get_scroll(bw, &sx, &sy) == NSERROR_OK) { + int scrollx = (int)((float)content_get_width(bw->current_content) * sx); + int scrolly = (int)((float)content_get_height(bw->current_content) * sy); + struct rect rect; + rect.x0 = rect.x1 = scrollx; + rect.y0 = rect.y1 = scrolly; + if (browser_window_set_scroll(bw, &rect) != NSERROR_OK) { + NSLOG(netsurf, WARNING, + "Unable to set browser scroll offsets to %d by %d", + scrollx, scrolly); + } + } + browser_window_history_update(bw, c); hotlist_update_url(hlcache_handle_get_url(c)); @@ -2014,6 +2028,20 @@ browser_window_navigate(struct browser_window *bw, NSLOG(netsurf, INFO, "bw %p, url %s", bw, nsurl_access(url)); + /* If we're navigating and we have a history entry and a content + * then update the history entry before we navigate to save our + * current state. However since history navigation pre-moves + * the history state, we ensure that we only do this if we've not + * been suppressed. In the suppressed case, the history code + * updates the history itself before navigating. + */ + if (bw->current_content != NULL && + bw->history != NULL && + bw->history->current != NULL && + !(flags & BW_NAVIGATE_NO_TERMINAL_HISTORY_UPDATE)) { + browser_window_history_update(bw, bw->current_content); + } + /* don't allow massively nested framesets */ for (cur = bw; cur->parent; cur = cur->parent) { depth++; diff --git a/desktop/browser_history.c b/desktop/browser_history.c index c8a896290..dac9c7671 100644 --- a/desktop/browser_history.c +++ b/desktop/browser_history.c @@ -32,6 +32,7 @@ #include "utils/utils.h" #include "netsurf/layout.h" #include "netsurf/content.h" +#include "netsurf/window.h" #include "content/hlcache.h" #include "content/urldb.h" #include "netsurf/bitmap.h" @@ -377,6 +378,8 @@ browser_window_history_add(struct browser_window *bw, entry->page.url = nsurl_ref(hlcache_handle_get_url(content)); entry->page.frag_id = frag_id ? lwc_string_ref(frag_id) : NULL; entry->page.title = title; + entry->page.scroll_x = 0.0f; + entry->page.scroll_y = 0.0f; /* create thumbnail for localhistory view */ NSLOG(netsurf, DEBUG, @@ -424,6 +427,7 @@ nserror browser_window_history_update(struct browser_window *bw, { struct history *history; char *title; + int sx, sy; assert(bw != NULL); @@ -442,7 +446,7 @@ nserror browser_window_history_update(struct browser_window *bw, if (title == NULL) { return NSERROR_NOMEM; } - + NSLOG(netsurf, INFO, "Updating history entry for %s", title); free(history->current->page.title); history->current->page.title = title; @@ -450,10 +454,41 @@ nserror browser_window_history_update(struct browser_window *bw, guit->bitmap->render(history->current->page.bitmap, content); } + if (guit->window->get_scroll(bw->window, &sx, &sy)) { + /* Successfully got scroll offsets, update the entry */ + history->current->page.scroll_x = \ + (float)sx / (float)content_get_width(content); + history->current->page.scroll_y = \ + (float)sy / (float)content_get_height(content); + NSLOG(netsurf, INFO, "Updated scroll offsets to %g by %g", + history->current->page.scroll_x, + history->current->page.scroll_y); + } return NSERROR_OK; } +/* exported interface documented in desktop/browser_private.h */ +nserror +browser_window_history_get_scroll(struct browser_window *bw, + float *sx, float *sy) +{ + struct history *history; + + assert(bw != NULL); + + history = bw->history; + + if (!history || + !history->current || + !history->current->page.bitmap) { + return NSERROR_INVALID; + } + + *sx = history->current->page.scroll_x; + *sy = history->current->page.scroll_y; + return NSERROR_OK; +} /* exported interface documented in desktop/browser_history.h */ void browser_window_history_destroy(struct browser_window *bw) @@ -565,9 +600,11 @@ nserror browser_window_history_go(struct browser_window *bw, url, NULL, bw, NULL); history->current = current; } else { + browser_window_history_update(bw, bw->current_content); history->current = entry; error = browser_window_navigate(bw, url, NULL, - BW_NAVIGATE_NONE, NULL, NULL, NULL); + BW_NAVIGATE_NO_TERMINAL_HISTORY_UPDATE, + NULL, NULL, NULL); } nsurl_unref(url); diff --git a/desktop/browser_private.h b/desktop/browser_private.h index 3cdef5c89..192d22bf0 100644 --- a/desktop/browser_private.h +++ b/desktop/browser_private.h @@ -46,6 +46,8 @@ struct history_page { lwc_string *frag_id; /** Fragment identifier, or NULL. */ char *title; /**< Page title, never NULL. */ struct bitmap *bitmap; /**< Thumbnail bitmap, or NULL. */ + float scroll_x; /**< Scroll X offset when visited */ + float scroll_y; /**< Scroll Y offset when visited */ }; /** @@ -325,7 +327,7 @@ nserror browser_window_history_add(struct browser_window *bw, struct hlcache_handle *content, lwc_string *frag_id); /** - * Update the thumbnail for the current entry. + * Update the thumbnail and scroll offsets for the current entry. * * \param bw The browser window to update the history within. * \param content content for current entry @@ -334,6 +336,17 @@ nserror browser_window_history_add(struct browser_window *bw, nserror browser_window_history_update(struct browser_window *bw, struct hlcache_handle *content); +/** + * Retrieve the stored scroll offsets for the current history entry + * + * \param bw The browser window to retrieve scroll offsets for. + * \param sx Pointer to a float for the X scroll offset + * \param sy Pointer to a float for the Y scroll offset + * \return NSERROR_OK or error code on failure. + */ +nserror browser_window_history_get_scroll(struct browser_window *bw, + float *sx, float *sy); + /** * Free a history structure. * diff --git a/include/netsurf/browser_window.h b/include/netsurf/browser_window.h index 567e314c5..6c44e161f 100644 --- a/include/netsurf/browser_window.h +++ b/include/netsurf/browser_window.h @@ -116,7 +116,10 @@ enum browser_window_nav_flags { * A transaction is unverifiable if the user does not * have that option. */ - BW_NAVIGATE_UNVERIFIABLE = (1 << 2) + BW_NAVIGATE_UNVERIFIABLE = (1 << 2), + + /** suppress initial history updates (used by back/fwd/etc) */ + BW_NAVIGATE_NO_TERMINAL_HISTORY_UPDATE = (1 << 3) }; /** -- cgit v1.2.3 From 628fb0ceeff58573a3e094471dda7f07230df3f5 Mon Sep 17 00:00:00 2001 From: Michael Drake Date: Sat, 23 Sep 2017 16:02:38 +0100 Subject: Browser history: Update history scroll offsets on scroll to fragment. --- desktop/browser.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/desktop/browser.c b/desktop/browser.c index c8768b949..b82d8eff3 100644 --- a/desktop/browser.c +++ b/desktop/browser.c @@ -2386,6 +2386,11 @@ static bool frag_scroll(struct browser_window *bw) rect.x1 = rect.x0; rect.y1 = rect.y0; if (browser_window_set_scroll(bw, &rect) == NSERROR_OK) { + if (bw->current_content != NULL && + bw->history != NULL && + bw->history->current != NULL) { + browser_window_history_update(bw, bw->current_content); + } return true; } return false; -- cgit v1.2.3 From fb4be0feb2afd8a3d321673c92a5612be570a70a Mon Sep 17 00:00:00 2001 From: Michael Drake Date: Sat, 23 Sep 2017 16:03:31 +0100 Subject: Browser history: Create new history entries early in the READY state. This prevents us updating the previous history entry with this page's scroll offsets. --- desktop/browser.c | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/desktop/browser.c b/desktop/browser.c index b82d8eff3..19cfebb99 100644 --- a/desktop/browser.c +++ b/desktop/browser.c @@ -1405,23 +1405,6 @@ browser_window_callback(hlcache_handle *c, bw->current_content = c; bw->loading_content = NULL; - /* Format the new content to the correct dimensions */ - browser_window_get_dimensions(bw, &width, &height, true); - content_reformat(c, false, width, height); - - browser_window_remove_caret(bw, false); - - if (bw->window != NULL) { - guit->window->new_content(bw->window); - - browser_window_refresh_url_bar(bw); - } - - /* new content; set scroll_to_top */ - browser_window_update(bw, true); - content_open(c, bw, 0, 0); - browser_window_set_status(bw, content_get_status_message(c)); - /* history */ if (bw->history_add && bw->history) { nsurl *url = hlcache_handle_get_url(c); @@ -1458,6 +1441,23 @@ browser_window_callback(hlcache_handle *c, browser_window_history_add(bw, c, bw->frag_id); } + /* Format the new content to the correct dimensions */ + browser_window_get_dimensions(bw, &width, &height, true); + content_reformat(c, false, width, height); + + browser_window_remove_caret(bw, false); + + if (bw->window != NULL) { + guit->window->new_content(bw->window); + + browser_window_refresh_url_bar(bw); + } + + /* new content; set scroll_to_top */ + browser_window_update(bw, true); + content_open(c, bw, 0, 0); + browser_window_set_status(bw, content_get_status_message(c)); + /* frames */ if ((content_get_type(c) == CONTENT_HTML) && (html_get_frameset(c) != NULL)) { -- cgit v1.2.3 From 9ca33854bf35b46a7796b334ace870029d3e36b9 Mon Sep 17 00:00:00 2001 From: Michael Drake Date: Sat, 23 Sep 2017 16:10:45 +0100 Subject: Browser history: Don't segfault when visiting pages with frames. Core can't make queries of front end about browser windows with no gui window. --- desktop/browser_history.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/desktop/browser_history.c b/desktop/browser_history.c index dac9c7671..640302773 100644 --- a/desktop/browser_history.c +++ b/desktop/browser_history.c @@ -454,7 +454,8 @@ nserror browser_window_history_update(struct browser_window *bw, guit->bitmap->render(history->current->page.bitmap, content); } - if (guit->window->get_scroll(bw->window, &sx, &sy)) { + if (bw->window != NULL && + guit->window->get_scroll(bw->window, &sx, &sy)) { /* Successfully got scroll offsets, update the entry */ history->current->page.scroll_x = \ (float)sx / (float)content_get_width(content); -- cgit v1.2.3