HTML drags now go via content msg.

This commit is contained in:
Michael Drake 2013-02-08 13:22:53 +00:00
parent 9ec663f3a9
commit 4747bbbfb2
7 changed files with 233 additions and 102 deletions

View File

@ -78,7 +78,8 @@ typedef enum {
CONTENT_MSG_SCROLL, /**< Request to scroll content */
CONTENT_MSG_DRAGSAVE, /**< Allow drag saving of content */
CONTENT_MSG_SAVELINK, /**< Allow URL to be saved */
CONTENT_MSG_POINTER /**< Wants a specific mouse pointer set */
CONTENT_MSG_POINTER, /**< Wants a specific mouse pointer set */
CONTENT_MSG_DRAG /**< A drag started or ended */
} content_msg;
/** RFC5988 metadata link */
@ -152,14 +153,15 @@ union content_msg_data {
} savelink;
/** CONTENT_MSG_POINTER - Mouse pointer to set */
browser_pointer_shape pointer;
/** CONTENT_MSG_PASTE - Content requests that clipboard is pasted */
/** CONTENT_MSG_DRAG - Drag start or end */
struct {
/* TODO: Get rid of these coords.
* browser_window_paste_text doesn't take coords, but
* RISC OS front end is doing something different. */
int x;
int y;
} paste;
enum {
CONTENT_DRAG_NONE,
CONTENT_DRAG_SCROLL,
CONTENT_DRAG_SELECTION
} type;
const struct rect *rect;
} drag;
};
/** parameters to content redraw */

View File

@ -1545,6 +1545,25 @@ nserror browser_window_callback(hlcache_handle *c,
browser_window_set_pointer(bw, event->data.pointer);
break;
case CONTENT_MSG_DRAG:
{
browser_drag_type bdt = DRAGGING_NONE;
switch (event->data.drag.type) {
case CONTENT_DRAG_NONE:
bdt = DRAGGING_NONE;
break;
case CONTENT_DRAG_SCROLL:
bdt = DRAGGING_SELECTION;
break;
case CONTENT_DRAG_SELECTION:
bdt = DRAGGING_CONTENT_SCROLLBAR;
break;
}
browser_window_set_drag_type(bw, bdt, event->data.drag.rect);
}
break;
default:
assert(0);
}

View File

@ -57,8 +57,6 @@ typedef enum {
DRAGGING_SCR_X,
DRAGGING_SCR_Y,
DRAGGING_CONTENT_SCROLLBAR,
DRAGGING_CONTENT_TEXTAREA_SCROLLBAR,
DRAGGING_CONTENT_TEXTAREA_SELECTION,
DRAGGING_OTHER
} browser_drag_type;

View File

@ -28,6 +28,7 @@
#include "render/box_textarea.h"
#include "render/font.h"
#include "render/form.h"
#include "utils/log.h"
static bool box_textarea_browser_caret_callback(struct browser_window *bw,
@ -124,23 +125,20 @@ static bool box_textarea_browser_paste_callback(struct browser_window *bw,
static void box_textarea_callback(void *data, struct textarea_msg *msg)
{
struct form_textarea_data *d = data;
struct content *c = (struct content *)d->html;
struct html_content *html = d->html;
struct form_control *gadget = d->gadget;
struct box *box = gadget->box;
union content_msg_data msg_data;
switch (msg->type) {
case TEXTAREA_MSG_DRAG_REPORT:
if (msg->data.drag == TEXTAREA_DRAG_NONE) {
/* Textarea drag finished */
html->textarea = NULL;
html_drag_type drag_type = HTML_DRAG_NONE;
union html_drag_owner drag_owner;
drag_owner.no_owner = true;
browser_window_set_drag_type(html->bw,
DRAGGING_NONE, NULL);
msg_data.pointer = BROWSER_POINTER_AUTO;
content_broadcast(c, CONTENT_MSG_POINTER, msg_data);
html_set_drag_type(d->html, drag_type, drag_owner,
NULL);
} else {
/* Textarea drag started */
struct rect rect = {
@ -149,16 +147,25 @@ static void box_textarea_callback(void *data, struct textarea_msg *msg)
.x1 = INT_MAX,
.y1 = INT_MAX
};
browser_drag_type bdt;
html_drag_type drag_type;
union html_drag_owner drag_owner;
drag_owner.textarea = box;
if (msg->data.drag == TEXTAREA_DRAG_SCROLLBAR)
bdt = DRAGGING_CONTENT_TEXTAREA_SCROLLBAR;
else
bdt = DRAGGING_CONTENT_TEXTAREA_SELECTION;
switch (msg->data.drag) {
case TEXTAREA_DRAG_SCROLLBAR:
drag_type = HTML_DRAG_TEXTAREA_SCROLLBAR;
break;
case TEXTAREA_DRAG_SELECTION:
drag_type = HTML_DRAG_TEXTAREA_SELECTION;
break;
default:
LOG(("Drag type not handled."));
assert(0);
break;
}
browser_window_set_drag_type(html->bw, bdt, &rect);
html->textarea = msg->ta;
html_set_drag_type(d->html, drag_type, drag_owner,
&rect);
}
break;

View File

@ -343,8 +343,8 @@ html_create_html_data(html_content *c, const http_parameter *params)
c->iframe = NULL;
c->page = NULL;
c->font_func = &nsfont;
c->scrollbar = NULL;
c->textarea = NULL;
c->drag_type = HTML_DRAG_NONE;
c->drag_owner.no_owner = true;
c->scripts_count = 0;
c->scripts = NULL;
c->jscontext = NULL;
@ -1308,6 +1308,29 @@ html_object_callback(hlcache_handle *object,
content_broadcast(&c->base, event->type, event->data);
break;
case CONTENT_MSG_DRAG:
{
html_drag_type drag_type = HTML_DRAG_NONE;
union html_drag_owner drag_owner;
drag_owner.content = box;
switch (event->data.drag.type) {
case CONTENT_DRAG_NONE:
drag_type = HTML_DRAG_NONE;
drag_owner.no_owner = true;
break;
case CONTENT_DRAG_SCROLL:
drag_type = HTML_DRAG_CONTENT_SCROLL;
break;
case CONTENT_DRAG_SELECTION:
drag_type = HTML_DRAG_CONTENT_SELECTION;
break;
}
html_set_drag_type(c, drag_type, drag_owner,
event->data.drag.rect);
}
break;
default:
assert(0);
}

View File

@ -224,9 +224,10 @@ void html_mouse_track(struct content *c, struct browser_window *bw,
browser_mouse_state mouse, int x, int y)
{
html_content *html = (html_content*) c;
browser_drag_type drag_type = browser_window_get_drag_type(bw);
union html_drag_owner drag_owner;
if (drag_type == DRAGGING_SELECTION && !mouse) {
if (html->drag_type == HTML_DRAG_SELECTION && !mouse) {
/* End of selection drag */
int dir = -1;
size_t idx;
@ -238,40 +239,37 @@ void html_mouse_track(struct content *c, struct browser_window *bw,
if (idx != 0)
selection_track(&html->sel, mouse, idx);
browser_window_set_drag_type(bw, DRAGGING_NONE, NULL);
drag_owner.no_owner = true;
html_set_drag_type(html, HTML_DRAG_NONE, drag_owner, NULL);
}
switch (drag_type) {
case DRAGGING_SELECTION: {
struct box *box;
int dir = -1;
int dx, dy;
if (html->drag_type == HTML_DRAG_SELECTION) {
/* Selection drag */
struct box *box;
int dir = -1;
int dx, dy;
if (selection_dragging_start(&html->sel))
dir = 1;
if (selection_dragging_start(&html->sel))
dir = 1;
box = box_pick_text_box(html, x, y, dir, &dx, &dy);
box = box_pick_text_box(html, x, y, dir, &dx, &dy);
if (box) {
int pixel_offset;
size_t idx;
plot_font_style_t fstyle;
if (box != NULL) {
int pixel_offset;
size_t idx;
plot_font_style_t fstyle;
font_plot_style_from_css(box->style, &fstyle);
font_plot_style_from_css(box->style, &fstyle);
nsfont.font_position_in_string(&fstyle,
box->text, box->length,
dx, &idx, &pixel_offset);
nsfont.font_position_in_string(&fstyle,
box->text, box->length,
dx, &idx, &pixel_offset);
selection_track(&html->sel, mouse,
box->byte_offset + idx);
}
selection_track(&html->sel, mouse,
box->byte_offset + idx);
}
break;
default:
html_mouse_action(c, bw, mouse, x, y);
break;
} else {
html_mouse_action(c, bw, mouse, x, y);
}
}
@ -356,29 +354,30 @@ void html_mouse_action(struct content *c, struct browser_window *bw,
return;
}
if (!mouse && html->scrollbar != NULL) {
/* drag end: scrollbar */
html_overflow_scroll_drag_end(html->scrollbar, mouse, x, y);
}
if (html->drag_type == HTML_DRAG_SCROLLBAR) {
struct scrollbar *scr = html->drag_owner.scrollbar;
struct html_scrollbar_data *data = scrollbar_get_data(scr);
if (!mouse) {
/* drag end: scrollbar */
html_overflow_scroll_drag_end(scr, mouse, x, y);
}
if (html->scrollbar != NULL) {
struct html_scrollbar_data *data =
scrollbar_get_data(html->scrollbar);
box = data->box;
box_coords(box, &box_x, &box_y);
if (scrollbar_is_horizontal(html->scrollbar)) {
if (scrollbar_is_horizontal(scr)) {
scroll_mouse_x = x - box_x ;
scroll_mouse_y = y - (box_y + box->padding[TOP] +
box->height + box->padding[BOTTOM] -
SCROLLBAR_WIDTH);
status = scrollbar_mouse_action(html->scrollbar, mouse,
status = scrollbar_mouse_action(scr, mouse,
scroll_mouse_x, scroll_mouse_y);
} else {
scroll_mouse_x = x - (box_x + box->padding[LEFT] +
box->width + box->padding[RIGHT] -
SCROLLBAR_WIDTH);
scroll_mouse_y = y - box_y;
status = scrollbar_mouse_action(html->scrollbar, mouse,
status = scrollbar_mouse_action(scr, mouse,
scroll_mouse_x, scroll_mouse_y);
}
@ -387,8 +386,35 @@ void html_mouse_action(struct content *c, struct browser_window *bw,
return;
}
if (html->drag_type == HTML_DRAG_TEXTAREA_SELECTION ||
html->drag_type == HTML_DRAG_TEXTAREA_SCROLLBAR) {
box = html->drag_owner.textarea;
assert(box->gadget != NULL);
assert(box->gadget->type == GADGET_TEXTAREA ||
box->gadget->type == GADGET_PASSWORD ||
box->gadget->type == GADGET_TEXTBOX);
box_coords(box, &box_x, &box_y);
textarea_mouse_action(box->gadget->data.text.ta, mouse,
x - box_x, y - box_y);
/* TODO: Set appropriate statusbar message */
return;
}
if (html->drag_type == HTML_DRAG_CONTENT_SELECTION ||
html->drag_type == HTML_DRAG_CONTENT_SCROLL) {
box = html->drag_owner.content;
assert(box->object != NULL);
box_coords(box, &box_x, &box_y);
content_mouse_track(box->object, bw, mouse,
x - box_x, y - box_y);
return;
}
/* Content related drags handled by now */
browser_window_set_drag_type(bw, DRAGGING_NONE, NULL);
assert(html->drag_type == HTML_DRAG_NONE);
/* search the box tree for a link, imagemap, form control, or
* box with scrollbars
@ -734,11 +760,16 @@ void html_mouse_action(struct content *c, struct browser_window *bw,
/* key presses must be directed at the
* main browser window, paste text
* operations ignored */
html_drag_type drag_type;
union html_drag_owner drag_owner;
if (selection_dragging(&html->sel)) {
browser_window_set_drag_type(bw,
DRAGGING_SELECTION,
NULL);
drag_type = HTML_DRAG_SELECTION;
drag_owner.no_owner = true;
html_set_drag_type(html,
drag_type,
drag_owner,
NULL);
status = messages_get(
"Selecting");
}
@ -845,35 +876,34 @@ void html_overflow_scroll_callback(void *client_data,
html_content *html = (html_content *)data->c;
struct box *box = data->box;
union content_msg_data msg_data;
html_drag_type drag_type;
union html_drag_owner drag_owner;
switch(scrollbar_data->msg) {
case SCROLLBAR_MSG_MOVED:
html__redraw_a_box(html, box);
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
};
browser_window_set_drag_type(html->bw,
DRAGGING_CONTENT_SCROLLBAR, &rect);
case SCROLLBAR_MSG_MOVED:
html__redraw_a_box(html, box);
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
};
drag_type = HTML_DRAG_SCROLLBAR;
drag_owner.scrollbar = scrollbar_data->scrollbar;
html_set_drag_type(html, drag_type, drag_owner, &rect);
}
break;
case SCROLLBAR_MSG_SCROLL_FINISHED:
drag_type = HTML_DRAG_NONE;
drag_owner.no_owner = true;
html_set_drag_type(html, drag_type, drag_owner, NULL);
html->scrollbar = scrollbar_data->scrollbar;
}
break;
case SCROLLBAR_MSG_SCROLL_FINISHED:
html->scrollbar = NULL;
browser_window_set_drag_type(html->bw,
DRAGGING_NONE, NULL);
msg_data.pointer = BROWSER_POINTER_AUTO;
content_broadcast(data->c, CONTENT_MSG_POINTER,
msg_data);
break;
msg_data.pointer = BROWSER_POINTER_AUTO;
content_broadcast(data->c, CONTENT_MSG_POINTER, msg_data);
break;
}
}
@ -912,3 +942,39 @@ void html_overflow_scroll_drag_end(struct scrollbar *scrollbar,
scroll_mouse_x, scroll_mouse_y);
}
}
void html_set_drag_type(html_content *html, html_drag_type drag_type,
union html_drag_owner drag_owner, const struct rect *rect)
{
union content_msg_data msg_data;
assert(html != NULL);
html->drag_type = drag_type;
html->drag_owner = drag_owner;
switch (drag_type) {
case HTML_DRAG_NONE:
assert(drag_owner.no_owner == true);
msg_data.drag.type = CONTENT_DRAG_NONE;
break;
case HTML_DRAG_SCROLLBAR:
case HTML_DRAG_TEXTAREA_SCROLLBAR:
case HTML_DRAG_CONTENT_SCROLL:
msg_data.drag.type = CONTENT_DRAG_SCROLL;
break;
case HTML_DRAG_SELECTION:
assert(drag_owner.no_owner == true);
/* Fall through */
case HTML_DRAG_TEXTAREA_SELECTION:
case HTML_DRAG_CONTENT_SELECTION:
msg_data.drag.type = CONTENT_DRAG_SELECTION;
break;
}
msg_data.drag.rect = rect;
/* Inform the content's drag status change */
content_broadcast((struct content *)html, CONTENT_MSG_DRAG, msg_data);
}

View File

@ -27,6 +27,22 @@
#include "desktop/selection.h"
#include "render/html.h"
typedef enum {
HTML_DRAG_NONE, /** No drag */
HTML_DRAG_SELECTION, /** Own; Text selection */
HTML_DRAG_SCROLLBAR, /** Not own; drag in scrollbar widget */
HTML_DRAG_TEXTAREA_SELECTION, /** Not own; drag in textarea widget */
HTML_DRAG_TEXTAREA_SCROLLBAR, /** Not own; drag in textarea widget */
HTML_DRAG_CONTENT_SELECTION, /** Not own; drag in child content */
HTML_DRAG_CONTENT_SCROLL /** Not own; drag in child content */
} html_drag_type;
union html_drag_owner {
bool no_owner;
struct box *content;
struct scrollbar *scrollbar;
struct box *textarea;
}; /**< For drags we don't own */
/** Data specific to CONTENT_HTML. */
typedef struct html_content {
struct content base;
@ -98,13 +114,10 @@ typedef struct html_content {
* object within a page. */
struct html_content *page;
/** Scrollbar capturing all mouse events, updated to any active HTML
* scrollbar, or NULL when no scrollbar drags active */
struct scrollbar *scrollbar;
/** Textarea capturing all mouse events, updated to any active HTML
* textarea, or NULL when no textarea drags active */
struct textarea *textarea;
/* Current drag type */
html_drag_type drag_type;
/** Widget capturing all mouse events */
union html_drag_owner drag_owner;
/** Open core-handled form SELECT menu,
* or NULL if none currently open. */
@ -128,6 +141,9 @@ void html_set_status(html_content *c, const char *extra);
void html__redraw_a_box(html_content *html, struct box *box);
void html_set_drag_type(html_content *html, html_drag_type drag_type,
union html_drag_owner drag_owner, const struct rect *rect);
struct browser_window *html_get_browser_window(struct content *c);
struct search_context *html_get_search(struct content *c);
void html_set_search(struct content *c, struct search_context *s);