I modified the patch to fit the suggestions You gave me on IRC. Now
the scroll offsets are kept up-to-date all the time. I had problems
with the scroll-child event in GtkScrolledWindow not getting called on
any kind of scroll so I used the value-changed events of the two
scrollbars. There is one thing that is still bothering me - doesn't
calling the callback function every time you scroll have an impact on
scroll efficiency?


Index: gtk/gtk_window.c
===================================================================
--- gtk/gtk_window.c    (wersja 6748)
+++ gtk/gtk_window.c    (kopia robocza)
@@ -20,6 +20,7 @@
 #include <inttypes.h>
 #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 @@
                                                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,7 +87,9 @@
 {
        struct gui_window *g;           /**< what we're creating to return */
         GtkPolicyType scrollpolicy;
-
+       GtkAdjustment *vadj;
+       GtkAdjustment *hadj;
+       
        g = malloc(sizeof(*g));
                if (!g) {
                warn_user("NoMemory", 0);
@@ -140,6 +144,9 @@
                                            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 @@
                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;
 }
@@ -581,8 +590,15 @@

        return TRUE;
 }
-
-
+       
+void nsgtk_window_scrolled(GtkAdjustment *ga, gpointer data)
+{
+       struct gui_window *g = data;
+       if (!g->setting_scroll) {
+               history_set_current_scroll(g->bw);
+       }
+}              
+               
 void nsgtk_reflow_all_windows(void)
 {
        for (struct gui_window *g = window_list; g; g = g->next) {
@@ -718,8 +734,10 @@
         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;
 }


Index: gtk/gtk_window.h
===================================================================
--- gtk/gtk_window.h    (wersja 6748)
+++ gtk/gtk_window.h    (kopia robocza)
@@ -34,7 +34,8 @@
        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
          * with a gtkfixed in that
Index: riscos/window.c
===================================================================
--- riscos/window.c     (wersja 6748)
+++ riscos/window.c     (kopia robocza)
@@ -2537,7 +2537,7 @@
                                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;
Index: desktop/history_core.c
===================================================================
--- desktop/history_core.c      (wersja 6748)
+++ desktop/history_core.c      (kopia robocza)
@@ -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 @@
        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 @@
        entry->forward = entry->forward_pref = entry->forward_last = 0;
        entry->children = 0;
        entry->bitmap = 0;
+       entry->sx = 0;
+       entry->sy = 0;
        if (history->current) {
                if (history->current->forward_last)
                        history->current->forward_last->next = entry;
@@ -755,3 +760,58 @@

        return 0;
 }
+
+/**
+ * Save in the history the scroll offsets of the current page
+ * \param  bw  browser window with the page
+ */
+
+void history_set_current_scroll(struct browser_window *bw)
+{
+       int sx, sy;
+       struct history *history = bw->history;
+       
+       if (!history || !history->current)
+               return;
+
+       gui_window_get_scroll(bw->window, &sx, &sy);
+       history->current->sx = sx;
+       history->current->sy = sy;
+}
+
+/**
+ * Load from the history the scroll offsets of the current page
+ * \param  bw  browser window 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 browser_window *bw, int *sx, int *sy)
+{
+       struct history *history = bw->history;
+       
+       if (!history || !history->current)
+               return false;
+
+       *sx = history->current->sx;
+       *sy = history->current->sy;
+       return true;
+}
+
+/**
+ * Clear the scroll offsets as if the page was never visited
+ * \param  bw  browser window with the page
+ */
+
+void history_clear_current_scroll(struct browser_window *bw)
+{
+       struct history *history = bw->history;
+       
+       if (!history || !history->current)
+               return;
+
+       history->current->sx = -1;
+       history->current->sy = -1;
+}
+
Index: desktop/history_core.h
===================================================================
--- desktop/history_core.h      (wersja 6748)
+++ desktop/history_core.h      (kopia robocza)
@@ -46,5 +46,7 @@
 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 browser_window *bw);
+bool history_get_current_scroll(struct browser_window *bw, int *sx, int *sy);
+void history_clear_current_scroll(struct browser_window *bw);
 #endif
Index: desktop/browser.c
===================================================================
--- desktop/browser.c   (wersja 6748)
+++ desktop/browser.c   (kopia robocza)
@@ -347,7 +347,8 @@
                if (same_url && !post_urlenc && !post_multipart &&
                                !strchr(url2, '?')) {
                        free(url2);
-                       browser_window_update(bw, false);
+                       history_clear_current_scroll(bw);                       
+                       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;
@@ -452,7 +453,7 @@
                        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);

@@ -491,7 +492,7 @@
        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 +542,7 @@
                }
                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:
@@ -762,11 +763,10 @@
  * \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;
@@ -778,17 +778,21 @@

        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, &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);
 }
@@ -1060,7 +1064,7 @@
        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;
Index: desktop/browser.h
===================================================================
--- desktop/browser.h   (wersja 6748)
+++ desktop/browser.h   (kopia robocza)
@@ -223,7 +223,7 @@
                const char *url, const char *referrer, bool history_add);
 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);
Index: amiga/gui.c
===================================================================
--- amiga/gui.c (wersja 6748)
+++ amiga/gui.c (kopia robocza)
@@ -1335,7 +1335,7 @@
                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))
 //             {

Reply via email to