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.
This commit is contained in:
Matthias Clasen 2018-07-29 09:43:00 -04:00
parent fff2fabd7a
commit 7d3b8b0d09

View File

@ -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);
}