📄 dw_gtk_viewport.c
字号:
world_y = y + gtk_layout_get_vadjustment(GTK_LAYOUT(viewport))->value; dw_widget = Dw_gtk_viewport_widget_at_point (viewport, world_x, world_y); return Dw_widget_mouse_event (dw_widget, widget, world_x, world_y, event); } } return FALSE;}/* * Standard Gtk+ function */static gint Dw_gtk_viewport_button_press (GtkWidget *widget, GdkEventButton *event){ /* We focus always the viewport window (i.e., more precisely, the * GktDwScrolledFrame). */ if (widget->parent) gtk_widget_grab_focus(widget->parent); return Dw_gtk_viewport_mouse_event (widget, event->x, event->y, (GdkEvent*) event);}/* * Standard Gtk+ function */static gint Dw_gtk_viewport_button_release (GtkWidget *widget, GdkEventButton *event){ return Dw_gtk_viewport_mouse_event (widget, event->x, event->y, (GdkEvent*) event);}/* * Standard Gtk+ function */static gint Dw_gtk_viewport_motion_notify (GtkWidget *widget, GdkEventMotion *event){ GtkDwViewport *viewport = GTK_DW_VIEWPORT (widget); viewport->mouse_x = event->x; viewport->mouse_y = event->y; return Dw_gtk_viewport_mouse_event (widget, event->x, event->y, (GdkEvent*) event);}/* * Standard Gtk+ function */static gint Dw_gtk_viewport_enter_notify (GtkWidget *widget, GdkEventCrossing *event){ return Dw_gtk_viewport_mouse_event (widget, event->x, event->y, NULL);}/* * Standard Gtk+ function */static gint Dw_gtk_viewport_leave_notify (GtkWidget *widget, GdkEventCrossing *event){ /* There will anyway be no Dw widget, thus this simple call */ return Dw_widget_mouse_event (NULL, widget, 0, 0, NULL);}/* * This function is called when the viewport changes, and causes * motion_notify events to be simulated. */static void Dw_gtk_viewport_adj_changed (GtkAdjustment *adj, GtkDwViewport *viewport){ Dw_gtk_viewport_mouse_event (GTK_WIDGET (viewport), viewport->mouse_x, viewport->mouse_y, NULL);}/********************** * * * public functions * * * **********************//* * Set the top-level Dw widget. * If there is already one, you must destroy it before, otherwise the * function will fail. */void a_Dw_gtk_viewport_add_dw (GtkDwViewport *viewport, DwWidget *widget){ g_return_if_fail (viewport->child == NULL); viewport->child = widget; DBG_OBJ_ASSOC(widget, viewport); widget->parent = NULL; widget->viewport = GTK_WIDGET (viewport); /*widget->window = viewport->back_pixmap;*/ if (GTK_WIDGET_REALIZED (viewport)) a_Dw_widget_realize (widget); Dw_gtk_viewport_calc_size (viewport); Dw_gtk_viewport_remove_anchor (viewport); a_Findtext_state_set_widget (viewport->findtext_state, widget); a_Selection_reset (viewport->selection);}/************************************************** * * * Functions used by GtkDwViewport and DwWidget * * * **************************************************//* * This function only *recognizes* that the top-level Dw widget is to * be removed. It is called by Dw_widget_shutdown. * Don't use this function directly! */void Dw_gtk_viewport_remove_dw (GtkDwViewport *viewport){ a_Findtext_state_set_widget (viewport->findtext_state, NULL); viewport->child = NULL; Dw_gtk_viewport_remove_anchor (viewport); Dw_gtk_viewport_calc_size (viewport);}/* * Used by Dw_gtk_viewport_calc_size. */static void Dw_gtk_viewport_calc_child_size (GtkDwViewport *viewport, gint32 child_width, gint32 child_height, DwRequisition *child_requisition){ if (child_width < 0) child_width = 0; if (child_height < 0) child_height = 0; DEBUG_MSG (2, " width = %d, height = %d ...\n", child_width, child_height); a_Dw_widget_set_width (viewport->child, child_width); a_Dw_widget_set_ascent (viewport->child, child_height); a_Dw_widget_set_descent (viewport->child, 0); a_Dw_widget_size_request (viewport->child, child_requisition);}/* * Calculate the size of the scrolled area and allocate the top-level * widget. This function is called when the top-level Dw widget has * changed its size etc. */void Dw_gtk_viewport_calc_size (GtkDwViewport *viewport){ GtkWidget *widget; GtkScrolledWindow *scrolled; DwRequisition child_requisition; DwAllocation child_allocation; gint border_width, space; GtkRequisition bar_requisition; gint max_width, max_height, bar_width_diff, bar_height_diff, child_height; if (viewport->calc_size_blocked) return; viewport->calc_size_blocked = TRUE; if (viewport->child) { /* * Determine the size hints for the Dw widget. This is a bit * tricky, because you must know if scrollbars are visible or * not, which depends on the size of the Dw widget, which then * depends on the hints. The idea is to test several * configurations, there are four of them, from combining the * cases horizontal/vertical scrollbar visible/invisible. * * For optimization, the horizontal scrollbar is currently not * regarded, the height hint is always the same, as if the * scrollbar was allways visible. In future, this may be * implemented correctly, by using the minimal width to optimize * most cases. (Minimal widths will also be used by tables.) * * Furthermore, the last result (vertical scrollbar visible or * not) is stored in the viewport, and tested first. This will * make a second test only necessary when the visibility * switches, which normally happens only once when filling the * page with text. (Actually, this assumes that the page size is * always *growing*, but this is nevertheless true in dillo.) */ widget = GTK_WIDGET (viewport); scrolled = GTK_SCROLLED_WINDOW (widget->parent->parent); space = GTK_SCROLLED_WINDOW_CLASS(GTK_OBJECT(scrolled)->klass) ->scrollbar_spacing; border_width = GTK_CONTAINER(viewport)->border_width; gtk_widget_size_request (scrolled->vscrollbar, &bar_requisition); bar_width_diff = bar_requisition.width + space; max_width = widget->allocation.width - 2 * border_width; if (scrolled->vscrollbar_visible) max_width += bar_width_diff; gtk_widget_size_request (scrolled->hscrollbar, &bar_requisition); bar_height_diff = bar_requisition.height + space; max_height = widget->allocation.height - 2 * border_width; if (scrolled->hscrollbar_visible) max_height += bar_height_diff; DEBUG_MSG (2, "------------------------------------------------->\n"); DEBUG_MSG (2, "Dw_gtk_viewport_calc_size: %d x %d (%c/%c) -> %d x %d\n", widget->allocation.width, widget->allocation.height, scrolled->vscrollbar_visible ? 't' : 'f', scrolled->hscrollbar_visible ? 't' : 'f', max_width, max_height); if (scrolled->vscrollbar_policy == GTK_POLICY_NEVER) child_height = max_height; else child_height = max_height - bar_height_diff; switch (scrolled->vscrollbar_policy) { case GTK_POLICY_ALWAYS: Dw_gtk_viewport_calc_child_size (viewport, max_width - bar_width_diff, child_height, &child_requisition); break; case GTK_POLICY_AUTOMATIC: if (viewport->vscrollbar_used) { DEBUG_MSG (2, "Testing with vertical scrollbar ...\n"); Dw_gtk_viewport_calc_child_size (viewport, max_width - bar_width_diff, child_height, &child_requisition); if (child_requisition.ascent + child_requisition.descent <= child_height) { DEBUG_MSG (2, " failed!\n"); Dw_gtk_viewport_calc_child_size (viewport, max_width, child_height, &child_requisition); viewport->vscrollbar_used = TRUE; } } else { DEBUG_MSG (2, "Testing without vertical scrollbar ...\n"); Dw_gtk_viewport_calc_child_size (viewport, max_width, child_height, &child_requisition); /* todo: see above */ if (child_requisition.ascent + child_requisition.descent > child_height) { DEBUG_MSG (2, " failed!\n"); Dw_gtk_viewport_calc_child_size (viewport, max_width - bar_width_diff, child_height, &child_requisition); viewport->vscrollbar_used = TRUE; } } break; case GTK_POLICY_NEVER: Dw_gtk_viewport_calc_child_size (viewport, max_width, child_height, &child_requisition); } child_allocation.x = border_width; child_allocation.y = border_width; child_allocation.width = child_requisition.width; child_allocation.ascent = child_requisition.ascent; child_allocation.descent = child_requisition.descent; a_Dw_widget_size_allocate (viewport->child, &child_allocation); gtk_layout_set_size (GTK_LAYOUT (viewport), child_requisition.width + 2 * border_width, child_requisition.ascent + child_requisition.descent + 2 * border_width); DEBUG_MSG (1, "Setting size to %d x %d\n", child_requisition.width + 2 * border_width, child_requisition.ascent + child_requisition.descent + 2 * border_width); DEBUG_MSG (2, "<-------------------------------------------------\n"); } else { gtk_layout_set_size (GTK_LAYOUT (viewport), 1, 1); viewport->hscrollbar_used = FALSE; viewport->vscrollbar_used = FALSE; } Dw_gtk_viewport_update_anchor (viewport); gtk_widget_queue_draw (GTK_WIDGET (viewport)); viewport->calc_size_blocked = FALSE;}/* used by Dw_gtk_viewport_widget_at_point */typedef struct{ gint32 x; gint32 y; DwWidget *widget;} WidgetAtPointData;/* used by Dw_gtk_viewport_widget_at_point */static void Dw_gtk_viewport_widget_at_point_callback (DwWidget *widget, gpointer data){ WidgetAtPointData *callback_data; callback_data = (WidgetAtPointData*) data; DEBUG_MSG (1, " Checking %p ...\n", widget); if (/* As a special exception, for the top-level widget, not the * allocation is regarded, but the whole viewport. This makes * selections more useful, since so the user can start the * selection outside of the allocation. */ widget->parent == NULL || /* Otherwise, check whether pointer is in the allocation. */ (callback_data->x >= widget->allocation.x && callback_data->y >= widget->allocation.y && callback_data->x < widget->allocation.x + widget->allocation.width && callback_data->y < widget->allocation.y + DW_WIDGET_HEIGHT(widget))) { DEBUG_MSG (1, " yes\n"); if (DW_IS_CONTAINER (widget)) a_Dw_container_forall (DW_CONTAINER (widget), Dw_gtk_viewport_widget_at_point_callback, data); if (callback_data->widget == NULL) callback_data->widget = widget; }}/* * Return the widget at point (x, y) (world coordinates). */DwWidget* Dw_gtk_viewport_widget_at_point (GtkDwViewport *viewport, gint32 x, gint32 y){ WidgetAtPointData callback_data; callback_data.x = x; callback_data.y = y; callback_data.widget = NULL; if (viewport->child) Dw_gtk_viewport_widget_at_point_callback (viewport->child, &callback_data); return callback_data.widget;}/************* * * * Anchors * * * *************//* * Add or change an anchor. * The widget is responsible for storing a copy of name. * * todo: Currently, no horizontal scrolling is done. This is generally * possible, DW_HPOS_INTO_VIEW should be used for this, but it is * rather complicated to determine the width of an anchor. This would * be the lenght of the region between <a> and </a>, the page widget * would have to have two kinds of content types (opening and closing * anchor), and some changes in the HTML parser are necessary. */void p_Dw_gtk_viewport_put_anchor (DwWidget *widget, gchar *name, gint32 y){ GtkDwViewport *viewport; GtkDwViewportAnchor *anchor;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -