-static void ql_drag_begin(GtkWidget attribute((unused)) *w,
- GdkDragContext attribute((unused)) *dc,
- gpointer user_data) {
- struct queuelike *const ql = user_data;
- struct ql_drag_begin_state qdbs[1];
- GdkPixmap *icon;
-
- //fprintf(stderr, "drag-begin\n");
- memset(qdbs, 0, sizeof *qdbs);
- qdbs->ql = ql;
- /* Find out how many rows there are */
- if(!(qdbs->rows = gtk_tree_selection_count_selected_rows(ql->selection)))
- return; /* doesn't make sense */
- /* Generate a pixmap for each row */
- qdbs->pixmaps = xcalloc(qdbs->rows, sizeof *qdbs->pixmaps);
- gtk_tree_selection_selected_foreach(ql->selection,
- ql_drag_make_row_pixmaps,
- qdbs);
- /* Determine the size of the final icon */
- int height = 0, width = 0;
- for(int n = 0; n < qdbs->rows; ++n) {
- int pxw, pxh;
- gdk_drawable_get_size(qdbs->pixmaps[n], &pxw, &pxh);
- if(pxw > width)
- width = pxw;
- height += pxh;
- }
- if(!width || !height)
- return; /* doesn't make sense */
- /* Construct the icon */
- icon = gdk_pixmap_new(qdbs->pixmaps[0], width, height, -1);
- GdkGC *gc = gdk_gc_new(icon);
- gdk_gc_set_colormap(gc, gtk_widget_get_colormap(ql->view));
- int y = 0;
- for(int n = 0; n < qdbs->rows; ++n) {
- int pxw, pxh;
- gdk_drawable_get_size(qdbs->pixmaps[n], &pxw, &pxh);
- gdk_draw_drawable(icon,
- gc,
- qdbs->pixmaps[n],
- 0, 0, /* source coords */
- 0, y, /* dest coords */
- pxw, pxh); /* size */
- y += pxh;
+static GtkTreePath *ql_drop_path(GtkWidget *w,
+ GtkTreeModel *model,
+ int wx, int wy,
+ GtkTreeViewDropPosition *posp) {
+ GtkTreePath *path = NULL;
+ GtkTreeViewDropPosition pos;
+ GtkTreeIter iter[1], last[1];
+ int tx, ty;
+
+ gtk_tree_view_convert_widget_to_tree_coords(GTK_TREE_VIEW(w),
+ wx, wy, &tx, &ty);
+ if(gtk_tree_view_get_dest_row_at_pos(GTK_TREE_VIEW(w),
+ wx, wy,
+ &path,
+ &pos)) {
+ //fprintf(stderr, "gtk_tree_view_get_dest_row_at_pos() -> TRUE\n");
+ // Normalize drop position
+ switch(pos) {
+ case GTK_TREE_VIEW_DROP_INTO_OR_BEFORE:
+ pos = GTK_TREE_VIEW_DROP_BEFORE;
+ break;
+ case GTK_TREE_VIEW_DROP_INTO_OR_AFTER:
+ pos = GTK_TREE_VIEW_DROP_AFTER;
+ break;
+ default: break;
+ }
+ } else if(gtk_tree_model_get_iter_first(model, iter)) {
+ /* If the pointer isn't over any particular row then either it's below
+ * the last row, in which case we want the dropzone to be below that row;
+ * or it's above the first row (in the column headings) in which case we
+ * want the dropzone to be above that row. */
+ if(ty >= 0) {
+ /* Find the last row */
+ do {
+ *last = *iter;
+ } while(gtk_tree_model_iter_next(model, iter));
+ /* The drop target is just after it */
+ pos = GTK_TREE_VIEW_DROP_AFTER;
+ *iter = *last;
+ } else {
+ /* The drop target will be just before the first row */
+ pos = GTK_TREE_VIEW_DROP_BEFORE;
+ }
+ path = gtk_tree_model_get_path(model, iter);