示例#1
0
static gboolean
drag_motion_callback (GtkWidget *widget,
		      GdkDragContext *context,
		      int x, int y,
		      guint32 time)
{
	int action;

	nemo_icon_container_ensure_drag_data (NEMO_ICON_CONTAINER (widget), context, time);
	nemo_icon_container_position_shadow (NEMO_ICON_CONTAINER (widget), x, y);
	nemo_icon_dnd_update_drop_target (NEMO_ICON_CONTAINER (widget), context, x, y);
	set_up_auto_scroll_if_needed (NEMO_ICON_CONTAINER (widget));
	/* Find out what the drop actions are based on our drag selection and
	 * the drop target.
	 */
	action = 0;
	nemo_icon_container_get_drop_action (NEMO_ICON_CONTAINER (widget), context, x, y,
						 &action);
	if (action != 0) {
		start_dnd_highlight (widget);
	}
	  
	gdk_drag_status (context, action, time);

	return TRUE;
}
示例#2
0
/* FIXME bugzilla.gnome.org 47445: Needs to become a shared function */
static void
get_data_on_first_target_we_support (GtkWidget *widget, GdkDragContext *context, guint32 time, int x, int y)
{
	GtkTargetList *list;
	GdkAtom target;

	if (drop_types_list == NULL) {
		drop_types_list = gtk_target_list_new (drop_types,
						       G_N_ELEMENTS (drop_types) - 1);
		gtk_target_list_add_text_targets (drop_types_list, NEMO_ICON_DND_TEXT);
	}
	if (drop_types_list_root == NULL) {
		drop_types_list_root = gtk_target_list_new (drop_types,
							    G_N_ELEMENTS (drop_types));
		gtk_target_list_add_text_targets (drop_types_list_root, NEMO_ICON_DND_TEXT);
	}
	
	if (nemo_icon_container_get_is_desktop (NEMO_ICON_CONTAINER (widget))) {
		list = drop_types_list_root;
	} else {
		list = drop_types_list;
	}

	target = gtk_drag_dest_find_target (widget, context, list);
	if (target != GDK_NONE) {
		guint info;
		NemoDragInfo *drag_info;
		gboolean found;

		drag_info = &(NEMO_ICON_CONTAINER (widget)->details->dnd_info->drag_info);

		found = gtk_target_list_find (list, target, &info);
		g_assert (found);

		/* Don't get_data for destructive ops */
		if ((info == NEMO_ICON_DND_ROOTWINDOW_DROP ||
		     info == NEMO_ICON_DND_XDNDDIRECTSAVE) &&
		    !drag_info->drop_occured) {
			/* We can't call get_data here, because that would
			   make the source execute the rootwin action or the direct save */
			drag_info->got_drop_data_type = TRUE;
			drag_info->data_type = info;
		} else {
			if (info == NEMO_ICON_DND_XDNDDIRECTSAVE) {
				set_direct_save_uri (widget, context, drag_info, x, y);
			}
			gtk_drag_get_data (GTK_WIDGET (widget), context,
					   target, time);
		}
	}
}
示例#3
0
static void
nemo_icon_container_dropped_icon_feedback (GtkWidget *widget,
					       GtkSelectionData *data,
					       int x, int y)
{
	NemoIconContainer *container;
	NemoIconDndInfo *dnd_info;

	container = NEMO_ICON_CONTAINER (widget);
	dnd_info = container->details->dnd_info;
	
	/* Delete old selection list. */
	nemo_drag_destroy_selection_list (dnd_info->drag_info.selection_list);
	dnd_info->drag_info.selection_list = NULL;

	/* Delete old shadow if any. */
	if (dnd_info->shadow != NULL) {
		/* FIXME bugzilla.gnome.org 42484: 
		 * Is a destroy really sufficient here? Who does the unref? */
		eel_canvas_item_destroy (dnd_info->shadow);
	}

	/* Build the selection list and the shadow. */
	dnd_info->drag_info.selection_list = nemo_drag_build_selection_list (data);
	dnd_info->shadow = create_selection_shadow (container, dnd_info->drag_info.selection_list);
	nemo_icon_container_position_shadow (container, x, y);
}
示例#4
0
/* Queue a redraw of the dnd highlight rect */
static void
dnd_highlight_queue_redraw (GtkWidget *widget)
{
	NemoIconDndInfo *dnd_info;
	int width, height;
	GtkAllocation allocation;
	
	dnd_info = NEMO_ICON_CONTAINER (widget)->details->dnd_info;
	
	if (!dnd_info->highlighted) {
		return;
	}

	gtk_widget_get_allocation (widget, &allocation);
	width = allocation.width;
	height = allocation.height;

	/* we don't know how wide the shadow is exactly,
	 * so we expose a 10-pixel wide border
	 */
	gtk_widget_queue_draw_area (widget,
				    0, 0,
				    width, 10);
	gtk_widget_queue_draw_area (widget,
				    0, 0,
				    10, height);
	gtk_widget_queue_draw_area (widget,
				    0, height - 10,
				    width, 10);
	gtk_widget_queue_draw_area (widget,
				    width - 10, 0,
				    10, height);
}
示例#5
0
static void
drag_begin_callback (GtkWidget      *widget,
		     GdkDragContext *context,
		     gpointer        data)
{
	NemoIconContainer *container;
	cairo_surface_t *surface;
	double x1, y1, x2, y2, winx, winy;
	int x_offset, y_offset;
	int start_x, start_y;

	container = NEMO_ICON_CONTAINER (widget);

	start_x = container->details->dnd_info->drag_info.start_x +
		gtk_adjustment_get_value (gtk_scrollable_get_hadjustment (GTK_SCROLLABLE (container)));
	start_y = container->details->dnd_info->drag_info.start_y +
		gtk_adjustment_get_value (gtk_scrollable_get_vadjustment (GTK_SCROLLABLE (container)));

        /* create a pixmap and mask to drag with */
        surface = nemo_icon_canvas_item_get_drag_surface (container->details->drag_icon->item);

        /* compute the image's offset */
	eel_canvas_item_get_bounds (EEL_CANVAS_ITEM (container->details->drag_icon->item),
				    &x1, &y1, &x2, &y2);
	eel_canvas_world_to_window (EEL_CANVAS (container), 
				    x1, y1,  &winx, &winy);
        x_offset = start_x - winx;
        y_offset = start_y - winy;

        cairo_surface_set_device_offset (surface, -x_offset, -y_offset);
        gtk_drag_set_icon_surface (context, surface);
        cairo_surface_destroy (surface);
}
示例#6
0
static void
drag_leave_callback (GtkWidget *widget,
		     GdkDragContext *context,
		     guint32 time,
		     gpointer data)
{
	NemoIconDndInfo *dnd_info;

	dnd_info = NEMO_ICON_CONTAINER (widget)->details->dnd_info;
	
	if (dnd_info->shadow != NULL)
		eel_canvas_item_hide (dnd_info->shadow);

	stop_dnd_highlight (widget);
	
	set_drop_target (NEMO_ICON_CONTAINER (widget), NULL);
	stop_auto_scroll (NEMO_ICON_CONTAINER (widget));
	nemo_icon_container_free_drag_data(NEMO_ICON_CONTAINER (widget));
}
示例#7
0
NemoIconContainer *
nemo_icon_view_container_construct (NemoIconViewContainer *icon_container, NemoIconView *view)
{
	AtkObject *atk_obj;

	g_return_val_if_fail (NEMO_IS_ICON_VIEW (view), NULL);

	icon_container->view = view;
	atk_obj = gtk_widget_get_accessible (GTK_WIDGET (icon_container));
	atk_object_set_name (atk_obj, _("Icon View"));

	return NEMO_ICON_CONTAINER (icon_container);
}
示例#8
0
static void
drag_end_callback (GtkWidget *widget,
		   GdkDragContext *context,
		   gpointer data)
{
	NemoIconContainer *container;
	NemoIconDndInfo *dnd_info;

	container = NEMO_ICON_CONTAINER (widget);
	dnd_info = container->details->dnd_info;

	nemo_drag_destroy_selection_list (dnd_info->drag_info.selection_list);
	dnd_info->drag_info.selection_list = NULL;
}
示例#9
0
/* Adaptor function used with nemo_icon_container_each_selected_icon
 * to help iterate over all selected items, passing uris, x, y, w and h
 * values to the iteratee
 */
static void
each_icon_get_data_binder (NemoDragEachSelectedItemDataGet iteratee, 
	gpointer iterator_context, gpointer data)
{
	IconGetDataBinderContext context;
	NemoIconContainer *container;

	g_assert (NEMO_IS_ICON_CONTAINER (iterator_context));
	container = NEMO_ICON_CONTAINER (iterator_context);

	context.iterator_context = iterator_context;
	context.iteratee = iteratee;
	context.iteratee_data = data;
	nemo_icon_container_each_selected_icon (container, icon_get_data_binder, &context);
}
示例#10
0
static void
stop_dnd_highlight (GtkWidget *widget)
{
	NemoIconDndInfo *dnd_info;
	
	dnd_info = NEMO_ICON_CONTAINER (widget)->details->dnd_info;

	if (dnd_info->highlighted) {
		g_signal_handlers_disconnect_by_func (widget,
						      drag_highlight_draw,
						      NULL);
		dnd_highlight_queue_redraw (widget);
		dnd_info->highlighted = FALSE;
	}
}
示例#11
0
static gboolean
icon_get_data_binder (NemoIcon *icon, gpointer data)
{
	IconGetDataBinderContext *context;
	EelDRect world_rect;
	EelIRect widget_rect;
	char *uri;
	NemoIconContainer *container;

	context = (IconGetDataBinderContext *)data;

	g_assert (NEMO_IS_ICON_CONTAINER (context->iterator_context));

	container = NEMO_ICON_CONTAINER (context->iterator_context);

	world_rect = nemo_icon_canvas_item_get_icon_rectangle (icon->item);

	canvas_rect_world_to_widget (EEL_CANVAS (container), &world_rect, &widget_rect);

	uri = nemo_icon_container_get_icon_uri (container, icon);
	if (uri == NULL) {
		g_warning ("no URI for one of the iterated icons");
		return TRUE;
	}

	widget_rect = eel_irect_offset_by (widget_rect, 
		- container->details->dnd_info->drag_info.start_x,
		- container->details->dnd_info->drag_info.start_y);

	widget_rect = eel_irect_scale_by (widget_rect, 
		1 / EEL_CANVAS (container)->pixels_per_unit);
	
	/* pass the uri, mouse-relative x/y and icon width/height */
	context->iteratee (uri, 
			   (int) widget_rect.x0,
			   (int) widget_rect.y0,
			   widget_rect.x1 - widget_rect.x0,
			   widget_rect.y1 - widget_rect.y0,
			   context->iteratee_data);

	g_free (uri);

	return TRUE;
}
示例#12
0
static void
set_direct_save_uri (GtkWidget *widget, GdkDragContext *context, NemoDragInfo *drag_info, int x, int y)
{
	GFile *base, *child;
	char *filename, *drop_target;
	gchar *uri;
	
	drag_info->got_drop_data_type = TRUE;
	drag_info->data_type = NEMO_ICON_DND_XDNDDIRECTSAVE;
	
	uri = NULL;
	
	filename = get_direct_save_filename (context);
	drop_target = nemo_icon_container_find_drop_target (NEMO_ICON_CONTAINER (widget), 
								context, x, y, NULL, TRUE);
	
	if (drop_target && eel_uri_is_trash (drop_target)) {
		g_free (drop_target);
		drop_target = NULL; /* Cannot save to trash ...*/
	}
	
	if (filename != NULL && drop_target != NULL) {
		/* Resolve relative path */
		base = g_file_new_for_uri (drop_target);
		child = g_file_get_child (base, filename);
		uri = g_file_get_uri (child);
		g_object_unref (base);
		g_object_unref (child);
		
		/* Change the uri property */
		gdk_property_change (gdk_drag_context_get_source_window (context),
				     gdk_atom_intern (NEMO_ICON_DND_XDNDDIRECTSAVE_TYPE, FALSE),
				     gdk_atom_intern ("text/plain", FALSE), 8,
				     GDK_PROP_MODE_REPLACE, (const guchar *) uri,
				     strlen (uri));
		
		drag_info->direct_save_uri = uri;
	} 
	
	g_free (filename);
	g_free (drop_target);
}
示例#13
0
static void
start_dnd_highlight (GtkWidget *widget)
{
	NemoIconDndInfo *dnd_info;
	GtkWidget *toplevel;
	
	dnd_info = NEMO_ICON_CONTAINER (widget)->details->dnd_info;

	toplevel = gtk_widget_get_toplevel (widget);
	if (toplevel != NULL &&
	    g_object_get_data (G_OBJECT (toplevel), "is_desktop_window")) {
		return;
	}

	if (!dnd_info->highlighted) {
		dnd_info->highlighted = TRUE;
		g_signal_connect_after (widget, "draw",
					G_CALLBACK (drag_highlight_draw),
					NULL);
		dnd_highlight_queue_redraw (widget);
	}
}
示例#14
0
static gboolean
drag_drop_callback (GtkWidget *widget,
		    GdkDragContext *context,
		    int x,
		    int y,
		    guint32 time,
		    gpointer data)
{
	NemoIconDndInfo *dnd_info;

	dnd_info = NEMO_ICON_CONTAINER (widget)->details->dnd_info;

	/* tell the drag_data_received callback that
	   the drop occured and that it can actually
	   process the actions.
	   make sure it is going to be called at least once.
	*/
	dnd_info->drag_info.drop_occured = TRUE;

	get_data_on_first_target_we_support (widget, context, time, x, y);
	
	return TRUE;
}
示例#15
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;
}
示例#16
0
static void
drag_data_received_callback (GtkWidget *widget,
			     GdkDragContext *context,
			     int x,
			     int y,
			     GtkSelectionData *data,
			     guint info,
			     guint32 time,
			     gpointer user_data)
{
    	NemoDragInfo *drag_info;
	char *tmp;
	const char *tmp_raw;
	int length;
	gboolean success;

	drag_info = &(NEMO_ICON_CONTAINER (widget)->details->dnd_info->drag_info);

	drag_info->got_drop_data_type = TRUE;
	drag_info->data_type = info;

	switch (info) {
	case NEMO_ICON_DND_GNOME_ICON_LIST:
		nemo_icon_container_dropped_icon_feedback (widget, data, x, y);
		break;
	case NEMO_ICON_DND_URI_LIST:
	case NEMO_ICON_DND_TEXT:
	case NEMO_ICON_DND_XDNDDIRECTSAVE:
	case NEMO_ICON_DND_RAW:
		/* Save the data so we can do the actual work on drop. */
		if (drag_info->selection_data != NULL) {
			gtk_selection_data_free (drag_info->selection_data);
		}
		drag_info->selection_data = gtk_selection_data_copy (data);
		break;

	/* Netscape keeps sending us the data, even though we accept the first drag */
	case NEMO_ICON_DND_NETSCAPE_URL:
		if (drag_info->selection_data != NULL) {
			gtk_selection_data_free (drag_info->selection_data);
			drag_info->selection_data = gtk_selection_data_copy (data);
		}
		break;
	case NEMO_ICON_DND_ROOTWINDOW_DROP:
		/* Do nothing, this won't even happen, since we don't want to call get_data twice */
		break;
	}

	/* this is the second use case of this callback.
	 * we have to do the actual work for the drop.
	 */
	if (drag_info->drop_occured) {

		success = FALSE;
		switch (info) {
		case NEMO_ICON_DND_GNOME_ICON_LIST:
			nemo_icon_container_receive_dropped_icons
				(NEMO_ICON_CONTAINER (widget),
				 context, x, y);
			break;
		case NEMO_ICON_DND_NETSCAPE_URL:
			receive_dropped_netscape_url
				(NEMO_ICON_CONTAINER (widget),
				 (char *) gtk_selection_data_get_data (data), context, x, y);
			success = TRUE;
			break;
		case NEMO_ICON_DND_URI_LIST:
			receive_dropped_uri_list
				(NEMO_ICON_CONTAINER (widget),
				 (char *) gtk_selection_data_get_data (data), context, x, y);
			success = TRUE;
			break;
		case NEMO_ICON_DND_TEXT:
			tmp = gtk_selection_data_get_text (data);
			receive_dropped_text
				(NEMO_ICON_CONTAINER (widget),
				 (char *) tmp, context, x, y);
			success = TRUE;
			g_free (tmp);
			break;
		case NEMO_ICON_DND_RAW:
			length = gtk_selection_data_get_length (data);
			tmp_raw = gtk_selection_data_get_data (data);
			receive_dropped_raw
				(NEMO_ICON_CONTAINER (widget),
				 tmp_raw, length, drag_info->direct_save_uri,
				 context, x, y);
			success = TRUE;
			break;
		case NEMO_ICON_DND_ROOTWINDOW_DROP:
			/* Do nothing, everything is done by the sender */
			break;
		case NEMO_ICON_DND_XDNDDIRECTSAVE:
		{
			const guchar *selection_data;
			gint selection_length;
			gint selection_format;

			selection_data = gtk_selection_data_get_data (drag_info->selection_data);
			selection_length = gtk_selection_data_get_length (drag_info->selection_data);
			selection_format = gtk_selection_data_get_format (drag_info->selection_data);

			if (selection_format == 8 &&
			    selection_length == 1 &&
			    selection_data[0] == 'F') {
				gtk_drag_get_data (widget, context,
				                  gdk_atom_intern (NEMO_ICON_DND_RAW_TYPE,
				                                   FALSE),
				                  time);
				return;
			} else if (selection_format == 8 &&
				   selection_length == 1 &&
				   selection_data[0] == 'F' &&
			           drag_info->direct_save_uri != NULL) {
				GdkPoint p;
				GFile *location;

				location = g_file_new_for_uri (drag_info->direct_save_uri);

				nemo_file_changes_queue_file_added (location);
				p.x = x; p.y = y;
				nemo_file_changes_queue_schedule_position_set (
				                 location,
				                 p,
				                 gdk_screen_get_number (
				                             gtk_widget_get_screen (widget)));
				g_object_unref (location);
				nemo_file_changes_consume_changes (TRUE);
				success = TRUE;
			}
			break;
		} /* NEMO_ICON_DND_XDNDDIRECTSAVE */
		}
		gtk_drag_finish (context, success, FALSE, time);
		
		nemo_icon_container_free_drag_data (NEMO_ICON_CONTAINER (widget));
		
		set_drop_target (NEMO_ICON_CONTAINER (widget), NULL);

		/* reinitialise it for the next dnd */
		drag_info->drop_occured = FALSE;
	}

}