Browse Source

1998-12-02 Federico Mena Quintero <federico@nuclecu.unam.mx>

	* gdesktop.c (setup_desktop_dnd): New function to set up drops
	to the root window.
	(setup_xdnd_proxy): Function by Owen Taylor to set up a DnD proxy
	window.
	(drag_data_received): Function to handle drops on the root window.
	(desktop_destroy): Destroy the DnD setup.
	(reload_desktop_icons): New function to reload the desktop.

	* gscreen.c (drag_types, drop_types): Removed url-list; only
	uri-list should be there.

	* gdesktop.h: Removed TARGET_URL_LIST from the DnD enumerations.
Miguel de Icaza 26 years ago
parent
commit
c0ac4984ab
4 changed files with 195 additions and 23 deletions
  1. 13 0
      gnome/ChangeLog
  2. 180 16
      gnome/gdesktop.c
  3. 0 2
      gnome/gdesktop.h
  4. 2 5
      gnome/gscreen.c

+ 13 - 0
gnome/ChangeLog

@@ -1,5 +1,18 @@
 1998-12-02  Federico Mena Quintero  <federico@nuclecu.unam.mx>
 
+	* gdesktop.c (setup_desktop_dnd): New function to set up drops
+	to the root window.
+	(setup_xdnd_proxy): Function by Owen Taylor to set up a DnD proxy
+	window.
+	(drag_data_received): Function to handle drops on the root window.
+	(desktop_destroy): Destroy the DnD setup.
+	(reload_desktop_icons): New function to reload the desktop.
+
+	* gscreen.c (drag_types, drop_types): Removed url-list; only
+	uri-list should be there.
+
+	* gdesktop.h: Removed TARGET_URL_LIST from the DnD enumerations.
+
 	* gtkdtree.c (gtk_dtree_do_select_dir): Made static, as it is for
 	internal use only.
 	Fixed a little bunch of compiler warnings.

+ 180 - 16
gnome/gdesktop.c

@@ -28,11 +28,14 @@
 #if 1
 #include <config.h>
 #include "fs.h"
+#include <gdk/gdkx.h>
+#include <gtk/gtkinvisible.h>
 #include <gnome.h>
 #include "dialog.h"
 #include "gdesktop.h"
 #include "gdesktop-icon.h"
 #include "gmetadata.h"
+#include "gdnd.h"
 #include "gpopup.h"
 #include "../vfs/vfs.h"
 
@@ -85,6 +88,16 @@ static struct layout_slot *layout_slots;
 /* The last icon to be selected */
 static struct desktop_icon_info *last_selected_icon;
 
+/* Drag and drop targets for the desktop */
+static GtkTargetEntry dnd_targets[] = {
+	{ "text/uri-list", 0, TARGET_URI_LIST }
+};
+
+static int dnd_ntargets = sizeof (dnd_targets) / sizeof (dnd_targets[0]);
+
+static GtkWidget *dnd_proxy_window;
+
+	
 
 /* Looks for a free slot in the layout_slots array and returns the coordinates that coorespond to
  * it.  "Free" means it either has zero icons in it, or it has the minimum number of icons of all
@@ -587,7 +600,7 @@ create_desktop_dir (void)
 
 /* Reads the ~/Desktop directory and creates the initial desktop icons */
 static void
-load_initial_desktop_icons (void)
+load_desktop_icons (void)
 {
 	struct dirent *dirent;
 	DIR *dir;
@@ -630,6 +643,164 @@ load_initial_desktop_icons (void)
 		}
 }
 
+/* Destroys all the current desktop icons */
+static void
+destroy_desktop_icons (void)
+{
+	int i;
+	GList *l;
+	struct desktop_icon_info *dii;
+
+	for (i = 0; i < (layout_cols * layout_rows); i++) {
+		l = layout_slots[i].icons;
+
+		while (l) {
+			dii = l->data;
+			l = l->next;
+
+			desktop_icon_info_free (dii);
+		}
+	}
+}
+
+/* Reloads the desktop icons */
+static void
+reload_desktop_icons (void)
+{
+	destroy_desktop_icons ();
+	load_desktop_icons ();
+}
+
+/* Sets up a proxy window for DnD on the specified X window.  Courtesy of Owen Taylor */
+static gboolean 
+setup_xdnd_proxy (guint32 xid, GdkWindow *proxy_window)
+{
+	GdkAtom xdnd_proxy_atom;
+	guint32 proxy_xid;
+	Atom type;
+	int format;
+	unsigned long nitems, after;
+	Window *proxy_data;
+	Window proxy;
+	guint32 old_warnings;
+
+	XGrabServer (GDK_DISPLAY ());
+
+	xdnd_proxy_atom = gdk_atom_intern ("XdndProxy", FALSE);
+	proxy_xid = GDK_WINDOW_XWINDOW (proxy_window);
+	type = None;
+	proxy = None;
+
+	old_warnings = gdk_error_warnings;
+
+	gdk_error_code = 0;
+	gdk_error_warnings = 0;
+
+	/* Check if somebody else already owns drops on the root window */
+
+	XGetWindowProperty (GDK_DISPLAY (), xid,
+			    xdnd_proxy_atom, 0,
+			    1, False, AnyPropertyType,
+			    &type, &format, &nitems, &after,
+			    (guchar **) &proxy_data);
+
+	if (type != None) {
+		if ((format == 32) && (nitems == 1))
+			proxy = *proxy_data;
+
+		XFree (proxy_data);
+	}
+
+	/* The property was set, now check if the window it points to exists and has a XdndProxy
+	 * property pointing to itself.
+	 */
+	if (proxy) {
+		XGetWindowProperty (GDK_DISPLAY (), proxy, 
+				    xdnd_proxy_atom, 0, 
+				    1, False, AnyPropertyType,
+				    &type, &format, &nitems, &after, 
+				    (guchar **) &proxy_data);
+
+		if (!gdk_error_code && type != None) {
+			if ((format == 32) && (nitems == 1))
+				if (*proxy_data != proxy)
+					proxy = GDK_NONE;
+
+			XFree (proxy_data);
+		} else
+			proxy = GDK_NONE;
+	}
+
+	if (!proxy) {
+		/* OK, we can set the property to point to us */
+
+		XChangeProperty (GDK_DISPLAY (), xid,
+				 xdnd_proxy_atom, gdk_atom_intern ("WINDOW", FALSE),
+				 32, PropModeReplace,
+				 (guchar *) &proxy_xid, 1);
+	}
+
+	gdk_error_code = 0;
+	gdk_error_warnings = old_warnings;
+  
+	XUngrabServer (GDK_DISPLAY ());
+
+	if (!proxy) {
+		/* Mark our window as a valid proxy window with a XdndProxy
+		 * property pointing recursively;
+		 */
+		XChangeProperty (GDK_DISPLAY (), proxy_xid,
+				 xdnd_proxy_atom, gdk_atom_intern ("WINDOW", FALSE),
+				 32, PropModeReplace,
+				 (guchar *) &proxy_xid, 1);
+      
+		return TRUE;
+	} else
+		return FALSE;
+}
+
+/* Callback used when the root window receives a drop */
+static void  
+drag_data_received (GtkWidget *widget, GdkDragContext *context, gint x, gint y,
+		    GtkSelectionData *data, guint info, guint time, gpointer user_data)
+{
+	switch (info) {
+	case TARGET_URI_LIST:
+		printf ("uri list dropped on desktop!\n");
+
+		gdnd_drop_on_directory (context, data, desktop_directory);
+		reload_desktop_icons (); /* FIXME: this is inefficient and it sucks! */
+		
+		/* FIXME: return TRUE for delete if appropriate */
+		gtk_drag_finish (context, TRUE, FALSE, time);
+		return;
+
+	default:
+		break;
+	}
+
+	gtk_drag_finish (context, FALSE, FALSE, time);
+}
+
+/* Sets up drag and drop to the desktop root window */
+static void
+setup_desktop_dnd (void)
+{
+	dnd_proxy_window = gtk_invisible_new ();
+	gtk_widget_show (dnd_proxy_window);
+
+	if (!setup_xdnd_proxy (GDK_ROOT_WINDOW (), dnd_proxy_window->window))
+		g_warning ("Eeeeek, some moron is already taking drops on the root window!");
+
+	gtk_drag_dest_set (dnd_proxy_window,
+			   GTK_DEST_DEFAULT_MOTION | GTK_DEST_DEFAULT_DROP,
+			   dnd_targets, dnd_ntargets,
+			   GDK_ACTION_COPY | GDK_ACTION_MOVE | GDK_ACTION_LINK);
+
+	gtk_signal_connect (GTK_OBJECT (dnd_proxy_window), "drag_data_received",
+			    GTK_SIGNAL_FUNC (drag_data_received), NULL);
+}
+
 /**
  * desktop_init
  *
@@ -641,7 +812,8 @@ desktop_init (void)
 {
 	create_layout_info ();
 	create_desktop_dir ();
-	load_initial_desktop_icons ();
+	load_desktop_icons ();
+	setup_desktop_dnd ();
 }
 
 /**
@@ -652,22 +824,9 @@ desktop_init (void)
 void
 desktop_destroy (void)
 {
-	int i;
-	GList *l;
-	struct desktop_icon_info *dii;
-
 	/* Destroy the desktop icons */
 
-	for (i = 0; i < (layout_cols * layout_rows); i++) {
-		l = layout_slots[i].icons;
-
-		while (l) {
-			dii = l->data;
-			l = l->next;
-
-			desktop_icon_info_free (dii);
-		}
-	}
+	destroy_desktop_icons ();
 
 	/* Cleanup */
 
@@ -678,6 +837,11 @@ desktop_destroy (void)
 
 	g_free (desktop_directory);
 	desktop_directory = NULL;
+
+	/* Remove DnD crap */
+
+	gtk_widget_destroy (dnd_proxy_window);
+	XDeleteProperty (GDK_DISPLAY (), GDK_ROOT_WINDOW (), gdk_atom_intern ("XdndProxy", FALSE));
 }
 
 

+ 0 - 2
gnome/gdesktop.h

@@ -44,7 +44,6 @@ void desktop_destroy (void);
 
 enum {
 	TARGET_URI_LIST,
-	TARGET_URL_LIST,
 	TARGET_TEXT_PLAIN,
 };
 typedef enum {
@@ -69,7 +68,6 @@ typedef struct {
 /* Drag and drop types recognized by us */
 enum {
 	TARGET_URI_LIST,
-	TARGET_URL_LIST,
 	TARGET_TEXT_PLAIN,
 };
 

+ 2 - 5
gnome/gscreen.c

@@ -67,13 +67,11 @@ static char *drop_types [] = { "url:ALL" };
 
 static GtkTargetEntry drag_types [] = {
 	{ "text/uri-list", 0, TARGET_URI_LIST },
-	{ "text/url-list", 0, TARGET_URL_LIST },
-	{ "text/plain",    0, TARGET_TEXT_PLAIN },
+	{ "text/plain",    0, TARGET_TEXT_PLAIN }
 };
 
 static GtkTargetEntry drop_types [] = {
-	{ "text/uri-list", 0, TARGET_URI_LIST },
-	{ "text/url-list", 0, TARGET_URL_LIST },
+	{ "text/uri-list", 0, TARGET_URI_LIST }
 };
 
 #define ELEMENTS(x) (sizeof (x) / sizeof (x[0]))
@@ -721,7 +719,6 @@ panel_drag_data_get (GtkWidget        *widget,
 	char *data;
 			
 	switch (info){
-	case TARGET_URL_LIST:
 	case TARGET_URI_LIST:
 	case TARGET_TEXT_PLAIN:
 		data = panel_build_selected_file_list (panel, &len);