diff options
author | Michael Drake <tlsa@netsurf-browser.org> | 2011-06-14 20:00:18 +0000 |
---|---|---|
committer | Michael Drake <tlsa@netsurf-browser.org> | 2011-06-14 20:00:18 +0000 |
commit | 53f4da342088e0fe685034d0582cbf6fa13527ae (patch) | |
tree | 063970a74db5d904993cd2cc392f5e07f211b6a4 /desktop/browser.c | |
parent | 6ed9b1de8bb2aa5220c60fbf0b42aea78f889da1 (diff) | |
download | netsurf-53f4da342088e0fe685034d0582cbf6fa13527ae.tar.gz netsurf-53f4da342088e0fe685034d0582cbf6fa13527ae.tar.bz2 |
First pass at core iframes. Currently lacking scrollbars.
svn path=/trunk/netsurf/; revision=12474
Diffstat (limited to 'desktop/browser.c')
-rw-r--r-- | desktop/browser.c | 296 |
1 files changed, 263 insertions, 33 deletions
diff --git a/desktop/browser.c b/desktop/browser.c index a7126a64b..fa2d1bcbb 100644 --- a/desktop/browser.c +++ b/desktop/browser.c @@ -112,7 +112,8 @@ bool browser_window_redraw(struct browser_window *bw, int x, int y, } /* Browser window has content */ - if (plot.option_knockout) + if (bw->browser_window_type != BROWSER_WINDOW_IFRAME && + plot.option_knockout) knockout_plot_start(&plot); plot.clip(clip); @@ -133,7 +134,8 @@ bool browser_window_redraw(struct browser_window *bw, int x, int y, plot_ok &= content_redraw(bw->current_content, x, y, width, height, clip, bw->scale, 0xFFFFFF, false, false); - if (plot.option_knockout) + if (bw->browser_window_type != BROWSER_WINDOW_IFRAME && + plot.option_knockout) knockout_plot_end(); return plot_ok; @@ -153,8 +155,60 @@ bool browser_window_redraw_ready(struct browser_window *bw) return true; } +/* 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: + gui_window_update_extent(bw->window); + break; + case BROWSER_WINDOW_IFRAME: + /* TODO */ + break; + } +} + +/* exported interface, documented in browser.h */ +void browser_window_get_position(struct browser_window *bw, bool root, + int *pos_x, int *pos_y) +{ + int x, y; + *pos_x = 0; + *pos_y = 0; + + assert(bw != NULL); + + while (bw) { + switch (bw->browser_window_type) { + default: + /* fall through to NORMAL until frame(set)s are handled + * in the core */ + case BROWSER_WINDOW_NORMAL: + /* There is no offset to the root browser window */ + break; + case BROWSER_WINDOW_IFRAME: + /* offset comes from its box position in parent bw */ + box_coords(bw->box, &x, &y); + + *pos_x += x; + *pos_y += y; + break; + } + + bw = bw->parent; + + if (!root) { + /* return if we just wanted the position in the parent + * browser window. */ + return; + } + } +} + /** - * Create and open a new browser window with the given page. + * Create and open a new root browser window with the given page. * * \param url URL to start fetching in the new window (copied) * \param clone The browser window to clone @@ -166,6 +220,7 @@ struct browser_window *browser_window_create(const char *url, const char *referer, bool history_add, bool new_tab) { struct browser_window *bw; + struct browser_window *top; assert(clone || history_add); @@ -183,10 +238,18 @@ struct browser_window *browser_window_create(const char *url, bw->border = true; bw->no_resize = true; bw->last_action = wallclock(); - - bw->window = gui_create_browser_window(bw, clone, new_tab); + bw->sel = selection_create(); /* gui window */ + /* from the front end's pov, it clones the top level browser window, + * so find that. */ + top = clone; + while (top && !top->window && top->parent) { + top = top->parent; + } + + bw->window = gui_create_browser_window(bw, top, new_tab); + if (bw->window == NULL) { browser_window_destroy(bw); return NULL; @@ -217,13 +280,15 @@ void browser_window_initialise_common(struct browser_window *bw, bw->history = history_clone(clone->history); /* window characteristics */ - bw->sel = selection_create(bw); + bw->sel = NULL; bw->refresh_interval = -1; bw->reformat_pending = false; bw->drag_type = DRAGGING_NONE; bw->scale = (float) option_scale / 100.0; + bw->focus = NULL; + /* initialise status text cache */ bw->status_text = NULL; bw->status_text_len = 0; @@ -534,7 +599,7 @@ nserror browser_window_callback(hlcache_handle *c, bw->loading_content = NULL; /* Format the new content to the correct dimensions */ - gui_window_get_dimensions(bw->window, &width, &height, true); + browser_window_get_dimensions(bw, &width, &height, true); content_reformat(c, width, height); browser_window_remove_caret(bw); @@ -568,9 +633,11 @@ nserror browser_window_callback(hlcache_handle *c, } /* favicon preload */ - if (content_get_type(c) == CONTENT_HTML) + if (bw->browser_window_type == BROWSER_WINDOW_NORMAL && + content_get_type(c) == CONTENT_HTML) { gui_window_set_icon(bw->window, - html_get_favicon(bw->current_content)); + html_get_favicon(bw->current_content)); + } /* text selection */ if (content_get_type(c) == CONTENT_HTML) @@ -651,7 +718,7 @@ nserror browser_window_callback(hlcache_handle *c, break; case CONTENT_MSG_REDRAW: - gui_window_update_box(bw->window, &event->data); + browser_window_update_box(bw, &event->data); break; case CONTENT_MSG_REFRESH: @@ -660,7 +727,10 @@ nserror browser_window_callback(hlcache_handle *c, case CONTENT_MSG_FAVICON_REFRESH: /* Cause the GUI to update */ - gui_window_set_icon(bw->window, html_get_favicon(bw->current_content)); + if (bw->browser_window_type == BROWSER_WINDOW_NORMAL) { + gui_window_set_icon(bw->window, + html_get_favicon(bw->current_content)); + } break; default: @@ -671,6 +741,41 @@ nserror browser_window_callback(hlcache_handle *c, } +/* + * Get the dimensions of the area a browser window occupies + * + * \param bw The browser window to get dimensions of + * \param width Updated to the browser window viewport width + * \param height Updated to the browser window viewport height + * \param scaled Whether we want the height with scale applied + */ + +void browser_window_get_dimensions(struct browser_window *bw, + int *width, int *height, bool scaled) +{ + struct rect rect; + + switch (bw->browser_window_type) { + case BROWSER_WINDOW_IFRAME: + /* browser window is size of associated box */ + box_bounds(bw->box, &rect); + /* TODO: Handle scale */ + *width = rect.x1 - rect.x0; + *height = rect.y1 - rect.y0; + 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); + gui_window_get_dimensions(bw->window, width, height, scaled); + break; + } +} + + /** * Transfer the loading_content to a new download window. */ @@ -833,22 +938,75 @@ void browser_window_update(struct browser_window *bw, bool scroll_to_top) if (bw->current_content == NULL) return; - gui_window_set_title(bw->window, - content_get_title(bw->current_content)); + 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, + content_get_title(bw->current_content)); + + browser_window_update_extent(bw); + + if (scroll_to_top) + gui_window_set_scroll(bw->window, 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)) { + gui_window_set_scroll(bw->window, x, y); + } - gui_window_update_extent(bw->window); + gui_window_redraw_window(bw->window); - if (scroll_to_top) - gui_window_set_scroll(bw->window, 0, 0); + break; + case BROWSER_WINDOW_IFRAME: + /* Internal iframe browser window */ + + /** \TODO handle scrollbar extents, scroll offset */ - /** \todo don't do this if the user has scrolled */ - /* if frag_id exists, then try to scroll to it */ - if (bw->frag_id && html_get_id_offset(bw->current_content, bw->frag_id, - &x, &y)) { - gui_window_set_scroll(bw->window, x, y); + html_redraw_a_box(bw->parent->current_content, bw->box); + break; } +} + + +void browser_window_update_box(struct browser_window *bw, + const union content_msg_data *data) +{ + int pos_x; + int pos_y; + union content_msg_data data_copy = *data; + 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, data); + break; + + case BROWSER_WINDOW_IFRAME: + browser_window_get_position(bw, true, &pos_x, &pos_y); - gui_window_redraw_window(bw->window); + top = bw; + while (top && !top->window && top->parent) { + top = top->parent; + } + + /* TODO: update gui_window_update_box so it takes a struct rect + * instead of msg data. */ + data_copy.redraw.x += pos_x; + data_copy.redraw.y += pos_y; + data_copy.redraw.object_x += pos_x; + data_copy.redraw.object_y += pos_y; + + gui_window_update_box(top->window, &data_copy); + break; + } } @@ -993,9 +1151,19 @@ void browser_window_set_status(struct browser_window *bw, const char *text) * \param shape shape to use */ -void browser_window_set_pointer(struct gui_window *g, gui_pointer_shape shape) +void browser_window_set_pointer(struct browser_window *bw, + gui_pointer_shape shape) { - gui_window_set_pointer(g, shape); + struct browser_window *root = bw; + + while (root && !root->window && root->parent) { + root = root->parent; + } + + assert(root); + assert(root->window); + + gui_window_set_pointer(root->window, shape); } @@ -1061,12 +1229,27 @@ void browser_window_destroy_internal(struct browser_window *bw) schedule_remove(browser_window_refresh, bw); + /* If this brower window is not the root window, and has focus, unset + * the root browser window's focus pointer. */ + if (!bw->window) { + struct browser_window *top = bw; + + while (top && !top->window && top->parent) + top = top->parent; + + if (top->focus == bw) + top->focus = NULL; + } + /* Destruction order is important: we must ensure that the frontend * destroys any window(s) associated with this browser window before * we attempt any destructive cleanup. */ - gui_window_destroy(bw->window); + if (bw->window) { + /* Only the root window has a GUI window */ + gui_window_destroy(bw->window); + } if (bw->loading_content != NULL) { hlcache_handle_release(bw->loading_content); @@ -1083,8 +1266,18 @@ void browser_window_destroy_internal(struct browser_window *bw) bw->current_content = NULL; } + if (bw->box != NULL) { + bw->box->iframe = NULL; + bw->box = NULL; + } + + /* TODO: After core FRAMES are done, should be + * if (bw->browser_window_type == BROWSER_WINDOW_NORMAL) */ + if (bw->browser_window_type != BROWSER_WINDOW_IFRAME) { + selection_destroy(bw->sel); + } + /* These simply free memory, so are safe here */ - selection_destroy(bw->sel); history_destroy(bw->history); free(bw->name); @@ -1212,6 +1405,11 @@ void browser_window_refresh_url_bar(struct browser_window *bw, const char *url, bw->visible_select_menu = NULL; + if (bw->parent != NULL) { + /* Not root window; don't set a URL in GUI URL bar */ + return; + } + if (frag == NULL) { /* With no fragment, we may as well pass url straight through * saving a malloc, copy, free cycle. @@ -1425,6 +1623,10 @@ void browser_window_mouse_track(struct browser_window *bw, browser_window_mouse_drag_end(bw, mouse, x, y); } + if (bw->drag_type != DRAGGING_NONE) { + selection_set_browser_window(bw->sel, bw); + } + if (bw->drag_type == DRAGGING_FRAME) { browser_window_resize_frame(bw, bw->x0 + x, bw->y0 + y); } else if (bw->drag_type == DRAGGING_PAGE_SCROLL) { @@ -1439,7 +1641,17 @@ void browser_window_mouse_track(struct browser_window *bw, bw->drag_start_scroll_x = scrollx; bw->drag_start_scroll_y = scrolly; - gui_window_set_scroll(bw->window, scrollx, scrolly); + switch (bw->browser_window_type) { + default: + /* Fall through to normal, until frame(set)s are + * handled in the core */ + case BROWSER_WINDOW_NORMAL: + gui_window_set_scroll(bw->window, scrollx, scrolly); + break; + case BROWSER_WINDOW_IFRAME: + /* TODO */ + break; + } } else { assert(c != NULL); content_mouse_track(c, bw, mouse, x, y); @@ -1460,10 +1672,19 @@ void browser_window_mouse_click(struct browser_window *bw, browser_mouse_state mouse, int x, int y) { hlcache_handle *c = bw->current_content; + struct browser_window *top; if (!c) return; + /* Set focus browser window */ + top = bw; + while (top && !top->window && top->parent) + top = top->parent; + top->focus = bw; + + selection_set_browser_window(bw->sel, bw); + switch (content_get_type(c)) { case CONTENT_HTML: case CONTENT_TEXTPLAIN: @@ -1481,7 +1702,7 @@ void browser_window_mouse_click(struct browser_window *bw, else if (mouse & (BROWSER_MOUSE_DRAG_1 | BROWSER_MOUSE_DRAG_2)) { browser_window_page_drag_start(bw, x, y); - browser_window_set_pointer(bw->window, GUI_POINTER_MOVE); + browser_window_set_pointer(bw, GUI_POINTER_MOVE); } break; } @@ -1495,10 +1716,10 @@ void browser_window_mouse_click(struct browser_window *bw, * \param mouse state of mouse buttons and modifier keys * \param x coordinate of mouse * \param y coordinate of mouse + * + * TODO: MOVE content specific stuff out */ -// TODO: MOVE content specific stuff out - void browser_window_mouse_drag_end(struct browser_window *bw, browser_mouse_state mouse, int x, int y) { @@ -1581,10 +1802,19 @@ void browser_window_page_drag_start(struct browser_window *bw, int x, int y) bw->drag_start_x = x; bw->drag_start_y = y; - gui_window_get_scroll(bw->window, &bw->drag_start_scroll_x, - &bw->drag_start_scroll_y); + switch (bw->browser_window_type) { + default: + /* fall through until frame(set)s are handled in core */ + case BROWSER_WINDOW_NORMAL: + gui_window_get_scroll(bw->window, &bw->drag_start_scroll_x, + &bw->drag_start_scroll_y); - gui_window_scroll_start(bw->window); + gui_window_scroll_start(bw->window); + break; + case BROWSER_WINDOW_IFRAME: + /* TODO */ + break; + } } |