summaryrefslogtreecommitdiff
path: root/render
diff options
context:
space:
mode:
authorMichael Drake <tlsa@netsurf-browser.org>2009-08-14 10:37:33 +0000
committerMichael Drake <tlsa@netsurf-browser.org>2009-08-14 10:37:33 +0000
commit13afa0ff4c591e7800dc4c11a81d04c335418c05 (patch)
tree017f315584621f418a8bab5627aee8f8364d377b /render
parent3549846a9aec635bea82a919c5c1e38c7163731a (diff)
downloadnetsurf-13afa0ff4c591e7800dc4c11a81d04c335418c05.tar.gz
netsurf-13afa0ff4c591e7800dc4c11a81d04c335418c05.tar.bz2
Merge Paul Blokus' selectscroll branch. Adds core select menu widget for forms and core scrollbar widget.
svn path=/trunk/netsurf/; revision=9289
Diffstat (limited to 'render')
-rw-r--r--render/box.c164
-rw-r--r--render/box.h13
-rw-r--r--render/form.c492
-rw-r--r--render/form.h34
-rw-r--r--render/html_redraw.c454
-rw-r--r--render/layout.c7
-rw-r--r--render/layout.h2
7 files changed, 783 insertions, 383 deletions
diff --git a/render/box.c b/render/box.c
index b1ebfcbad..0c0985dab 100644
--- a/render/box.c
+++ b/render/box.c
@@ -29,11 +29,13 @@
#include "content/content.h"
#include "css/css.h"
#include "css/dump.h"
+#include "desktop/scroll.h"
#include "desktop/options.h"
#include "render/box.h"
#include "render/form.h"
#include "utils/log.h"
#include "utils/talloc.h"
+#include "utils/utils.h"
static bool box_contains_point(struct box *box, int x, int y, bool *physically);
@@ -80,7 +82,7 @@ struct box * box_create(css_computed_style *style,
box->descendant_x1 = box->descendant_y1 = 0;
for (i = 0; i != 4; i++)
box->margin[i] = box->padding[i] = box->border[i].width = 0;
- box->scroll_x = box->scroll_y = 0;
+ box->scroll_x = box->scroll_y = NULL;
box->min_width = 0;
box->max_width = UNKNOWN_MAX_WIDTH;
box->byte_offset = 0;
@@ -226,6 +228,10 @@ void box_free_box(struct box *box)
if (!box->clone) {
if (box->gadget)
form_free_control(box->gadget);
+ if (box->scroll_x != NULL)
+ scroll_destroy(box->scroll_x);
+ if (box->scroll_y != NULL)
+ scroll_destroy(box->scroll_y);
}
talloc_free(box);
@@ -251,8 +257,8 @@ void box_coords(struct box *box, int *x, int *y)
} while (!box->float_children);
} else
box = box->parent;
- *x += box->x - box->scroll_x;
- *y += box->y - box->scroll_y;
+ *x += box->x - scroll_get_offset(box->scroll_x);
+ *y += box->y - scroll_get_offset(box->scroll_y);
}
}
@@ -328,8 +334,10 @@ struct box *box_at_point(struct box *box, const int x, const int y,
/* consider floats second, since they will often overlap other boxes */
for (child = box->float_children; child; child = child->next_float) {
if (box_contains_point(child, x - bx, y - by, &physically)) {
- *box_x = bx + child->x - child->scroll_x;
- *box_y = by + child->y - child->scroll_y;
+ *box_x = bx + child->x -
+ scroll_get_offset(child->scroll_x);
+ *box_y = by + child->y -
+ scroll_get_offset(child->scroll_y);
if (physically)
return child;
@@ -345,8 +353,10 @@ non_float_children:
if (box_is_float(child))
continue;
if (box_contains_point(child, x - bx, y - by, &physically)) {
- *box_x = bx + child->x - child->scroll_x;
- *box_y = by + child->y - child->scroll_y;
+ *box_x = bx + child->x -
+ scroll_get_offset(child->scroll_x);
+ *box_y = by + child->y -
+ scroll_get_offset(child->scroll_y);
if (physically)
return child;
@@ -370,16 +380,18 @@ siblings:
/* siblings and siblings of ancestors */
while (box) {
if (box_is_float(box)) {
- bx -= box->x - box->scroll_x;
- by -= box->y - box->scroll_y;
+ bx -= box->x - scroll_get_offset(box->scroll_x);
+ by -= box->y - scroll_get_offset(box->scroll_y);
for (sibling = box->next_float; sibling;
sibling = sibling->next_float) {
if (box_contains_point(sibling,
x - bx, y - by, &physically)) {
*box_x = bx + sibling->x -
- sibling->scroll_x;
+ scroll_get_offset(
+ sibling->scroll_x);
*box_y = by + sibling->y -
- sibling->scroll_y;
+ scroll_get_offset(
+ sibling->scroll_y);
if (physically)
return sibling;
@@ -398,8 +410,8 @@ siblings:
goto non_float_children;
} else {
- bx -= box->x - box->scroll_x;
- by -= box->y - box->scroll_y;
+ bx -= box->x - scroll_get_offset(box->scroll_x);
+ by -= box->y - scroll_get_offset(box->scroll_y);
for (sibling = box->next; sibling;
sibling = sibling->next) {
if (box_is_float(sibling))
@@ -407,9 +419,11 @@ siblings:
if (box_contains_point(sibling, x - bx, y - by,
&physically)) {
*box_x = bx + sibling->x -
- sibling->scroll_x;
+ scroll_get_offset(
+ sibling->scroll_x);
*box_y = by + sibling->y -
- sibling->scroll_y;
+ scroll_get_offset(
+ sibling->scroll_y);
if (physically)
return sibling;
@@ -978,3 +992,123 @@ void box_duplicate_update(struct box *box,
box->next_float = box_dict_element->new;
}
}
+
+/**
+ * Applies the given scroll setup to a box. This includes scroll
+ * creation/deletion as well as scroll dimension updates.
+ *
+ * \param box the box to handle the scrolls for
+ * \param x X coordinate of the box
+ * \param y Y coordinate of the box
+ * \param bottom whether the horizontal scrollbar should be present
+ * \param right whether the vertical scrollbar should be present
+ * \return true on success false otherwise
+ */
+bool box_handle_scrollbars(struct box *box, int x, int y, bool bottom,
+ bool right)
+{
+ struct browser_scroll_data *data;
+ int padding_width, padding_height;
+
+ padding_width = box->width + box->padding[RIGHT] + box->padding[LEFT];
+ padding_height = box->height + box->padding[TOP] + box->padding[BOTTOM];
+
+ if (!bottom && box->scroll_x != NULL) {
+ data = scroll_get_data(box->scroll_x);
+ scroll_destroy(box->scroll_x);
+ free(data);
+ box->scroll_x = NULL;
+ }
+
+ if (!right && box->scroll_y != NULL) {
+ data = scroll_get_data(box->scroll_x);
+ scroll_destroy(box->scroll_y);
+ free(data);
+ box->scroll_y = NULL;
+ }
+
+ if (!bottom && !right)
+ return true;
+
+ if (right) {
+ if (box->scroll_y == NULL) {
+ data = malloc(sizeof(struct browser_scroll_data));
+ if (data == NULL) {
+ LOG(("malloc failed"));
+ warn_user("NoMemory", 0);
+ return false;
+ }
+ data->bw = current_redraw_browser;
+ data->box = box;
+ if (!scroll_create(false,
+ padding_height,
+ box->descendant_y1 - box->descendant_y0,
+ box->height,
+ data,
+ browser_scroll_callback,
+ &(box->scroll_y)))
+ return false;
+ } else
+ scroll_set_length_and_visible(box->scroll_y,
+ padding_height, box->height);
+ }
+ if (bottom) {
+ if (box->scroll_x == NULL) {
+ data = malloc(sizeof(struct browser_scroll_data));
+ if (data == NULL) {
+ LOG(("malloc failed"));
+ warn_user("NoMemory", 0);
+ return false;
+ }
+ data->bw = current_redraw_browser;
+ data->box = box;
+ if (!scroll_create(true,
+ padding_width -
+ (right ? SCROLLBAR_WIDTH : 0),
+ box->descendant_x1 - box->descendant_x0,
+ box->width,
+ data,
+ browser_scroll_callback,
+ &box->scroll_x))
+ return false;
+ } else
+ scroll_set_length_and_visible(box->scroll_x,
+ padding_width -
+ (right ? SCROLLBAR_WIDTH : 0),
+ box->width);
+ }
+
+ if (right && bottom)
+ scroll_make_pair(box->scroll_x, box->scroll_y);
+
+ return true;
+}
+
+/**
+ * Determine if a box has a vertical scrollbar.
+ *
+ * \param box scrolling box
+ * \return the box has a vertical scrollbar
+ */
+
+bool box_vscrollbar_present(const struct box * const box)
+{
+ return box->descendant_y0 < -box->border[TOP].width ||
+ box->padding[TOP] + box->height + box->padding[BOTTOM] +
+ box->border[BOTTOM].width < box->descendant_y1;
+}
+
+
+/**
+ * Determine if a box has a horizontal scrollbar.
+ *
+ * \param box scrolling box
+ * \return the box has a horizontal scrollbar
+ */
+
+bool box_hscrollbar_present(const struct box * const box)
+{
+ return box->descendant_x0 < -box->border[LEFT].width ||
+ box->padding[LEFT] + box->width + box->padding[RIGHT] +
+ box->border[RIGHT].width < box->descendant_x1;
+}
diff --git a/render/box.h b/render/box.h
index 701329108..39a6c2521 100644
--- a/render/box.h
+++ b/render/box.h
@@ -167,8 +167,8 @@ struct box {
int padding[4]; /**< Padding: TOP, RIGHT, BOTTOM, LEFT. */
struct box_border border[4]; /**< Border: TOP, RIGHT, BOTTOM, LEFT. */
- int scroll_x; /**< Horizontal scroll of descendants. */
- int scroll_y; /**< Vertical scroll of descendants. */
+ struct scroll *scroll_x; /**< Horizontal scroll. */
+ struct scroll *scroll_y; /**< Vertical scroll. */
/** Width of box taking all line breaks (including margins etc). Must
* be non-negative. */
@@ -314,15 +314,10 @@ bool box_visible(struct box *box);
void box_dump(FILE *stream, struct box *box, unsigned int depth);
bool box_extract_link(const char *rel, const char *base, char **result);
+bool box_handle_scrollbars(struct box *box, int x, int y, bool bottom,
+ bool right);
bool box_vscrollbar_present(const struct box *box);
bool box_hscrollbar_present(const struct box *box);
-void box_scrollbar_dimensions(const struct box *box,
- int padding_width, int padding_height, int w,
- bool *vscroll, bool *hscroll,
- int *well_height,
- int *bar_top, int *bar_height,
- int *well_width,
- int *bar_left, int *bar_width);
bool xml_to_box(xmlNode *n, struct content *c);
diff --git a/render/form.c b/render/form.c
index 01e5e1d2f..968397a21 100644
--- a/render/form.c
+++ b/render/form.c
@@ -2,6 +2,7 @@
* Copyright 2004 James Bursa <bursa@users.sourceforge.net>
* Copyright 2003 Phil Mellor <monkeyson@users.sourceforge.net>
* Copyright 2005-9 John-Mark Bell <jmb@netsurf-browser.org>
+ * Copyright 2009 Paul Blokus <paul_pl@users.sourceforge.net>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
@@ -29,18 +30,60 @@
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
+#include "css/css.h"
+#include "css/utils.h"
+#include "desktop/gui.h"
+#include "desktop/knockout.h"
+#include "desktop/plot_style.h"
+#include "desktop/plotters.h"
+#include "desktop/scroll.h"
#include "render/box.h"
+#include "render/font.h"
#include "render/form.h"
+#include "render/layout.h"
#include "utils/log.h"
+#include "utils/messages.h"
#include "utils/url.h"
#include "utils/utf8.h"
#include "utils/utils.h"
+#define MAX_SELECT_HEIGHT 210
+#define SELECT_LINE_SPACING 0.2
+#define SELECT_BORDER_WIDTH 1
+#define SELECT_SELECTED_COLOUR 0xDB9370
+
+struct form_select_menu {
+ int line_height;
+ int width, height;
+ struct scroll *scroll;
+ int f_size;
+ bool scroll_capture;
+ select_menu_redraw_callback callback;
+ void *client_data;
+ struct browser_window *bw;
+};
+
+static plot_style_t plot_style_fill_selected = {
+ .fill_type = PLOT_OP_TYPE_SOLID,
+ .fill_colour = SELECT_SELECTED_COLOUR,
+};
+
+static plot_font_style_t plot_fstyle_entry = {
+ .family = PLOT_FONT_FAMILY_SANS_SERIF,
+ .weight = 400,
+ .flags = FONTF_NONE,
+ .background = 0xffffff,
+ .foreground = 0x000000,
+};
static char *form_textarea_value(struct form_control *textarea);
static char *form_acceptable_charset(struct form *form);
static char *form_encode_item(const char *item, const char *charset,
const char *fallback);
+static void form_select_menu_clicked(struct form_control *control,
+ int x, int y);
+static void form_select_menu_scroll_callback(void *client_data,
+ struct scroll_msg_data *scroll_data);
/**
* Create a struct form.
@@ -199,6 +242,8 @@ void form_free_control(struct form_control *control)
free(option->value);
free(option);
}
+ if (control->data.select.menu != NULL)
+ form_free_select_menu(control);
}
free(control);
@@ -812,3 +857,450 @@ char *form_encode_item(const char *item, const char *charset,
return ret;
}
+/**
+ * Open a select menu for a select form control, creating it if necessary.
+ *
+ * \param client_data data passed to the redraw callback
+ * \param control the select form control for which the menu is being
+ * opened
+ * \param callback redraw callback for the select menu
+ * \param bw the browser window in which the select menu is being
+ * opened
+ * \return false on memory exhaustion, true otherwise
+ */
+bool form_open_select_menu(void *client_data,
+ struct form_control *control,
+ select_menu_redraw_callback callback,
+ struct browser_window *bw)
+{
+ int i, line_height_with_spacing, scroll;
+ struct form_option *option;
+ struct box *box;
+ plot_font_style_t fstyle;
+ int total_height;
+ struct form_select_menu *menu;
+
+
+ /* if the menu is opened for the first time */
+ if (control->data.select.menu == NULL) {
+
+ menu = calloc(1, sizeof (struct form_select_menu));
+ if (menu == NULL) {
+ warn_user("NoMemory", 0);
+ return false;
+ }
+
+ control->data.select.menu = menu;
+
+ box = control->box;
+
+ menu->width = box->width +
+ box->border[RIGHT].width +
+ box->border[LEFT].width +
+ box->padding[RIGHT] + box->padding[LEFT];
+
+ font_plot_style_from_css(control->box->style,
+ &fstyle);
+ menu->f_size = fstyle.size;
+
+ menu->line_height =
+ FIXTOINT(FDIVI((FMUL(FLTTOFIX(1.2),
+ FMULI(nscss_screen_dpi,
+ (fstyle.size / FONT_SIZE_SCALE)))), 72));
+
+ line_height_with_spacing = menu->line_height +
+ menu->line_height *
+ SELECT_LINE_SPACING;
+
+ total_height = control->data.select.num_items *
+ line_height_with_spacing;
+ menu->height = total_height;
+
+ scroll = 0;
+ if (menu->height > MAX_SELECT_HEIGHT) {
+
+ menu->height = MAX_SELECT_HEIGHT;
+
+ if (control->data.select.num_selected > 0) {
+ i = 0;
+ option = control->data.select.items;
+ while (!option->selected) {
+ option = option->next;
+ i++;
+ }
+
+ if ((i + 1) * line_height_with_spacing >
+ MAX_SELECT_HEIGHT)
+ scroll = (i + 1) *
+ line_height_with_spacing
+ - MAX_SELECT_HEIGHT;
+ }
+ }
+ menu->client_data = client_data;
+ menu->callback = callback;
+ if (!scroll_create(false,
+ menu->height,
+ total_height,
+ menu->height,
+ control,
+ form_select_menu_scroll_callback,
+ &(menu->scroll))) {
+ free(menu);
+ return false;
+ }
+ menu->bw = bw;
+ }
+ else menu = control->data.select.menu;
+
+ menu->callback(client_data, 0, 0, menu->width, menu->height);
+
+ return true;
+}
+
+
+/**
+ * Destroy a select menu and free allocated memory.
+ *
+ * \param control the select form control owning the select menu being
+ * destroyed
+ */
+void form_free_select_menu(struct form_control *control)
+{
+ if (control->data.select.menu->scroll != NULL)
+ scroll_destroy(control->data.select.menu->scroll);
+ free(control->data.select.menu);
+ control->data.select.menu = NULL;
+}
+
+/**
+ * Redraw an opened select menu.
+ *
+ * \param control the select menu being redrawn
+ * \param x the X coordinate to draw the menu at
+ * \param x the Y coordinate to draw the menu at
+ * \param scale current redraw scale
+ * \param clip_x0 minimum x of clipping rectangle
+ * \param clip_y0 minimum y of clipping rectangle
+ * \param clip_x1 maximum x of clipping rectangle
+ * \param clip_y1 maximum y of clipping rectangle
+ * \return true on success, false otherwise
+ */
+bool form_redraw_select_menu(struct form_control *control, int x, int y,
+ float scale, int clip_x0, int clip_y0, int clip_x1, int clip_y1)
+{
+ struct box *box;
+ struct form_select_menu *menu = control->data.select.menu;
+ struct form_option *option;
+ int line_height, line_height_with_spacing;
+ int width, height;
+ int x0, y0, x1, scrollbar_x, y1, y2, y3;
+ int item_y;
+ int text_pos_offset, text_x;
+ int scrollbar_width = SCROLLBAR_WIDTH;
+ int i;
+ int scroll;
+ int x_cp, y_cp;
+
+ box = control->box;
+
+ x_cp = x;
+ y_cp = y;
+ width = menu->width;
+ height = menu->height;
+ line_height = menu->line_height;
+
+ line_height_with_spacing = line_height +
+ line_height * SELECT_LINE_SPACING;
+ scroll = scroll_get_offset(menu->scroll);
+
+ if (scale != 1.0) {
+ x *= scale;
+ y *= scale;
+ width *= scale;
+ height *= scale;
+ scrollbar_width *= scale;
+
+ i = scroll / line_height_with_spacing;
+ scroll -= i * line_height_with_spacing;
+ line_height *= scale;
+ line_height_with_spacing *= scale;
+ scroll *= scale;
+ scroll += i * line_height_with_spacing;
+ }
+
+
+ x0 = x;
+ y0 = y;
+ x1 = x + width - 1;
+ y1 = y + height - 1;
+ scrollbar_x = x1 - scrollbar_width;
+
+ if (!plot.clip(x0, y0, x1 + 1, y1 + 1))
+ return false;
+ if (!plot.rectangle(x0, y0, x1, y1 ,plot_style_stroke_darkwbasec))
+ return false;
+
+
+ x0 = x0 + SELECT_BORDER_WIDTH;
+ y0 = y0 + SELECT_BORDER_WIDTH;
+ x1 = x1 - SELECT_BORDER_WIDTH;
+ y1 = y1 - SELECT_BORDER_WIDTH;
+ height = height - 2 * SELECT_BORDER_WIDTH;
+
+ if (!plot.clip(x0, y0, x1 + 1, y1 + 1))
+ return false;
+ if (!plot.rectangle(x0, y0, x1 + 1, y1 + 1,
+ plot_style_fill_lightwbasec))
+ return false;
+ option = control->data.select.items;
+ item_y = line_height_with_spacing;
+
+ while (item_y < scroll) {
+ option = option->next;
+ item_y += line_height_with_spacing;
+ }
+ item_y -= line_height_with_spacing;
+ text_pos_offset = y - scroll +
+ (int) (line_height * (0.75 + SELECT_LINE_SPACING));
+ text_x = x + (box->border[LEFT].width + box->padding[LEFT]) * scale;
+
+ plot_fstyle_entry.size = menu->f_size;
+
+ while (option && item_y - scroll < height) {
+
+ if (option->selected) {
+ y2 = y + item_y - scroll;
+ y3 = y + item_y + line_height_with_spacing - scroll;
+ if (!plot.rectangle(x0, (y0 > y2 ? y0 : y2),
+ scrollbar_x + 1,
+ (y3 < y1 + 1 ? y3 : y1 + 1),
+ &plot_style_fill_selected))
+ return false;
+ }
+
+ y2 = text_pos_offset + item_y;
+ if (!plot.text(text_x, y2, option->text,
+ strlen(option->text), &plot_fstyle_entry))
+ return false;
+
+ item_y += line_height_with_spacing;
+ option = option->next;
+ }
+
+ if (!scroll_redraw(menu->scroll,
+ x_cp + menu->width - SCROLLBAR_WIDTH,
+ y_cp,
+ clip_x0, clip_y0, clip_x1, clip_y1, scale))
+ return false;
+
+ return true;
+}
+
+/**
+ * Check whether a clipping rectangle is completely contained in the
+ * select menu.
+ *
+ * \param control the select menu to check the clipping rectangle for
+ * \param scale the current browser window scale
+ * \param clip_x0 minimum x of clipping rectangle
+ * \param clip_y0 minimum y of clipping rectangle
+ * \param clip_x1 maximum x of clipping rectangle
+ * \param clip_y1 maximum y of clipping rectangle
+ * \return true if inside false otherwise
+ */
+bool form_clip_inside_select_menu(struct form_control *control, float scale,
+ int clip_x0, int clip_y0, int clip_x1, int clip_y1)
+{
+ struct form_select_menu *menu = control->data.select.menu;
+ int width, height;
+
+
+ width = menu->width;
+ height = menu->height;
+
+ if (scale != 1.0) {
+ width *= scale;
+ height *= scale;
+ }
+
+ if (clip_x0 >= 0 && clip_x1 <= width &&
+ clip_y0 >= 0 && clip_y1 <= height)
+ return true;
+
+ return false;
+}
+
+/**
+ * Handle a click on the area of the currently opened select menu.
+ *
+ * \param control the select menu which received the click
+ * \param x X coordinate of click
+ * \param y Y coordinate of click
+ */
+void form_select_menu_clicked(struct form_control *control, int x, int y)
+{
+ struct form_select_menu *menu = control->data.select.menu;
+ struct form_option *option;
+ int line_height, line_height_with_spacing;
+ int item_bottom_y;
+ int scroll, i;
+
+ scroll = scroll_get_offset(menu->scroll);
+
+ line_height = menu->line_height;
+ line_height_with_spacing = line_height +
+ line_height * SELECT_LINE_SPACING;
+
+ option = control->data.select.items;
+ item_bottom_y = line_height_with_spacing;
+ i = 0;
+ while (option && item_bottom_y < scroll + y) {
+ item_bottom_y += line_height_with_spacing;
+ option = option->next;
+ i++;
+ }
+
+ if (option != NULL)
+ browser_window_form_select(menu->bw, control, i);
+
+ menu->callback(menu->client_data, 0, 0, menu->width, menu->height);
+}
+
+/**
+ * Handle mouse action for the currently opened select menu.
+ *
+ * \param control the select menu which received the mouse action
+ * \param mouse current mouse state
+ * \param x X coordinate of click
+ * \param y Y coordinate of click
+ * \return text for the browser status bar or NULL if the menu has
+ * to be closed
+ */
+const char *form_select_mouse_action(struct form_control *control,
+ browser_mouse_state mouse, int x, int y)
+{
+ struct form_select_menu *menu = control->data.select.menu;
+ int x0, y0, x1, y1, scrollbar_x;
+ const char *status = NULL;
+ bool multiple = control->data.select.multiple;
+
+ x0 = 0;
+ y0 = 0;
+ x1 = menu->width;
+ y1 = menu->height;
+ scrollbar_x = x1 - SCROLLBAR_WIDTH;
+
+ if (menu->scroll_capture ||
+ (x > scrollbar_x && x < x1 && y > y0 && y < y1)) {
+ /* The scroll is currently capturing all events or the mouse
+ * event is taking place on the scrollbar widget area
+ */
+ x -= scrollbar_x;
+ return scroll_mouse_action(menu->scroll,
+ mouse, x, y);
+ }
+
+
+ if (x > x0 && x < scrollbar_x && y > y0 && y < y1) {
+ /* over option area */
+
+ if (mouse & (BROWSER_MOUSE_CLICK_1 | BROWSER_MOUSE_CLICK_2))
+ /* button 1 or 2 click */
+ form_select_menu_clicked(control, x, y);
+
+ if (!(mouse & BROWSER_MOUSE_CLICK_1 && !multiple))
+ /* anything but a button 1 click over a single select
+ menu */
+ status = messages_get(control->data.select.multiple ?
+ "SelectMClick" : "SelectClick");
+
+ } else if (!(mouse & (BROWSER_MOUSE_CLICK_1 | BROWSER_MOUSE_CLICK_2)))
+ /* if not a button 1 or 2 click*/
+ status = messages_get("SelectClose");
+
+ return status;
+}
+
+/**
+ * Handle mouse drag end for the currently opened select menu.
+ *
+ * \param control the select menu which received the mouse drag end
+ * \param mouse current mouse state
+ * \param x X coordinate of drag end
+ * \param y Y coordinate of drag end
+ */
+void form_select_mouse_drag_end(struct form_control *control,
+ browser_mouse_state mouse, int x, int y)
+{
+ int x0, y0, x1, y1;
+ struct form_select_menu *menu = control->data.select.menu;
+
+ if (menu->scroll_capture) {
+ x -= menu->width - SCROLLBAR_WIDTH;
+ scroll_mouse_drag_end(menu->scroll,
+ mouse, x, y);
+ return;
+ }
+
+ x0 = 0;
+ y0 = 0;
+ x1 = menu->width;
+ y1 = menu->height;
+
+
+ if (x > x0 && x < x1 - SCROLLBAR_WIDTH && y > y0 && y < y1)
+ /* handle drag end above the option area like a regular click */
+ form_select_menu_clicked(control, x, y);
+}
+
+/**
+ * Callback for the select menus scroll
+ */
+void form_select_menu_scroll_callback(void *client_data,
+ struct scroll_msg_data *scroll_data)
+{
+ struct form_control *control = client_data;
+ struct form_select_menu *menu = control->data.select.menu;
+
+ switch (scroll_data->msg) {
+ case SCROLL_MSG_REDRAW:
+ menu->callback(menu->client_data,
+ menu->width -
+ SCROLLBAR_WIDTH + scroll_data->x0,
+ scroll_data->y0,
+ scroll_data->x1 - scroll_data->x0,
+ scroll_data->y1 - scroll_data->y0);
+ break;
+ case SCROLL_MSG_MOVED:
+ menu->callback(menu->client_data,
+ 0, 0,
+ menu->width - SCROLLBAR_WIDTH,
+ menu->height);
+ break;
+ case SCROLL_MSG_SCROLL_START:
+ menu->scroll_capture = true;
+ gui_window_box_scroll_start(menu->bw->window,
+ scroll_data->x0, scroll_data->y0,
+ scroll_data->x1, scroll_data->y1);
+ break;
+ case SCROLL_MSG_SCROLL_FINISHED:
+ menu->scroll_capture = false;
+ break;
+ default:
+ break;
+ }
+}
+
+/**
+ * Get the dimensions of a select menu.
+ *
+ * \param control the select menu to get the dimensions of
+ * \param width gets updated to menu width
+ * \param height gets updated to menu height
+ */
+void form_select_get_dimensions(struct form_control *control,
+ int *width, int *height)
+{
+ *width = control->data.select.menu->width;
+ *height = control->data.select.menu->height;
+}
diff --git a/render/form.h b/render/form.h
index eaecf3411..a31c24975 100644
--- a/render/form.h
+++ b/render/form.h
@@ -1,6 +1,7 @@
/*
* Copyright 2003 Phil Mellor <monkeyson@users.sourceforge.net>
* Copyright 2003 James Bursa <bursa@users.sourceforge.net>
+ * Copyright 2009 Paul Blokus <paul_pl@users.sourceforge.net>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
@@ -25,11 +26,13 @@
#define _NETSURF_RENDER_FORM_H_
#include <stdbool.h>
+#include "desktop/browser.h"
#include "utils/config.h"
struct box;
struct form_control;
struct form_option;
+struct form_select_menu;
/** Form submit method. */
typedef enum {
@@ -105,6 +108,7 @@ struct form_control {
int num_selected;
/** Currently selected item, if num_selected == 1. */
struct form_option *current;
+ struct form_select_menu *menu;
} select;
} data;
@@ -129,6 +133,19 @@ struct form_successful_control {
struct form_successful_control *next; /**< Next in linked list. */
};
+/**
+ * Called by the select menu when it wants an area to be redrawn. The
+ * coordinates are menu origin relative.
+ *
+ * \param client_data data which was passed to form_open_select_menu
+ * \param x X coordinate of redraw rectangle
+ * \param y Y coordinate of redraw rectangle
+ * \param width width of redraw rectangle
+ * \param height height of redraw rectangle
+ */
+typedef void(*select_menu_redraw_callback)(void *client_data,
+ int x, int y, int width, int height);
+
struct form *form_new(void *node, const char *action, const char *target,
form_method method, const char *charset,
const char *doc_charset);
@@ -145,4 +162,21 @@ char *form_url_encode(struct form *form,
struct form_successful_control *control);
void form_free_successful(struct form_successful_control *control);
+bool form_open_select_menu(void *client_data,
+ struct form_control *control,
+ select_menu_redraw_callback redraw_callback,
+ struct browser_window *bw);
+void form_free_select_menu(struct form_control *control);
+bool form_redraw_select_menu(struct form_control *control, int x, int y,
+ float scale,
+ int clip_x0, int clip_y0, int clip_x1, int clip_y1);
+bool form_clip_inside_select_menu(struct form_control *control, float scale,
+ int clip_x0, int clip_y0, int clip_x1, int clip_y1);
+const char *form_select_mouse_action(struct form_control *control,
+ browser_mouse_state mouse, int x, int y);
+void form_select_mouse_drag_end(struct form_control *control,
+ browser_mouse_state mouse, int x, int y);
+void form_select_get_dimensions(struct form_control *control,
+ int *width, int *height);
+
#endif
diff --git a/render/html_redraw.c b/render/html_redraw.c
index 4a8d72bec..2f4fdf794 100644
--- a/render/html_redraw.c
+++ b/render/html_redraw.c
@@ -5,6 +5,7 @@
* Copyright 2005-2006 Adrian Lees <adrianl@users.sourceforge.net>
* Copyright 2006 Rob Kendrick <rjek@netsurf-browser.org>
* Copyright 2008 Michael Drake <tlsa@netsurf-browser.org>
+ * Copyright 2009 Paul Blokus <paul_pl@users.sourceforge.net>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
@@ -40,6 +41,7 @@
#include "desktop/textinput.h"
#include "desktop/options.h"
#include "desktop/print.h"
+#include "desktop/scroll.h"
#include "image/bitmap.h"
#include "render/box.h"
#include "render/font.h"
@@ -89,23 +91,9 @@ static bool html_redraw_text_decoration_inline(struct box *box, int x, int y,
float scale, colour colour, float ratio);
static bool html_redraw_text_decoration_block(struct box *box, int x, int y,
float scale, colour colour, float ratio);
-static bool html_redraw_scrollbars(struct box *box, float scale,
- int x, int y, int padding_width, int padding_height,
- colour background_colour);
bool html_redraw_debug = false;
-/** Overflow scrollbar colours
- *
- * Overflow scrollbar colours can be set by front end code to try to match
- * scrollbar colours used on the desktop.
- *
- * If a front end doesn't set scrollbar colours, these defaults are used.
- */
-colour css_scrollbar_fg_colour = 0x00d9d9d9; /* light grey */
-colour css_scrollbar_bg_colour = 0x006b6b6b; /* mid grey */
-colour css_scrollbar_arrow_colour = 0x00444444; /* dark grey */
-
/**
* Draw a CONTENT_HTML using the current set of plotters (plot).
*
@@ -131,7 +119,8 @@ bool html_redraw(struct content *c, int x, int y,
float scale, colour background_colour)
{
struct box *box;
- bool result, want_knockout;
+ bool result = true, want_knockout;
+ bool select, select_only;
plot_style_t pstyle_fill_bg = {
.fill_type = PLOT_OP_TYPE_SOLID,
.fill_colour = background_colour,
@@ -144,18 +133,53 @@ bool html_redraw(struct content *c, int x, int y,
if (want_knockout)
knockout_plot_start(&plot);
- /* clear to background colour */
- result = plot.clip(clip_x0, clip_y0, clip_x1, clip_y1);
-
- if (c->data.html.background_colour != NS_TRANSPARENT)
- pstyle_fill_bg.fill_colour = c->data.html.background_colour;
-
- result &= plot.rectangle(clip_x0, clip_y0, clip_x1, clip_y1, &pstyle_fill_bg);
-
- result &= html_redraw_box(box, x, y,
- clip_x0, clip_y0, clip_x1, clip_y1,
- scale, pstyle_fill_bg.fill_colour);
+ /* The select menu needs special treating because, when opened, it
+ * reaches beyond its layout box.
+ */
+ select = false;
+ select_only = false;
+ if (current_redraw_browser != NULL &&
+ current_redraw_browser->visible_select_menu != NULL) {
+ struct form_control *control =
+ current_redraw_browser->visible_select_menu;
+ select = true;
+ /* check if the redraw rectangle is completely inside of the
+ select menu */
+ select_only = form_clip_inside_select_menu(control, scale,
+ clip_x0, clip_y0, clip_x1, clip_y1);
+ }
+
+ if (!select_only) {
+ /* clear to background colour */
+ result = plot.clip(clip_x0, clip_y0, clip_x1, clip_y1);
+
+ if (c->data.html.background_colour != NS_TRANSPARENT)
+ pstyle_fill_bg.fill_colour =
+ c->data.html.background_colour;
+
+ result &= plot.rectangle(clip_x0, clip_y0, clip_x1, clip_y1,
+ &pstyle_fill_bg);
+
+ result &= html_redraw_box(box, x, y,
+ clip_x0, clip_y0, clip_x1, clip_y1,
+ scale, pstyle_fill_bg.fill_colour);
+ }
+ if (select) {
+ int menu_x, menu_y;
+ box = current_redraw_browser->visible_select_menu->box;
+ box_coords(box, &menu_x, &menu_y);
+
+ menu_x -= box->border[LEFT].width;
+ menu_y += box->height + box->border[BOTTOM].width +
+ box->padding[BOTTOM] + box->padding[TOP];
+ result &= form_redraw_select_menu(
+ current_redraw_browser->visible_select_menu,
+ x + menu_x, y + menu_y,
+ current_redraw_browser->scale,
+ clip_x0, clip_y0, clip_x1, clip_y1);
+ }
+
if (want_knockout)
knockout_plot_end();
@@ -195,6 +219,7 @@ bool html_redraw_box(struct box *box,
int x_scrolled, y_scrolled;
struct box *bg_box = NULL;
css_color bgcol = 0;
+ bool has_x_scroll, has_y_scroll;
if (html_redraw_printing && box->printed)
return true;
@@ -622,8 +647,8 @@ bool html_redraw_box(struct box *box,
return false;
if (box->object) {
- x_scrolled = x - box->scroll_x * scale;
- y_scrolled = y - box->scroll_y * scale;
+ x_scrolled = x - scroll_get_offset(box->scroll_x) * scale;
+ y_scrolled = y - scroll_get_offset(box->scroll_y) * scale;
if (!content_redraw(box->object,
x_scrolled + padding_left,
y_scrolled + padding_top,
@@ -664,23 +689,52 @@ bool html_redraw_box(struct box *box,
/* list marker */
if (box->list_marker)
if (!html_redraw_box(box->list_marker,
- x_parent + box->x - box->scroll_x,
- y_parent + box->y - box->scroll_y,
+ x_parent + box->x -
+ scroll_get_offset(box->scroll_x),
+ y_parent + box->y -
+ scroll_get_offset(box->scroll_y),
clip_x0, clip_y0, clip_x1, clip_y1,
scale, current_background_color))
return false;
/* scrollbars */
- if (box->style && box->type != BOX_BR && box->type != BOX_TABLE &&
- box->type != BOX_INLINE &&
+ if (current_redraw_browser && box->style && box->type != BOX_BR &&
+ box->type != BOX_TABLE && box->type != BOX_INLINE &&
(css_computed_overflow(box->style) ==
CSS_OVERFLOW_SCROLL ||
css_computed_overflow(box->style) ==
- CSS_OVERFLOW_AUTO))
- if (!html_redraw_scrollbars(box, scale, x, y,
- padding_width, padding_height,
- current_background_color))
+ CSS_OVERFLOW_AUTO)) {
+
+ has_x_scroll = false;
+ has_y_scroll = false;
+
+ has_x_scroll = box_hscrollbar_present(box);
+
+ has_y_scroll = box_vscrollbar_present(box);
+
+ if (!box_handle_scrollbars(box,
+ x_parent + box->x, y_parent + box->y,
+ has_x_scroll, has_y_scroll))
return false;
+
+ if (box->scroll_x != NULL)
+ scroll_redraw(box->scroll_x,
+ x_parent + box->x,
+ y_parent + box->y + box->padding[TOP] +
+ box->height + box->padding[BOTTOM] -
+ SCROLLBAR_WIDTH,
+ clip_x0, clip_y0, clip_x1, clip_y1,
+ scale);
+ if (box->scroll_y != NULL)
+ scroll_redraw(box->scroll_y,
+ x_parent + box->x + box->padding[LEFT] +
+ box->width + box->padding[RIGHT] -
+ SCROLLBAR_WIDTH,
+ y_parent + box->y,
+ clip_x0, clip_y0, clip_x1, clip_y1,
+ scale);
+ }
+
if (box->type == BOX_BLOCK || box->type == BOX_INLINE_BLOCK ||
box->type == BOX_TABLE_CELL || box->object)
@@ -717,16 +771,20 @@ bool html_redraw_box_children(struct box *box,
if (c->type != BOX_FLOAT_LEFT && c->type != BOX_FLOAT_RIGHT)
if (!html_redraw_box(c,
- x_parent + box->x - box->scroll_x,
- y_parent + box->y - box->scroll_y,
+ x_parent + box->x -
+ scroll_get_offset(box->scroll_x),
+ y_parent + box->y -
+ scroll_get_offset(box->scroll_y),
clip_x0, clip_y0, clip_x1, clip_y1,
scale, current_background_color))
return false;
}
for (c = box->float_children; c; c = c->next_float)
if (!html_redraw_box(c,
- x_parent + box->x - box->scroll_x,
- y_parent + box->y - box->scroll_y,
+ x_parent + box->x -
+ scroll_get_offset(box->scroll_x),
+ y_parent + box->y -
+ scroll_get_offset(box->scroll_y),
clip_x0, clip_y0, clip_x1, clip_y1,
scale, current_background_color))
return false;
@@ -1957,319 +2015,3 @@ bool html_redraw_text_decoration_block(struct box *box, int x, int y,
}
return true;
}
-
-static inline bool
-html_redraw_scrollbar_rectangle(int x0, int y0, int x1, int y1, colour c,
- bool inset)
-{
- static plot_style_t c0 = {
- .stroke_type = PLOT_OP_TYPE_SOLID,
- .stroke_width = 1,
- };
-
- static plot_style_t c1 = {
- .stroke_type = PLOT_OP_TYPE_SOLID,
- .stroke_width = 1,
- };
-
- static plot_style_t c2 = {
- .stroke_type = PLOT_OP_TYPE_SOLID,
- .stroke_width = 1,
- };
-
- if (inset) {
- c0.stroke_colour = darken_colour(c);
- c1.stroke_colour = lighten_colour(c);
- } else {
- c0.stroke_colour = lighten_colour(c);
- c1.stroke_colour = darken_colour(c);
- }
- c2.stroke_colour = blend_colour(c0.stroke_colour, c1.stroke_colour);
-
- if (!plot.line(x0, y0, x1, y0, &c0)) return false;
- if (!plot.line(x1, y0, x1, y1 + 1, &c1)) return false;
- if (!plot.line(x1, y0, x1, y0 + 1, &c2)) return false;
- if (!plot.line(x1, y1, x0, y1, &c1)) return false;
- if (!plot.line(x0, y1, x0, y0, &c0)) return false;
- if (!plot.line(x0, y1, x0, y1 + 1, &c2)) return false;
- return true;
-}
-
-/**
- * Plot scrollbars for a scrolling box.
- *
- * \param box scrolling box
- * \param scale scale for redraw
- * \param x coordinate of box
- * \param y coordinate of box
- * \param padding_width width of padding box
- * \param padding_height height of padding box
- * \return true if successful, false otherwise
- */
-
-bool html_redraw_scrollbars(struct box *box, float scale,
- int x, int y, int padding_width, int padding_height,
- colour background_colour)
-{
- const int w = SCROLLBAR_WIDTH * scale;
- bool vscroll, hscroll;
- int well_height, bar_top, bar_height;
- int well_width, bar_left, bar_width;
- int v[6]; /* array of triangle vertices */
- plot_style_t pstyle_css_scrollbar_bg_colour = {
- .fill_type = PLOT_OP_TYPE_SOLID,
- .fill_colour = css_scrollbar_bg_colour,
- };
- plot_style_t pstyle_css_scrollbar_fg_colour = {
- .fill_type = PLOT_OP_TYPE_SOLID,
- .fill_colour = css_scrollbar_fg_colour,
- };
- plot_style_t pstyle_css_scrollbar_arrow_colour = {
- .fill_type = PLOT_OP_TYPE_SOLID,
- .fill_colour = css_scrollbar_arrow_colour,
- };
-
- box_scrollbar_dimensions(box, padding_width, padding_height, w,
- &vscroll, &hscroll,
- &well_height, &bar_top, &bar_height,
- &well_width, &bar_left, &bar_width);
-
-
- /* horizontal scrollbar */
- if (hscroll) {
- /* scrollbar outline */
- if (!html_redraw_scrollbar_rectangle(x,
- y + padding_height - w,
- x + padding_width - 1,
- y + padding_height - 1,
- css_scrollbar_bg_colour, true))
- return false;
- /* left arrow icon border */
- if (!html_redraw_scrollbar_rectangle(x + 1,
- y + padding_height - w + 1,
- x + w - 2,
- y + padding_height - 2,
- css_scrollbar_fg_colour, false))
- return false;
- /* left arrow icon background */
- if (!plot.rectangle(x + 2,
- y + padding_height - w + 2,
- x + w - 2,
- y + padding_height - 2,
- &pstyle_css_scrollbar_fg_colour))
- return false;
- /* left arrow */
- v[0] = x + w / 4;
- v[1] = y + padding_height - w / 2;
- v[2] = x + w * 3 / 4;
- v[3] = y + padding_height - w * 3 / 4;
- v[4] = x + w * 3 / 4;
- v[5] = y + padding_height - w / 4;
- if (!plot.polygon(v, 3, &pstyle_css_scrollbar_arrow_colour))
- return false;
- /* scroll well background */
- if (!plot.rectangle(x + w - 1,
- y + padding_height - w + 1,
- x + w + well_width + (vscroll ? 2 : 1),
- y + padding_height - 1,
- &pstyle_css_scrollbar_bg_colour))
- return false;
- /* scroll position indicator bar */
- if (!html_redraw_scrollbar_rectangle(x + w + bar_left,
- y + padding_height - w + 1,
- x + w + bar_left + bar_width + (vscroll? 1 : 0),
- y + padding_height - 2,
- css_scrollbar_fg_colour, false))
- return false;
- if (!plot.rectangle(x + w + bar_left + 1,
- y + padding_height - w + 2,
- x + w + bar_left + bar_width + (vscroll? 1 : 0),
- y + padding_height - 2,
- &pstyle_css_scrollbar_fg_colour))
- return false;
- /* right arrow icon border */
- if (!html_redraw_scrollbar_rectangle(x + w + well_width + 2,
- y + padding_height - w + 1,
- x + w + well_width + w - (vscroll ? 1 : 2),
- y + padding_height - 2,
- css_scrollbar_fg_colour, false))
- return false;
- /* right arrow icon background */
- if (!plot.rectangle(x + w + well_width + 3,
- y + padding_height - w + 2,
- x + w + well_width + w - (vscroll ? 1 : 2),
- y + padding_height - 2,
- &pstyle_css_scrollbar_fg_colour))
- return false;
- /* right arrow */
- v[0] = x + w + well_width + w * 3 / 4 + (vscroll ? 1 : 0);
- v[1] = y + padding_height - w / 2;
- v[2] = x + w + well_width + w / 4 + (vscroll ? 1 : 0);
- v[3] = y + padding_height - w * 3 / 4;
- v[4] = x + w + well_width + w / 4 + (vscroll ? 1 : 0);
- v[5] = y + padding_height - w / 4;
- if (!plot.polygon(v, 3, &pstyle_css_scrollbar_arrow_colour))
- return false;
- }
-
- /* vertical scrollbar */
- if (vscroll) {
- /* outline */
- if (!html_redraw_scrollbar_rectangle(x + padding_width - w,
- y,
- x + padding_width - 1,
- y + padding_height - 1,
- css_scrollbar_bg_colour,
- true))
- return false;
- /* top arrow background */
- if (!html_redraw_scrollbar_rectangle(x + padding_width - w + 1,
- y + 1,
- x + padding_width - 2,
- y + w - 2,
- css_scrollbar_fg_colour,
- false))
- return false;
- if (!plot.rectangle(x + padding_width - w + 2,
- y + 2,
- x + padding_width - 2,
- y + w - 2,
- &pstyle_css_scrollbar_fg_colour))
- return false;
- /* up arrow */
- v[0] = x + padding_width - w / 2;
- v[1] = y + w / 4;
- v[2] = x + padding_width - w * 3 / 4;
- v[3] = y + w * 3 / 4;
- v[4] = x + padding_width - w / 4;
- v[5] = y + w * 3 / 4;
- if (!plot.polygon(v, 3, &pstyle_css_scrollbar_arrow_colour))
- return false;
- /* scroll well background */
- if (!plot.rectangle(x + padding_width - w + 1,
- y + w - 1,
- x + padding_width - 1,
- y + padding_height - w + 1,
- &pstyle_css_scrollbar_bg_colour))
- return false;
- /* scroll position indicator bar */
- if (!html_redraw_scrollbar_rectangle(x + padding_width - w + 1,
- y + w + bar_top,
- x + padding_width - 2,
- y + w + bar_top + bar_height,
- css_scrollbar_fg_colour, false))
- return false;
- if (!plot.rectangle(x + padding_width - w + 2,
- y + w + bar_top + 1,
- x + padding_width - 2,
- y + w + bar_top + bar_height,
- &pstyle_css_scrollbar_fg_colour))
- return false;
- /* bottom arrow background */
- if (!html_redraw_scrollbar_rectangle(x + padding_width - w + 1,
- y + padding_height - w + 1,
- x + padding_width - 2,
- y + padding_height - 2,
- css_scrollbar_fg_colour, false))
- return false;
- if (!plot.rectangle(x + padding_width - w + 2,
- y + padding_height - w + 2,
- x + padding_width - 2,
- y + padding_height - 2,
- &pstyle_css_scrollbar_fg_colour))
- return false;
- /* down arrow */
- v[0] = x + padding_width - w / 2;
- v[1] = y + w + well_height + w * 3 / 4;
- v[2] = x + padding_width - w * 3 / 4;
- v[3] = y + w + well_height + w / 4;
- v[4] = x + padding_width - w / 4;
- v[5] = y + w + well_height + w / 4;
- if (!plot.polygon(v, 3, &pstyle_css_scrollbar_arrow_colour))
- return false;
- }
-
- return true;
-}
-
-
-/**
- * Determine if a box has a vertical scrollbar.
- *
- * \param box scrolling box
- * \return the box has a vertical scrollbar
- */
-
-bool box_vscrollbar_present(const struct box * const box)
-{
- return box->descendant_y0 < -box->border[TOP].width ||
- box->padding[TOP] + box->height + box->padding[BOTTOM] +
- box->border[BOTTOM].width < box->descendant_y1;
-}
-
-
-/**
- * Determine if a box has a horizontal scrollbar.
- *
- * \param box scrolling box
- * \return the box has a horizontal scrollbar
- */
-
-bool box_hscrollbar_present(const struct box * const box)
-{
- return box->descendant_x0 < -box->border[LEFT].width ||
- box->padding[LEFT] + box->width + box->padding[RIGHT] +
- box->border[RIGHT].width < box->descendant_x1;
-}
-
-
-/**
- * Calculate scrollbar dimensions and positions for a box.
- *
- * \param box scrolling box
- * \param padding_width scaled width of padding box
- * \param padding_height scaled height of padding box
- * \param w scaled scrollbar width
- * \param vscroll updated to vertical scrollbar present
- * \param hscroll updated to horizontal scrollbar present
- * \param well_height updated to vertical well height
- * \param bar_top updated to top position of vertical scrollbar
- * \param bar_height updated to height of vertical scrollbar
- * \param well_width updated to horizontal well width
- * \param bar_left updated to left position of horizontal scrollbar
- * \param bar_width updated to width of horizontal scrollbar
- */
-
-void box_scrollbar_dimensions(const struct box * const box,
- const int padding_width, const int padding_height, const int w,
- bool * const vscroll, bool * const hscroll,
- int * const well_height,
- int * const bar_top, int * const bar_height,
- int * const well_width,
- int * const bar_left, int * const bar_width)
-{
- *vscroll = box_vscrollbar_present(box);
- *hscroll = box_hscrollbar_present(box);
- *well_height = padding_height - w - w;
- *bar_top = 0;
- *bar_height = *well_height;
- if (box->descendant_y1 - box->descendant_y0 != 0) {
- *bar_top = (float) *well_height * (float) box->scroll_y /
- (float) (box->descendant_y1 -
- box->descendant_y0);
- *bar_height = (float) *well_height * (float) box->height /
- (float) (box->descendant_y1 -
- box->descendant_y0);
- }
- *well_width = padding_width - w - w - (*vscroll ? w : 0);
- *bar_left = 0;
- *bar_width = *well_width;
- if (box->descendant_x1 - box->descendant_x0 != 0) {
- *bar_left = (float) *well_width * (float) box->scroll_x /
- (float) (box->descendant_x1 -
- box->descendant_x0);
- *bar_width = (float) *well_width * (float) box->width /
- (float) (box->descendant_x1 -
- box->descendant_x0);
- }
-}
diff --git a/render/layout.c b/render/layout.c
index 3ba9b038d..f2c0c158e 100644
--- a/render/layout.c
+++ b/render/layout.c
@@ -44,6 +44,7 @@
#include "content/content.h"
#include "desktop/gui.h"
#include "desktop/options.h"
+#include "desktop/scroll.h"
#include "render/box.h"
#include "render/font.h"
#include "render/form.h"
@@ -1989,8 +1990,9 @@ bool layout_line(struct box *first, int *width, int *y,
if (opt_maxwidth < opt_width)
opt_maxwidth =opt_width;
}
-
b->width = opt_maxwidth;
+ if (option_core_select_menu)
+ b->width += SCROLLBAR_WIDTH;
} else {
font_func->font_width(&fstyle, b->text,
b->length, &b->width);
@@ -2624,6 +2626,9 @@ struct box *layout_minmax_line(struct box *first,
}
b->width = opt_maxwidth;
+ if (option_core_select_menu)
+ b->width += SCROLLBAR_WIDTH;
+
} else {
font_func->font_width(&fstyle, b->text,
b->length, &b->width);
diff --git a/render/layout.h b/render/layout.h
index 2d07a40e9..30d9757f6 100644
--- a/render/layout.h
+++ b/render/layout.h
@@ -27,8 +27,6 @@
#ifndef _NETSURF_RENDER_LAYOUT_H_
#define _NETSURF_RENDER_LAYOUT_H_
-#define SCROLLBAR_WIDTH 16
-
struct box;
bool layout_document(struct content *content, int width, int height);