void nautilus_drag_autoscroll_start (NautilusDragInfo *drag_info, GtkWidget *widget, GtkFunction callback, gpointer user_data) { if (nautilus_drag_autoscroll_in_scroll_region (widget)) { if (drag_info->auto_scroll_timeout_id == 0) { drag_info->waiting_to_autoscroll = TRUE; drag_info->start_auto_scroll_in = eel_get_system_time() + AUTOSCROLL_INITIAL_DELAY; drag_info->auto_scroll_timeout_id = g_timeout_add (AUTOSCROLL_TIMEOUT_INTERVAL, callback, user_data); } } else { if (drag_info->auto_scroll_timeout_id != 0) { g_source_remove (drag_info->auto_scroll_timeout_id); drag_info->auto_scroll_timeout_id = 0; } } }
static int auto_scroll_timeout_callback (gpointer data) { NemoIconContainer *container; GtkWidget *widget; float x_scroll_delta, y_scroll_delta; GdkRectangle exposed_area; GtkAllocation allocation; g_assert (NEMO_IS_ICON_CONTAINER (data)); widget = GTK_WIDGET (data); container = NEMO_ICON_CONTAINER (widget); if (container->details->dnd_info->drag_info.waiting_to_autoscroll && container->details->dnd_info->drag_info.start_auto_scroll_in > eel_get_system_time()) { /* not yet */ return TRUE; } container->details->dnd_info->drag_info.waiting_to_autoscroll = FALSE; nemo_drag_autoscroll_calculate_delta (widget, &x_scroll_delta, &y_scroll_delta); if (x_scroll_delta == 0 && y_scroll_delta == 0) { /* no work */ return TRUE; } /* Clear the old dnd highlight frame */ dnd_highlight_queue_redraw (widget); if (!nemo_icon_container_scroll (container, (int)x_scroll_delta, (int)y_scroll_delta)) { /* the scroll value got pinned to a min or max adjustment value, * we ended up not scrolling */ return TRUE; } /* Make sure the dnd highlight frame is redrawn */ dnd_highlight_queue_redraw (widget); /* update cached drag start offsets */ container->details->dnd_info->drag_info.start_x -= x_scroll_delta; container->details->dnd_info->drag_info.start_y -= y_scroll_delta; /* Due to a glitch in GtkLayout, whe need to do an explicit draw of the exposed * area. * Calculate the size of the area we need to draw */ gtk_widget_get_allocation (widget, &allocation); exposed_area.x = allocation.x; exposed_area.y = allocation.y; exposed_area.width = allocation.width; exposed_area.height = allocation.height; if (x_scroll_delta > 0) { exposed_area.x = exposed_area.width - x_scroll_delta; } else if (x_scroll_delta < 0) { exposed_area.width = -x_scroll_delta; } if (y_scroll_delta > 0) { exposed_area.y = exposed_area.height - y_scroll_delta; } else if (y_scroll_delta < 0) { exposed_area.height = -y_scroll_delta; } /* offset it to 0, 0 */ exposed_area.x -= allocation.x; exposed_area.y -= allocation.y; gtk_widget_queue_draw_area (widget, exposed_area.x, exposed_area.y, exposed_area.width, exposed_area.height); return TRUE; }