diff --git a/terminal/terminal-preferences.c b/terminal/terminal-preferences.c index 9c50922..0fc0fb1 100644 --- a/terminal/terminal-preferences.c +++ b/terminal/terminal-preferences.c @@ -59,6 +59,7 @@ enum PROP_ACCEL_SET_TITLE, PROP_ACCEL_RESET, PROP_ACCEL_RESET_AND_CLEAR, + PROP_ACCEL_COPY_INPUT_TO_TABS, PROP_ACCEL_PREV_TAB, PROP_ACCEL_NEXT_TAB, PROP_ACCEL_SWITCH_TO_TAB1, @@ -478,6 +479,17 @@ terminal_preferences_class_init (TerminalPreferencesClass *klass) EXO_PARAM_READWRITE)); /** + * TerminalPreferences:accel-copy-input-to-tabs: + **/ + g_object_class_install_property (gobject_class, + PROP_ACCEL_COPY_INPUT_TO_TABS, + g_param_spec_string ("accel-copy-input-to-tabs", + _("Copy Input to Tabs"), + "AccelCopyInputToTabs", + NULL, + EXO_PARAM_READWRITE)); + + /** * TerminalPreferences:accel-prev-tab: **/ g_object_class_install_property (gobject_class, diff --git a/terminal/terminal-screen.c b/terminal/terminal-screen.c index 6b0f016..f2ded89 100644 --- a/terminal/terminal-screen.c +++ b/terminal/terminal-screen.c @@ -105,6 +105,10 @@ static void terminal_screen_vte_child_exited (VteTerminal TerminalScreen *screen); static void terminal_screen_vte_eof (VteTerminal *terminal, TerminalScreen *screen); +static void terminal_screen_vte_commit (VteTerminal *terminal, + const gchar *text, + guint length, + TerminalScreen *screen); static GtkWidget *terminal_screen_vte_get_context_menu (TerminalWidget *widget, TerminalScreen *screen); static void terminal_screen_vte_selection_changed (VteTerminal *terminal, @@ -138,7 +142,9 @@ struct _TerminalScreen gchar **custom_command; gchar *custom_title; - gboolean hold; + guint hold : 1; + + gulong commit_handler; guint background_timer_id; guint launch_idle_id; @@ -149,7 +155,8 @@ struct _TerminalScreen -static guint screen_signals[LAST_SIGNAL]; +static guint screen_signals[LAST_SIGNAL]; +static GSList *screens = NULL; @@ -223,8 +230,9 @@ static void terminal_screen_init (TerminalScreen *screen) { screen->working_directory = g_get_current_dir (); - screen->terminal = g_object_new (TERMINAL_TYPE_WIDGET, NULL); + screens = g_slist_prepend (screens, screen); + g_object_connect (G_OBJECT (screen->terminal), "signal::child-exited", G_CALLBACK (terminal_screen_vte_child_exited), screen, "signal::eof", G_CALLBACK (terminal_screen_vte_eof), screen, @@ -317,6 +325,8 @@ terminal_screen_finalize (GObject *object) { TerminalScreen *screen = TERMINAL_SCREEN (object); + screens = g_slist_remove (screens, screen); + if (G_UNLIKELY (screen->background_timer_id != 0)) g_source_remove (screen->background_timer_id); @@ -345,6 +355,7 @@ terminal_screen_get_property (GObject *object, const gchar *title = NULL; TerminalTitle mode; gchar *initial = NULL; + gchar *copy_input; switch (prop_id) { @@ -375,7 +386,21 @@ terminal_screen_get_property (GObject *object, title = vte_terminal_get_window_title (VTE_TERMINAL (screen->terminal)); } } - g_value_set_string (value, title != NULL ? title : _("Untitled")); + + if (G_UNLIKELY (title == NULL)) + title = _("Untitled"); + + if (screen->commit_handler != 0) + { + /* TRANSLATORS: this word is shown before the terminal title when + * 'Copy Input to Tabs' is enabled */ + copy_input = g_strdup_printf ("[%s] %s", _("Copy"), title); + g_value_take_string (value, copy_input); + } + else + { + g_value_set_string (value, title); + } g_free (initial); break; @@ -889,6 +914,41 @@ terminal_screen_vte_eof (VteTerminal *terminal, +static void +terminal_screen_vte_commit (VteTerminal *terminal, + const gchar *text, + guint length, + TerminalScreen *screen) +{ + GSList *li; + TerminalScreen *other; + GtkWidget *toplevel; + + terminal_return_if_fail (TERMINAL_IS_SCREEN (screen)); + terminal_return_if_fail (VTE_TERMINAL (screen->terminal) == terminal); + + toplevel = gtk_widget_get_toplevel (GTK_WIDGET (screen)); + + for (li = screens; li != NULL; li = li->next) + { + other = TERMINAL_SCREEN (li->data); + + /* send the input to all other tabs in this window, except for the + * tab emitting the events */ + if (other != screen && gtk_widget_get_toplevel (GTK_WIDGET (other)) == toplevel) + { + /* block commits on the other tab and send the input */ + if (other->commit_handler != 0) + g_signal_handler_block (G_OBJECT (other->terminal), other->commit_handler); + vte_terminal_feed_child (VTE_TERMINAL (other->terminal), text, length); + if (other->commit_handler != 0) + g_signal_handler_unblock (G_OBJECT (other->terminal), other->commit_handler); + } + } +} + + + static GtkWidget* terminal_screen_vte_get_context_menu (TerminalWidget *widget, TerminalScreen *screen) @@ -1515,6 +1575,61 @@ terminal_screen_set_hold (TerminalScreen *screen, /** + * terminal_screen_get_copy_input: + * @screen : A #TerminalScreen. + * + * Checks whether the terminal screen is copying its input to + * other screen with the same toplevel window (ie. all tabs in this + * window). + * + * Return value: %TRUE if @screen copying is enabled + **/ +gboolean +terminal_screen_get_copy_input (TerminalScreen *screen) +{ + terminal_return_val_if_fail (TERMINAL_IS_SCREEN (screen), FALSE); + return (screen->commit_handler != 0); +} + + + +/** + * terminal_screen_set_copy_input: + * @screen : A #TerminalScreen. + * @copy_input : %TRUE to enable copy for this screen, + * %FALSE to deactivate it. + * + * Whether this screen will listen to user input and send it + * to other screen with the same toplevel. + **/ +void +terminal_screen_set_copy_input (TerminalScreen *screen, + gboolean copy_input) +{ + terminal_return_if_fail (TERMINAL_IS_SCREEN (screen)); + + if (G_UNLIKELY ((screen->commit_handler != 0) == copy_input)) + return; + + if (screen->commit_handler != 0) + { + g_signal_handler_disconnect (G_OBJECT (screen->terminal), screen->commit_handler); + screen->commit_handler = 0; + } + else + { + screen->commit_handler = g_signal_connect (G_OBJECT (screen->terminal), "commit", + G_CALLBACK (terminal_screen_vte_commit), + screen); + } + + /* change the title */ + g_object_notify (G_OBJECT (screen), "title"); +} + + + +/** * terminal_screen_has_selection: * @screen : A #TerminalScreen. * diff --git a/terminal/terminal-screen.h b/terminal/terminal-screen.h index 1b0a9af..4eb9532 100644 --- a/terminal/terminal-screen.h +++ b/terminal/terminal-screen.h @@ -70,6 +70,10 @@ gboolean terminal_screen_get_hold (TerminalScreen *scree void terminal_screen_set_hold (TerminalScreen *screen, gboolean hold); +gboolean terminal_screen_get_copy_input (TerminalScreen *screen); +void terminal_screen_set_copy_input (TerminalScreen *screen, + gboolean clone); + gboolean terminal_screen_has_selection (TerminalScreen *screen); void terminal_screen_copy_clipboard (TerminalScreen *screen); diff --git a/terminal/terminal-shortcut-editor.c b/terminal/terminal-shortcut-editor.c index be3766a..702a61e 100644 --- a/terminal/terminal-shortcut-editor.c +++ b/terminal/terminal-shortcut-editor.c @@ -122,6 +122,7 @@ static const ToplevelMenu toplevel_menus[] = "accel-set-title", "accel-reset", "accel-reset-and-clear", + "accel-copy-input-to-tabs", NULL, }, }, diff --git a/terminal/terminal-window-ui.xml b/terminal/terminal-window-ui.xml index 33491aa..d9ed13c 100644 --- a/terminal/terminal-window-ui.xml +++ b/terminal/terminal-window-ui.xml @@ -37,6 +37,7 @@ +