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