[PATCH] Visual notification when opening stuff in nautilus (was Re: What is the official way to get an icon coordinates from a NautilusFile ?)



Hey all,

I have attached a new patch to fix bug 147994 -
Notification when you open a file in nautilus (like the panel)
http://bugzilla.gnome.org/show_bug.cgi?id=147994
and have attached it to this email as well.

It adds zooming boxes in nautilus when you activate one or several
icons in an icon view, either folders or files. In the case of
folders, the zooming boxes expand to the position of the newly opened
folder. It works in spatial or browser mode (but not yet in list
view).

This kind of animation is really helpful because 1. it provides a
visual notification that nautilus has registered your click (no more
double-clicking on openoffice files and wondering if something is
actually happening) and 2. it provides a strong visual link between a
folder icon and its opened window. (3. it looks nice :-))

Comments ?
Cheers
Vincent

On 6/2/05, Alexander Larsson <alexl redhat com> wrote:
> On Wed, 2005-06-01 at 17:47 -0400, Vincent Noel wrote:
> > Hey all,
> > I'm trying to come up with a patch for bug #147994 - visual
> > notification when you double-click on something on your desktop (e.g.
> > the "zooming boxes" you get when you click a launcher on your panel).
> > In order to do this, I need to find the screen coordinates of the
> > selected icon in the active window - I've tried to get them using
> >    position_string = nautilus_file_get_metadata (file,
> > NAUTILUS_METADATA_KEY_ICON_POSITION, "");
> > But it does not work (I get nonsense as a result).
> 
> Yeah, the metadata is only used for manual placement mode, and its about
> the positioning in the icon container, not on the screen.
> 
> > What is the good, official way to do this ?
> 
> There is none at the moment. You'd have to create some.
> 
> =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
>  Alexander Larsson                                            Red Hat, Inc
>                    alexl redhat com    alla lysator liu se
> He's a witless native American jungle king from the Mississippi delta. She's a
> vivacious tomboy Valkyrie from a secret island of warrior women. They fight
> crime!
> 
>
Index: src/nautilus-window-manage-views.c
===================================================================
RCS file: /cvs/gnome/nautilus/src/nautilus-window-manage-views.c,v
retrieving revision 1.351
diff -u -r1.351 nautilus-window-manage-views.c
--- src/nautilus-window-manage-views.c	19 Apr 2005 12:01:16 -0000	1.351
+++ src/nautilus-window-manage-views.c	3 Jun 2005 16:52:07 -0000
@@ -34,6 +34,7 @@
 #include "nautilus-main.h"
 #include "nautilus-window-private.h"
 #include "nautilus-zoom-control.h"
+#include "file-manager/xstuff.h"
 #include <eel/eel-accessibility.h>
 #include <eel/eel-debug.h>
 #include <eel/eel-gdk-extensions.h>
@@ -842,6 +843,7 @@
 	NautilusWindow *window;
 	char *location;
 	char *home_uri;
+	GdkRectangle rect;
 
 	window = callback_data;
 	
@@ -899,6 +901,11 @@
 		}
 		create_content_view (window, view_id);
 		g_free (view_id);
+		
+		gtk_window_get_position (GTK_WINDOW (window), &rect.x, &rect.y);
+		gtk_window_get_default_size (GTK_WINDOW (window), &rect.width, &rect.height);
+		xstuff_queued_zoom_animate (GTK_WIDGET (window), &rect);
+
 	} else {
 		display_view_selection_failure (window, file,
 						location);
Index: src/file-manager/Makefile.am
===================================================================
RCS file: /cvs/gnome/nautilus/src/file-manager/Makefile.am,v
retrieving revision 1.80
diff -u -r1.80 Makefile.am
--- src/file-manager/Makefile.am	25 Nov 2004 14:59:54 -0000	1.80
+++ src/file-manager/Makefile.am	3 Jun 2005 16:52:07 -0000
@@ -38,6 +38,8 @@
 	fm-tree-model.h			\
 	fm-tree-view.c			\
 	fm-tree-view.h			\
+	xstuff.c			\
+	xstuff.h			\
 	$(NULL)
 
 
Index: src/file-manager/fm-directory-view.c
===================================================================
RCS file: /cvs/gnome/nautilus/src/file-manager/fm-directory-view.c,v
retrieving revision 1.683
diff -u -r1.683 fm-directory-view.c
--- src/file-manager/fm-directory-view.c	2 Jun 2005 20:15:04 -0000	1.683
+++ src/file-manager/fm-directory-view.c	3 Jun 2005 16:52:07 -0000
@@ -32,6 +32,7 @@
 #include "fm-directory-view.h"
 #include "fm-list-view.h"
 #include "fm-desktop-icon-view.h"
+#include "xstuff.h"
 
 #include "fm-actions.h"
 #include "fm-error-reporting.h"
@@ -84,6 +85,7 @@
 #include <libnautilus-private/nautilus-file-utilities.h>
 #include <libnautilus-private/nautilus-file-private.h> /* for nautilus_file_get_existing */
 #include <libnautilus-private/nautilus-global-preferences.h>
+#include <libnautilus-private/nautilus-icon-private.h>
 #include <libnautilus-private/nautilus-icon-factory.h>
 #include <libnautilus-private/nautilus-link.h>
 #include <libnautilus-private/nautilus-metadata.h>
@@ -7019,6 +7021,50 @@
 			     parameters);
 }
 
+static GdkRectangle *
+get_icon_rectangle (FMDirectoryView *view, NautilusFile *file)
+{
+	NautilusIconContainer *container;
+	NautilusIconCanvasItem *item;
+	ArtDRect rect;
+	GdkRectangle *rectangle;
+	GList *p;
+	NautilusIcon *icon;
+	char *icon_uri, *uri;
+	int container_x, container_y;
+
+	g_return_val_if_fail (FM_IS_DIRECTORY_VIEW (view), NULL);
+	g_return_val_if_fail (NAUTILUS_IS_FILE (file), NULL);
+
+	icon_uri = nautilus_file_get_activation_uri (file);
+
+	g_return_val_if_fail (NAUTILUS_IS_ICON_CONTAINER (GTK_BIN(view)->child), NULL);	
+	container = NAUTILUS_ICON_CONTAINER (GTK_BIN (view)->child);
+
+	for (p = container->details->icons; p!=NULL; p = p->next) {
+		icon = p->data;
+		if (!icon->is_selected) {
+			continue;
+		}
+		/* This is to get the real local address */
+		uri = nautilus_icon_container_get_icon_drop_target_uri (container, icon);
+		if (gnome_vfs_uris_match (uri, icon_uri)) {
+			item = icon->item;
+			rect = nautilus_icon_canvas_item_get_icon_rectangle (item);
+			gdk_window_get_origin (GTK_WIDGET(container)->window, 
+					       &container_x, &container_y);
+			rectangle = g_new0 (GdkRectangle, 1);
+			rectangle->x = rect.x0 + container_x;
+			rectangle->y = rect.y0 + container_y;
+			rectangle->width = rect.x1 - rect.x0;
+			rectangle->height = rect.y1 - rect.y0;
+			return rectangle;
+		} 
+	}
+	return NULL;
+}
+
+
 static void
 activate_callback (NautilusFile *file, gpointer callback_data)
 {
@@ -7029,6 +7075,7 @@
 	char *old_working_dir;
 	ActivationAction action;
 	GdkScreen *screen;
+	GdkRectangle *rectangle;
 
 	parameters = callback_data;
 
@@ -7043,6 +7090,12 @@
 		return;
 	}
 
+	rectangle = get_icon_rectangle (view, file);
+	if (rectangle) {
+		xstuff_queue_zoom (rectangle);
+		g_free (rectangle);
+	}
+
 	orig_uri = uri = nautilus_file_get_activation_uri (file);
 
 	action = get_activation_action (file);
@@ -7058,6 +7111,7 @@
 	
 	switch (action) {
 	case ACTIVATION_ACTION_LAUNCH_DESKTOP_FILE :
+		xstuff_queued_zoom_animate (GTK_WIDGET(view), NULL);
 		file_uri = nautilus_file_get_uri (file);
 		nautilus_launch_desktop_file (
 				screen, file_uri, NULL,
@@ -7065,11 +7119,13 @@
 		g_free (file_uri);		 
 		break;
 	case ACTIVATION_ACTION_LAUNCH_APPLICATION_FROM_COMMAND :
+		xstuff_queued_zoom_animate (GTK_WIDGET(view), NULL);
 		uri += strlen (NAUTILUS_COMMAND_SPECIFIER);
 		nautilus_launch_application_from_command (screen, NULL, uri, NULL, FALSE);
 		break;
 	case ACTIVATION_ACTION_LAUNCH :
 	case ACTIVATION_ACTION_LAUNCH_IN_TERMINAL :
+		xstuff_queued_zoom_animate (GTK_WIDGET(view), NULL);
 		old_working_dir = change_to_view_directory (view);
 
 		executable_path = gnome_vfs_get_local_path_from_uri (uri);
@@ -7090,6 +7146,7 @@
 		open_location (view, uri, parameters->mode, parameters->flags);
 		break;
 	case ACTIVATION_ACTION_OPEN_IN_APPLICATION :
+		xstuff_queued_zoom_animate (GTK_WIDGET(view), NULL);
 		nautilus_launch_show_file
 			(file, fm_directory_view_get_containing_window (view));
 		
--- /dev/null	Fri Mar 23 23:37:44 2001
+++ src/file-manager/xstuff.c	Fri Jun  3 12:37:32 2005
@@ -0,0 +1,543 @@
+/*
+ * GNOME panel x stuff
+ *
+ * Copyright (C) 2000, 2001 Eazel, Inc.
+ *               2002 Sun Microsystems Inc.
+ *
+ * Authors: George Lebl <jirka 5z com>
+ *          Mark McLoughlin <mark skynet ie>
+ *
+ *  Contains code from the Window Maker window manager
+ *
+ *  Copyright (c) 1997-2002 Alfredo K. Kojima
+
+ */
+#include <config.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <gdk/gdk.h>
+#include <gdk/gdkx.h>
+
+#include <X11/Xlib.h>
+#include <X11/Xatom.h>
+
+#include "xstuff.h"
+
+GList *pending_zooms = NULL;
+
+static Atom
+panel_atom_get (const char *atom_name)
+{
+	static GHashTable *atom_hash;
+	Display           *xdisplay;
+	Atom               retval;
+
+	g_return_val_if_fail (atom_name != NULL, None);
+
+	xdisplay = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
+
+	if (!atom_hash)
+		atom_hash = g_hash_table_new_full (
+				g_str_hash, g_str_equal, g_free, NULL);
+
+	retval = GPOINTER_TO_UINT (g_hash_table_lookup (atom_hash, atom_name));
+	if (!retval) {
+		retval = XInternAtom (xdisplay, atom_name, FALSE);
+
+		if (retval != None)
+			g_hash_table_insert (atom_hash, g_strdup (atom_name),
+					     GUINT_TO_POINTER (retval));
+	}
+
+	return retval;
+}
+
+/* Stolen from deskguide */
+static gpointer
+get_typed_property_data (Display *xdisplay,
+			 Window   xwindow,
+			 Atom     property,
+			 Atom     requested_type,
+			 gint    *size_p,
+			 guint    expected_format)
+{
+  static const guint prop_buffer_lengh = 1024 * 1024;
+  unsigned char *prop_data = NULL;
+  Atom type_returned = 0;
+  unsigned long nitems_return = 0, bytes_after_return = 0;
+  int format_returned = 0;
+  gpointer data = NULL;
+  gboolean abort = FALSE;
+
+  g_return_val_if_fail (size_p != NULL, NULL);
+  *size_p = 0;
+
+  gdk_error_trap_push ();
+
+  abort = XGetWindowProperty (xdisplay,
+			      xwindow,
+			      property,
+			      0, prop_buffer_lengh,
+			      False,
+			      requested_type,
+			      &type_returned, &format_returned,
+			      &nitems_return,
+			      &bytes_after_return,
+			      &prop_data) != Success;
+  if (gdk_error_trap_pop () ||
+      type_returned == None)
+    abort++;
+  if (!abort &&
+      requested_type != AnyPropertyType &&
+      requested_type != type_returned)
+    {
+      g_warning (G_GNUC_PRETTY_FUNCTION "(): Property has wrong type, probably on crack");
+      abort++;
+    }
+  if (!abort && bytes_after_return)
+    {
+      g_warning (G_GNUC_PRETTY_FUNCTION "(): Eeek, property has more than %u bytes, stored on harddisk?",
+		 prop_buffer_lengh);
+      abort++;
+    }
+  if (!abort && expected_format && expected_format != format_returned)
+    {
+      g_warning (G_GNUC_PRETTY_FUNCTION "(): Expected format (%u) unmatched (%d), programmer was drunk?",
+		 expected_format, format_returned);
+      abort++;
+    }
+  if (!abort && prop_data && nitems_return && format_returned)
+    {
+      switch (format_returned)
+	{
+	case 32:
+	  *size_p = nitems_return * 4;
+	  if (sizeof (gulong) == 8)
+	    {
+	      guint32 i, *mem = g_malloc0 (*size_p + 1);
+	      gulong *prop_longs = (gulong*) prop_data;
+
+	      for (i = 0; i < *size_p / 4; i++)
+		mem[i] = prop_longs[i];
+	      data = mem;
+	    }
+	  break;
+	case 16:
+	  *size_p = nitems_return * 2;
+	  break;
+	case 8:
+	  *size_p = nitems_return;
+	  break;
+	default:
+	  g_warning ("Unknown property data format with %d bits (extraterrestrial?)",
+		     format_returned);
+	  break;
+	}
+      if (!data && *size_p)
+	{
+	  guint8 *mem = g_malloc (*size_p + 1);
+
+	  memcpy (mem, prop_data, *size_p);
+	  mem[*size_p] = 0;
+	  data = mem;
+	}
+    }
+
+  if (prop_data)
+    XFree (prop_data);
+  
+  return data;
+}
+
+gboolean
+xstuff_is_compliant_wm (void)
+{
+	Display  *xdisplay;
+	Window    root_window;
+	gpointer  data;
+	int       size;
+
+	xdisplay = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
+	root_window = GDK_WINDOW_XWINDOW (
+				gdk_get_default_root_window ());
+
+        /* FIXME this is totally broken; should be using
+         * gdk_net_wm_supports() on particular hints when we rely
+         * on those particular hints
+         */
+	data = get_typed_property_data (
+			xdisplay, root_window,
+			panel_atom_get ("_NET_SUPPORTED"),
+			XA_ATOM, &size, 32);
+
+	if (!data)
+		return FALSE;
+
+	/* Actually checks for some of these */
+	g_free (data);
+	return TRUE;
+}
+
+gboolean
+xstuff_net_wm_supports (const char *hint)
+{
+	return gdk_net_wm_supports (gdk_atom_intern (hint, FALSE));
+}
+
+/* This is such a broken stupid function. */   
+void
+xstuff_set_pos_size (GdkWindow *window, int x, int y, int w, int h)
+{
+	XSizeHints size_hints;
+	int old_x, old_y, old_w, old_h;
+
+	old_x = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (window), "xstuff-cached-x"));
+	old_y = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (window), "xstuff-cached-y"));
+	old_w = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (window), "xstuff-cached-w"));
+	old_h = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (window), "xstuff-cached-h"));
+
+	if (x == old_x && y == old_y && w == old_w && h == old_h)
+		return;
+
+	/* Do not add USPosition / USSize here, fix the damn WM */
+	size_hints.flags = PPosition | PSize | PMaxSize | PMinSize;
+	size_hints.x = 0; /* window managers aren't supposed to and  */
+	size_hints.y = 0; /* don't use these fields */
+	size_hints.width = w;
+	size_hints.height = h;
+	size_hints.min_width = w;
+       	size_hints.min_height = h;
+	size_hints.max_width = w;
+	size_hints.max_height = h;
+  
+	gdk_error_trap_push ();
+
+	XSetWMNormalHints (GDK_WINDOW_XDISPLAY (window),
+			   GDK_WINDOW_XWINDOW (window),
+			   &size_hints);
+
+	gdk_window_move_resize (window, x, y, w, h);
+
+	gdk_flush ();
+	gdk_error_trap_pop ();
+
+	g_object_set_data (G_OBJECT (window), "xstuff-cached-x", GINT_TO_POINTER (x));
+	g_object_set_data (G_OBJECT (window), "xstuff-cached-y", GINT_TO_POINTER (y));
+	g_object_set_data (G_OBJECT (window), "xstuff-cached-w", GINT_TO_POINTER (w));
+	g_object_set_data (G_OBJECT (window), "xstuff-cached-h", GINT_TO_POINTER (h));
+}
+
+void
+xstuff_set_wmspec_dock_hints (GdkWindow *window,
+			      gboolean autohide)
+{
+        Atom atoms [2] = { None, None };
+        
+	if (!autohide)
+		atoms [0] = panel_atom_get ("_NET_WM_WINDOW_TYPE_DOCK");
+	else {
+		atoms [0] = panel_atom_get ("_GNOME_WINDOW_TYPE_AUTOHIDE_PANEL");
+		atoms [1] = panel_atom_get ("_NET_WM_WINDOW_TYPE_DOCK");
+	}
+
+        XChangeProperty (GDK_WINDOW_XDISPLAY (window),
+                         GDK_WINDOW_XWINDOW (window),
+			 panel_atom_get ("_NET_WM_WINDOW_TYPE"),
+                         XA_ATOM, 32, PropModeReplace,
+                         (unsigned char *) atoms, 
+			 autohide ? 2 : 1);
+}
+
+void
+xstuff_set_wmspec_strut (GdkWindow *window,
+			 int        left,
+			 int        right,
+			 int        top,
+			 int        bottom)
+{
+	long vals [4];
+        
+	vals [0] = left;
+	vals [1] = right;
+	vals [2] = top;
+	vals [3] = bottom;
+
+        XChangeProperty (GDK_WINDOW_XDISPLAY (window),
+                         GDK_WINDOW_XWINDOW (window),
+			 panel_atom_get ("_NET_WM_STRUT"),
+                         XA_CARDINAL, 32, PropModeReplace,
+                         (unsigned char *) vals, 4);
+}
+
+void
+xstuff_delete_property (GdkWindow *window, const char *name)
+{
+	Display *xdisplay = GDK_WINDOW_XDISPLAY (window);
+	Window   xwindow  = GDK_WINDOW_XWINDOW (window);
+
+        XDeleteProperty (xdisplay, xwindow,
+			 panel_atom_get (name));
+}
+
+/* Zoom animation */
+#define MINIATURIZE_ANIMATION_FRAMES_Z   1
+#define MINIATURIZE_ANIMATION_STEPS_Z    6
+/* the delay per draw */
+#define MINIATURIZE_ANIMATION_DELAY_Z    10
+
+static void 
+draw_zoom_animation (GdkScreen *gscreen,
+		     int x, int y, int w, int h,
+		     int fx, int fy, int fw, int fh, 
+		     int steps)
+{
+#define FRAMES (MINIATURIZE_ANIMATION_FRAMES_Z)
+	float cx[FRAMES], cy[FRAMES], cw[FRAMES], ch[FRAMES];
+	int cxi[FRAMES], cyi[FRAMES], cwi[FRAMES], chi[FRAMES];
+	float xstep, ystep, wstep, hstep;
+	int i, j;
+	GC frame_gc;
+	XGCValues gcv;
+	GdkColor color = { 65535, 65535, 65535 };
+	Display *dpy;
+	Window root_win;
+	int screen;
+	int depth;
+
+	dpy = gdk_x11_display_get_xdisplay (gdk_screen_get_display (gscreen));
+	root_win = gdk_x11_drawable_get_xid (gdk_screen_get_root_window (gscreen));
+	screen = gdk_screen_get_number (gscreen);
+	depth = gdk_drawable_get_depth (gdk_screen_get_root_window (gscreen));
+
+	/* frame GC */
+	gdk_colormap_alloc_color (
+		gdk_screen_get_system_colormap (gscreen), &color, FALSE, TRUE);
+	gcv.function = GXxor;
+	/* this will raise the probability of the XORed color being different
+	 * of the original color in PseudoColor when not all color cells are
+	 * initialized */
+	if (DefaultVisual(dpy, screen)->class==PseudoColor)
+		gcv.plane_mask = (1<<(depth-1))|1;
+	else
+		gcv.plane_mask = AllPlanes;
+	gcv.foreground = color.pixel;
+	if (gcv.foreground == 0)
+		gcv.foreground = 1;
+	gcv.line_width = 1;
+	gcv.subwindow_mode = IncludeInferiors;
+	gcv.graphics_exposures = False;
+
+	frame_gc = XCreateGC(dpy, root_win, GCForeground|GCGraphicsExposures
+			     |GCFunction|GCSubwindowMode|GCLineWidth
+			     |GCPlaneMask, &gcv);
+
+	xstep = (float)(fx-x)/steps;
+	ystep = (float)(fy-y)/steps;
+	wstep = (float)(fw-w)/steps;
+	hstep = (float)(fh-h)/steps;
+    
+	for (j=0; j<FRAMES; j++) {
+		cx[j] = (float)x;
+		cy[j] = (float)y;
+		cw[j] = (float)w;
+		ch[j] = (float)h;
+		cxi[j] = (int)cx[j];
+		cyi[j] = (int)cy[j];
+		cwi[j] = (int)cw[j];
+		chi[j] = (int)ch[j];
+	}
+	XGrabServer(dpy);
+	for (i=0; i<steps; i++) {
+		for (j=0; j<FRAMES; j++) {
+			XDrawRectangle(dpy, root_win, frame_gc, cxi[j], cyi[j], cwi[j], chi[j]);
+		}
+		XFlush(dpy);
+#if (MINIATURIZE_ANIMATION_DELAY_Z > 0)
+		usleep(MINIATURIZE_ANIMATION_DELAY_Z);
+#else
+		usleep(10);
+#endif
+		for (j=0; j<FRAMES; j++) {
+			XDrawRectangle(dpy, root_win, frame_gc, 
+				       cxi[j], cyi[j], cwi[j], chi[j]);
+			if (j<FRAMES-1) {
+				cx[j]=cx[j+1];
+				cy[j]=cy[j+1];
+				cw[j]=cw[j+1];
+				ch[j]=ch[j+1];
+				
+				cxi[j]=cxi[j+1];
+				cyi[j]=cyi[j+1];
+				cwi[j]=cwi[j+1];
+				chi[j]=chi[j+1];
+				
+			} else {
+				cx[j]+=xstep;
+				cy[j]+=ystep;
+				cw[j]+=wstep;
+				ch[j]+=hstep;
+
+				cxi[j] = (int)cx[j];
+				cyi[j] = (int)cy[j];
+				cwi[j] = (int)cw[j];
+				chi[j] = (int)ch[j];
+			}
+		}
+	}
+
+	for (j=0; j<FRAMES; j++) {
+		XDrawRectangle(dpy, root_win, frame_gc, 
+				       cxi[j], cyi[j], cwi[j], chi[j]);
+	}
+	XFlush(dpy);
+#if (MINIATURIZE_ANIMATION_DELAY_Z > 0)
+	usleep(MINIATURIZE_ANIMATION_DELAY_Z);
+#else
+	usleep(10);
+#endif
+	for (j=0; j<FRAMES; j++) {
+		XDrawRectangle(dpy, root_win, frame_gc, 
+				       cxi[j], cyi[j], cwi[j], chi[j]);
+	}
+    
+	XUngrabServer(dpy);
+	XFreeGC (dpy, frame_gc);
+	gdk_colormap_free_colors (gdk_screen_get_system_colormap (gscreen),
+				  &color, 1);
+}
+#undef FRAMES
+
+void
+xstuff_zoom_animate (GtkWidget *widget, GdkRectangle *opt_rect,
+										 GdkRectangle *opt_dest)
+{
+	GdkScreen *gscreen;
+	GdkRectangle rect, dest;
+	int monitor;
+
+	if (opt_rect)
+		rect = *opt_rect;
+	else {
+		gdk_window_get_origin (widget->window, &rect.x, &rect.y);
+		if (GTK_WIDGET_NO_WINDOW (widget)) {
+			rect.x += widget->allocation.x;
+			rect.y += widget->allocation.y;
+		}
+		rect.height = widget->allocation.height;
+		rect.width = widget->allocation.width;
+	}
+
+	gscreen = gtk_widget_get_screen (widget);
+	if (opt_dest==NULL) {
+		monitor = gdk_screen_get_monitor_at_window (gscreen, widget->window);
+		gdk_screen_get_monitor_geometry (gscreen, monitor, &dest);
+	}	else {
+		dest.x = opt_dest->x;
+		dest.y = opt_dest->y;
+		dest.width = opt_dest->width;
+		dest.height = opt_dest->height;
+	}
+
+	draw_zoom_animation (gscreen,
+			     rect.x, rect.y, rect.width, rect.height,
+			     dest.x, dest.y, dest.width, dest.height,
+			     MINIATURIZE_ANIMATION_STEPS_Z);
+}
+
+int
+xstuff_get_current_workspace (GdkScreen *screen)
+{
+	Window  root_window;
+	Atom    type = None;
+	gulong  nitems;
+	gulong  bytes_after;
+	gulong *num;
+	int     format;
+	int     result;
+	int     retval;
+
+	root_window = gdk_x11_drawable_get_xid (
+				gdk_screen_get_root_window (screen));
+
+	gdk_error_trap_push ();
+	result = XGetWindowProperty (gdk_display,
+				     root_window,
+				     panel_atom_get ("_NET_CURRENT_DESKTOP"),
+				     0, G_MAXLONG,
+				     False, XA_CARDINAL, &type, &format, &nitems,
+				     &bytes_after, (gpointer) &num);
+	if (gdk_error_trap_pop () || result != Success)
+		return -1;
+ 
+	if (type != XA_CARDINAL) {
+		XFree (num);
+		return -1;
+	}
+
+	retval = *num;
+ 
+	XFree (num);
+
+	return retval;
+}
+
+void
+xstuff_grab_key_on_all_screens (int      keycode,
+				guint    modifiers,
+				gboolean grab)
+{
+	GdkDisplay *display;
+	int         n_screens;
+	int         i;
+
+	display   = gdk_display_get_default ();
+	n_screens = gdk_display_get_n_screens (display);
+
+	for (i = 0; i < n_screens; i++) {
+		GdkWindow *root;
+
+		root = gdk_screen_get_root_window (
+				gdk_display_get_screen (display, i));
+
+		if (grab)
+			XGrabKey (gdk_x11_display_get_xdisplay (display),
+				  keycode, modifiers,
+				  gdk_x11_drawable_get_xid (root),
+				  True, GrabModeAsync, GrabModeAsync);
+		else
+			XUngrabKey (gdk_x11_display_get_xdisplay (display),
+				    keycode, modifiers,
+				    gdk_x11_drawable_get_xid (root));
+	}
+}
+
+void 
+xstuff_queue_zoom (GdkRectangle *start)
+{
+	GdkRectangle *new;
+
+	new = g_new0 (GdkRectangle, 1);
+	new->x = start->x;
+	new->y = start->y;
+	new->width = start->width;
+	new->height = start->height;
+
+	pending_zooms = g_list_append (pending_zooms, new);
+}
+
+void
+xstuff_queued_zoom_animate (GtkWidget *widget, 
+														GdkRectangle *dest)
+{
+	GdkRectangle *orig;
+
+	if (!pending_zooms)
+		return;
+
+	orig = g_list_last (pending_zooms)->data;
+	pending_zooms = g_list_remove (pending_zooms, orig);
+
+	xstuff_zoom_animate (widget, orig, dest);
+	g_free (orig);
+}
--- /dev/null	Fri Mar 23 23:37:44 2001
+++ src/file-manager/xstuff.h	Thu Jun  2 17:09:24 2005
@@ -0,0 +1,38 @@
+#ifndef __XSTUFF_H__
+#define __XSTUFF_H__
+
+#include <gdk/gdk.h>
+#include <gtk/gtkwidget.h>
+
+void xstuff_delete_property		(GdkWindow *window,
+					 const char *name);
+gboolean xstuff_is_compliant_wm		(void);
+gboolean xstuff_net_wm_supports         (const char *hint);
+
+void xstuff_unsetup_desktop_area	(void);
+void xstuff_set_pos_size		(GdkWindow *window,
+					 int x, int y,
+					 int w, int h);
+void xstuff_set_wmspec_dock_hints       (GdkWindow *window,
+					 gboolean autohide);
+void xstuff_set_wmspec_strut		(GdkWindow *window,
+					 int left,
+					 int right,
+					 int top,
+					 int bottom);
+
+void xstuff_zoom_animate                (GtkWidget    *widget,
+					 GdkRectangle *opt_src_rect, GdkRectangle *opt_dest);
+
+int  xstuff_get_current_workspace       (GdkScreen *screen);
+
+void xstuff_grab_key_on_all_screens     (int      keycode,
+					 guint    modifiers,
+					 gboolean grab);
+void xstuff_queued_zoom_animate (GtkWidget *widget, 
+																 GdkRectangle *dest);
+void 
+xstuff_queue_zoom (GdkRectangle *start);
+
+
+#endif /* __XSTUFF_H__ */


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]