1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
2 
3 /*
4  * nemo-window-pane.c: Nemo window pane
5  *
6  * Copyright (C) 2008 Free Software Foundation, Inc.
7  * Copyright (C) 2011 Red Hat, Inc.
8  *
9  * This program is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU General Public License as
11  * published by the Free Software Foundation; either version 2 of the
12  * License, or (at your option) any later version.
13  *
14  * This program 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
21  * Free Software Foundation, Inc., 51 Franklin Street - Suite 500,
22  * Boston, MA 02110-1335, USA.
23  *
24  * Authors: Holger Berndt <berndth@gmx.de>
25  *          Cosimo Cecchi <cosimoc@redhat.com>
26  *
27  */
28 
29 #include "nemo-window-pane.h"
30 
31 #include "nemo-actions.h"
32 #include "nemo-application.h"
33 #include "nemo-location-bar.h"
34 #include "nemo-notebook.h"
35 #include "nemo-pathbar.h"
36 #include "nemo-toolbar.h"
37 #include "nemo-window-manage-views.h"
38 #include "nemo-window-private.h"
39 #include "nemo-window-menus.h"
40 #include "nemo-icon-view.h"
41 #include "nemo-list-view.h"
42 
43 #include <glib/gi18n.h>
44 
45 #include <libnemo-private/nemo-clipboard.h>
46 #include <libnemo-private/nemo-global-preferences.h>
47 #include <libnemo-private/nemo-entry.h>
48 
49 #define DEBUG_FLAG NEMO_DEBUG_WINDOW
50 #include <libnemo-private/nemo-debug.h>
51 
52 // For: NEMO_IS_DESKTOP_WINDOW
53 #include "nemo-desktop-window.h"
54 
55 enum {
56 	PROP_WINDOW = 1,
57 	NUM_PROPERTIES
58 };
59 
60 static GParamSpec *properties[NUM_PROPERTIES] = { NULL, };
61 
G_DEFINE_TYPE(NemoWindowPane,nemo_window_pane,GTK_TYPE_BOX)62 G_DEFINE_TYPE (NemoWindowPane, nemo_window_pane,
63 	       GTK_TYPE_BOX)
64 
65 static gboolean
66 widget_is_in_temporary_bars (GtkWidget *widget,
67 			     NemoWindowPane *pane)
68 {
69 	gboolean res = FALSE;
70 
71 	if (gtk_widget_get_ancestor (widget, NEMO_TYPE_LOCATION_BAR) != NULL &&
72 	     pane->temporary_navigation_bar)
73 		res = TRUE;
74 
75 	return res;
76 }
77 
78 static void
unset_focus_widget(NemoWindowPane * pane)79 unset_focus_widget (NemoWindowPane *pane)
80 {
81 	if (pane->last_focus_widget != NULL) {
82 		g_object_remove_weak_pointer (G_OBJECT (pane->last_focus_widget),
83 					      (gpointer *) &pane->last_focus_widget);
84 		pane->last_focus_widget = NULL;
85 	}
86 }
87 
88 static void
remember_focus_widget(NemoWindowPane * pane)89 remember_focus_widget (NemoWindowPane *pane)
90 {
91 	GtkWidget *focus_widget;
92 
93 	focus_widget = gtk_window_get_focus (GTK_WINDOW (pane->window));
94 	if (focus_widget != NULL &&
95 	    !widget_is_in_temporary_bars (focus_widget, pane)) {
96 		unset_focus_widget (pane);
97 
98 		pane->last_focus_widget = focus_widget;
99 		g_object_add_weak_pointer (G_OBJECT (focus_widget),
100 					   (gpointer *) &(pane->last_focus_widget));
101 	}
102 }
103 
104 static void
restore_focus_widget(NemoWindowPane * pane)105 restore_focus_widget (NemoWindowPane *pane)
106 {
107 	if (pane->last_focus_widget != NULL) {
108 		if (NEMO_IS_VIEW (pane->last_focus_widget)) {
109 			nemo_view_grab_focus (NEMO_VIEW (pane->last_focus_widget));
110 		} else {
111 			gtk_widget_grab_focus (pane->last_focus_widget);
112 		}
113 
114 		unset_focus_widget (pane);
115 	}
116 }
117 
118 static NemoWindowSlot *
get_next_or_previous_slot(NemoWindowPane * pane)119 get_next_or_previous_slot (NemoWindowPane *pane)
120 {
121 	GtkNotebook *gnotebook;
122 	gint page_num;
123 	GtkWidget *page;
124 
125 	g_return_val_if_fail (pane != NULL, NULL);
126 
127 	gnotebook = GTK_NOTEBOOK (pane->notebook);
128 	page = NULL;
129 
130 	/* If we don't have an active slot, return the first page in the
131 	 * notebook.
132 	 */
133 	if (!pane->active_slot) {
134 		page = gtk_notebook_get_nth_page (gnotebook, 0);
135 	} else {
136 		/* Otherwise, return the next or previous slot that appears in
137 		 * the notebook. We don't use pane->slots to select the next
138 		 * slot as the list does not represent the order in which slots
139 		 * are actually displayed in the pane.
140 		 */
141 		page_num = gtk_notebook_page_num (
142 			gnotebook, GTK_WIDGET (pane->active_slot));
143 		if (page_num != -1) {
144 			page = gtk_notebook_get_nth_page (
145 				gnotebook, page_num+1);
146 			/* Get the previous page if there is no next one. */
147 			if (!page) {
148 				page = gtk_notebook_get_nth_page (
149 					gnotebook, page_num-1);
150 			}
151 		}
152 	}
153 
154 	if (page)
155 		return NEMO_WINDOW_SLOT (page);
156 	return NULL;
157 }
158 
159 static int
bookmark_list_get_uri_index(GList * list,GFile * location)160 bookmark_list_get_uri_index (GList *list, GFile *location)
161 {
162 	NemoBookmark *bookmark;
163 	GList *l;
164 	GFile *tmp;
165 	int i;
166 
167 	g_return_val_if_fail (location != NULL, -1);
168 
169 	for (i = 0, l = list; l != NULL; i++, l = l->next) {
170 		bookmark = NEMO_BOOKMARK (l->data);
171 
172 		tmp = nemo_bookmark_get_location (bookmark);
173 		if (g_file_equal (location, tmp)) {
174 			g_object_unref (tmp);
175 			return i;
176 		}
177 		g_object_unref (tmp);
178 	}
179 
180 	return -1;
181 }
182 
183 static void
nemo_window_pane_hide_temporary_bars(NemoWindowPane * pane)184 nemo_window_pane_hide_temporary_bars (NemoWindowPane *pane)
185 {
186 	NemoWindowSlot *slot;
187 	NemoDirectory *directory;
188 
189 	slot = pane->active_slot;
190 
191 	if (pane->temporary_navigation_bar) {
192 		directory = nemo_directory_get (slot->location);
193 
194 		pane->temporary_navigation_bar = FALSE;
195 
196 		/* if we're in a search directory, hide the main bar, and show the search
197 		 * bar again; otherwise, just hide the whole toolbar.
198 		 */
199 		if (NEMO_IS_SEARCH_DIRECTORY (directory)) {
200 			nemo_toolbar_set_show_main_bar (NEMO_TOOLBAR (pane->tool_bar), FALSE);
201 		} else {
202 			gtk_widget_hide (pane->tool_bar);
203 		}
204 
205 		nemo_directory_unref (directory);
206 	}
207 }
208 
209 static void
location_entry_changed_cb(NemoToolbar * toolbar,gboolean val,gpointer data)210 location_entry_changed_cb (NemoToolbar *toolbar, gboolean val, gpointer data)
211 {
212     NemoWindowPane *pane = NEMO_WINDOW_PANE (data);
213     nemo_window_pane_ensure_location_bar (pane);
214 }
215 
216 static void
navigation_bar_cancel_callback(GtkWidget * widget,NemoWindowPane * pane)217 navigation_bar_cancel_callback (GtkWidget *widget,
218 				NemoWindowPane *pane)
219 {
220 	GtkAction *location;
221 
222 	location = gtk_action_group_get_action (pane->action_group,
223 					      NEMO_ACTION_TOGGLE_LOCATION);
224 	gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (location), FALSE);
225 
226 	nemo_window_pane_hide_temporary_bars (pane);
227 	restore_focus_widget (pane);
228 }
229 
230 static void
navigation_bar_location_changed_callback(GtkWidget * widget,GFile * location,NemoWindowPane * pane)231 navigation_bar_location_changed_callback (GtkWidget *widget,
232                                           GFile *location,
233                                           NemoWindowPane *pane)
234 {
235     nemo_window_pane_hide_temporary_bars (pane);
236 
237     restore_focus_widget (pane);
238 
239     nemo_window_slot_open_location (pane->active_slot, location, 0);
240 }
241 
242 static gboolean
toolbar_focus_in_callback(GtkWidget * widget,GdkEventFocus * event,gpointer user_data)243 toolbar_focus_in_callback (GtkWidget *widget,
244 			   GdkEventFocus *event,
245 			   gpointer user_data)
246 {
247 	NemoWindowPane *pane = user_data;
248 	nemo_window_set_active_pane (pane->window, pane);
249 
250 	return FALSE;
251 }
252 
253 static void
path_bar_location_changed_callback(GtkWidget * widget,GFile * location,NemoWindowPane * pane)254 path_bar_location_changed_callback (GtkWidget *widget,
255 				    GFile *location,
256 				    NemoWindowPane *pane)
257 {
258 	NemoWindowSlot *slot;
259 	int i;
260 
261 	slot = pane->active_slot;
262 	nemo_window_set_active_pane (pane->window, pane);
263 
264 	/* check whether we already visited the target location */
265 	i = bookmark_list_get_uri_index (slot->back_list, location);
266 	if (i >= 0) {
267 		nemo_window_back_or_forward (pane->window, TRUE, i, 0);
268 	} else {
269 		nemo_window_slot_open_location (pane->active_slot, location, 0);
270 	}
271 }
272 
273 static gboolean
path_bar_button_pressed_callback(GtkWidget * widget,GdkEventButton * event,NemoWindowPane * pane)274 path_bar_button_pressed_callback (GtkWidget *widget,
275 				  GdkEventButton *event,
276 				  NemoWindowPane *pane)
277 {
278 	NemoWindowSlot *slot;
279 	NemoView *view;
280 	GFile *location;
281 	char *uri;
282 
283 	g_object_set_data (G_OBJECT (widget), "handle-button-release",
284 			   GINT_TO_POINTER (TRUE));
285 
286 	if (event->button == 3) {
287 		slot = nemo_window_get_active_slot (pane->window);
288 		view = slot->content_view;
289 		if (view != NULL) {
290 			location = nemo_path_bar_get_path_for_button (
291 				NEMO_PATH_BAR (pane->path_bar), widget);
292 			if (location != NULL) {
293 				uri = g_file_get_uri (location);
294 				nemo_view_pop_up_location_context_menu (
295 					view, event, uri);
296 				g_object_unref (location);
297 				g_free (uri);
298 				return TRUE;
299 			}
300 		}
301 	}
302 
303     if (event->button == 2)
304         return TRUE;
305 
306     return FALSE;
307 }
308 
309 static gboolean
path_bar_button_released_callback(GtkWidget * widget,GdkEventButton * event,NemoWindowPane * pane)310 path_bar_button_released_callback (GtkWidget *widget,
311 				   GdkEventButton *event,
312 				   NemoWindowPane *pane)
313 {
314 	NemoWindowSlot *slot;
315 	NemoWindowOpenFlags flags;
316 	GFile *location;
317 	int mask;
318 	gboolean handle_button_release;
319 
320 	mask = event->state & gtk_accelerator_get_default_mod_mask ();
321 	flags = 0;
322 
323 	handle_button_release = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (widget),
324 						  "handle-button-release"));
325 
326 	if (event->type == GDK_BUTTON_RELEASE && handle_button_release) {
327 		location = nemo_path_bar_get_path_for_button (NEMO_PATH_BAR (pane->path_bar), widget);
328 
329 		if (event->button == 2 && mask == 0) {
330 			flags = NEMO_WINDOW_OPEN_FLAG_NEW_TAB;
331 		} else if (event->button == 1 && mask == GDK_CONTROL_MASK) {
332 			flags = NEMO_WINDOW_OPEN_FLAG_NEW_WINDOW;
333 		}
334 
335 		if (flags != 0) {
336 			slot = nemo_window_get_active_slot (pane->window);
337 			nemo_window_slot_open_location (slot, location, flags);
338 			g_object_unref (location);
339 			return TRUE;
340 		}
341 
342 		g_object_unref (location);
343 	}
344 
345 	return FALSE;
346 }
347 
348 static void
path_bar_button_drag_begin_callback(GtkWidget * widget,GdkEventButton * event,gpointer user_data)349 path_bar_button_drag_begin_callback (GtkWidget *widget,
350 				     GdkEventButton *event,
351 				     gpointer user_data)
352 {
353 	g_object_set_data (G_OBJECT (widget), "handle-button-release",
354 			   GINT_TO_POINTER (FALSE));
355 }
356 
357 static void
notebook_popup_menu_new_tab_cb(GtkMenuItem * menuitem,gpointer user_data)358 notebook_popup_menu_new_tab_cb (GtkMenuItem *menuitem,
359 				gpointer user_data)
360 {
361 	NemoWindowPane *pane;
362 
363 	pane = user_data;
364 	nemo_window_new_tab (pane->window);
365 }
366 
367 static void
path_bar_path_set_callback(GtkWidget * widget,GFile * location,NemoWindowPane * pane)368 path_bar_path_set_callback (GtkWidget *widget,
369 			    GFile *location,
370 			    NemoWindowPane *pane)
371 {
372 	GList *children, *l;
373 	GtkWidget *child;
374 
375 	children = gtk_container_get_children (GTK_CONTAINER (widget));
376 
377 	for (l = children; l != NULL; l = l->next) {
378 		child = GTK_WIDGET (l->data);
379 
380 		if (!GTK_IS_TOGGLE_BUTTON (child)) {
381 			continue;
382 		}
383 
384 		if (!g_signal_handler_find (child,
385 					    G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA,
386 					    0, 0, NULL,
387 					    path_bar_button_pressed_callback,
388 					    pane)) {
389 			g_signal_connect (child, "button-press-event",
390 					  G_CALLBACK (path_bar_button_pressed_callback),
391 					  pane);
392 			g_signal_connect (child, "button-release-event",
393 					  G_CALLBACK (path_bar_button_released_callback),
394 					  pane);
395 			g_signal_connect (child, "drag-begin",
396 					  G_CALLBACK (path_bar_button_drag_begin_callback),
397 					  pane);
398 		}
399 	}
400 
401 	g_list_free (children);
402 }
403 
404 static void
reorder_tab(NemoWindowPane * pane,int offset)405 reorder_tab (NemoWindowPane *pane, int offset)
406 {
407 	int num_target_tab;
408 
409 	g_return_if_fail (pane != NULL);
410 
411 	num_target_tab = GPOINTER_TO_INT (
412 		g_object_get_data (G_OBJECT (pane), "num_target_tab"));
413 	nemo_notebook_reorder_child_relative (
414 		NEMO_NOTEBOOK (pane->notebook), num_target_tab, offset);
415 }
416 
417 static void
notebook_popup_menu_move_left_cb(GtkMenuItem * menuitem,gpointer user_data)418 notebook_popup_menu_move_left_cb (GtkMenuItem *menuitem,
419 				  gpointer user_data)
420 {
421 	reorder_tab (NEMO_WINDOW_PANE (user_data), -1);
422 }
423 
424 static void
notebook_popup_menu_move_right_cb(GtkMenuItem * menuitem,gpointer user_data)425 notebook_popup_menu_move_right_cb (GtkMenuItem *menuitem,
426 				   gpointer user_data)
427 {
428 	reorder_tab (NEMO_WINDOW_PANE (user_data), 1);
429 }
430 
431 /* emitted when the user clicks the "close" button of tabs */
432 static void
notebook_tab_close_requested(NemoNotebook * notebook,NemoWindowSlot * slot,NemoWindowPane * pane)433 notebook_tab_close_requested (NemoNotebook *notebook,
434 			      NemoWindowSlot *slot,
435 			      NemoWindowPane *pane)
436 {
437 	nemo_window_pane_close_slot (pane, slot);
438 }
439 
440 static void
notebook_popup_menu_close_cb(GtkMenuItem * menuitem,gpointer user_data)441 notebook_popup_menu_close_cb (GtkMenuItem *menuitem,
442 			      gpointer user_data)
443 {
444 	NemoWindowPane *pane;
445 	NemoNotebook *notebook;
446 	int num_target_tab;
447 	GtkWidget *page;
448 
449 	pane = NEMO_WINDOW_PANE (user_data);
450 	g_return_if_fail (pane != NULL);
451 	notebook = NEMO_NOTEBOOK (pane->notebook);
452 	num_target_tab = GPOINTER_TO_INT (
453 		g_object_get_data (G_OBJECT (pane), "num_target_tab"));
454 	page = gtk_notebook_get_nth_page (
455 		GTK_NOTEBOOK (notebook), num_target_tab);
456 	notebook_tab_close_requested (
457 		notebook, NEMO_WINDOW_SLOT (page), pane);
458 }
459 
460 static void
notebook_popup_menu_show(NemoWindowPane * pane,GdkEventButton * event,int num_target_tab)461 notebook_popup_menu_show (NemoWindowPane *pane,
462 			  GdkEventButton *event,
463 			  int 	 	  num_target_tab)
464 {
465 	GtkWidget *popup;
466 	GtkWidget *item;
467 	GtkWidget *image;
468 	int button, event_time;
469 	gboolean can_move_left, can_move_right;
470 	NemoNotebook *notebook;
471 
472 	notebook = NEMO_NOTEBOOK (pane->notebook);
473 
474 	can_move_left = nemo_notebook_can_reorder_child_relative (
475 		notebook, num_target_tab, -1);
476 	can_move_right = nemo_notebook_can_reorder_child_relative (
477 		notebook, num_target_tab, 1);
478 
479 	popup = gtk_menu_new();
480 
481 	item = gtk_menu_item_new_with_mnemonic (_("_New Tab"));
482 	g_signal_connect (item, "activate",
483 			  G_CALLBACK (notebook_popup_menu_new_tab_cb),
484 			  pane);
485 	gtk_menu_shell_append (GTK_MENU_SHELL (popup),
486 			       item);
487 
488 	gtk_menu_shell_append (GTK_MENU_SHELL (popup),
489 			       gtk_separator_menu_item_new ());
490 
491 	/* Store the target tab index in the pane object so we don't have to
492 	 * wrap user data in a custom struct which may leak if none of the
493 	 * callbacks which would free it again is invoked.
494 	 */
495 	g_object_set_data (G_OBJECT (pane), "num_target_tab",
496 			   GINT_TO_POINTER (num_target_tab));
497 
498 	item = gtk_menu_item_new_with_mnemonic (_("Move Tab _Left"));
499 	g_signal_connect (item, "activate",
500 			  G_CALLBACK (notebook_popup_menu_move_left_cb),
501 			  pane);
502 	gtk_menu_shell_append (GTK_MENU_SHELL (popup),
503 			       item);
504 	gtk_widget_set_sensitive (item, can_move_left);
505 
506 	item = gtk_menu_item_new_with_mnemonic (_("Move Tab _Right"));
507 	g_signal_connect (item, "activate",
508 			  G_CALLBACK (notebook_popup_menu_move_right_cb),
509 			  pane);
510 	gtk_menu_shell_append (GTK_MENU_SHELL (popup),
511 			       item);
512 	gtk_widget_set_sensitive (item, can_move_right);
513 
514 	gtk_menu_shell_append (GTK_MENU_SHELL (popup),
515 			       gtk_separator_menu_item_new ());
516 
517 	item = gtk_image_menu_item_new_with_mnemonic (_("_Close Tab"));
518 	image = gtk_image_new_from_stock (GTK_STOCK_CLOSE, GTK_ICON_SIZE_MENU);
519 	gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item), image);
520 	g_signal_connect (item, "activate",
521 			  G_CALLBACK (notebook_popup_menu_close_cb), pane);
522 	gtk_menu_shell_append (GTK_MENU_SHELL (popup),
523 			       item);
524 
525 	gtk_widget_show_all (popup);
526 
527 	if (event) {
528 		button = event->button;
529 		event_time = event->time;
530 	} else {
531 		button = 0;
532 		event_time = gtk_get_current_event_time ();
533 	}
534 
535 	/* TODO is this correct? */
536 	gtk_menu_attach_to_widget (GTK_MENU (popup),
537 				   pane->notebook,
538 				   NULL);
539 
540 	gtk_menu_popup (GTK_MENU (popup), NULL, NULL, NULL, NULL,
541 			button, event_time);
542 }
543 
544 static gboolean
notebook_button_press_cb(GtkWidget * widget,GdkEventButton * event,gpointer user_data)545 notebook_button_press_cb (GtkWidget *widget,
546                           GdkEventButton *event,
547                           gpointer user_data)
548 {
549 	NemoWindowPane *pane;
550 	NemoNotebook *notebook;
551 	int tab_clicked;
552 
553 	if (event->type != GDK_BUTTON_PRESS)
554 		return FALSE;
555 
556 	/* Not a button event we actually care about, so just bail */
557 	if (event->button != 1 && event->button != 2 && event->button != 3)
558 		return FALSE;
559 
560 	pane = NEMO_WINDOW_PANE (user_data);
561 	notebook = NEMO_NOTEBOOK (pane->notebook);
562 	tab_clicked = nemo_notebook_find_tab_num_at_pos (
563 		notebook, event->x_root, event->y_root);
564 
565 	/* Do not change the current page on middle-click events. Close the
566 	 * clicked tab instead.
567 	 */
568 	if (event->button == 2) {
569 		if (tab_clicked != -1) {
570 			GtkWidget *page = gtk_notebook_get_nth_page (
571 				GTK_NOTEBOOK (notebook), tab_clicked);
572 			notebook_tab_close_requested (
573 				notebook, NEMO_WINDOW_SLOT (page), pane);
574 		}
575 	} else {
576 		if (event->button == 3) {
577 			notebook_popup_menu_show (pane, event, tab_clicked);
578 		} else {
579 			gtk_notebook_set_current_page (GTK_NOTEBOOK (notebook),
580 						       tab_clicked);
581 		}
582 	}
583 
584 	return FALSE;
585 }
586 
587 static gboolean
notebook_popup_menu_cb(GtkWidget * widget,gpointer user_data)588 notebook_popup_menu_cb (GtkWidget *widget,
589 			gpointer user_data)
590 {
591 	NemoWindowPane *pane;
592 	int page_num;
593 
594 	pane = NEMO_WINDOW_PANE (user_data);
595 	page_num = gtk_notebook_get_current_page (
596 		GTK_NOTEBOOK (pane->notebook));
597 	if (page_num == -1)
598 	       return FALSE;
599 	notebook_popup_menu_show (pane, NULL, page_num);
600 	return TRUE;
601 }
602 
603 static gboolean
notebook_switch_page_cb(GtkNotebook * notebook,GtkWidget * page,unsigned int page_num,NemoWindowPane * pane)604 notebook_switch_page_cb (GtkNotebook *notebook,
605 			 GtkWidget *page,
606 			 unsigned int page_num,
607 			 NemoWindowPane *pane)
608 {
609 	NemoWindowSlot *slot;
610 	GtkWidget *widget;
611 
612 	widget = gtk_notebook_get_nth_page (GTK_NOTEBOOK (pane->notebook), page_num);
613 	g_assert (widget != NULL);
614 
615 	/* find slot corresponding to the target page */
616 	slot = NEMO_WINDOW_SLOT (widget);
617 	g_assert (slot != NULL);
618 
619 	nemo_window_set_active_slot (nemo_window_slot_get_window (slot),
620 					 slot);
621 
622 	return FALSE;
623 }
624 
625 static void
notebook_page_removed_cb(GtkNotebook * notebook,GtkWidget * page,guint page_num,gpointer user_data)626 notebook_page_removed_cb (GtkNotebook *notebook,
627 			  GtkWidget *page,
628 			  guint page_num,
629 			  gpointer user_data)
630 {
631 	NemoWindowPane *pane = user_data;
632 	NemoWindowSlot *slot = NEMO_WINDOW_SLOT (page), *next_slot;
633 	gboolean dnd_slot;
634 
635 	dnd_slot = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (slot), "dnd-window-slot"));
636 	if (!dnd_slot) {
637 		return;
638 	}
639 
640 	if (pane->active_slot == slot) {
641 		next_slot = get_next_or_previous_slot (pane);
642 		nemo_window_set_active_slot (pane->window, next_slot);
643 	}
644 
645 	nemo_window_manage_views_close_slot (slot);
646 	pane->slots = g_list_remove (pane->slots, slot);
647 }
648 
649 static void
notebook_page_added_cb(GtkNotebook * notebook,GtkWidget * page,guint page_num,gpointer user_data)650 notebook_page_added_cb (GtkNotebook *notebook,
651 			GtkWidget *page,
652 			guint page_num,
653 			gpointer user_data)
654 {
655 	NemoWindowPane *pane;
656 	NemoWindowSlot *slot;
657 	NemoWindowSlot *dummy_slot;
658 	gboolean dnd_slot;
659 
660 	pane = NEMO_WINDOW_PANE (user_data);
661 	slot = NEMO_WINDOW_SLOT (page);
662 
663 	//Slot has been dropped onto another pane (new window or tab bar of other window)
664 	//So reassociate the pane if needed.
665 	if (slot->pane != pane) {
666 		slot->pane->slots = g_list_remove (slot->pane->slots, slot);
667 		slot->pane = pane;
668 		pane->slots = g_list_append (pane->slots, slot);
669 		g_signal_emit_by_name (slot, "changed-pane");
670 		nemo_window_set_active_slot (nemo_window_slot_get_window (slot), slot);
671 	}
672 
673 	dnd_slot = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (slot), "dnd-window-slot"));
674 
675 	if (!dnd_slot) {
676 		//Slot does not come from dnd window creation.
677 		return;
678 	}
679 
680 	g_object_set_data (G_OBJECT (page), "dnd-window-slot",
681 		   GINT_TO_POINTER (FALSE));
682 
683 	dummy_slot = g_list_nth_data (pane->slots, 0);
684 	if (dummy_slot != NULL) {
685 		nemo_window_pane_remove_slot_unsafe (
686 			dummy_slot->pane, dummy_slot);
687 	}
688 
689 	gtk_widget_show (GTK_WIDGET (pane));
690 	gtk_widget_show (GTK_WIDGET (pane->window));
691 }
692 
693 static GtkNotebook *
notebook_create_window_cb(GtkNotebook * notebook,GtkWidget * page,gint x,gint y,gpointer user_data)694 notebook_create_window_cb (GtkNotebook *notebook,
695 			   GtkWidget *page,
696 			   gint x,
697 			   gint y,
698 			   gpointer user_data)
699 {
700 	NemoApplication *app;
701 	NemoWindow *new_window;
702 	NemoWindowPane *new_pane;
703 	NemoWindowSlot *slot;
704 
705 	if (!NEMO_IS_WINDOW_SLOT (page)) {
706 		return NULL;
707 	}
708 
709 	app = NEMO_APPLICATION (g_application_get_default ());
710 	new_window = nemo_application_create_window
711 		(app, gtk_widget_get_screen (GTK_WIDGET (notebook)));
712 
713 	slot = NEMO_WINDOW_SLOT (page);
714 	g_object_set_data (G_OBJECT (slot), "dnd-window-slot",
715 			   GINT_TO_POINTER (TRUE));
716 
717 	gtk_window_set_position (GTK_WINDOW (new_window), GTK_WIN_POS_MOUSE);
718 
719 	new_pane = nemo_window_get_active_pane (new_window);
720 	return GTK_NOTEBOOK (new_pane->notebook);
721 }
722 
723 static void
action_show_hide_search_callback(GtkAction * action,gpointer user_data)724 action_show_hide_search_callback (GtkAction *action,
725 				  gpointer user_data)
726 {
727 	NemoWindowPane *pane = user_data;
728 	NemoWindow *window = pane->window;
729 	NemoWindowSlot *slot;
730 
731 	slot = pane->active_slot;
732 
733 	if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action))) {
734 	    remember_focus_widget (pane);
735 	    nemo_window_slot_set_query_editor_visible (slot, TRUE);
736 	} else {
737 		/* Do nothing if the query editor is not visible to begin with,
738 		   i.e. if toggle action was due to switching from a search tab */
739 		if (nemo_query_editor_get_active (NEMO_QUERY_EDITOR (slot->query_editor))) {
740 			GFile *location = NULL;
741 
742 			restore_focus_widget (pane);
743 
744 			if (slot->query_editor != NULL) {
745                 /* If closing the search bar, restore the original location */
746                 location = g_file_new_for_uri (nemo_query_editor_get_base_uri (slot->query_editor));
747 
748 				/* Last try: use the home directory as the return location */
749 				if (location == NULL) {
750 					location = g_file_new_for_path (g_get_home_dir ());
751 				}
752 
753 				nemo_window_go_to (window, location);
754 				g_object_unref (location);
755 			}
756 
757 			nemo_window_slot_set_query_editor_visible (slot, FALSE);
758 		}
759 	}
760 }
761 
762 static void
setup_search_action(NemoWindowPane * pane)763 setup_search_action (NemoWindowPane *pane)
764 {
765 	GtkActionGroup *group = pane->action_group;
766 	GtkAction *action;
767 
768 	action = gtk_action_group_get_action (group, NEMO_ACTION_SEARCH);
769 	g_signal_connect (action, "activate",
770 			  G_CALLBACK (action_show_hide_search_callback), pane);
771 }
772 
773 static void
toolbar_action_group_activated_callback(GtkActionGroup * action_group,GtkAction * action,gpointer user_data)774 toolbar_action_group_activated_callback (GtkActionGroup *action_group,
775 					 GtkAction *action,
776 					 gpointer user_data)
777 {
778 	NemoWindowPane *pane = user_data;
779 	nemo_window_set_active_pane (pane->window, pane);
780 }
781 
782 static void
nemo_window_pane_set_property(GObject * object,guint arg_id,const GValue * value,GParamSpec * pspec)783 nemo_window_pane_set_property (GObject *object,
784 				   guint arg_id,
785 				   const GValue *value,
786 				   GParamSpec *pspec)
787 {
788 	NemoWindowPane *self = NEMO_WINDOW_PANE (object);
789 
790 	switch (arg_id) {
791 	case PROP_WINDOW:
792 		self->window = g_value_get_object (value);
793 		break;
794 	default:
795 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, arg_id, pspec);
796 		break;
797 	}
798 }
799 
800 static void
nemo_window_pane_get_property(GObject * object,guint arg_id,GValue * value,GParamSpec * pspec)801 nemo_window_pane_get_property (GObject *object,
802 				   guint arg_id,
803 				   GValue *value,
804 				   GParamSpec *pspec)
805 {
806 	NemoWindowPane *self = NEMO_WINDOW_PANE (object);
807 
808 	switch (arg_id) {
809 	case PROP_WINDOW:
810 		g_value_set_object (value, self->window);
811 		break;
812 	default:
813 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, arg_id, pspec);
814 		break;
815 	}
816 }
817 
818 static void
nemo_window_pane_dispose(GObject * object)819 nemo_window_pane_dispose (GObject *object)
820 {
821 	NemoWindowPane *pane = NEMO_WINDOW_PANE (object);
822 
823 	unset_focus_widget (pane);
824 
825 	pane->window = NULL;
826 	g_clear_object (&pane->action_group);
827 
828 	g_assert (pane->slots == NULL);
829 
830 	G_OBJECT_CLASS (nemo_window_pane_parent_class)->dispose (object);
831 }
832 
833 gboolean
only_show_active_pane_toolbar_mapping(GValue * value,GVariant * variant,gpointer user_data)834 only_show_active_pane_toolbar_mapping (GValue *value,
835                                        GVariant *variant,
836                                        gpointer user_data)
837 {
838     NemoWindowPane *pane = user_data;
839 
840     if (nemo_window_disable_chrome_mapping (value,
841                                             variant,
842                                             pane->window)) {
843         gboolean chrome_allowed = g_value_get_boolean (value);
844         gboolean self_is_active = (pane == nemo_window_get_active_pane (pane->window));
845 
846         g_value_set_boolean (value, chrome_allowed && self_is_active);
847     }
848 
849     return TRUE;
850 }
851 
852 static void
nemo_window_pane_constructed(GObject * obj)853 nemo_window_pane_constructed (GObject *obj)
854 {
855 	NemoWindowPane *pane = NEMO_WINDOW_PANE (obj);
856 	GtkSizeGroup *header_size_group;
857 	NemoWindow *window;
858 	GtkActionGroup *action_group;
859 
860 	G_OBJECT_CLASS (nemo_window_pane_parent_class)->constructed (obj);
861 
862 	window = pane->window;
863 
864 	header_size_group = gtk_size_group_new (GTK_SIZE_GROUP_VERTICAL);
865 	gtk_size_group_set_ignore_hidden (header_size_group, FALSE);
866 
867 	/* build the toolbar */
868 	action_group = nemo_window_create_toolbar_action_group (window);
869 	pane->toolbar_action_group = action_group;
870 	pane->tool_bar = GTK_WIDGET (nemo_toolbar_new (action_group));
871 
872     g_signal_connect_object (pane->tool_bar, "notify::show-location-entry",
873                              G_CALLBACK (location_entry_changed_cb),
874                              pane, 0);
875 
876 	pane->action_group = action_group;
877 
878     if (!NEMO_IS_DESKTOP_WINDOW (window))
879         setup_search_action (pane);
880 
881 	g_signal_connect (pane->action_group, "pre-activate",
882 			  G_CALLBACK (toolbar_action_group_activated_callback), pane);
883 
884 	/* Pack to windows hbox (under the menu */
885 	gtk_box_pack_start (GTK_BOX (window->details->toolbar_holder),
886 			    pane->tool_bar,
887 			    TRUE, TRUE, 0);
888 
889 	/* start as non-active */
890 	nemo_window_pane_set_active (pane, FALSE);
891 
892 	g_settings_bind_with_mapping (nemo_window_state,
893 				      NEMO_WINDOW_STATE_START_WITH_TOOLBAR,
894 				      pane->tool_bar,
895 				      "visible",
896 				      G_SETTINGS_BIND_GET,
897 				      only_show_active_pane_toolbar_mapping, NULL,
898 				      pane, NULL);
899 
900 	/* connect to the pathbar signals */
901 	pane->path_bar = nemo_toolbar_get_path_bar (NEMO_TOOLBAR (pane->tool_bar));
902 	gtk_size_group_add_widget (header_size_group, pane->path_bar);
903 
904 	g_signal_connect_object (pane->path_bar, "path-clicked",
905 				 G_CALLBACK (path_bar_location_changed_callback), pane, 0);
906 	g_signal_connect_object (pane->path_bar, "path-set",
907 				 G_CALLBACK (path_bar_path_set_callback), pane, 0);
908 
909 	/* connect to the location bar signals */
910 	pane->location_bar = nemo_toolbar_get_location_bar (NEMO_TOOLBAR (pane->tool_bar));
911 	gtk_size_group_add_widget (header_size_group, pane->location_bar);
912 
913 	nemo_clipboard_set_up_editable
914 		(GTK_EDITABLE (nemo_location_bar_get_entry (NEMO_LOCATION_BAR (pane->location_bar))),
915 		 nemo_window_get_ui_manager (NEMO_WINDOW (window)),
916 		 TRUE);
917 
918 	g_signal_connect_object (pane->location_bar, "location-changed",
919 				 G_CALLBACK (navigation_bar_location_changed_callback), pane, 0);
920 	g_signal_connect_object (pane->location_bar, "cancel",
921 				 G_CALLBACK (navigation_bar_cancel_callback), pane, 0);
922 	g_signal_connect_object (nemo_location_bar_get_entry (NEMO_LOCATION_BAR (pane->location_bar)), "focus-in-event",
923 				 G_CALLBACK (toolbar_focus_in_callback), pane, 0);
924 
925 	/* initialize the notebook */
926 	pane->notebook = g_object_new (NEMO_TYPE_NOTEBOOK, NULL);
927 	gtk_box_pack_start (GTK_BOX (pane), pane->notebook,
928 			    TRUE, TRUE, 0);
929 	g_signal_connect (pane->notebook,
930 			  "tab-close-request",
931 			  G_CALLBACK (notebook_tab_close_requested),
932 			  pane);
933 	g_signal_connect_after (pane->notebook,
934 				"button_press_event",
935 				G_CALLBACK (notebook_button_press_cb),
936 				pane);
937 	g_signal_connect (pane->notebook, "popup-menu",
938 			  G_CALLBACK (notebook_popup_menu_cb),
939 			  pane);
940 	g_signal_connect (pane->notebook,
941 			  "switch-page",
942 			  G_CALLBACK (notebook_switch_page_cb),
943 			  pane);
944 	g_signal_connect (pane->notebook, "create-window",
945 			  G_CALLBACK (notebook_create_window_cb),
946 			  pane);
947 	g_signal_connect (pane->notebook, "page-added",
948 			  G_CALLBACK (notebook_page_added_cb),
949 			  pane);
950 	g_signal_connect (pane->notebook, "page-removed",
951 			  G_CALLBACK (notebook_page_removed_cb),
952 			  pane);
953 
954 	gtk_notebook_set_show_tabs (GTK_NOTEBOOK (pane->notebook), FALSE);
955 	gtk_notebook_set_show_border (GTK_NOTEBOOK (pane->notebook), FALSE);
956 	gtk_notebook_set_group_name (GTK_NOTEBOOK (pane->notebook), "nemo-slots");
957 	gtk_widget_show (pane->notebook);
958 	gtk_container_set_border_width (GTK_CONTAINER (pane->notebook), 0);
959 
960 	/* Ensure that the view has some minimal size and that other parts
961 	 * of the UI (like location bar and tabs) don't request more and
962 	 * thus affect the default position of the split view paned.
963 	 */
964 	gtk_widget_set_size_request (GTK_WIDGET (pane), 60, 60);
965 
966 	/*
967 	 * If we're on the desktop we need to make sure the toolbar can never show
968 	 */
969 	if (NEMO_IS_DESKTOP_WINDOW(window)) {
970 		gtk_widget_hide (GTK_WIDGET (window->details->toolbar_holder));
971 	}
972 
973 	/* we can unref the size group now */
974 	g_object_unref (header_size_group);
975 }
976 
977 static void
nemo_window_pane_class_init(NemoWindowPaneClass * klass)978 nemo_window_pane_class_init (NemoWindowPaneClass *klass)
979 {
980 	GObjectClass *oclass = G_OBJECT_CLASS (klass);
981 
982 	oclass->constructed = nemo_window_pane_constructed;
983 	oclass->dispose = nemo_window_pane_dispose;
984 	oclass->set_property = nemo_window_pane_set_property;
985 	oclass->get_property = nemo_window_pane_get_property;
986 
987 	properties[PROP_WINDOW] =
988 		g_param_spec_object ("window",
989 				     "The NemoWindow",
990 				     "The parent NemoWindow",
991 				     NEMO_TYPE_WINDOW,
992 				     G_PARAM_READWRITE |
993 				     G_PARAM_CONSTRUCT_ONLY |
994 				     G_PARAM_STATIC_STRINGS);
995 
996 	g_object_class_install_properties (oclass, NUM_PROPERTIES, properties);
997 }
998 
999 static void
nemo_window_pane_init(NemoWindowPane * pane)1000 nemo_window_pane_init (NemoWindowPane *pane)
1001 {
1002 	pane->slots = NULL;
1003 	pane->active_slot = NULL;
1004 
1005 	gtk_orientable_set_orientation (GTK_ORIENTABLE (pane), GTK_ORIENTATION_VERTICAL);
1006 
1007 	GtkStyleContext *context;
1008 
1009 	context = gtk_widget_get_style_context (GTK_WIDGET (pane));
1010 	gtk_style_context_add_class (context, "nemo-window-pane");
1011 }
1012 
1013 NemoWindowPane *
nemo_window_pane_new(NemoWindow * window)1014 nemo_window_pane_new (NemoWindow *window)
1015 {
1016 	return g_object_new (NEMO_TYPE_WINDOW_PANE,
1017 			     "window", window,
1018 			     NULL);
1019 }
1020 
1021 static void
nemo_window_pane_set_active_style(NemoWindowPane * pane,gboolean is_active)1022 nemo_window_pane_set_active_style (NemoWindowPane *pane,
1023 				       gboolean is_active)
1024 {
1025 	GtkStyleContext *style;
1026 	gboolean has_inactive;
1027 
1028 	style = gtk_widget_get_style_context (GTK_WIDGET (pane));
1029 	has_inactive = gtk_style_context_has_class (style, "nemo-inactive-pane");
1030 
1031 	if (has_inactive == !is_active) {
1032 		return;
1033 	}
1034 
1035 	if (is_active) {
1036 		gtk_style_context_remove_class (style, "nemo-inactive-pane");
1037 	} else {
1038 		gtk_style_context_add_class (style, "nemo-inactive-pane");
1039 	}
1040 
1041 	gtk_widget_reset_style (GTK_WIDGET (pane));
1042 }
1043 
1044 void
nemo_window_pane_set_active(NemoWindowPane * pane,gboolean is_active)1045 nemo_window_pane_set_active (NemoWindowPane *pane,
1046 				 gboolean is_active)
1047 {
1048 	NemoNavigationState *nav_state;
1049 
1050 	if (is_active) {
1051 		nav_state = nemo_window_get_navigation_state (pane->window);
1052 		nemo_navigation_state_set_master (nav_state, pane->action_group);
1053 	}
1054 	/* pane inactive style */
1055 	nemo_window_pane_set_active_style (pane, is_active);
1056 }
1057 
1058 GtkActionGroup *
nemo_window_pane_get_toolbar_action_group(NemoWindowPane * pane)1059 nemo_window_pane_get_toolbar_action_group (NemoWindowPane *pane)
1060 {
1061 	g_return_val_if_fail (NEMO_IS_WINDOW_PANE (pane), NULL);
1062 
1063 	return pane->toolbar_action_group;
1064 }
1065 
1066 void
nemo_window_pane_sync_location_widgets(NemoWindowPane * pane)1067 nemo_window_pane_sync_location_widgets (NemoWindowPane *pane)
1068 {
1069 	NemoWindowSlot *slot, *active_slot;
1070 	NemoNavigationState *nav_state;
1071 	slot = pane->active_slot;
1072 
1073 	nemo_window_pane_hide_temporary_bars (pane);
1074 
1075 	/* Change the location bar and path bar to match the current location. */
1076 	if (slot->location != NULL) {
1077 		char *uri;
1078 
1079 		/* this may be NULL if we just created the slot */
1080 		uri = nemo_window_slot_get_location_uri (slot);
1081 		nemo_location_bar_set_location (NEMO_LOCATION_BAR (pane->location_bar), uri);
1082 		g_free (uri);
1083 		nemo_path_bar_set_path (NEMO_PATH_BAR (pane->path_bar), slot->location);
1084         restore_focus_widget (pane);
1085 	}
1086 
1087 	/* Update window global UI if this is the active pane */
1088 	if (pane == nemo_window_get_active_pane (pane->window)) {
1089 		nemo_window_sync_up_button (pane->window);
1090 
1091 		/* Check if the back and forward buttons need enabling or disabling. */
1092 		active_slot = nemo_window_get_active_slot (pane->window);
1093 		nav_state = nemo_window_get_navigation_state (pane->window);
1094 
1095 		nemo_navigation_state_set_boolean (nav_state,
1096 						       NEMO_ACTION_BACK,
1097 						       active_slot->back_list != NULL);
1098 		nemo_navigation_state_set_boolean (nav_state,
1099 						       NEMO_ACTION_FORWARD,
1100 						       active_slot->forward_list != NULL);
1101 
1102 	}
1103 }
1104 
1105 static void
toggle_toolbar_search_button(NemoWindowPane * pane,gboolean active)1106 toggle_toolbar_search_button (NemoWindowPane *pane,
1107                                   gboolean        active)
1108 {
1109 	GtkActionGroup *group;
1110 	GtkAction *action;
1111 
1112 	group = pane->action_group;
1113 	action = gtk_action_group_get_action (group, NEMO_ACTION_SEARCH);
1114 
1115 	gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), active);
1116 }
1117 
1118 void
nemo_window_pane_sync_search_widgets(NemoWindowPane * pane)1119 nemo_window_pane_sync_search_widgets (NemoWindowPane *pane)
1120 {
1121 	NemoWindowSlot *slot;
1122 	NemoDirectory *directory;
1123 	NemoSearchDirectory *search_directory;
1124 
1125 	slot = pane->active_slot;
1126 	search_directory = NULL;
1127 
1128 	directory = nemo_directory_get (slot->location);
1129 	if (NEMO_IS_SEARCH_DIRECTORY (directory)) {
1130 		search_directory = NEMO_SEARCH_DIRECTORY (directory);
1131 	}
1132 
1133 	if (search_directory != NULL) {
1134 		toggle_toolbar_search_button (pane, TRUE);
1135 	} else  {
1136 		/* If we're not in a search directory, make sure the query editor visibility matches the
1137 		   search button due to a quirk when switching tabs. TODO: Another approach would be to
1138 		   leave the editor visible and toggle the search button true. Which is better? */
1139 		if (nemo_query_editor_get_active (NEMO_QUERY_EDITOR (slot->query_editor))) {
1140 			nemo_window_slot_set_query_editor_visible (slot, FALSE);
1141 		}
1142 	    	toggle_toolbar_search_button (pane, FALSE);
1143 	}
1144 
1145 	nemo_directory_unref (directory);
1146 }
1147 
1148 void
nemo_window_pane_close_slot(NemoWindowPane * pane,NemoWindowSlot * slot)1149 nemo_window_pane_close_slot (NemoWindowPane *pane,
1150 				 NemoWindowSlot *slot)
1151 {
1152 	NemoWindow *window;
1153 
1154 	DEBUG ("Requesting to remove slot %p from pane %p", slot, pane);
1155 
1156 	window = pane->window;
1157 	if (!window)
1158 		return;
1159 
1160 	if (pane->active_slot == slot) {
1161 		NemoWindowSlot *next_slot;
1162 		next_slot = get_next_or_previous_slot (NEMO_WINDOW_PANE (pane));
1163 		nemo_window_set_active_slot (window, next_slot);
1164 	}
1165 
1166 	nemo_window_pane_remove_slot_unsafe (pane, slot);
1167 
1168 	/* If that was the last slot in the pane, close the pane or even the
1169 	 * whole window.
1170 	 */
1171 	if (pane->slots == NULL) {
1172 		if (nemo_window_split_view_showing (window)) {
1173 			NemoWindowPane *new_pane;
1174 
1175 			DEBUG ("Last slot removed from the pane %p, closing it", pane);
1176 			nemo_window_close_pane (window, pane);
1177 
1178 			new_pane = g_list_nth_data (window->details->panes, 0);
1179 
1180 			if (new_pane->active_slot == NULL) {
1181 				new_pane->active_slot = get_next_or_previous_slot (new_pane);
1182 			}
1183 
1184 			DEBUG ("Calling set_active_pane, new slot %p", new_pane->active_slot);
1185 			nemo_window_set_active_pane (window, new_pane);
1186 			nemo_window_update_show_hide_menu_items (window);
1187 		} else {
1188 			DEBUG ("Last slot removed from the last pane, close the window");
1189 			nemo_window_close (window);
1190 		}
1191 	}
1192 }
1193 
1194 void
nemo_window_pane_grab_focus(NemoWindowPane * pane)1195 nemo_window_pane_grab_focus (NemoWindowPane *pane)
1196 {
1197 	if (NEMO_IS_WINDOW_PANE (pane) && pane->active_slot) {
1198 		nemo_view_grab_focus (pane->active_slot->content_view);
1199 	}
1200 }
1201 
1202 void
nemo_window_pane_ensure_location_bar(NemoWindowPane * pane)1203 nemo_window_pane_ensure_location_bar (NemoWindowPane *pane)
1204 {
1205     gboolean show_location, use_temp_toolbars;
1206 
1207     use_temp_toolbars = !g_settings_get_boolean (nemo_window_state,
1208                      NEMO_WINDOW_STATE_START_WITH_TOOLBAR);
1209     show_location = nemo_toolbar_get_show_location_entry (NEMO_TOOLBAR (pane->tool_bar));
1210 
1211     if (use_temp_toolbars) {
1212         if (!pane->temporary_navigation_bar) {
1213             gtk_widget_show (pane->tool_bar);
1214             pane->temporary_navigation_bar = TRUE;
1215         }
1216     }
1217     if (show_location) {
1218         remember_focus_widget (pane);
1219         nemo_location_bar_activate (NEMO_LOCATION_BAR (pane->location_bar));
1220     } else {
1221         restore_focus_widget (pane);
1222     }
1223 }
1224 
1225 void
nemo_window_pane_remove_slot_unsafe(NemoWindowPane * pane,NemoWindowSlot * slot)1226 nemo_window_pane_remove_slot_unsafe (NemoWindowPane *pane,
1227 				     NemoWindowSlot *slot)
1228 {
1229 	int page_num;
1230 	GtkNotebook *notebook;
1231 
1232 	g_assert (NEMO_IS_WINDOW_SLOT (slot));
1233 	g_assert (NEMO_IS_WINDOW_PANE (slot->pane));
1234 
1235 	DEBUG ("Removing slot %p", slot);
1236 
1237 	/* save pane because slot is not valid anymore after this call */
1238 	pane = slot->pane;
1239 	notebook = GTK_NOTEBOOK (pane->notebook);
1240 
1241 	nemo_window_manage_views_close_slot (slot);
1242 
1243 	page_num = gtk_notebook_page_num (notebook, GTK_WIDGET (slot));
1244 	g_assert (page_num >= 0);
1245 
1246 	g_signal_handlers_block_by_func (notebook,
1247 					 G_CALLBACK (notebook_switch_page_cb),
1248 					 pane);
1249 	/* this will call gtk_widget_destroy on the slot */
1250 	gtk_notebook_remove_page (notebook, page_num);
1251 	g_signal_handlers_unblock_by_func (notebook,
1252 					   G_CALLBACK (notebook_switch_page_cb),
1253 					   pane);
1254 
1255 	gtk_notebook_set_show_tabs (notebook,
1256 				    gtk_notebook_get_n_pages (notebook) > 1);
1257 	pane->slots = g_list_remove (pane->slots, slot);
1258 }
1259 
1260 NemoWindowSlot *
nemo_window_pane_open_slot(NemoWindowPane * pane,NemoWindowOpenSlotFlags flags)1261 nemo_window_pane_open_slot (NemoWindowPane *pane,
1262 				NemoWindowOpenSlotFlags flags)
1263 {
1264 	NemoWindowSlot *slot;
1265 
1266 	g_assert (NEMO_IS_WINDOW_PANE (pane));
1267 	g_assert (NEMO_IS_WINDOW (pane->window));
1268 
1269 	slot = nemo_window_slot_new (pane);
1270 
1271 	g_signal_handlers_block_by_func (pane->notebook,
1272 					 G_CALLBACK (notebook_switch_page_cb),
1273 					 pane);
1274 	nemo_notebook_add_tab (NEMO_NOTEBOOK (pane->notebook),
1275 				   slot,
1276 				   (flags & NEMO_WINDOW_OPEN_SLOT_APPEND) != 0 ?
1277 				   -1 :
1278 				   gtk_notebook_get_current_page (GTK_NOTEBOOK (pane->notebook)) + 1,
1279 				   FALSE);
1280 	g_signal_handlers_unblock_by_func (pane->notebook,
1281 					   G_CALLBACK (notebook_switch_page_cb),
1282 					   pane);
1283 
1284 	pane->slots = g_list_append (pane->slots, slot);
1285 
1286 	return slot;
1287 }
1288