示例#1
0
文件: frames.c 项目: ysei/NetSurf
void browser_window_recalculate_iframes(struct browser_window *bw)
{
	struct browser_window *window;
	int index;

	for (index = 0; index < bw->iframe_count; index++) {
		window = &(bw->iframes[index]);

		if (window != NULL) {
			browser_window_handle_scrollbars(window);
		}
	}
}
示例#2
0
文件: frames.c 项目: ysei/NetSurf
void browser_window_recalculate_frameset(struct browser_window *bw)
{
	int widths[bw->cols][bw->rows];
	int heights[bw->cols][bw->rows];
	int bw_width, bw_height;
	int avail_width, avail_height;
	int row, row2, col, index;
	struct browser_window *window;
	float relative;
	int size, extent, applied;
	int x, y;
	int new_width, new_height;

	assert(bw);

	/* window dimensions */
	if (!bw->parent) {
		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->width;
		bw_height = bw->height;
	}
	bw_width++;
	bw_height++;

	/* widths */
	for (row = 0; row < bw->rows; row++) {
		avail_width = bw_width;
		relative = 0;
		for (col = 0; col < bw->cols; col++) {
			index = (row * bw->cols) + col;
			window = &bw->children[index];

			switch (window->frame_width.unit) {
			case FRAME_DIMENSION_PIXELS:
				widths[col][row] = window->frame_width.value *
						window->scale;
				if (window->border) {
					if (col != 0)
						widths[col][row] += 1;
					if (col != bw->cols - 1)
						widths[col][row] += 1;
				}
				break;
			case FRAME_DIMENSION_PERCENT:
				widths[col][row] = bw_width *
						window->frame_width.value / 100;
				break;
			case FRAME_DIMENSION_RELATIVE:
				widths[col][row] = 0;
				relative += window->frame_width.value;
				break;
			default:
				/* unknown frame dimension unit */
				assert(window->frame_width.unit ==
						FRAME_DIMENSION_PIXELS ||
						window->frame_width.unit ==
						FRAME_DIMENSION_PERCENT ||
						window->frame_width.unit ==
						FRAME_DIMENSION_RELATIVE);
				break;
			}
			avail_width -= widths[col][row];
		}

		/* Redistribute to fit window */
		if ((relative > 0) && (avail_width > 0)) {
			/* Expand the relative sections to fill remainder */
			for (col = 0; col < bw->cols; col++) {
				index = (row * bw->cols) + col;
				window = &bw->children[index];

				if (window->frame_width.unit ==
						FRAME_DIMENSION_RELATIVE) {
					size = avail_width * window->
							frame_width.value /
							relative;
					avail_width -= size;
					relative -= window->frame_width.value;
					widths[col][row] += size;
				}
			}
		} else if (bw_width != avail_width) {
			/* proportionally distribute error */
			extent = avail_width;
			applied = 0;
			for (col = 0; col < bw->cols; col++) {
				if (col == bw->cols - 1) {
					/* Last cell, use up remainder */
					widths[col][row] += extent - applied;
					widths[col][row] =
							widths[col][row] < 0 ?
							0 : widths[col][row];
				} else {
					/* Find size of cell adjustment */
					size = (widths[col][row] * extent) /
							(bw_width - extent);
					/* Modify cell */
					widths[col][row] += size;
					applied += size;
				}
			}
		}
	}

	/* heights */
	for (col = 0; col < bw->cols; col++) {
		avail_height = bw_height;
		relative = 0;
		for (row = 0; row < bw->rows; row++) {
			index = (row * bw->cols) + col;
			window = &bw->children[index];

			switch (window->frame_height.unit) {
			case FRAME_DIMENSION_PIXELS:
				heights[col][row] = window->frame_height.value *
						window->scale;
				if (window->border) {
					if (row != 0)
						heights[col][row] += 1;
					if (row != bw->rows - 1)
						heights[col][row] += 1;
				}
				break;
			case FRAME_DIMENSION_PERCENT:
				heights[col][row] = bw_height *
						window->frame_height.value / 100;
				break;
			case FRAME_DIMENSION_RELATIVE:
				heights[col][row] = 0;
				relative += window->frame_height.value;
				break;
			default:
				/* unknown frame dimension unit */
				assert(window->frame_height.unit ==
						FRAME_DIMENSION_PIXELS ||
						window->frame_height.unit ==
						FRAME_DIMENSION_PERCENT ||
						window->frame_height.unit ==
						FRAME_DIMENSION_RELATIVE);
				break;
			}
			avail_height -= heights[col][row];
		}

		if (avail_height == 0)
			continue;

		/* Redistribute to fit window */
		if ((relative > 0) && (avail_height > 0)) {
			/* Expand the relative sections to fill remainder */
			for (row = 0; row < bw->rows; row++) {
				index = (row * bw->cols) + col;
				window = &bw->children[index];

				if (window->frame_height.unit ==
						FRAME_DIMENSION_RELATIVE) {
					size = avail_height * window->
							frame_height.value /
							relative;
					avail_height -= size;
					relative -= window->frame_height.value;
					heights[col][row] += size;
				}
			}
		} else if (bw_height != avail_height) {
			/* proportionally distribute error */
			extent = avail_height;
			applied = 0;
			for (row = 0; row < bw->rows; row++) {
				if (row == bw->rows - 1) {
					/* Last cell, use up remainder */
					heights[col][row] += extent - applied;
					heights[col][row] =
							heights[col][row] < 0 ?
							0 : heights[col][row];
				} else {
					/* Find size of cell adjustment */
					size = (heights[col][row] * extent) /
							(bw_height - extent);
					/* Modify cell */
					heights[col][row] += size;
					applied += size;
				}
			}
		}
	}

	/* position frames and calculate children */
	for (row = 0; row < bw->rows; row++) {
		x = 0;
		for (col = 0; col < bw->cols; col++) {
			index = (row * bw->cols) + col;
			window = &bw->children[index];

			y = 0;
			for (row2 = 0; row2 < row; row2++)
				y+= heights[col][row2];

			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);
		}
	}
}
示例#3
0
/**
 * Callback for (i)frame scrollbars.
 */
void browser_window_scroll_callback(void *client_data,
		struct scrollbar_msg_data *scrollbar_data)
{
	struct browser_window *bw = client_data;

	switch(scrollbar_data->msg) {
	case SCROLLBAR_MSG_MOVED:
		if (bw->browser_window_type == BROWSER_WINDOW_IFRAME) {
			html_redraw_a_box(bw->parent->current_content, bw->box);
		} else {
			struct rect rect;

			rect.x0 = scrollbar_get_offset(bw->scroll_x);
			rect.y0 = scrollbar_get_offset(bw->scroll_y);
			rect.x1 = rect.x0 + bw->width;
			rect.y1 = rect.y0 + bw->height;

			browser_window_update_box(bw, &rect);
		}
		break;
	case SCROLLBAR_MSG_SCROLL_START:
	{
		struct rect rect = {
			.x0 = scrollbar_data->x0,
			.y0 = scrollbar_data->y0,
			.x1 = scrollbar_data->x1,
			.y1 = scrollbar_data->y1
		};

		if (scrollbar_is_horizontal(scrollbar_data->scrollbar))
			browser_window_set_drag_type(bw, DRAGGING_SCR_X, &rect);
		else
			browser_window_set_drag_type(bw, DRAGGING_SCR_Y, &rect);
	}
		break;
	case SCROLLBAR_MSG_SCROLL_FINISHED:
		browser_window_set_drag_type(bw, DRAGGING_NONE, NULL);

		browser_window_set_pointer(bw, BROWSER_POINTER_DEFAULT);
		break;
	}
}

/* exported interface, documented in browser.h */
void browser_window_handle_scrollbars(struct browser_window *bw)
{
	struct hlcache_handle *h = bw->current_content;
	bool scroll_x;
	bool scroll_y;
	int c_width = 0;
	int c_height = 0;

	assert(!bw->window); /* Core-handled windows only */

	if (h != NULL) {
		c_width  = content_get_width(h);
		c_height = content_get_height(h);
	}

	if (bw->scrolling == BW_SCROLLING_YES) {
		scroll_x = true;
		scroll_y = true;
	} else if (bw->scrolling == BW_SCROLLING_AUTO &&
			bw->current_content) {
		int bw_width = bw->width;
		int bw_height = bw->height;

		/* subtract existing scrollbar width */
		bw_width -= bw->scroll_y ? SCROLLBAR_WIDTH : 0;
		bw_height -= bw->scroll_x ? SCROLLBAR_WIDTH : 0;

		scroll_y = (c_height > bw_height) ? true : false;
		scroll_x = (c_width > bw_width) ? true : false;
	} else {
		/* No scrollbars */
		scroll_x = false;
		scroll_y = false;
	}

	if (!scroll_x && bw->scroll_x != NULL) {
		scrollbar_destroy(bw->scroll_x);
		bw->scroll_x = NULL;
	}

	if (!scroll_y && bw->scroll_y != NULL) {
		scrollbar_destroy(bw->scroll_y);
		bw->scroll_y = NULL;
	}

	if (scroll_y) {
		int length = bw->height;
		int visible = bw->height - (scroll_x ? SCROLLBAR_WIDTH : 0);

		if (bw->scroll_y == NULL) {
			/* create vertical scrollbar */
			if (scrollbar_create(false, length, c_height, visible,
					     bw, browser_window_scroll_callback,
					     &(bw->scroll_y)) != NSERROR_OK) {
				return;
			}
		} else {
			/* update vertical scrollbar */
			scrollbar_set_extents(bw->scroll_y, length,
					visible, c_height);
		}
	}

	if (scroll_x) {
		int length = bw->width - (scroll_y ? SCROLLBAR_WIDTH : 0);
		int visible = length;

		if (bw->scroll_x == NULL) {
			/* create horizontal scrollbar */
			if (scrollbar_create(true, length, c_width, visible,
					     bw, browser_window_scroll_callback,
					     &(bw->scroll_x)) != NSERROR_OK) {
				return;
			}
		} else {
			/* update horizontal scrollbar */
			scrollbar_set_extents(bw->scroll_x, length,
					visible, c_width);
		}
	}

	if (scroll_x && scroll_y)
		scrollbar_make_pair(bw->scroll_x, bw->scroll_y);
}


/* exported function documented in desktop/frames.h */
nserror browser_window_create_iframes(struct browser_window *bw,
		struct content_html_iframe *iframe)
{
	struct browser_window *window;
	struct content_html_iframe *cur;
	struct rect rect;
	int iframes = 0;
	int index;
	nserror ret = NSERROR_OK;

	if (iframe == NULL) {
		return NSERROR_BAD_PARAMETER;
	}

	/* Count iframe list and allocate enough space within the
	 * browser window.
	 */
	for (cur = iframe; cur; cur = cur->next) {
		iframes++;
	}
	bw->iframes = calloc(iframes, sizeof(*bw));
	if (!bw->iframes) {
		return NSERROR_NOMEM;
	}
	bw->iframe_count = iframes;

	index = 0;
	for (cur = iframe; cur; cur = cur->next) {
		window = &(bw->iframes[index++]);

		/* Initialise common parts */
		browser_window_initialise_common(BW_CREATE_NONE,
				window, NULL);

		/* window characteristics */
		window->browser_window_type = BROWSER_WINDOW_IFRAME;
		window->scrolling = cur->scrolling;
		window->border = cur->border;
		window->border_colour = cur->border_colour;
		window->no_resize = true;
		window->margin_width = cur->margin_width;
		window->margin_height = cur->margin_height;
		window->scale = bw->scale;
		if (cur->name != NULL) {
			window->name = strdup(cur->name);
			if (window->name == NULL) {
				free(bw->iframes) ;
				bw->iframes = 0;
				bw->iframe_count = 0;
				return NSERROR_NOMEM;
			}
		}

		/* linking */
		window->box = cur->box;
		window->parent = bw;
		window->box->iframe = window;

		/* iframe dimensions */
		box_bounds(window->box, &rect);

		browser_window_set_position(window, rect.x0, rect.y0);
		browser_window_set_dimensions(window, rect.x1 - rect.x0,
				rect.y1 - rect.y0);
	}

	/* calculate dimensions */
	browser_window_update_extent(bw);
	browser_window_recalculate_iframes(bw);

	index = 0;
	for (cur = iframe; cur; cur = cur->next) {
		window = &(bw->iframes[index++]);
		if (cur->url) {
			/* fetch iframe's content */
			ret = browser_window_navigate(window,
				cur->url,
				hlcache_handle_get_url(bw->current_content),
				BW_NAVIGATE_UNVERIFIABLE,
				NULL,
				NULL,
				bw->current_content);
		}
	}

	return ret;
}


/**
 * Recalculate iframe positions following a resize.
 *
 * \param  bw	    The browser window to reposition iframes for
 */

void browser_window_recalculate_iframes(struct browser_window *bw)
{
	struct browser_window *window;
	int index;

	for (index = 0; index < bw->iframe_count; index++) {
		window = &(bw->iframes[index]);

		if (window != NULL) {
			browser_window_handle_scrollbars(window);
		}
	}
}


/* exported interface documented in desktop/frames.h */
nserror browser_window_create_frameset(struct browser_window *bw,
		struct content_html_frames *frameset)
{
	int row, col, index;
	struct content_html_frames *frame;
	struct browser_window *window;
	hlcache_handle *parent;

	assert(bw && frameset);

	/* 1. Create children */
	assert(bw->children == NULL);
	assert(frameset->cols + frameset->rows != 0);

	bw->children = calloc((frameset->cols * frameset->rows), sizeof(*bw));
	if (!bw->children) {
		return NSERROR_NOMEM;
	}

	bw->cols = frameset->cols;
	bw->rows = frameset->rows;
	for (row = 0; row < bw->rows; row++) {
		for (col = 0; col < bw->cols; col++) {
			index = (row * bw->cols) + col;
			frame = &frameset->children[index];
			window = &bw->children[index];

			/* Initialise common parts */
			browser_window_initialise_common(BW_CREATE_NONE,
					window, NULL);

			/* window characteristics */
			if (frame->children)
				window->browser_window_type =
						BROWSER_WINDOW_FRAMESET;
			else
				window->browser_window_type =
						BROWSER_WINDOW_FRAME;
			window->scrolling = frame->scrolling;
			window->border = frame->border;
			window->border_colour = frame->border_colour;
			window->no_resize = frame->no_resize;
			window->frame_width = frame->width;
			window->frame_height = frame->height;
			window->margin_width = frame->margin_width;
			window->margin_height = frame->margin_height;
			if (frame->name) {
				window->name = strdup(frame->name);
				if (!window->name) {
					free(bw->children);
					bw->children = NULL;
					return NSERROR_NOMEM;
				}
			}

			window->scale = bw->scale;

			/* linking */
			window->parent = bw;

			if (window->name)
				LOG("Created frame '%s'", window->name);
			else
				LOG("Created frame (unnamed)");
		}
	}

	/* 2. Calculate dimensions */
	browser_window_update_extent(bw);
	browser_window_recalculate_frameset(bw);

	/* 3. Recurse for grandchildren */
	for (row = 0; row < bw->rows; row++) {
		for (col = 0; col < bw->cols; col++) {
			index = (row * bw->cols) + col;
			frame = &frameset->children[index];
			window = &bw->children[index];

			if (frame->children)
				browser_window_create_frameset(window, frame);
		}
	}

	/* Use the URL of the first ancestor window containing html content
	 * as the referer */
	for (window = bw; window->parent; window = window->parent) {
		if (window->current_content &&
				content_get_type(window->current_content) ==
				CONTENT_HTML)
			break;
	}

	parent = window->current_content;

	/* 4. Launch content */
	for (row = 0; row < bw->rows; row++) {
		for (col = 0; col < bw->cols; col++) {
			index = (row * bw->cols) + col;
			frame = &frameset->children[index];
			window = &bw->children[index];

			if (frame->url) {
				browser_window_navigate(window,
					frame->url,
					hlcache_handle_get_url(parent),
					BW_NAVIGATE_HISTORY |
					BW_NAVIGATE_UNVERIFIABLE,
					NULL,
					NULL,
					parent);
			}
		}
	}

	return NSERROR_OK;
}