nautilus-gtk-extensions.c 7.66 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */

/* nautilus-gtk-extensions.c - implementation of new functions that operate on
  			       gtk classes. Perhaps some of these should be
  			       rolled into gtk someday.

   Copyright (C) 1999, 2000 Eazel, Inc.

   The Gnome Library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Library General Public License as
   published by the Free Software Foundation; either version 2 of the
   License, or (at your option) any later version.

   The Gnome Library is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Library General Public License for more details.

   You should have received a copy of the GNU Library General Public
   License along with the Gnome Library; see the file COPYING.LIB.  If not,
   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
   Boston, MA 02111-1307, USA.

   Authors: John Sullivan <sullivan@eazel.com>
*/

#include "nautilus-gtk-extensions.h"
#include <gnome.h>


31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
/**
 * nautilus_gtk_signal_connect_free_data:
 * 
 * Attach a function pointer and user data to a signal, and free
 * the user data when the signal is disconnected.
 * @object: the object which emits the signal. For example, a button in the button press signal.
 * @name: the name of the signal.
 * @func: function pointer to attach to the signal.
 * @data: the user data associated with the function. g_free() will be called on
 * this user data when the signal is disconnected.
 **/
guint nautilus_gtk_signal_connect_free_data (GtkObject *object,
				  	     const gchar *name,
				  	     GtkSignalFunc func,
				  	     gpointer data)
{
	return gtk_signal_connect_full (object, 
					name, 
					func, 
					NULL, /* marshal */
					data, 
					(GtkDestroyNotify)g_free, 
					FALSE, /* is this an object signal? */
					FALSE); /* invoke func after signal? */
}

57 58 59 60 61 62 63 64 65 66
/**
 * nautilus_gtk_window_hide_retain_geometry:
 * 
 * Hide a GtkWindow such that when reopened it will be in the same
 * place it is now.
 * @window: The GtkWindow to be hidden.
 **/
static void
nautilus_gtk_window_hide_retain_geometry (GtkWindow *window) {
	gchar *geometry_string;
67
	int left, top, width, height;
68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104

	g_return_if_fail (GTK_IS_WINDOW (window));

	/* Save and restore position to keep it in same position when next shown. */

	geometry_string = gnome_geometry_string(GTK_WIDGET (window)->window);
    
	gtk_widget_hide (GTK_WIDGET (window));

	if (gnome_parse_geometry (geometry_string, &left, &top, &width, &height)) 
	{
		gtk_window_set_default_size (window, width, height);
		gtk_widget_set_uposition (GTK_WIDGET (window), left, top);
	}

	g_free (geometry_string);
}

/**
 * nautilus_gtk_window_present:
 * 
 * Presents to the user a window that may be hidden, iconified, or buried.
 * @window: The GtkWindow to be presented to the user.
 **/
void
nautilus_gtk_window_present (GtkWindow *window) {
	g_assert (GTK_IS_WINDOW (window));

	/* Hide first if already showing, so it will reappear on top.
	 * This works with iconified windows as well.
	 */
	if (GTK_WIDGET_VISIBLE (GTK_WIDGET (window))) 
	{
		nautilus_gtk_window_hide_retain_geometry (window);
	}
    
	gtk_widget_show (GTK_WIDGET (window));
105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135
}

/**
 * nautilus_gtk_selection_data_copy_deep:
 * 
 * Copies a GtkSelectionData, and copies the data too.
 * @data: The GtkSelectionData to be copied.
 **/
GtkSelectionData *
nautilus_gtk_selection_data_copy_deep (const GtkSelectionData *data)
{
	GtkSelectionData *copy;

	copy = g_new0 (GtkSelectionData, 1);
	gtk_selection_data_set (copy, data->type, data->format, data->data, data->length);

	return copy;
}

/**
 * nautilus_gtk_selection_data_free_deep:
 * 
 * Frees a GtkSelectionData, and frees the data too.
 * @data: The GtkSelectionData to be freed.
 **/
void
nautilus_gtk_selection_data_free_deep (GtkSelectionData *data)
{
	g_free (data->data);
	gtk_selection_data_free (data);
}
136

137 138 139 140 141 142 143 144 145 146 147 148 149 150
/**
 * nautilus_gtk_signal_connect_free_data:
 * 
 * Function to displace the popup menu some, otherwise the first item
 * gets selected right away.
 * This function gets called by gtk_menu_popup ().
 *
 * @menu: the popup menu.
 * @x: x coord where gtk want to place the menu
 * @y: y coord where gtk want to place the menu
 * @user_data: something
 **/
static void
nautilus_popup_menu_position_func (GtkMenu   *menu,
151 152
				   int      *x,
				   int      *y,
153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168
				   gpointer  user_data)
{
	GdkPoint *offset;

	g_assert (x != NULL);
	g_assert (y != NULL);

	offset = (GdkPoint*) user_data;

	g_assert (offset != NULL);

	/*
	 * XXX: Check for screen boundaries.  Also, the cast from 
	 * gint16 might cause problems.  Unfortunately, GdkPoint
	 * uses gint16.
	 */
169 170
	*x += (int) offset->x;
	*y += (int) offset->y;
171 172
}

173 174 175 176 177 178 179 180 181 182 183 184 185
/**
 * nautilus_pop_up_context_menu:
 * 
 * Pop up a context menu under the mouse. This assumes that
 * a mouse down event just occurred, with the 3rd button pressed.
 * (Context menus only appear with the 3rd mouse button, by UI
 * convention.) The menu is sunk after use, so it will be destroyed
 * unless the caller first ref'ed it.
 * 
 * This function is more of a helper function than a gtk extension,
 * so perhaps it belongs in a different file.
 * 
 * @menu: The menu to pop up under the mouse.
186 187
 * @offset_x: Number of pixels to displace the popup menu vertically
 * @offset_y: Number of pixels to displace the popup menu horizontally
188 189
 **/
void 
190 191 192
nautilus_pop_up_context_menu (GtkMenu	*menu,
			      gint16	offset_x,
			      gint16	offset_y)
193
{
194 195
	GdkPoint offset;

196 197
	g_return_if_fail (GTK_IS_MENU (menu));

198 199 200
	offset.x = offset_x;
	offset.y = offset_y;

201 202 203 204
	/* We pass current time here instead of extracting it from
	 * the event, for API simplicity. This does not seem to make
	 * any practical difference. See man XGrabPointer for details.
	 */
205 206 207 208 209 210 211
	gtk_menu_popup (menu,					/* menu */
			NULL,					/* parent_menu_shell */
			NULL,					/* parent_menu_item */
			nautilus_popup_menu_position_func,	/* func */
			(gpointer) &offset,			/* data */
			3,					/* button */
			GDK_CURRENT_TIME);			/* activate_time */
212 213 214

	gtk_object_sink (GTK_OBJECT(menu));
}
215 216


217 218 219 220 221 222 223
typedef void (*NautilusGtkSignal_NONE__POINTER_INT_INT_DOUBLE) (GtkObject * object,
								gpointer arg1,
								int arg2,
								int arg3,
								double arg4,
								gpointer user_data);

224 225
typedef void (*NautilusGtkSignal_NONE__POINTER_INT_INT_DOUBLE_DOUBLE) (GtkObject * object,
								       gpointer arg1,
226 227 228 229
								       int arg2,
								       int arg3,
								       double arg4,
								       double arg5,
230 231
								       gpointer user_data);

232 233 234 235 236

typedef void (*NautilusGtkSignal_NONE__DOUBLE) (GtkObject * object,
						double arg1,
						gpointer user_data);

237 238 239 240 241 242 243 244 245 246 247 248 249 250 251
void
nautilus_gtk_marshal_NONE__POINTER_INT_INT_DOUBLE (GtkObject * object,
						   GtkSignalFunc func,
						   gpointer func_data,
						   GtkArg * args)
{
	(* (NautilusGtkSignal_NONE__POINTER_INT_INT_DOUBLE) func)
		(object,
		 GTK_VALUE_POINTER (args[0]),
		 GTK_VALUE_INT (args[1]),
		 GTK_VALUE_INT (args[2]),
		 GTK_VALUE_DOUBLE (args[3]),
		 func_data);
}

252 253 254 255 256 257
void
nautilus_gtk_marshal_NONE__POINTER_INT_INT_DOUBLE_DOUBLE (GtkObject * object,
							  GtkSignalFunc func,
							  gpointer func_data,
							  GtkArg * args)
{
258 259 260 261 262 263 264 265
	(* (NautilusGtkSignal_NONE__POINTER_INT_INT_DOUBLE_DOUBLE) func)
		(object,
		 GTK_VALUE_POINTER (args[0]),
		 GTK_VALUE_INT (args[1]), 
		 GTK_VALUE_INT (args[2]), 
		 GTK_VALUE_DOUBLE (args[3]), 
		 GTK_VALUE_DOUBLE (args[4]), 
		 func_data);
266
}
267 268 269 270 271 272 273 274 275 276 277 278 279 280



void
nautilus_gtk_marshal_NONE__DOUBLE (GtkObject    *object,
				   GtkSignalFunc func,
				   gpointer      func_data,
				   GtkArg        *args)
{
	(* (NautilusGtkSignal_NONE__DOUBLE) func)
		(object,
		 GTK_VALUE_DOUBLE (args[0]),
		 func_data);
}