diff options
Diffstat (limited to 'render')
-rw-r--r-- | render/box_textarea.c | 66 | ||||
-rw-r--r-- | render/box_textarea.h | 11 | ||||
-rw-r--r-- | render/html.c | 112 | ||||
-rw-r--r-- | render/html.h | 1 | ||||
-rw-r--r-- | render/html_interaction.c | 359 | ||||
-rw-r--r-- | render/html_internal.h | 70 | ||||
-rw-r--r-- | render/textplain.c | 49 |
7 files changed, 568 insertions, 100 deletions
diff --git a/render/box_textarea.c b/render/box_textarea.c index 3109904d0..3d9838fa1 100644 --- a/render/box_textarea.c +++ b/render/box_textarea.c @@ -31,14 +31,11 @@ #include "utils/log.h" -static bool box_textarea_browser_caret_callback(struct browser_window *bw, - uint32_t key, void *p1, void *p2) +bool box_textarea_keypress(html_content *html, struct box *box, uint32_t key) { - struct box *box = p1; struct form_control *gadget = box->gadget; struct textarea *ta = gadget->data.text.ta; struct form* form = box->gadget->form; - html_content *html = p2; struct content *c = (struct content *) html; assert(ta != NULL); @@ -104,21 +101,6 @@ static bool box_textarea_browser_caret_callback(struct browser_window *bw, } -static void box_textarea_browser_move_callback(struct browser_window *bw, - void *p1, void *p2) -{ -} - - -static bool box_textarea_browser_paste_callback(struct browser_window *bw, - const char *utf8, unsigned utf8_len, bool last, - void *p1, void *p2) -{ - printf("AWWOOOOOGA!\n"); - return true; -} - - /** * Callback for html form textareas. */ @@ -175,23 +157,43 @@ static void box_textarea_callback(void *data, struct textarea_msg *msg) html__redraw_a_box(html, box); break; - case TEXTAREA_MSG_MOVED_CARET: + case TEXTAREA_MSG_SELECTION_REPORT: + if (msg->data.selection.have_selection) { + /* Textarea now has a selection */ + union html_selection_owner sel_owner; + sel_owner.textarea = box; + + html_set_selection(d->html, HTML_SELECTION_TEXTAREA, + sel_owner, + msg->data.selection.read_only); + } else { + /* The textarea now has no selection */ + union html_selection_owner sel_owner; + sel_owner.none = true; + + html_set_selection(d->html, HTML_SELECTION_NONE, + sel_owner, true); + } + break; + + case TEXTAREA_MSG_CARET_UPDATE: if (html->bw == NULL) break; - if (msg->data.caret.hidden) { - browser_window_remove_caret(html->bw); + if (msg->data.caret.type == TEXTAREA_CARET_HIDE) { + union html_focus_owner focus_owner; + focus_owner.textarea = box; + html_set_focus(d->html, HTML_FOCUS_TEXTAREA, + focus_owner, true, 0, 0, 0, NULL); } else { - int x, y; - box_coords(box, &x, &y); - browser_window_place_caret(html->bw, - x + msg->data.caret.x, - y + msg->data.caret.y, - msg->data.caret.height, - box_textarea_browser_caret_callback, - box_textarea_browser_paste_callback, - box_textarea_browser_move_callback, - box, html); + union html_focus_owner focus_owner; + focus_owner.textarea = box; + html_set_focus(d->html, HTML_FOCUS_TEXTAREA, + focus_owner, false, + msg->data.caret.pos.x, + msg->data.caret.pos.y, + msg->data.caret.pos.height, + msg->data.caret.pos.clip); } break; } diff --git a/render/box_textarea.h b/render/box_textarea.h index 30414e816..a7a377076 100644 --- a/render/box_textarea.h +++ b/render/box_textarea.h @@ -41,4 +41,15 @@ struct dom_node; bool box_textarea_create_textarea(html_content *html, struct box *box, struct dom_node *node); + +/** + * Handle form textarea keypress input + * + * \param html html content object + * \param box box with textarea widget + * \param key keypress + * \return true iff keypress handled + */ +bool box_textarea_keypress(html_content *html, struct box *box, uint32_t key); + #endif diff --git a/render/html.c b/render/html.c index 4fc152a84..e697c9f12 100644 --- a/render/html.c +++ b/render/html.c @@ -346,6 +346,10 @@ html_create_html_data(html_content *c, const http_parameter *params) c->font_func = &nsfont; c->drag_type = HTML_DRAG_NONE; c->drag_owner.no_owner = true; + c->selection_type = HTML_SELECTION_NONE; + c->selection_owner.none = true; + c->focus_type = HTML_FOCUS_SELF; + c->focus_owner.self = true; c->scripts_count = 0; c->scripts = NULL; c->jscontext = NULL; @@ -1309,6 +1313,28 @@ html_object_callback(hlcache_handle *object, content_broadcast(&c->base, event->type, event->data); break; + case CONTENT_MSG_CARET: + { + union html_focus_owner focus_owner; + focus_owner.content = box; + + switch (event->data.caret.type) { + case CONTENT_CARET_REMOVE: + case CONTENT_CARET_HIDE: + html_set_focus(c, HTML_FOCUS_CONTENT, focus_owner, + true, 0, 0, 0, NULL); + break; + case CONTENT_CARET_SET_POS: + html_set_focus(c, HTML_FOCUS_CONTENT, focus_owner, + false, event->data.caret.pos.x, + event->data.caret.pos.y, + event->data.caret.pos.height, + event->data.caret.pos.clip); + break; + } + } + break; + case CONTENT_MSG_DRAG: { html_drag_type drag_type = HTML_DRAG_NONE; @@ -1332,6 +1358,23 @@ html_object_callback(hlcache_handle *object, } break; + case CONTENT_MSG_SELECTION: + { + html_selection_type sel_type; + union html_selection_owner sel_owner; + + if (event->data.selection.selection) { + sel_type = HTML_SELECTION_CONTENT; + sel_owner.content = box; + } else { + sel_type = HTML_SELECTION_NONE; + sel_owner.none = true; + } + html_set_selection(c, sel_type, sel_owner, + event->data.selection.read_only); + } + break; + default: assert(0); } @@ -1514,6 +1557,10 @@ html_convert_css_callback(hlcache_handle *css, } break; + case CONTENT_MSG_POINTER: + /* Really don't want this to continue after the switch */ + return NSERROR_OK; + default: assert(0); } @@ -2513,8 +2560,13 @@ html_open(struct content *c, html->bw = bw; html->page = (html_content *) page; + html->drag_type = HTML_DRAG_NONE; + html->drag_owner.no_owner = true; + /* text selection */ selection_init(&html->sel, html->layout); + html->selection_type = HTML_SELECTION_NONE; + html->selection_owner.none = true; for (object = html->object_list; object != NULL; object = next) { next = object->next; @@ -2541,6 +2593,8 @@ static void html_close(struct content *c) html_content *html = (html_content *) c; struct content_html_object *object, *next; + selection_clear(&html->sel, false); + if (html->search != NULL) search_destroy_context(html->search); @@ -2567,11 +2621,63 @@ static void html_close(struct content *c) * Return an HTML content's selection context */ -static struct selection *html_get_selection(struct content *c) +static void html_clear_selection(struct content *c) +{ + html_content *html = (html_content *) c; + + switch (html->selection_type) { + case HTML_SELECTION_NONE: + /* Nothing to do */ + assert(html->selection_owner.none == true); + break; + case HTML_SELECTION_TEXTAREA: + textarea_clear_selection(html->selection_owner.textarea-> + gadget->data.text.ta); + break; + case HTML_SELECTION_SELF: + assert(html->selection_owner.none == false); + selection_clear(&html->sel, true); + break; + case HTML_SELECTION_CONTENT: + content_clear_selection(html->selection_owner.content->object); + break; + default: + break; + } + + /* There is no selection now. */ + html->selection_type = HTML_SELECTION_NONE; + html->selection_owner.none = true; +} + + +/** + * Return an HTML content's selection context + */ + +static char *html_get_selection(struct content *c) { html_content *html = (html_content *) c; - return &html->sel; + switch (html->selection_type) { + case HTML_SELECTION_TEXTAREA: + return textarea_get_selection(html->selection_owner.textarea-> + gadget->data.text.ta); + case HTML_SELECTION_SELF: + assert(html->selection_owner.none == false); + return selection_get_copy(&html->sel); + case HTML_SELECTION_CONTENT: + return content_get_selection( + html->selection_owner.content->object); + case HTML_SELECTION_NONE: + /* Nothing to do */ + assert(html->selection_owner.none == true); + break; + default: + break; + } + + return NULL; } @@ -3214,10 +3320,12 @@ static const content_handler html_content_handler = { .stop = html_stop, .mouse_track = html_mouse_track, .mouse_action = html_mouse_action, + .keypress = html_keypress, .redraw = html_redraw, .open = html_open, .close = html_close, .get_selection = html_get_selection, + .clear_selection = html_clear_selection, .get_contextual_content = html_get_contextual_content, .scroll_at_point = html_scroll_at_point, .drop_file_at_point = html_drop_file_at_point, diff --git a/render/html.h b/render/html.h index a9f7967f6..c208f47d6 100644 --- a/render/html.h +++ b/render/html.h @@ -50,6 +50,7 @@ struct textarea; struct scrollbar; struct scrollbar_msg_data; struct search_context; +struct selection; /** * Container for stylesheets used by an HTML document diff --git a/render/html_interaction.c b/render/html_interaction.c index 3f1bee475..d734c6b9f 100644 --- a/render/html_interaction.c +++ b/render/html_interaction.c @@ -223,54 +223,7 @@ static size_t html_selection_drag_end(struct html_content *html, 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; - union html_drag_owner drag_owner; - - if (html->drag_type == HTML_DRAG_SELECTION && !mouse) { - /* End of selection drag */ - int dir = -1; - size_t idx; - - if (selection_dragging_start(&html->sel)) - dir = 1; - - idx = html_selection_drag_end(html, mouse, x, y, dir); - - if (idx != 0) - selection_track(&html->sel, mouse, idx); - - drag_owner.no_owner = true; - html_set_drag_type(html, HTML_DRAG_NONE, drag_owner, NULL); - } - - 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; - - box = box_pick_text_box(html, x, y, dir, &dx, &dy); - - if (box != NULL) { - int pixel_offset; - size_t idx; - plot_font_style_t fstyle; - - font_plot_style_from_css(box->style, &fstyle); - - nsfont.font_position_in_string(&fstyle, - box->text, box->length, - dx, &idx, &pixel_offset); - - selection_track(&html->sel, mouse, - box->byte_offset + idx); - } - } else { - html_mouse_action(c, bw, mouse, x, y); - } + html_mouse_action(c, bw, mouse, x, y); } @@ -323,6 +276,11 @@ void html_mouse_action(struct content *c, struct browser_window *bw, browser_drag_type drag_type = browser_window_get_drag_type(bw); union content_msg_data msg_data; struct dom_node *node = NULL; + union html_drag_owner drag_owner; + union html_selection_owner sel_owner; + bool click = mouse & (BROWSER_MOUSE_PRESS_1 | BROWSER_MOUSE_PRESS_2 | + BROWSER_MOUSE_CLICK_1 | BROWSER_MOUSE_CLICK_2 | + BROWSER_MOUSE_DRAG_1 | BROWSER_MOUSE_DRAG_2); if (drag_type != DRAGGING_NONE && !mouse && html->visible_select_menu != NULL) { @@ -349,7 +307,55 @@ void html_mouse_action(struct content *c, struct browser_window *bw, &width, &height); html->visible_select_menu = NULL; browser_window_redraw_rect(bw, box_x, box_y, - width, height); + width, height); + } + return; + } + + if (html->drag_type == HTML_DRAG_SELECTION) { + /* Selection drag */ + + if (!mouse) { + /* End of selection drag */ + int dir = -1; + size_t idx; + + if (selection_dragging_start(&html->sel)) + dir = 1; + + idx = html_selection_drag_end(html, mouse, x, y, dir); + + if (idx != 0) + selection_track(&html->sel, mouse, idx); + + drag_owner.no_owner = true; + html_set_drag_type(html, HTML_DRAG_NONE, + drag_owner, NULL); + return; + } + + struct box *box; + int dir = -1; + int dx, dy; + + if (selection_dragging_start(&html->sel)) + dir = 1; + + box = box_pick_text_box(html, x, y, dir, &dx, &dy); + + if (box != NULL) { + int pixel_offset; + size_t idx; + plot_font_style_t fstyle; + + font_plot_style_from_css(box->style, &fstyle); + + nsfont.font_position_in_string(&fstyle, + box->text, box->length, + dx, &idx, &pixel_offset); + + selection_track(&html->sel, mouse, + box->byte_offset + idx); } return; } @@ -413,6 +419,16 @@ void html_mouse_action(struct content *c, struct browser_window *bw, return; } + if (html->drag_type == HTML_DRAG_CONTENT_SELECTION) { + 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 */ assert(html->drag_type == HTML_DRAG_NONE); @@ -536,7 +552,8 @@ void html_mouse_action(struct content *c, struct browser_window *bw, /* mouse inside padding box */ if ((box->scroll_y != NULL) && - (x > (padding_right - SCROLLBAR_WIDTH))) { + (x > (padding_right - + SCROLLBAR_WIDTH))) { /* mouse above vertical box scroll */ scrollbar = box->scroll_y; @@ -546,7 +563,8 @@ void html_mouse_action(struct content *c, struct browser_window *bw, break; } else if ((box->scroll_x != NULL) && - (y > (padding_bottom - SCROLLBAR_WIDTH))) { + (y > (padding_bottom - + SCROLLBAR_WIDTH))) { /* mouse above horizontal box scroll */ scrollbar = box->scroll_x; @@ -628,6 +646,15 @@ void html_mouse_action(struct content *c, struct browser_window *bw, pointer = get_pointer_shape(gadget_box, false); + if (click && (html->selection_type != + HTML_SELECTION_TEXTAREA || + html->selection_owner.textarea != + gadget_box)) { + sel_owner.none = true; + html_set_selection(html, HTML_SELECTION_NONE, + sel_owner, true); + } + textarea_mouse_action(gadget->data.text.ta, mouse, x - gadget_box_x, y - gadget_box_y); break; @@ -679,6 +706,14 @@ void html_mouse_action(struct content *c, struct browser_window *bw, x - pos_x, y - pos_y); } } else if (html_object_box) { + + if (click && (html->selection_type != HTML_SELECTION_CONTENT || + html->selection_owner.content != + html_object_box)) { + sel_owner.none = true; + html_set_selection(html, HTML_SELECTION_NONE, + sel_owner, true); + } if (mouse & BROWSER_MOUSE_CLICK_1 || mouse & BROWSER_MOUSE_CLICK_2) { content_mouse_action(html_object_box->object, @@ -738,11 +773,18 @@ void html_mouse_action(struct content *c, struct browser_window *bw, /* if clicking in the main page, remove the selection from any * text areas */ if (!done) { - struct box *layout = html->layout; - - if (mouse && (mouse < BROWSER_MOUSE_MOD_1) && - selection_root(&html->sel) != layout) { - selection_init(&html->sel, layout); + + if (click && html->focus_type != HTML_FOCUS_SELF) { + union html_focus_owner fo; + fo.self = true; + html_set_focus(html, HTML_FOCUS_SELF, fo, + true, 0, 0, 0, NULL); + } + if (click && html->selection_type != + HTML_SELECTION_SELF) { + sel_owner.none = true; + html_set_selection(html, HTML_SELECTION_NONE, + sel_owner, true); } if (text_box) { @@ -781,8 +823,24 @@ void html_mouse_action(struct content *c, struct browser_window *bw, done = true; } - } else if (mouse & BROWSER_MOUSE_PRESS_1) + } else if (mouse & BROWSER_MOUSE_PRESS_1) { + union html_selection_owner sel_owner; + sel_owner.none = true; selection_clear(&html->sel, true); + } + + if (selection_defined(&html->sel)) { + sel_owner.none = false; + html_set_selection(html, HTML_SELECTION_SELF, + sel_owner, + selection_read_only( + &html->sel)); + } else if (click && html->selection_type != + HTML_SELECTION_NONE) { + sel_owner.none = true; + html_set_selection(html, HTML_SELECTION_NONE, + sel_owner, true); + } } if (!done) { @@ -832,7 +890,10 @@ void html_mouse_action(struct content *c, struct browser_window *bw, } if (mouse && mouse < BROWSER_MOUSE_MOD_1) { /* ensure key presses still act on the browser window */ - browser_window_remove_caret(bw); + union html_focus_owner fo; + fo.self = true; + html_set_focus(html, HTML_FOCUS_SELF, fo, + true, 0, 0, 0, NULL); } } @@ -876,6 +937,61 @@ void html_mouse_action(struct content *c, struct browser_window *bw, /** + * Handle keypresses. + * + * \param c content of type CONTENT_TEXTPLAIN + * \param key The UCS4 character codepoint + * \return true if key handled, false otherwise + */ + +bool html_keypress(struct content *c, uint32_t key) +{ + html_content *html = (html_content *) c; + struct selection *sel = &html->sel; + struct box *box; + + switch (html->focus_type) { + case HTML_FOCUS_CONTENT: + box = html->focus_owner.content; + return content_keypress(box->object, key); + + case HTML_FOCUS_TEXTAREA: + box = html->focus_owner.textarea; + return textarea_keypress(box->gadget->data.text.ta, key); + + default: + /* Deal with it below */ + break; + } + + switch (key) { + case KEY_COPY_SELECTION: + selection_copy_to_clipboard(sel); + return true; + + case KEY_CLEAR_SELECTION: + selection_clear(sel, true); + return true; + + case KEY_SELECT_ALL: + selection_select_all(sel); + return true; + + case KEY_ESCAPE: + if (selection_defined(sel)) { + selection_clear(sel, true); + return true; + } + + /* if there's no selection, leave Escape for the caller */ + return false; + } + + return false; +} + + +/** * Callback for in-page scrollbars. */ void html_overflow_scroll_callback(void *client_data, @@ -985,6 +1101,131 @@ void html_set_drag_type(html_content *html, html_drag_type drag_type, } msg_data.drag.rect = rect; - /* Inform the content's drag status change */ + /* Inform of the content's drag status change */ content_broadcast((struct content *)html, CONTENT_MSG_DRAG, msg_data); } + +/* Documented in html_internal.h */ +void html_set_focus(html_content *html, html_focus_type focus_type, + union html_focus_owner focus_owner, bool hide_caret, + int x, int y, int height, const struct rect *clip) +{ + union content_msg_data msg_data; + int x_off = 0; + int y_off = 0; + bool textarea_lost_focus = html->focus_type == HTML_FOCUS_TEXTAREA && + focus_type != HTML_FOCUS_TEXTAREA; + + assert(html != NULL); + + switch (focus_type) { + case HTML_FOCUS_SELF: + assert(focus_owner.self == true); + if (html->focus_type == HTML_FOCUS_SELF) + /* Don't need to tell anyone anything */ + return; + break; + + case HTML_FOCUS_CONTENT: + box_coords(focus_owner.content, &x_off, &y_off); + break; + + case HTML_FOCUS_TEXTAREA: + box_coords(focus_owner.textarea, &x_off, &y_off); + break; + } + + html->focus_type = focus_type; + html->focus_owner = focus_owner; + + if (textarea_lost_focus) { + msg_data.caret.type = CONTENT_CARET_REMOVE; + } else if (focus_type != HTML_FOCUS_SELF && hide_caret) { + msg_data.caret.type = CONTENT_CARET_HIDE; + } else { + msg_data.caret.type = CONTENT_CARET_SET_POS; + msg_data.caret.pos.x = x + x_off; + msg_data.caret.pos.y = y + y_off; + msg_data.caret.pos.height = height; + msg_data.caret.pos.clip = clip; + } + + /* Inform of the content's drag status change */ + content_broadcast((struct content *)html, CONTENT_MSG_CARET, msg_data); +} + +/* Documented in html_internal.h */ +void html_set_selection(html_content *html, html_selection_type selection_type, + union html_selection_owner selection_owner, bool read_only) +{ + union content_msg_data msg_data; + struct box *box; + bool changed = false; + bool same_type = html->selection_type == selection_type; + + assert(html != NULL); + + if ((selection_type == HTML_SELECTION_NONE && + html->selection_type != HTML_SELECTION_NONE) || + (selection_type != HTML_SELECTION_NONE && + html->selection_type == HTML_SELECTION_NONE)) + /* Existance of selection has changed, and we'll need to + * inform our owner */ + changed = true; + + /* Clear any existing selection */ + if (html->selection_type != HTML_SELECTION_NONE) { + switch (html->selection_type) { + case HTML_SELECTION_SELF: + if (same_type) + break; + selection_clear(&html->sel, true); + break; + case HTML_SELECTION_TEXTAREA: + if (same_type && html->selection_owner.textarea == + selection_owner.textarea) + break; + box = html->selection_owner.textarea; + textarea_clear_selection(box->gadget->data.text.ta); + break; + case HTML_SELECTION_CONTENT: + if (same_type && html->selection_owner.content == + selection_owner.content) + break; + box = html->selection_owner.content; + content_clear_selection(box->object); + break; + default: + break; + } + } + + html->selection_type = selection_type; + html->selection_owner = selection_owner; + + if (!changed) + /* Don't need to report lack of change to owner */ + return; + + /* Prepare msg */ + switch (selection_type) { + case HTML_SELECTION_NONE: + assert(selection_owner.none == true); + msg_data.selection.selection = false; + break; + case HTML_SELECTION_SELF: + assert(selection_owner.none == false); + /* fall through */ + case HTML_SELECTION_TEXTAREA: + case HTML_SELECTION_CONTENT: + msg_data.selection.selection = true; + break; + default: + break; + } + msg_data.selection.read_only = read_only; + + /* Inform of the content's selection status change */ + content_broadcast((struct content *)html, CONTENT_MSG_SELECTION, + msg_data); +} diff --git a/render/html_internal.h b/render/html_internal.h index 3e562bc39..80b126b25 100644 --- a/render/html_internal.h +++ b/render/html_internal.h @@ -43,6 +43,29 @@ union html_drag_owner { struct box *textarea; }; /**< For drags we don't own */ +typedef enum { + HTML_SELECTION_NONE, /** No selection */ + HTML_SELECTION_TEXTAREA, /** Selection in one of our textareas */ + HTML_SELECTION_SELF, /** Selection in this html content */ + HTML_SELECTION_CONTENT /** Selection in child content */ +} html_selection_type; +union html_selection_owner { + bool none; + struct box *textarea; + struct box *content; +}; /**< For getting at selections in this content or things in this content */ + +typedef enum { + HTML_FOCUS_SELF, /** Focus is our own */ + HTML_FOCUS_CONTENT, /** Focus belongs to child content */ + HTML_FOCUS_TEXTAREA /** Focus belongs to textarea */ +} html_focus_type; +union html_focus_owner { + bool self; + struct box *textarea; + struct box *content; +}; /**< For directing input */ + /** Data specific to CONTENT_HTML. */ typedef struct html_content { struct content base; @@ -114,18 +137,28 @@ typedef struct html_content { * object within a page. */ struct html_content *page; - /* Current drag type */ + /** Current drag type */ html_drag_type drag_type; /** Widget capturing all mouse events */ union html_drag_owner drag_owner; + /** Current selection state */ + html_selection_type selection_type; + /** Current selection owner */ + union html_selection_owner selection_owner; + + /** Current input focus target type */ + html_focus_type focus_type; + /** Current input focus target */ + union html_focus_owner focus_owner; + + /** HTML content's own text selection object */ + struct selection sel; + /** Open core-handled form SELECT menu, * or NULL if none currently open. */ struct form_control *visible_select_menu; - /** Selection state */ - struct selection sel; - /** Context for free text search, or NULL if none */ struct search_context *search; @@ -152,6 +185,34 @@ 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); +/** + * Set our selection status, and inform whatever owns the content + * + * \param html HTML content + * \param selection_type Type of selection + * \param selection_owner What owns the selection + * \param read_only True iff selection is read only + */ +void html_set_selection(html_content *html, html_selection_type selection_type, + union html_selection_owner selection_owner, bool read_only); + +/** + * Set our input focus, and inform whatever owns the content + * + * \param html HTML content + * \param focus_type Type of input focus + * \param focus_owner What owns the focus + * \param hide_caret True iff caret to be hidden + * \param x Carret x-coord rel to owner + * \param y Carret y-coord rel to owner + * \param height Carret height + * \param clip Carret clip rect + */ +void html_set_focus(html_content *html, html_focus_type focus_type, + union html_focus_owner focus_owner, bool hide_caret, + int x, int y, int height, const struct rect *clip); + + 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); @@ -179,6 +240,7 @@ void html_mouse_track(struct content *c, struct browser_window *bw, browser_mouse_state mouse, int x, int y); void html_mouse_action(struct content *c, struct browser_window *bw, browser_mouse_state mouse, int x, int y); +bool html_keypress(struct content *c, uint32_t key); void html_overflow_scroll_callback(void *client_data, struct scrollbar_msg_data *scrollbar_data); diff --git a/render/textplain.c b/render/textplain.c index 6cf334fe2..b9d0b81e5 100644 --- a/render/textplain.c +++ b/render/textplain.c @@ -40,6 +40,7 @@ #include "desktop/plotters.h" #include "desktop/search.h" #include "desktop/selection.h" +#include "desktop/textinput.h" #include "render/font.h" #include "render/search.h" #include "render/textplain.h" @@ -107,6 +108,7 @@ static void textplain_mouse_track(struct content *c, struct browser_window *bw, browser_mouse_state mouse, int x, int y); static void textplain_mouse_action(struct content *c, struct browser_window *bw, browser_mouse_state mouse, int x, int y); +static bool textplain_keypress(struct content *c, uint32_t key); static void textplain_reformat(struct content *c, int width, int height); static void textplain_destroy(struct content *c); static bool textplain_redraw(struct content *c, struct content_redraw_data *data, @@ -114,7 +116,7 @@ static bool textplain_redraw(struct content *c, struct content_redraw_data *data static void textplain_open(struct content *c, struct browser_window *bw, struct content *page, struct object_params *params); void textplain_close(struct content *c); -struct selection *textplain_get_selection(struct content *c); +char *textplain_get_selection(struct content *c); struct search_context *textplain_get_search(struct content *c); static nserror textplain_clone(const struct content *old, struct content **newc); @@ -139,6 +141,7 @@ static const content_handler textplain_content_handler = { .destroy = textplain_destroy, .mouse_track = textplain_mouse_track, .mouse_action = textplain_mouse_action, + .keypress = textplain_keypress, .redraw = textplain_redraw, .open = textplain_open, .close = textplain_close, @@ -716,6 +719,46 @@ void textplain_mouse_action(struct content *c, struct browser_window *bw, /** + * Handle keypresses. + * + * \param c content of type CONTENT_TEXTPLAIN + * \param key The UCS4 character codepoint + * \return true if key handled, false otherwise + */ + +bool textplain_keypress(struct content *c, uint32_t key) +{ + textplain_content *text = (textplain_content *) c; + struct selection *sel = &text->sel; + + switch (key) { + case KEY_COPY_SELECTION: + selection_copy_to_clipboard(sel); + return true; + + case KEY_CLEAR_SELECTION: + selection_clear(sel, true); + return true; + + case KEY_SELECT_ALL: + selection_select_all(sel); + return true; + + case KEY_ESCAPE: + if (selection_defined(sel)) { + selection_clear(sel, true); + return true; + } + + /* if there's no selection, leave Escape for the caller */ + return false; + } + + return false; +} + + +/** * Draw a CONTENT_TEXTPLAIN using the current set of plotters (plot). * * \param c content of type CONTENT_TEXTPLAIN @@ -893,11 +936,11 @@ void textplain_close(struct content *c) * Return an textplain content's selection context */ -struct selection *textplain_get_selection(struct content *c) +char *textplain_get_selection(struct content *c) { textplain_content *text = (textplain_content *) c; - return &text->sel; + return selection_get_copy(&text->sel); } |