📄 gtkwidget.c
字号:
{ g_return_if_fail (widget != NULL); g_return_if_fail (GTK_IS_WIDGET (widget)); if (widget->allocation.width || widget->allocation.height) { if (GTK_WIDGET_NO_WINDOW (widget)) gtk_widget_queue_clear_area (widget, widget->allocation.x, widget->allocation.y, widget->allocation.width, widget->allocation.height); else gtk_widget_queue_clear_area (widget, 0, 0, widget->allocation.width, widget->allocation.height); }}static gintgtk_widget_draw_data_combine (GtkDrawData *parent, GtkDrawData *child){ gint parent_x2, parent_y2; gint child_x2, child_y2; /* Check for intersection */ parent_x2 = parent->rect.x + parent->rect.width; child_x2 = child->rect.x + child->rect.width; parent_y2 = parent->rect.y + parent->rect.height; child_y2 = child->rect.y + child->rect.height; if ((child->rect.x > parent_x2) || (parent->rect.x > child_x2) || (child->rect.y > parent_y2) || (parent->rect.y > child_y2)) return FALSE; else { parent->rect.x = MIN (parent->rect.x, child->rect.x); parent->rect.y = MIN (parent->rect.y, child->rect.y); parent->rect.width = MAX (parent_x2, child_x2) - parent->rect.x; parent->rect.height = MAX (parent_y2, child_y2) - parent->rect.y; } return TRUE;}/* Take a rectangle with respect to window, and translate it * to coordinates relative to widget's allocation, clipping through * intermediate windows. Returns whether translation failed. If the * translation failed, we have something like a handlebox, where * the child widget's GdkWindow is not a child of the parents GdkWindow. */static gbooleangtk_widget_clip_rect (GtkWidget *widget, GdkWindow *window, GdkRectangle *rect, gint *x_offset, gint *y_offset){ gint x,y, width, height; while (window && (window != widget->window)) { gdk_window_get_position (window, &x, &y); rect->x += x; if (x_offset) *x_offset += x; rect->y += y; if (y_offset) *y_offset += y; window = gdk_window_get_parent (window); if (!window) return FALSE; gdk_window_get_size (window, &width, &height); if (rect->x < 0) { rect->width = (rect->width > -rect->x) ? rect->width + rect->x : 0; rect->x = 0; } if (rect->y < 0) { rect->height = (rect->height > -rect->y) ? rect->width + rect->y : 0; rect->y = 0; } if (rect->x + rect->width > width) rect->width = (width > rect->x) ? width - rect->x : 0; if (rect->y + rect->height > height) rect->height = (height > rect->y) ? height - rect->y : 0; } if (!window) return FALSE; if (!GTK_WIDGET_NO_WINDOW (widget)) { if (gdk_window_get_toplevel (window) != window) { gdk_window_get_position (window, &x, &y); rect->x += x - widget->allocation.x; if (x_offset) *x_offset += x - widget->allocation.x; rect->y += y - widget->allocation.y; if (y_offset) *y_offset += y - widget->allocation.y; } } return TRUE;}static gintgtk_widget_idle_draw (gpointer cb_data){ GSList *widget_list; GSList *old_queue; GSList *draw_data_list; GtkWidget *widget; if (!draw_data_tmp_key_id) draw_data_tmp_key_id = g_quark_from_static_string (draw_data_tmp_key); GDK_THREADS_ENTER (); old_queue = gtk_widget_redraw_queue; gtk_widget_redraw_queue = NULL; /* Translate all draw requests to be allocation-relative. * At the same time, move all the data out of the way, * so when we get down to the draw step, we can queue * more information for "next time", if the application * is that foolhardy. */ widget_list = old_queue; while (widget_list) { widget = widget_list->data; draw_data_list = gtk_object_get_data_by_id (GTK_OBJECT (widget), draw_data_key_id); gtk_object_set_data_by_id (GTK_OBJECT (widget), draw_data_key_id, NULL); gtk_object_set_data_by_id (GTK_OBJECT (widget), draw_data_tmp_key_id, draw_data_list); /* XXX: Since we are unsetting this flag here, further * down the only way we can check if a redraw is queued * on a given widget is by calling gtk_object_get_data. * for speed purposes we might well want a private * flag GTK_REDRAW_PROCESSING or something. */ GTK_PRIVATE_UNSET_FLAG (widget, GTK_REDRAW_PENDING); GTK_PRIVATE_UNSET_FLAG (widget, GTK_FULLDRAW_PENDING); while (draw_data_list) { gboolean full_allocation = FALSE; GtkDrawData *data = draw_data_list->data; if (data->window) { /* If the translation fails, we have a handlebox, * so redraw the whole widget. Could be done better? */ full_allocation = !gtk_widget_clip_rect (widget, data->window, &data->rect, NULL, NULL); data->window = NULL; } else if ((data->rect.width == 0) && (data->rect.height == 0)) full_allocation = TRUE; if (full_allocation) { if (GTK_WIDGET_NO_WINDOW (widget)) { data->rect.x = widget->allocation.x; data->rect.y = widget->allocation.y; } else { data->rect.x = 0; data->rect.y = 0; } data->rect.width = widget->allocation.width; data->rect.height = widget->allocation.height; } draw_data_list = draw_data_list->next; } widget_list = widget_list->next; } /* Coalesce redraws. */ widget_list = old_queue; while (widget_list) { GSList *prev_node = NULL; widget = widget_list->data; draw_data_list = gtk_object_get_data_by_id (GTK_OBJECT (widget), draw_data_tmp_key_id); while (draw_data_list) { gint x_offset, y_offset; GtkDrawData *data = draw_data_list->data; GSList *parent_list = draw_data_list->next; GtkWidget *parent; GdkWindow *window; x_offset = 0; y_offset = 0; parent = widget; while (parent) { while (parent_list) { if (gtk_widget_draw_data_combine (parent_list->data, data)) { GSList *tmp; if (prev_node) prev_node->next = draw_data_list->next; else gtk_object_set_data_by_id (GTK_OBJECT (widget), draw_data_tmp_key_id, draw_data_list->next); tmp = draw_data_list->next; draw_data_list->next = draw_data_free_list; draw_data_free_list = draw_data_list; draw_data_list = tmp; goto next_rect; } parent_list = parent_list->next; } window = parent->window; if (parent->parent && parent->parent->window != window) { if (!GTK_WIDGET_NO_WINDOW (parent)) { gint x, y; gdk_window_get_position (window, &x, &y); data->rect.x -= x - parent->allocation.x; x_offset -= x - parent->allocation.x; data->rect.y -= y - parent->allocation.y; y_offset -= y - parent->allocation.y; } /* If we can't translate the rectangle, stop trying to * merge. (This occurs for a handlebox) */ if (!gtk_widget_clip_rect (parent->parent, window, &data->rect, &x_offset, &y_offset)) parent = NULL; } if (parent) parent = parent->parent; if (parent) parent_list = gtk_object_get_data_by_id (GTK_OBJECT (parent), draw_data_tmp_key_id); else parent_list = NULL; } /* OK, this rectangle stays around. But take advantage * of the work we've done to clip it to the visible area - * rect.width/height have already been appropriately * decreased */ data->rect.x -= x_offset; data->rect.y -= y_offset; prev_node = draw_data_list; draw_data_list = draw_data_list->next; next_rect: continue; } widget_list = widget_list->next; } /* Process the draws */ widget_list = old_queue; while (widget_list) { GSList *tmp_list; widget = widget_list->data; draw_data_list = gtk_object_get_data_by_id (GTK_OBJECT (widget), draw_data_tmp_key_id); gtk_object_set_data_by_id (GTK_OBJECT (widget), draw_data_tmp_key_id, NULL); tmp_list = draw_data_list; while (tmp_list) { GtkDrawData *data = tmp_list->data; if ((data->rect.width != 0) && (data->rect.height != 0)) gtk_widget_draw (widget, &data->rect); if (tmp_list->next) tmp_list = tmp_list->next; else { tmp_list->next = draw_data_free_list; draw_data_free_list = draw_data_list; break; } } widget_list = widget_list->next; } g_slist_free (old_queue); GDK_THREADS_LEAVE (); return FALSE;}voidgtk_widget_queue_resize (GtkWidget *widget){ g_return_if_fail (widget != NULL); g_return_if_fail (GTK_IS_WIDGET (widget)); if (GTK_IS_RESIZE_CONTAINER (widget)) gtk_container_clear_resize_widgets (GTK_CONTAINER (widget)); gtk_widget_queue_clear (widget); if (widget->parent) gtk_container_queue_resize (GTK_CONTAINER (widget->parent)); else if (GTK_WIDGET_TOPLEVEL (widget)) gtk_container_queue_resize (GTK_CONTAINER (widget));}/***************************************** * gtk_widget_draw: * * arguments: * * results: *****************************************/voidgtk_widget_draw (GtkWidget *widget, GdkRectangle *area){ GdkRectangle temp_area; g_return_if_fail (widget != NULL); g_return_if_fail (GTK_IS_WIDGET (widget)); if (GTK_WIDGET_DRAWABLE (widget)) { if (!area) { if (GTK_WIDGET_NO_WINDOW (widget)) { temp_area.x = widget->allocation.x; temp_area.y = widget->allocation.y; } else { temp_area.x = 0; temp_area.y = 0; } temp_area.width = widget->allocation.width; temp_area.height = widget->allocation.height; area = &temp_area; } gtk_signal_emit (GTK_OBJECT (widget), widget_signals[DRAW], area); }}/***************************************** * gtk_widget_draw_focus: * * arguments: * * results: *****************************************/voidgtk_widget_draw_focus (GtkWidget *widget){ g_return_if_fail (widget != NULL); g_return_if_fail (GTK_IS_WIDGET (widget)); gtk_signal_emit (GTK_OBJECT (widget), widget_signals[DRAW_FOCUS]);}/***************************************** * gtk_widget_draw_default: * * arguments: * * results: *****************************************/voidgtk_widget_draw_default (GtkWidget *widget){ g_return_if_fail (widget != NULL); g_return_if_fail (GTK_IS_WIDGET (widget)); gtk_signal_emit (GTK_OBJECT (widget), widget_signals[DRAW_DEFAULT]);}/***************************************** * gtk_widget_size_request: * * arguments: * * results: *****************************************/voidgtk_widget_size_request (GtkWidget *widget, GtkRequisition *requisition){ g_return_if_fail (widget != NULL); g_return_if_fail (GTK_IS_WIDGET (widget));#ifdef G_ENABLE_DEBUG if (requisition == &widget->requisition) g_warning ("gtk_widget_size_request() called on child widget with request equal\n to widget->requisition. gtk_widget_set_usize() may not work properly.");#endif /* G_ENABLE_DEBUG */ gtk_widget_ref (widget); gtk_widget_ensure_style (widget); gtk_signal_emit (GTK_OBJECT (widget), widget_signals[SIZE_REQUEST], &widget->requisition); if (requisition) gtk_widget_get_child_requisition (widget, requisition); gtk_widget_unref (widget);}/***************************************** * gtk_widget_get_requesition: * * arguments: * * results: *****************************************/voidgtk_widget_get_child_requisition (GtkWidget *widget, GtkRequisition *requisition){ GtkWidgetAuxInfo *aux_info; g_return_if_fail (widget != NULL); g_return_if_fail (GTK_IS_WIDGET (widget)); *requisition = widget->requisition; aux_info =
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -