[project @ 2004-07-17 23:32:08 by bursa]

Rewrite and simplify mouse click handling.

svn path=/import/netsurf/; revision=1094
This commit is contained in:
James Bursa 2004-07-17 23:32:09 +00:00
parent a9aef8bf60
commit f23fd2a094
11 changed files with 519 additions and 496 deletions

View File

@ -108,6 +108,15 @@ Form_Reset:Reset
Form_None:
Form_Many:(Many)
Form_Drop:Drop file here
FormSelect:Click to choose a form item
FormCheckbox:Click to check this option
FormRadio:Click to choose this option
FormSubmit:Send form to %s
FormBadSubmit:Warning: form can not be submitted
FormTextarea:Click to edit the text
FormTextbox:Click to edit this field
FormReset:Reset form (not implemented)
FormFile:Drop a file here to upload it
Not2xx:Server returned an error

View File

@ -108,6 +108,15 @@ Form_Reset:Effacer
Form_None:
Form_Many:(Plusieurs)
Form_Drop:Déposer les fichiers ici
FormSelect:Click to choose a form item
FormCheckbox:Click to check this option
FormRadio:Click to choose this option
FormSubmit:Send form to %s
FormBadSubmit:Warning: form can not be submitted
FormTextarea:Click to edit the text
FormTextbox:Click to edit this field
FormReset:Reset form (not implemented)
FormFile:Drop a file here to upload it
Not2xx:Le serveur a renvoyé une erreur

View File

@ -49,6 +49,8 @@ static void browser_window_set_status(struct browser_window *bw,
static void browser_window_set_pointer(gui_pointer_shape shape);
static void download_window_callback(fetch_msg msg, void *p, const char *data,
unsigned long size);
static void browser_window_mouse_click_html(struct browser_window *bw,
browser_mouse_click click, int x, int y);
static void browser_window_text_selection(struct browser_window* bw,
unsigned long click_x, unsigned long click_y, int click_type);
@ -58,13 +60,9 @@ static int redraw_box_list(struct browser_window* bw, struct box* current,
unsigned long x, unsigned long y, struct box_position* start,
struct box_position* end, int* plot);
static void browser_window_redraw_boxes(struct browser_window* bw, struct box_position* start, struct box_position* end);
static void browser_window_follow_link(struct browser_window* bw,
unsigned long click_x, unsigned long click_y, int click_type);
static void clear_radio_gadgets(struct browser_window* bw, struct box* box, struct form_control* group);
static void gui_redraw_gadget2(struct browser_window* bw, struct box* box, struct form_control* g,
unsigned long x, unsigned long y);
static void browser_window_gadget_select(struct browser_window* bw, struct form_control* g, int item);
static int browser_window_gadget_click(struct browser_window* bw, unsigned long click_x, unsigned long click_y);
static void browser_form_submit(struct browser_window *bw, struct form *form,
struct form_control *submit_button);
static void browser_window_textarea_click(struct browser_window* bw,
@ -533,6 +531,204 @@ void download_window_callback(fetch_msg msg, void *p, const char *data,
}
/**
* Handle mouse clicks in a browser window.
*
* \param bw browser window
* \param click type of mouse click
* \param x coordinate of mouse
* \param y coordinate of mouse
*/
void browser_window_mouse_click(struct browser_window *bw,
browser_mouse_click click, int x, int y)
{
if (!bw->current_content)
return;
if (bw->current_content->type == CONTENT_HTML)
browser_window_mouse_click_html(bw, click, x, y);
}
/**
* Handle mouse clicks in an HTML content window.
*
* \param bw browser window
* \param click type of mouse click
* \param x coordinate of mouse
* \param y coordinate of mouse
*/
void browser_window_mouse_click_html(struct browser_window *bw,
browser_mouse_click click, int x, int y)
{
struct content *c = bw->current_content;
struct box *box = c->data.html.layout;
int box_x = 0, box_y = 0;
struct content *content = c;
struct content *gadget_content = c;
char *base_url = 0;
char *href = 0;
char *title = 0;
struct form_control *gadget = 0;
const char *status = 0;
char status_buffer[200];
gui_pointer_shape pointer = GUI_POINTER_DEFAULT;
char *url;
/* search the box tree for a link, imagemap, or form control */
while ((box = box_at_point(box, x, y, &box_x, &box_y, &content))) {
if (box->style &&
box->style->visibility == CSS_VISIBILITY_HIDDEN)
continue;
if (box->href) {
base_url = content->data.html.base_url;
href = box->href;
}
if (box->usemap) {
base_url = content->data.html.base_url;
href = imagemap_get(content, box->usemap,
box_x, box_y, x, y);
}
if (box->gadget) {
gadget_content = content;
base_url = content->data.html.base_url;
gadget = box->gadget;
}
if (box->title)
title = box->title;
if (box->style && box->style->cursor != CSS_CURSOR_UNKNOWN)
pointer = get_pointer_shape(box->style->cursor);
}
if (gadget) {
switch (gadget->type) {
case GADGET_SELECT:
status = messages_get("FormSelect");
pointer = GUI_POINTER_MENU;
if (click == BROWSER_MOUSE_CLICK_1)
gui_create_form_select_menu(bw, gadget);
break;
case GADGET_CHECKBOX:
status = messages_get("FormCheckbox");
if (click == BROWSER_MOUSE_CLICK_1) {
gadget->selected = !gadget->selected;
gui_redraw_gadget(bw, gadget);
}
break;
case GADGET_RADIO:
status = messages_get("FormRadio");
if (click == BROWSER_MOUSE_CLICK_1) {
clear_radio_gadgets(bw,
gadget_content->data.html.
layout, gadget);
gadget->selected = true;
gui_redraw_gadget(bw, gadget);
}
break;
case GADGET_IMAGE:
if (click == BROWSER_MOUSE_CLICK_1) {
gadget->data.image.mx = x - box_x;
gadget->data.image.my = y - box_y;
}
/* drop through */
case GADGET_SUBMIT:
if (gadget->form) {
url = url_join(gadget->form->action, base_url);
snprintf(status_buffer, sizeof status_buffer,
messages_get("FormSubmit"),
url ? url :
gadget->form->action);
status = status_buffer;
pointer = GUI_POINTER_POINT;
if (click == BROWSER_MOUSE_CLICK_1)
browser_form_submit(bw, gadget->form,
gadget);
} else {
status = messages_get("FormBadSubmit");
}
break;
case GADGET_TEXTAREA:
status = messages_get("FormTextarea");
pointer = GUI_POINTER_CARET;
if (click == BROWSER_MOUSE_CLICK_1)
browser_window_textarea_click(bw,
box_x, box_y,
x - box_x, y - box_y,
box);
break;
case GADGET_TEXTBOX:
case GADGET_PASSWORD:
status = messages_get("FormTextbox");
pointer = GUI_POINTER_CARET;
if (click == BROWSER_MOUSE_CLICK_1)
browser_window_input_click(bw,
box_x, box_y,
x - box_x, y - box_y,
box);
break;
case GADGET_HIDDEN:
/* not possible: no box generated */
break;
case GADGET_RESET:
status = messages_get("FormReset");
break;
case GADGET_FILE:
status = messages_get("FormFile");
break;
}
} else if (href) {
url = url_join(href, base_url);
if (!url)
return;
if (title) {
snprintf(status_buffer, sizeof status_buffer, "%s: %s",
title, url);
status = status_buffer;
} else
status = url;
pointer = GUI_POINTER_POINT;
if (click == BROWSER_MOUSE_CLICK_1 ||
click == BROWSER_MOUSE_CLICK_2) {
if (fetch_can_fetch(url)) {
if (click == BROWSER_MOUSE_CLICK_1)
browser_window_go(bw, url);
else
browser_window_create(url, bw);
} else {
gui_launch_url(url);
}
}
} else if (title) {
status = title;
} else {
if (bw->loading_content)
status = bw->loading_content->status_message;
else
status = c->status_message;
}
assert(status);
browser_window_set_status(bw, status);
browser_window_set_pointer(pointer);
}
void clear_radio_gadgets(struct browser_window *bw, struct box *box,
struct form_control *group)
{
@ -587,138 +783,8 @@ void gui_redraw_gadget(struct browser_window* bw, struct form_control* g)
gui_redraw_gadget2(bw, bw->current_content->data.html.layout->children, g, 0, 0);
}
void browser_window_gadget_select(struct browser_window* bw, struct form_control* g, int item)
{
struct form_option* o;
int count;
struct box *inline_box = g->box->children->children;
int x, y;
for (count = 0, o = g->data.select.items;
o != NULL;
count++, o = o->next) {
if (!g->data.select.multiple)
o->selected = false;
if (count == item) {
if (g->data.select.multiple) {
if (o->selected) {
o->selected = false;
g->data.select.num_selected--;
} else {
o->selected = true;
g->data.select.num_selected++;
}
} else {
o->selected = true;
}
}
if (o->selected)
g->data.select.current = o;
}
xfree(inline_box->text);
if (g->data.select.num_selected == 0)
inline_box->text = xstrdup(messages_get("Form_None"));
else if (g->data.select.num_selected == 1)
inline_box->text = xstrdup(g->data.select.current->text);
else
inline_box->text = xstrdup(messages_get("Form_Many"));
inline_box->width = g->box->width;
inline_box->length = strlen(inline_box->text);
box_coords(g->box, &x, &y);
gui_window_redraw(bw->window, (unsigned int)x, (unsigned int)y,
(unsigned int)(x + g->box->width),
(unsigned int)(y + g->box->height));
}
int browser_window_gadget_click(struct browser_window* bw, unsigned long click_x, unsigned long click_y)
{
struct box_selection* click_boxes;
int found, plot_index;
int i;
int x, y;
found = 0;
click_boxes = NULL;
plot_index = 0;
assert(bw->current_content->type == CONTENT_HTML);
box_under_area(bw->current_content,
bw->current_content->data.html.layout->children,
click_x, click_y, 0, 0, &click_boxes, &found, &plot_index);
if (found == 0)
return 0;
for (i = found - 1; i >= 0; i--)
{
if (click_boxes[i].box->style->visibility == CSS_VISIBILITY_HIDDEN)
continue;
if (click_boxes[i].box->gadget)
{
struct form_control* g = click_boxes[i].box->gadget;
/* gadget clicked */
switch (g->type)
{
case GADGET_SELECT:
gui_gadget_combo(bw, g, click_x, click_y);
break;
case GADGET_CHECKBOX:
g->selected = !g->selected;
gui_redraw_gadget(bw, g);
break;
case GADGET_RADIO:
clear_radio_gadgets(bw, click_boxes[i].content->data.html.layout->children, g);
g->selected = true;
gui_redraw_gadget(bw, g);
break;
case GADGET_SUBMIT:
if (g->form)
browser_form_submit(bw, g->form, g);
break;
case GADGET_TEXTAREA:
browser_window_textarea_click(bw,
(unsigned int)click_boxes[i].actual_x,
(unsigned int)click_boxes[i].actual_y,
(int)(click_x - click_boxes[i].actual_x),
(int)(click_y - click_boxes[i].actual_y),
click_boxes[i].box);
break;
case GADGET_TEXTBOX:
case GADGET_PASSWORD:
browser_window_input_click(bw,
(unsigned int)click_boxes[i].actual_x,
(unsigned int)click_boxes[i].actual_y,
click_x - click_boxes[i].actual_x,
click_y - click_boxes[i].actual_y,
click_boxes[i].box);
break;
case GADGET_HIDDEN:
break;
case GADGET_IMAGE:
box_coords(click_boxes[i].box, &x, &y);
g->data.image.mx = click_x - x;
g->data.image.my = click_y - y;
if (g->form)
browser_form_submit(bw, g->form, g);
break;
case GADGET_RESET:
break;
case GADGET_FILE:
break;
}
xfree(click_boxes);
return 1;
}
}
xfree(click_boxes);
return 0;
}
/**
@ -1342,46 +1408,66 @@ bool browser_window_key_press(struct browser_window *bw, char key)
}
int browser_window_action(struct browser_window *bw,
struct browser_action *act)
/**
* Process a selection from a form select menu.
*
* \param bw browser window with menu
* \param control form control with menu
* \param item index of item selected from the menu
*/
void browser_window_form_select(struct browser_window *bw,
struct form_control *control, int item)
{
switch (act->type) {
case act_MOUSE_AT:
browser_window_follow_link(bw, act->data.mouse.x,
act->data.mouse.y, 0);
break;
case act_MOUSE_CLICK:
return browser_window_gadget_click(bw, act->data.mouse.x,
act->data.mouse.y);
break;
case act_CLEAR_SELECTION:
// browser_window_text_selection(bw, act->data.mouse.x,
// act->data.mouse.y, 0);
break;
case act_START_NEW_SELECTION:
// browser_window_text_selection(bw, act->data.mouse.x,
// act->data.mouse.y, 1);
break;
case act_ALTER_SELECTION:
// browser_window_text_selection(bw, act->data.mouse.x,
// act->data.mouse.y, 2);
break;
case act_FOLLOW_LINK:
browser_window_follow_link(bw, act->data.mouse.x,
act->data.mouse.y, 1);
break;
case act_FOLLOW_LINK_NEW_WINDOW:
browser_window_follow_link(bw, act->data.mouse.x,
act->data.mouse.y, 2);
break;
case act_GADGET_SELECT:
browser_window_gadget_select(bw, act->data.gadget_select.g,
act->data.gadget_select.item);
default:
break;
struct form_option *o;
int count;
struct box *inline_box = control->box->children->children;
int x, y;
for (count = 0, o = control->data.select.items;
o != NULL;
count++, o = o->next) {
if (!control->data.select.multiple)
o->selected = false;
if (count == item) {
if (control->data.select.multiple) {
if (o->selected) {
o->selected = false;
control->data.select.num_selected--;
} else {
o->selected = true;
control->data.select.num_selected++;
}
return 0;
} else {
o->selected = true;
}
}
if (o->selected)
control->data.select.current = o;
}
free(inline_box->text);
inline_box->text = 0;
if (control->data.select.num_selected == 0)
inline_box->text = strdup(messages_get("Form_None"));
else if (control->data.select.num_selected == 1)
inline_box->text = strdup(control->data.select.current->text);
else
inline_box->text = strdup(messages_get("Form_Many"));
if (!inline_box->text) {
warn_user("NoMemory", 0);
inline_box->length = 0;
} else
inline_box->length = strlen(inline_box->text);
inline_box->width = control->box->width;
box_coords(control->box, &x, &y);
gui_window_redraw(bw->window, x, y,
x + control->box->width, y + control->box->height);
}
void box_under_area(struct content *content, struct box *box,
unsigned long x, unsigned long y,
@ -1471,170 +1557,6 @@ gui_pointer_shape get_pointer_shape(css_cursor cursor) {
return pointer;
}
void browser_window_follow_link(struct browser_window *bw,
unsigned long click_x,
unsigned long click_y, int click_type)
{
struct box_selection *click_boxes;
int found, plot_index;
int i;
int done = 0;
struct css_style *style;
gui_pointer_shape pointer = GUI_POINTER_DEFAULT;
found = 0;
click_boxes = NULL;
plot_index = 0;
if (bw->current_content->type != CONTENT_HTML)
return;
box_under_area(bw->current_content,
bw->current_content->data.html.layout->children,
click_x, click_y, 0, 0, &click_boxes, &found,
&plot_index);
if (found == 0)
return;
for (i = found - 1; i >= 0; i--) {
style = click_boxes[i].box->style;
if (style != 0 && style->visibility == CSS_VISIBILITY_HIDDEN)
continue;
if (click_boxes[i].box->href != NULL) {
char *url =
url_join((char *) click_boxes[i].box->href,
click_boxes[i].content->data.html.
base_url);
if (!url)
continue;
if (click_type == 1) {
if (fetch_can_fetch(url)) {
browser_window_go(bw, url);
}
else {
gui_launch_url(url);
done = 1;
}
} else if (click_type == 2) {
if (fetch_can_fetch(url)) {
browser_window_create(url, bw);
}
else {
gui_launch_url(url);
done = 1;
}
} else if (click_type == 0) {
browser_window_set_status(bw, url);
pointer = GUI_POINTER_POINT;
done = 1;
}
free(url);
break;
}
if (click_boxes[i].box->usemap != NULL) {
char *href, *url;
href = imagemap_get(click_boxes[i].content,
click_boxes[i].box->usemap,
click_boxes[i].actual_x,
click_boxes[i].actual_y,
click_x, click_y);
if (!href)
continue;
url = url_join(href,
click_boxes[i].content->data.html.
base_url);
if (!url)
continue;
if (click_type == 1) {
if (fetch_can_fetch(url)) {
browser_window_go(bw, url);
}
else {
gui_launch_url(url);
done = 1;
}
} else if (click_type == 2) {
if (fetch_can_fetch(url)) {
browser_window_create(url, NULL);
}
else {
gui_launch_url(url);
done = 1;
}
} else if (click_type == 0) {
browser_window_set_status(bw, url);
pointer = GUI_POINTER_POINT;
done = 1;
}
free(url);
break;
}
if (click_type == 0 && click_boxes[i].box->gadget != NULL) {
if (click_boxes[i].box->gadget->type == GADGET_TEXTBOX ||
click_boxes[i].box->gadget->type == GADGET_TEXTAREA ||
click_boxes[i].box->gadget->type == GADGET_PASSWORD) {
pointer = GUI_POINTER_CARET;
done = 1;
break;
}
else if (click_boxes[i].box->gadget->type == GADGET_SELECT) {
pointer = GUI_POINTER_MENU;
done = 1;
break;
}
else if (click_boxes[i].box->gadget->type == GADGET_SUBMIT || click_boxes[i].box->gadget->type == GADGET_IMAGE) {
struct form *form;
char *url, *href;
form = click_boxes[i].box->gadget->form;
if (!form) continue;
href = form->action;
if (!href) continue;
url = url_join(href, click_boxes[i].content->data.html.base_url);
if (!url) continue;
browser_window_set_status(bw, url);
free(url);
done = 1;
break;
}
}
if (click_type == 0 && click_boxes[i].box->title != NULL) {
browser_window_set_status(bw,
click_boxes[i].box->
title);
done = 1;
break;
}
if (click_type == 0 && style != 0 &&
style->cursor != CSS_CURSOR_UNKNOWN &&
pointer == GUI_POINTER_DEFAULT) {
pointer = get_pointer_shape(click_boxes[i].box->style->cursor);
}
}
if (click_type == 0 && done == 0) {
if (bw->loading_content != 0) {
browser_window_set_status(bw,
bw->loading_content->
status_message);
}
else {
browser_window_set_status(bw,
bw->current_content->
status_message);
}
}
browser_window_set_pointer(pointer);
free(click_boxes);
return;
}
void browser_window_text_selection(struct browser_window *bw,
unsigned long click_x,

View File

@ -53,25 +53,12 @@ struct browser_window
};
struct browser_action
{
enum { act_UNKNOWN,
act_MOUSE_AT, act_MOUSE_CLICK, act_START_NEW_SELECTION,
act_ALTER_SELECTION, act_CLEAR_SELECTION,
act_FOLLOW_LINK, act_FOLLOW_LINK_NEW_WINDOW,
act_GADGET_SELECT
} type;
union {
struct {
unsigned long x;
unsigned long y;
} mouse;
struct {
struct form_control* g;
int item;
} gadget_select;
} data;
};
typedef enum {
BROWSER_MOUSE_CLICK_1,
BROWSER_MOUSE_CLICK_2,
BROWSER_MOUSE_HOVER,
} browser_mouse_click;
struct box_selection
{
@ -93,7 +80,11 @@ void browser_window_stop(struct browser_window *bw);
void browser_window_reload(struct browser_window *bw, bool all);
void browser_window_destroy(struct browser_window *bw);
int browser_window_action(struct browser_window* bw, struct browser_action* act);
void browser_window_mouse_click(struct browser_window *bw,
browser_mouse_click click, int x, int y);
bool browser_window_key_press(struct browser_window *bw, char key);
void browser_window_form_select(struct browser_window *bw,
struct form_control *control, int item);
void box_under_area(struct content *content, struct box* box, unsigned long x, unsigned long y, unsigned long ox, unsigned long oy,
struct box_selection** found, int* count, int* plot_index);
@ -105,8 +96,6 @@ int box_position_distance(struct box_position* x, struct box_position* y);
void gui_redraw_gadget(struct browser_window* bw, struct form_control* g);
bool browser_window_key_press(struct browser_window *bw, char key);
/* In platform specific hotlist.c. */
void hotlist_visited(struct content *content);

View File

@ -25,6 +25,11 @@ typedef enum { GUI_POINTER_DEFAULT, GUI_POINTER_POINT, GUI_POINTER_CARET,
#include "netsurf/content/content.h"
#include "netsurf/desktop/browser.h"
void gui_init(int argc, char** argv);
void gui_multitask(void);
void gui_poll(bool active);
void gui_quit(void);
struct gui_window *gui_create_browser_window(struct browser_window *bw,
struct browser_window *clone);
void gui_window_destroy(struct gui_window *g);
@ -39,6 +44,10 @@ void gui_window_set_extent(struct gui_window *g, int width, int height);
void gui_window_set_status(struct gui_window *g, const char *text);
void gui_window_set_pointer(gui_pointer_shape shape);
void gui_window_set_url(struct gui_window *g, const char *url);
void gui_window_start_throbber(struct gui_window *g);
void gui_window_stop_throbber(struct gui_window *g);
void gui_window_place_caret(struct gui_window *g, int x, int y, int height);
void gui_window_new_content(struct gui_window *g);
struct gui_download_window *gui_download_window_create(const char *url,
const char *mime_type, struct fetch *fetch,
@ -49,20 +58,9 @@ void gui_download_window_error(struct gui_download_window *dw,
const char *error_msg);
void gui_download_window_done(struct gui_download_window *dw);
void gui_init(int argc, char** argv);
void gui_multitask(void);
void gui_poll(bool active);
void gui_quit(void);
void gui_window_start_throbber(struct gui_window *g);
void gui_window_stop_throbber(struct gui_window *g);
void gui_gadget_combo(struct browser_window* bw, struct form_control* g, unsigned long mx, unsigned long my);
void gui_window_place_caret(struct gui_window *g, int x, int y, int height);
void gui_create_form_select_menu(struct browser_window *bw,
struct form_control *control);
void gui_launch_url(const char *url);
void gui_window_new_content(struct gui_window *g);
#endif

View File

@ -2454,32 +2454,6 @@ bool plugin_decode(struct content* content, char* url, struct box* box,
}
/**
* Find the absolute coordinates of a box.
*
* \param box the box to calculate coordinates of
* \param x updated to x coordinate
* \param y updated to y coordinate
*/
void box_coords(struct box *box, int *x, int *y)
{
*x = box->x;
*y = box->y;
while (box->parent) {
if (box->type == BOX_FLOAT_LEFT ||
box->type == BOX_FLOAT_RIGHT) {
do {
box = box->parent;
} while (!box->float_children);
} else
box = box->parent;
*x += box->x;
*y += box->y;
}
}
struct box_result box_frameset(xmlNode *n, struct box_status *status,
struct css_style *style)
{
@ -2709,3 +2683,105 @@ struct box_multi_length *box_parse_multi_lengths(const char *s,
*count = n;
return length;
}
/**
* Find the absolute coordinates of a box.
*
* \param box the box to calculate coordinates of
* \param x updated to x coordinate
* \param y updated to y coordinate
*/
void box_coords(struct box *box, int *x, int *y)
{
*x = box->x;
*y = box->y;
while (box->parent) {
if (box->type == BOX_FLOAT_LEFT ||
box->type == BOX_FLOAT_RIGHT) {
do {
box = box->parent;
} while (!box->float_children);
} else
box = box->parent;
*x += box->x;
*y += box->y;
}
}
/**
* Find the boxes at a point.
*
* \param box box to search children of
* \param x point to find, in global document coordinates
* \param y point to find, in global document coordinates
* \param box_x position of box, in global document coordinates, updated
* to position of returned box, if any
* \param box_y position of box, in global document coordinates, updated
* to position of returned box, if any
* \param content updated to content of object that returned box is in, if any
* \return box at given point, or 0 if none found
*
* To find all the boxes in the heirarchy at a certain point, use code like
* this:
* \code
* struct box *box = top_of_document_to_search;
* int box_x = 0, box_y = 0;
* struct content *content = document_to_search;
*
* while ((box = box_at_point(box, x, y, &box_x, &box_y, &content))) {
* // process box
* }
* \endcode
*/
struct box *box_at_point(struct box *box, int x, int y,
int *box_x, int *box_y,
struct content **content)
{
struct box *child;
assert(box);
/* drill into HTML objects */
if (box->object) {
if (box->object->type == CONTENT_HTML &&
box->object->data.html.layout) {
*content = box->object;
box = box->object->data.html.layout;
} else {
return 0;
}
}
/* consider floats first, since they will often overlap other boxes */
for (child = box->float_children; child; child = child->next_float) {
if (*box_x + child->x <= x &&
x < *box_x + child->x + child->width &&
*box_y + child->y <= y &&
y < *box_y + child->y + child->height) {
*box_x += child->x;
*box_y += child->y;
return child;
}
}
/* non-float children */
for (child = box->children; child; child = child->next) {
if (child->type == BOX_FLOAT_LEFT ||
child->type == BOX_FLOAT_RIGHT)
continue;
if (*box_x + child->x <= x &&
x < *box_x + child->x + child->width &&
*box_y + child->y <= y &&
y < *box_y + child->y + child->height) {
*box_x += child->x;
*box_y += child->y;
return child;
}
}
return 0;
}

View File

@ -248,5 +248,8 @@ void box_add_child(struct box * parent, struct box * child);
void box_insert_sibling(struct box *box, struct box *new_box);
void box_free(struct box *box);
void box_coords(struct box *box, int *x, int *y);
struct box *box_at_point(struct box *box, int x, int y,
int *box_x, int *box_y,
struct content **content);
#endif

View File

@ -35,7 +35,6 @@
#include "netsurf/desktop/netsurf.h"
#include "netsurf/desktop/options.h"
#include "netsurf/render/font.h"
#include "netsurf/render/form.h"
#include "netsurf/render/html.h"
#include "netsurf/riscos/gui.h"
#include "netsurf/riscos/help.h"
@ -62,8 +61,6 @@ const char *__dynamic_da_name = "NetSurf"; /**< For UnixLib. */
int __feature_imagefs_is_file = 1; /**< For UnixLib. */
char *NETSURF_DIR;
wimp_menu *combo_menu;
struct form_control *current_gadget;
/** The pointer is over a window which is tracking mouse movement. */
static bool gui_track = false;
@ -958,53 +955,6 @@ void ro_gui_user_message(wimp_event_no event, wimp_message *message)
}
void gui_gadget_combo(struct browser_window* bw, struct form_control* g, unsigned long mx, unsigned long my)
{
int count;
struct form_option* o;
wimp_pointer pointer;
if (combo_menu != NULL)
xfree(combo_menu);
for (count = 0, o = g->data.select.items; o != NULL; ++count, o = o->next)
/* no body */;
combo_menu = xcalloc(1, wimp_SIZEOF_MENU(count));
combo_menu->title_data.indirected_text.text =
messages_get("SelectMenu");
combo_menu->title_fg = wimp_COLOUR_BLACK;
combo_menu->title_bg = wimp_COLOUR_LIGHT_GREY;
combo_menu->work_fg = wimp_COLOUR_BLACK;
combo_menu->work_bg = wimp_COLOUR_WHITE;
combo_menu->width = 0;
combo_menu->height = wimp_MENU_ITEM_HEIGHT;
combo_menu->gap = wimp_MENU_ITEM_GAP;
for (count = 0, o = g->data.select.items; o != NULL; ++count, o = o->next) {
combo_menu->entries[count].menu_flags = 0;
if (count == 0)
combo_menu->entries[count].menu_flags = wimp_MENU_TITLE_INDIRECTED;
if (o->selected)
combo_menu->entries[count].menu_flags |= wimp_MENU_TICKED;
if (o->next == NULL)
combo_menu->entries[count].menu_flags |= wimp_MENU_LAST;
combo_menu->entries[count].sub_menu = wimp_NO_SUB_MENU;
combo_menu->entries[count].icon_flags = wimp_ICON_TEXT | wimp_ICON_INDIRECTED | wimp_ICON_FILLED | wimp_ICON_VCENTRED | (wimp_COLOUR_BLACK << wimp_ICON_FG_COLOUR_SHIFT) | (wimp_COLOUR_WHITE << wimp_ICON_BG_COLOUR_SHIFT) | (wimp_BUTTON_MENU_ICON << wimp_ICON_BUTTON_TYPE_SHIFT);
/* \todo combo_menu->entries[count].data.indirected_text.text needs to be free() when menu gets closed. */
combo_menu->entries[count].data.indirected_text.text = cnv_str_local_enc(o->text);
combo_menu->entries[count].data.indirected_text.validation = "\0";
combo_menu->entries[count].data.indirected_text.size = strlen(combo_menu->entries[count].data.indirected_text.text) + 1;
}
wimp_get_pointer_info(&pointer);
current_gadget = g;
ro_gui_create_menu(combo_menu, pointer.pos.x - 64, pointer.pos.y, bw->window);
}
/**
* Handle Message_DataLoad (file dragged in).
*/

View File

@ -18,6 +18,7 @@
#include "oslib/wimp.h"
#include "oslib/wimpspriteop.h"
#include "netsurf/desktop/gui.h"
#include "netsurf/render/form.h"
#include "netsurf/riscos/gui.h"
#include "netsurf/riscos/help.h"
#include "netsurf/riscos/options.h"
@ -57,6 +58,12 @@ struct gui_window *current_gui;
wimp_menu *current_menu;
static int current_menu_x, current_menu_y;
/** Menu of options for form select controls. */
static wimp_menu *gui_form_select_menu = 0;
/** Form control which gui_form_select_menu is for. */
static struct form_control *gui_form_select_control;
/* Default menu item flags
*/
#define DEFAULT_FLAGS (wimp_ICON_TEXT | wimp_ICON_FILLED | \
@ -512,18 +519,16 @@ void ro_gui_popup_menu(wimp_menu *menu, wimp_w w, wimp_i i)
void ro_gui_menu_selection(wimp_selection *selection)
{
struct browser_action msg;
wimp_pointer pointer;
wimp_window_state state;
os_error *error;
wimp_get_pointer_info(&pointer);
if (current_menu == combo_menu && selection->items[0] >= 0) {
msg.type = act_GADGET_SELECT;
msg.data.gadget_select.g = current_gadget;
msg.data.gadget_select.item = selection->items[0];
browser_window_action(current_gui->bw, &msg);
if (current_menu == gui_form_select_menu && 0 <= selection->items[0]) {
browser_window_form_select(current_gui->bw,
gui_form_select_control,
selection->items[0]);
} else if (current_menu == iconbar_menu) {
switch (selection->items[0]) {
@ -655,8 +660,6 @@ void ro_gui_menu_selection(wimp_selection *selection)
case 1: /* Select all */
break;
case 2: /* Clear */
msg.type = act_CLEAR_SELECTION;
browser_window_action(current_gui->bw, &msg);
break;
}
break;
@ -807,10 +810,13 @@ void ro_gui_menu_selection(wimp_selection *selection)
}
if (pointer.buttons == wimp_CLICK_ADJUST) {
if (current_menu == combo_menu)
gui_gadget_combo(current_gui->bw, current_gadget, (unsigned int)current_menu_x, (unsigned int)current_menu_y);
if (current_menu == gui_form_select_menu)
gui_create_form_select_menu(current_gui->bw,
gui_form_select_control);
else
ro_gui_create_menu(current_menu, current_menu_x, current_menu_y, current_gui);
ro_gui_create_menu(current_menu,
current_menu_x, current_menu_y,
current_gui);
} else {
if (current_menu == hotlist_menu) {
ro_gui_hotlist_menu_closed();
@ -1458,3 +1464,92 @@ void ro_gui_menu_object_reload(void)
}
}
/**
* Display a menu of options for a form select control.
*
* \param bw browser window containing form control
* \param control form control of type GADGET_SELECT
*/
void gui_create_form_select_menu(struct browser_window *bw,
struct form_control *control)
{
unsigned int i = 0, j;
struct form_option *option;
wimp_pointer pointer;
os_error *error;
for (option = control->data.select.items; option; option = option->next)
i++;
if (i == 0)
return;
if (gui_form_select_menu) {
for (j = 0; ; j++) {
free(gui_form_select_menu->entries[j].data.
indirected_text.text);
if (gui_form_select_menu->entries[j].menu_flags &
wimp_MENU_LAST)
break;
}
free(gui_form_select_menu);
gui_form_select_menu = 0;
}
gui_form_select_menu = malloc(wimp_SIZEOF_MENU(i));
if (!gui_form_select_menu) {
warn_user("NoMemory", 0);
return;
}
gui_form_select_menu->title_data.indirected_text.text =
messages_get("SelectMenu");
gui_form_select_menu->title_fg = wimp_COLOUR_BLACK;
gui_form_select_menu->title_bg = wimp_COLOUR_LIGHT_GREY;
gui_form_select_menu->work_fg = wimp_COLOUR_BLACK;
gui_form_select_menu->work_bg = wimp_COLOUR_WHITE;
gui_form_select_menu->width = 200;
gui_form_select_menu->height = wimp_MENU_ITEM_HEIGHT;
gui_form_select_menu->gap = wimp_MENU_ITEM_GAP;
for (i = 0, option = control->data.select.items; option;
i++, option = option->next) {
gui_form_select_menu->entries[i].menu_flags = 0;
if (option->selected)
gui_form_select_menu->entries[i].menu_flags =
wimp_MENU_TICKED;
gui_form_select_menu->entries[i].sub_menu = wimp_NO_SUB_MENU;
gui_form_select_menu->entries[i].icon_flags = wimp_ICON_TEXT |
wimp_ICON_INDIRECTED | wimp_ICON_FILLED |
(wimp_COLOUR_BLACK <<
wimp_ICON_FG_COLOUR_SHIFT) |
(wimp_COLOUR_WHITE <<
wimp_ICON_BG_COLOUR_SHIFT);
/* \todo can cnv_str_local_enc() fail? */
gui_form_select_menu->entries[i].data.indirected_text.text =
cnv_str_local_enc(option->text);
gui_form_select_menu->entries[i].data.indirected_text.
validation = "\0";
gui_form_select_menu->entries[i].data.indirected_text.size =
strlen(gui_form_select_menu->entries[i].
data.indirected_text.text) + 1;
}
gui_form_select_menu->entries[0].menu_flags |=
wimp_MENU_TITLE_INDIRECTED;
gui_form_select_menu->entries[i - 1].menu_flags |= wimp_MENU_LAST;
error = xwimp_get_pointer_info(&pointer);
if (error) {
LOG(("xwimp_get_pointer_info: 0x%x: %s",
error->errnum, error->errmess));
warn_user("WimpError", error->errmess);
}
current_gui = bw->window;
gui_form_select_control = control;
ro_gui_create_menu(gui_form_select_menu,
pointer.pos.x - 64, pointer.pos.y, bw->window);
}

View File

@ -35,7 +35,7 @@ void ro_gui_start_selection(wimp_pointer *pointer, wimp_window_state *state,
void ro_gui_selection_drag_end(wimp_dragged *drag)
{
struct browser_action msg;
/* struct browser_action msg; */
int final_x0, final_y0;
wimp_window_state state;
@ -45,16 +45,16 @@ void ro_gui_selection_drag_end(wimp_dragged *drag)
final_x0 = window_x_units(drag->final.x0, &state) / 2;
final_y0 = window_y_units(drag->final.y0, &state) / 2;
msg.data.mouse.x = final_x0;
/* msg.data.mouse.x = final_x0;
msg.data.mouse.y = final_y0;
msg.type = act_ALTER_SELECTION;
browser_window_action(current_gui->bw, &msg);
browser_window_action(current_gui->bw, &msg);*/
if (box_position_eq(&(current_gui->bw->current_content->data.html.text_selection.start),
&(current_gui->bw->current_content->data.html.text_selection.end)))
{
msg.type = act_CLEAR_SELECTION;
browser_window_action(current_gui->bw, &msg);
/* msg.type = act_CLEAR_SELECTION;
browser_window_action(current_gui->bw, &msg);*/
}
current_gui->bw->current_content->data.html.text_selection.altering = alter_UNKNOWN;
}

View File

@ -908,14 +908,7 @@ void ro_gui_window_mouse_at(struct gui_window *g, wimp_pointer *pointer)
x = window_x_units(pointer->pos.x, &state) / 2 / g->option.scale;
y = -window_y_units(pointer->pos.y, &state) / 2 / g->option.scale;
if (g->bw->current_content != NULL)
{
struct browser_action msg;
msg.type = act_MOUSE_AT;
msg.data.mouse.x = x;
msg.data.mouse.y = y;
browser_window_action(g->bw, &msg);
}
browser_window_mouse_click(g->bw, BROWSER_MOUSE_HOVER, x, y);
}
@ -1034,7 +1027,6 @@ void ro_gui_status_click(struct gui_window *g, wimp_pointer *pointer)
void ro_gui_window_click(struct gui_window *g, wimp_pointer *pointer)
{
struct browser_action msg;
int x, y;
wimp_window_state state;
os_error *error;
@ -1066,33 +1058,13 @@ void ro_gui_window_click(struct gui_window *g, wimp_pointer *pointer)
}
}
if (pointer->buttons == wimp_CLICK_MENU) {
if (pointer->buttons == wimp_CLICK_MENU)
ro_gui_create_menu(browser_menu, pointer->pos.x - 64,
pointer->pos.y, g);
return;
}
if (pointer->buttons == wimp_CLICK_SELECT) {
msg.type = act_MOUSE_CLICK;
msg.data.mouse.x = x;
msg.data.mouse.y = y;
if (browser_window_action(
g->bw, &msg) == 1)
return;
msg.type = act_UNKNOWN;
}
if (pointer->buttons == wimp_CLICK_SELECT
|| pointer->buttons == wimp_CLICK_ADJUST) {
if (pointer->buttons == wimp_CLICK_SELECT)
msg.type = act_FOLLOW_LINK;
else
msg.type = act_FOLLOW_LINK_NEW_WINDOW;
msg.data.mouse.x = x;
msg.data.mouse.y = y;
browser_window_action(g->bw, &msg);
}
else if (pointer->buttons == wimp_CLICK_SELECT)
browser_window_mouse_click(g->bw, BROWSER_MOUSE_CLICK_1, x, y);
else if (pointer->buttons == wimp_CLICK_ADJUST)
browser_window_mouse_click(g->bw, BROWSER_MOUSE_CLICK_2, x, y);
}