From 41e4928e25039119b97035640cf97b1949a129d4 Mon Sep 17 00:00:00 2001 From: Michael Drake Date: Mon, 11 Mar 2013 12:57:33 +0000 Subject: Fix pointer shape and status bar messages for textareas and their scrollbars. --- desktop/browser.c | 24 ++++++++++++------ desktop/scrollbar.c | 64 +++++++++++++++++++++++++++++++++++++++-------- desktop/scrollbar.h | 29 +++++++++++++++++++-- desktop/textarea.c | 61 ++++++++++++++++++++++++++++---------------- desktop/textarea.h | 26 ++++++++++++++++--- render/form.c | 5 ++-- render/html_interaction.c | 37 +++++++++++++++++++-------- 7 files changed, 188 insertions(+), 58 deletions(-) diff --git a/desktop/browser.c b/desktop/browser.c index 8d115e749..9d6786bd0 100644 --- a/desktop/browser.c +++ b/desktop/browser.c @@ -2618,8 +2618,10 @@ void browser_window_mouse_track(struct browser_window *bw, bw->drag_type == DRAGGING_NONE) || bw->drag_type == DRAGGING_SCR_X) { /* Start a scrollbar drag, or continue existing drag */ - status = scrollbar_mouse_action(bw->scroll_x, mouse, - scr_x, scr_y); + status = scrollbar_mouse_status_to_message( + scrollbar_mouse_action( + bw->scroll_x, mouse, + scr_x, scr_y)); pointer = BROWSER_POINTER_DEFAULT; if (status != NULL) @@ -2643,8 +2645,10 @@ void browser_window_mouse_track(struct browser_window *bw, bw->drag_type == DRAGGING_NONE) || bw->drag_type == DRAGGING_SCR_Y) { /* Start a scrollbar drag, or continue existing drag */ - status = scrollbar_mouse_action(bw->scroll_y, mouse, - scr_x, scr_y); + status = scrollbar_mouse_status_to_message( + scrollbar_mouse_action( + bw->scroll_y, mouse, + scr_x, scr_y)); pointer = BROWSER_POINTER_DEFAULT; if (status != NULL) @@ -2737,8 +2741,10 @@ void browser_window_mouse_click(struct browser_window *bw, if (scr_x > 0 && scr_x < browser_window_get_scrollbar_len(bw, true) && scr_y > 0 && scr_y < SCROLLBAR_WIDTH) { - status = scrollbar_mouse_action(bw->scroll_x, mouse, - scr_x, scr_y); + status = scrollbar_mouse_status_to_message( + scrollbar_mouse_action( + bw->scroll_x, mouse, + scr_x, scr_y)); pointer = BROWSER_POINTER_DEFAULT; if (status != NULL) @@ -2758,8 +2764,10 @@ void browser_window_mouse_click(struct browser_window *bw, if (scr_y > 0 && scr_y < browser_window_get_scrollbar_len(bw, false) && scr_x > 0 && scr_x < SCROLLBAR_WIDTH) { - status = scrollbar_mouse_action(bw->scroll_y, mouse, - scr_x, scr_y); + status = scrollbar_mouse_status_to_message( + scrollbar_mouse_action( + bw->scroll_y, mouse, + scr_x, scr_y)); pointer = BROWSER_POINTER_DEFAULT; if (status != NULL) diff --git a/desktop/scrollbar.c b/desktop/scrollbar.c index 7768be233..5517a6f0d 100644 --- a/desktop/scrollbar.c +++ b/desktop/scrollbar.c @@ -613,12 +613,12 @@ static void scrollbar_drag_start_internal(struct scrollbar *s, int x, int y, /* * Exported function. Documented in scrollbar.h */ -const char *scrollbar_mouse_action(struct scrollbar *s, +scrollbar_mouse_status scrollbar_mouse_action(struct scrollbar *s, browser_mouse_state mouse, int x, int y) { int x0, y0, x1, y1; int val; - const char *status; + scrollbar_mouse_status status = SCROLLBAR_MOUSE_NONE; bool h; /* we want mouse presses and mouse drags that were not started at the @@ -642,7 +642,7 @@ const char *scrollbar_mouse_action(struct scrollbar *s, if (!s->dragging && !(x >= x0 && x <= x1 && y >= y0 && y <= y1)) { /* Not a drag and mouse outside scrollbar widget */ - return NULL; + return SCROLLBAR_MOUSE_NONE; } @@ -660,9 +660,9 @@ const char *scrollbar_mouse_action(struct scrollbar *s, !(s->drag_content)); if (s->pair_drag) { scrollbar_mouse_action(s->pair, mouse, x, y); - status = messages_get("ScrollBoth"); + status = SCROLLBAR_MOUSE_BOTH; } else - status = messages_get(h ? "ScrollH" : "ScrollV"); + status = h ? SCROLLBAR_MOUSE_HRZ : SCROLLBAR_MOUSE_VRT; return status; } @@ -670,7 +670,7 @@ const char *scrollbar_mouse_action(struct scrollbar *s, if (val < SCROLLBAR_WIDTH) { /* left/up arrow */ - status = messages_get(h ? "ScrollLeft" : "ScrollUp"); + status = h ? SCROLLBAR_MOUSE_LFT : SCROLLBAR_MOUSE_UP; if (but1) scrollbar_set(s, s->offset - SCROLLBAR_WIDTH, false); else if (but2) @@ -679,7 +679,7 @@ const char *scrollbar_mouse_action(struct scrollbar *s, } else if (val < SCROLLBAR_WIDTH + s->bar_pos) { /* well between left/up arrow and bar */ - status = messages_get(h ? "ScrollPLeft" : "ScrollPUp"); + status = h ? SCROLLBAR_MOUSE_PLFT : SCROLLBAR_MOUSE_PUP; if (but1) scrollbar_set(s, s->offset - s->length, false); @@ -689,7 +689,7 @@ const char *scrollbar_mouse_action(struct scrollbar *s, } else if (val > s->length - SCROLLBAR_WIDTH) { /* right/down arrow */ - status = messages_get(h ? "ScrollRight" : "ScrollDown"); + status = h ? SCROLLBAR_MOUSE_RGT : SCROLLBAR_MOUSE_DWN; if (but1) scrollbar_set(s, s->offset + SCROLLBAR_WIDTH, false); @@ -700,7 +700,7 @@ const char *scrollbar_mouse_action(struct scrollbar *s, s->bar_len) { /* well between right/down arrow and bar */ - status = messages_get(h ? "ScrollPRight" : "ScrollPDown"); + status = h ? SCROLLBAR_MOUSE_PRGT : SCROLLBAR_MOUSE_PDWN; if (but1) scrollbar_set(s, s->offset + s->length, false); else if (but2) @@ -709,7 +709,7 @@ const char *scrollbar_mouse_action(struct scrollbar *s, else { /* scrollbar position indication bar */ - status = messages_get(h ? "ScrollH" : "ScrollV"); + status = h ? SCROLLBAR_MOUSE_HRZ : SCROLLBAR_MOUSE_VRT; } @@ -726,6 +726,50 @@ const char *scrollbar_mouse_action(struct scrollbar *s, } +/* + * Exported function. Documented in scrollbar.h + */ +const char *scrollbar_mouse_status_to_message(scrollbar_mouse_status status) +{ + switch ((unsigned int) status) { + case SCROLLBAR_MOUSE_UP: + case SCROLLBAR_MOUSE_UP | SCROLLBAR_MOUSE_USED: + return messages_get("ScrollUp"); + case SCROLLBAR_MOUSE_PUP: + case SCROLLBAR_MOUSE_PUP | SCROLLBAR_MOUSE_USED: + return messages_get("ScrollPUp"); + case SCROLLBAR_MOUSE_VRT: + case SCROLLBAR_MOUSE_VRT | SCROLLBAR_MOUSE_USED: + return messages_get("ScrollV"); + case SCROLLBAR_MOUSE_PDWN: + case SCROLLBAR_MOUSE_PDWN | SCROLLBAR_MOUSE_USED: + return messages_get("ScrollPDown"); + case SCROLLBAR_MOUSE_DWN: + case SCROLLBAR_MOUSE_DWN | SCROLLBAR_MOUSE_USED: + return messages_get("ScrollDown"); + case SCROLLBAR_MOUSE_LFT: + case SCROLLBAR_MOUSE_LFT | SCROLLBAR_MOUSE_USED: + return messages_get("ScrollLeft"); + case SCROLLBAR_MOUSE_PLFT: + case SCROLLBAR_MOUSE_PLFT | SCROLLBAR_MOUSE_USED: + return messages_get("ScrollPLeft"); + case SCROLLBAR_MOUSE_HRZ: + case SCROLLBAR_MOUSE_HRZ | SCROLLBAR_MOUSE_USED: + return messages_get("ScrollH"); + case SCROLLBAR_MOUSE_PRGT: + case SCROLLBAR_MOUSE_PRGT | SCROLLBAR_MOUSE_USED: + return messages_get("ScrollPRight"); + case SCROLLBAR_MOUSE_RGT: + case SCROLLBAR_MOUSE_RGT | SCROLLBAR_MOUSE_USED: + return messages_get("ScrollRight"); + default: + break; + } + + return NULL; +} + + /* * Exported function. Documented in scrollbar.h */ diff --git a/desktop/scrollbar.h b/desktop/scrollbar.h index 2ce4a154e..fb1773761 100644 --- a/desktop/scrollbar.h +++ b/desktop/scrollbar.h @@ -152,6 +152,23 @@ void scrollbar_set_extents(struct scrollbar *s, int length, */ bool scrollbar_is_horizontal(struct scrollbar *s); +/* Scrollbar mouse input status flags */ +typedef enum { + SCROLLBAR_MOUSE_NONE = 0, /**< Not relevant */ + SCROLLBAR_MOUSE_USED = (1 << 0), /**< Took action with input */ + SCROLLBAR_MOUSE_BOTH = (1 << 1), /**< Scrolling both bars */ + SCROLLBAR_MOUSE_UP = (1 << 2), /**< Hover: scroll up */ + SCROLLBAR_MOUSE_PUP = (1 << 3), /**< Hover: scroll page up */ + SCROLLBAR_MOUSE_VRT = (1 << 4), /**< Hover: vert. drag bar */ + SCROLLBAR_MOUSE_PDWN = (1 << 5), /**< Hover: scroll page down */ + SCROLLBAR_MOUSE_DWN = (1 << 6), /**< Hover: scroll down */ + SCROLLBAR_MOUSE_LFT = (1 << 7), /**< Hover: scroll left */ + SCROLLBAR_MOUSE_PLFT = (1 << 8), /**< Hover: scroll page left */ + SCROLLBAR_MOUSE_HRZ = (1 << 9), /**< Hover: horiz. drag bar */ + SCROLLBAR_MOUSE_PRGT = (1 << 10), /**< Hover: scroll page right */ + SCROLLBAR_MOUSE_RGT = (1 << 11) /**< Hover: scroll right */ +} scrollbar_mouse_status; + /** * Handle mouse actions other then drag ends. * @@ -159,11 +176,19 @@ bool scrollbar_is_horizontal(struct scrollbar *s); * \param mouse mouse state * \param x X coordinate of the mouse * \param y Y coordinate of the mouse - * \return message for the status bar or NULL on failure + * \return the scrollbar mouse status */ -const char *scrollbar_mouse_action(struct scrollbar *s, +scrollbar_mouse_status scrollbar_mouse_action(struct scrollbar *s, browser_mouse_state mouse, int x, int y); +/** + * Get a status bar message from a scrollbar mouse input status. + * + * \param status Status to convert to message + * \return Message for the status bar or NULL on failure + */ +const char *scrollbar_mouse_status_to_message(scrollbar_mouse_status status); + /** * Handle end of mouse drags. * diff --git a/desktop/textarea.c b/desktop/textarea.c index 46de70639..b73ebbfc1 100644 --- a/desktop/textarea.c +++ b/desktop/textarea.c @@ -2236,14 +2236,17 @@ bool textarea_keypress(struct textarea *ta, uint32_t key) * \param mouse the mouse state at action moment * \param x X coordinate * \param y Y coordinate - * \return true if action was handled false otherwise + * \return textarea mouse state */ -static bool textarea_mouse_scrollbar_action(struct textarea *ta, - browser_mouse_state mouse, int x, int y) +static textarea_mouse_status textarea_mouse_scrollbar_action( + struct textarea *ta, browser_mouse_state mouse, int x, int y) { int sx, sy; /* xy coord offset for scrollbar */ int sl; /* scrollbar length */ + assert(SCROLLBAR_MOUSE_USED == (1 << 0)); + assert(TEXTAREA_MOUSE_SCR_USED == (1 << 3)); + /* Existing scrollbar drag */ if (ta->drag_info.type == TEXTAREA_DRAG_SCROLLBAR) { /* Scrollbar drag in progress; pass input to scrollbar */ @@ -2256,9 +2259,8 @@ static bool textarea_mouse_scrollbar_action(struct textarea *ta, SCROLLBAR_WIDTH; y -= ta->border_width; } - scrollbar_mouse_action(ta->drag_info.data.scrollbar, - mouse, x, y); - return true; + return (scrollbar_mouse_action(ta->drag_info.data.scrollbar, + mouse, x, y) << 3); } /* Horizontal scrollbar */ @@ -2271,8 +2273,8 @@ static bool textarea_mouse_scrollbar_action(struct textarea *ta, (ta->bar_y != NULL ? SCROLLBAR_WIDTH : 0); if (sx >= 0 && sy >= 0 && sx < sl && sy < SCROLLBAR_WIDTH) { - scrollbar_mouse_action(ta->bar_x, mouse, sx, sy); - return true; + return (scrollbar_mouse_action(ta->bar_x, mouse, + sx, sy) << 3); } } @@ -2285,22 +2287,23 @@ static bool textarea_mouse_scrollbar_action(struct textarea *ta, sl = ta->vis_height - 2 * ta->border_width; if (sx >= 0 && sy >= 0 && sx < SCROLLBAR_WIDTH && sy < sl) { - scrollbar_mouse_action(ta->bar_y, mouse, sx, sy); - return true; + return (scrollbar_mouse_action(ta->bar_y, mouse, + sx, sy) << 3); } } - return false; + return TEXTAREA_MOUSE_NONE; } /* exported interface, documented in textarea.h */ -bool textarea_mouse_action(struct textarea *ta, browser_mouse_state mouse, - int x, int y) +textarea_mouse_status textarea_mouse_action(struct textarea *ta, + browser_mouse_state mouse, int x, int y) { int c_start, c_end; unsigned int c_off; struct textarea_msg msg; + textarea_mouse_status status = TEXTAREA_MOUSE_NONE; if (ta->drag_info.type != TEXTAREA_DRAG_NONE && mouse == BROWSER_MOUSE_HOVER) { @@ -2309,21 +2312,26 @@ bool textarea_mouse_action(struct textarea *ta, browser_mouse_state mouse, } /* Mouse action might be a scrollbar's responsibility */ - if (textarea_mouse_scrollbar_action(ta, mouse, x, y)) { + status = textarea_mouse_scrollbar_action(ta, mouse, x, y); + if (status != TEXTAREA_MOUSE_NONE) { /* Mouse action was handled by a scrollbar */ - return true; + return status; } + status |= TEXTAREA_MOUSE_EDITOR; + /* Mouse action is textarea's responsibility */ if (mouse & BROWSER_MOUSE_DOUBLE_CLICK) { /* Select word */ textarea_set_caret_xy(ta, x, y); - return textarea_select_fragment(ta); + textarea_select_fragment(ta); + status |= TEXTAREA_MOUSE_USED; } else if (mouse & BROWSER_MOUSE_TRIPLE_CLICK) { /* Select paragraph */ textarea_set_caret_xy(ta, x, y); - return textarea_select_paragraph(ta); + textarea_select_paragraph(ta); + status |= TEXTAREA_MOUSE_USED; } else if (mouse & BROWSER_MOUSE_PRESS_1) { /* Place caret */ @@ -2335,6 +2343,7 @@ bool textarea_mouse_action(struct textarea *ta, browser_mouse_state mouse, /* Clear selection */ textarea_clear_selection(ta); } + status |= TEXTAREA_MOUSE_USED; } else if (mouse & BROWSER_MOUSE_PRESS_2) { c_start = textarea_get_caret(ta); @@ -2347,12 +2356,13 @@ bool textarea_mouse_action(struct textarea *ta, browser_mouse_state mouse, c_start = ((unsigned)c_start > c_off) ? ta->sel_end : ta->sel_start; ta->drag_start_char = c_start; - return textarea_select(ta, c_start, c_off, false); + textarea_select(ta, c_start, c_off, false); } else { /* Select to caret */ ta->drag_start_char = c_start; - return textarea_select(ta, c_start, c_off, false); + textarea_select(ta, c_start, c_off, false); } + status |= TEXTAREA_MOUSE_USED; } else if (mouse & (BROWSER_MOUSE_DRAG_1 | BROWSER_MOUSE_DRAG_2)) { /* Selection start */ @@ -2367,7 +2377,8 @@ bool textarea_mouse_action(struct textarea *ta, browser_mouse_state mouse, ta->callback(ta->data, &msg); - return textarea_select(ta, c_start, c_end, false); + textarea_select(ta, c_start, c_end, false); + status |= TEXTAREA_MOUSE_USED; } else if (mouse & (BROWSER_MOUSE_HOLDING_1 | BROWSER_MOUSE_HOLDING_2) && @@ -2400,10 +2411,16 @@ bool textarea_mouse_action(struct textarea *ta, browser_mouse_state mouse, need_redraw = textarea_scroll(ta, scrx, scry); - return textarea_select(ta, c_start, c_end, need_redraw); + textarea_select(ta, c_start, c_end, need_redraw); + status |= TEXTAREA_MOUSE_USED; } - return true; + if (ta->sel_start != -1) { + /* Have selection */ + status |= TEXTAREA_MOUSE_SELECTION; + } + + return status; } diff --git a/desktop/textarea.h b/desktop/textarea.h index befd6aa99..8652c5436 100644 --- a/desktop/textarea.h +++ b/desktop/textarea.h @@ -196,6 +196,26 @@ void textarea_redraw(struct textarea *ta, int x, int y, colour bg, float scale, */ bool textarea_keypress(struct textarea *ta, uint32_t key); +/* Text area mouse input status flags */ +typedef enum { + TEXTAREA_MOUSE_NONE = 0, /**< Not relevant */ + TEXTAREA_MOUSE_USED = (1 << 0), /**< Took action with input */ + TEXTAREA_MOUSE_EDITOR = (1 << 1), /**< Hover: caret pointer */ + TEXTAREA_MOUSE_SELECTION= (1 << 2), /**< Hover: selection */ + TEXTAREA_MOUSE_SCR_USED = (1 << 3), /**< Scrollbar action */ + TEXTAREA_MOUSE_SCR_BOTH = (1 << 4), /**< Scrolling both bars */ + TEXTAREA_MOUSE_SCR_UP = (1 << 5), /**< Hover: scroll up */ + TEXTAREA_MOUSE_SCR_PUP = (1 << 6), /**< Hover: scroll page up */ + TEXTAREA_MOUSE_SCR_VRT = (1 << 7), /**< Hover: vert. drag bar */ + TEXTAREA_MOUSE_SCR_PDWN = (1 << 8), /**< Hover: scroll page down */ + TEXTAREA_MOUSE_SCR_DWN = (1 << 9), /**< Hover: scroll down */ + TEXTAREA_MOUSE_SCR_LFT = (1 << 10), /**< Hover: scroll left */ + TEXTAREA_MOUSE_SCR_PLFT = (1 << 11), /**< Hover: scroll page left */ + TEXTAREA_MOUSE_SCR_HRZ = (1 << 12), /**< Hover: horiz. drag bar */ + TEXTAREA_MOUSE_SCR_PRGT = (1 << 13), /**< Hover: scroll page right */ + TEXTAREA_MOUSE_SCR_RGT = (1 << 14) /**< Hover: scroll right */ +} textarea_mouse_status; + /** * Handles all kinds of mouse action * @@ -203,10 +223,10 @@ bool textarea_keypress(struct textarea *ta, uint32_t key); * \param mouse the mouse state at action moment * \param x X coordinate * \param y Y coordinate - * \return true if action was handled false otherwise + * \return the textarea mouse status */ -bool textarea_mouse_action(struct textarea *ta, browser_mouse_state mouse, - int x, int y); +textarea_mouse_status textarea_mouse_action(struct textarea *ta, + browser_mouse_state mouse, int x, int y); /** * Clear any selection in the textarea. diff --git a/render/form.c b/render/form.c index 46d5b28f6..a6784e26f 100644 --- a/render/form.c +++ b/render/form.c @@ -1249,8 +1249,9 @@ const char *form_select_mouse_action(struct form_control *control, * event is taking place on the scrollbar widget area */ x -= scrollbar_x; - return scrollbar_mouse_action(menu->scrollbar, - mouse, x, y); + return scrollbar_mouse_status_to_message( + scrollbar_mouse_action(menu->scrollbar, + mouse, x, y)); } diff --git a/render/html_interaction.c b/render/html_interaction.c index aa6fc1126..a5f263b68 100644 --- a/render/html_interaction.c +++ b/render/html_interaction.c @@ -376,15 +376,19 @@ void html_mouse_action(struct content *c, struct browser_window *bw, scroll_mouse_y = y - (box_y + box->padding[TOP] + box->height + box->padding[BOTTOM] - SCROLLBAR_WIDTH); - status = scrollbar_mouse_action(scr, mouse, - scroll_mouse_x, scroll_mouse_y); + status = scrollbar_mouse_status_to_message( + 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(scr, mouse, - scroll_mouse_x, scroll_mouse_y); + status = scrollbar_mouse_status_to_message( + scrollbar_mouse_action(scr, mouse, + scroll_mouse_x, + scroll_mouse_y)); } msg_data.explicit_status_text = status; @@ -586,10 +590,14 @@ void html_mouse_action(struct content *c, struct browser_window *bw, * mistake; they will refer to the last box returned by box_at_point */ if (scrollbar) { - status = scrollbar_mouse_action(scrollbar, mouse, - scroll_mouse_x, scroll_mouse_y); + status = scrollbar_mouse_status_to_message( + scrollbar_mouse_action(scrollbar, mouse, + scroll_mouse_x, + scroll_mouse_y)); pointer = BROWSER_POINTER_DEFAULT; } else if (gadget) { + textarea_mouse_status ta_status; + switch (gadget->type) { case GADGET_SELECT: status = messages_get("FormSelect"); @@ -600,7 +608,7 @@ void html_mouse_action(struct content *c, struct browser_window *bw, form_open_select_menu(c, gadget, form_select_menu_callback, c); - pointer = BROWSER_POINTER_DEFAULT; + pointer = BROWSER_POINTER_DEFAULT; } else if (mouse & BROWSER_MOUSE_CLICK_1) gui_create_form_select_menu(bw, gadget); break; @@ -644,8 +652,6 @@ void html_mouse_action(struct content *c, struct browser_window *bw, else status = messages_get("FormTextbox"); - pointer = get_pointer_shape(gadget_box, false); - if (click && (html->selection_type != HTML_SELECTION_TEXTAREA || html->selection_owner.textarea != @@ -655,8 +661,17 @@ void html_mouse_action(struct content *c, struct browser_window *bw, sel_owner, true); } - textarea_mouse_action(gadget->data.text.ta, mouse, - x - gadget_box_x, y - gadget_box_y); + ta_status = textarea_mouse_action(gadget->data.text.ta, + mouse, x - gadget_box_x, + y - gadget_box_y); + + if (ta_status & TEXTAREA_MOUSE_EDITOR) { + pointer = get_pointer_shape(gadget_box, false); + } else { + pointer = BROWSER_POINTER_DEFAULT; + status = scrollbar_mouse_status_to_message( + ta_status >> 3); + } break; case GADGET_HIDDEN: /* not possible: no box generated */ -- cgit v1.2.3