Corewindow: Sanitise scrolling API.

Now the core has a helper so that all the front ends don't need
to implement the scroll to show area API.

Now they simply have get and set scroll APIs.
This commit is contained in:
Michael Drake 2019-08-03 15:52:42 +01:00
parent 8cff4b79d6
commit 3938d5340b
10 changed files with 202 additions and 108 deletions

View File

@ -13,7 +13,7 @@ desktop/version.c: testament $(OBJROOT)/testament.h
# S_BROWSER are sources related to full browsers but are common
# between RISC OS, GTK, BeOS and AmigaOS builds
S_BROWSER := browser.c browser_window.c browser_history.c \
download.c frames.c netsurf.c \
download.c frames.c netsurf.c cw_helper.c \
save_complete.c save_text.c selection.c textinput.c gui_factory.c \
save_pdf.c font_haru.c

View File

@ -33,6 +33,7 @@
#include "netsurf/plotters.h"
#include "netsurf/keypress.h"
#include "desktop/cw_helper.h"
#include "desktop/gui_internal.h"
#include "desktop/system_colour.h"
#include "desktop/browser_private.h"
@ -294,9 +295,9 @@ local_history_scroll_to_cursor(struct local_history_session *session)
cursor.y1 = cursor.y0 + LOCAL_HISTORY_HEIGHT +
LOCAL_HISTORY_BOTTOM_MARGIN / 2;
session->cw_t->scroll_visible(session->core_window_handle, &cursor);
return NSERROR_OK;
return cw_helper_scroll_visible(session->cw_t,
session->core_window_handle,
&cursor);
}
/* exported interface documented in desktop/local_history.h */

View File

@ -39,11 +39,12 @@
#include "content/hlcache.h"
#include "css/utils.h"
#include "desktop/system_colour.h"
#include "desktop/knockout.h"
#include "desktop/textarea.h"
#include "desktop/treeview.h"
#include "desktop/cw_helper.h"
#include "desktop/gui_internal.h"
#include "desktop/system_colour.h"
/**
* The maximum horizontal size a treeview can possibly be.
@ -404,9 +405,7 @@ static inline void treeview__cw_scroll_top(
.y1 = tree_g.line_height,
};
if (tree->cw_t != NULL) {
tree->cw_t->scroll_visible(tree->cw_h, &r);
}
cw_helper_scroll_visible(tree->cw_t, tree->cw_h, &r);
}
@ -584,9 +583,7 @@ static inline void treeview__cw_scroll_to_node(
r.y1 += r.y0; /* Apply the Y offset to the second Y coordinate */
if (tree->cw_t != NULL) {
tree->cw_t->scroll_visible(tree->cw_h, &r);
}
cw_helper_scroll_visible(tree->cw_t, tree->cw_h, &r);
}

View File

@ -825,16 +825,17 @@ ami_cw_invalidate_area(struct core_window *cw, const struct rect *r)
}
static void
static nserror
ami_cw_get_window_dimensions(struct core_window *cw, int *width, int *height)
{
struct ami_corewindow *ami_cw = (struct ami_corewindow *)cw;
ami_cw_window_size(ami_cw, width, height);
return NSERROR_OK;
}
static void
static nserror
ami_cw_update_size(struct core_window *cw, int width, int height)
{
struct ami_corewindow *ami_cw = (struct ami_corewindow *)cw;
@ -861,11 +862,12 @@ ami_cw_update_size(struct core_window *cw, int width, int height)
SCROLLER_Visible, win_h,
TAG_DONE);
}
return NSERROR_OK;
}
static void
ami_cw_scroll_visible(struct core_window *cw, const struct rect *r)
static nserror
ami_cw_get_scroll(struct core_window *cw, int *x, int *y)
{
struct ami_corewindow *ami_cw = (struct ami_corewindow *)cw;
@ -879,43 +881,49 @@ ami_cw_scroll_visible(struct core_window *cw, const struct rect *r)
ami_cw_scroller_top(ami_cw, &win_x0, &win_y0);
win_x1 = win_x0 + win_w;
win_y1 = win_y0 + win_h;
*x = win_x0;
*y = win_y0;
return NSERROR_OK
}
if(r->y1 > win_y1) scrollsety = r->y1 - win_h;
if(r->y0 < (LONG)win_y0) scrollsety = r->y0;
if(r->x1 > win_x1) scrollsetx = r->x1 - win_w;
if(r->x0 < (LONG)win_x0) scrollsetx = r->x0;
static nserror
ami_cw_set_scroll(struct core_window *cw, int x, int y)
{
struct ami_corewindow *ami_cw = (struct ami_corewindow *)cw;
if(ami_cw->scroll_y_visible == true) {
RefreshSetGadgetAttrs((APTR)ami_cw->objects[GID_CW_VSCROLL], ami_cw->win, NULL,
SCROLLER_Top, scrollsety,
SCROLLER_Top, y,
TAG_DONE);
}
if(ami_cw->scroll_x_visible == true) {
RefreshSetGadgetAttrs((APTR)ami_cw->objects[GID_CW_HSCROLL], ami_cw->win, NULL,
SCROLLER_Top, scrollsetx,
SCROLLER_Top, x,
TAG_DONE);
}
/* probably need to redraw here */
ami_cw_redraw(ami_cw, NULL);
return NSERROR_OK;
}
static void
static nserror
ami_cw_drag_status(struct core_window *cw, core_window_drag_status ds)
{
struct ami_corewindow *ami_cw = (struct ami_corewindow *)cw;
ami_cw->drag_status = ds;
return NSERROR_OK;
}
struct core_window_callback_table ami_cw_cb_table = {
.invalidate = ami_cw_invalidate_area,
.update_size = ami_cw_update_size,
.scroll_visible = ami_cw_scroll_visible,
.set_scroll = ami_cw_set_scroll,
.get_scroll = ami_cw_get_scroll,
.get_window_dimensions = ami_cw_get_window_dimensions,
.drag_status = ami_cw_drag_status
};

View File

@ -426,7 +426,7 @@ atari_treeview_invalidate_area(struct core_window *cw,
* \param width the width in px, or negative if don't care
* \param height the height in px, or negative if don't care
*/
static void
static nserror
atari_treeview_update_size(struct core_window *cw, int width, int height)
{
GRECT area;
@ -436,7 +436,7 @@ atari_treeview_update_size(struct core_window *cw, int width, int height)
if (tv != NULL) {
if (tv->disposing)
return;
return NSERROR_INVALID;
/* Get acces to the gemtk window slider settings: */
slid = gemtk_wm_get_scroll_info(tv->window);
@ -465,6 +465,8 @@ atari_treeview_update_size(struct core_window *cw, int width, int height)
*/
gemtk_wm_update_slider(tv->window, GEMTK_WM_VH_SLIDER);
}
return NSERROR_OK;
}
@ -474,11 +476,18 @@ atari_treeview_update_size(struct core_window *cw, int width, int height)
* \param cw the core window object
* \param r rectangle to make visible
*/
static void
atari_treeview_scroll_visible(struct core_window *cw, const struct rect *r)
static nserror
atari_treeview_set_scroll(struct core_window *cw, int x, int y)
{
/* atari frontend doesn't support dragging outside the treeview */
/* so there is no need to implement this? */
/* TODO */
return NSERROR_OK;
}
static nserror
atari_treeview_get_scroll(struct core_window *cw, int *x, int *y)
{
/* TODO */
return NSERROR_NOT_IMPLEMENTED;
}
@ -489,7 +498,7 @@ atari_treeview_scroll_visible(struct core_window *cw, const struct rect *r)
* \param width to be set to viewport width in px, if non NULL
* \param height to be set to viewport height in px, if non NULL
*/
static void
static nserror
atari_treeview_get_window_dimensions(struct core_window *cw,
int *width,
int *height)
@ -501,6 +510,8 @@ atari_treeview_get_window_dimensions(struct core_window *cw,
*width = work.g_w;
*height = work.g_h;
}
return NSERROR_OK;
}
@ -510,10 +521,10 @@ atari_treeview_get_window_dimensions(struct core_window *cw,
* \param cw the core window object
* \param ds the current drag status
*/
static void
static nserror
atari_treeview_drag_status(struct core_window *cw, core_window_drag_status ds)
{
return NSERROR_NOT_IMPLEMENTED;
}
@ -523,7 +534,8 @@ atari_treeview_drag_status(struct core_window *cw, core_window_drag_status ds)
static struct core_window_callback_table cw_t = {
.invalidate = atari_treeview_invalidate_area,
.update_size = atari_treeview_update_size,
.scroll_visible = atari_treeview_scroll_visible,
.set_scroll = atari_treeview_set_scroll,
.get_scroll = atari_treeview_get_scroll,
.get_window_dimensions = atari_treeview_get_window_dimensions,
.drag_status = atari_treeview_drag_status
};

View File

@ -136,7 +136,7 @@ fb_cw_invalidate(struct core_window *cw, const struct rect *r)
}
static void
static nserror
fb_cw_update_size(struct core_window *cw, int width, int height)
{
/* struct fb_corewindow *fb_cw = (struct fb_corewindow *)cw;
@ -144,41 +144,58 @@ fb_cw_update_size(struct core_window *cw, int width, int height)
toolkit_widget_set_size_request(FB_WIDGET(fb_cw->drawing_area),
width, height);
*/
return NSERROR_OK;
}
static void
fb_cw_scroll_visible(struct core_window *cw, const struct rect *r)
static nserror
fb_cw_set_scroll(struct core_window *cw, int x, int y)
{
/* struct fb_corewindow *fb_cw = (struct fb_corewindow *)cw;
toolkit_scroll_widget(fb_cw->widget, r);
*/
return NSERROR_OK;
}
static void
static nserror
fb_cw_get_scroll(struct core_window *cw, int *x, int *y)
{
/* struct fb_corewindow *fb_cw = (struct fb_corewindow *)cw;
toolkit_scroll_widget(fb_cw->widget, r);
*/
return NSERROR_NOT_IMPLEMENTED;
}
static nserror
fb_cw_get_window_dimensions(struct core_window *cw, int *width, int *height)
{
struct fb_corewindow *fb_cw = (struct fb_corewindow *)cw;
*width = fbtk_get_width(fb_cw->drawable);
*height = fbtk_get_height(fb_cw->drawable);
return NSERROR_OK;
}
static void
static nserror
fb_cw_drag_status(struct core_window *cw, core_window_drag_status ds)
{
struct fb_corewindow *fb_cw = (struct fb_corewindow *)cw;
fb_cw->drag_status = ds;
return NSERROR_OK;
}
struct core_window_callback_table fb_cw_cb_table = {
.invalidate = fb_cw_invalidate,
.update_size = fb_cw_update_size,
.scroll_visible = fb_cw_scroll_visible,
.set_scroll = fb_cw_set_scroll,
.get_scroll = fb_cw_get_scroll,
.get_window_dimensions = fb_cw_get_window_dimensions,
.drag_status = fb_cw_drag_status
};

View File

@ -588,13 +588,15 @@ nsgtk_cw_invalidate_area(struct core_window *cw, const struct rect *rect)
* \param width New widget width.
* \param height New widget height.
*/
static void
static nserror
nsgtk_cw_update_size(struct core_window *cw, int width, int height)
{
struct nsgtk_corewindow *nsgtk_cw = (struct nsgtk_corewindow *)cw;
gtk_widget_set_size_request(GTK_WIDGET(nsgtk_cw->drawing_area),
width, height);
return NSERROR_OK;
}
@ -604,12 +606,10 @@ nsgtk_cw_update_size(struct core_window *cw, int width, int height)
* \param cw core window handle.
* \param r rectangle that needs scrolling.
*/
static void
nsgtk_cw_scroll_visible(struct core_window *cw, const struct rect *r)
static nserror
nsgtk_cw_set_scroll(struct core_window *cw, int x, int y)
{
struct nsgtk_corewindow *nsgtk_cw = (struct nsgtk_corewindow *)cw;
int x0, y0, x1, y1;
gdouble vpage, hpage;
GtkAdjustment *vadj;
GtkAdjustment *hadj;
@ -619,41 +619,36 @@ nsgtk_cw_scroll_visible(struct core_window *cw, const struct rect *r)
assert(vadj != NULL);
assert(hadj != NULL);
g_object_get(vadj, "page-size", &vpage, NULL);
g_object_get(hadj, "page-size", &hpage, NULL);
gtk_adjustment_set_value(vadj, y);
gtk_adjustment_set_value(hadj, x);
y0 = (int)(gtk_adjustment_get_value(vadj));
y1 = y0 + vpage;
x0 = (int)(gtk_adjustment_get_value(hadj));
x1 = x0 + hpage;
return NSERROR_OK;
}
if (r->y1 > y1) {
/* The bottom of the rectangle is off the bottom of the
* window, so scroll down to fit it
*/
y0 = r->y1 - vpage;
}
if (r->y0 < y0) {
/* The top of the rectangle is off the top of the window,
* so scroll up to fit it
*/
y0 = r->y0;
}
if (r->x1 > x1) {
/* The right of the rectangle is off the right of the window
* so scroll right to fit it
*/
x0 = r->x1 - hpage;
}
if (r->x0 < x0) {
/* The left of the rectangle is off the left of the window
* so scroll left to fit it
*/
x0 = r->x0;
}
gtk_adjustment_set_value(vadj, y0);
gtk_adjustment_set_value(hadj, x0);
/**
* scroll window core window callback
*
* \param cw core window handle.
* \param r rectangle that needs scrolling.
*/
static nserror
nsgtk_cw_get_scroll(struct core_window *cw, int *x, int *y)
{
struct nsgtk_corewindow *nsgtk_cw = (struct nsgtk_corewindow *)cw;
GtkAdjustment *vadj;
GtkAdjustment *hadj;
vadj = gtk_scrolled_window_get_vadjustment(nsgtk_cw->scrolled);
hadj = gtk_scrolled_window_get_hadjustment(nsgtk_cw->scrolled);
assert(vadj != NULL);
assert(hadj != NULL);
*y = (int)(gtk_adjustment_get_value(vadj));
*x = (int)(gtk_adjustment_get_value(hadj));
return NSERROR_OK;
}
@ -664,7 +659,7 @@ nsgtk_cw_scroll_visible(struct core_window *cw, const struct rect *r)
* \param[out] width to be set to viewport width in px
* \param[out] height to be set to viewport height in px
*/
static void
static nserror
nsgtk_cw_get_window_dimensions(struct core_window *cw, int *width, int *height)
{
struct nsgtk_corewindow *nsgtk_cw = (struct nsgtk_corewindow *)cw;
@ -679,6 +674,8 @@ nsgtk_cw_get_window_dimensions(struct core_window *cw, int *width, int *height)
vadj = gtk_scrolled_window_get_vadjustment(nsgtk_cw->scrolled);
g_object_get(vadj, "page-size", &page, NULL);
*height = page;
return NSERROR_OK;
}
@ -688,11 +685,13 @@ nsgtk_cw_get_window_dimensions(struct core_window *cw, int *width, int *height)
* \param cw core window handle.
* \param ds The new drag status.
*/
static void
static nserror
nsgtk_cw_drag_status(struct core_window *cw, core_window_drag_status ds)
{
struct nsgtk_corewindow *nsgtk_cw = (struct nsgtk_corewindow *)cw;
nsgtk_cw->drag_status = ds;
return NSERROR_OK;
}
@ -702,7 +701,8 @@ nsgtk_cw_drag_status(struct core_window *cw, core_window_drag_status ds)
static struct core_window_callback_table nsgtk_cw_cb_table = {
.invalidate = nsgtk_cw_invalidate_area,
.update_size = nsgtk_cw_update_size,
.scroll_visible = nsgtk_cw_scroll_visible,
.set_scroll = nsgtk_cw_set_scroll,
.get_scroll = nsgtk_cw_get_scroll,
.get_window_dimensions = nsgtk_cw_get_window_dimensions,
.drag_status = nsgtk_cw_drag_status
};

View File

@ -792,7 +792,7 @@ ro_cw_invalidate(struct core_window *cw, const struct rect *r)
/**
* Callback from the core to update the content area size.
*/
static void
static nserror
ro_cw_update_size(struct core_window *cw, int width, int height)
{
struct ro_corewindow *ro_cw = (struct ro_corewindow *)cw;
@ -811,7 +811,7 @@ ro_cw_update_size(struct core_window *cw, int width, int height)
if (error) {
NSLOG(netsurf, INFO, "xwimp_get_window_state: 0x%x: %s",
error->errnum, error->errmess);
return;
return NSERROR_INVALID;
}
/* only update the window if it is open */
@ -824,14 +824,15 @@ ro_cw_update_size(struct core_window *cw, int width, int height)
update_scrollbars(ro_cw, &open);
}
return NSERROR_OK;
}
/**
* Callback from the core to scroll the visible content.
*/
static void
ro_cw_scroll_visible(struct core_window *cw, const struct rect *r)
static nserror
ro_cw_get_scroll(struct core_window *cw, int *x, int *y)
{
struct ro_corewindow *ro_cw = (struct ro_corewindow *)cw;
wimp_window_state state = {
@ -843,17 +844,39 @@ ro_cw_scroll_visible(struct core_window *cw, const struct rect *r)
if (error) {
NSLOG(netsurf, ERROR, "xwimp_get_window_state: 0x%x: %s",
error->errnum, error->errmess);
return;
return NSERROR_INVALID;
}
/* TODO:
* Scroll so the area is brought into view, not just the top left of
* the rectangle. See `nsgtk_cw_scroll_visible`.
*/
state.xscroll = -r->x0 * 2;
state.yscroll = -r->y0 * 2;
*x = state.xscroll / 2;
*y = state.yscroll / 2;
return NSERROR_OK;
}
/**
* Callback from the core to scroll the visible content.
*/
static nserror
ro_cw_set_scroll(struct core_window *cw, int x, int y)
{
struct ro_corewindow *ro_cw = (struct ro_corewindow *)cw;
wimp_window_state state = {
.w = ro_cw->wh,
};
os_error *error;
error = xwimp_get_window_state(&state);
if (error) {
NSLOG(netsurf, ERROR, "xwimp_get_window_state: 0x%x: %s",
error->errnum, error->errmess);
return NSERROR_INVALID;
}
state.xscroll = -x * 2;
state.yscroll = -y * 2;
ro_cw_open(PTR_WIMP_OPEN(&state));
return NSERROR_OK;
}
@ -864,7 +887,7 @@ ro_cw_scroll_visible(struct core_window *cw, const struct rect *r)
* \param[out] width to be set to viewport width in px
* \param[out] height to be set to viewport height in px
*/
static void
static nserror
ro_cw_get_window_dimensions(struct core_window *cw, int *width, int *height)
{
struct ro_corewindow *ro_cw = (struct ro_corewindow *)cw;
@ -876,29 +899,33 @@ ro_cw_get_window_dimensions(struct core_window *cw, int *width, int *height)
if (error) {
NSLOG(netsurf, INFO, "xwimp_get_window_state: 0x%x: %s",
error->errnum, error->errmess);
return;
return NSERROR_INVALID;
}
*width = (state.visible.x1 - state.visible.x0) / 2;
*height = (state.visible.y1 - state.visible.y0) / 2;
return NSERROR_OK;
}
/**
* Callback from the core to update the drag status.
*/
static void
static nserror
ro_cw_drag_status(struct core_window *cw, core_window_drag_status ds)
{
struct ro_corewindow *ro_cw = (struct ro_corewindow *)cw;
ro_cw->drag_status = ds;
return NSERROR_OK;
}
struct core_window_callback_table ro_cw_cb_table = {
.invalidate = ro_cw_invalidate,
.update_size = ro_cw_update_size,
.scroll_visible = ro_cw_scroll_visible,
.set_scroll = ro_cw_set_scroll,
.get_scroll = ro_cw_get_scroll,
.get_window_dimensions = ro_cw_get_window_dimensions,
.drag_status = ro_cw_drag_status
};

View File

@ -443,7 +443,7 @@ nsw32_cw_invalidate_area(struct core_window *cw, const struct rect *rect)
/**
* Callback from the core to update the content area size
*/
static void
static nserror
nsw32_cw_update_size(struct core_window *cw, int width, int height)
{
struct nsw32_corewindow *nsw32_cw = (struct nsw32_corewindow *)cw;
@ -453,13 +453,23 @@ nsw32_cw_update_size(struct core_window *cw, int width, int height)
NSLOG(netsurf, INFO, "new content size w:%d h:%d", width, height);
update_scrollbars(nsw32_cw);
return NSERROR_OK;
}
static void
nsw32_cw_scroll_visible(struct core_window *cw, const struct rect *r)
static nserror
nsw32_cw_set_scroll(struct core_window *cw, int x, int y)
{
/** /todo call setscroll apropriately */
return NSERROR_OK;
}
static nserror
nsw32_cw_get_scroll(struct core_window *cw, int *x, int *y)
{
/** /todo call getscroll apropriately */
return NSERROR_NOT_IMPLEMENTED;
}
@ -470,7 +480,7 @@ nsw32_cw_scroll_visible(struct core_window *cw, const struct rect *r)
* \param[out] width to be set to viewport width in px
* \param[out] height to be set to viewport height in px
*/
static void
static nserror
nsw32_cw_get_window_dimensions(struct core_window *cw, int *width, int *height)
{
struct nsw32_corewindow *nsw32_cw = (struct nsw32_corewindow *)cw;
@ -479,21 +489,24 @@ nsw32_cw_get_window_dimensions(struct core_window *cw, int *width, int *height)
GetClientRect(nsw32_cw->hWnd, &rc);
*width = rc.right;
*height = rc.bottom;
return NSERROR_OK;
}
static void
static nserror
nsw32_cw_drag_status(struct core_window *cw, core_window_drag_status ds)
{
struct nsw32_corewindow *nsw32_cw = (struct nsw32_corewindow *)cw;
nsw32_cw->drag_status = ds;
return NSERROR_OK;
}
struct core_window_callback_table nsw32_cw_cb_table = {
.invalidate = nsw32_cw_invalidate_area,
.update_size = nsw32_cw_update_size,
.scroll_visible = nsw32_cw_scroll_visible,
.set_scroll = nsw32_cw_set_scroll,
.get_scroll = nsw32_cw_get_scroll,
.get_window_dimensions = nsw32_cw_get_window_dimensions,
.drag_status = nsw32_cw_drag_status
};

View File

@ -74,16 +74,33 @@ struct core_window_callback_table {
* \param[in] cw the core window object
* \param[in] width the width in px, or negative if don't care
* \param[in] height the height in px, or negative if don't care
* \return NSERROR_OK on success or appropriate error code
*/
void (*update_size)(struct core_window *cw, int width, int height);
nserror (*update_size)(struct core_window *cw, int width, int height);
/**
* Scroll the window to make area visible
* Scroll the window to given scroll offsets
*
* Note: Core callers of this may want to look at calling
* the `cw_helper_scroll_visible()`, rather than calling
* this directly.
*
* \param[in] cw the core window object
* \param[in] r rectangle to make visible
* \param[in] x x-scroll value to set
* \param[in] y y-scroll value to set
* \return NSERROR_OK on success or appropriate error code
*/
void (*scroll_visible)(struct core_window *cw, const struct rect *r);
nserror (*set_scroll)(struct core_window *cw, int x, int y);
/**
* Get the current scroll offsets
*
* \param[in] cw the core window object
* \param[out] returns horizontal scroll in px
* \param[out] returns vertical scroll in px
* \return NSERROR_OK on success or appropriate error code
*/
nserror (*get_scroll)(struct core_window *cw, int *x, int *y);
/**
* Get window viewport dimensions
@ -91,8 +108,9 @@ struct core_window_callback_table {
* \param[in] cw the core window object
* \param[out] width to be set to viewport width in px
* \param[out] height to be set to viewport height in px
* \return NSERROR_OK on success or appropriate error code
*/
void (*get_window_dimensions)(struct core_window *cw,
nserror (*get_window_dimensions)(struct core_window *cw,
int *width, int *height);
/**
@ -100,8 +118,9 @@ struct core_window_callback_table {
*
* \param[in] cw the core window object
* \param[in] ds the current drag status
* \return NSERROR_OK on success or appropriate error code
*/
void (*drag_status)(struct core_window *cw,
nserror (*drag_status)(struct core_window *cw,
core_window_drag_status ds);
};