From 7d3b8b0d09b0a11e2d51fcc015bce86b60e4b660 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Sun, 29 Jul 2018 09:43:00 -0400 Subject: [PATCH] treeview: Get rid of child surfaces Drop the drag-highlight and drag surfaces. The highlighting is broken anyway, so just drop it for now. And for dragging the header button, we can just position it properly, that works just as well as this reparenting approach. --- gtk/gtktreeview.c | 386 ++++------------------------------------------ 1 file changed, 26 insertions(+), 360 deletions(-) diff --git a/gtk/gtktreeview.c b/gtk/gtktreeview.c index f9ccd551c4..40af08657a 100644 --- a/gtk/gtktreeview.c +++ b/gtk/gtktreeview.c @@ -387,10 +387,9 @@ struct _GtkTreeViewPrivate guint scroll_timeout; /* Interactive Header reordering */ - GdkSurface *drag_surface; - GdkSurface *drag_highlight_surface; GtkTreeViewColumn *drag_column; gint drag_column_x; + gint drag_column_y; /* Interactive Header Resizing */ gint drag_pos; @@ -2250,20 +2249,6 @@ gtk_tree_view_unrealize (GtkWidget *widget) priv->typeselect_flush_timeout = 0; } - if (priv->drag_surface) - { - gtk_widget_unregister_surface (widget, priv->drag_surface); - gdk_surface_destroy (priv->drag_surface); - priv->drag_surface = NULL; - } - - if (priv->drag_highlight_surface) - { - gtk_widget_unregister_surface (widget, priv->drag_highlight_surface); - gdk_surface_destroy (priv->drag_highlight_surface); - priv->drag_highlight_surface = NULL; - } - GTK_WIDGET_CLASS (gtk_tree_view_parent_class)->unrealize (widget); } @@ -2454,11 +2439,13 @@ gtk_tree_view_size_allocate_columns (GtkWidget *widget) gint column_width; column = list->data; + column_width = _gtk_tree_view_column_request_width (column); - if (!gtk_tree_view_column_get_visible (column) || column == tree_view->priv->drag_column) + if (!gtk_tree_view_column_get_visible (column)) continue; - column_width = _gtk_tree_view_column_request_width (column); + if (column == tree_view->priv->drag_column) + goto next; if (gtk_tree_view_column_get_expand (column)) { @@ -2493,7 +2480,7 @@ gtk_tree_view_size_allocate_columns (GtkWidget *widget) else _gtk_tree_view_column_allocate (column, width + x_offset, column_width, tree_view->priv->header_height); - + next: width += column_width; } @@ -2512,7 +2499,8 @@ static void gtk_tree_view_size_allocate_drag_column (GtkWidget *widget) { GtkTreeView *tree_view = GTK_TREE_VIEW (widget); - GtkAllocation drag_allocation; + GtkAllocation allocation; + int baseline; GtkWidget *button; if (tree_view->priv->drag_column == NULL) @@ -2520,11 +2508,13 @@ gtk_tree_view_size_allocate_drag_column (GtkWidget *widget) button = gtk_tree_view_column_get_button (tree_view->priv->drag_column); - drag_allocation.x = 0; - drag_allocation.y = 0; - drag_allocation.width = gdk_surface_get_width (tree_view->priv->drag_surface); - drag_allocation.height = gdk_surface_get_height (tree_view->priv->drag_surface); - gtk_widget_size_allocate (button, &drag_allocation, -1); + allocation.x = tree_view->priv->drag_column_x; + allocation.y = tree_view->priv->drag_column_y; + allocation.width = gtk_widget_get_allocated_width (button); + allocation.height = gtk_widget_get_allocated_height (button); + baseline = gtk_widget_get_allocated_baseline (button); + + gtk_widget_size_allocate (button, &allocation, baseline); } static void @@ -3175,12 +3165,8 @@ gtk_tree_view_button_release_drag_column (GtkTreeView *tree_view) context = gtk_widget_get_style_context (button); gtk_style_context_remove_class (context, GTK_STYLE_CLASS_DND); - g_object_ref (button); - gtk_container_remove (GTK_CONTAINER (tree_view), button); gtk_tree_view_update_button_position (tree_view, tree_view->priv->drag_column); - gtk_widget_set_parent (button, GTK_WIDGET (tree_view)); - g_object_unref (button); - gtk_widget_queue_resize (widget); + gtk_widget_queue_allocate (widget); gtk_widget_grab_focus (button); @@ -3199,9 +3185,6 @@ gtk_tree_view_button_release_drag_column (GtkTreeView *tree_view) tree_view->priv->cur_reorder->left_column); } tree_view->priv->drag_column = NULL; - gtk_widget_unregister_surface (widget, tree_view->priv->drag_surface); - gdk_surface_destroy (tree_view->priv->drag_surface); - tree_view->priv->drag_surface = NULL; for (l = tree_view->priv->column_drag_info; l != NULL; l = l->next) g_slice_free (GtkTreeViewColumnReorder, l->data); @@ -3209,9 +3192,6 @@ gtk_tree_view_button_release_drag_column (GtkTreeView *tree_view) tree_view->priv->column_drag_info = NULL; tree_view->priv->cur_reorder = NULL; - if (tree_view->priv->drag_highlight_surface) - gdk_surface_hide (tree_view->priv->drag_highlight_surface); - /* Reset our flags */ tree_view->priv->drag_column_surface_state = DRAG_COLUMN_WINDOW_STATE_UNSET; tree_view->priv->in_column_drag = FALSE; @@ -3254,13 +3234,7 @@ gtk_tree_view_column_drag_gesture_end (GtkGestureDrag *gesture, tree_view->priv->cur_reorder = NULL; if (tree_view->priv->in_column_drag) - { - GdkDevice *device; - - gtk_tree_view_button_release_drag_column (tree_view); - device = gtk_gesture_get_device (GTK_GESTURE (gesture)); - gdk_seat_ungrab (gdk_device_get_seat (device)); - } + gtk_tree_view_button_release_drag_column (tree_view); else if (tree_view->priv->in_column_resize) gtk_tree_view_button_release_column_resize (tree_view); } @@ -3556,248 +3530,6 @@ update_prelight (GtkTreeView *tree_view, prelight_or_select (tree_view, tree, node, x, y); } - - - -/* Our motion arrow is either a box (in the case of the original spot) - * or an arrow. It is expander_size wide. - */ -/* - * 11111111111111 - * 01111111111110 - * 00111111111100 - * 00011111111000 - * 00001111110000 - * 00000111100000 - * 00000111100000 - * 00000111100000 - * ~ ~ ~ ~ ~ ~ ~ - * 00000111100000 - * 00000111100000 - * 00000111100000 - * 00001111110000 - * 00011111111000 - * 00111111111100 - * 01111111111110 - * 11111111111111 - */ - -static void -gtk_tree_view_motion_draw_column_motion_arrow (GtkTreeView *tree_view) -{ - GtkTreeViewColumnReorder *reorder = tree_view->priv->cur_reorder; - GtkWidget *widget = GTK_WIDGET (tree_view); - cairo_surface_t *mask_image; - gint x; - gint y; - gint width; - gint height; - gint arrow_type = DRAG_COLUMN_WINDOW_STATE_UNSET; - cairo_t *cr; - - if (!reorder || - reorder->left_column == tree_view->priv->drag_column || - reorder->right_column == tree_view->priv->drag_column) - arrow_type = DRAG_COLUMN_WINDOW_STATE_ORIGINAL; - else if (reorder->left_column || reorder->right_column) - { - GtkAllocation left_allocation, right_allocation; - GdkRectangle visible_rect; - GtkWidget *button; - - gtk_tree_view_get_visible_rect (tree_view, &visible_rect); - if (reorder->left_column) - { - button = gtk_tree_view_column_get_button (reorder->left_column); - gtk_widget_get_allocation (button, &left_allocation); - x = left_allocation.x + left_allocation.width; - } - else - { - button = gtk_tree_view_column_get_button (reorder->right_column); - gtk_widget_get_allocation (button, &right_allocation); - x = right_allocation.x; - } - - if (x < visible_rect.x) - arrow_type = DRAG_COLUMN_WINDOW_STATE_ARROW_LEFT; - else if (x > visible_rect.x + visible_rect.width) - arrow_type = DRAG_COLUMN_WINDOW_STATE_ARROW_RIGHT; - else - arrow_type = DRAG_COLUMN_WINDOW_STATE_ARROW; - } - - /* We want to draw the rectangle over the initial location. */ - if (arrow_type == DRAG_COLUMN_WINDOW_STATE_ORIGINAL) - { - if (tree_view->priv->drag_column_surface_state != DRAG_COLUMN_WINDOW_STATE_ORIGINAL) - { - GtkAllocation drag_allocation; - GtkWidget *button; - - if (tree_view->priv->drag_highlight_surface) - { - gtk_widget_unregister_surface (GTK_WIDGET (tree_view), tree_view->priv->drag_highlight_surface); - gdk_surface_destroy (tree_view->priv->drag_highlight_surface); - } - - button = gtk_tree_view_column_get_button (tree_view->priv->drag_column); - gtk_widget_get_allocation (button, &drag_allocation); - width = drag_allocation.width; - height = drag_allocation.height; - tree_view->priv->drag_highlight_surface = gdk_surface_new_child (gtk_widget_get_surface (widget), - &(GdkRectangle){ - tree_view->priv->drag_column_x, - 0, - drag_allocation.width, - drag_allocation.height}); - gtk_widget_register_surface (GTK_WIDGET (tree_view), tree_view->priv->drag_highlight_surface); - - tree_view->priv->drag_column_surface_state = DRAG_COLUMN_WINDOW_STATE_ORIGINAL; - } - } - else if (arrow_type == DRAG_COLUMN_WINDOW_STATE_ARROW) - { - GtkAllocation button_allocation, allocation; - GtkWidget *button; - - width = gtk_tree_view_get_expander_size (tree_view); - - /* Get x, y, width, height of arrow */ - gtk_widget_get_allocation (widget, &allocation); - x = allocation.x; - y = allocation.y; - - if (reorder->left_column) - { - button = gtk_tree_view_column_get_button (reorder->left_column); - gtk_widget_get_allocation (button, &button_allocation); - x += button_allocation.x + button_allocation.width - width/2; - height = button_allocation.height; - } - else - { - button = gtk_tree_view_column_get_button (reorder->right_column); - gtk_widget_get_allocation (button, &button_allocation); - x += button_allocation.x - width/2; - height = button_allocation.height; - } - y -= width/2; /* The arrow takes up only half the space */ - height += width; - - /* Create the new window */ - if (tree_view->priv->drag_column_surface_state != DRAG_COLUMN_WINDOW_STATE_ARROW) - { - if (tree_view->priv->drag_highlight_surface) - { - gtk_widget_unregister_surface (GTK_WIDGET (tree_view), tree_view->priv->drag_highlight_surface); - gdk_surface_destroy (tree_view->priv->drag_highlight_surface); - } - - tree_view->priv->drag_highlight_surface = gdk_surface_new_popup (gtk_widget_get_display (widget), - &(GdkRectangle) { x, y, width, height }); - gtk_widget_register_surface (GTK_WIDGET (tree_view), tree_view->priv->drag_highlight_surface); - - mask_image = cairo_image_surface_create (CAIRO_FORMAT_A1, width, height); - - cr = cairo_create (mask_image); - cairo_move_to (cr, 0, 0); - cairo_line_to (cr, width, 0); - cairo_line_to (cr, width / 2., width / 2); - cairo_move_to (cr, 0, height); - cairo_line_to (cr, width, height); - cairo_line_to (cr, width / 2., height - width / 2.); - cairo_fill (cr); - cairo_destroy (cr); - - cairo_surface_destroy (mask_image); - } - - tree_view->priv->drag_column_surface_state = DRAG_COLUMN_WINDOW_STATE_ARROW; - gdk_surface_move (tree_view->priv->drag_highlight_surface, x, y); - } - else if (arrow_type == DRAG_COLUMN_WINDOW_STATE_ARROW_LEFT || - arrow_type == DRAG_COLUMN_WINDOW_STATE_ARROW_RIGHT) - { - GtkAllocation allocation; - GtkWidget *button; - gint expander_size; - - expander_size = gtk_tree_view_get_expander_size (tree_view); - - /* Get x, y, width, height of arrow */ - width = expander_size/2; /* remember, the arrow only takes half the available width */ - gtk_widget_get_allocation (widget, &allocation); - x = allocation.x; - y = allocation.y; - if (arrow_type == DRAG_COLUMN_WINDOW_STATE_ARROW_RIGHT) - { - x += gtk_widget_get_allocated_width (widget) - width; - } - - if (reorder->left_column) - { - button = gtk_tree_view_column_get_button (reorder->left_column); - height = gtk_widget_get_allocated_height (button); - } - else - { - button = gtk_tree_view_column_get_button (reorder->right_column); - height = gtk_widget_get_allocated_height (button); - } - - y -= expander_size; - height += 2 * expander_size; - - /* Create the new window */ - if (tree_view->priv->drag_column_surface_state != DRAG_COLUMN_WINDOW_STATE_ARROW_LEFT && - tree_view->priv->drag_column_surface_state != DRAG_COLUMN_WINDOW_STATE_ARROW_RIGHT) - { - if (tree_view->priv->drag_highlight_surface) - { - gtk_widget_unregister_surface (GTK_WIDGET (tree_view), tree_view->priv->drag_highlight_surface); - gdk_surface_destroy (tree_view->priv->drag_highlight_surface); - } - - tree_view->priv->drag_highlight_surface = gdk_surface_new_popup (gtk_widget_get_display (widget), - &(GdkRectangle) { x, y, width, height }); - gtk_widget_register_surface (GTK_WIDGET (tree_view), tree_view->priv->drag_highlight_surface); - - mask_image = cairo_image_surface_create (CAIRO_FORMAT_A1, width, height); - - cr = cairo_create (mask_image); - /* mirror if we're on the left */ - if (arrow_type == DRAG_COLUMN_WINDOW_STATE_ARROW_LEFT) - { - cairo_translate (cr, width, 0); - cairo_scale (cr, -1, 1); - } - cairo_move_to (cr, 0, 0); - cairo_line_to (cr, width, width); - cairo_line_to (cr, 0, expander_size); - cairo_move_to (cr, 0, height); - cairo_line_to (cr, width, height - width); - cairo_line_to (cr, 0, height - expander_size); - cairo_fill (cr); - cairo_destroy (cr); - - cairo_surface_destroy (mask_image); - } - - tree_view->priv->drag_column_surface_state = arrow_type; - gdk_surface_move (tree_view->priv->drag_highlight_surface, x, y); - } - else - { - g_warning (G_STRLOC"Invalid GtkTreeViewColumnReorder struct"); - gdk_surface_hide (tree_view->priv->drag_highlight_surface); - return; - } - - gdk_surface_show (tree_view->priv->drag_highlight_surface); - gdk_surface_raise (tree_view->priv->drag_highlight_surface); -} - static gboolean gtk_tree_view_motion_resize_column (GtkTreeView *tree_view, gdouble x, @@ -3842,7 +3574,6 @@ gtk_tree_view_update_current_reorder (GtkTreeView *tree_view) } tree_view->priv->cur_reorder = reorder; - gtk_tree_view_motion_draw_column_motion_arrow (tree_view); } static void @@ -3884,7 +3615,7 @@ gtk_tree_view_vertical_autoscroll (GtkTreeView *tree_view) MAX (gtk_adjustment_get_value (tree_view->priv->vadjustment) + offset, 0.0)); } -static gboolean +static void gtk_tree_view_horizontal_autoscroll (GtkTreeView *tree_view) { GdkEventSequence *sequence; @@ -3912,39 +3643,31 @@ gtk_tree_view_horizontal_autoscroll (GtkTreeView *tree_view) gtk_adjustment_set_value (tree_view->priv->hadjustment, MAX (gtk_adjustment_get_value (tree_view->priv->hadjustment) + offset, 0.0)); - - return TRUE; - } -static gboolean +static void gtk_tree_view_motion_drag_column (GtkTreeView *tree_view, gdouble x, gdouble y) { GtkTreeViewColumn *column = tree_view->priv->drag_column; GtkWidget *button; - gint win_x, win_y; gint width, button_width; button = gtk_tree_view_column_get_button (column); x += gtk_adjustment_get_value (tree_view->priv->hadjustment); /* Handle moving the header */ - gdk_surface_get_position (tree_view->priv->drag_surface, &win_x, &win_y); width = gtk_widget_get_allocated_width (GTK_WIDGET (tree_view)); button_width = gtk_widget_get_allocated_width (button); - win_x = CLAMP (x - _gtk_tree_view_column_get_drag_x (column), 0, - MAX (tree_view->priv->width, width) - button_width); - gdk_surface_move (tree_view->priv->drag_surface, win_x, win_y); - gdk_surface_raise (tree_view->priv->drag_surface); + tree_view->priv->drag_column_x = CLAMP (x - _gtk_tree_view_column_get_drag_x (column), 0, + MAX (tree_view->priv->width, width) - button_width); /* autoscroll, if needed */ gtk_tree_view_horizontal_autoscroll (tree_view); /* Update the current reorder position and arrow; */ gtk_tree_view_update_current_reorder (tree_view); - - return TRUE; + gtk_widget_queue_allocate (GTK_WIDGET (tree_view)); } static void @@ -5179,34 +4902,6 @@ gtk_tree_view_snapshot (GtkWidget *widget, gtk_snapshot_pop (snapshot); -#if 0 - Thyis clearly does not work. priv->drag_highlight_surface is potentially a toplevel... - if (tree_view->priv->drag_highlight_surface) - { - GdkRGBA color; - - gtk_style_context_get_color (context, &color); - cairo_save (cr); - if (tree_view->priv->drag_column_surface_state == DRAG_COLUMN_WINDOW_STATE_ORIGINAL) - { - cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, 0.0); - cairo_paint (cr); - gdk_cairo_set_source_rgba (cr, &color); - cairo_rectangle (cr, - 1, 1, - gdk_surface_get_width (tree_view->priv->drag_highlight_surface) - 2, - gdk_surface_get_height (tree_view->priv->drag_highlight_surface) - 2); - cairo_stroke (cr); - } - else - { - gdk_cairo_set_source_rgba (cr, &color); - cairo_paint (cr); - } - cairo_restore (cr); - } -#endif - gtk_snapshot_push_clip (snapshot, &GRAPHENE_RECT_INIT( 0, 0, @@ -5227,16 +4922,14 @@ gtk_tree_view_snapshot (GtkWidget *widget, if (gtk_tree_view_column_get_visible (column)) { button = gtk_tree_view_column_get_button (column); - gtk_widget_snapshot_child (widget, - button, snapshot); + gtk_widget_snapshot_child (widget, button, snapshot); } } - if (tree_view->priv->drag_surface) + if (tree_view->priv->drag_column) { button = gtk_tree_view_column_get_button (tree_view->priv->drag_column); - gtk_widget_snapshot_child (widget, - button, snapshot); + gtk_widget_snapshot_child (widget, button, snapshot); } gtk_style_context_restore (context); @@ -9493,14 +9186,12 @@ _gtk_tree_view_column_start_drag (GtkTreeView *tree_view, GtkTreeViewColumn *column, GdkDevice *device) { - GtkAllocation allocation; GtkAllocation button_allocation; GtkWidget *button; GtkStyleContext *context; g_return_if_fail (tree_view->priv->column_drag_info == NULL); g_return_if_fail (tree_view->priv->cur_reorder == NULL); - g_return_if_fail (tree_view->priv->drag_surface == NULL); gtk_tree_view_set_column_drag_info (tree_view, column); @@ -9512,41 +9203,16 @@ _gtk_tree_view_column_start_drag (GtkTreeView *tree_view, context = gtk_widget_get_style_context (button); gtk_style_context_add_class (context, GTK_STYLE_CLASS_DND); - gtk_widget_get_allocation (button, &button_allocation); - button_allocation.y = 0; - - tree_view->priv->drag_surface = gdk_surface_new_child (gtk_widget_get_surface (GTK_WIDGET (tree_view)), - &button_allocation); - gtk_widget_register_surface (GTK_WIDGET (tree_view), tree_view->priv->drag_surface); - - /* Kids, don't try this at home */ - g_object_ref (button); - gtk_container_remove (GTK_CONTAINER (tree_view), button); - gtk_widget_set_parent_surface (button, tree_view->priv->drag_surface); - gtk_widget_set_parent (button, GTK_WIDGET (tree_view)); - g_object_unref (button); - gtk_widget_get_allocation (button, &button_allocation); tree_view->priv->drag_column_x = button_allocation.x; - allocation = button_allocation; - allocation.x = 0; - gtk_widget_size_allocate (button, &allocation, -1); + tree_view->priv->drag_column_y = button_allocation.y; tree_view->priv->drag_column = column; - gdk_surface_show (tree_view->priv->drag_surface); gtk_widget_grab_focus (GTK_WIDGET (tree_view)); tree_view->priv->in_column_drag = TRUE; - /* Widget reparenting above unmaps and indirectly breaks - * the implicit grab, replace it with an active one. - */ - gdk_seat_grab (gdk_device_get_seat (device), - tree_view->priv->drag_surface, - GDK_SEAT_CAPABILITY_ALL, FALSE, - NULL, NULL, NULL, NULL); - gtk_gesture_set_state (tree_view->priv->column_drag_gesture, GTK_EVENT_SEQUENCE_CLAIMED); }