Index: configure.in.in =================================================================== --- configure.in.in (revision 26399) +++ configure.in.in (working copy) @@ -82,7 +82,7 @@ dnl *** Check for required packages *** dnl *********************************** XDT_CHECK_PACKAGE([EXO], [exo-0.3], [0.3.2]) -XDT_CHECK_PACKAGE([GTK], [gtk+-2.0], [2.6.0]) +XDT_CHECK_PACKAGE([GTK], [gtk+-2.0], [2.10.0]) XDT_CHECK_PACKAGE([VTE], [vte], [0.11.11]) dnl ************************************************* Index: terminal/terminal-screen.c =================================================================== --- terminal/terminal-screen.c (revision 26399) +++ terminal/terminal-screen.c (working copy) @@ -373,7 +373,7 @@ static void terminal_screen_realize (GtkWidget *widget) { -#if GTK_CHECK_VERSION(2,10,0) && defined(HAVE_VTE_TERMINAL_SET_OPACITY) +#ifdef HAVE_VTE_TERMINAL_SET_OPACITY GdkScreen *screen; #endif @@ -383,7 +383,7 @@ if (!GTK_WIDGET_REALIZED (TERMINAL_SCREEN (widget)->terminal)) gtk_widget_realize (TERMINAL_SCREEN (widget)->terminal); -#if GTK_CHECK_VERSION(2,10,0) && defined(HAVE_VTE_TERMINAL_SET_OPACITY) +#ifdef HAVE_VTE_TERMINAL_SET_OPACITY /* connect to the "composited-changed" signal */ screen = gtk_widget_get_screen (widget); g_signal_connect_swapped (G_OBJECT (screen), "composited-changed", G_CALLBACK (terminal_screen_update_background), widget); @@ -395,7 +395,7 @@ static void terminal_screen_unrealize (GtkWidget *widget) { -#if GTK_CHECK_VERSION(2,10,0) && defined(HAVE_VTE_TERMINAL_SET_OPACITY) +#ifdef HAVE_VTE_TERMINAL_SET_OPACITY GdkScreen *screen; /* disconnect the "composited-changed" handler */ @@ -854,6 +854,11 @@ GdkPixbuf *image; gdouble background_darkness; + _terminal_return_val_if_fail (TERMINAL_IS_SCREEN (screen), FALSE); + _terminal_return_val_if_fail (VTE_IS_TERMINAL (screen->terminal), FALSE); + + GDK_THREADS_ENTER (); + g_object_get (G_OBJECT (screen->preferences), "background-mode", &background_mode, NULL); if (background_mode == TERMINAL_BACKGROUND_SOLID) @@ -861,7 +866,7 @@ vte_terminal_set_background_image (VTE_TERMINAL (screen->terminal), NULL); vte_terminal_set_background_saturation (VTE_TERMINAL (screen->terminal), 1.0); vte_terminal_set_background_transparent (VTE_TERMINAL (screen->terminal), FALSE); -#if GTK_CHECK_VERSION(2,10,0) && defined(HAVE_VTE_TERMINAL_SET_OPACITY) +#ifdef HAVE_VTE_TERMINAL_SET_OPACITY vte_terminal_set_opacity (VTE_TERMINAL (screen->terminal), 0xFFFF); #endif } @@ -875,7 +880,7 @@ screen->terminal->allocation.width, screen->terminal->allocation.height); vte_terminal_set_background_image (VTE_TERMINAL (screen->terminal), image); -#if GTK_CHECK_VERSION(2,10,0) && defined(HAVE_VTE_TERMINAL_SET_OPACITY) +#ifdef HAVE_VTE_TERMINAL_SET_OPACITY vte_terminal_set_opacity (VTE_TERMINAL (screen->terminal), 0xFFFF); #endif if (image != NULL) @@ -887,7 +892,7 @@ g_object_get (G_OBJECT (screen->preferences), "background-darkness", &background_darkness, NULL); vte_terminal_set_background_image (VTE_TERMINAL (screen->terminal), NULL); -#if GTK_CHECK_VERSION(2,10,0) && defined(HAVE_VTE_TERMINAL_SET_OPACITY) +#ifdef HAVE_VTE_TERMINAL_SET_OPACITY /* check if the X screen is composited */ if (gdk_screen_is_composited (gtk_widget_get_screen (user_data))) { @@ -900,12 +905,14 @@ #endif vte_terminal_set_background_saturation (VTE_TERMINAL (screen->terminal), 1.0 - background_darkness); vte_terminal_set_background_transparent (VTE_TERMINAL (screen->terminal), TRUE); -#if GTK_CHECK_VERSION(2,10,0) && defined(HAVE_VTE_TERMINAL_SET_OPACITY) +#ifdef HAVE_VTE_TERMINAL_SET_OPACITY vte_terminal_set_opacity (VTE_TERMINAL (screen->terminal), 0xFFFF); } #endif } + GDK_THREADS_LEAVE (); + return FALSE; } @@ -1071,12 +1078,11 @@ gint xpad; gint ypad; - gtk_widget_set_size_request (screen->terminal, 2000, 2000); gtk_widget_size_request (GTK_WIDGET (window), &window_requisition); gtk_widget_size_request (screen->terminal, &terminal_requisition); - width = window_requisition.width - terminal_requisition.width; - height = window_requisition.height - terminal_requisition.height; + width = MAX (window_requisition.width - terminal_requisition.width, 0); + height = MAX (window_requisition.height - terminal_requisition.height, 0); if (force_columns < 0) columns = VTE_TERMINAL (screen->terminal)->column_count; Index: terminal/terminal-marshal.list =================================================================== --- terminal/terminal-marshal.list (revision 26399) +++ terminal/terminal-marshal.list (working copy) @@ -1,2 +1,3 @@ OBJECT:VOID VOID:STRING,ENUM +VOID:OBJECT,INT,INT Index: terminal/terminal-widget.c =================================================================== --- terminal/terminal-widget.c (revision 26399) +++ terminal/terminal-widget.c (working copy) @@ -72,6 +72,7 @@ TARGET_TEXT_PLAIN, TARGET_MOZ_URL, TARGET_APPLICATION_X_COLOR, + TARGET_GTK_NOTEBOOK_TAB, }; @@ -132,6 +133,7 @@ { "STRING", 0, TARGET_STRING }, { "text/plain", 0, TARGET_TEXT_PLAIN }, { "application/x-color", 0, TARGET_APPLICATION_X_COLOR }, + { "GTK_NOTEBOOK_TAB", GTK_TARGET_SAME_APP, TARGET_GTK_NOTEBOOK_TAB }, }; @@ -185,7 +187,7 @@ GTK_DEST_DEFAULT_HIGHLIGHT | GTK_DEST_DEFAULT_DROP, targets, G_N_ELEMENTS (targets), - GDK_ACTION_COPY | GDK_ACTION_LINK); + GDK_ACTION_COPY | GDK_ACTION_LINK | GDK_ACTION_MOVE); /* monitor the misc-highlight-urls setting */ g_signal_connect_swapped (G_OBJECT (widget->preferences), "notify::misc-highlight-urls", @@ -437,6 +439,7 @@ gchar *text; gint argc; gint n; + GtkWidget *screen; switch (info) { @@ -564,7 +567,24 @@ g_value_unset (&value); } break; + + case TARGET_GTK_NOTEBOOK_TAB: + /* 'send' the drag to the parent widget (TerminalScreen) */ + screen = gtk_widget_get_parent (widget); + if (G_LIKELY (screen)) + { + g_signal_emit_by_name (G_OBJECT (screen), "drag-data-received", context, + x, y, selection_data, info, time); + } + break; + + default: + /* never finish the drag */ + return; } + + if (info != TARGET_GTK_NOTEBOOK_TAB) + gtk_drag_finish (context, TRUE, FALSE, time); } Index: terminal/terminal-tab-header.c =================================================================== --- terminal/terminal-tab-header.c (revision 26399) +++ terminal/terminal-tab-header.c (working copy) @@ -78,21 +78,8 @@ void (*set_title) (TerminalTabHeader *header); }; -struct _TerminalTabHeader -{ - GtkHBox __parent__; - TerminalPreferences *preferences; - GtkWidget *ebox; - GtkWidget *label; - - /* the popup menu */ - GtkWidget *menu; -}; - - - static guint header_signals[LAST_SIGNAL]; @@ -185,6 +172,8 @@ header->preferences = terminal_preferences_get (); + header->tab_pos_binding = NULL; + gtk_widget_push_composite_child (); header->ebox = g_object_new (GTK_TYPE_EVENT_BOX, "border-width", 2, NULL); Index: terminal/terminal-tab-header.h =================================================================== --- terminal/terminal-tab-header.h (revision 26399) +++ terminal/terminal-tab-header.h (working copy) @@ -36,6 +36,21 @@ typedef struct _TerminalTabHeaderClass TerminalTabHeaderClass; typedef struct _TerminalTabHeader TerminalTabHeader; +struct _TerminalTabHeader +{ + GtkHBox __parent__; + + TerminalPreferences *preferences; + + GtkWidget *ebox; + GtkWidget *label; + + /* the popup menu */ + GtkWidget *menu; + + ExoBinding *tab_pos_binding; +}; + GType terminal_tab_header_get_type (void) G_GNUC_CONST; GtkWidget *terminal_tab_header_new (void); Index: terminal/terminal-window.c =================================================================== --- terminal/terminal-window.c (revision 26399) +++ terminal/terminal-window.c (working copy) @@ -54,6 +54,7 @@ #include #include #include +#include #include #include #include @@ -100,16 +101,32 @@ static void terminal_window_page_notified (GtkNotebook *notebook, GParamSpec *pspec, TerminalWindow *window); -static void terminal_window_page_switched (GtkNotebook *notebook, +static void terminal_window_notebook_visibility (TerminalWindow *window); +static void terminal_window_page_reordered (GtkNotebook *notebook, GtkNotebookPage *page, guint page_num, TerminalWindow *window); -#if GTK_CHECK_VERSION (2,10,0) -static void terminal_window_page_reordered (GtkNotebook *notebook, - GtkNotebookPage *page, +static void terminal_window_page_added (GtkNotebook *notebook, + GtkWidget *child, guint page_num, TerminalWindow *window); -#endif +static void terminal_window_page_removed (GtkNotebook *notebook, + GtkWidget *child, + guint page_num, + TerminalWindow *window); +static void terminal_window_page_drag_data_received (GtkWidget *widget, + GdkDragContext *context, + gint x, + gint y, + GtkSelectionData *selection_data, + guint info, + guint time, + TerminalWindow *window); +static GtkNotebook *terminal_window_page_detach (GtkNotebook *notebook, + GtkWidget *child, + gint x, + gint y, + TerminalWindow *window); static GtkWidget *terminal_window_get_context_menu (TerminalScreen *screen, TerminalWindow *window); static void terminal_window_detach_screen (TerminalWindow *window, @@ -117,9 +134,6 @@ static void terminal_window_notify_title (TerminalScreen *screen, GParamSpec *pspec, TerminalWindow *window); -static void terminal_window_screen_removed (GtkNotebook *notebook, - TerminalScreen *screen, - TerminalWindow *window); static void terminal_window_action_new_tab (GtkAction *action, TerminalWindow *window); static void terminal_window_action_new_window (GtkAction *action, @@ -144,26 +158,26 @@ TerminalWindow *window); static void terminal_window_action_show_toolbars (GtkToggleAction *action, TerminalWindow *window); -static void terminal_window_action_show_borders (GtkToggleAction *action, - TerminalWindow *window); -static void terminal_window_action_fullscreen (GtkToggleAction *action, - TerminalWindow *window); -static void terminal_window_action_prev_tab (GtkAction *action, - TerminalWindow *window); -static void terminal_window_action_next_tab (GtkAction *action, - TerminalWindow *window); -static void terminal_window_action_set_title (GtkAction *action, - TerminalWindow *window); -static void terminal_window_action_reset (GtkAction *action, - TerminalWindow *window); -static void terminal_window_action_reset_and_clear (GtkAction *action, - TerminalWindow *window); -static void terminal_window_action_contents (GtkAction *action, - TerminalWindow *window); -static void terminal_window_action_report_bug (GtkAction *action, - TerminalWindow *window); -static void terminal_window_action_about (GtkAction *action, - TerminalWindow *window); +static void terminal_window_action_show_borders (GtkToggleAction *action, + TerminalWindow *window); +static void terminal_window_action_fullscreen (GtkToggleAction *action, + TerminalWindow *window); +static void terminal_window_action_prev_tab (GtkAction *action, + TerminalWindow *window); +static void terminal_window_action_next_tab (GtkAction *action, + TerminalWindow *window); +static void terminal_window_action_set_title (GtkAction *action, + TerminalWindow *window); +static void terminal_window_action_reset (GtkAction *action, + TerminalWindow *window); +static void terminal_window_action_reset_and_clear (GtkAction *action, + TerminalWindow *window); +static void terminal_window_action_contents (GtkAction *action, + TerminalWindow *window); +static void terminal_window_action_report_bug (GtkAction *action, + TerminalWindow *window); +static void terminal_window_action_about (GtkAction *action, + TerminalWindow *window); @@ -191,6 +205,9 @@ static guint window_signals[LAST_SIGNAL]; +#if GTK_CHECK_VERSION (2,12,0) +static gpointer window_notebook_group = "Terminal"; +#endif @@ -242,7 +259,7 @@ { GtkWidgetClass *gtkwidget_class; GObjectClass *gobject_class; - + gobject_class = G_OBJECT_CLASS (klass); gobject_class->dispose = terminal_window_dispose; gobject_class->finalize = terminal_window_finalize; @@ -269,12 +286,13 @@ window_signals[NEW_WINDOW_WITH_SCREEN] = g_signal_new (I_("new-window-with-screen"), G_TYPE_FROM_CLASS (gobject_class), - G_SIGNAL_RUN_LAST, + G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (TerminalWindowClass, new_window_with_screen), NULL, NULL, - g_cclosure_marshal_VOID__OBJECT, - G_TYPE_NONE, 1, - G_TYPE_OBJECT); + _terminal_marshal_VOID__OBJECT_INT_INT, + G_TYPE_NONE, 3, + G_TYPE_OBJECT, + G_TYPE_INT, G_TYPE_INT); } @@ -317,6 +335,7 @@ gtk_ui_manager_insert_action_group (window->ui_manager, window->action_group, 0); gtk_ui_manager_add_ui_from_string (window->ui_manager, terminal_window_ui, terminal_window_ui_length, NULL); + accel_group = gtk_ui_manager_get_accel_group (window->ui_manager); gtk_window_add_accel_group (GTK_WINDOW (window), accel_group); @@ -348,6 +367,7 @@ } } + /* setup mnemonics */ g_object_get (G_OBJECT (window->preferences), "shortcuts-no-mnemonics", &bval, NULL); if (G_UNLIKELY (bval)) @@ -375,16 +395,26 @@ "tab-vborder", 0, NULL); exo_binding_new (G_OBJECT (window->preferences), "misc-tab-position", G_OBJECT (window->notebook), "tab-pos"); - g_signal_connect_after (G_OBJECT (window->notebook), "switch-page", - G_CALLBACK (terminal_window_page_switched), window); + + /* set the notebook group id */ +#if GTK_CHECK_VERSION (2,12,0) + gtk_notebook_set_group (GTK_NOTEBOOK (window->notebook), window_notebook_group); +#else + gtk_notebook_set_group_id (GTK_NOTEBOOK (window->notebook), 1); +#endif + + /* signals */ g_signal_connect (G_OBJECT (window->notebook), "notify::page", G_CALLBACK (terminal_window_page_notified), window); - g_signal_connect (G_OBJECT (window->notebook), "remove", - G_CALLBACK (terminal_window_screen_removed), window); - -#if GTK_CHECK_VERSION (2,10,0) g_signal_connect (G_OBJECT (window->notebook), "page-reordered", G_CALLBACK (terminal_window_page_reordered), window); + g_signal_connect (G_OBJECT (window->notebook), "page-removed", + G_CALLBACK (terminal_window_page_removed), window); + g_signal_connect (G_OBJECT (window->notebook), "page-added", + G_CALLBACK (terminal_window_page_added), window); +#if GTK_CHECK_VERSION (2,12,0) + g_signal_connect (G_OBJECT (window->notebook), "create-window", + G_CALLBACK (terminal_window_page_detach), window); #endif gtk_box_pack_start (GTK_BOX (vbox), window->notebook, TRUE, TRUE, 0); @@ -591,7 +621,9 @@ TerminalScreen *active; gint grid_width; gint grid_height; - + + GDK_THREADS_ENTER (); + /* The trick is rather simple here. This is called before any Gtk+ resizing operation takes * place, so the columns/rows on the active terminal screen are still set to their old values. * We simply query these values and force them to be set with the new style. @@ -603,6 +635,8 @@ terminal_window_set_size_force_grid (window, active, grid_width, grid_height); } + GDK_THREADS_LEAVE (); + return FALSE; } @@ -826,7 +860,17 @@ static gboolean terminal_window_delete_event (TerminalWindow *window) { - return !terminal_window_confirm_close (window); + gboolean result; + + /* get close confirmation from the user */ + result = terminal_window_confirm_close (window); + + /* disconnect remove signal if we're closing the window */ + if (result) + g_signal_handlers_disconnect_by_func (G_OBJECT (window->notebook), + G_CALLBACK (terminal_window_page_removed), window); + + return !result; } @@ -853,55 +897,270 @@ static void -terminal_window_page_switched (GtkNotebook *notebook, - GtkNotebookPage *page, - guint page_num, - TerminalWindow *window) +terminal_window_notebook_visibility (TerminalWindow *window) { - TerminalScreen *terminal; - gint grid_width; - gint grid_height; + TerminalScreen *active; + gboolean always_show_tabs, tabs_shown; + gint npages; + gint grid_width, grid_height; - terminal = terminal_window_get_active (window); - if (G_LIKELY (terminal != NULL)) + /* check if we should always display tabs */ + g_object_get (G_OBJECT (window->preferences), "misc-always-show-tabs", &always_show_tabs, NULL); + + /* current notebook status */ + tabs_shown = gtk_notebook_get_show_tabs (GTK_NOTEBOOK (window->notebook)); + npages = gtk_notebook_get_n_pages (GTK_NOTEBOOK (window->notebook)); + + /* change the visibility if the new status differs */ + if (((npages > 1) != tabs_shown) || (always_show_tabs && !tabs_shown)) { - /* FIXME: This isn't really needed anymore, instead we - * could grab the grid size of the previously selected - * page and apply that to the newly selected page. - */ + /* get active screen */ + active = terminal_window_get_active (window); - /* This is a bit tricky, but seems to be necessary to get the - * sizing correct: First we query the current terminal size - * (rows x columns), then we force a size update on the terminal - * window (which may reset the terminal size). Afterwards we - * reset the terminal screen size to the original values and - * resize the terminal window accordingly. - */ - terminal_screen_get_size (terminal, &grid_width, &grid_height); - terminal_screen_set_size (terminal, grid_width, grid_height); - terminal_window_set_size_force_grid (window, terminal, grid_width, grid_height); + /* get screen grid size */ + terminal_screen_get_size (active, &grid_width, &grid_height); + + /* show or hide the tabs */ + gtk_notebook_set_show_tabs (GTK_NOTEBOOK (window->notebook), !tabs_shown); + + /* don't focus the notebook */ + GTK_WIDGET_UNSET_FLAGS (window->notebook, GTK_CAN_FOCUS); + + /* resize the window */ + terminal_screen_force_resize_window (active, GTK_WINDOW (window), grid_width, grid_height); } } -#if GTK_CHECK_VERSION (2,10,0) static void terminal_window_page_reordered (GtkNotebook *notebook, GtkNotebookPage *page, guint page_num, TerminalWindow *window) { - - /* Regenerate the "Go" menu. - * This also updates the accelerators. - */ + + /* Regenerate the "Go" menu */ terminal_window_rebuild_gomenu (window); } -#endif +static void +terminal_window_page_added (GtkNotebook *notebook, + GtkWidget *child, + guint page_num, + TerminalWindow *window) +{ + gint grid_width, grid_height; + GtkAction *action; + TerminalTabHeader *header; + TerminalScreen *active; + + _terminal_return_if_fail (TERMINAL_IS_SCREEN (child)); + _terminal_return_if_fail (TERMINAL_IS_WINDOW (window)); + + /* get tab header */ + header = g_object_get_data (G_OBJECT (child), I_("terminal-tab-header")); + + _terminal_return_if_fail (TERMINAL_IS_TAB_HEADER (header)); + + /* tab position binding */ + header->tab_pos_binding = exo_binding_new (G_OBJECT (window->notebook), "tab-pos", G_OBJECT (header), "tab-pos"); + + /* connect screen signals */ + g_signal_connect (G_OBJECT (child), "get-context-menu", G_CALLBACK (terminal_window_get_context_menu), window); + g_signal_connect (G_OBJECT (child), "notify::title", G_CALLBACK (terminal_window_notify_title), window); + g_signal_connect_swapped (G_OBJECT (child), "selection-changed", G_CALLBACK (terminal_window_update_actions), window); + g_signal_connect (G_OBJECT (child), "drag-data-received", G_CALLBACK (terminal_window_page_drag_data_received), window); + + /* get action from window action group */ + action = gtk_action_group_get_action (window->action_group, "set-title"); + + /* connect tab label signals */ + g_signal_connect_swapped (G_OBJECT (header), "detach-tab", G_CALLBACK (terminal_window_detach_screen), window); + g_signal_connect_swapped (G_OBJECT (header), "set-title", G_CALLBACK (gtk_action_activate), action); + + /* set visibility of the notebook */ + terminal_window_notebook_visibility (window); + + /* get the active tab */ + active = terminal_window_get_active (window); + if (G_LIKELY (active != NULL)) + { + /* set new screen grid size based on the old one */ + terminal_screen_get_size (active, &grid_width, &grid_height); + terminal_screen_set_size (TERMINAL_SCREEN (child), grid_width, grid_height); + } + else + { + /* set the window size (needed for resizing) */ + terminal_screen_get_size (TERMINAL_SCREEN (child), &grid_width, &grid_height); + terminal_window_set_size_force_grid (window, TERMINAL_SCREEN (child), grid_width, grid_height); + } + + /* regenerate the "Go" menu */ + terminal_window_rebuild_gomenu (window); + + /* update all screen sensitive actions (Copy, Prev Tab, ...) */ + terminal_window_update_actions (window); +} + + + +static void +terminal_window_page_removed (GtkNotebook *notebook, + GtkWidget *child, + guint page_num, + TerminalWindow *window) +{ + TerminalTabHeader *header; + GtkAction *action; + gint npages; + + _terminal_return_if_fail (TERMINAL_IS_SCREEN (child)); + _terminal_return_if_fail (TERMINAL_IS_WINDOW (window)); + _terminal_return_if_fail (header->tab_pos_binding != NULL); + + /* get header */ + header = g_object_get_data (G_OBJECT (child), I_("terminal-tab-header")); + + /* get old window action */ + action = gtk_action_group_get_action (window->action_group, "set-title"); + + /* disconnect signals */ + g_signal_handlers_disconnect_by_func (G_OBJECT (child), terminal_window_get_context_menu, window); + g_signal_handlers_disconnect_by_func (G_OBJECT (child), terminal_window_notify_title, window); + g_signal_handlers_disconnect_by_func (G_OBJECT (child), terminal_window_update_actions, window); + g_signal_handlers_disconnect_by_func (G_OBJECT (child), terminal_window_page_drag_data_received, window); + g_signal_handlers_disconnect_by_func (G_OBJECT (header), terminal_window_detach_screen, window); + g_signal_handlers_disconnect_by_func (G_OBJECT (header), gtk_action_activate, action); + + /* remove exo binding */ + exo_binding_unbind (header->tab_pos_binding); + + /* set tab visibility */ + npages = gtk_notebook_get_n_pages (GTK_NOTEBOOK (window->notebook)); + if (G_UNLIKELY (npages == 0)) + { + /* no tabs, destroy the window */ + gtk_widget_destroy (GTK_WIDGET (window)); + } + else + { + /* set visibility of the notebook */ + terminal_window_notebook_visibility (window); + + /* regenerate the "Go" menu */ + terminal_window_rebuild_gomenu (window); + + /* update all screen sensitive actions (Copy, Prev Tab, ...) */ + terminal_window_update_actions (window); + } +} + + + +static void +terminal_window_page_drag_data_received (GtkWidget *widget, + GdkDragContext *context, + gint x, + gint y, + GtkSelectionData *selection_data, + guint info, + guint time, + TerminalWindow *window) +{ + GtkWidget *source_widget; + GtkWidget **screen; + GtkWidget *child, *label; + gint i, n_pages; + + _terminal_return_if_fail (TERMINAL_IS_WINDOW (window)); + + /* get the source notebook (other window) */ + source_widget = gtk_drag_get_source_widget (context); + + /* get the dragged screen */ + screen = (GtkWidget **) selection_data->data; + + /* check */ + if (source_widget && TERMINAL_IS_SCREEN (*screen)) + { + /* take a reference */ + g_object_ref (G_OBJECT (*screen)); + + /* remove the document from the source notebook */ + gtk_container_remove (GTK_CONTAINER (source_widget), *screen); + + /* get the number of pages in the new window */ + n_pages = gtk_notebook_get_n_pages (GTK_NOTEBOOK (window->notebook)); + + /* figure out where to insert the tab in the notebook */ + for (i = 0; i < n_pages; i++) + { + /* get the child label */ + child = gtk_notebook_get_nth_page (GTK_NOTEBOOK (window->notebook), i); + label = gtk_notebook_get_tab_label (GTK_NOTEBOOK (window->notebook), child); + + /* break if we have a matching drop position */ + if (x < (label->allocation.x + label->allocation.width / 2)) + break; + } + + /* add the screen to the new window */ + terminal_window_add (window, TERMINAL_SCREEN (*screen)); + + /* move the child to the correct position */ + gtk_notebook_reorder_child (GTK_NOTEBOOK (window->notebook), *screen, i); + + /* release reference */ + g_object_unref (G_OBJECT (*screen)); + + /* finish the drag */ + gtk_drag_finish (context, TRUE, TRUE, time); + } +} + + + +static GtkNotebook * +terminal_window_page_detach (GtkNotebook *notebook, + GtkWidget *child, + gint x, + gint y, + TerminalWindow *window) +{ + TerminalScreen *screen; + + _terminal_return_val_if_fail (TERMINAL_IS_WINDOW (window), NULL); + _terminal_return_val_if_fail (TERMINAL_IS_SCREEN (child), NULL); + _terminal_return_val_if_fail (notebook == GTK_NOTEBOOK (window->notebook), NULL); + + /* only create new window when there are more then 2 tabs (bug #2686) */ + if (gtk_notebook_get_n_pages (notebook) >= 2) + { + /* get the screen */ + screen = TERMINAL_SCREEN (child); + + /* take a reference */ + g_object_ref (G_OBJECT (screen)); + + /* remove screen from active window */ + gtk_container_remove (GTK_CONTAINER (window->notebook), child); + + /* create new window with the screen */ + g_signal_emit (G_OBJECT (window), window_signals[NEW_WINDOW_WITH_SCREEN], 0, screen, x, y); + + /* release our reference */ + g_object_unref (G_OBJECT (screen)); + } + + return NULL; +} + + + static GtkWidget* terminal_window_get_context_menu (TerminalScreen *screen, TerminalWindow *window) @@ -942,20 +1201,10 @@ { GtkWidget *screen; - /* verify that we have atleast two tabs, otherwise we'll crash, - * see http://bugzilla.xfce.org/show_bug.cgi?id=2686. - */ - if (gtk_notebook_get_n_pages (GTK_NOTEBOOK (window->notebook)) >= 2) - { - screen = g_object_get_data (G_OBJECT (header), "terminal-window-screen"); - if (G_LIKELY (screen != NULL)) - { - g_object_ref (G_OBJECT (screen)); - gtk_container_remove (GTK_CONTAINER (window->notebook), screen); - g_signal_emit (G_OBJECT (window), window_signals[NEW_WINDOW_WITH_SCREEN], 0, screen); - g_object_unref (G_OBJECT (screen)); - } - } + /* get the screen */ + screen = g_object_get_data (G_OBJECT (header), I_("terminal-window-screen")); + if (G_LIKELY (screen != NULL)) + terminal_window_page_detach (GTK_NOTEBOOK (window->notebook), screen, -1, -1, window); } @@ -981,50 +1230,6 @@ static void -terminal_window_screen_removed (GtkNotebook *notebook, - TerminalScreen *screen, - TerminalWindow *window) -{ - TerminalScreen *active; - gboolean always_show_tabs; - gint npages; - gint grid_width; - gint grid_height; - - npages = gtk_notebook_get_n_pages (GTK_NOTEBOOK (window->notebook)); - if (G_UNLIKELY (npages == 0)) - { - gtk_widget_destroy (GTK_WIDGET (window)); - } - else - { - /* check tabs should always be visible */ - g_object_get (G_OBJECT (window->preferences), "misc-always-show-tabs", &always_show_tabs, NULL); - - /* change the visibility of the tabs accordingly */ - gtk_notebook_set_show_tabs (GTK_NOTEBOOK (window->notebook), always_show_tabs || (npages > 1)); - - /* meh, Gtk+, who wants focus on the notebook? */ - GTK_WIDGET_UNSET_FLAGS (window->notebook, GTK_CAN_FOCUS); - - active = terminal_window_get_active (window); - if (G_LIKELY (active != NULL)) - { - terminal_screen_get_size (screen, &grid_width, &grid_height); - terminal_window_set_size_force_grid (window, active, grid_width, grid_height); - } - - /* regenerate the "Go" menu */ - terminal_window_rebuild_gomenu (window); - - /* update all screen sensitive actions (Copy, Prev Tab, ...) */ - terminal_window_update_actions (window); - } -} - - - -static void terminal_window_action_new_tab (GtkAction *action, TerminalWindow *window) { @@ -1071,14 +1276,11 @@ { TerminalScreen *terminal; + /* get active terminal window */ terminal = terminal_window_get_active (window); + if (G_LIKELY (terminal != NULL)) - { - g_object_ref (G_OBJECT (terminal)); - gtk_container_remove (GTK_CONTAINER (window->notebook), GTK_WIDGET (terminal)); - g_signal_emit (G_OBJECT (window), window_signals[NEW_WINDOW_WITH_SCREEN], 0, terminal); - g_object_unref (G_OBJECT (terminal)); - } + terminal_window_page_detach (GTK_NOTEBOOK (window->notebook), GTK_WIDGET (terminal), -1, -1, window); } @@ -1489,77 +1691,29 @@ terminal_window_add (TerminalWindow *window, TerminalScreen *screen) { - TerminalScreen *active; GtkWidget *header; - GtkAction *action; - gboolean always_show_tabs; - gint npages; gint page; - gint grid_width; - gint grid_height; _terminal_return_if_fail (TERMINAL_IS_WINDOW (window)); _terminal_return_if_fail (TERMINAL_IS_SCREEN (screen)); - active = terminal_window_get_active (window); - if (G_LIKELY (active != NULL)) - { - terminal_screen_get_size (active, &grid_width, &grid_height); - terminal_screen_set_size (screen, grid_width, grid_height); - } - - action = gtk_action_group_get_action (window->action_group, "set-title"); - header = terminal_tab_header_new (); exo_binding_new (G_OBJECT (screen), "title", G_OBJECT (header), "title"); - exo_binding_new (G_OBJECT (window->notebook), "tab-pos", G_OBJECT (header), "tab-pos"); g_signal_connect_swapped (G_OBJECT (header), "close-tab", G_CALLBACK (gtk_widget_destroy), screen); - g_signal_connect_swapped (G_OBJECT (header), "detach-tab", G_CALLBACK (terminal_window_detach_screen), window); - g_signal_connect_swapped (G_OBJECT (header), "set-title", G_CALLBACK (gtk_action_activate), action); g_object_set_data_full (G_OBJECT (header), I_("terminal-window-screen"), g_object_ref (G_OBJECT (screen)), (GDestroyNotify) g_object_unref); + g_object_set_data_full (G_OBJECT (screen), I_("terminal-tab-header"), g_object_ref (G_OBJECT (header)), (GDestroyNotify) g_object_unref); gtk_widget_show (header); - page = gtk_notebook_append_page (GTK_NOTEBOOK (window->notebook), - GTK_WIDGET (screen), header); - gtk_notebook_set_tab_label_packing (GTK_NOTEBOOK (window->notebook), - GTK_WIDGET (screen), - TRUE, TRUE, GTK_PACK_START); + page = gtk_notebook_append_page (GTK_NOTEBOOK (window->notebook), GTK_WIDGET (screen), header); + gtk_notebook_set_tab_label_packing (GTK_NOTEBOOK (window->notebook), GTK_WIDGET (screen), TRUE, TRUE, GTK_PACK_START); -#if GTK_CHECK_VERSION(2,10,0) - gtk_notebook_set_tab_reorderable (GTK_NOTEBOOK (window->notebook), - GTK_WIDGET (screen), - TRUE); -#endif + /* allow tab sorting and dnd */ + gtk_notebook_set_tab_reorderable (GTK_NOTEBOOK (window->notebook), GTK_WIDGET (screen), TRUE); + gtk_notebook_set_tab_detachable (GTK_NOTEBOOK (window->notebook), GTK_WIDGET (screen), TRUE); - /* check if we should always display tabs */ - g_object_get (G_OBJECT (window->preferences), "misc-always-show-tabs", &always_show_tabs, NULL); - - /* change the visibility of the tabs accordingly */ - npages = gtk_notebook_get_n_pages (GTK_NOTEBOOK (window->notebook)); - gtk_notebook_set_show_tabs (GTK_NOTEBOOK (window->notebook), always_show_tabs || (npages > 1)); - - /* yep, still no focus on the notebook! */ - GTK_WIDGET_UNSET_FLAGS (window->notebook, GTK_CAN_FOCUS); - - g_signal_connect (G_OBJECT (screen), "get-context-menu", - G_CALLBACK (terminal_window_get_context_menu), window); - g_signal_connect (G_OBJECT (screen), "notify::title", - G_CALLBACK (terminal_window_notify_title), window); - g_signal_connect_swapped (G_OBJECT (screen), "selection-changed", - G_CALLBACK (terminal_window_update_actions), window); - - terminal_window_rebuild_gomenu (window); - - /* need to save the grid size here for detached screens */ - terminal_screen_get_size (screen, &grid_width, &grid_height); - /* need to show this first, else we cannot switch to it */ gtk_widget_show (GTK_WIDGET (screen)); gtk_notebook_set_current_page (GTK_NOTEBOOK (window->notebook), page); - - terminal_window_set_size_force_grid (window, screen, grid_width, grid_height); - - gtk_widget_queue_draw (GTK_WIDGET (screen)); } Index: terminal/terminal-window.h =================================================================== --- terminal/terminal-window.h (revision 26399) +++ terminal/terminal-window.h (working copy) @@ -44,7 +44,9 @@ void (*new_window) (TerminalWindow *window, const gchar *working_directory); void (*new_window_with_screen) (TerminalWindow *window, - TerminalScreen *screen); + TerminalScreen *screen, + gint x, + gint y); }; GType terminal_window_get_type (void) G_GNUC_CONST; Index: terminal/terminal-app.c =================================================================== --- terminal/terminal-app.c (revision 26399) +++ terminal/terminal-app.c (working copy) @@ -60,6 +60,8 @@ TerminalApp *app); static void terminal_app_new_window_with_terminal (TerminalWindow *window, TerminalScreen *terminal, + gint x, + gint y, TerminalApp *app); static void terminal_app_window_destroyed (GtkWidget *window, TerminalApp *app); @@ -253,16 +255,26 @@ static void terminal_app_new_window_with_terminal (TerminalWindow *existing, TerminalScreen *terminal, + gint x, + gint y, TerminalApp *app) { GtkWidget *window; GdkScreen *screen; + + _terminal_return_if_fail (TERMINAL_IS_WINDOW (existing)); + _terminal_return_if_fail (TERMINAL_IS_SCREEN (terminal)); + _terminal_return_if_fail (TERMINAL_IS_APP (app)); window = terminal_app_create_window (app, FALSE, TERMINAL_VISIBILITY_DEFAULT, TERMINAL_VISIBILITY_DEFAULT, TERMINAL_VISIBILITY_DEFAULT); + /* set new window position */ + if (x > -1 && y > -1) + gtk_window_move (GTK_WINDOW (window), x, y); + /* place the new window on the same screen as * the existing window. */ @@ -347,9 +359,7 @@ terminal_app_find_screen (const gchar *display_name) { const gchar *other_name; -#if GTK_CHECK_VERSION(2,10,0) GdkColormap *colormap; -#endif GdkDisplay *display = NULL; GdkScreen *screen = NULL; GSList *displays; @@ -410,7 +420,6 @@ g_object_ref (G_OBJECT (screen)); } -#if GTK_CHECK_VERSION(2,10,0) /* check if we already checked this screen */ if (g_object_get_data (G_OBJECT (screen), "terminal-checked-screen") == NULL) { @@ -427,7 +436,6 @@ /* mark this screen as handled */ g_object_set_data (G_OBJECT (screen), I_("terminal-checked-screen"), GINT_TO_POINTER (1)); } -#endif return screen; }