nautilus-3.6.3/src/nautilus-window.c

No issues found

   1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
   2 
   3 /*
   4  *  Nautilus
   5  *
   6  *  Copyright (C) 1999, 2000, 2004 Red Hat, Inc.
   7  *  Copyright (C) 1999, 2000, 2001 Eazel, Inc.
   8  *
   9  *  Nautilus is free software; you can redistribute it and/or
  10  *  modify it under the terms of the GNU General Public
  11  *  License as published by the Free Software Foundation; either
  12  *  version 2 of the License, or (at your option) any later version.
  13  *
  14  *  Nautilus is distributed in the hope that it will be useful,
  15  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  16  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  17  *  General Public License for more details.
  18  *
  19  *  You should have received a copy of the GNU General Public
  20  *  License along with this program; if not, write to the Free
  21  *  Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  22  *
  23  *  Authors: Elliot Lee <sopwith@redhat.com>
  24  *  	     John Sullivan <sullivan@eazel.com>
  25  *           Alexander Larsson <alexl@redhat.com>
  26  */
  27 
  28 /* nautilus-window.c: Implementation of the main window object */
  29 
  30 #include <config.h>
  31 
  32 #include "nautilus-window-private.h"
  33 
  34 #include "nautilus-actions.h"
  35 #include "nautilus-application.h"
  36 #include "nautilus-bookmarks-window.h"
  37 #include "nautilus-desktop-window.h"
  38 #include "nautilus-location-entry.h"
  39 #include "nautilus-mime-actions.h"
  40 #include "nautilus-notebook.h"
  41 #include "nautilus-places-sidebar.h"
  42 #include "nautilus-pathbar.h"
  43 #include "nautilus-toolbar.h"
  44 #include "nautilus-view-factory.h"
  45 #include "nautilus-window-manage-views.h"
  46 #include "nautilus-window-slot.h"
  47 #include "nautilus-list-view.h"
  48 #include "nautilus-canvas-view.h"
  49 
  50 #include <eel/eel-debug.h>
  51 #include <eel/eel-gtk-extensions.h>
  52 #include <gdk-pixbuf/gdk-pixbuf.h>
  53 #include <gdk/gdkx.h>
  54 #include <gdk/gdkkeysyms.h>
  55 #include <gtk/gtk.h>
  56 #include <glib/gi18n.h>
  57 #ifdef HAVE_X11_XF86KEYSYM_H
  58 #include <X11/XF86keysym.h>
  59 #endif
  60 #include <libnautilus-private/nautilus-file-utilities.h>
  61 #include <libnautilus-private/nautilus-file-attributes.h>
  62 #include <libnautilus-private/nautilus-global-preferences.h>
  63 #include <libnautilus-private/nautilus-metadata.h>
  64 #include <libnautilus-private/nautilus-profile.h>
  65 #include <libnautilus-private/nautilus-clipboard.h>
  66 #include <libnautilus-private/nautilus-search-directory.h>
  67 #include <libnautilus-private/nautilus-signaller.h>
  68 
  69 #define DEBUG_FLAG NAUTILUS_DEBUG_WINDOW
  70 #include <libnautilus-private/nautilus-debug.h>
  71 
  72 #include <math.h>
  73 #include <sys/time.h>
  74 
  75 /* dock items */
  76 #define MAX_TITLE_LENGTH 180
  77 
  78 /* Forward and back buttons on the mouse */
  79 static gboolean mouse_extra_buttons = TRUE;
  80 static int mouse_forward_button = 9;
  81 static int mouse_back_button = 8;
  82 
  83 static void mouse_back_button_changed		     (gpointer                  callback_data);
  84 static void mouse_forward_button_changed	     (gpointer                  callback_data);
  85 static void use_extra_mouse_buttons_changed          (gpointer                  callback_data);
  86 
  87 /* Sanity check: highest mouse button value I could find was 14. 5 is our 
  88  * lower threshold (well-documented to be the one of the button events for the 
  89  * scrollwheel), so it's hardcoded in the functions below. However, if you have
  90  * a button that registers higher and want to map it, file a bug and 
  91  * we'll move the bar. Makes you wonder why the X guys don't have 
  92  * defined values for these like the XKB stuff, huh?
  93  */
  94 #define UPPER_MOUSE_LIMIT 14
  95 
  96 enum {
  97 	PROP_DISABLE_CHROME = 1,
  98 	NUM_PROPERTIES,
  99 };
 100 
 101 enum {
 102 	LOADING_URI,
 103 	SLOT_ADDED,
 104 	SLOT_REMOVED,
 105 	LAST_SIGNAL
 106 };
 107 
 108 static guint signals[LAST_SIGNAL] = { 0 };
 109 static GParamSpec *properties[NUM_PROPERTIES] = { NULL, };
 110 
 111 G_DEFINE_TYPE (NautilusWindow, nautilus_window, GTK_TYPE_APPLICATION_WINDOW);
 112 
 113 static const struct {
 114 	unsigned int keyval;
 115 	const char *action;
 116 } extra_window_keybindings [] = {
 117 #ifdef HAVE_X11_XF86KEYSYM_H
 118 	{ XF86XK_AddFavorite,	NAUTILUS_ACTION_ADD_BOOKMARK },
 119 	{ XF86XK_Favorites,	NAUTILUS_ACTION_EDIT_BOOKMARKS },
 120 	{ XF86XK_Go,		NAUTILUS_ACTION_ENTER_LOCATION },
 121 	{ XF86XK_HomePage,      NAUTILUS_ACTION_GO_HOME },
 122 	{ XF86XK_OpenURL,	NAUTILUS_ACTION_ENTER_LOCATION },
 123 	{ XF86XK_Refresh,	NAUTILUS_ACTION_RELOAD },
 124 	{ XF86XK_Reload,	NAUTILUS_ACTION_RELOAD },
 125 	{ XF86XK_Search,	NAUTILUS_ACTION_SEARCH },
 126 	{ XF86XK_Start,		NAUTILUS_ACTION_GO_HOME },
 127 	{ XF86XK_Stop,		NAUTILUS_ACTION_STOP },
 128 	{ XF86XK_ZoomIn,	NAUTILUS_ACTION_ZOOM_IN },
 129 	{ XF86XK_ZoomOut,	NAUTILUS_ACTION_ZOOM_OUT },
 130 	{ XF86XK_Back,		NAUTILUS_ACTION_BACK },
 131 	{ XF86XK_Forward,	NAUTILUS_ACTION_FORWARD }
 132 
 133 #endif
 134 };
 135 
 136 void
 137 nautilus_window_go_to (NautilusWindow *window, GFile *location)
 138 {
 139 	g_return_if_fail (NAUTILUS_IS_WINDOW (window));
 140 
 141 	nautilus_window_slot_open_location (nautilus_window_get_active_slot (window),
 142 					    location, 0);
 143 }
 144 
 145 void
 146 nautilus_window_go_to_full (NautilusWindow *window,
 147 			    GFile          *location,
 148 			    NautilusWindowGoToCallback callback,
 149 			    gpointer        user_data)
 150 {
 151 	g_return_if_fail (NAUTILUS_IS_WINDOW (window));
 152 
 153 	nautilus_window_slot_open_location_full (nautilus_window_get_active_slot (window),
 154 						 location, 0, NULL, callback, user_data);
 155 }
 156 
 157 static int
 158 bookmark_list_get_uri_index (GList *list, GFile *location)
 159 {
 160 	NautilusBookmark *bookmark;
 161 	GList *l;
 162 	GFile *tmp;
 163 	int i;
 164 
 165 	g_return_val_if_fail (location != NULL, -1);
 166 
 167 	for (i = 0, l = list; l != NULL; i++, l = l->next) {
 168 		bookmark = NAUTILUS_BOOKMARK (l->data);
 169 
 170 		tmp = nautilus_bookmark_get_location (bookmark);
 171 		if (g_file_equal (location, tmp)) {
 172 			g_object_unref (tmp);
 173 			return i;
 174 		}
 175 		g_object_unref (tmp);
 176 	}
 177 
 178 	return -1;
 179 }
 180 
 181 static void
 182 unset_focus_widget (NautilusWindow *window)
 183 {
 184 	if (window->details->last_focus_widget != NULL) {
 185 		g_object_remove_weak_pointer (G_OBJECT (window->details->last_focus_widget),
 186 					      (gpointer *) &window->details->last_focus_widget);
 187 		window->details->last_focus_widget = NULL;
 188 	}
 189 }
 190 
 191 static void
 192 remember_focus_widget (NautilusWindow *window)
 193 {
 194 	GtkWidget *focus_widget;
 195 
 196 	focus_widget = gtk_window_get_focus (GTK_WINDOW (window));
 197 	if (focus_widget != NULL) {
 198 		unset_focus_widget (window);
 199 
 200 		window->details->last_focus_widget = focus_widget;
 201 		g_object_add_weak_pointer (G_OBJECT (focus_widget),
 202 					   (gpointer *) &(window->details->last_focus_widget));
 203 	}
 204 }
 205 
 206 void
 207 nautilus_window_grab_focus (NautilusWindow *window)
 208 {
 209 	if (NAUTILUS_IS_WINDOW (window) &&
 210 	    window->details->active_slot &&
 211 	    window->details->active_slot->content_view) {
 212 		nautilus_view_grab_focus (window->details->active_slot->content_view);
 213 	}
 214 }
 215 
 216 static void
 217 restore_focus_widget (NautilusWindow *window)
 218 {
 219 	if (window->details->last_focus_widget != NULL) {
 220 		if (NAUTILUS_IS_VIEW (window->details->last_focus_widget)) {
 221 			nautilus_view_grab_focus (NAUTILUS_VIEW (window->details->last_focus_widget));
 222 		} else {
 223 			gtk_widget_grab_focus (window->details->last_focus_widget);
 224 		}
 225 
 226 		unset_focus_widget (window);
 227 	}
 228 }
 229 
 230 static void
 231 location_entry_cancel_callback (GtkWidget      *widget,
 232 				NautilusWindow *window)
 233 {
 234 	nautilus_toolbar_set_show_location_entry (NAUTILUS_TOOLBAR (window->details->toolbar), FALSE);
 235 
 236 	restore_focus_widget (window);
 237 }
 238 
 239 static void
 240 location_entry_location_changed_callback (GtkWidget      *widget,
 241 					  GFile          *location,
 242 					  NautilusWindow *window)
 243 {
 244 	nautilus_toolbar_set_show_location_entry (NAUTILUS_TOOLBAR (window->details->toolbar), FALSE);
 245 
 246 	restore_focus_widget (window);
 247 
 248 	nautilus_window_slot_open_location (window->details->active_slot, location, 0);
 249 }
 250 
 251 static gboolean
 252 notebook_switch_page_cb (GtkNotebook    *notebook,
 253 			 GtkWidget      *page,
 254 			 unsigned int    page_num,
 255 			 NautilusWindow *window)
 256 {
 257 	NautilusWindowSlot *slot;
 258 	GtkWidget *widget;
 259 
 260 	widget = gtk_notebook_get_nth_page (GTK_NOTEBOOK (window->details->notebook), page_num);
 261 	g_assert (widget != NULL);
 262 
 263 	/* find slot corresponding to the target page */
 264 	slot = NAUTILUS_WINDOW_SLOT (widget);
 265 	g_assert (slot != NULL);
 266 
 267 	nautilus_window_set_active_slot (nautilus_window_slot_get_window (slot),
 268 					 slot);
 269 
 270 	return FALSE;
 271 }
 272 
 273 static void
 274 close_slot (NautilusWindow     *window,
 275 	    NautilusWindowSlot *slot,
 276 	    gboolean            remove_from_notebook)
 277 {
 278 	int page_num;
 279 	GtkNotebook *notebook;
 280 
 281 	g_assert (NAUTILUS_IS_WINDOW_SLOT (slot));
 282 
 283 	DEBUG ("Closing slot %p", slot);
 284 
 285 	nautilus_window_manage_views_close_slot (slot);
 286 	window->details->slots = g_list_remove (window->details->slots, slot);
 287 
 288 	g_signal_emit (window, signals[SLOT_REMOVED], 0, slot);
 289 
 290 	notebook = GTK_NOTEBOOK (window->details->notebook);
 291 
 292 	if (remove_from_notebook) {
 293 		page_num = gtk_notebook_page_num (notebook, GTK_WIDGET (slot));
 294 		g_assert (page_num >= 0);
 295 
 296 		/* this will call gtk_widget_destroy on the slot */
 297 		gtk_notebook_remove_page (notebook, page_num);
 298 	}
 299 }
 300 
 301 NautilusWindowSlot *
 302 nautilus_window_open_slot (NautilusWindow             *window,
 303 			   NautilusWindowOpenSlotFlags flags)
 304 {
 305 	NautilusWindowSlot *slot;
 306 
 307 	g_assert (NAUTILUS_IS_WINDOW (window));
 308 
 309 	slot = nautilus_window_slot_new (window);
 310 
 311 	g_signal_handlers_block_by_func (window->details->notebook,
 312 					 G_CALLBACK (notebook_switch_page_cb),
 313 					 window);
 314 	nautilus_notebook_add_tab (NAUTILUS_NOTEBOOK (window->details->notebook),
 315 				   slot,
 316 				   (flags & NAUTILUS_WINDOW_OPEN_SLOT_APPEND) != 0 ?
 317 				   -1 :
 318 				   gtk_notebook_get_current_page (GTK_NOTEBOOK (window->details->notebook)) + 1,
 319 				   FALSE);
 320 	g_signal_handlers_unblock_by_func (window->details->notebook,
 321 					   G_CALLBACK (notebook_switch_page_cb),
 322 					   window);
 323 
 324 	window->details->slots = g_list_append (window->details->slots, slot);
 325 	g_signal_emit (window, signals[SLOT_ADDED], 0, slot);
 326 
 327 	return slot;
 328 }
 329 
 330 void
 331 nautilus_window_new_tab (NautilusWindow *window)
 332 {
 333 	NautilusWindowSlot *current_slot;
 334 	NautilusWindowSlot *new_slot;
 335 	NautilusWindowOpenFlags flags;
 336 	GFile *location;
 337 	int new_slot_position;
 338 	char *scheme;
 339 
 340 	current_slot = nautilus_window_get_active_slot (window);
 341 	location = nautilus_window_slot_get_location (current_slot);
 342 
 343 	if (location != NULL) {
 344 		flags = 0;
 345 
 346 		new_slot_position = g_settings_get_enum (nautilus_preferences, NAUTILUS_PREFERENCES_NEW_TAB_POSITION);
 347 		if (new_slot_position == NAUTILUS_NEW_TAB_POSITION_END) {
 348 			flags = NAUTILUS_WINDOW_OPEN_SLOT_APPEND;
 349 		}
 350 
 351 		scheme = g_file_get_uri_scheme (location);
 352 		if (!strcmp (scheme, "x-nautilus-search")) {
 353 			g_object_unref (location);
 354 			location = g_file_new_for_path (g_get_home_dir ());
 355 		}
 356 		g_free (scheme);
 357 
 358 		new_slot = nautilus_window_open_slot (window, flags);
 359 		nautilus_window_set_active_slot (window, new_slot);
 360 		nautilus_window_slot_open_location (new_slot, location, 0);
 361 		g_object_unref (location);
 362 	}
 363 }
 364 
 365 static void
 366 update_cursor (NautilusWindow *window)
 367 {
 368 	NautilusWindowSlot *slot;
 369 	GdkCursor *cursor;
 370 
 371 	slot = nautilus_window_get_active_slot (window);
 372 
 373 	if (slot->allow_stop) {
 374 		cursor = gdk_cursor_new (GDK_WATCH);
 375 		gdk_window_set_cursor (gtk_widget_get_window (GTK_WIDGET (window)), cursor);
 376 		g_object_unref (cursor);
 377 	} else {
 378 		gdk_window_set_cursor (gtk_widget_get_window (GTK_WIDGET (window)), NULL);
 379 	}
 380 }
 381 
 382 void
 383 nautilus_window_sync_allow_stop (NautilusWindow *window,
 384 				 NautilusWindowSlot *slot)
 385 {
 386 	GtkAction *stop_action;
 387 	GtkAction *reload_action;
 388 	gboolean allow_stop, slot_is_active;
 389 
 390 	stop_action = gtk_action_group_get_action (nautilus_window_get_main_action_group (window),
 391 						   NAUTILUS_ACTION_STOP);
 392 	reload_action = gtk_action_group_get_action (nautilus_window_get_main_action_group (window),
 393 						     NAUTILUS_ACTION_RELOAD);
 394 	allow_stop = gtk_action_get_sensitive (stop_action);
 395 
 396 	slot_is_active = (slot == nautilus_window_get_active_slot (window));
 397 
 398 	if (!slot_is_active ||
 399 	    allow_stop != slot->allow_stop) {
 400 		if (slot_is_active) {
 401 			gtk_action_set_visible (stop_action, slot->allow_stop);
 402 			gtk_action_set_visible (reload_action, !slot->allow_stop);
 403 		}
 404 
 405 		if (gtk_widget_get_realized (GTK_WIDGET (window))) {
 406 			update_cursor (window);
 407 		}
 408 
 409 		nautilus_notebook_sync_loading (NAUTILUS_NOTEBOOK (window->details->notebook), slot);
 410 	}
 411 }
 412 
 413 void
 414 nautilus_window_prompt_for_location (NautilusWindow *window,
 415 				     const char     *initial)
 416 {
 417 	GtkWidget *entry;
 418 
 419 	g_return_if_fail (NAUTILUS_IS_WINDOW (window));
 420 
 421 	entry = nautilus_window_ensure_location_entry (window);
 422 
 423 	if (initial) {
 424 		nautilus_location_entry_set_uri (NAUTILUS_LOCATION_ENTRY (entry),
 425 						 initial);
 426 	}
 427 }
 428 
 429 /* Code should never force the window taller than this size.
 430  * (The user can still stretch the window taller if desired).
 431  */
 432 static guint
 433 get_max_forced_height (GdkScreen *screen)
 434 {
 435 	return (gdk_screen_get_height (screen) * 90) / 100;
 436 }
 437 
 438 /* Code should never force the window wider than this size.
 439  * (The user can still stretch the window wider if desired).
 440  */
 441 static guint
 442 get_max_forced_width (GdkScreen *screen)
 443 {
 444 	return (gdk_screen_get_width (screen) * 90) / 100;
 445 }
 446 
 447 /* This must be called when construction of NautilusWindow is finished,
 448  * since it depends on the type of the argument, which isn't decided at
 449  * construction time.
 450  */
 451 static void
 452 nautilus_window_set_initial_window_geometry (NautilusWindow *window)
 453 {
 454 	GdkScreen *screen;
 455 	guint max_width_for_screen, max_height_for_screen;
 456 	guint default_width, default_height;
 457 
 458 	screen = gtk_window_get_screen (GTK_WINDOW (window));
 459 	
 460 	max_width_for_screen = get_max_forced_width (screen);
 461 	max_height_for_screen = get_max_forced_height (screen);
 462 	
 463 	default_width = NAUTILUS_WINDOW_DEFAULT_WIDTH;
 464 	default_height = NAUTILUS_WINDOW_DEFAULT_HEIGHT;
 465 
 466 	gtk_window_set_default_size (GTK_WINDOW (window), 
 467 				     MIN (default_width, 
 468 				          max_width_for_screen), 
 469 				     MIN (default_height, 
 470 				          max_height_for_screen));
 471 }
 472 
 473 static gboolean
 474 save_sidebar_width_cb (gpointer user_data)
 475 {
 476 	NautilusWindow *window = user_data;
 477 
 478 	window->details->sidebar_width_handler_id = 0;
 479 
 480 	DEBUG ("Saving sidebar width: %d", window->details->side_pane_width);
 481 
 482 	g_settings_set_int (nautilus_window_state,
 483 			    NAUTILUS_WINDOW_STATE_SIDEBAR_WIDTH,
 484 			    window->details->side_pane_width);
 485 
 486 	return FALSE;
 487 }
 488 
 489 /* side pane helpers */
 490 static void
 491 side_pane_size_allocate_callback (GtkWidget *widget,
 492 				  GtkAllocation *allocation,
 493 				  gpointer user_data)
 494 {
 495 	NautilusWindow *window;
 496 
 497 	window = user_data;
 498 
 499 	if (window->details->sidebar_width_handler_id != 0) {
 500 		g_source_remove (window->details->sidebar_width_handler_id);
 501 		window->details->sidebar_width_handler_id = 0;
 502 	}
 503 
 504 	if (allocation->width != window->details->side_pane_width &&
 505 	    allocation->width > 1) {
 506 		window->details->side_pane_width = allocation->width;
 507 
 508 		window->details->sidebar_width_handler_id =
 509 			g_idle_add (save_sidebar_width_cb, window);
 510 	}
 511 }
 512 
 513 static void
 514 setup_side_pane_width (NautilusWindow *window)
 515 {
 516 	g_return_if_fail (window->details->sidebar != NULL);
 517 
 518 	window->details->side_pane_width =
 519 		g_settings_get_int (nautilus_window_state,
 520 				    NAUTILUS_WINDOW_STATE_SIDEBAR_WIDTH);
 521 
 522 	gtk_paned_set_position (GTK_PANED (window->details->content_paned),
 523 				window->details->side_pane_width);
 524 }
 525 
 526 static void
 527 nautilus_window_set_up_sidebar (NautilusWindow *window)
 528 {
 529 	GtkWidget *sidebar;
 530 
 531 	window->details->sidebar = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
 532 	gtk_style_context_add_class (gtk_widget_get_style_context (window->details->sidebar),
 533 				     GTK_STYLE_CLASS_SIDEBAR);
 534 
 535 	gtk_paned_pack1 (GTK_PANED (window->details->content_paned),
 536 			 GTK_WIDGET (window->details->sidebar),
 537 			 FALSE, FALSE);
 538 
 539 	setup_side_pane_width (window);
 540 	g_signal_connect (window->details->sidebar, 
 541 			  "size_allocate",
 542 			  G_CALLBACK (side_pane_size_allocate_callback),
 543 			  window);
 544 
 545 	sidebar = nautilus_places_sidebar_new (window);
 546 	gtk_box_pack_start (GTK_BOX (window->details->sidebar), sidebar, TRUE, TRUE, 0);
 547 	gtk_widget_show (sidebar);
 548 	gtk_widget_show (GTK_WIDGET (window->details->sidebar));
 549 }
 550 
 551 static void
 552 nautilus_window_tear_down_sidebar (NautilusWindow *window)
 553 {
 554 	DEBUG ("Destroying sidebar");
 555 
 556 	if (window->details->sidebar != NULL) {
 557 		gtk_widget_destroy (GTK_WIDGET (window->details->sidebar));
 558 		window->details->sidebar = NULL;
 559 	}
 560 }
 561 
 562 void
 563 nautilus_window_hide_sidebar (NautilusWindow *window)
 564 {
 565 	DEBUG ("Called hide_sidebar()");
 566 
 567 	if (window->details->sidebar == NULL) {
 568 		return;
 569 	}
 570 
 571 	nautilus_window_tear_down_sidebar (window);
 572 }
 573 
 574 void
 575 nautilus_window_show_sidebar (NautilusWindow *window)
 576 {
 577 	DEBUG ("Called show_sidebar()");
 578 
 579 	if (window->details->sidebar != NULL) {
 580 		return;
 581 	}
 582 
 583 	if (window->details->disable_chrome) {
 584 		return;
 585 	}
 586 
 587 	nautilus_window_set_up_sidebar (window);
 588 }
 589 
 590 gboolean
 591 nautilus_window_disable_chrome_mapping (GValue *value,
 592 					GVariant *variant,
 593 					gpointer user_data)
 594 {
 595 	NautilusWindow *window = user_data;
 596 
 597 	g_value_set_boolean (value,
 598 			     g_variant_get_boolean (variant) &&
 599 			     !window->details->disable_chrome);
 600 
 601 	return TRUE;
 602 }
 603 
 604 static inline NautilusWindowSlot *
 605 get_first_inactive_slot (NautilusWindow *window)
 606 {
 607 	GList *l;
 608 	NautilusWindowSlot *slot;
 609 
 610 	for (l = window->details->slots; l != NULL; l = l->next) {
 611 		slot = NAUTILUS_WINDOW_SLOT (l->data);
 612 		if (slot != window->details->active_slot) {
 613 			return slot;
 614 		}
 615 	}
 616 
 617 	return NULL;
 618 }
 619 
 620 void
 621 nautilus_window_slot_close (NautilusWindow     *window,
 622 			    NautilusWindowSlot *slot)
 623 {
 624 	NautilusWindowSlot *next_slot;
 625 
 626 	DEBUG ("Requesting to remove slot %p from window %p", slot, window);
 627 	if (window == NULL)
 628 		return;
 629 
 630 	if (window->details->active_slot == slot) {
 631 		next_slot = get_first_inactive_slot (window);
 632 		nautilus_window_set_active_slot (window, next_slot);
 633 	}
 634 
 635 	close_slot (window, slot, TRUE);
 636 
 637 	/* If that was the last slot in the window, close the window. */
 638 	if (window->details->slots == NULL) {
 639 		DEBUG ("Last slot removed, closing the window");
 640 		nautilus_window_close (window);
 641 	}
 642 }
 643 
 644 void
 645 nautilus_window_sync_search_widgets (NautilusWindow *window)
 646 {
 647 	NautilusDirectory *directory;
 648 	NautilusWindowSlot *slot;
 649 	gboolean visible;
 650 
 651 	slot = window->details->active_slot;
 652 	visible = slot->search_visible;
 653 
 654 	directory = nautilus_directory_get (slot->location);
 655 	if (NAUTILUS_IS_SEARCH_DIRECTORY (directory)) {
 656 		visible = TRUE;
 657 	}
 658 
 659 	nautilus_window_slot_set_search_visible (slot, visible);
 660 	nautilus_directory_unref (directory);
 661 }
 662 
 663 void
 664 nautilus_window_sync_location_widgets (NautilusWindow *window)
 665 {
 666 	NautilusWindowSlot *slot, *active_slot;
 667 	GtkActionGroup *action_group;
 668 	GtkAction *action;
 669 
 670 	slot = window->details->active_slot;
 671 
 672 	/* Change the location bar and path bar to match the current location. */
 673 	if (slot->location != NULL) {
 674 		char *uri;
 675 		GtkWidget *location_entry;
 676 		GtkWidget *path_bar;
 677 
 678 		location_entry = nautilus_toolbar_get_location_entry (NAUTILUS_TOOLBAR (window->details->toolbar));
 679 		path_bar = nautilus_toolbar_get_path_bar (NAUTILUS_TOOLBAR (window->details->toolbar));
 680 
 681 		/* this may be NULL if we just created the slot */
 682 		uri = nautilus_window_slot_get_location_uri (slot);
 683 		nautilus_location_entry_set_uri (NAUTILUS_LOCATION_ENTRY (location_entry), uri);
 684 		g_free (uri);
 685 		nautilus_path_bar_set_path (NAUTILUS_PATH_BAR (path_bar), slot->location);
 686 	}
 687 
 688 	nautilus_window_sync_up_button (window);
 689 
 690 	/* Check if the back and forward buttons need enabling or disabling. */
 691 	active_slot = nautilus_window_get_active_slot (window);
 692 	action_group = nautilus_window_get_main_action_group (window);
 693 
 694 	action = gtk_action_group_get_action (action_group, NAUTILUS_ACTION_BACK);
 695 	gtk_action_set_sensitive (action, active_slot->back_list != NULL);
 696 
 697 	action = gtk_action_group_get_action (action_group, NAUTILUS_ACTION_FORWARD);
 698 	gtk_action_set_sensitive (action, active_slot->forward_list != NULL);
 699 }
 700 
 701 GtkWidget *
 702 nautilus_window_ensure_location_entry (NautilusWindow *window)
 703 {
 704 	GtkWidget *location_entry;
 705 
 706 	remember_focus_widget (window);
 707 
 708 	nautilus_toolbar_set_show_location_entry (NAUTILUS_TOOLBAR (window->details->toolbar), TRUE);
 709 
 710 	location_entry = nautilus_toolbar_get_location_entry (NAUTILUS_TOOLBAR (window->details->toolbar));
 711 	nautilus_location_entry_focus (NAUTILUS_LOCATION_ENTRY (location_entry));
 712 
 713 	return location_entry;
 714 }
 715 
 716 static void
 717 path_bar_location_changed_callback (GtkWidget      *widget,
 718 				    GFile          *location,
 719 				    NautilusWindow *window)
 720 {
 721 	NautilusWindowSlot *slot;
 722 	int i;
 723 
 724 	slot = window->details->active_slot;
 725 	/* check whether we already visited the target location */
 726 	i = bookmark_list_get_uri_index (slot->back_list, location);
 727 	if (i >= 0) {
 728 		nautilus_window_back_or_forward (window, TRUE, i, 0);
 729 	} else {
 730 		nautilus_window_slot_open_location (slot, location, 0);
 731 	}
 732 }
 733 
 734 static void
 735 path_bar_path_event_callback (NautilusPathBar *path_bar,
 736 			      GFile           *location,
 737 			      GdkEventButton  *event,
 738 			      NautilusWindow  *window)
 739 {
 740 	NautilusWindowSlot *slot;
 741 	NautilusWindowOpenFlags flags;
 742 	int mask;
 743 	NautilusView *view;
 744 	char *uri;
 745 
 746 	if (event->type == GDK_BUTTON_RELEASE) {
 747 		mask = event->state & gtk_accelerator_get_default_mod_mask ();
 748 		flags = 0;
 749 
 750 		if (event->button == 2 && mask == 0) {
 751 			flags = NAUTILUS_WINDOW_OPEN_FLAG_NEW_TAB;
 752 		} else if (event->button == 1 && mask == GDK_CONTROL_MASK) {
 753 			flags = NAUTILUS_WINDOW_OPEN_FLAG_NEW_WINDOW;
 754 		}
 755 
 756 		if (flags != 0) {
 757 			slot = nautilus_window_get_active_slot (window);
 758 			nautilus_window_slot_open_location (slot, location, flags);
 759 		}
 760 	} else if (event->button == 3) {
 761 		slot = nautilus_window_get_active_slot (window);
 762 		view = slot->content_view;
 763 		if (view != NULL) {
 764 			uri = g_file_get_uri (location);
 765 			nautilus_view_pop_up_location_context_menu (view, event, uri);
 766 			g_free (uri);
 767 		}
 768 	}
 769 }
 770 
 771 static void
 772 notebook_popup_menu_new_tab_cb (GtkMenuItem *menuitem,
 773 				gpointer user_data)
 774 {
 775 	NautilusWindow *window = user_data;
 776 
 777 	nautilus_window_new_tab (window);
 778 }
 779 
 780 static void
 781 notebook_popup_menu_move_left_cb (GtkMenuItem *menuitem,
 782 				  gpointer user_data)
 783 {
 784 	NautilusWindow *window = user_data;
 785 
 786 	nautilus_notebook_reorder_current_child_relative (NAUTILUS_NOTEBOOK (window->details->notebook), -1);
 787 }
 788 
 789 static void
 790 notebook_popup_menu_move_right_cb (GtkMenuItem *menuitem,
 791 				   gpointer user_data)
 792 {
 793 	NautilusWindow *window = user_data;
 794 
 795 	nautilus_notebook_reorder_current_child_relative (NAUTILUS_NOTEBOOK (window->details->notebook), 1);
 796 }
 797 
 798 static void
 799 notebook_popup_menu_close_cb (GtkMenuItem *menuitem,
 800 			      gpointer user_data)
 801 {
 802 	NautilusWindow *window = user_data;
 803 	NautilusWindowSlot *slot;
 804 
 805 	slot = window->details->active_slot;
 806 	nautilus_window_slot_close (window, slot);
 807 }
 808 
 809 static void
 810 notebook_popup_menu_show (NautilusWindow *window,
 811 			  GdkEventButton *event)
 812 {
 813 	GtkWidget *popup;
 814 	GtkWidget *item;
 815 	GtkWidget *image;
 816 	int button, event_time;
 817 	gboolean can_move_left, can_move_right;
 818 	NautilusNotebook *notebook;
 819 
 820 	notebook = NAUTILUS_NOTEBOOK (window->details->notebook);
 821 
 822 	can_move_left = nautilus_notebook_can_reorder_current_child_relative (notebook, -1);
 823 	can_move_right = nautilus_notebook_can_reorder_current_child_relative (notebook, 1);
 824 
 825 	popup = gtk_menu_new ();
 826 
 827 	item = gtk_menu_item_new_with_mnemonic (_("_New Tab"));
 828 	g_signal_connect (item, "activate",
 829 			  G_CALLBACK (notebook_popup_menu_new_tab_cb),
 830 			  window);
 831 	gtk_menu_shell_append (GTK_MENU_SHELL (popup),
 832 			       item);
 833 
 834 	gtk_menu_shell_append (GTK_MENU_SHELL (popup),
 835 			       gtk_separator_menu_item_new ());
 836 
 837 	item = gtk_menu_item_new_with_mnemonic (_("Move Tab _Left"));
 838 	g_signal_connect (item, "activate",
 839 			  G_CALLBACK (notebook_popup_menu_move_left_cb),
 840 			  window);
 841 	gtk_menu_shell_append (GTK_MENU_SHELL (popup),
 842 			       item);
 843 	gtk_widget_set_sensitive (item, can_move_left);
 844 
 845 	item = gtk_menu_item_new_with_mnemonic (_("Move Tab _Right"));
 846 	g_signal_connect (item, "activate",
 847 			  G_CALLBACK (notebook_popup_menu_move_right_cb),
 848 			  window);
 849 	gtk_menu_shell_append (GTK_MENU_SHELL (popup),
 850 			       item);
 851 	gtk_widget_set_sensitive (item, can_move_right);
 852 
 853 	gtk_menu_shell_append (GTK_MENU_SHELL (popup),
 854 			       gtk_separator_menu_item_new ());
 855 
 856 	item = gtk_image_menu_item_new_with_mnemonic (_("_Close Tab"));
 857 	image = gtk_image_new_from_stock (GTK_STOCK_CLOSE, GTK_ICON_SIZE_MENU);
 858 	gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item), image);
 859 	g_signal_connect (item, "activate",
 860 			  G_CALLBACK (notebook_popup_menu_close_cb), window);
 861 	gtk_menu_shell_append (GTK_MENU_SHELL (popup),
 862 			       item);
 863 
 864 	gtk_widget_show_all (popup);
 865 
 866 	if (event) {
 867 		button = event->button;
 868 		event_time = event->time;
 869 	} else {
 870 		button = 0;
 871 		event_time = gtk_get_current_event_time ();
 872 	}
 873 
 874 	/* TODO is this correct? */
 875 	gtk_menu_attach_to_widget (GTK_MENU (popup),
 876 				   window->details->notebook,
 877 				   NULL);
 878 
 879 	gtk_menu_popup (GTK_MENU (popup), NULL, NULL, NULL, NULL,
 880 			button, event_time);
 881 }
 882 
 883 /* emitted when the user clicks the "close" button of tabs */
 884 static void
 885 notebook_tab_close_requested (NautilusNotebook   *notebook,
 886 			      NautilusWindowSlot *slot,
 887 			      NautilusWindow     *window)
 888 {
 889 	nautilus_window_slot_close (window, slot);
 890 }
 891 
 892 static gboolean
 893 notebook_button_press_cb (GtkWidget *widget,
 894 			  GdkEventButton *event,
 895 			  gpointer user_data)
 896 {
 897 	NautilusWindow *window = user_data;
 898 
 899 	if (GDK_BUTTON_PRESS == event->type && 3 == event->button) {
 900 		notebook_popup_menu_show (window, event);
 901 		return TRUE;
 902 	}
 903 
 904 	return FALSE;
 905 }
 906 
 907 static gboolean
 908 notebook_popup_menu_cb (GtkWidget *widget,
 909 			gpointer user_data)
 910 {
 911 	NautilusWindow *window = user_data;
 912 	notebook_popup_menu_show (window, NULL);
 913 	return TRUE;
 914 }
 915 
 916 static GtkWidget *
 917 create_toolbar (NautilusWindow *window)
 918 {
 919 	GtkSizeGroup *header_size_group;
 920 	GtkWidget *toolbar;
 921 	GtkWidget *path_bar;
 922 	GtkWidget *location_entry;
 923 
 924 	header_size_group = gtk_size_group_new (GTK_SIZE_GROUP_VERTICAL);
 925 	gtk_size_group_set_ignore_hidden (header_size_group, FALSE);
 926 
 927 	/* build the toolbar */
 928 	toolbar = nautilus_toolbar_new (NAUTILUS_WINDOW (window));
 929 
 930 	g_object_bind_property (window, "disable-chrome",
 931 				toolbar, "visible",
 932 				G_BINDING_INVERT_BOOLEAN);
 933 
 934 	/* connect to the pathbar signals */
 935 	path_bar = nautilus_toolbar_get_path_bar (NAUTILUS_TOOLBAR (toolbar));
 936 	gtk_size_group_add_widget (header_size_group, path_bar);
 937 
 938 	g_signal_connect_object (path_bar, "path-clicked",
 939 				 G_CALLBACK (path_bar_location_changed_callback), window, 0);
 940 	g_signal_connect_object (path_bar, "path-event",
 941 				 G_CALLBACK (path_bar_path_event_callback), window, 0);
 942 
 943 	/* connect to the location entry signals */
 944 	location_entry = nautilus_toolbar_get_location_entry (NAUTILUS_TOOLBAR (toolbar));
 945 	gtk_size_group_add_widget (header_size_group, location_entry);
 946 
 947 	nautilus_clipboard_set_up_editable (GTK_EDITABLE (location_entry),
 948 					    nautilus_window_get_ui_manager (NAUTILUS_WINDOW (window)),
 949 					    TRUE);
 950 
 951 	g_signal_connect_object (location_entry, "location-changed",
 952 				 G_CALLBACK (location_entry_location_changed_callback), window, 0);
 953 	g_signal_connect_object (location_entry, "cancel",
 954 				 G_CALLBACK (location_entry_cancel_callback), window, 0);
 955 
 956 	g_object_unref (header_size_group);
 957 
 958 	return toolbar;
 959 }
 960 
 961 static void
 962 notebook_num_pages_changed (NautilusWindow *window)
 963 {
 964 	NautilusView *view;
 965 	NautilusWindowSlot *active_slot;
 966 
 967 	active_slot = nautilus_window_get_active_slot (window);
 968 	if (active_slot == NULL) {
 969 		return;
 970 	}
 971 	view = nautilus_window_slot_get_current_view (active_slot);
 972 	if (view == NULL) {
 973 		return;
 974 	}
 975 
 976 	/* Only add a shadow to the scrolled window when we're in a tabless
 977 	 * notebook, since when the notebook has tabs, it will draw its own
 978 	 * border.
 979 	 */
 980 	if (g_list_length (window->details->slots) > 1 ||
 981 	    NAUTILUS_IS_DESKTOP_WINDOW (window)) {
 982 		gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (view), GTK_SHADOW_NONE);
 983 	} else {
 984 		gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (view), GTK_SHADOW_IN);
 985 	}
 986 }
 987 
 988 static void
 989 notebook_page_removed_cb (GtkNotebook *notebook,
 990 			  GtkWidget *page,
 991 			  guint page_num,
 992 			  gpointer user_data)
 993 {
 994 	NautilusWindow *window = user_data;
 995 	NautilusWindowSlot *slot = NAUTILUS_WINDOW_SLOT (page), *next_slot;
 996 	gboolean dnd_slot;
 997 
 998 	notebook_num_pages_changed (window);
 999 
1000 	dnd_slot = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (slot), "dnd-window-slot"));
1001 	if (!dnd_slot) {
1002 		return;
1003 	}
1004 
1005 	if (window->details->active_slot == slot) {
1006 		next_slot = get_first_inactive_slot (window);
1007 		nautilus_window_set_active_slot (window, next_slot);
1008 	}
1009 
1010 	close_slot (window, slot, FALSE);
1011 }
1012 
1013 static void
1014 notebook_page_added_cb (GtkNotebook *notebook,
1015 			GtkWidget *page,
1016 			guint page_num,
1017 			gpointer user_data)
1018 {
1019 	NautilusWindow *window = user_data;
1020 	NautilusWindowSlot *slot = NAUTILUS_WINDOW_SLOT (page);
1021 	NautilusWindowSlot *dummy_slot;
1022 	gboolean dnd_slot;
1023 
1024 	/* It's too early here to call notebook_num_pages_changed(),
1025 	 * since the view might not be associagted to the slot yet.
1026 	 * Defer the call to nautilus_window_connect_content_view().
1027 	 */
1028 
1029 	dnd_slot = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (slot), "dnd-window-slot"));
1030 	if (!dnd_slot) {
1031 		return;
1032 	}
1033 
1034 	g_object_set_data (G_OBJECT (page), "dnd-window-slot",
1035 			   GINT_TO_POINTER (FALSE));
1036 
1037 	nautilus_window_slot_set_window (slot, window);
1038 	window->details->slots = g_list_append (window->details->slots, slot);
1039 	g_signal_emit (window, signals[SLOT_ADDED], 0, slot);
1040 
1041 	nautilus_window_set_active_slot (window, slot);
1042 
1043 	dummy_slot = g_list_nth_data (window->details->slots, 0);
1044 	if (dummy_slot != NULL) {
1045 		close_slot (window, dummy_slot, TRUE);
1046 	}
1047 
1048 	gtk_widget_show (GTK_WIDGET (window));
1049 }
1050 
1051 static GtkNotebook *
1052 notebook_create_window_cb (GtkNotebook *notebook,
1053 			   GtkWidget *page,
1054 			   gint x,
1055 			   gint y,
1056 			   gpointer user_data)
1057 {
1058 	NautilusApplication *app;
1059 	NautilusWindow *new_window;
1060 	NautilusWindowSlot *slot;
1061 
1062 	if (!NAUTILUS_IS_WINDOW_SLOT (page)) {
1063 		return NULL;
1064 	}
1065 
1066 	app = NAUTILUS_APPLICATION (g_application_get_default ());
1067 	new_window = nautilus_application_create_window
1068 		(app, gtk_widget_get_screen (GTK_WIDGET (notebook)));
1069 
1070 	slot = NAUTILUS_WINDOW_SLOT (page);
1071 	g_object_set_data (G_OBJECT (slot), "dnd-window-slot",
1072 			   GINT_TO_POINTER (TRUE));
1073 
1074 	gtk_window_set_position (GTK_WINDOW (new_window), GTK_WIN_POS_MOUSE);
1075 
1076 	return GTK_NOTEBOOK (new_window->details->notebook);
1077 }
1078 
1079 static GtkWidget *
1080 create_notebook (NautilusWindow *window)
1081 {
1082 	GtkWidget *notebook;
1083 
1084 	notebook = g_object_new (NAUTILUS_TYPE_NOTEBOOK, NULL);
1085 	g_signal_connect (notebook, "tab-close-request",
1086 			  G_CALLBACK (notebook_tab_close_requested),
1087 			  window);
1088 	g_signal_connect (notebook, "popup-menu",
1089 			  G_CALLBACK (notebook_popup_menu_cb),
1090 			  window);
1091 	g_signal_connect (notebook, "switch-page",
1092 			  G_CALLBACK (notebook_switch_page_cb),
1093 			  window);
1094 	g_signal_connect (notebook, "create-window",
1095 			  G_CALLBACK (notebook_create_window_cb),
1096 			  window);
1097 	g_signal_connect (notebook, "page-added",
1098 			  G_CALLBACK (notebook_page_added_cb),
1099 			  window);
1100 	g_signal_connect (notebook, "page-removed",
1101 			  G_CALLBACK (notebook_page_removed_cb),
1102 			  window);
1103 	g_signal_connect_after (notebook, "button-press-event",
1104 				G_CALLBACK (notebook_button_press_cb),
1105 				window);
1106 
1107 	gtk_notebook_set_show_tabs (GTK_NOTEBOOK (notebook), FALSE);
1108 	gtk_notebook_set_show_border (GTK_NOTEBOOK (notebook), FALSE);
1109 	gtk_widget_show (notebook);
1110 	gtk_container_set_border_width (GTK_CONTAINER (notebook), 0);
1111 
1112 	gtk_box_pack_start (GTK_BOX (window->details->main_view),
1113 			    notebook,
1114 			    TRUE, TRUE, 0);
1115 
1116 	return notebook;
1117 }
1118 
1119 static void
1120 nautilus_window_constructed (GObject *self)
1121 {
1122 	NautilusWindow *window;
1123 	GtkWidget *grid;
1124 	NautilusWindowSlot *slot;
1125 
1126 	window = NAUTILUS_WINDOW (self);
1127 
1128 	nautilus_profile_start (NULL);
1129 
1130 	G_OBJECT_CLASS (nautilus_window_parent_class)->constructed (self);
1131 
1132 	/* disable automatic menubar handling, since we show our regular
1133 	 * menubar together with the app menu.
1134 	 */
1135 	gtk_application_window_set_show_menubar (GTK_APPLICATION_WINDOW (self), FALSE);
1136 
1137 	grid = gtk_grid_new ();
1138 	gtk_orientable_set_orientation (GTK_ORIENTABLE (grid), GTK_ORIENTATION_VERTICAL);
1139 	gtk_widget_show (grid);
1140 	gtk_container_add (GTK_CONTAINER (window), grid);
1141 
1142 	nautilus_window_initialize_menus (window);
1143 	nautilus_window_initialize_actions (window);
1144 
1145 	/* Register to menu provider extension signal managing menu updates */
1146 	g_signal_connect_object (nautilus_signaller_get_current (), "popup_menu_changed",
1147 			 G_CALLBACK (nautilus_window_load_extension_menus), window, G_CONNECT_SWAPPED);
1148 	window->details->toolbar = create_toolbar (window);
1149 	gtk_container_add (GTK_CONTAINER (grid), window->details->toolbar);
1150 	gtk_widget_set_hexpand (window->details->toolbar, TRUE);
1151 	gtk_widget_set_vexpand (window->details->toolbar, FALSE);
1152 	gtk_widget_show (window->details->toolbar);
1153 
1154 	window->details->content_paned = gtk_paned_new (GTK_ORIENTATION_HORIZONTAL);
1155 	gtk_widget_set_hexpand (window->details->content_paned, TRUE);
1156 	gtk_widget_set_vexpand (window->details->content_paned, TRUE);
1157 
1158 	gtk_container_add (GTK_CONTAINER (grid), window->details->content_paned);
1159 	gtk_widget_show (window->details->content_paned);
1160 
1161 	window->details->main_view = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
1162 	gtk_paned_pack2 (GTK_PANED (window->details->content_paned), window->details->main_view,
1163 			 TRUE, FALSE);
1164 	gtk_widget_show (window->details->main_view);
1165 
1166 	window->details->notebook = create_notebook (window);
1167 	nautilus_window_set_initial_window_geometry (window);
1168 
1169 	slot = nautilus_window_open_slot (window, 0);
1170 	nautilus_window_set_active_slot (window, slot);
1171 
1172 	if (g_settings_get_boolean (nautilus_window_state, NAUTILUS_WINDOW_STATE_START_WITH_SIDEBAR)) {
1173 		nautilus_window_show_sidebar (window);
1174 	} else {
1175 		nautilus_window_hide_sidebar (window);
1176 	}
1177 
1178 	nautilus_profile_end (NULL);
1179 }
1180 
1181 static void
1182 nautilus_window_set_property (GObject *object,
1183 			      guint arg_id,
1184 			      const GValue *value,
1185 			      GParamSpec *pspec)
1186 {
1187 	NautilusWindow *window;
1188 
1189 	window = NAUTILUS_WINDOW (object);
1190 	
1191 	switch (arg_id) {
1192 	case PROP_DISABLE_CHROME:
1193 		window->details->disable_chrome = g_value_get_boolean (value);
1194 		break;
1195 	default:
1196 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, arg_id, pspec);
1197 		break;
1198 	}
1199 }
1200 
1201 static void
1202 nautilus_window_get_property (GObject *object,
1203 			      guint arg_id,
1204 			      GValue *value,
1205 			      GParamSpec *pspec)
1206 {
1207 	NautilusWindow *window;
1208 
1209 	window = NAUTILUS_WINDOW (object);
1210 
1211 	switch (arg_id) {
1212 	case PROP_DISABLE_CHROME:
1213 		g_value_set_boolean (value, window->details->disable_chrome);
1214 		break;
1215 	}
1216 }
1217 
1218 static void
1219 destroy_slots_foreach (gpointer data,
1220 		       gpointer user_data)
1221 {
1222 	NautilusWindowSlot *slot = data;
1223 	NautilusWindow *window = user_data;
1224 
1225 	close_slot (window, slot, TRUE);
1226 }
1227 
1228 static void
1229 nautilus_window_destroy (GtkWidget *object)
1230 {
1231 	NautilusWindow *window;
1232 	GList *slots_copy;
1233 
1234 	window = NAUTILUS_WINDOW (object);
1235 
1236 	DEBUG ("Destroying window");
1237 
1238 	/* close the sidebar first */
1239 	nautilus_window_tear_down_sidebar (window);
1240 
1241 	/* close all slots safely */
1242 	slots_copy = g_list_copy (window->details->slots);
1243 	g_list_foreach (slots_copy, (GFunc) destroy_slots_foreach, window);
1244 	g_list_free (slots_copy);
1245 
1246 	/* the slots list should now be empty */
1247 	g_assert (window->details->slots == NULL);
1248 
1249 	window->details->active_slot = NULL;
1250 
1251 	GTK_WIDGET_CLASS (nautilus_window_parent_class)->destroy (object);
1252 }
1253 
1254 static void
1255 nautilus_window_finalize (GObject *object)
1256 {
1257 	NautilusWindow *window;
1258 
1259 	window = NAUTILUS_WINDOW (object);
1260 
1261 	if (window->details->sidebar_width_handler_id != 0) {
1262 		g_source_remove (window->details->sidebar_width_handler_id);
1263 		window->details->sidebar_width_handler_id = 0;
1264 	}
1265 
1266 	nautilus_window_finalize_menus (window);
1267 
1268 	g_clear_object (&window->details->ui_manager);
1269 
1270 	/* nautilus_window_close() should have run */
1271 	g_assert (window->details->slots == NULL);
1272 
1273 	G_OBJECT_CLASS (nautilus_window_parent_class)->finalize (object);
1274 }
1275 
1276 void
1277 nautilus_window_view_visible (NautilusWindow *window,
1278 			      NautilusView   *view)
1279 {
1280 	NautilusWindowSlot *slot;
1281 	GList *l;
1282 
1283 	g_return_if_fail (NAUTILUS_IS_WINDOW (window));
1284 
1285 	slot = nautilus_window_get_slot_for_view (window, view);
1286 
1287 	if (slot->visible) {
1288 		return;
1289 	}
1290 
1291 	slot->visible = TRUE;
1292 
1293 	/* Look for other non-visible slots */
1294 	for (l = window->details->slots; l != NULL; l = l->next) {
1295 		slot = l->data;
1296 
1297 		if (!slot->visible) {
1298 			return;
1299 		}
1300 	}
1301 
1302 	/* Look for other non-visible slots */
1303 	for (l = window->details->slots; l != NULL; l = l->next) {
1304 		slot = l->data;
1305 
1306 		nautilus_window_slot_update_title (slot);
1307 	}
1308 
1309 	nautilus_window_grab_focus (window);
1310 
1311 	/* All slots, show window */
1312 	gtk_widget_show (GTK_WIDGET (window));
1313 }
1314 
1315 static void
1316 nautilus_window_save_geometry (NautilusWindow *window)
1317 {
1318 	char *geometry_string;
1319 	gboolean is_maximized;
1320 
1321 	g_assert (NAUTILUS_IS_WINDOW (window));
1322 
1323 	if (gtk_widget_get_window (GTK_WIDGET (window))) {
1324 		geometry_string = eel_gtk_window_get_geometry_string (GTK_WINDOW (window));
1325 		is_maximized = gdk_window_get_state (gtk_widget_get_window (GTK_WIDGET (window)))
1326 				& GDK_WINDOW_STATE_MAXIMIZED;
1327 
1328 		if (!is_maximized) {
1329 			g_settings_set_string
1330 				(nautilus_window_state, NAUTILUS_WINDOW_STATE_GEOMETRY,
1331 				 geometry_string);
1332 		}
1333 		g_free (geometry_string);
1334 
1335 		g_settings_set_boolean
1336 			(nautilus_window_state, NAUTILUS_WINDOW_STATE_MAXIMIZED,
1337 			 is_maximized);
1338 	}
1339 }
1340 
1341 void
1342 nautilus_window_close (NautilusWindow *window)
1343 {
1344 	NAUTILUS_WINDOW_CLASS (G_OBJECT_GET_CLASS (window))->close (window);
1345 }
1346 
1347 void
1348 nautilus_window_set_active_slot (NautilusWindow *window, NautilusWindowSlot *new_slot)
1349 {
1350 	NautilusWindowSlot *old_slot;
1351 
1352 	g_assert (NAUTILUS_IS_WINDOW (window));
1353 
1354 	DEBUG ("Setting new slot %p as active", new_slot);
1355 
1356 	if (new_slot) {
1357 		g_assert ((window == nautilus_window_slot_get_window (new_slot)));
1358 	}
1359 
1360 	old_slot = nautilus_window_get_active_slot (window);
1361 
1362 	if (old_slot == new_slot) {
1363 		return;
1364 	}
1365 
1366 	/* make old slot inactive if it exists (may be NULL after init, for example) */
1367 	if (old_slot != NULL) {
1368 		/* inform window */
1369 		if (old_slot->content_view != NULL) {
1370 			nautilus_window_disconnect_content_view (window, old_slot->content_view);
1371 		}
1372 
1373 		/* inform slot & view */
1374 		g_signal_emit_by_name (old_slot, "inactive");
1375 	}
1376 
1377 	window->details->active_slot = new_slot;
1378 
1379 	/* make new slot active, if it exists */
1380 	if (new_slot) {
1381 		/* inform sidebar panels */
1382                 nautilus_window_report_location_change (window);
1383 		/* TODO decide whether "selection-changed" should be emitted */
1384 
1385 		if (new_slot->content_view != NULL) {
1386                         /* inform window */
1387                         nautilus_window_connect_content_view (window, new_slot->content_view);
1388                 }
1389 
1390 		/* inform slot & view */
1391                 g_signal_emit_by_name (new_slot, "active");
1392 	}
1393 }
1394 
1395 static void
1396 nautilus_window_get_preferred_width (GtkWidget *widget,
1397 				     gint *minimal_width,
1398 				     gint *natural_width)
1399 {
1400 	GdkScreen *screen;
1401 	gint max_w, min_w, default_w;
1402 
1403 	screen = gtk_window_get_screen (GTK_WINDOW (widget));	
1404 
1405 	max_w = get_max_forced_width (screen);
1406 	min_w = NAUTILUS_WINDOW_MIN_WIDTH;
1407 
1408 	default_w = NAUTILUS_WINDOW_DEFAULT_WIDTH;
1409 
1410 	*minimal_width = MIN (min_w, max_w);
1411 	*natural_width = MIN (default_w, max_w);
1412 }
1413 
1414 static void
1415 nautilus_window_get_preferred_height (GtkWidget *widget,
1416 				      gint *minimal_height,
1417 				      gint *natural_height)
1418 {
1419 	GdkScreen *screen;
1420 	gint max_h, min_h, default_h;
1421 
1422 	screen = gtk_window_get_screen (GTK_WINDOW (widget));	
1423 
1424 	max_h = get_max_forced_height (screen);
1425 
1426 	min_h = NAUTILUS_WINDOW_MIN_HEIGHT;
1427 
1428 	default_h = NAUTILUS_WINDOW_DEFAULT_HEIGHT;
1429 
1430 	*minimal_height = MIN (min_h, max_h);
1431 	*natural_height = MIN (default_h, max_h);
1432 }
1433 
1434 static void
1435 nautilus_window_realize (GtkWidget *widget)
1436 {
1437 	GTK_WIDGET_CLASS (nautilus_window_parent_class)->realize (widget);
1438 	update_cursor (NAUTILUS_WINDOW (widget));
1439 }
1440 
1441 static gboolean
1442 nautilus_window_key_press_event (GtkWidget *widget,
1443 				 GdkEventKey *event)
1444 {
1445 	NautilusWindow *window;
1446 	NautilusWindowSlot *active_slot;
1447 	NautilusView *view;
1448 	GtkWidget *focus_widget;
1449 	int i;
1450 
1451 	window = NAUTILUS_WINDOW (widget);
1452 
1453 	active_slot = nautilus_window_get_active_slot (window);
1454 	view = active_slot->content_view;
1455 
1456 	if (view != NULL && nautilus_view_get_is_renaming (view)) {
1457 		/* if we're renaming, just forward the event to the
1458 		 * focused widget and return. We don't want to process the window
1459 		 * accelerator bindings, as they might conflict with the 
1460 		 * editable widget bindings.
1461 		 */
1462 		if (gtk_window_propagate_key_event (GTK_WINDOW (window), event)) {
1463 			return TRUE;
1464 		}
1465 	}
1466 
1467 	focus_widget = gtk_window_get_focus (GTK_WINDOW (window));
1468 	if (view != NULL && focus_widget != NULL &&
1469 	    GTK_IS_EDITABLE (focus_widget)) {
1470 		/* if we have input focus on a GtkEditable (e.g. a GtkEntry), forward
1471 		 * the event to it before activating accelerator bindings too.
1472 		 */
1473 		if (gtk_window_propagate_key_event (GTK_WINDOW (window), event)) {
1474 			return TRUE;
1475 		}
1476 	}
1477 
1478 	for (i = 0; i < G_N_ELEMENTS (extra_window_keybindings); i++) {
1479 		if (extra_window_keybindings[i].keyval == event->keyval) {
1480 			const GList *action_groups;
1481 			GtkAction *action;
1482 
1483 			action = NULL;
1484 
1485 			action_groups = gtk_ui_manager_get_action_groups (window->details->ui_manager);
1486 			while (action_groups != NULL && action == NULL) {
1487 				action = gtk_action_group_get_action (action_groups->data, extra_window_keybindings[i].action);
1488 				action_groups = action_groups->next;
1489 			}
1490 
1491 			g_assert (action != NULL);
1492 			if (gtk_action_is_sensitive (action)) {
1493 				gtk_action_activate (action);
1494 				return TRUE;
1495 			}
1496 
1497 			break;
1498 		}
1499 	}
1500 
1501 	if (GTK_WIDGET_CLASS (nautilus_window_parent_class)->key_press_event (widget, event)) {
1502 		return TRUE;
1503 	}
1504 
1505 	if (nautilus_window_slot_handle_event (window->details->active_slot, event)) {
1506 		nautilus_window_slot_set_search_visible (window->details->active_slot, TRUE);
1507 		return TRUE;
1508 	}
1509 
1510 	return FALSE;
1511 }
1512 
1513 /*
1514  * Main API
1515  */
1516 
1517 static void
1518 real_sync_view_as_menus (NautilusWindow *window)
1519 {
1520 	NautilusWindowSlot *slot;
1521 	GtkActionGroup *action_group;
1522 	GtkAction *action;
1523 
1524 	g_assert (NAUTILUS_IS_WINDOW (window));
1525 
1526 	slot = nautilus_window_get_active_slot (window);
1527 
1528 	if (slot->content_view == NULL || slot->new_content_view != NULL) {
1529 		return;
1530 	}
1531 
1532 	action_group = nautilus_window_get_main_action_group (window);
1533 
1534 	if (nautilus_window_slot_content_view_matches_iid (slot, NAUTILUS_LIST_VIEW_ID)) {
1535 		action = gtk_action_group_get_action (action_group, NAUTILUS_ACTION_VIEW_LIST);
1536 	} else {
1537 		action = gtk_action_group_get_action (action_group, NAUTILUS_ACTION_VIEW_GRID);
1538 	}
1539 
1540 	gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE);
1541 }
1542 
1543 /**
1544  * nautilus_window_sync_view_as_menus:
1545  *
1546  * Set the visible item of the "View as" option menu and
1547  * the marked "View as" item in the View menu to
1548  * match the current content view.
1549  *
1550  * @window: The NautilusWindow whose "View as" option menu should be synched.
1551  */
1552 void
1553 nautilus_window_sync_view_as_menus (NautilusWindow *window)
1554 {
1555 	if (NAUTILUS_WINDOW_CLASS (G_OBJECT_GET_CLASS (window))->sync_view_as_menus != NULL) {
1556 		NAUTILUS_WINDOW_CLASS (G_OBJECT_GET_CLASS (window))->sync_view_as_menus (window);
1557 	}
1558 }
1559 
1560 void
1561 nautilus_window_sync_up_button (NautilusWindow *window)
1562 {
1563 	GtkAction *action;
1564 	GtkActionGroup *action_group;
1565 	NautilusWindowSlot *slot;
1566 	gboolean allowed;
1567 	GFile *parent;
1568 
1569 	slot = nautilus_window_get_active_slot (window);
1570 
1571 	allowed = FALSE;
1572 	if (slot->location != NULL) {
1573 		parent = g_file_get_parent (slot->location);
1574 		allowed = parent != NULL;
1575 
1576 		g_clear_object (&parent);
1577 	}
1578 
1579 	action_group = nautilus_window_get_main_action_group (window);
1580 
1581 	action = gtk_action_group_get_action (action_group,
1582 					      NAUTILUS_ACTION_UP);
1583 	gtk_action_set_sensitive (action, allowed);
1584 }
1585 
1586 void
1587 nautilus_window_sync_title (NautilusWindow *window,
1588 			    NautilusWindowSlot *slot)
1589 {
1590 	if (NAUTILUS_WINDOW_CLASS (G_OBJECT_GET_CLASS (window))->sync_title != NULL) {
1591 		NAUTILUS_WINDOW_CLASS (G_OBJECT_GET_CLASS (window))->sync_title (window, slot);
1592 
1593 		return;
1594 	}
1595 
1596 	if (slot == nautilus_window_get_active_slot (window)) {
1597 		gtk_window_set_title (GTK_WINDOW (window), slot->title);
1598 	}
1599 
1600 	nautilus_notebook_sync_tab_label (NAUTILUS_NOTEBOOK (window->details->notebook), slot);
1601 }
1602 
1603 void
1604 nautilus_window_sync_zoom_widgets (NautilusWindow *window)
1605 {
1606 	NautilusWindowSlot *slot;
1607 	NautilusView *view;
1608 	GtkActionGroup *action_group;
1609 	GtkAction *action;
1610 	gboolean supports_zooming;
1611 	gboolean can_zoom, can_zoom_in, can_zoom_out;
1612 	NautilusZoomLevel zoom_level;
1613 
1614 	slot = nautilus_window_get_active_slot (window);
1615 	view = slot->content_view;
1616 
1617 	if (view != NULL) {
1618 		supports_zooming = nautilus_view_supports_zooming (view);
1619 		zoom_level = nautilus_view_get_zoom_level (view);
1620 		can_zoom = supports_zooming &&
1621 			   zoom_level >= NAUTILUS_ZOOM_LEVEL_SMALLEST &&
1622 			   zoom_level <= NAUTILUS_ZOOM_LEVEL_LARGEST;
1623 		can_zoom_in = can_zoom && nautilus_view_can_zoom_in (view);
1624 		can_zoom_out = can_zoom && nautilus_view_can_zoom_out (view);
1625 	} else {
1626 		supports_zooming = FALSE;
1627 		can_zoom = FALSE;
1628 		can_zoom_in = FALSE;
1629 		can_zoom_out = FALSE;
1630 	}
1631 
1632 	action_group = nautilus_window_get_main_action_group (window);
1633 
1634 	action = gtk_action_group_get_action (action_group,
1635 					      NAUTILUS_ACTION_ZOOM_IN);
1636 	gtk_action_set_visible (action, supports_zooming);
1637 	gtk_action_set_sensitive (action, can_zoom_in);
1638 	
1639 	action = gtk_action_group_get_action (action_group,
1640 					      NAUTILUS_ACTION_ZOOM_OUT);
1641 	gtk_action_set_visible (action, supports_zooming);
1642 	gtk_action_set_sensitive (action, can_zoom_out);
1643 
1644 	action = gtk_action_group_get_action (action_group,
1645 					      NAUTILUS_ACTION_ZOOM_NORMAL);
1646 	gtk_action_set_visible (action, supports_zooming);
1647 	gtk_action_set_sensitive (action, can_zoom);
1648 }
1649 
1650 static void
1651 zoom_level_changed_callback (NautilusView *view,
1652                              NautilusWindow *window)
1653 {
1654 	g_assert (NAUTILUS_IS_WINDOW (window));
1655 
1656 	/* This is called each time the component in
1657 	 * the active slot successfully completed
1658 	 * a zooming operation.
1659 	 */
1660 	nautilus_window_sync_zoom_widgets (window);
1661 }
1662 
1663 
1664 /* These are called
1665  *   A) when switching the view within the active slot
1666  *   B) when switching the active slot
1667  *   C) when closing the active slot (disconnect)
1668 */
1669 void
1670 nautilus_window_connect_content_view (NautilusWindow *window,
1671 				      NautilusView *view)
1672 {
1673 	NautilusWindowSlot *slot;
1674 	NautilusDirectory *directory;
1675 
1676 	g_assert (NAUTILUS_IS_WINDOW (window));
1677 	g_assert (NAUTILUS_IS_VIEW (view));
1678 
1679 	slot = nautilus_window_get_slot_for_view (window, view);
1680 
1681 	if (slot != nautilus_window_get_active_slot (window)) {
1682 		return;
1683 	}
1684 
1685 	g_signal_connect (view, "zoom-level-changed",
1686 			  G_CALLBACK (zoom_level_changed_callback),
1687 			  window);
1688 
1689 	/* See the comment in notebook_page_added_cb() */
1690 	notebook_num_pages_changed (window);
1691 
1692       /* Update displayed view in menu. Only do this if we're not switching
1693        * locations though, because if we are switching locations we'll
1694        * install a whole new set of views in the menu later (the current
1695        * views in the menu are for the old location).
1696        */
1697 	if (slot->pending_location == NULL) {
1698 		nautilus_window_sync_view_as_menus (window);
1699 	} else {
1700 		directory = nautilus_directory_get (slot->pending_location);
1701 		if (!NAUTILUS_IS_SEARCH_DIRECTORY (directory)) {
1702 			nautilus_view_grab_focus (view);
1703 		}
1704 
1705 		nautilus_directory_unref (directory);
1706 	}
1707 }
1708 
1709 void
1710 nautilus_window_disconnect_content_view (NautilusWindow *window,
1711 					 NautilusView *view)
1712 {
1713 	NautilusWindowSlot *slot;
1714 
1715 	g_assert (NAUTILUS_IS_WINDOW (window));
1716 	g_assert (NAUTILUS_IS_VIEW (view));
1717 
1718 	slot = nautilus_window_get_slot_for_view (window, view);
1719 
1720 	if (slot != nautilus_window_get_active_slot (window)) {
1721 		return;
1722 	}
1723 
1724 	g_signal_handlers_disconnect_by_func (view, G_CALLBACK (zoom_level_changed_callback), window);
1725 }
1726 
1727 /**
1728  * nautilus_window_show:
1729  * @widget:	GtkWidget
1730  *
1731  * Call parent and then show/hide window items
1732  * base on user prefs.
1733  */
1734 static void
1735 nautilus_window_show (GtkWidget *widget)
1736 {	
1737 	NautilusWindow *window;
1738 
1739 	window = NAUTILUS_WINDOW (widget);
1740 
1741 	GTK_WIDGET_CLASS (nautilus_window_parent_class)->show (widget);	
1742 
1743 	gtk_ui_manager_ensure_update (window->details->ui_manager);
1744 }
1745 
1746 GtkUIManager *
1747 nautilus_window_get_ui_manager (NautilusWindow *window)
1748 {
1749 	g_return_val_if_fail (NAUTILUS_IS_WINDOW (window), NULL);
1750 
1751 	return window->details->ui_manager;
1752 }
1753 
1754 GtkActionGroup *
1755 nautilus_window_get_main_action_group (NautilusWindow *window)
1756 {
1757 	g_return_val_if_fail (NAUTILUS_IS_WINDOW (window), NULL);
1758 
1759 	return window->details->main_action_group;
1760 }
1761 
1762 void
1763 nautilus_window_slot_set_viewed_file (NautilusWindowSlot *slot,
1764 				      NautilusFile *file)
1765 {
1766 	NautilusFileAttributes attributes;
1767 
1768 	if (slot->viewed_file == file) {
1769 		return;
1770 	}
1771 
1772 	nautilus_file_ref (file);
1773 
1774 	if (slot->viewed_file != NULL) {
1775 		nautilus_file_monitor_remove (slot->viewed_file,
1776 					      slot);
1777 	}
1778 
1779 	if (file != NULL) {
1780 		attributes =
1781 			NAUTILUS_FILE_ATTRIBUTE_INFO |
1782 			NAUTILUS_FILE_ATTRIBUTE_LINK_INFO;
1783 		nautilus_file_monitor_add (file, slot, attributes);
1784 	}
1785 
1786 	nautilus_file_unref (slot->viewed_file);
1787 	slot->viewed_file = file;
1788 }
1789 
1790 NautilusWindowSlot *
1791 nautilus_window_get_slot_for_view (NautilusWindow *window,
1792 				   NautilusView *view)
1793 {
1794 	NautilusWindowSlot *slot;
1795 	GList *l;
1796 
1797 	slot = NULL;
1798 	for (l = window->details->slots; l; l = l->next) {
1799 		NautilusWindowSlot *tmp = l->data;
1800 
1801 		if (tmp->content_view == view ||
1802 		    tmp->new_content_view == view) {
1803 			slot = tmp;
1804 			break;
1805 		}
1806 	}
1807 
1808 	return slot;
1809 }
1810 
1811 NautilusWindowSlot *
1812 nautilus_window_get_active_slot (NautilusWindow *window)
1813 {
1814 	g_assert (NAUTILUS_IS_WINDOW (window));
1815 
1816 	return window->details->active_slot;
1817 }
1818 
1819 GList *
1820 nautilus_window_get_slots (NautilusWindow *window)
1821 {
1822 	g_assert (NAUTILUS_IS_WINDOW (window));
1823 
1824 	return window->details->slots;
1825 }
1826 
1827 static gboolean
1828 nautilus_window_state_event (GtkWidget *widget,
1829 			     GdkEventWindowState *event)
1830 {
1831 	if (event->changed_mask & GDK_WINDOW_STATE_MAXIMIZED) {
1832 		g_settings_set_boolean (nautilus_window_state, NAUTILUS_WINDOW_STATE_MAXIMIZED,
1833 					event->new_window_state & GDK_WINDOW_STATE_MAXIMIZED);
1834 	}
1835 
1836 	if (GTK_WIDGET_CLASS (nautilus_window_parent_class)->window_state_event != NULL) {
1837 		return GTK_WIDGET_CLASS (nautilus_window_parent_class)->window_state_event (widget, event);
1838 	}
1839 
1840 	return FALSE;
1841 }
1842 
1843 static gboolean
1844 nautilus_window_delete_event (GtkWidget *widget,
1845 			      GdkEventAny *event)
1846 {
1847 	nautilus_window_close (NAUTILUS_WINDOW (widget));
1848 	return FALSE;
1849 }
1850 
1851 static gboolean
1852 nautilus_window_button_press_event (GtkWidget *widget,
1853 				    GdkEventButton *event)
1854 {
1855 	NautilusWindow *window;
1856 	gboolean handled;
1857 
1858 	window = NAUTILUS_WINDOW (widget);
1859 
1860 	if (mouse_extra_buttons && (event->button == mouse_back_button)) {
1861 		nautilus_window_back_or_forward (window, TRUE, 0, 0);
1862 		handled = TRUE; 
1863 	} else if (mouse_extra_buttons && (event->button == mouse_forward_button)) {
1864 		nautilus_window_back_or_forward (window, FALSE, 0, 0);
1865 		handled = TRUE;
1866 	} else if (GTK_WIDGET_CLASS (nautilus_window_parent_class)->button_press_event) {
1867 		handled = GTK_WIDGET_CLASS (nautilus_window_parent_class)->button_press_event (widget, event);
1868 	} else {
1869 		handled = FALSE;
1870 	}
1871 	return handled;
1872 }
1873 
1874 static void
1875 mouse_back_button_changed (gpointer callback_data)
1876 {
1877 	int new_back_button;
1878 
1879 	new_back_button = g_settings_get_int (nautilus_preferences, NAUTILUS_PREFERENCES_MOUSE_BACK_BUTTON);
1880 
1881 	/* Bounds checking */
1882 	if (new_back_button < 6 || new_back_button > UPPER_MOUSE_LIMIT)
1883 		return;
1884 
1885 	mouse_back_button = new_back_button;
1886 }
1887 
1888 static void
1889 mouse_forward_button_changed (gpointer callback_data)
1890 {
1891 	int new_forward_button;
1892 
1893 	new_forward_button = g_settings_get_int (nautilus_preferences, NAUTILUS_PREFERENCES_MOUSE_FORWARD_BUTTON);
1894 
1895 	/* Bounds checking */
1896 	if (new_forward_button < 6 || new_forward_button > UPPER_MOUSE_LIMIT)
1897 		return;
1898 
1899 	mouse_forward_button = new_forward_button;
1900 }
1901 
1902 static void
1903 use_extra_mouse_buttons_changed (gpointer callback_data)
1904 {
1905 	mouse_extra_buttons = g_settings_get_boolean (nautilus_preferences, NAUTILUS_PREFERENCES_MOUSE_USE_EXTRA_BUTTONS);
1906 }
1907 
1908 
1909 /*
1910  * Main API
1911  */
1912 
1913 static void
1914 nautilus_window_init (NautilusWindow *window)
1915 {
1916 	GtkWindowGroup *window_group;
1917 
1918 	window->details = G_TYPE_INSTANCE_GET_PRIVATE (window, NAUTILUS_TYPE_WINDOW, NautilusWindowDetails);
1919 
1920 	window->details->slots = NULL;
1921 	window->details->active_slot = NULL;
1922 
1923 	window_group = gtk_window_group_new ();
1924 	gtk_window_group_add_window (window_group, GTK_WINDOW (window));
1925 	g_object_unref (window_group);
1926 
1927 	/* Set initial window title */
1928 	gtk_window_set_title (GTK_WINDOW (window), _("Files"));
1929 	gtk_window_set_icon_name (GTK_WINDOW (window), "system-file-manager");
1930 	gtk_window_set_hide_titlebar_when_maximized (GTK_WINDOW (window), TRUE);
1931 }
1932 
1933 static NautilusIconInfo *
1934 real_get_icon (NautilusWindow *window,
1935                NautilusWindowSlot *slot)
1936 {
1937         return nautilus_file_get_icon (slot->viewed_file, 48,
1938 				       NAUTILUS_FILE_ICON_FLAGS_IGNORE_VISITING |
1939 				       NAUTILUS_FILE_ICON_FLAGS_USE_MOUNT_ICON);
1940 }
1941 
1942 static void
1943 real_window_close (NautilusWindow *window)
1944 {
1945 	g_return_if_fail (NAUTILUS_IS_WINDOW (window));
1946 
1947 	nautilus_window_save_geometry (window);
1948 
1949 	gtk_widget_destroy (GTK_WIDGET (window));
1950 }
1951 
1952 static void
1953 nautilus_window_class_init (NautilusWindowClass *class)
1954 {
1955 	GObjectClass *oclass = G_OBJECT_CLASS (class);
1956 	GtkWidgetClass *wclass = GTK_WIDGET_CLASS (class);
1957 
1958 	oclass->finalize = nautilus_window_finalize;
1959 	oclass->constructed = nautilus_window_constructed;
1960 	oclass->get_property = nautilus_window_get_property;
1961 	oclass->set_property = nautilus_window_set_property;
1962 
1963 	wclass->destroy = nautilus_window_destroy;
1964 	wclass->show = nautilus_window_show;
1965 	wclass->get_preferred_width = nautilus_window_get_preferred_width;
1966 	wclass->get_preferred_height = nautilus_window_get_preferred_height;
1967 	wclass->realize = nautilus_window_realize;
1968 	wclass->key_press_event = nautilus_window_key_press_event;
1969 	wclass->window_state_event = nautilus_window_state_event;
1970 	wclass->button_press_event = nautilus_window_button_press_event;
1971 	wclass->delete_event = nautilus_window_delete_event;
1972 
1973 	class->get_icon = real_get_icon;
1974 	class->close = real_window_close;
1975 	class->sync_view_as_menus = real_sync_view_as_menus;
1976 
1977 	properties[PROP_DISABLE_CHROME] =
1978 		g_param_spec_boolean ("disable-chrome",
1979 				      "Disable chrome",
1980 				      "Disable window chrome, for the desktop",
1981 				      FALSE,
1982 				      G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
1983 				      G_PARAM_STATIC_STRINGS);
1984 
1985 	signals[LOADING_URI] =
1986 		g_signal_new ("loading_uri",
1987 			      G_TYPE_FROM_CLASS (class),
1988 			      G_SIGNAL_RUN_LAST,
1989 			      0,
1990 			      NULL, NULL,
1991 			      g_cclosure_marshal_VOID__STRING,
1992 			      G_TYPE_NONE, 1,
1993 			      G_TYPE_STRING);
1994 	signals[SLOT_ADDED] =
1995 		g_signal_new ("slot-added",
1996 			      G_TYPE_FROM_CLASS (class),
1997 			      G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
1998 			      0,
1999 			      NULL, NULL,
2000 			      g_cclosure_marshal_VOID__OBJECT,
2001 			      G_TYPE_NONE, 1, NAUTILUS_TYPE_WINDOW_SLOT);
2002 	signals[SLOT_REMOVED] =
2003 		g_signal_new ("slot-removed",
2004 			      G_TYPE_FROM_CLASS (class),
2005 			      G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
2006 			      0,
2007 			      NULL, NULL,
2008 			      g_cclosure_marshal_VOID__OBJECT,
2009 			      G_TYPE_NONE, 1, NAUTILUS_TYPE_WINDOW_SLOT);
2010 
2011 	g_signal_connect_swapped (nautilus_preferences,
2012 				  "changed::" NAUTILUS_PREFERENCES_MOUSE_BACK_BUTTON,
2013 				  G_CALLBACK(mouse_back_button_changed),
2014 				  NULL);
2015 
2016 	g_signal_connect_swapped (nautilus_preferences,
2017 				  "changed::" NAUTILUS_PREFERENCES_MOUSE_FORWARD_BUTTON,
2018 				  G_CALLBACK(mouse_forward_button_changed),
2019 				  NULL);
2020 
2021 	g_signal_connect_swapped (nautilus_preferences,
2022 				  "changed::" NAUTILUS_PREFERENCES_MOUSE_USE_EXTRA_BUTTONS,
2023 				  G_CALLBACK(use_extra_mouse_buttons_changed),
2024 				  NULL);
2025 
2026 	g_object_class_install_properties (oclass, NUM_PROPERTIES, properties);
2027 	g_type_class_add_private (oclass, sizeof (NautilusWindowDetails));
2028 }
2029 
2030 NautilusWindow *
2031 nautilus_window_new (GtkApplication *application,
2032 		     GdkScreen      *screen)
2033 {
2034 	return g_object_new (NAUTILUS_TYPE_WINDOW,
2035 			     "application", application,
2036 			     "screen", screen,
2037 			     NULL);
2038 }
2039 
2040 NautilusWindowOpenFlags
2041 nautilus_event_get_window_open_flags (void)
2042 {
2043 	NautilusWindowOpenFlags flags = 0;
2044 	GdkEvent *event;
2045 
2046 	event = gtk_get_current_event ();
2047 
2048 	if (event == NULL) {
2049 		return flags;
2050 	}
2051 
2052 	if ((event->type == GDK_BUTTON_PRESS || event->type == GDK_BUTTON_RELEASE) &&
2053 	    (event->button.button == 2)) {
2054 		flags |= NAUTILUS_WINDOW_OPEN_FLAG_NEW_TAB;
2055 	}
2056 
2057 	gdk_event_free (event);
2058 
2059 	return flags;
2060 }
2061 
2062 void
2063 nautilus_window_show_about_dialog (NautilusWindow *window)
2064 {
2065 	const gchar *authors[] = {
2066 		"Alexander Larsson",
2067 		"Ali Abdin",
2068 		"Anders Carlsson",
2069 		"Andrew Walton",
2070 		"Andy Hertzfeld",
2071 		"Arlo Rose",
2072 		"Christian Neumair",
2073 		"Cosimo Cecchi",
2074 		"Darin Adler",
2075 		"David Camp",
2076 		"Eli Goldberg",
2077 		"Elliot Lee",
2078 		"Eskil Heyn Olsen",
2079 		"Ettore Perazzoli",
2080 		"Gene Z. Ragan",
2081 		"George Lebl",
2082 		"Ian McKellar",
2083 		"J Shane Culpepper",
2084 		"James Willcox",
2085 		"Jan Arne Petersen",
2086 		"John Harper",
2087 		"John Sullivan",
2088 		"Josh Barrow",
2089 		"Maciej Stachowiak",
2090 		"Mark McLoughlin",
2091 		"Mathieu Lacage",
2092 		"Mike Engber",
2093 		"Mike Fleming",
2094 		"Pavel Cisler",
2095 		"Ramiro Estrugo",
2096 		"Raph Levien",
2097 		"Rebecca Schulman",
2098 		"Robey Pointer",
2099 		"Robin * Slomkowski",
2100 		"Seth Nickell",
2101 		"Susan Kare",
2102 		"Tomas Bzatek",
2103 		"William Jon McCann",
2104 		NULL
2105 	};
2106 	const gchar *documenters[] = {
2107 		"GNOME Documentation Team",
2108 		"Sun Microsystems",
2109 		NULL
2110 	};
2111 	const gchar *license[] = {
2112 		N_("Files is free software; you can redistribute it and/or modify "
2113 		   "it under the terms of the GNU General Public License as published by "
2114 		   "the Free Software Foundation; either version 2 of the License, or "
2115 		   "(at your option) any later version."),
2116 		N_("Files is distributed in the hope that it will be useful, "
2117 		   "but WITHOUT ANY WARRANTY; without even the implied warranty of "
2118 		   "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the "
2119 		   "GNU General Public License for more details."),
2120 		N_("You should have received a copy of the GNU General Public License "
2121 		   "along with Nautilus; if not, write to the Free Software Foundation, Inc., "
2122 		   "51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA")
2123 	};
2124 	gchar *license_trans, *copyright_str;
2125 	GDateTime *date;
2126 
2127 	license_trans = g_strjoin ("\n\n", _(license[0]), _(license[1]),
2128 					     _(license[2]), NULL);
2129 
2130 	date = g_date_time_new_now_local ();
2131 
2132 	/* Translators: these two strings here indicate the copyright time span,
2133 	 * e.g. 1999-2011.
2134 	 */
2135 	copyright_str = g_strdup_printf (_("Copyright \xC2\xA9 %Id\xE2\x80\x93%Id "
2136 					   "The Files authors"), 1999, g_date_time_get_year (date));
2137 
2138 	gtk_show_about_dialog (window ? GTK_WINDOW (window) : NULL,
2139 			       "program-name", _("Files"),
2140 			       "version", VERSION,
2141 			       "comments", _("Access and organize your files."),
2142 			       "copyright", copyright_str,
2143 			       "license", license_trans,
2144 			       "wrap-license", TRUE,
2145 			       "authors", authors,
2146 			       "documenters", documenters,
2147 				/* Translators should localize the following string
2148 				 * which will be displayed at the bottom of the about
2149 				 * box to give credit to the translator(s).
2150 				 */
2151 			      "translator-credits", _("translator-credits"),
2152 			      "logo-icon-name", "system-file-manager",
2153 			      NULL);
2154 
2155 	g_free (license_trans);
2156 	g_free (copyright_str);
2157 	g_date_time_unref (date);
2158 }