void ro_treeview_mouse_at(wimp_pointer *pointer) { os_error *error; ro_treeview *tv; wimp_window_state state; int xpos, ypos; browser_mouse_state mouse; if (pointer->buttons & (wimp_CLICK_MENU)) return; tv = (ro_treeview *) ro_gui_wimp_event_get_user_data(pointer->w); if (tv == NULL) { LOG(("NULL treeview block for window: 0x%x", (unsigned int) pointer->w)); return; } if (tv->drag == TREE_NO_DRAG) return; /* We know now that it's not a Menu click and the treeview thinks * that a drag is in progress. */ state.w = tv->w; error = xwimp_get_window_state(&state); if (error) { LOG(("xwimp_get_window_state: 0x%x: %s", error->errnum, error->errmess)); warn_user("WimpError", error->errmess); return; } /* Convert the returned mouse coordinates into NetSurf's internal * units. */ xpos = ((pointer->pos.x - state.visible.x0) + state.xscroll - tv->origin.x) / 2; ypos = ((state.visible.y1 - pointer->pos.y) - state.yscroll + tv->origin.y) / 2; /* Start to process the mouse click. */ mouse = ro_gui_mouse_drag_state(pointer->buttons, wimp_BUTTON_DOUBLE_CLICK_DRAG); tree_mouse_action(tv->tree, mouse, xpos, ypos); if (!(mouse & BROWSER_MOUSE_DRAG_ON)) { tree_drag_end(tv->tree, mouse, tv->drag_start.x, tv->drag_start.y, xpos, ypos); tv->drag = TREE_NO_DRAG; } if (tv->callbacks != NULL && tv->callbacks->toolbar_button_update != NULL) tv->callbacks->toolbar_button_update(); }
static gboolean nsgtk_tree_window_draw_event(GtkWidget *widget, cairo_t *cr, gpointer data) { struct tree *tree = (struct tree *)data; struct redraw_context ctx = { .interactive = true, .background_images = true, .plot = &nsgtk_plotters }; double x1; double y1; double x2; double y2; current_widget = widget; current_cr = cr; cairo_clip_extents(cr, &x1, &y1, &x2, &y2); tree_draw(tree, 0, 0, x1, y1, x2 - x1, y2 - y1, &ctx); current_widget = NULL; return FALSE; } #else /* signal handler functions for a tree window */ static gboolean nsgtk_tree_window_draw_event(GtkWidget *widget, GdkEventExpose *event, gpointer g) { struct tree *tree = (struct tree *) g; struct redraw_context ctx = { .interactive = true, .background_images = true, .plot = &nsgtk_plotters }; int x, y, width, height; x = event->area.x; y = event->area.y; width = event->area.width; height = event->area.height; current_widget = widget; current_cr = gdk_cairo_create(nsgtk_widget_get_window(widget)); tree_draw(tree, 0, 0, x, y, width, height, &ctx); current_widget = NULL; cairo_destroy(current_cr); return FALSE; } #endif void nsgtk_tree_window_hide(GtkWidget *widget, gpointer g) { } gboolean nsgtk_tree_window_button_press_event(GtkWidget *widget, GdkEventButton *event, gpointer g) { struct nsgtk_treeview *tw = g; struct tree *tree = tw->tree; gtk_widget_grab_focus(GTK_WIDGET(tw->drawing_area)); tw->mouse_pressed = true; tw->mouse_pressed_x = event->x; tw->mouse_pressed_y = event->y; if (event->type == GDK_2BUTTON_PRESS) tw->mouse_state = BROWSER_MOUSE_DOUBLE_CLICK; switch (event->button) { case 1: tw->mouse_state |= BROWSER_MOUSE_PRESS_1; break; case 2: tw->mouse_state |= BROWSER_MOUSE_PRESS_2; break; } /* Handle the modifiers too */ if (event->state & GDK_SHIFT_MASK) tw->mouse_state |= BROWSER_MOUSE_MOD_1; if (event->state & GDK_CONTROL_MASK) tw->mouse_state |= BROWSER_MOUSE_MOD_2; if (event->state & GDK_MOD1_MASK) tw->mouse_state |= BROWSER_MOUSE_MOD_3; /* Record where we pressed, for use when determining whether to start * a drag in motion notify events. */ tw->last_x = event->x; tw->last_y = event->y; tree_mouse_action(tree, tw->mouse_state, event->x, event->y); return TRUE; } gboolean nsgtk_tree_window_button_release_event(GtkWidget *widget, GdkEventButton *event, gpointer g) { bool shift = event->state & GDK_SHIFT_MASK; bool ctrl = event->state & GDK_CONTROL_MASK; bool alt = event->state & GDK_MOD1_MASK; struct nsgtk_treeview *tw = (struct nsgtk_treeview *) g; struct tree *tree = tw->tree; /* We consider only button 1 clicks as double clicks. * If the mouse state is PRESS then we are waiting for a release to emit * a click event, otherwise just reset the state to nothing*/ if (tw->mouse_state & BROWSER_MOUSE_DOUBLE_CLICK) { if (tw->mouse_state & BROWSER_MOUSE_PRESS_1) tw->mouse_state ^= BROWSER_MOUSE_PRESS_1 | BROWSER_MOUSE_CLICK_1; else if (tw->mouse_state & BROWSER_MOUSE_PRESS_2) tw->mouse_state ^= (BROWSER_MOUSE_PRESS_2 | BROWSER_MOUSE_CLICK_2 | BROWSER_MOUSE_DOUBLE_CLICK); } else if (tw->mouse_state & BROWSER_MOUSE_PRESS_1) { tw->mouse_state ^= (BROWSER_MOUSE_PRESS_1 | BROWSER_MOUSE_CLICK_1); } else if (tw->mouse_state & BROWSER_MOUSE_PRESS_2) { tw->mouse_state ^= (BROWSER_MOUSE_PRESS_2 | BROWSER_MOUSE_CLICK_2); } else if (tw->mouse_state & BROWSER_MOUSE_HOLDING_1) { tw->mouse_state ^= (BROWSER_MOUSE_HOLDING_1 | BROWSER_MOUSE_DRAG_ON); } else if (tw->mouse_state & BROWSER_MOUSE_HOLDING_2) { tw->mouse_state ^= (BROWSER_MOUSE_HOLDING_2 | BROWSER_MOUSE_DRAG_ON); } /* Handle modifiers being removed */ if (tw->mouse_state & BROWSER_MOUSE_MOD_1 && !shift) tw->mouse_state ^= BROWSER_MOUSE_MOD_1; if (tw->mouse_state & BROWSER_MOUSE_MOD_2 && !ctrl) tw->mouse_state ^= BROWSER_MOUSE_MOD_2; if (tw->mouse_state & BROWSER_MOUSE_MOD_3 && !alt) tw->mouse_state ^= BROWSER_MOUSE_MOD_3; if (tw->mouse_state & ~(BROWSER_MOUSE_MOD_1 | BROWSER_MOUSE_MOD_2 | BROWSER_MOUSE_MOD_3)) { tree_mouse_action(tree, tw->mouse_state, event->x, event->y); } else { tree_drag_end(tree, tw->mouse_state, tw->mouse_pressed_x, tw->mouse_pressed_y, event->x, event->y); } tw->mouse_state = 0; tw->mouse_pressed = false; return TRUE; } gboolean nsgtk_tree_window_motion_notify_event(GtkWidget *widget, GdkEventMotion *event, gpointer g) { bool shift = event->state & GDK_SHIFT_MASK; bool ctrl = event->state & GDK_CONTROL_MASK; bool alt = event->state & GDK_MOD1_MASK; struct nsgtk_treeview *tw = (struct nsgtk_treeview *) g; struct tree *tree = tw->tree; if (tw->mouse_pressed == false) return TRUE; if ((abs(event->x - tw->last_x) < 5) && (abs(event->y - tw->last_y) < 5)) { /* Mouse hasn't moved far enough from press coordinate for this * to be considered a drag. */ return FALSE; } else { /* This is a drag, ensure it's always treated as such, even if * we drag back over the press location */ tw->last_x = INT_MIN; tw->last_y = INT_MIN; } if (tw->mouse_state & BROWSER_MOUSE_PRESS_1) { /* Start button 1 drag */ tree_mouse_action(tree, BROWSER_MOUSE_DRAG_1, tw->mouse_pressed_x, tw->mouse_pressed_y); /* Replace PRESS with HOLDING and declare drag in progress */ tw->mouse_state ^= (BROWSER_MOUSE_PRESS_1 | BROWSER_MOUSE_HOLDING_1); tw->mouse_state |= BROWSER_MOUSE_DRAG_ON; return TRUE; } else if (tw->mouse_state & BROWSER_MOUSE_PRESS_2){ /* Start button 2s drag */ tree_mouse_action(tree, BROWSER_MOUSE_DRAG_2, tw->mouse_pressed_x, tw->mouse_pressed_y); /* Replace PRESS with HOLDING and declare drag in progress */ tw->mouse_state ^= (BROWSER_MOUSE_PRESS_2 | BROWSER_MOUSE_HOLDING_2); tw->mouse_state |= BROWSER_MOUSE_DRAG_ON; return TRUE; } /* Handle modifiers being removed */ if (tw->mouse_state & BROWSER_MOUSE_MOD_1 && !shift) tw->mouse_state ^= BROWSER_MOUSE_MOD_1; if (tw->mouse_state & BROWSER_MOUSE_MOD_2 && !ctrl) tw->mouse_state ^= BROWSER_MOUSE_MOD_2; if (tw->mouse_state & BROWSER_MOUSE_MOD_3 && !alt) tw->mouse_state ^= BROWSER_MOUSE_MOD_3; if (tw->mouse_state & (BROWSER_MOUSE_HOLDING_1 | BROWSER_MOUSE_HOLDING_2)) tree_mouse_action(tree, tw->mouse_state, event->x, event->y); return TRUE; }
static bool ro_treeview_mouse_click(wimp_pointer *pointer) { os_error *error; ro_treeview *tv; wimp_window_state state; int xpos, ypos; browser_mouse_state mouse; bool handled = false; tv = (ro_treeview *) ro_gui_wimp_event_get_user_data(pointer->w); if (tv == NULL) { LOG(("NULL treeview block for window: 0x%x", (unsigned int) pointer->w)); return false; } state.w = tv->w; error = xwimp_get_window_state(&state); if (error) { LOG(("xwimp_get_window_state: 0x%x: %s", error->errnum, error->errmess)); warn_user("WimpError", error->errmess); return false; } /* Convert the returned mouse coordinates into NetSurf's internal * units. */ xpos = ((pointer->pos.x - state.visible.x0) + state.xscroll - tv->origin.x) / 2; ypos = ((state.visible.y1 - pointer->pos.y) - state.yscroll + tv->origin.y) / 2; /* Start to process the mouse click. * * Select and Adjust are processed normally. To get filer-like operation * with selections, Menu clicks are passed to the treeview first as * Select if there are no selected nodes in the tree. */ mouse = 0; if (pointer->buttons == wimp_CLICK_MENU) { if (!tree_node_has_selection(tree_get_root(tv->tree))) mouse |= BROWSER_MOUSE_CLICK_1; } else { mouse = ro_gui_mouse_click_state(pointer->buttons, wimp_BUTTON_DOUBLE_CLICK_DRAG); /* Give the window input focus on Select-clicks. This wouldn't * be necessary if the core used the RISC OS caret. */ if (mouse & BROWSER_MOUSE_CLICK_1) xwimp_set_caret_position(tv->w, -1, -100, -100, 32, -1); } if (mouse != 0) { handled = tree_mouse_action(tv->tree, mouse, xpos, ypos); tv->drag = tree_drag_status(tv->tree); if (tv->drag != TREE_NO_DRAG) { tv->drag_start.x = xpos; tv->drag_start.y = ypos; } /* If it's a visible drag, start the RO side of the visible * effects. */ if (tv->drag == TREE_SELECT_DRAG || tv->drag == TREE_MOVE_DRAG) ro_treeview_drag_start(tv, pointer, &state); if (tv->callbacks != NULL && tv->callbacks->toolbar_button_update != NULL) tv->callbacks->toolbar_button_update(); } /* Special actions for some mouse buttons. Adjust closes the dialog; * Menu opens a menu. For the latter, we assume that the owning module * will have attached a window menu to our parent window with the auto * flag unset (so that we can fudge the selection above). If it hasn't, * the call will quietly fail. * * \TODO -- Adjust-click close isn't a perfect copy of what the RO * version did: adjust clicks anywhere close the tree, and * selections persist. */ switch(pointer->buttons) { case wimp_CLICK_ADJUST: if (handled) ro_gui_dialog_close(tv->w); break; case wimp_CLICK_MENU: ro_gui_wimp_event_process_window_menu_click(pointer); break; } return true; }