From c0ac4984ab52e13ef9c2cc90afe416de82423206 Mon Sep 17 00:00:00 2001 From: Miguel de Icaza Date: Wed, 2 Dec 1998 23:37:27 +0000 Subject: [PATCH] 1998-12-02 Federico Mena Quintero * 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. --- gnome/ChangeLog | 13 +++ gnome/gdesktop.c | 212 +++++++++++++++++++++++++++++++++++++++++------ gnome/gdesktop.h | 2 - gnome/gscreen.c | 7 +- 4 files changed, 203 insertions(+), 31 deletions(-) diff --git a/gnome/ChangeLog b/gnome/ChangeLog index 772fc0b39..7641c8754 100644 --- a/gnome/ChangeLog +++ b/gnome/ChangeLog @@ -1,5 +1,18 @@ 1998-12-02 Federico Mena Quintero + * 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. diff --git a/gnome/gdesktop.c b/gnome/gdesktop.c index d9b551425..acd3fa11d 100644 --- a/gnome/gdesktop.c +++ b/gnome/gdesktop.c @@ -28,11 +28,14 @@ #if 1 #include #include "fs.h" +#include +#include #include #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,34 +643,14 @@ load_initial_desktop_icons (void) } } -/** - * desktop_init - * - * Initializes the desktop by setting up the default icons (if necessary), setting up drag and drop, - * and other miscellaneous tasks. - */ -void -desktop_init (void) -{ - create_layout_info (); - create_desktop_dir (); - load_initial_desktop_icons (); -} - -/** - * desktop_destroy - * - * Shuts the desktop down by destroying the desktop icons. - */ -void -desktop_destroy (void) +/* Destroys all the current desktop icons */ +static void +destroy_desktop_icons (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; @@ -668,6 +661,172 @@ desktop_destroy (void) 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 + * + * Initializes the desktop by setting up the default icons (if necessary), setting up drag and drop, + * and other miscellaneous tasks. + */ +void +desktop_init (void) +{ + create_layout_info (); + create_desktop_dir (); + load_desktop_icons (); + setup_desktop_dnd (); +} + +/** + * desktop_destroy + * + * Shuts the desktop down by destroying the desktop icons. + */ +void +desktop_destroy (void) +{ + /* Destroy the desktop icons */ + + 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)); } diff --git a/gnome/gdesktop.h b/gnome/gdesktop.h index 537e54e74..f45769c20 100644 --- a/gnome/gdesktop.h +++ b/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, }; diff --git a/gnome/gscreen.c b/gnome/gscreen.c index 3d4c06a77..3a7046612 100644 --- a/gnome/gscreen.c +++ b/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);