diff options
-rw-r--r-- | desktop/browser.c | 155 | ||||
-rw-r--r-- | desktop/gui_factory.c | 9 | ||||
-rw-r--r-- | frontends/amiga/gui.c | 21 | ||||
-rw-r--r-- | frontends/atari/gui.c | 29 | ||||
-rw-r--r-- | frontends/beos/window.cpp | 25 | ||||
-rw-r--r-- | frontends/framebuffer/gui.c | 31 | ||||
-rw-r--r-- | frontends/gtk/window.c | 32 | ||||
-rw-r--r-- | frontends/monkey/browser.c | 35 | ||||
-rw-r--r-- | frontends/riscos/window.c | 179 | ||||
-rw-r--r-- | frontends/windows/drawable.c | 13 | ||||
-rw-r--r-- | frontends/windows/window.c | 88 | ||||
-rw-r--r-- | frontends/windows/window.h | 15 | ||||
-rw-r--r-- | include/netsurf/browser_window.h | 20 | ||||
-rw-r--r-- | include/netsurf/window.h | 31 |
14 files changed, 380 insertions, 303 deletions
diff --git a/desktop/browser.c b/desktop/browser.c index 73a86c2e3..4b6a5bbd0 100644 --- a/desktop/browser.c +++ b/desktop/browser.c @@ -586,36 +586,33 @@ static void browser_window_set_selection(struct browser_window *bw, top->selection.read_only = read_only; } -/* exported interface, documented in browser.h */ -void browser_window_scroll_visible(struct browser_window *bw, - const struct rect *rect) -{ - assert(bw != NULL); +/** + * Set the scroll position of a browser window. + * + * scrolls the viewport to ensure the specified rectangle of the + * content is shown. + * + * \param gw gui_window to scroll + * \param rect The rectangle to ensure is shown. + * \return NSERROR_OK on success or apropriate error code. + */ +static nserror +browser_window_set_scroll(struct browser_window *bw, + const struct rect *rect) +{ if (bw->window != NULL) { - /* Front end window */ - guit->window->scroll_visible(bw->window, - rect->x0, rect->y0, rect->x1, rect->y1); - } else { - /* Core managed browser window */ - if (bw->scroll_x != NULL) - scrollbar_set(bw->scroll_x, rect->x0, false); - if (bw->scroll_y != NULL) - scrollbar_set(bw->scroll_y, rect->y0, false); + return guit->window->set_scroll(bw->window, rect); } -} -/* exported interface, documented in browser.h */ -void browser_window_set_scroll(struct browser_window *bw, int x, int y) -{ - if (bw->window != NULL) { - guit->window->set_scroll(bw->window, x, y); - } else { - if (bw->scroll_x != NULL) - scrollbar_set(bw->scroll_x, x, false); - if (bw->scroll_y != NULL) - scrollbar_set(bw->scroll_y, y, false); + if (bw->scroll_x != NULL) { + scrollbar_set(bw->scroll_x, rect->x0, false); } + if (bw->scroll_y != NULL) { + scrollbar_set(bw->scroll_y, rect->y0, false); + } + + return NSERROR_OK; } /** @@ -1610,25 +1607,28 @@ browser_window_callback(hlcache_handle *c, break; case CONTENT_MSG_SCROLL: + { + struct rect rect = { + .x0 = event->data.scroll.x0, + .y0 = event->data.scroll.y0, + }; + /* Content wants to be scrolled */ - if (bw->current_content != c) + if (bw->current_content != c) { break; + } if (event->data.scroll.area) { - struct rect rect = { - .x0 = event->data.scroll.x0, - .y0 = event->data.scroll.y0, - .x1 = event->data.scroll.x1, - .y1 = event->data.scroll.y1 - }; - browser_window_scroll_visible(bw, &rect); + rect.x1 = event->data.scroll.x1; + rect.y1 = event->data.scroll.y1; } else { - browser_window_set_scroll(bw, - event->data.scroll.x0, - event->data.scroll.y0); + rect.x1 = event->data.scroll.x0; + rect.y1 = event->data.scroll.y0; } + browser_window_set_scroll(bw, &rect); break; + } case CONTENT_MSG_DRAGSAVE: { @@ -2324,13 +2324,48 @@ void browser_window_set_dimensions(struct browser_window *bw, } +/** + * scroll to a fragment if present + * + * \param bw browser window + * \return true if the scroll was sucessful + */ +static bool frag_scroll(struct browser_window *bw) +{ + struct rect rect; + + if (bw->frag_id == NULL) { + return false; + } + + if (!html_get_id_offset(bw->current_content, + bw->frag_id, + &rect.x0, + &rect.y0)) { + return false; + } + + rect.x1 = rect.x0; + rect.y1 = rect.y0; + if (browser_window_set_scroll(bw, &rect) == NSERROR_OK) { + return true; + } + return false; +} + /* Exported interface, documented in browser.h */ void browser_window_update(struct browser_window *bw, bool scroll_to_top) { - int x, y; + static const struct rect zrect = { + .x0 = 0, + .y0 = 0, + .x1 = 0, + .y1 = 0 + }; - if (bw->current_content == NULL) + if (bw->current_content == NULL) { return; + } switch (bw->browser_window_type) { @@ -2343,13 +2378,9 @@ void browser_window_update(struct browser_window *bw, bool scroll_to_top) /* if frag_id exists, then try to scroll to it */ /** @todo don't do this if the user has scrolled */ - if (bw->frag_id && - html_get_id_offset(bw->current_content, - bw->frag_id, &x, &y)) { - browser_window_set_scroll(bw, x, y); - } else { + if (!frag_scroll(bw)) { if (scroll_to_top) { - browser_window_set_scroll(bw, 0, 0); + browser_window_set_scroll(bw, &zrect); } } @@ -2364,15 +2395,13 @@ void browser_window_update(struct browser_window *bw, bool scroll_to_top) browser_window_update_extent(bw); - if (scroll_to_top) - browser_window_set_scroll(bw, 0, 0); + if (scroll_to_top) { + browser_window_set_scroll(bw, &zrect); + } /* if frag_id exists, then try to scroll to it */ /** @todo don't do this if the user has scrolled */ - if (bw->frag_id && html_get_id_offset(bw->current_content, - bw->frag_id, &x, &y)) { - browser_window_set_scroll(bw, x, y); - } + frag_scroll(bw); html_redraw_a_box(bw->parent->current_content, bw->box); break; @@ -2382,15 +2411,13 @@ void browser_window_update(struct browser_window *bw, bool scroll_to_top) struct rect rect; browser_window_update_extent(bw); - if (scroll_to_top) - browser_window_set_scroll(bw, 0, 0); + if (scroll_to_top) { + browser_window_set_scroll(bw, &zrect); + } /* if frag_id exists, then try to scroll to it */ /** @todo don't do this if the user has scrolled */ - if (bw->frag_id && html_get_id_offset(bw->current_content, - bw->frag_id, &x, &y)) { - browser_window_set_scroll(bw, x, y); - } + frag_scroll(bw); rect.x0 = scrollbar_get_offset(bw->scroll_x); rect.y0 = scrollbar_get_offset(bw->scroll_y); @@ -3078,17 +3105,19 @@ void browser_window_mouse_track(struct browser_window *bw, browser_window_resize_frame(bw, bw->x + x, bw->y + y); } else if (bw->drag.type == DRAGGING_PAGE_SCROLL) { /* mouse movement since drag started */ - int scrollx = bw->drag.start_x - x; - int scrolly = bw->drag.start_y - y; + struct rect rect; + + rect.x0 = bw->drag.start_x - x; + rect.y0 = bw->drag.start_y - y; /* new scroll offsets */ - scrollx += bw->drag.start_scroll_x; - scrolly += bw->drag.start_scroll_y; + rect.x0 += bw->drag.start_scroll_x; + rect.y0 += bw->drag.start_scroll_y; - bw->drag.start_scroll_x = scrollx; - bw->drag.start_scroll_y = scrolly; + bw->drag.start_scroll_x = rect.x1 = rect.x0; + bw->drag.start_scroll_y = rect.y1 = rect.y0; - browser_window_set_scroll(bw, scrollx, scrolly); + browser_window_set_scroll(bw, &rect); } else { assert(c != NULL); content_mouse_track(c, bw, mouse, x, y); diff --git a/desktop/gui_factory.c b/desktop/gui_factory.c index 559823d61..ca9eff1da 100644 --- a/desktop/gui_factory.c +++ b/desktop/gui_factory.c @@ -82,12 +82,6 @@ static void gui_default_window_set_icon(struct gui_window *g, { } -static void gui_default_window_scroll_visible(struct gui_window *g, - int x0, int y0, - int x1, int y1) -{ - guit->window->set_scroll(g, x0, y0); -} static void gui_default_window_new_content(struct gui_window *g) { @@ -212,9 +206,6 @@ static nserror verify_window_register(struct gui_window_table *gwt) if (gwt->save_link == NULL) { gwt->save_link = gui_default_window_save_link; } - if (gwt->scroll_visible == NULL) { - gwt->scroll_visible = gui_default_window_scroll_visible; - } if (gwt->new_content == NULL) { gwt->new_content = gui_default_window_new_content; } diff --git a/frontends/amiga/gui.c b/frontends/amiga/gui.c index bf3102ac7..18816c496 100644 --- a/frontends/amiga/gui.c +++ b/frontends/amiga/gui.c @@ -4970,13 +4970,28 @@ static bool gui_window_get_scroll(struct gui_window *g, int *restrict sx, int *r return true; } -static void gui_window_set_scroll(struct gui_window *g, int sx, int sy) +/** + * Set the scroll position of a amiga browser window. + * + * Scrolls the viewport to ensure the specified rectangle of the + * content is shown. The amiga implementation scrolls the contents so + * the specified point in the content is at the top of the viewport. + * + * \param gw gui_window to scroll + * \param rect The rectangle to ensure is shown. + * \return NSERROR_OK on success or apropriate error code. + */ +static nserror gui_window_set_scroll(struct gui_window *g, const struct rect *rect) { struct IBox *bbox; int width, height; + nserror res; - if(!g) return; - if(!g->bw || browser_window_has_content(g->bw) == false) return; + if(!g) { + return NSERROR_BAD_PARAMETER; + } + if(!g->bw || + browser_window_has_content(g->bw) == false) return; if(ami_gui_get_space_box((Object *)g->shared->objects[GID_BROWSER], &bbox) != NSERROR_OK) { amiga_warn_user("NoMemory", ""); diff --git a/frontends/atari/gui.c b/frontends/atari/gui.c index cdea953b2..4876d3106 100644 --- a/frontends/atari/gui.c +++ b/frontends/atari/gui.c @@ -424,17 +424,30 @@ bool gui_window_get_scroll(struct gui_window *w, int *sx, int *sy) return( true ); } -static void gui_window_set_scroll(struct gui_window *w, int sx, int sy) +/** + * Set the scroll position of a atari browser window. + * + * Scrolls the viewport to ensure the specified rectangle of the + * content is shown. The atari implementation scrolls the contents so + * the specified point in the content is at the top of the viewport. + * + * \param gw gui window to scroll + * \param rect The rectangle to ensure is shown. + * \return NSERROR_OK on success or apropriate error code. + */ +static nserror +gui_window_set_scroll(struct gui_window *gw, const struct rect *rect) { - if ( (w == NULL) - || (w->browser->bw == NULL) - || (!browser_window_has_content(w->browser->bw))) - return; + if ((gw == NULL) || + (gw->browser->bw == NULL) || + (!browser_window_has_content(gw->browser->bw))) { + return NSERROR_BAD_PARAMETER; + } - LOG("scroll (gui_window: %p) %d, %d\n", w, sx, sy); - window_scroll_by(w->root, sx, sy); - return; + LOG("scroll (gui_window: %p) %d, %d\n", gw, rect->x0, rect->y0); + window_scroll_by(gw->root, rect->x0, rect->y0); + return NSERROR_OK; } /** diff --git a/frontends/beos/window.cpp b/frontends/beos/window.cpp index f3d63da98..2121d9456 100644 --- a/frontends/beos/window.cpp +++ b/frontends/beos/window.cpp @@ -981,7 +981,7 @@ void nsbeos_redraw_caret(struct gui_window *g) /** * Invalidate an area of a beos browser window * - * \param gw The netsurf window being invalidated. + * \param g The netsurf window being invalidated. * \param rect area to redraw or NULL for entrire window area. * \return NSERROR_OK or appropriate error code. */ @@ -1034,7 +1034,19 @@ static bool gui_window_get_scroll(struct gui_window *g, int *sx, int *sy) return true; } -static void gui_window_set_scroll(struct gui_window *g, int sx, int sy) +/** + * Set the scroll position of a beos browser window. + * + * Scrolls the viewport to ensure the specified rectangle of the + * content is shown. The beos implementation scrolls the contents so + * the specified point in the content is at the top of the viewport. + * + * \param g gui window to scroll + * \param rect The rectangle to ensure is shown. + * \return NSERROR_OK on success or apropriate error code. + */ +static nserror +gui_window_set_scroll(struct gui_window *g, const struct rect *rect) { //CALLED(); if (g->view == NULL) @@ -1044,11 +1056,13 @@ static void gui_window_set_scroll(struct gui_window *g, int sx, int sy) #warning XXX: report to view frame ? if (g->view->ScrollBar(B_HORIZONTAL)) - g->view->ScrollBar(B_HORIZONTAL)->SetValue(sx); + g->view->ScrollBar(B_HORIZONTAL)->SetValue(rect->x0); if (g->view->ScrollBar(B_VERTICAL)) - g->view->ScrollBar(B_VERTICAL)->SetValue(sy); + g->view->ScrollBar(B_VERTICAL)->SetValue(rect->y0); g->view->UnlockLooper(); + + return NSERROR_OK; } @@ -1315,7 +1329,7 @@ struct gui_clipboard_table *beos_clipboard_table = &clipboard_table; /** * Find the current dimensions of a beos browser window content area. * - * \param gw The gui window to measure content area of. + * \param g The gui window to measure content area of. * \param width receives width of window * \param height receives height of window * \param scaled whether to return scaled values @@ -1361,7 +1375,6 @@ static struct gui_window_table window_table = { gui_window_stop_throbber, NULL, //drag_start NULL, //save_link - NULL, //scroll_visible NULL, //scroll_start gui_window_new_content, NULL, //create_form_select_menu diff --git a/frontends/framebuffer/gui.c b/frontends/framebuffer/gui.c index 0221a8ec3..062cb5659 100644 --- a/frontends/framebuffer/gui.c +++ b/frontends/framebuffer/gui.c @@ -1807,7 +1807,7 @@ gui_window_destroy(struct gui_window *gw) /** * Invalidates an area of a framebuffer browser window * - * \param gw The netsurf window being invalidated. + * \param g The netsurf window being invalidated. * \param rect area to redraw or NULL for the entire window area * \return NSERROR_OK on success or appropriate error code */ @@ -1844,16 +1844,29 @@ gui_window_get_scroll(struct gui_window *g, int *sx, int *sy) return true; } -static void -gui_window_set_scroll(struct gui_window *gw, int sx, int sy) +/** + * Set the scroll position of a framebuffer browser window. + * + * Scrolls the viewport to ensure the specified rectangle of the + * content is shown. The framebuffer implementation scrolls the contents so + * the specified point in the content is at the top of the viewport. + * + * \param gw gui_window to scroll + * \param rect The rectangle to ensure is shown. + * \return NSERROR_OK on success or apropriate error code. + */ +static nserror +gui_window_set_scroll(struct gui_window *gw, const struct rect *rect) { struct browser_widget_s *bwidget = fbtk_get_userpw(gw->browser); float scale = browser_window_get_scale(gw->bw); assert(bwidget); - widget_scroll_x(gw, sx * scale, true); - widget_scroll_y(gw, sy * scale, true); + widget_scroll_x(gw, rect->x0 * scale, true); + widget_scroll_y(gw, rect->y0 * scale, true); + + return NSERROR_OK; } @@ -1867,16 +1880,16 @@ gui_window_set_scroll(struct gui_window *gw, int sx, int sy) * \return NSERROR_OK on sucess and width and height updated. */ static nserror -gui_window_get_dimensions(struct gui_window *g, +gui_window_get_dimensions(struct gui_window *gw, int *width, int *height, bool scaled) { - *width = fbtk_get_width(g->browser); - *height = fbtk_get_height(g->browser); + *width = fbtk_get_width(gw->browser); + *height = fbtk_get_height(gw->browser); if (scaled) { - float scale = browser_window_get_scale(g->bw); + float scale = browser_window_get_scale(gw->bw); *width /= scale; *height /= scale; } diff --git a/frontends/gtk/window.c b/frontends/gtk/window.c index ecd6d0a35..78a6f6274 100644 --- a/frontends/gtk/window.c +++ b/frontends/gtk/window.c @@ -1041,11 +1041,25 @@ static void gui_window_set_status(struct gui_window *g, const char *text) } -static void gui_window_set_scroll(struct gui_window *g, int sx, int sy) +/** + * Set the scroll position of a gtk browser window. + * + * Scrolls the viewport to ensure the specified rectangle of the + * content is shown. The GTK implementation scrolls the contents so + * the specified point in the content is at the top of the viewport. + * + * \param gw gui window to scroll + * \param rect The rectangle to ensure is shown. + * \return NSERROR_OK on success or apropriate error code. + */ +static nserror +gui_window_set_scroll(struct gui_window *g, const struct rect *rect) { GtkAdjustment *vadj = nsgtk_layout_get_vadjustment(g->layout); GtkAdjustment *hadj = nsgtk_layout_get_hadjustment(g->layout); - gdouble vlower, vpage, vupper, hlower, hpage, hupper, x = (double)sx, y = (double)sy; + gdouble vlower, vpage, vupper, hlower, hpage, hupper; + gdouble x = (gdouble)rect->x0; + gdouble y = (gdouble)rect->y0; assert(vadj); assert(hadj); @@ -1053,17 +1067,23 @@ static void gui_window_set_scroll(struct gui_window *g, int sx, int sy) g_object_get(vadj, "page-size", &vpage, "lower", &vlower, "upper", &vupper, NULL); g_object_get(hadj, "page-size", &hpage, "lower", &hlower, "upper", &hupper, NULL); - if (x < hlower) + if (x < hlower) { x = hlower; - if (x > (hupper - hpage)) + } + if (x > (hupper - hpage)) { x = hupper - hpage; - if (y < vlower) + } + if (y < vlower) { y = vlower; - if (y > (vupper - vpage)) + } + if (y > (vupper - vpage)) { y = vupper - vpage; + } gtk_adjustment_set_value(vadj, y); gtk_adjustment_set_value(hadj, x); + + return NSERROR_OK; } static void gui_window_update_extent(struct gui_window *g) diff --git a/frontends/monkey/browser.c b/frontends/monkey/browser.c index 8d5154e0b..93360aa29 100644 --- a/frontends/monkey/browser.c +++ b/frontends/monkey/browser.c @@ -112,7 +112,7 @@ gui_window_set_title(struct gui_window *g, const char *title) /** * Find the current dimensions of a monkey browser window content area. * - * \param gw The gui window to measure content area of. + * \param g The gui window to measure content area of. * \param width receives width of window * \param height receives height of window * \param scaled whether to return scaled values @@ -154,14 +154,29 @@ gui_window_stop_throbber(struct gui_window *g) fprintf(stdout, "WINDOW STOP_THROBBER WIN %u\n", g->win_num); } -static void -gui_window_set_scroll(struct gui_window *g, int sx, int sy) + +/** + * Set the scroll position of a monkey browser window. + * + * Scrolls the viewport to ensure the specified rectangle of the + * content is shown. + * + * \param gw gui window to scroll + * \param rect The rectangle to ensure is shown. + * \return NSERROR_OK on success or apropriate error code. + */ +static nserror +gui_window_set_scroll(struct gui_window *gw, const struct rect *rect) { - g->scrollx = sx; - g->scrolly = sy; - fprintf(stdout, "WINDOW SET_SCROLL WIN %u X %d Y %d\n", g->win_num, sx, sy); + gw->scrollx = rect->x0; + gw->scrolly = rect->y0; + + fprintf(stdout, "WINDOW SET_SCROLL WIN %u X0 %d Y0 %d X1 %d Y1 %d\n", + gw->win_num, rect->x0, rect->y0, rect->x1, rect->y1); + return NSERROR_OK; } + /** * Invalidates an area of a monkey browser window * @@ -298,13 +313,6 @@ gui_window_scroll_start(struct gui_window *g) return true; } -static void -gui_window_scroll_visible(struct gui_window *g, int x0, int y0, - int x1, int y1) -{ - fprintf(stdout, "WINDOW SCROLL_VISIBLE WIN %u X0 %d Y0 %d X1 %d Y1 %d\n", - g->win_num, x0, y0, x1, y1); -} static void gui_window_place_caret(struct gui_window *g, int x, int y, int height, @@ -527,7 +535,6 @@ static struct gui_window_table window_table = { .remove_caret = gui_window_remove_caret, .drag_start = gui_window_drag_start, .save_link = gui_window_save_link, - .scroll_visible = gui_window_scroll_visible, .scroll_start = gui_window_scroll_start, .new_content = gui_window_new_content, .start_throbber = gui_window_start_throbber, diff --git a/frontends/riscos/window.c b/frontends/riscos/window.c index 1d5c0938a..3496d4b48 100644 --- a/frontends/riscos/window.c +++ b/frontends/riscos/window.c @@ -806,124 +806,118 @@ static bool gui_window_get_scroll(struct gui_window *g, int *sx, int *sy) /** - * Set the scroll position of a browser window. + * Set the scroll position of a riscos browser window. * - * \param g gui_window to scroll - * \param sx point to place at top-left of window - * \param sy point to place at top-left of window - */ - -static void gui_window_set_scroll(struct gui_window *g, int sx, int sy) -{ - wimp_window_state state; - os_error *error; - - assert(g); - - state.w = g->window; - error = xwimp_get_window_state(&state); - if (error) { - LOG("xwimp_get_window_state: 0x%x: %s", error->errnum, error->errmess); - ro_warn_user("WimpError", error->errmess); - return; - } - - state.xscroll = sx * 2 * g->scale; - state.yscroll = -sy * 2 * g->scale; - if (g->toolbar) - state.yscroll += ro_toolbar_full_height(g->toolbar); - ro_gui_window_open(PTR_WIMP_OPEN(&state)); -} - - -/** - * Scrolls the specified area of a browser window into view. + * Scrolls the viewport to ensure the specified rectangle of the + * content is shown. * - * \param g gui_window to scroll - * \param x0 left point to ensure visible - * \param y0 bottom point to ensure visible - * \param x1 right point to ensure visible - * \param y1 top point to ensure visible + * \param g gui window to scroll + * \param rect The rectangle to ensure is shown. + * \return NSERROR_OK on success or apropriate error code. */ -static void gui_window_scroll_visible(struct gui_window *g, int x0, int y0, int x1, int y1) +static nserror +gui_window_set_scroll(struct gui_window *g, const struct rect *rect) { wimp_window_state state; os_error *error; - int cx0, cy0, width, height; - int padding_available; int toolbar_height = 0; - int correction; assert(g); state.w = g->window; error = xwimp_get_window_state(&state); if (error) { - LOG("xwimp_get_window_state: 0x%x: %s", error->errnum, error->errmess); + LOG("xwimp_get_window_state: 0x%x: %s", + error->errnum, error->errmess); ro_warn_user("WimpError", error->errmess); - return; + return NSERROR_BAD_PARAMETER; } - if (g->toolbar) + if (g->toolbar) { toolbar_height = ro_toolbar_full_height(g->toolbar); - - x0 = x0 * 2 * g->scale; - y0 = y0 * 2 * g->scale; - x1 = x1 * 2 * g->scale; - y1 = y1 * 2 * g->scale; - - cx0 = state.xscroll; - cy0 = -state.yscroll + toolbar_height; - width = state.visible.x1 - state.visible.x0; - height = state.visible.y1 - state.visible.y0 - toolbar_height; - - /* make sure we're visible */ - correction = (x1 - cx0 - width); - if (correction > 0) - cx0 += correction; - correction = (y1 - cy0 - height); - if (correction > 0) - cy0 += correction; - if (x0 < cx0) - cx0 = x0; - if (y0 < cy0) - cy0 = y0; - - /* try to give a SCROLL_VISIBLE_PADDING border of space around us */ - padding_available = (width - x1 + x0) / 2; - if (padding_available > 0) { - if (padding_available > SCROLL_VISIBLE_PADDING) - padding_available = SCROLL_VISIBLE_PADDING; - correction = (cx0 + width - x1); - if (correction < padding_available) - cx0 += padding_available; - correction = (x0 - cx0); - if (correction < padding_available) - cx0 -= padding_available; - } - padding_available = (height - y1 + y0) / 2; - if (padding_available > 0) { - if (padding_available > SCROLL_VISIBLE_PADDING) - padding_available = SCROLL_VISIBLE_PADDING; - correction = (cy0 + height - y1); - if (correction < padding_available) - cy0 += padding_available; - correction = (y0 - cy0); - if (correction < padding_available) - cy0 -= padding_available; } - state.xscroll = cx0; - state.yscroll = -cy0 + toolbar_height; + if ((rect->x0 == rect->x1) && (rect->y0 == rect->y1)) { + /* scroll to top */ + state.xscroll = rect->x0 * 2 * g->scale; + state.yscroll = (-rect->y0 * 2 * g->scale) + toolbar_height; + } else { + /* scroll area into view with padding */ + int x0, y0, x1, y1; + int cx0, cy0, width, height; + int padding_available; + int correction; + + x0 = rect->x0 * 2 * g->scale; + y0 = rect->y0 * 2 * g->scale; + x1 = rect->x1 * 2 * g->scale; + y1 = rect->y1 * 2 * g->scale; + + cx0 = state.xscroll; + cy0 = -state.yscroll + toolbar_height; + width = state.visible.x1 - state.visible.x0; + height = state.visible.y1 - state.visible.y0 - toolbar_height; + + /* make sure we're visible */ + correction = (x1 - cx0 - width); + if (correction > 0) { + cx0 += correction; + } + correction = (y1 - cy0 - height); + if (correction > 0) { + cy0 += correction; + } + if (x0 < cx0) { + cx0 = x0; + } + if (y0 < cy0) { + cy0 = y0; + } + + /* try to give a SCROLL_VISIBLE_PADDING border of space around us */ + padding_available = (width - x1 + x0) / 2; + if (padding_available > 0) { + if (padding_available > SCROLL_VISIBLE_PADDING) { + padding_available = SCROLL_VISIBLE_PADDING; + } + correction = (cx0 + width - x1); + if (correction < padding_available) { + cx0 += padding_available; + } + correction = (x0 - cx0); + if (correction < padding_available) { + cx0 -= padding_available; + } + } + padding_available = (height - y1 + y0) / 2; + if (padding_available > 0) { + if (padding_available > SCROLL_VISIBLE_PADDING) { + padding_available = SCROLL_VISIBLE_PADDING; + } + correction = (cy0 + height - y1); + if (correction < padding_available) { + cy0 += padding_available; + } + correction = (y0 - cy0); + if (correction < padding_available) { + cy0 -= padding_available; + } + } + + state.xscroll = cx0; + state.yscroll = -cy0 + toolbar_height; + } ro_gui_window_open(PTR_WIMP_OPEN(&state)); + + return NSERROR_OK; } /** * Find the current dimensions of a browser window's content area. * - * \param g gui_window to measure - * \param width receives width of window + * \param gw gui window to measure + * \param width receives width of window * \param height receives height of window * \param scaled whether to return scaled values */ @@ -4988,7 +4982,6 @@ static struct gui_window_table window_table = { .remove_caret = gui_window_remove_caret, .save_link = gui_window_save_link, .drag_start = gui_window_drag_start, - .scroll_visible = gui_window_scroll_visible, .scroll_start = gui_window_scroll_start, .new_content = gui_window_new_content, .start_throbber = gui_window_start_throbber, diff --git a/frontends/windows/drawable.c b/frontends/windows/drawable.c index 0bd1bae87..4540b1293 100644 --- a/frontends/windows/drawable.c +++ b/frontends/windows/drawable.c @@ -137,8 +137,10 @@ nsws_drawable_vscroll(struct gui_window *gw, HWND hwnd, WPARAM wparam) SetScrollInfo(hwnd, SB_VERT, &si, TRUE); GetScrollInfo(hwnd, SB_VERT, &si); if (si.nPos != mem) { - win32_window_set_scroll(gw, gw->scrollx, gw->scrolly + - gw->requestscrolly + si.nPos - mem); + struct rect rect; + rect.x0 = rect.x1 = gw->scrollx; + rect.y0 = rect.y1 = gw->scrolly + gw->requestscrolly + si.nPos - mem; + win32_window_set_scroll(gw, &rect); } return 0; @@ -201,9 +203,10 @@ nsws_drawable_hscroll(struct gui_window *gw, HWND hwnd, WPARAM wparam) SetScrollInfo(hwnd, SB_HORZ, &si, TRUE); GetScrollInfo(hwnd, SB_HORZ, &si); if (si.nPos != mem) { - win32_window_set_scroll(gw, - gw->scrollx + gw->requestscrollx + si.nPos - mem, - gw->scrolly); + struct rect rect; + rect.x0 = rect.x1 = gw->scrollx + gw->requestscrollx + si.nPos - mem; + rect.y0 = rect.y1 = gw->scrolly; + win32_window_set_scroll(gw, &rect); } return 0; diff --git a/frontends/windows/window.c b/frontends/windows/window.c index 829067b32..6ba61c546 100644 --- a/frontends/windows/window.c +++ b/frontends/windows/window.c @@ -923,7 +923,7 @@ win32_window_invalidate_area(struct gui_window *gw, const struct rect *rect) */ static void nsws_set_scale(struct gui_window *gw, float scale) { - int x, y; + struct rect rect; assert(gw != NULL); @@ -931,8 +931,8 @@ static void nsws_set_scale(struct gui_window *gw, float scale) return; } - x = gw->scrollx; - y = gw->scrolly; + rect.x0 = rect.x1 = gw->scrollx; + rect.y0 = rect.y1 = gw->scrolly; gw->scale = scale; @@ -941,7 +941,7 @@ static void nsws_set_scale(struct gui_window *gw, float scale) } win32_window_invalidate_area(gw, NULL); - win32_window_set_scroll(gw, x, y); + win32_window_set_scroll(gw, &rect); } @@ -1338,7 +1338,7 @@ nsws_window_resize(struct gui_window *gw, WPARAM wparam, LPARAM lparam) { - int x, y; + struct rect rect; RECT rstatus, rtool; if ((gw->toolbar == NULL) || @@ -1351,7 +1351,7 @@ nsws_window_resize(struct gui_window *gw, GetClientRect(gw->toolbar, &rtool); GetWindowRect(gw->statusbar, &rstatus); - win32_window_get_scroll(gw, &x, &y); + win32_window_get_scroll(gw, &rect.x0, &rect.y0); gw->width = LOWORD(lparam); gw->height = HIWORD(lparam) - (rtool.bottom - rtool.top) - (rstatus.bottom - rstatus.top); @@ -1365,7 +1365,7 @@ nsws_window_resize(struct gui_window *gw, } nsws_window_update_forward_back(gw); - win32_window_set_scroll(gw, x, y); + win32_window_set_scroll(gw, &rect); if (gw->toolbar != NULL) { SendMessage(gw->toolbar, TB_SETSTATE, @@ -1830,40 +1830,39 @@ bool nsws_window_go(HWND hwnd, const char *urltxt) /* exported interface documented in windows/window.h */ -void win32_window_set_scroll(struct gui_window *w, int sx, int sy) +nserror win32_window_set_scroll(struct gui_window *gw, const struct rect *rect) { SCROLLINFO si; - nserror err; + nserror res; int height; int width; POINT p; - if ((w == NULL) || (w->bw == NULL)) - return; - - err = browser_window_get_extents(w->bw, true, &width, &height); - if (err != NSERROR_OK) { - return; + if ((gw == NULL) || (gw->bw == NULL)) { + return NSERROR_BAD_PARAMETER; } - /*LOG("scroll sx,sy:%d,%d x,y:%d,%d w.h:%d,%d",sx,sy,w->scrollx,w->scrolly, width,height);*/ + res = browser_window_get_extents(gw->bw, true, &width, &height); + if (res != NSERROR_OK) { + return res; + } /* The resulting gui window scroll must remain within the * windows bounding box. */ - if (sx < 0) { - w->requestscrollx = -w->scrollx; - } else if (sx > (width - w->width)) { - w->requestscrollx = (width - w->width) - w->scrollx; + if (rect->x0 < 0) { + gw->requestscrollx = -gw->scrollx; + } else if (rect->x0 > (width - gw->width)) { + gw->requestscrollx = (width - gw->width) - gw->scrollx; } else { - w->requestscrollx = sx - w->scrollx; + gw->requestscrollx = rect->x0 - gw->scrollx; } - if (sy < 0) { - w->requestscrolly = -w->scrolly; - } else if (sy > (height - w->height)) { - w->requestscrolly = (height - w->height) - w->scrolly; + if (rect->y0 < 0) { + gw->requestscrolly = -gw->scrolly; + } else if (rect->y0 > (height - gw->height)) { + gw->requestscrolly = (height - gw->height) - gw->scrolly; } else { - w->requestscrolly = sy - w->scrolly; + gw->requestscrolly = rect->y0 - gw->scrolly; } /*LOG("requestscroll x,y:%d,%d", w->requestscrollx, w->requestscrolly);*/ @@ -1873,10 +1872,10 @@ void win32_window_set_scroll(struct gui_window *w, int sx, int sy) si.fMask = SIF_ALL; si.nMin = 0; si.nMax = height - 1; - si.nPage = w->height; - si.nPos = max(w->scrolly + w->requestscrolly, 0); - si.nPos = min(si.nPos, height - w->height); - SetScrollInfo(w->drawingarea, SB_VERT, &si, TRUE); + si.nPage = gw->height; + si.nPos = max(gw->scrolly + gw->requestscrolly, 0); + si.nPos = min(si.nPos, height - gw->height); + SetScrollInfo(gw->drawingarea, SB_VERT, &si, TRUE); /*LOG("SetScrollInfo VERT min:%d max:%d page:%d pos:%d", si.nMin, si.nMax, si.nPage, si.nPos);*/ /* set the horizontal scroll offset */ @@ -1884,30 +1883,31 @@ void win32_window_set_scroll(struct gui_window *w, int sx, int sy) si.fMask = SIF_ALL; si.nMin = 0; si.nMax = width -1; - si.nPage = w->width; - si.nPos = max(w->scrollx + w->requestscrollx, 0); - si.nPos = min(si.nPos, width - w->width); - SetScrollInfo(w->drawingarea, SB_HORZ, &si, TRUE); + si.nPage = gw->width; + si.nPos = max(gw->scrollx + gw->requestscrollx, 0); + si.nPos = min(si.nPos, width - gw->width); + SetScrollInfo(gw->drawingarea, SB_HORZ, &si, TRUE); /*LOG("SetScrollInfo HORZ min:%d max:%d page:%d pos:%d", si.nMin, si.nMax, si.nPage, si.nPos);*/ /* Set caret position */ GetCaretPos(&p); - HideCaret(w->drawingarea); - SetCaretPos(p.x - w->requestscrollx, p.y - w->requestscrolly); - ShowCaret(w->drawingarea); + HideCaret(gw->drawingarea); + SetCaretPos(p.x - gw->requestscrollx, p.y - gw->requestscrolly); + ShowCaret(gw->drawingarea); RECT r, redraw; r.top = 0; - r.bottom = w->height + 1; + r.bottom = gw->height + 1; r.left = 0; - r.right = w->width + 1; - ScrollWindowEx(w->drawingarea, - w->requestscrollx, - w->requestscrolly, &r, NULL, NULL, &redraw, SW_INVALIDATE); + r.right = gw->width + 1; + ScrollWindowEx(gw->drawingarea, - gw->requestscrollx, - gw->requestscrolly, &r, NULL, NULL, &redraw, SW_INVALIDATE); /*LOG("ScrollWindowEx %d, %d", - w->requestscrollx, - w->requestscrolly);*/ - w->scrolly += w->requestscrolly; - w->scrollx += w->requestscrollx; - w->requestscrollx = 0; - w->requestscrolly = 0; + gw->scrolly += gw->requestscrolly; + gw->scrollx += gw->requestscrollx; + gw->requestscrollx = 0; + gw->requestscrolly = 0; + return NSERROR_OK; } diff --git a/frontends/windows/window.h b/frontends/windows/window.h index d927c2899..3cdb9aefe 100644 --- a/frontends/windows/window.h +++ b/frontends/windows/window.h @@ -73,6 +73,7 @@ struct gui_window { struct gui_window *next, *prev; /**< global linked list */ }; +struct rect; /** * Obtain gui window structure from window handle. @@ -91,13 +92,17 @@ struct gui_window *nsws_get_gui_window(HWND hwnd); bool nsws_window_go(HWND hwnd, const char *urltxt); /** - * scroll the window + * Set the scroll position of a win32 browser window. * - * \param w The win32 gui window to scroll. - * \param sx the new 'absolute' horizontal scroll location - * \param sy the new 'absolute' vertical scroll location + * Scrolls the viewport to ensure the specified rectangle of the + * content is shown. The win32 implementation scrolls the contents so + * the specified point in the content is at the top of the viewport. + * + * \param gw The win32 gui window to scroll. + * \param rect The rectangle to ensure is shown. + * \return NSERROR_OK on success or apropriate error code. */ -void win32_window_set_scroll(struct gui_window *w, int sx, int sy); +nserror win32_window_set_scroll(struct gui_window *gw, const struct rect *rect); /** * Create the main browser window class. diff --git a/include/netsurf/browser_window.h b/include/netsurf/browser_window.h index c56cf5571..567e314c5 100644 --- a/include/netsurf/browser_window.h +++ b/include/netsurf/browser_window.h @@ -572,26 +572,6 @@ void browser_window_get_position(struct browser_window *bw, bool root, */ void browser_window_set_position(struct browser_window *bw, int x, int y); -/** - * Scroll the browser window to display the passed area - * - * \param bw browser window to scroll - * \param rect area to display - */ -void browser_window_scroll_visible(struct browser_window *bw, - const struct rect *rect); - -/** - * Set scroll offsets for a browser window. - * - * \param bw The browser window - * \param x The x scroll offset to set - * \param y The y scroll offset to set - * - * \todo Do we really need this and browser_window_scroll_visible? - * Ditto for gui_window_* variants. - */ -void browser_window_set_scroll(struct browser_window *bw, int x, int y); /** * Set drag type for a browser window, and inform front end diff --git a/include/netsurf/window.h b/include/netsurf/window.h index b9a68639c..81fc0676b 100644 --- a/include/netsurf/window.h +++ b/include/netsurf/window.h @@ -136,11 +136,20 @@ struct gui_window_table { /** * Set the scroll position of a browser window. * - * \param g gui_window to scroll - * \param sx point to place at top-left of window - * \param sy point to place at top-left of window + * scrolls the viewport to ensure the specified rectangle of + * the content is shown. + * If the rectangle is of zero size i.e. x0 == x1 and y0 == y1 + * the contents will be scrolled so the specified point in the + * content is at the top of the viewport. + * If the size of the rectangle is non zero the frontend may + * add padding or center the defined area or it may simply + * align as in the zero size rectangle + * + * \param gw gui_window to scroll + * \param rect The rectangle to ensure is shown. + * \return NSERROR_OK on success or apropriate error code. */ - void (*set_scroll)(struct gui_window *g, int sx, int sy); + nserror (*set_scroll)(struct gui_window *gw, const struct rect *rect); /** @@ -267,20 +276,6 @@ struct gui_window_table { */ nserror (*save_link)(struct gui_window *g, struct nsurl *url, const char *title); - /** - * Scrolls the specified area of a browser window into view. - * - * @todo investigate if this can be merged with set_scroll - * which is what the default implementation used by most - * toolkits uses. - * - * \param g gui_window to scroll - * \param x0 left point to ensure visible - * \param y0 bottom point to ensure visible - * \param x1 right point to ensure visible - * \param y1 top point to ensure visible - */ - void (*scroll_visible)(struct gui_window *g, int x0, int y0, int x1, int y1); /** * Starts drag scrolling of a browser window |