commit e795e9355a607cbda3790e5c651c1a6f829e4326 from: Omar Polo date: Tue Jan 18 12:02:54 2022 UTC save and restore scroll position Save the offset to the first and current line of the buffers and restore it when the page is loaded. This restores almost the exact viewport: we save the offset of the *real* line in the document, but they get wrapped before being displayed, so the actual restored position may be slightly above from the original one (think of a long paragraph that gets wrapped over multiple visual lines.) In practice, this isn't a drawback but only an improvement over the current behaviour. In the future we could save also the offset *inside* the line, to restore the exact position, but that felt unnecessary for now. Persisting the postion on the session file ensures that even when re-opening telescope the scroll position is correct. There are some very active pages, such as antenna or other aggregator, where this feature doesn't really work well if you re-open the page after a while, since new links are available, but otherwise is a god sent! See also github issue #1 commit - 8f1633da06463e8909dbf68a870aa64350f32a12 commit + e795e9355a607cbda3790e5c651c1a6f829e4326 blob - e0300e5b784883ba10478180a1982bb46bf71d81 blob + df5c9e0f7f76af2a8f2d3d32e0c10c254f96ed4b --- fs.c +++ fs.c @@ -505,20 +505,15 @@ handle_session_tab(struct imsg *imsg, size_t datalen) tab.title[sizeof(tab.title)-1] != '\0') die(); - fprintf(session, "%s", tab.uri); + fprintf(session, "%s ", tab.uri); - if (tab.flags == 0) - fprintf(session, " - "); - else { - fprintf(session, " "); - if (tab.flags & TAB_CURRENT) - fprintf(session, "current,"); - if (tab.flags & TAB_KILLED) - fprintf(session, "killed,"); - fprintf(session, " "); - } + if (tab.flags & TAB_CURRENT) + fprintf(session, "current,"); + if (tab.flags & TAB_KILLED) + fprintf(session, "killed,"); - fprintf(session, "%s\n", tab.title); + fprintf(session, "top=%zu,cur=%zu %s\n", tab.top_line, + tab.current_line, tab.title); } static void @@ -729,8 +724,17 @@ parse_session_line(char *line) tab.flags |= TAB_CURRENT; else if (!strcmp(ap, "killed")) tab.flags |= TAB_KILLED; + else if (has_prefix(ap, "top=")) + tab.top_line = strtonum(ap, 0, UINT32_MAX, NULL); + else if (has_prefix(ap, "cur=")) + tab.current_line = strtonum(ap, 0, UINT32_MAX, NULL); } + if (tab.top_line > tab.current_line) { + tab.top_line = 0; + tab.current_line = 0; + } + fs_send_ui(IMSG_SESSION_TAB, 0, -1, &tab, sizeof(tab)); } blob - b976103b7d9155135e9b6299d409c4a177dff2cb blob + b070ca002778f80064455071d2758eb31344edb0 --- session.c +++ session.c @@ -175,6 +175,8 @@ sendtab(struct tab *tab, int killed) if (killed) st.flags |= TAB_KILLED; + get_scroll_position(tab, &st.top_line, &st.current_line); + strlcpy(st.uri, tab->hist_cur->h, sizeof(st.uri)); strlcpy(st.title, tab->buffer.page.title, sizeof(st.title)); ui_send_fs(IMSG_SESSION_TAB, 0, &st, sizeof(st)); blob - f3dad28535b6cdf3067255a39b283eefaea162a7 blob + 43a69b8fbf331f85f67f3c290166e110e243b5c4 --- session.h +++ session.h @@ -23,6 +23,8 @@ struct session_tab { uint32_t flags; char uri[GEMINI_URL_LEN]; char title[TITLE_MAX]; + size_t top_line; + size_t current_line; }; struct session_tab_hist { blob - 3e22d7d2696d2b5de7f3822206fbf29b0077adf0 blob + c88eb65e440c6ab6fda841daf34ea245907a3538 --- telescope.c +++ telescope.c @@ -525,6 +525,8 @@ handle_imsg_session(struct imsg *imsg, size_t datalen) memcpy(&st, imsg->data, sizeof(st)); if ((tab = new_tab(st.uri, NULL, NULL)) == NULL) die(); + tab->hist_cur->line_off = st.top_line; + tab->hist_cur->current_off = st.current_line; strlcpy(tab->buffer.page.title, st.title, sizeof(tab->buffer.page.title)); if (st.flags & TAB_CURRENT) @@ -966,9 +968,13 @@ load_url(struct tab *tab, const char *url, const char int nohist = mode & LU_MODE_NOHIST; if (!nohist && (!lazy || tab->hist_cur == NULL)) { - if (tab->hist_cur != NULL) + if (tab->hist_cur != NULL) { + get_scroll_position(tab, &tab->hist_cur->line_off, + &tab->hist_cur->current_off); + hist_clear_forward(&tab->hist, TAILQ_NEXT(tab->hist_cur, entries)); + } if ((tab->hist_cur = calloc(1, sizeof(*tab->hist_cur))) == NULL) { blob - 305e1cb91f5d0ba833d9be079c9c955dde647564 blob + ed80ed8b3fb66923e2f4bfc855ba9e133173764b --- telescope.h +++ telescope.h @@ -186,6 +186,8 @@ struct histhead { }; struct hist { char h[1025]; + size_t line_off; + size_t current_off; TAILQ_ENTRY(hist) entries; }; blob - 50c0198b381a2c23359d22b587c97137ef545377 blob + 6b4c27951225c27c7399763b9ecfdfa8bd2231c0 --- ui.c +++ ui.c @@ -50,6 +50,8 @@ static struct event stdioev, winchev; +static void set_scroll_position(struct tab *, size_t, size_t); + static void restore_curs_x(struct buffer *); static int readkey(void); @@ -122,7 +124,65 @@ update_x_offset(void) x_offset = 0; } +static void +set_scroll_position(struct tab *tab, size_t top, size_t cur) +{ + struct line *last; + struct vline *vl; + size_t i = 0; + int topfound = 0, curfound = 0; + + last = TAILQ_FIRST(&tab->buffer.page.head); + TAILQ_FOREACH(vl, &tab->buffer.head, vlines) { + if (last != vl->parent) { + last = vl->parent; + i++; + } + + if (!topfound && i == top) { + topfound = 1; + tab->buffer.top_line = vl; + } + + if (!curfound && i == cur) { + curfound = 1; + tab->buffer.current_line = vl; + return; + } + } + + if (!topfound) { + tab->buffer.top_line = TAILQ_FIRST(&tab->buffer.head); + tab->buffer.current_line = tab->buffer.top_line; + } +} + void +get_scroll_position(struct tab *tab, size_t *top, size_t *cur) +{ + struct line *l; + int topfound = 0; + + *top = 0; + *cur = 0; + + if (tab->buffer.top_line == NULL || + tab->buffer.current_line == NULL) + return; + + TAILQ_FOREACH(l, &tab->buffer.page.head, lines) { + if (tab->buffer.top_line->parent == l) + topfound = 1; + if (tab->buffer.current_line->parent == l) + return; + + if (!topfound) + (*top)++; + (*cur)++; + } +} + +void save_excursion(struct excursion *place, struct buffer *buffer) { place->curs_x = buffer->curs_x; @@ -1149,6 +1209,13 @@ ui_on_tab_loaded(struct tab *tab) stop_loading_anim(tab); message("Loaded %s", tab->hist_cur->h); + if (tab->hist_cur->current_off != 0) { + set_scroll_position(tab, tab->hist_cur->line_off, + tab->hist_cur->current_off); + redraw_tab(tab); + return; + } + if (show_tab_bar) redraw_tabline(); blob - afad9aee56199c4eaf9fd0699492dfed7f1a7c28 blob + b6e87ce4f0479d0e29d024e4e875df0e36469954 --- ui.h +++ ui.h @@ -135,6 +135,7 @@ extern struct buffer downloadwin; extern int download_lines; extern int download_cols; +void get_scroll_position(struct tab *, size_t *, size_t *); void save_excursion(struct excursion *, struct buffer *); void restore_excursion(struct excursion *, struct buffer *); void global_key_unbound(void);