From 0a8ed41a1ad470bb62c908d0dc6272c1c541a1f2 Mon Sep 17 00:00:00 2001 From: Vincent Sanders Date: Fri, 2 Aug 2019 22:07:59 +0100 Subject: [PATCH] change browser_window_mouse_click to use unscaled coordinates this means frontends no longer need to scale mouse click events thus simplifying their implementation. --- content/handlers/html/html_interaction.c | 10 +- desktop/browser_window.c | 256 ++++++++++++----------- frontends/amiga/gui.c | 4 +- frontends/beos/window.cpp | 8 +- frontends/framebuffer/gui.c | 21 +- frontends/gtk/scaffolding.c | 8 +- frontends/gtk/window.c | 23 +- frontends/riscos/window.c | 24 ++- frontends/windows/drawable.c | 14 +- 9 files changed, 201 insertions(+), 167 deletions(-) diff --git a/content/handlers/html/html_interaction.c b/content/handlers/html/html_interaction.c index 985b325e2..b6b9de89a 100644 --- a/content/handlers/html/html_interaction.c +++ b/content/handlers/html/html_interaction.c @@ -843,14 +843,14 @@ void html_mouse_action(struct content *c, struct browser_window *bw, browser_window_get_position(iframe, false, &pos_x, &pos_y); - pos_x /= scale; - pos_y /= scale; - if (mouse & BROWSER_MOUSE_CLICK_1 || - mouse & BROWSER_MOUSE_CLICK_2) { + mouse & BROWSER_MOUSE_CLICK_2) { browser_window_mouse_click(iframe, mouse, - x - pos_x, y - pos_y); + (x * scale) - pos_x, + (y * scale) - pos_y); } else { + pos_x /= scale; + pos_y /= scale; browser_window_mouse_track(iframe, mouse, x - pos_x, y - pos_y); } diff --git a/desktop/browser_window.c b/desktop/browser_window.c index ccab57f17..659eabd7c 100644 --- a/desktop/browser_window.c +++ b/desktop/browser_window.c @@ -1485,6 +1485,137 @@ browser_window_mouse_drag_end(struct browser_window *bw, } } +/** + * Process mouse click event + * + * \param bw The browsing context receiving the event + * \param mouse The mouse event state + * \param x The scaled x co-ordinate of the event + * \param y The scaled y co-ordinate of the event + */ +static void +browser_window_mouse_click_internal(struct browser_window *bw, + browser_mouse_state mouse, + int x, int y) +{ + hlcache_handle *c = bw->current_content; + const char *status = NULL; + browser_pointer_shape pointer = BROWSER_POINTER_DEFAULT; + + if (bw->children) { + /* Browser window has children (frames) */ + struct browser_window *child; + int cur_child; + int children = bw->rows * bw->cols; + + for (cur_child = 0; cur_child < children; cur_child++) { + + child = &bw->children[cur_child]; + + if ((x < child->x) || + (y < child->y) || + (child->x + child->width < x) || + (child->y + child->height < y)) { + /* Click not in this child */ + continue; + } + + /* It's this child that contains the click; pass it + * on to child. */ + browser_window_mouse_click_internal(child, mouse, + x - child->x + scrollbar_get_offset( + child->scroll_x), + y - child->y + scrollbar_get_offset( + child->scroll_y)); + + /* Mouse action was for this child, we're done */ + return; + } + + return; + } + + if (!c) + return; + + if (bw->scroll_x != NULL) { + int scr_x, scr_y; + browser_window_get_scrollbar_pos(bw, true, &scr_x, &scr_y); + scr_x = x - scr_x - scrollbar_get_offset(bw->scroll_x); + scr_y = y - scr_y - scrollbar_get_offset(bw->scroll_y); + + if (scr_x > 0 && scr_x < get_horz_scrollbar_len(bw) && + scr_y > 0 && scr_y < SCROLLBAR_WIDTH) { + status = scrollbar_mouse_status_to_message( + scrollbar_mouse_action( + bw->scroll_x, mouse, + scr_x, scr_y)); + pointer = BROWSER_POINTER_DEFAULT; + + if (status != NULL) + browser_window_set_status(bw, status); + + browser_window_set_pointer(bw, pointer); + return; + } + } + + if (bw->scroll_y != NULL) { + int scr_x, scr_y; + browser_window_get_scrollbar_pos(bw, false, &scr_x, &scr_y); + scr_x = x - scr_x - scrollbar_get_offset(bw->scroll_x); + scr_y = y - scr_y - scrollbar_get_offset(bw->scroll_y); + + if (scr_y > 0 && scr_y < get_vert_scrollbar_len(bw) && + scr_x > 0 && scr_x < SCROLLBAR_WIDTH) { + status = scrollbar_mouse_status_to_message( + scrollbar_mouse_action( + bw->scroll_y, mouse, + scr_x, scr_y)); + pointer = BROWSER_POINTER_DEFAULT; + + if (status != NULL) + browser_window_set_status(bw, status); + + browser_window_set_pointer(bw, pointer); + return; + } + } + + switch (content_get_type(c)) { + case CONTENT_HTML: + case CONTENT_TEXTPLAIN: + { + /* Give bw focus */ + struct browser_window *root_bw = browser_window_get_root(bw); + if (bw != root_bw->focus) { + browser_window_remove_caret(bw, false); + browser_window_set_selection(bw, false, true); + root_bw->focus = bw; + } + + /* Pass mouse action to content */ + content_mouse_action(c, bw, mouse, x, y); + } + break; + default: + if (mouse & BROWSER_MOUSE_MOD_2) { + if (mouse & BROWSER_MOUSE_DRAG_2) { + guit->window->drag_save_object(bw->window, c, + GUI_SAVE_OBJECT_NATIVE); + } else if (mouse & BROWSER_MOUSE_DRAG_1) { + guit->window->drag_save_object(bw->window, c, + GUI_SAVE_OBJECT_ORIG); + } + } else if (mouse & (BROWSER_MOUSE_DRAG_1 | + BROWSER_MOUSE_DRAG_2)) { + browser_window_page_drag_start(bw, x, y); + browser_window_set_pointer(bw, BROWSER_POINTER_MOVE); + } + break; + } +} + /* exported interface, documented in netsurf/browser_window.h */ nserror @@ -3316,124 +3447,15 @@ void browser_window_mouse_track(struct browser_window *bw, /* exported interface documented in netsurf/browser_window.h */ -void browser_window_mouse_click(struct browser_window *bw, - browser_mouse_state mouse, int x, int y) +void +browser_window_mouse_click(struct browser_window *bw, + browser_mouse_state mouse, + int x, int y) { - hlcache_handle *c = bw->current_content; - const char *status = NULL; - browser_pointer_shape pointer = BROWSER_POINTER_DEFAULT; - - if (bw->children) { - /* Browser window has children (frames) */ - struct browser_window *child; - int cur_child; - int children = bw->rows * bw->cols; - - for (cur_child = 0; cur_child < children; cur_child++) { - - child = &bw->children[cur_child]; - - if (x < child->x || y < child->y || - child->x + child->width < x || - child->y + child->height < y) { - /* Click not in this child */ - continue; - } - - /* It's this child that contains the click; pass it - * on to child. */ - browser_window_mouse_click(child, mouse, - x - child->x + scrollbar_get_offset( - child->scroll_x), - y - child->y + scrollbar_get_offset( - child->scroll_y)); - - /* Mouse action was for this child, we're done */ - return; - } - - return; - } - - if (!c) - return; - - if (bw->scroll_x != NULL) { - int scr_x, scr_y; - browser_window_get_scrollbar_pos(bw, true, &scr_x, &scr_y); - scr_x = x - scr_x - scrollbar_get_offset(bw->scroll_x); - scr_y = y - scr_y - scrollbar_get_offset(bw->scroll_y); - - if (scr_x > 0 && scr_x < get_horz_scrollbar_len(bw) && - scr_y > 0 && scr_y < SCROLLBAR_WIDTH) { - status = scrollbar_mouse_status_to_message( - scrollbar_mouse_action( - bw->scroll_x, mouse, - scr_x, scr_y)); - pointer = BROWSER_POINTER_DEFAULT; - - if (status != NULL) - browser_window_set_status(bw, status); - - browser_window_set_pointer(bw, pointer); - return; - } - } - - if (bw->scroll_y != NULL) { - int scr_x, scr_y; - browser_window_get_scrollbar_pos(bw, false, &scr_x, &scr_y); - scr_x = x - scr_x - scrollbar_get_offset(bw->scroll_x); - scr_y = y - scr_y - scrollbar_get_offset(bw->scroll_y); - - if (scr_y > 0 && scr_y < get_vert_scrollbar_len(bw) && - scr_x > 0 && scr_x < SCROLLBAR_WIDTH) { - status = scrollbar_mouse_status_to_message( - scrollbar_mouse_action( - bw->scroll_y, mouse, - scr_x, scr_y)); - pointer = BROWSER_POINTER_DEFAULT; - - if (status != NULL) - browser_window_set_status(bw, status); - - browser_window_set_pointer(bw, pointer); - return; - } - } - - switch (content_get_type(c)) { - case CONTENT_HTML: - case CONTENT_TEXTPLAIN: - { - /* Give bw focus */ - struct browser_window *root_bw = browser_window_get_root(bw); - if (bw != root_bw->focus) { - browser_window_remove_caret(bw, false); - browser_window_set_selection(bw, false, true); - root_bw->focus = bw; - } - - /* Pass mouse action to content */ - content_mouse_action(c, bw, mouse, x, y); - } - break; - default: - if (mouse & BROWSER_MOUSE_MOD_2) { - if (mouse & BROWSER_MOUSE_DRAG_2) { - guit->window->drag_save_object(bw->window, c, - GUI_SAVE_OBJECT_NATIVE); - } else if (mouse & BROWSER_MOUSE_DRAG_1) { - guit->window->drag_save_object(bw->window, c, - GUI_SAVE_OBJECT_ORIG); - } - } else if (mouse & (BROWSER_MOUSE_DRAG_1 | - BROWSER_MOUSE_DRAG_2)) { - browser_window_page_drag_start(bw, x, y); - browser_window_set_pointer(bw, BROWSER_POINTER_MOVE); - } - break; - } + browser_window_mouse_click_internal(bw, + mouse, + (x / bw->scale), + (y / bw->scale)); } diff --git a/frontends/amiga/gui.c b/frontends/amiga/gui.c index e90f0d3c7..59b621060 100644 --- a/frontends/amiga/gui.c +++ b/frontends/amiga/gui.c @@ -2499,8 +2499,8 @@ static BOOL ami_gui_event(void *w) return FALSE; } - x = (ULONG)((gwin->win->MouseX - bbox->Left) / gwin->gw->scale); - y = (ULONG)((gwin->win->MouseY - bbox->Top) / gwin->gw->scale); + x = (ULONG)(gwin->win->MouseX - bbox->Left); + y = (ULONG)(gwin->win->MouseY - bbox->Top); ami_get_hscroll_pos(gwin, (ULONG *)&xs); ami_get_vscroll_pos(gwin, (ULONG *)&ys); diff --git a/frontends/beos/window.cpp b/frontends/beos/window.cpp index 6c12e4e8e..020c86feb 100644 --- a/frontends/beos/window.cpp +++ b/frontends/beos/window.cpp @@ -562,8 +562,8 @@ void nsbeos_dispatch_event(BMessage *message) if (mods & B_CONTROL_KEY) gui->mouse.state |= BROWSER_MOUSE_MOD_2; - gui->mouse.pressed_x = where.x / gui->scale; - gui->mouse.pressed_y = where.y / gui->scale; + gui->mouse.pressed_x = where.x; + gui->mouse.pressed_y = where.y; // make sure the view is in focus if (view && view->LockLooper()) { @@ -624,8 +624,8 @@ void nsbeos_dispatch_event(BMessage *message) if (gui->mouse.state & (BROWSER_MOUSE_CLICK_1|BROWSER_MOUSE_CLICK_2)) browser_window_mouse_click(gui->bw, (browser_mouse_state)gui->mouse.state, - where.x / gui->scale, - where.y / gui->scale); + where.x, + where.y); else browser_window_mouse_track(gui->bw, (browser_mouse_state)0, where.x, where.y); diff --git a/frontends/framebuffer/gui.c b/frontends/framebuffer/gui.c index 09216ee3a..957223407 100644 --- a/frontends/framebuffer/gui.c +++ b/frontends/framebuffer/gui.c @@ -628,8 +628,8 @@ fb_browser_window_click(fbtk_widget_t *widget, fbtk_callback_info *cbi) struct browser_widget_s *bwidget = fbtk_get_userpw(widget); browser_mouse_state mouse; float scale = browser_window_get_scale(gw->bw); - int x = (cbi->x + bwidget->scrollx) / scale; - int y = (cbi->y + bwidget->scrolly) / scale; + int x = cbi->x + bwidget->scrollx; + int y = cbi->y + bwidget->scrolly; uint64_t time_now; static struct { enum { CLICK_SINGLE, CLICK_DOUBLE, CLICK_TRIPLE } type; @@ -640,8 +640,7 @@ fb_browser_window_click(fbtk_widget_t *widget, fbtk_callback_info *cbi) cbi->event->type != NSFB_EVENT_KEY_UP) return 0; - NSLOG(netsurf, INFO, "browser window clicked at %d,%d", cbi->x, - cbi->y); + NSLOG(netsurf, INFO, "browser window clicked at %d,%d", cbi->x, cbi->y); switch (cbi->event->type) { case NSFB_EVENT_KEY_DOWN: @@ -666,14 +665,14 @@ fb_browser_window_click(fbtk_widget_t *widget, fbtk_callback_info *cbi) case NSFB_KEY_MOUSE_4: /* scroll up */ - if (browser_window_scroll_at_point(gw->bw, x, y, + if (browser_window_scroll_at_point(gw->bw, x/scale, y/scale, 0, -100) == false) widget_scroll_y(gw, -100, false); break; case NSFB_KEY_MOUSE_5: /* scroll down */ - if (browser_window_scroll_at_point(gw->bw, x, y, + if (browser_window_scroll_at_point(gw->bw, x/scale, y/scale, 0, 100) == false) widget_scroll_y(gw, 100, false); break; @@ -703,7 +702,7 @@ fb_browser_window_click(fbtk_widget_t *widget, fbtk_callback_info *cbi) gui_drag.state = GUI_DRAG_NONE; /* Tell core */ - browser_window_mouse_track(gw->bw, 0, x, y); + browser_window_mouse_track(gw->bw, 0, x/scale, y/scale); break; } /* This is a click; @@ -724,7 +723,7 @@ fb_browser_window_click(fbtk_widget_t *widget, fbtk_callback_info *cbi) } /* Tell core */ - browser_window_mouse_track(gw->bw, 0, x, y); + browser_window_mouse_track(gw->bw, 0, x/scale, y/scale); break; } /* This is a click; @@ -783,8 +782,8 @@ fb_browser_window_move(fbtk_widget_t *widget, fbtk_callback_info *cbi) struct gui_window *gw = cbi->context; struct browser_widget_s *bwidget = fbtk_get_userpw(widget); float scale = browser_window_get_scale(gw->bw); - int x = (cbi->x + bwidget->scrollx) / scale; - int y = (cbi->y + bwidget->scrolly) / scale; + int x = cbi->x + bwidget->scrollx; + int y = cbi->y + bwidget->scrolly; if (gui_drag.state == GUI_DRAG_PRESSED && (abs(x - gui_drag.x) > 5 || @@ -813,7 +812,7 @@ fb_browser_window_move(fbtk_widget_t *widget, fbtk_callback_info *cbi) mouse |= BROWSER_MOUSE_HOLDING_2; } - browser_window_mouse_track(gw->bw, mouse, x, y); + browser_window_mouse_track(gw->bw, mouse, x/scale, y/scale); return 0; } diff --git a/frontends/gtk/scaffolding.c b/frontends/gtk/scaffolding.c index 8c46fd884..6b6f936ff 100644 --- a/frontends/gtk/scaffolding.c +++ b/frontends/gtk/scaffolding.c @@ -2715,10 +2715,14 @@ void nsgtk_scaffolding_context_menu(struct nsgtk_scaffolding *g, gdouble y) { GtkMenu *gtkmenu; + struct browser_window *bw; + float scale; + + bw = nsgtk_get_browser_window(g->top_level); + scale = browser_window_get_scale(bw); /* update the global context menu features */ - browser_window_get_features(nsgtk_get_browser_window(g->top_level), - x, y, ¤t_menu_features); + browser_window_get_features(bw, x/scale, y/scale, ¤t_menu_features); if (current_menu_features.link != NULL) { /* menu is opening over a link */ diff --git a/frontends/gtk/window.c b/frontends/gtk/window.c index aab4597dc..341eb5db8 100644 --- a/frontends/gtk/window.c +++ b/frontends/gtk/window.c @@ -332,8 +332,13 @@ static gboolean nsgtk_window_motion_notify_event(GtkWidget *widget, return TRUE; } -static gboolean nsgtk_window_button_press_event(GtkWidget *widget, - GdkEventButton *event, gpointer data) +/** + * GTK signal handler for button-press-event on layout + */ +static gboolean +nsgtk_window_button_press_event(GtkWidget *widget, + GdkEventButton *event, + gpointer data) { struct gui_window *g = data; @@ -341,8 +346,8 @@ static gboolean nsgtk_window_button_press_event(GtkWidget *widget, gtk_widget_grab_focus(GTK_WIDGET(g->layout)); nsgtk_local_history_hide(); - g->mouse.pressed_x = event->x / browser_window_get_scale(g->bw); - g->mouse.pressed_y = event->y / browser_window_get_scale(g->bw); + g->mouse.pressed_x = event->x; + g->mouse.pressed_y = event->y; switch (event->button) { case 1: /* Left button, usually. Pass to core as BUTTON 1. */ @@ -382,8 +387,10 @@ static gboolean nsgtk_window_button_press_event(GtkWidget *widget, g->last_x = event->x; g->last_y = event->y; - browser_window_mouse_click(g->bw, g->mouse.state, g->mouse.pressed_x, - g->mouse.pressed_y); + browser_window_mouse_click(g->bw, + g->mouse.state, + g->mouse.pressed_x, + g->mouse.pressed_y); return TRUE; } @@ -410,8 +417,8 @@ static gboolean nsgtk_window_button_release_event(GtkWidget *widget, if (g->mouse.state & (BROWSER_MOUSE_CLICK_1 | BROWSER_MOUSE_CLICK_2)) { browser_window_mouse_click(g->bw, g->mouse.state, - event->x / browser_window_get_scale(g->bw), - event->y / browser_window_get_scale(g->bw)); + event->x, + event->y); } else { browser_window_mouse_track(g->bw, 0, event->x / browser_window_get_scale(g->bw), diff --git a/frontends/riscos/window.c b/frontends/riscos/window.c index b949c02ef..c439b655b 100644 --- a/frontends/riscos/window.c +++ b/frontends/riscos/window.c @@ -1152,10 +1152,12 @@ ro_gui_window_scroll_action(struct gui_window *g, */ if (pointer.w == g->window && - ro_gui_window_to_window_pos(g, - pointer.pos.x, pointer.pos.y, &pos)) - handled = browser_window_scroll_at_point(g->bw, pos.x, pos.y, - step_x, step_y); + ro_gui_window_to_window_pos(g, pointer.pos.x, pointer.pos.y, &pos)) + handled = browser_window_scroll_at_point(g->bw, + pos.x/g->scale, + pos.y/g->scale, + step_x, + step_y); /* If the core didn't do the scrolling, handle it via the Wimp. * Windows which contain frames can only be scrolled by the core, @@ -1249,7 +1251,7 @@ ro_gui_window_handle_local_keypress(struct gui_window *g, if (!ro_gui_window_to_window_pos(g, pointer.pos.x, pointer.pos.y, &pos)) return false; - browser_window_get_features(g->bw, pos.x, pos.y, &cont); + browser_window_get_features(g->bw, pos.x/g->scale, pos.y/g->scale, &cont); switch (c) { case IS_WIMP_KEY + wimp_KEY_F1: /* Help. */ @@ -2169,7 +2171,7 @@ ro_gui_window_menu_prepare(wimp_w w, if (ro_gui_window_to_window_pos(g, pointer->pos.x, pointer->pos.y, &pos)) { - browser_window_get_features(bw, pos.x, pos.y, &cont); + browser_window_get_features(bw, pos.x/g->scale, pos.y/g->scale, &cont); current_menu_main = cont.main; current_menu_object = cont.object; @@ -3830,7 +3832,7 @@ static void ro_gui_window_scroll_end(wimp_dragged *drag, void *data) } if (ro_gui_window_to_window_pos(g, drag->final.x0, drag->final.y0, &pos)) - browser_window_mouse_track(g->bw, 0, pos.x, pos.y); + browser_window_mouse_track(g->bw, 0, pos.x/g->scale, pos.y/g->scale); } @@ -4362,7 +4364,7 @@ bool ro_gui_window_dataload(struct gui_window *g, wimp_message *message) message->data.data_xfer.pos.y, &pos)) return false; - if (browser_window_drop_file_at_point(g->bw, pos.x, pos.y, + if (browser_window_drop_file_at_point(g->bw, pos.x/g->scale, pos.y/g->scale, message->data.data_xfer.file_name) == false) return false; @@ -4390,7 +4392,7 @@ void ro_gui_window_mouse_at(wimp_pointer *pointer, void *data) browser_window_mouse_track(g->bw, ro_gui_mouse_drag_state(pointer->buttons, wimp_BUTTON_DOUBLE_CLICK_DRAG), - pos.x, pos.y); + pos.x/g->scale, pos.y/g->scale); } @@ -4753,8 +4755,8 @@ ro_gui_window_to_window_pos(struct gui_window *g, int x, int y, os_coord *pos) ro_warn_user("WimpError", error->errmess); return false; } - pos->x = (x - (state.visible.x0 - state.xscroll)) / 2 / g->scale; - pos->y = ((state.visible.y1 - state.yscroll) - y) / 2 / g->scale; + pos->x = (x - (state.visible.x0 - state.xscroll)) / 2 ; + pos->y = ((state.visible.y1 - state.yscroll) - y) / 2 ; return true; } diff --git a/frontends/windows/drawable.c b/frontends/windows/drawable.c index e1fdbc84e..3cded7e0c 100644 --- a/frontends/windows/drawable.c +++ b/frontends/windows/drawable.c @@ -431,8 +431,8 @@ nsws_drawable_mouseup(struct gui_window *gw, browser_window_mouse_click(gw->bw, gw->mouse->state, - (x + gw->scrollx) / gw->scale, - (y + gw->scrolly) / gw->scale); + (x + gw->scrollx), + (y + gw->scrolly)); } else { browser_window_mouse_track(gw->bw, 0, @@ -476,8 +476,8 @@ nsws_drawable_mousedown(struct gui_window *gw, (y + gw->scrolly) / gw->scale); browser_window_mouse_click(gw->bw, gw->mouse->state, - (x + gw->scrollx) / gw->scale, - (y + gw->scrolly) / gw->scale); + (x + gw->scrollx), + (y + gw->scrolly)); return 0; } @@ -497,8 +497,8 @@ nsws_drawable_mousemove(struct gui_window *gw, int x, int y) return 0; /* scale co-ordinates */ - x = (x + gw->scrollx) / gw->scale; - y = (y + gw->scrolly) / gw->scale; + x = (x + gw->scrollx) ; + y = (y + gw->scrolly); /* if mouse button held down and pointer moved more than * minimum distance drag is happening */ @@ -535,7 +535,7 @@ nsws_drawable_mousemove(struct gui_window *gw, int x, int y) gw->mouse->state &= ~BROWSER_MOUSE_MOD_3; - browser_window_mouse_track(gw->bw, gw->mouse->state, x, y); + browser_window_mouse_track(gw->bw, gw->mouse->state, x/ gw->scale, y/ gw->scale); return 0; }