Implement frames in the core.

svn path=/trunk/netsurf/; revision=12709
This commit is contained in:
Michael Drake 2011-09-04 17:24:45 +00:00
parent e82474afed
commit 19317c76ba
2 changed files with 283 additions and 111 deletions

View File

@ -147,7 +147,7 @@ bool browser_window_redraw(struct browser_window *bw, int x, int y,
return false;
}
if (bw->current_content == NULL) {
if (bw->current_content == NULL && bw->children == NULL) {
/* Browser window has no content, render blank fill */
ctx->plot->clip(clip);
return ctx->plot->rectangle(clip->x0, clip->y0,
@ -155,15 +155,73 @@ bool browser_window_redraw(struct browser_window *bw, int x, int y,
plot_style_fill_white);
}
if (bw->browser_window_type != BROWSER_WINDOW_IFRAME &&
ctx->plot->option_knockout) {
/* Browser window has content OR children (frames) */
if (bw->window != NULL && ctx->plot->option_knockout) {
/* Root browser window: start knockout */
knockout_plot_start(ctx, &new_ctx);
}
/* Browser window has content */
new_ctx.plot->clip(clip);
/* Handle redraw of any browser window children */
if (bw->children) {
struct browser_window *child;
int cur_child;
int children = bw->rows * bw->cols;
if (bw->window != NULL)
/* Root browser window; start with blank fill */
plot_ok &= new_ctx.plot->rectangle(clip->x0, clip->y0,
clip->x1, clip->y1,
plot_style_fill_white);
/* Loop through all children of bw */
for (cur_child = 0; cur_child < children; cur_child++) {
/* Set current child */
child = &bw->children[cur_child];
/* Get frame edge box in global coordinates */
content_clip.x0 = (x + child->x) * child->scale;
content_clip.y0 = (y + child->y) * child->scale;
content_clip.x1 = content_clip.x0 +
child->width * child->scale;
content_clip.y1 = content_clip.y0 +
child->height * child->scale;
/* Intersect it with clip rectangle */
if (content_clip.x0 < clip->x0)
content_clip.x0 = clip->x0;
if (content_clip.y0 < clip->y0)
content_clip.y0 = clip->y0;
if (clip->x1 < content_clip.x1)
content_clip.x1 = clip->x1;
if (clip->y1 < content_clip.y1)
content_clip.y1 = clip->y1;
/* Skip this frame if it lies outside clip rectangle */
if (content_clip.x0 >= content_clip.x1 ||
content_clip.y0 >= content_clip.y1)
continue;
/* Redraw frame */
plot_ok &= browser_window_redraw(child,
x + child->x, y + child->y,
&content_clip, &new_ctx);
}
/* Nothing else to redraw for browser windows with children;
* cleanup and return */
if (bw->window != NULL && ctx->plot->option_knockout) {
/* Root browser window: knockout end */
knockout_plot_end();
}
return plot_ok;
}
/* Handle browser windows with content to redraw */
content_type = content_get_type(bw->current_content);
if (content_type != CONTENT_HTML && content_type != CONTENT_TEXTPLAIN) {
/* Set render area according to scale */
@ -229,8 +287,8 @@ bool browser_window_redraw(struct browser_window *bw, int x, int y,
}
}
if (bw->browser_window_type != BROWSER_WINDOW_IFRAME &&
ctx->plot->option_knockout) {
if (bw->window != NULL && ctx->plot->option_knockout) {
/* Root browser window: end knockout */
knockout_plot_end();
}
@ -254,16 +312,12 @@ bool browser_window_redraw_ready(struct browser_window *bw)
/* exported interface, documented in browser.h */
void browser_window_update_extent(struct browser_window *bw)
{
switch (bw->browser_window_type) {
default:
/* Fall through until core frame(set)s are implemented */
case BROWSER_WINDOW_NORMAL:
if (bw->window != NULL)
/* Front end window */
gui_window_update_extent(bw->window);
break;
case BROWSER_WINDOW_IFRAME:
else
/* Core-managed browser window */
browser_window_handle_scrollbars(bw);
break;
}
}
/* exported interface, documented in browser.h */
@ -277,16 +331,22 @@ void browser_window_get_position(struct browser_window *bw, bool root,
while (bw) {
switch (bw->browser_window_type) {
default:
/* fall through to NORMAL until frame(set)s are handled
* in the core */
case BROWSER_WINDOW_FRAME:
case BROWSER_WINDOW_FRAMESET:
*pos_x += bw->x * bw->scale;
*pos_y += bw->y * bw->scale;
break;
case BROWSER_WINDOW_NORMAL:
/* There is no offset to the root browser window */
break;
case BROWSER_WINDOW_IFRAME:
*pos_x += (bw->x - scrollbar_get_offset(bw->scroll_x)) * bw->scale;
*pos_y += (bw->y - scrollbar_get_offset(bw->scroll_y)) * bw->scale;
case BROWSER_WINDOW_IFRAME:
*pos_x += (bw->x - scrollbar_get_offset(bw->scroll_x)) *
bw->scale;
*pos_y += (bw->y - scrollbar_get_offset(bw->scroll_y)) *
bw->scale;
break;
}
@ -305,18 +365,13 @@ void browser_window_set_position(struct browser_window *bw, int x, int y)
{
assert(bw != NULL);
switch (bw->browser_window_type) {
default:
/* fall through to NORMAL until frame(set)s are handled
* in the core */
case BROWSER_WINDOW_NORMAL:
/* TODO: Not implemented yet */
break;
case BROWSER_WINDOW_IFRAME:
if (bw->window == NULL) {
/* Core managed browser window */
bw->x = x;
bw->y = y;
break;
} else {
LOG(("Asked to set position of front end window."));
assert(0);
}
}
@ -388,21 +443,16 @@ void browser_window_scroll_visible(struct browser_window *bw,
{
assert(bw != NULL);
switch (bw->browser_window_type) {
default:
/* fall through to NORMAL until frame(set)s are handled
* in the core */
case BROWSER_WINDOW_NORMAL:
if (bw->window != NULL) {
/* Front end window */
gui_window_scroll_visible(bw->window,
rect->x0, rect->y0, rect->x1, rect->y1);
break;
case BROWSER_WINDOW_IFRAME:
} 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);
break;
}
}
@ -936,6 +986,14 @@ nserror browser_window_callback(hlcache_handle *c,
.x1 = event->data.redraw.x + event->data.redraw.width,
.y1 = event->data.redraw.y + event->data.redraw.height
};
if (bw->browser_window_type == BROWSER_WINDOW_FRAME) {
rect.x0 -= scrollbar_get_offset(bw->scroll_x);
rect.y0 -= scrollbar_get_offset(bw->scroll_y);
rect.x1 -= scrollbar_get_offset(bw->scroll_x);
rect.y1 -= scrollbar_get_offset(bw->scroll_y);
}
browser_window_update_box(bw, &rect);
}
break;
@ -974,20 +1032,13 @@ void browser_window_get_dimensions(struct browser_window *bw,
{
assert(bw);
switch (bw->browser_window_type) {
case BROWSER_WINDOW_IFRAME:
if (bw->window == NULL) {
/* Core managed browser window */
*width = bw->width;
*height = bw->height;
break;
case BROWSER_WINDOW_FRAME:
case BROWSER_WINDOW_FRAMESET:
case BROWSER_WINDOW_NORMAL:
/* root window (or frame(set), currently); browser window is
* size of gui window viewport */
assert(bw->window);
} else {
/* Front end window */
gui_window_get_dimensions(bw->window, width, height, scaled);
break;
}
}
@ -1005,17 +1056,13 @@ void browser_window_set_dimensions(struct browser_window *bw,
{
assert(bw);
switch (bw->browser_window_type) {
case BROWSER_WINDOW_IFRAME:
if (bw->window == NULL) {
/* Core managed browser window */
bw->width = width;
bw->height = height;
break;
case BROWSER_WINDOW_FRAME:
case BROWSER_WINDOW_FRAMESET:
case BROWSER_WINDOW_NORMAL:
/* TODO: Not implemented yet */
break;
} else {
LOG(("Asked to set dimensions of front end window."));
assert(0);
}
}
@ -1183,9 +1230,7 @@ void browser_window_update(struct browser_window *bw, bool scroll_to_top)
return;
switch (bw->browser_window_type) {
default:
/* Fall through to normal
* (frame(set)s aren't handled by the core yet) */
case BROWSER_WINDOW_NORMAL:
/* Root browser window, constituting a front end window/tab */
gui_window_set_title(bw->window,
@ -1206,6 +1251,7 @@ void browser_window_update(struct browser_window *bw, bool scroll_to_top)
gui_window_redraw_window(bw->window);
break;
case BROWSER_WINDOW_IFRAME:
/* Internal iframe browser window */
@ -1223,6 +1269,35 @@ void browser_window_update(struct browser_window *bw, bool scroll_to_top)
html_redraw_a_box(bw->parent->current_content, bw->box);
break;
case BROWSER_WINDOW_FRAME:
{
struct rect rect;
browser_window_update_extent(bw);
if (scroll_to_top)
browser_window_set_scroll(bw, 0, 0);
/* 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);
}
rect.x0 = 0;
rect.y0 = 0;
rect.x1 = bw->width;
rect.y1 = bw->height;
browser_window_update_box(bw, &rect);
}
break;
default:
case BROWSER_WINDOW_FRAMESET:
/* Nothing to do */
break;
}
}
@ -1233,15 +1308,13 @@ void browser_window_update_box(struct browser_window *bw, struct rect *rect)
int pos_y;
struct browser_window *top;
switch (bw->browser_window_type) {
default:
/* fall through for frame(set)s,
* until they are handled by core */
case BROWSER_WINDOW_NORMAL:
gui_window_update_box(bw->window, rect);
break;
assert(bw);
case BROWSER_WINDOW_IFRAME:
if (bw->window != NULL) {
/* Front end window */
gui_window_update_box(bw->window, rect);
} else {
/* Core managed browser window */
browser_window_get_position(bw, true, &pos_x, &pos_y);
top = browser_window_get_root(bw);
@ -1252,7 +1325,6 @@ void browser_window_update_box(struct browser_window *bw, struct rect *rect)
rect->y1 += pos_y / bw->scale;
gui_window_update_box(top->window, rect);
break;
}
}
@ -1535,6 +1607,8 @@ void browser_window_destroy_internal(struct browser_window *bw)
*
* \param bw The browser window to find the owner of
* \return the browser window's owner
*
* TODO: REMOVE THIS FUNCTION
*/
struct browser_window *browser_window_owner(struct browser_window *bw)
@ -1579,7 +1653,10 @@ void browser_window_reformat(struct browser_window *bw, bool background,
/* Iframe dimensions are already scaled in parent's layout */
width /= bw->scale;
height /= bw->scale;
} else {
}
if (bw->window == NULL) {
/* Core managed browser window; subtract scrollbar width */
width -= bw->scroll_y ? SCROLLBAR_WIDTH : 0;
height -= bw->scroll_x ? SCROLLBAR_WIDTH : 0;
@ -1865,22 +1942,64 @@ void browser_window_mouse_track(struct browser_window *bw,
const char *status = NULL;
gui_pointer_shape pointer = GUI_POINTER_DEFAULT;
if (bw->window != NULL) {
/* root browser window */
if (bw->drag_window && bw != bw->drag_window) {
/* There's an active drag in a sub window.
* Pass the mouse action straight on to that bw. */
int off_x = 0;
int off_y = 0;
if (bw->window != NULL && bw->drag_window && bw != bw->drag_window) {
/* This is the root browser window and there's an active drag
* in a sub window.
* Pass the mouse action straight on to that bw. */
struct browser_window *drag_bw = bw->drag_window;
int off_x = 0;
int off_y = 0;
browser_window_get_position(bw->drag_window, true,
&off_x, &off_y);
browser_window_get_position(drag_bw, true, &off_x, &off_y);
browser_window_mouse_track(bw->drag_window, mouse,
if (drag_bw->browser_window_type == BROWSER_WINDOW_FRAME) {
off_x -= scrollbar_get_offset(drag_bw->scroll_x);
off_y -= scrollbar_get_offset(drag_bw->scroll_y);
browser_window_mouse_track(drag_bw, mouse,
x - off_x, y - off_y);
} else if (drag_bw->browser_window_type ==
BROWSER_WINDOW_IFRAME) {
browser_window_mouse_track(drag_bw, mouse,
x - off_x / bw->scale,
y - off_y / bw->scale);
}
return;
}
if (bw->children) {
/* Browser window has children (frames) */
struct browser_window *child;
int cur_child;
int children = bw->rows * bw->cols;
for (cur_child = 0; cur_child < children; cur_child++) {
child = &bw->children[cur_child];
if (x < child->x || y < child->y ||
child->x + child->width < x ||
child->y + child->height < y) {
/* Click not in this child */
continue;
}
/* It's this child that contains the mouse; pass
* mouse action on to child */
browser_window_mouse_track(child, mouse,
x - child->x + scrollbar_get_offset(
child->scroll_x),
y - child->y + scrollbar_get_offset(
child->scroll_y));
/* Mouse action was for this child, we're done */
return;
}
/* Odd if we reached here, but nothing else can use the click
* when there are children. */
return;
}
if (c == NULL && bw->drag_type != DRAGGING_FRAME)
@ -1978,6 +2097,38 @@ void browser_window_mouse_click(struct browser_window *bw,
const char *status = NULL;
gui_pointer_shape pointer = GUI_POINTER_DEFAULT;
if (bw->children) {
/* Browser window has children (frames) */
struct browser_window *child;
int cur_child;
int children = bw->rows * bw->cols;
for (cur_child = 0; cur_child < children; cur_child++) {
child = &bw->children[cur_child];
if (x < child->x || y < child->y ||
child->x + child->width < x ||
child->y + child->height < y) {
/* Click not in this child */
continue;
}
/* It's this child that contains the click; pass it
* on to child. */
browser_window_mouse_click(child, mouse,
x - child->x + scrollbar_get_offset(
child->scroll_x),
y - child->y + scrollbar_get_offset(
child->scroll_y));
/* Mouse action was for this child, we're done */
return;
}
return;
}
if (!c)
return;
@ -2136,19 +2287,16 @@ void browser_window_page_drag_start(struct browser_window *bw, int x, int y)
bw->drag_start_x = x;
bw->drag_start_y = y;
switch (bw->browser_window_type) {
default:
/* fall through until frame(set)s are handled in core */
case BROWSER_WINDOW_NORMAL:
if (bw->window != NULL) {
/* Front end window */
gui_window_get_scroll(bw->window, &bw->drag_start_scroll_x,
&bw->drag_start_scroll_y);
gui_window_scroll_start(bw->window);
break;
case BROWSER_WINDOW_IFRAME:
} else {
/* Core managed browser window */
bw->drag_start_scroll_x = scrollbar_get_offset(bw->scroll_x);
bw->drag_start_scroll_y = scrollbar_get_offset(bw->scroll_y);
break;
}
}

View File

@ -61,7 +61,18 @@ void browser_window_scroll_callback(void *client_data,
/* TODO: Is this needed? */
break;
case SCROLLBAR_MSG_MOVED:
html_redraw_a_box(bw->parent->current_content, bw->box);
if (bw->browser_window_type == BROWSER_WINDOW_IFRAME) {
html_redraw_a_box(bw->parent->current_content, bw->box);
} else {
struct rect rect;
rect.x0 = 0;
rect.y0 = 0;
rect.x1 = bw->width;
rect.y1 = bw->height;
browser_window_update_box(bw, &rect);
}
break;
case SCROLLBAR_MSG_SCROLL_START:
if (scrollbar_is_horizontal(scrollbar_data->scrollbar))
@ -315,15 +326,12 @@ void browser_window_create_frameset(struct browser_window *bw,
warn_user("NoMemory", 0);
}
/* TODO: When frames are handled in core:
* window->cur_sel = bw->cur_sel; */
window->cur_sel = bw->cur_sel;
window->scale = bw->scale;
/* linking */
window->parent = bw;
/* gui window */
window->window = gui_create_browser_window(window, bw, false);
if (window->name)
LOG(("Created frame '%s'", window->name));
else
@ -393,19 +401,20 @@ void browser_window_recalculate_frameset(struct browser_window *bw) {
float relative;
int size, extent;
int x, y;
int new_width, new_height;
assert(bw);
/* window dimensions */
if (!bw->parent) {
gui_window_get_dimensions(bw->window, &bw_width, &bw_height, false);
bw->x0 = 0;
bw->y0 = 0;
bw->x1 = bw_width;
bw->y1 = bw_height;
browser_window_get_dimensions(bw, &bw_width, &bw_height, true);
bw->x = 0;
bw->y = 0;
bw->width = bw_width;
bw->height = bw_height;
} else {
bw_width = bw->x1 - bw->x0;
bw_height = bw->y1 - bw->y0;
bw_width = bw->width;
bw_height = bw->height;
}
bw_width++;
bw_height++;
@ -471,8 +480,6 @@ void browser_window_recalculate_frameset(struct browser_window *bw) {
widths[col][row] = bw_width;
} else {
size = bw_width * widths[col][row] / extent;
bw_width -= size;
extent -= widths[col][row];
widths[col][row] = size;
}
}
@ -543,8 +550,6 @@ void browser_window_recalculate_frameset(struct browser_window *bw) {
heights[col][row] = bw_height;
} else {
size = bw_height * heights[col][row] / extent;
bw_height -= size;
extent -= heights[col][row];
heights[col][row] = size;
}
}
@ -561,10 +566,27 @@ void browser_window_recalculate_frameset(struct browser_window *bw) {
y = 0;
for (row2 = 0; row2 < row; row2++)
y+= heights[col][row2];
gui_window_position_frame(window->window, x, y,
x + widths[col][row] - 1,
y + heights[col][row] - 1);
window->x = x;
window->y = y;
new_width = widths[col][row] - 1;
new_height = heights[col][row] - 1;
if (window->width != new_width ||
window->height != new_height) {
/* Change in frame size */
browser_window_reformat(window, false,
new_width * bw->scale,
new_height * bw->scale);
window->width = new_width;
window->height = new_height;
browser_window_handle_scrollbars(window);
}
x += widths[col][row];
if (window->children)
browser_window_recalculate_frameset(window);
}
@ -827,7 +849,9 @@ bool browser_window_resize_frames(struct browser_window *bw, browser_mouse_state
bw->drag_resize_right = right;
bw->drag_resize_up = up;
bw->drag_resize_down = down;
gui_window_frame_resize_start(bw->window);
/* TODO: sort this out:
gui_window_frame_resize_start(bw->window); */
*status = messages_get("FrameDrag");
*action = true;