diff options
Diffstat (limited to 'desktop')
-rw-r--r-- | desktop/browser.c | 91 | ||||
-rw-r--r-- | desktop/browser.h | 23 | ||||
-rw-r--r-- | desktop/frames.c | 7 | ||||
-rw-r--r-- | desktop/selection.c | 37 | ||||
-rw-r--r-- | desktop/selection.h | 4 | ||||
-rw-r--r-- | desktop/textinput.c | 20 |
6 files changed, 108 insertions, 74 deletions
diff --git a/desktop/browser.c b/desktop/browser.c index 0fca4a2dd..54c89fe64 100644 --- a/desktop/browser.c +++ b/desktop/browser.c @@ -344,16 +344,40 @@ bool browser_window_has_selection(struct browser_window *bw) { assert(bw->window); - /* TODO: handle selections in (i)frames */ - - if (bw->current_content != NULL && bw->sel != NULL && - selection_defined(bw->sel)) { + if (bw->cur_sel != NULL && selection_defined(bw->cur_sel)) { return true; } else { return false; } } +/* exported interface, documented in browser.h */ +void browser_window_set_selection(struct browser_window *bw, + struct selection *s) +{ + assert(bw->window); + + if (bw->cur_sel != s && bw->cur_sel != NULL) { + /* Clear any existing selection */ + selection_clear(bw->cur_sel, true); + } + + /* Replace current selection pointer */ + if (s == NULL && bw->current_content != NULL) { + bw->cur_sel = content_get_selection(bw->current_content); + } else { + bw->cur_sel = s; + } +} + +/* exported interface, documented in browser.h */ +struct selection *browser_window_get_selection(struct browser_window *bw) +{ + assert(bw->window); + + return bw->cur_sel; +} + /** * Set scroll offsets for a browser window. * @@ -407,8 +431,6 @@ struct browser_window *browser_window_create(const char *url, bw->last_action = wallclock(); bw->focus = bw; - bw->sel = selection_create(); - /* gui window */ /* from the front end's pov, it clones the top level browser window, * so find that. */ @@ -446,7 +468,7 @@ void browser_window_initialise_common(struct browser_window *bw, bw->history = history_clone(clone->history); /* window characteristics */ - bw->sel = NULL; + bw->cur_sel = NULL; bw->refresh_interval = -1; bw->reformat_pending = false; @@ -799,13 +821,11 @@ nserror browser_window_callback(hlcache_handle *c, global_history_add(urldb_get_url(url)); } } - - /* text selection */ - if (content_get_type(c) == CONTENT_HTML) - selection_init(bw->sel, - html_get_box_tree(bw->current_content)); - if (content_get_type(c) == CONTENT_TEXTPLAIN) - selection_init(bw->sel, NULL); + + if (bw->window != NULL) { + browser_window_set_selection(bw, + content_get_selection(c)); + } /* frames */ if (content_get_type(c) == CONTENT_HTML && @@ -854,7 +874,6 @@ nserror browser_window_callback(hlcache_handle *c, else if (c == bw->current_content) { bw->current_content = NULL; browser_window_remove_caret(bw); - selection_init(bw->sel, NULL); } hlcache_handle_release(c); @@ -875,8 +894,6 @@ nserror browser_window_callback(hlcache_handle *c, /* reflow iframe positions */ if (html_get_iframe(c) != NULL) browser_window_recalculate_iframes(bw); - /* box tree may have changed, need to relabel */ - selection_reinit(bw->sel, html_get_box_tree(c)); } if (bw->move_callback) @@ -1439,6 +1456,12 @@ void browser_window_destroy_internal(struct browser_window *bw) if (top->focus == bw) top->focus = top; + + if (bw->current_content != NULL && + top->cur_sel == content_get_selection( + bw->current_content)) { + browser_window_set_selection(top, NULL); + } } /* Destruction order is important: we must ensure that the frontend @@ -1471,12 +1494,6 @@ void browser_window_destroy_internal(struct browser_window *bw) bw->box = NULL; } - /* TODO: After core FRAMES are done, should be - * if (bw->browser_window_type == BROWSER_WINDOW_NORMAL) */ - if (bw->browser_window_type != BROWSER_WINDOW_IFRAME) { - selection_destroy(bw->sel); - } - /* These simply free memory, so are safe here */ history_destroy(bw->history); @@ -1831,6 +1848,7 @@ void browser_window_mouse_track(struct browser_window *bw, browser_window_mouse_drag_end(bw, mouse, x, y); } + /* Browser window's horizontal scrollbar */ if (bw->scroll_x != NULL) { int scr_x, scr_y; browser_window_get_scrollbar_pos(bw, true, &scr_x, &scr_y); @@ -1853,6 +1871,7 @@ void browser_window_mouse_track(struct browser_window *bw, } } + /* Browser window's vertical scrollbar */ if (bw->scroll_y != NULL) { int scr_x, scr_y; browser_window_get_scrollbar_pos(bw, false, &scr_x, &scr_y); @@ -2002,31 +2021,7 @@ void browser_window_mouse_drag_end(struct browser_window *bw, switch (bw->drag_type) { case DRAGGING_SELECTION: - { - hlcache_handle *h = bw->current_content; - if (h) { - int dir = -1; - size_t idx; - - if (selection_dragging_start(bw->sel)) - dir = 1; - - if (content_get_type(h) == CONTENT_HTML) { - idx = html_selection_drag_end(h, mouse, x, y, - dir); - if (idx != 0) - selection_track(bw->sel, mouse, idx); - } else { - assert(content_get_type(h) == - CONTENT_TEXTPLAIN); - idx = textplain_offset_from_coords(h, x, y, - dir); - selection_track(bw->sel, mouse, idx); - } - } - selection_drag_end(bw->sel); - } - bw->drag_type = DRAGGING_NONE; + /* Drag handled by content handler */ break; case DRAGGING_OTHER: diff --git a/desktop/browser.h b/desktop/browser.h index d0695f295..f008cfc00 100644 --- a/desktop/browser.h +++ b/desktop/browser.h @@ -78,9 +78,6 @@ struct browser_window { /** Window history structure. */ struct history *history; - /** Selection state */ - struct selection *sel; - /** Handler for keyboard input, or 0. */ browser_caret_callback caret_callback; /** Handler for pasting text, or 0. */ @@ -193,6 +190,9 @@ struct browser_window { /** search context for free text search */ struct search_context *search_context; + /** Content with current selection, or NULL if none */ + struct selection *cur_sel; + /** cache of the currently displayed status text. */ char *status_text; /**< Current status bar text. */ int status_text_len; /**< Length of the ::status_text buffer. */ @@ -365,6 +365,23 @@ struct browser_window * browser_window_get_root(struct browser_window *bw); */ bool browser_window_has_selection(struct browser_window *bw); +/** + * Set pointer to current selection. Clears any existing selection. + * + * \param bw The browser window + * \param s The new selection + */ +void browser_window_set_selection(struct browser_window *bw, + struct selection *s); + +/** + * Get the current selection context from a root browser window + * + * \param bw The browser window + * \return the selection context, or NULL + */ +struct selection *browser_window_get_selection(struct browser_window *bw); + /* In platform specific hotlist.c. */ void hotlist_visited(struct hlcache_handle *c); diff --git a/desktop/frames.c b/desktop/frames.c index afcd84e01..f1710437f 100644 --- a/desktop/frames.c +++ b/desktop/frames.c @@ -201,7 +201,7 @@ void browser_window_create_iframes(struct browser_window *bw, window->no_resize = true; window->margin_width = cur->margin_width; window->margin_height = cur->margin_height; - window->sel = bw->sel; + window->cur_sel = bw->cur_sel; window->scale = bw->scale; if (cur->name) { window->name = strdup(cur->name); @@ -315,9 +315,8 @@ void browser_window_create_frameset(struct browser_window *bw, warn_user("NoMemory", 0); } - /* TODO: when framesets are handled in the core, remove - * the following line. */ - window->sel = selection_create(); + /* TODO: When frames are handled in core: + * window->cur_sel = bw->cur_sel; */ /* linking */ window->parent = bw; diff --git a/desktop/selection.c b/desktop/selection.c index 24502ac47..7c775f4c2 100644 --- a/desktop/selection.c +++ b/desktop/selection.c @@ -90,20 +90,34 @@ static struct box *get_box(struct box *b, unsigned offset, size_t *pidx); /** * Creates a new selection object associated with a browser window. * - * \param s selection object - * \param bw browser window + * \return new selection context */ struct selection *selection_create(void) { struct selection *s = calloc(1, sizeof(struct selection)); if (s) { + selection_prepare(s); + } + return s; +} + +/** + * Prepare a newly created selection object for use. + * + * \param s selection object + * \param bw browser window + */ + +void selection_prepare(struct selection *s) +{ + if (s) { s->bw = NULL; s->root = NULL; s->drag_state = DRAG_NONE; + s->max_idx = 0; selection_clear(s, false); } - return s; } /** @@ -304,12 +318,16 @@ bool selection_click(struct selection *s, browser_mouse_state mouse, gui_drag_save_selection(s, top->window); } else if (!modkeys) { - if (pos && (mouse & BROWSER_MOUSE_PRESS_1)) + if (pos && (mouse & BROWSER_MOUSE_PRESS_1)) { /* Clear the selection if mouse is pressed outside the selection, * Otherwise clear on release (to allow for drags) */ + browser_window_set_selection(top, s); + selection_clear(s, true); - else if (mouse & BROWSER_MOUSE_DRAG_1) { + } else if (mouse & BROWSER_MOUSE_DRAG_1) { /* start new selection drag */ + browser_window_set_selection(top, s); + selection_clear(s, true); selection_set_start(s, idx); @@ -325,6 +343,8 @@ bool selection_click(struct selection *s, browser_mouse_state mouse, if (!selection_defined(s)) return false; /* ignore Adjust drags */ + browser_window_set_selection(top, s); + if (pos >= 0) { selection_set_end(s, idx); @@ -385,6 +405,10 @@ void selection_track(struct selection *s, browser_mouse_state mouse, if (!SAME_SPACE(s, idx)) return; + if (!mouse) { + s->drag_state = DRAG_NONE; + } + switch (s->drag_state) { case DRAG_START: @@ -902,7 +926,8 @@ struct box *selection_get_end(struct selection *s, size_t *pidx) * \return true iff part of the given box lies within the selection */ -bool selection_highlighted(struct selection *s, unsigned start, unsigned end, +bool selection_highlighted(const struct selection *s, + unsigned start, unsigned end, unsigned *start_idx, unsigned *end_idx) { /* caller should have checked first for efficiency */ diff --git a/desktop/selection.h b/desktop/selection.h index 8dc3ce103..4b8bd8ec8 100644 --- a/desktop/selection.h +++ b/desktop/selection.h @@ -60,6 +60,7 @@ typedef bool (*seln_traverse_handler)(const char *text, size_t length, struct selection *selection_create(void); +void selection_prepare(struct selection *s); void selection_destroy(struct selection *s); void selection_init(struct selection *s, struct box *root); @@ -103,7 +104,8 @@ void selection_track(struct selection *s, browser_mouse_state mouse, bool selection_traverse(struct selection *s, seln_traverse_handler handler, void *handle); -bool selection_highlighted(struct selection *s, unsigned start, unsigned end, +bool selection_highlighted(const struct selection *s, + unsigned start, unsigned end, unsigned *start_idx, unsigned *end_idx); bool selection_save_text(struct selection *s, const char *path); diff --git a/desktop/textinput.c b/desktop/textinput.c index 32d8f5167..1879f414c 100644 --- a/desktop/textinput.c +++ b/desktop/textinput.c @@ -100,11 +100,7 @@ void browser_window_remove_caret(struct browser_window *bw) { struct browser_window *root_bw; - /* Find top level browser window */ - root_bw = bw; - while (root_bw && !root_bw->window && root_bw->parent) { - root_bw = root_bw->parent; - } + root_bw = browser_window_get_root(bw); gui_window_remove_caret(root_bw->window); @@ -113,8 +109,6 @@ void browser_window_remove_caret(struct browser_window *bw) bw->move_callback = NULL; bw->caret_p1 = NULL; bw->caret_p2 = NULL; - - selection_clear(bw->sel, true); } @@ -129,23 +123,25 @@ bool browser_window_key_press(struct browser_window *bw, uint32_t key) { struct browser_window *focus = bw->focus; + assert(bw->window != NULL); + /* keys that take effect wherever the caret is positioned */ switch (key) { case KEY_SELECT_ALL: - selection_select_all(focus->sel); + selection_select_all(bw->cur_sel); return true; case KEY_COPY_SELECTION: - gui_copy_to_clipboard(focus->sel); + gui_copy_to_clipboard(bw->cur_sel); return true; case KEY_CLEAR_SELECTION: - selection_clear(focus->sel, true); + selection_clear(bw->cur_sel, true); return true; case KEY_ESCAPE: - if (selection_defined(focus->sel)) { - selection_clear(focus->sel, true); + if (selection_defined(bw->cur_sel)) { + selection_clear(bw->cur_sel, true); return true; } /* if there's no selection, |