From 58cd1423383babef4a59e25f3e9f6a950d2fa6dc Mon Sep 17 00:00:00 2001 From: John Mark Bell Date: Tue, 17 Mar 2009 12:26:41 +0000 Subject: Remember the scroll position in the history, so that it's maintained when going back. (credit: Paweł Blokus) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit svn path=/trunk/netsurf/; revision=6793 --- amiga/gui.c | 2 +- desktop/browser.c | 69 +++++++++++++++++++++++++++----------------------- desktop/browser.h | 10 ++++---- desktop/history_core.c | 39 ++++++++++++++++++++++++++++ desktop/history_core.h | 2 ++ gtk/gtk_scaffolding.c | 7 +++++ gtk/gtk_window.c | 21 +++++++++++++++ gtk/gtk_window.h | 1 + riscos/window.c | 2 +- 9 files changed, 114 insertions(+), 39 deletions(-) diff --git a/amiga/gui.c b/amiga/gui.c index eaa2d3e7a..4dafa9ec7 100755 --- a/amiga/gui.c +++ b/amiga/gui.c @@ -1353,7 +1353,7 @@ void ami_switch_tab(struct gui_window_2 *gwin,bool redraw) GetAttr(SPACE_AreaBox,gwin->gadgets[GID_BROWSER],(ULONG *)&bbox); p96RectFill(gwin->win->RPort,bbox->Left,bbox->Top,bbox->Width+bbox->Left,bbox->Height+bbox->Top,0xffffffff); - browser_window_update(gwin->bw,false); + browser_window_update(gwin->bw); // if((gwin->bw->window->scrollx) || (gwin->bw->window->scrolly)) // { diff --git a/desktop/browser.c b/desktop/browser.c index 912ab92bc..4d4b4c05e 100644 --- a/desktop/browser.c +++ b/desktop/browser.c @@ -76,7 +76,7 @@ bool browser_reformat_pending; static void browser_window_go_post(struct browser_window *bw, const char *url, char *post_urlenc, struct form_successful_control *post_multipart, - bool history_add, const char *referer, bool download, + bool add_to_history, const char *referer, bool download, bool verifiable, const char *parent_url); static void browser_window_callback(content_msg msg, struct content *c, intptr_t p1, intptr_t p2, union content_msg_data data); @@ -139,11 +139,11 @@ static void browser_window_scroll_box(struct browser_window *bw, struct browser_window *browser_window_create(const char *url, struct browser_window *clone, - const char *referer, bool history_add, bool new_tab) + const char *referer, bool add_to_history, bool new_tab) { struct browser_window *bw; - assert(clone || history_add); + assert(clone || add_to_history); if ((bw = calloc(1, sizeof *bw)) == NULL) { warn_user("NoMemory", 0); @@ -165,7 +165,7 @@ struct browser_window *browser_window_create(const char *url, return NULL; } if (url) - browser_window_go(bw, url, referer, history_add); + browser_window_go(bw, url, referer, add_to_history); return bw; } @@ -208,11 +208,11 @@ void browser_window_initialise_common(struct browser_window *bw, */ void browser_window_go(struct browser_window *bw, const char *url, - const char *referer, bool history_add) + const char *referer, bool add_to_history) { /* All fetches passing through here are verifiable * (i.e are the result of user action) */ - browser_window_go_post(bw, url, 0, 0, history_add, referer, + browser_window_go_post(bw, url, 0, 0, add_to_history, referer, false, true, referer); } @@ -244,11 +244,11 @@ void browser_window_download(struct browser_window *bw, const char *url, */ void browser_window_go_unverifiable(struct browser_window *bw, - const char *url, const char *referer, bool history_add) + const char *url, const char *referer, bool add_to_history) { /* All fetches passing through here are unverifiable * (i.e are not the result of user action) */ - browser_window_go_post(bw, url, 0, 0, history_add, referer, + browser_window_go_post(bw, url, 0, 0, add_to_history, referer, false, false, referer); } @@ -259,7 +259,7 @@ void browser_window_go_unverifiable(struct browser_window *bw, * \param url URL to start fetching (copied) * \param post_urlenc url encoded post data, or 0 if none * \param post_multipart multipart post data, or 0 if none - * \param history_add add to window history + * \param add_to_history add to window history * \param referer the referring uri (copied), or 0 if none * \param download download, rather than render the uri * \param verifiable this transaction is verifiable @@ -270,14 +270,14 @@ void browser_window_go_unverifiable(struct browser_window *bw, * * If post_urlenc and post_multipart are 0 the url is fetched using GET. * - * The page is not added to the window history if add_history is false. This - * should be used when returning to a page in the window history. + * The page is not added to the window history if add_to_history is false. + * This should be used when returning to a page in the window history. */ void browser_window_go_post(struct browser_window *bw, const char *url, char *post_urlenc, struct form_successful_control *post_multipart, - bool history_add, const char *referer, bool download, + bool add_to_history, const char *referer, bool download, bool verifiable, const char *parent_url) { struct content *c; @@ -347,7 +347,10 @@ void browser_window_go_post(struct browser_window *bw, const char *url, if (same_url && !post_urlenc && !post_multipart && !strchr(url2, '?')) { free(url2); - browser_window_update(bw, false); + if (add_to_history) + history_add(bw->history, bw->current_content, + bw->frag_id); + browser_window_update(bw); snprintf(url_buf, sizeof url_buf, "%s#%s", bw->current_content->url, bw->frag_id); url_buf[sizeof url_buf - 1] = 0; @@ -364,7 +367,7 @@ void browser_window_go_post(struct browser_window *bw, const char *url, LOG(("Loading '%s' width %i, height %i", url2, width, height)); browser_window_set_status(bw, messages_get("Loading")); - bw->history_add = history_add; + bw->add_to_history = add_to_history; c = fetchcache(url2, browser_window_callback, (intptr_t) bw, 0, width, height, false, post_urlenc, post_multipart, verifiable, download); @@ -452,12 +455,12 @@ void browser_window_callback(content_msg msg, struct content *c, snprintf(url, sizeof url, "%s", c->url); url[sizeof url - 1] = 0; gui_window_set_url(bw->window, url); - browser_window_update(bw, true); + browser_window_update(bw); content_open(c, bw, 0, 0, 0, 0); browser_window_set_status(bw, c->status_message); /* history */ - if (bw->history_add && bw->history) { + if (bw->add_to_history && bw->history) { history_add(bw->history, c, bw->frag_id); if (urldb_add_url(c->url)) { urldb_set_url_title(c->url, @@ -491,7 +494,7 @@ void browser_window_callback(content_msg msg, struct content *c, case CONTENT_MSG_DONE: assert(bw->current_content == c); - browser_window_update(bw, false); + browser_window_update(bw); browser_window_set_status(bw, c->status_message); browser_window_stop_throbber(bw); history_update(bw->history, c); @@ -541,7 +544,7 @@ void browser_window_callback(content_msg msg, struct content *c, } if (bw->move_callback) bw->move_callback(bw, bw->caret_p); - browser_window_update(bw, false); + browser_window_update(bw); break; case CONTENT_MSG_REDRAW: @@ -673,7 +676,7 @@ void browser_window_convert_to_download(struct browser_window *bw) void browser_window_refresh(void *p) { struct browser_window *bw = p; - bool history_add = true; + bool add_to_history = true; assert(bw->current_content && (bw->current_content->status == CONTENT_STATUS_READY || @@ -691,7 +694,7 @@ void browser_window_refresh(void *p) (bw->current_content->refresh) && (!strcmp(bw->current_content->url, bw->current_content->refresh))) - history_add = false; + add_to_history = false; /* Treat an (almost) immediate refresh in a top-level browser window as * if it were an HTTP redirect, and thus make the resulting fetch @@ -702,10 +705,10 @@ void browser_window_refresh(void *p) */ if (bw->refresh_interval <= 100 && bw->parent == NULL) { browser_window_go(bw, bw->current_content->refresh, - bw->current_content->url, history_add); + bw->current_content->url, add_to_history); } else { browser_window_go_unverifiable(bw, bw->current_content->refresh, - bw->current_content->url, history_add); + bw->current_content->url, add_to_history); } } @@ -774,11 +777,10 @@ bool browser_window_check_throbber(struct browser_window *bw) * \param scroll_to_top move view to top of page */ -void browser_window_update(struct browser_window *bw, - bool scroll_to_top) +void browser_window_update(struct browser_window *bw) { struct box *pos; - int x, y; + int x, y, sx, sy; if (!bw->current_content) return; @@ -790,17 +792,20 @@ void browser_window_update(struct browser_window *bw, gui_window_update_extent(bw->window); - if (scroll_to_top) - gui_window_set_scroll(bw->window, 0, 0); - - /* todo: don't do this if the user has scrolled */ + if (!history_get_current_scroll(bw->history, &sx, &sy)) + sx = -1; + + /* if the page was scrolled before return to that position */ + if (sx != -1) { + gui_window_set_scroll(bw->window, sx, sy); /* if frag_id exists, then try to scroll to it */ - if (bw->frag_id && bw->current_content->type == CONTENT_HTML) { + } else if (bw->frag_id && bw->current_content->type == CONTENT_HTML) { if ((pos = box_find_by_id(bw->current_content->data.html.layout, bw->frag_id)) != 0) { box_coords(pos, &x, &y); gui_window_set_scroll(bw->window, x, y); } - } + } else + gui_window_set_scroll(bw->window, 0, 0); gui_window_redraw_window(bw->window); } @@ -1072,7 +1077,7 @@ void browser_window_set_scale_internal(struct browser_window *bw, float scale) c = bw->current_content; if (c) { if (!content_can_reformat(c)) { - browser_window_update(bw, false); + browser_window_update(bw); } else { bw->reformat_pending = true; browser_reformat_pending = true; diff --git a/desktop/browser.h b/desktop/browser.h index 3db08c325..ef9a3b061 100644 --- a/desktop/browser.h +++ b/desktop/browser.h @@ -80,7 +80,7 @@ struct browser_window { /** Busy indicator is active. */ bool throbbing; /** Add loading_content to the window history when it loads. */ - bool history_add; + bool add_to_history; /** Fragment identifier for current_content. */ char *frag_id; @@ -214,16 +214,16 @@ extern bool browser_reformat_pending; struct browser_window * browser_window_create(const char *url, struct browser_window *clone, const char *referrer, - bool history_add, bool new_tab); + bool add_to_history, bool new_tab); void browser_window_initialise_common(struct browser_window *bw, struct browser_window *clone); void browser_window_go(struct browser_window *bw, const char *url, - const char *referrer, bool history_add); + const char *referrer, bool add_to_history); void browser_window_go_unverifiable(struct browser_window *bw, - const char *url, const char *referrer, bool history_add); + const char *url, const char *referrer, bool add_to_history); void browser_window_download(struct browser_window *bw, const char *url, const char *referrer); -void browser_window_update(struct browser_window *bw, bool scroll_to_top); +void browser_window_update(struct browser_window *bw); void browser_window_stop(struct browser_window *bw); void browser_window_reload(struct browser_window *bw, bool all); void browser_window_destroy(struct browser_window *bw); diff --git a/desktop/history_core.c b/desktop/history_core.c index d6feb69be..433889bea 100644 --- a/desktop/history_core.c +++ b/desktop/history_core.c @@ -29,6 +29,7 @@ #include "content/content.h" #include "content/urldb.h" #include "css/css.h" +#include "desktop/browser.h" #include "desktop/gui.h" #include "desktop/history_core.h" #include "desktop/plotters.h" @@ -63,6 +64,8 @@ struct history_entry { int x; /**< Position of node. */ int y; /**< Position of node. */ struct bitmap *bitmap; /**< Thumbnail bitmap, or 0. */ + int sx; /**< X scroll offset. */ + int sy; /**< Y scroll offset. */ }; /** History tree for a window. */ @@ -259,6 +262,8 @@ void history_add(struct history *history, struct content *content, entry->forward = entry->forward_pref = entry->forward_last = 0; entry->children = 0; entry->bitmap = 0; + entry->sx = -1; + entry->sy = -1; if (history->current) { if (history->current->forward_last) history->current->forward_last->next = entry; @@ -755,3 +760,37 @@ struct history_entry *history_find_position(struct history_entry *entry, return 0; } + +/** + * Save in the history the scroll offsets of the current page + * \param history history with the page + * \param sx x offset to be set + * \param sy y offset to be set + */ + +void history_set_current_scroll(struct history *history, int sx, int sy) +{ + if (!history || !history->current) + return; + + history->current->sx = sx; + history->current->sy = sy; +} + +/** + * Load from the history the scroll offsets of the current page + * \param history history with the page + * \param sx updated to x offset + * \param sy updated to y offset + * \return true on success + */ + +bool history_get_current_scroll(struct history *history, int *sx, int *sy) +{ + if (!history || !history->current) + return false; + + *sx = history->current->sx; + *sy = history->current->sy; + return true; +} diff --git a/desktop/history_core.h b/desktop/history_core.h index 46de18848..4abb94ce8 100644 --- a/desktop/history_core.h +++ b/desktop/history_core.h @@ -46,5 +46,7 @@ bool history_redraw_rectangle(struct history *history, bool history_click(struct browser_window *bw, struct history *history, int x, int y, bool new_window); const char *history_position_url(struct history *history, int x, int y); +void history_set_current_scroll(struct history *history, int sx, int sy); +bool history_get_current_scroll(struct history *history, int *sx, int *sy); #endif diff --git a/gtk/gtk_scaffolding.c b/gtk/gtk_scaffolding.c index 8e687184c..a2c46ef17 100644 --- a/gtk/gtk_scaffolding.c +++ b/gtk/gtk_scaffolding.c @@ -1064,6 +1064,12 @@ MENUHANDLER(local_history) { struct gtk_scaffolding *gw = (struct gtk_scaffolding *)g; + /* if entries of the same url but different frag_ids have been added + * the history needs redrawing (what is done in the throbber code in + * other cases) + */ + nsgtk_window_update_back_forward(gw); + gtk_widget_show(GTK_WIDGET(gw->history_window->window)); gdk_window_raise(GTK_WIDGET(gw->history_window->window)->window); @@ -1149,6 +1155,7 @@ gboolean nsgtk_history_button_press_event(GtkWidget *widget, history_click(bw, bw->history, event->x, event->y, false); + nsgtk_window_update_back_forward(bw->window->scaffold); return TRUE; } diff --git a/gtk/gtk_window.c b/gtk/gtk_window.c index 1784f5926..7ab698e44 100644 --- a/gtk/gtk_window.c +++ b/gtk/gtk_window.c @@ -20,6 +20,7 @@ #include #include "gtk/gtk_window.h" #include "desktop/browser.h" +#include "desktop/history_core.h" #include "desktop/options.h" #include "desktop/textinput.h" #include "desktop/selection.h" @@ -52,6 +53,7 @@ static gboolean nsgtk_window_keypress_event(GtkWidget *, GdkEventKey *, gpointer); static gboolean nsgtk_window_size_allocate_event(GtkWidget *, GtkAllocation *, gpointer); +static void nsgtk_window_scrolled(GtkAdjustment *, gpointer); /* Other useful bits */ static void nsgtk_redraw_caret(struct gui_window *g); @@ -85,6 +87,8 @@ struct gui_window *gui_create_browser_window(struct browser_window *bw, { struct gui_window *g; /**< what we're creating to return */ GtkPolicyType scrollpolicy; + GtkAdjustment *vadj; + GtkAdjustment *hadj; g = malloc(sizeof(*g)); if (!g) { @@ -140,6 +144,9 @@ struct gui_window *gui_create_browser_window(struct browser_window *bw, GTK_SHADOW_NONE); g->viewport = GTK_VIEWPORT(gtk_bin_get_child(GTK_BIN(g->scrolledwindow))); g->tab = NULL; + + vadj = gtk_viewport_get_vadjustment(g->viewport); + hadj = gtk_viewport_get_hadjustment(g->viewport); if (bw->parent != NULL) /* Attach ourselves into our parent at the right point */ @@ -225,6 +232,8 @@ struct gui_window *gui_create_browser_window(struct browser_window *bw, nsgtk_window_keypress_event, g); CONNECT(g->viewport, "size_allocate", nsgtk_window_size_allocate_event, g); + CONNECT(vadj, "value-changed", nsgtk_window_scrolled, g); + CONNECT(hadj, "value-changed", nsgtk_window_scrolled, g); return g; } @@ -582,6 +591,16 @@ gboolean nsgtk_window_size_allocate_event(GtkWidget *widget, return TRUE; } +void nsgtk_window_scrolled(GtkAdjustment *ga, gpointer data) +{ + struct gui_window *g = data; + int sx, sy; + + if (!g->setting_scroll) { + gui_window_get_scroll(g->bw->window, &sx, &sy); + history_set_current_scroll(g->bw->history, sx, sy); + } +} void nsgtk_reflow_all_windows(void) { @@ -718,8 +737,10 @@ void gui_window_set_scroll(struct gui_window *g, int sx, int sy) if (y > (vupper - vpage)) y = vupper - vpage; + g->setting_scroll = true; gtk_adjustment_set_value(vadj, y); gtk_adjustment_set_value(hadj, x); + g->setting_scroll = false; } diff --git a/gtk/gtk_window.h b/gtk/gtk_window.h index 0f99549a7..ba81ad171 100644 --- a/gtk/gtk_window.h +++ b/gtk/gtk_window.h @@ -34,6 +34,7 @@ struct gui_window { int caretx, carety, careth; gui_pointer_shape current_pointer; int last_x, last_y; + bool setting_scroll; /* Within GTK, a gui_window is a scrolled window * with a viewport inside diff --git a/riscos/window.c b/riscos/window.c index 1cc9e7282..15dfbcc37 100644 --- a/riscos/window.c +++ b/riscos/window.c @@ -2537,7 +2537,7 @@ bool ro_gui_window_keypress(wimp_key *key) browser_window_set_scale(g->bw, scale, true); // g->reformat_pending = true; // if ((content) && (content->type != CONTENT_HTML)) -// browser_window_update(g->bw, false); +// browser_window_update(g->bw); // browser_reformat_pending = true; } return true; -- cgit v1.2.3