summaryrefslogtreecommitdiff
path: root/desktop
diff options
context:
space:
mode:
authorMichael Drake <tlsa@netsurf-browser.org>2011-07-13 13:20:26 +0000
committerMichael Drake <tlsa@netsurf-browser.org>2011-07-13 13:20:26 +0000
commit9c918930289b18dbfd4bb44081891d5780105bfd (patch)
tree372de7dbf3d8393550e46ab1f8de6e9a97cf2140 /desktop
parent1832155b7c64e0a977541930fc78f47bbd675ab2 (diff)
downloadnetsurf-9c918930289b18dbfd4bb44081891d5780105bfd.tar.gz
netsurf-9c918930289b18dbfd4bb44081891d5780105bfd.tar.bz2
Fix selection for non-gui browser windows (iframes).
Selection no longer uses current_redraw_browser. Fix long-standing selection bugs on platforms that use action on release behaviour. svn path=/trunk/netsurf/; revision=12598
Diffstat (limited to 'desktop')
-rw-r--r--desktop/browser.c91
-rw-r--r--desktop/browser.h23
-rw-r--r--desktop/frames.c7
-rw-r--r--desktop/selection.c37
-rw-r--r--desktop/selection.h4
-rw-r--r--desktop/textinput.c20
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,