From 19317c76bade273b6d71cef4e6aa33e50479f9d9 Mon Sep 17 00:00:00 2001 From: Michael Drake Date: Sun, 4 Sep 2011 17:24:45 +0000 Subject: Implement frames in the core. svn path=/trunk/netsurf/; revision=12709 --- desktop/browser.c | 330 +++++++++++++++++++++++++++++++++++++++--------------- desktop/frames.c | 66 +++++++---- 2 files changed, 284 insertions(+), 112 deletions(-) diff --git a/desktop/browser.c b/desktop/browser.c index 7701ad9d4..b4c5cc200 100644 --- a/desktop/browser.c +++ b/desktop/browser.c @@ -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; - - browser_window_get_position(bw->drag_window, true, - &off_x, &off_y); + 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_mouse_track(bw->drag_window, mouse, + browser_window_get_position(drag_bw, true, &off_x, &off_y); + + 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; } } diff --git a/desktop/frames.c b/desktop/frames.c index f1710437f..5cf82f9d5 100644 --- a/desktop/frames.c +++ b/desktop/frames.c @@ -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; -- cgit v1.2.3