Index: terminal/terminal-screen.c =================================================================== --- terminal/terminal-screen.c (revision 26875) +++ terminal/terminal-screen.c (working copy) @@ -44,6 +44,7 @@ #include #include #include +#include #if defined(GDK_WINDOWING_X11) #include @@ -56,6 +57,7 @@ PROP_0, PROP_CUSTOM_TITLE, PROP_TITLE, + PROP_ACTIVITY, }; enum @@ -107,6 +109,8 @@ TerminalScreen *screen); static void terminal_screen_vte_window_title_changed (VteTerminal *terminal, TerminalScreen *screen); +static void terminal_screen_vte_window_contents_changed (VteTerminal *terminal, + TerminalScreen *screen); static gboolean terminal_screen_timer_background (gpointer user_data); static void terminal_screen_timer_background_destroy (gpointer user_data); @@ -138,6 +142,9 @@ guint background_timer_id; guint launch_idle_id; + + gboolean activity; + guint reset_activity_cb; }; @@ -188,6 +195,17 @@ G_PARAM_READABLE)); /** + * TerminalScreen:activity: + **/ + g_object_class_install_property (gobject_class, + PROP_ACTIVITY, + g_param_spec_boolean ("activity", + "activity", + "activity", + FALSE, + G_PARAM_READWRITE)); + + /** * TerminalScreen::get-context-menu **/ screen_signals[GET_CONTEXT_MENU] = @@ -227,6 +245,7 @@ "signal::context-menu", G_CALLBACK (terminal_screen_vte_get_context_menu), screen, "signal::selection-changed", G_CALLBACK (terminal_screen_vte_selection_changed), screen, "signal::window-title-changed", G_CALLBACK (terminal_screen_vte_window_title_changed), screen, + "signal::contents-changed", G_CALLBACK (terminal_screen_vte_window_contents_changed), screen, "swapped-signal::size-allocate", G_CALLBACK (terminal_screen_timer_background), screen, "swapped-signal::style-set", G_CALLBACK (terminal_screen_update_colors), screen, NULL); @@ -340,6 +359,10 @@ g_value_take_string (value, terminal_screen_get_title (screen)); break; + case PROP_ACTIVITY: + g_value_set_boolean (value, screen->activity); + break; + default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -362,6 +385,10 @@ terminal_screen_set_custom_title (screen, g_value_get_string (value)); break; + case PROP_ACTIVITY: + screen->activity = g_value_get_boolean (value); + break; + default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -597,23 +624,7 @@ } } - - static void -query_color (TerminalPreferences *preferences, - const gchar *property, - GdkColor *color_return) -{ - gchar *spec; - - g_object_get (G_OBJECT (preferences), property, &spec, NULL); - gdk_color_parse (spec, color_return); - g_free (spec); -} - - - -static void terminal_screen_update_colors (TerminalScreen *screen) { GdkColor palette[16]; @@ -843,8 +854,39 @@ g_object_notify (G_OBJECT (screen), "title"); } +static gboolean terminal_screen_reset_activity(TerminalScreen *screen) +{ + screen->activity = FALSE; + screen->reset_activity_cb = 0; + g_object_notify (G_OBJECT (screen), "activity"); + return FALSE; +} +static void +terminal_screen_vte_window_contents_changed (VteTerminal *terminal, + TerminalScreen *screen) +{ + gdouble timeout_seconds = 2.0; + _terminal_return_if_fail (VTE_IS_TERMINAL (terminal)); + _terminal_return_if_fail (TERMINAL_IS_SCREEN (screen)); + + if (terminal_window_is_screen_active (screen)) + return; + + g_object_get (G_OBJECT (screen->preferences), "tab-activity-timeout", &timeout_seconds, NULL); + if (timeout_seconds < 1.0) + return; + + screen->activity = TRUE; + g_object_notify (G_OBJECT (screen), "activity"); + if (screen->reset_activity_cb != 0) { + g_source_remove(screen->reset_activity_cb); + } + screen->reset_activity_cb = g_timeout_add_seconds ((gint)timeout_seconds, + (GSourceFunc)terminal_screen_reset_activity, screen); +} + static gboolean terminal_screen_timer_background (gpointer user_data) { @@ -1232,8 +1274,6 @@ return title; } - - /** * terminal_screen_get_working_directory: * @screen : A #TerminalScreen. Index: terminal/terminal-tab-header.c =================================================================== --- terminal/terminal-tab-header.c (revision 26875) +++ terminal/terminal-tab-header.c (working copy) @@ -27,6 +27,7 @@ #include #include #include +#include @@ -35,6 +36,7 @@ PROP_0, PROP_TAB_POS, PROP_TITLE, + PROP_ACTIVITY, }; enum @@ -122,6 +124,17 @@ G_PARAM_READWRITE)); /** + * TerminalTabHeader:activity: + **/ + g_object_class_install_property (gobject_class, + PROP_ACTIVITY, + g_param_spec_boolean ("activity", + "activity", + "activity", + FALSE, + G_PARAM_READWRITE)); + + /** * TerminalTabHeader::close-tab: **/ header_signals[CLOSE_TAB] = @@ -237,6 +250,10 @@ g_object_get_property (G_OBJECT (header->label), "label", value); break; + case PROP_ACTIVITY: + g_object_get_property (G_OBJECT (header), "activity", value); + break; + default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -254,7 +271,9 @@ TerminalTabHeader *header = TERMINAL_TAB_HEADER (object); GtkPositionType position; const gchar *title; - + gboolean act = FALSE; + GdkColor act_color; + switch (prop_id) { case PROP_TAB_POS: @@ -285,6 +304,13 @@ gtk_label_set_text (GTK_LABEL (header->label), title); break; + case PROP_ACTIVITY: + act = g_value_get_boolean(value); + query_color (header->preferences, "tab-activity-color", &act_color); + /* strangely, inactive tab are in state ACTIVE */ + gtk_widget_modify_fg(header->label, GTK_STATE_ACTIVE, act ? &act_color:NULL); + break; + default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; Index: terminal/terminal-preferences-dialog.c =================================================================== --- terminal/terminal-preferences-dialog.c (revision 26875) +++ terminal/terminal-preferences-dialog.c (working copy) @@ -768,6 +768,52 @@ g_free (name); } + frame = g_object_new (GTK_TYPE_FRAME, "border-width", 0, "shadow-type", GTK_SHADOW_NONE, NULL); + gtk_box_pack_start (GTK_BOX (box), frame, FALSE, TRUE, 0); + gtk_widget_show (frame); + + label = g_object_new (GTK_TYPE_LABEL, "label", _("Tab activity"), "use-markup", TRUE, NULL); + gtk_frame_set_label_widget (GTK_FRAME (frame), label); + gtk_widget_show (label); + + table = gtk_table_new (2, 1, FALSE); + gtk_table_set_row_spacings (GTK_TABLE (table), 6); + gtk_table_set_col_spacings (GTK_TABLE (table), 12); + gtk_container_set_border_width (GTK_CONTAINER (table), 12); + gtk_container_add (GTK_CONTAINER (frame), table); + gtk_widget_show (table); + + label = g_object_new (GTK_TYPE_LABEL, + "label", _("T_ab activity color:"), + "use-underline", TRUE, + "xalign", 0.0, + NULL); + gtk_table_attach (GTK_TABLE (table), label, 0, 1, 0, 1, GTK_FILL, GTK_FILL, 0, 0); + gtk_widget_show (label); + + align = gtk_alignment_new (0.0, 0.5, 0.0, 0.0); + gtk_table_attach (GTK_TABLE (table), align, 1, 2, 0, 1, GTK_EXPAND | GTK_FILL, GTK_FILL, 0, 0); + gtk_widget_show (align); + + hbox = gtk_hbox_new (FALSE, 0); + gtk_container_add (GTK_CONTAINER (align), hbox); + gtk_widget_show (hbox); + + button = g_object_new (GTK_TYPE_COLOR_BUTTON, "title", _("Choose tab activity color"), NULL); + exo_mutual_binding_new (G_OBJECT (dialog->preferences), "tab-activity-color", G_OBJECT (button), "color"); + gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 0); + gtk_label_set_mnemonic_widget (GTK_LABEL (label), button); + gtk_widget_show (button); + + /* set Atk name/description and label relation for the button */ + object = gtk_widget_get_accessible (button); + atk_object_set_name (object, _("Color Selector")); + atk_object_set_description (object, _("Open a dialog to specify the color")); + relations = atk_object_ref_relation_set (gtk_widget_get_accessible (label)); + relation = atk_relation_new (&object, 1, ATK_RELATION_LABEL_FOR); + atk_relation_set_add (relations, relation); + g_object_unref (G_OBJECT (relation)); + icon = gtk_widget_render_icon (GTK_WIDGET (dialog->icon_bar), TERMINAL_STOCK_COLORS, GTK_ICON_SIZE_DIALOG, @@ -982,6 +1028,46 @@ /* set Atk label relation for the entry */ terminal_gtk_label_set_a11y_relation (GTK_LABEL (label), entry); +/* start */ + frame = g_object_new (GTK_TYPE_FRAME, "border-width", 0, "shadow-type", GTK_SHADOW_NONE, NULL); + gtk_box_pack_start (GTK_BOX (box), frame, FALSE, TRUE, 0); + gtk_widget_show (frame); + + label = g_object_new (GTK_TYPE_LABEL, "label", _("Tab activity indicator"), "use-markup", TRUE, NULL); + gtk_frame_set_label_widget (GTK_FRAME (frame), label); + gtk_widget_show (label); + + vbox = gtk_vbox_new (FALSE, 6); + gtk_container_set_border_width (GTK_CONTAINER (vbox), 12); + gtk_container_add (GTK_CONTAINER (frame), vbox); + gtk_widget_show (vbox); + + hbox = gtk_hbox_new (FALSE, 6); + gtk_container_set_border_width (GTK_CONTAINER (hbox), 0); + gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0); + gtk_widget_show (hbox); + + label = gtk_label_new (_("Reset tab activity indicator after")); + g_object_set (G_OBJECT (label), "wrap", TRUE, "xalign", 0.0, NULL); + gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0); + gtk_widget_show (label); + + button = gtk_spin_button_new_with_range (0.0, 30.0, 1.0); + gtk_spin_button_set_numeric(GTK_SPIN_BUTTON(button), TRUE); + exo_mutual_binding_new (G_OBJECT (dialog->preferences), "tab-activity-timeout", G_OBJECT (button), "value"); + gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 0); + gtk_label_set_mnemonic_widget (GTK_LABEL (label), button); + gtk_widget_show (button); + + /* set Atk label relation for the button */ + terminal_gtk_label_set_a11y_relation (GTK_LABEL (label), button); + + label = gtk_label_new (_("seconds")); + g_object_set (G_OBJECT (label), "wrap", TRUE, "xalign", 0.0, NULL); + gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0); + gtk_widget_show (label); + +/*end */ icon = gtk_widget_render_icon (GTK_WIDGET (dialog->icon_bar), TERMINAL_STOCK_ADVANCED, GTK_ICON_SIZE_DIALOG, Index: terminal/terminal-preferences.c =================================================================== --- terminal/terminal-preferences.c (revision 26875) +++ terminal/terminal-preferences.c (working copy) @@ -130,6 +130,8 @@ PROP_TERM, PROP_VTE_WORKAROUND_TITLE_BUG, PROP_WORD_CHARS, + PROP_TAB_ACTIVITY_COLOR, + PROP_TAB_ACTIVITY_TIMEOUT, N_PROPERTIES, }; @@ -910,6 +912,27 @@ EXO_PARAM_READWRITE)); /** + * TerminalPreferences:tab-activity-color: + **/ + g_object_class_install_property (gobject_class, + PROP_TAB_ACTIVITY_COLOR, + g_param_spec_string ("tab-activity-color", + "tab-activity-color", + "tab-activity-color", + "#afff00000000", + EXO_PARAM_READWRITE)); + /** + * TerminalPreferences:tab-activity-timeout: + **/ + g_object_class_install_property (gobject_class, + PROP_TAB_ACTIVITY_TIMEOUT, + g_param_spec_double ("tab-activity-timeout", + "tab-activity-timeout", + "tab-activity-timeout", + 0.0, 30.0, 2.0, + EXO_PARAM_READWRITE)); + + /** * TerminalPreferences:command-update-records: **/ g_object_class_install_property (gobject_class, @@ -1640,5 +1663,16 @@ return preferences; } +void +query_color (TerminalPreferences *preferences, + const gchar *property, + GdkColor *color_return) +{ + gchar *spec; + g_object_get (G_OBJECT (preferences), property, &spec, NULL); + gdk_color_parse (spec, color_return); + g_free (spec); +} + Index: terminal/terminal-preferences.h =================================================================== --- terminal/terminal-preferences.h (revision 26875) +++ terminal/terminal-preferences.h (working copy) @@ -83,6 +83,11 @@ TerminalPreferences *terminal_preferences_get (void); +void query_color (TerminalPreferences *preferences, + const gchar *property, + GdkColor *color_return); + + G_END_DECLS; #endif /* !__TERMINAL_PREFERENCES_H__ */ Index: terminal/terminal-window.c =================================================================== --- terminal/terminal-window.c (revision 26875) +++ terminal/terminal-window.c (working copy) @@ -889,8 +889,8 @@ title = terminal_screen_get_title (terminal); gtk_window_set_title (GTK_WINDOW (window), title); g_free (title); - terminal_window_update_actions (window); + g_object_set (G_OBJECT (terminal), "activity", FALSE, NULL); } } @@ -1225,8 +1225,6 @@ } } - - static void terminal_window_action_new_tab (GtkAction *action, TerminalWindow *window) @@ -1697,9 +1695,11 @@ header = terminal_tab_header_new (); exo_binding_new (G_OBJECT (screen), "title", G_OBJECT (header), "title"); + exo_binding_new (G_OBJECT (screen), "activity", G_OBJECT (header), "activity"); g_signal_connect_swapped (G_OBJECT (header), "close-tab", G_CALLBACK (gtk_widget_destroy), screen); 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); + g_object_set_data_full (G_OBJECT (screen), I_("terminal-window"), g_object_ref (G_OBJECT (window)), (GDestroyNotify) g_object_unref); gtk_widget_show (header); page = gtk_notebook_append_page (GTK_NOTEBOOK (window->notebook), GTK_WIDGET (screen), header); @@ -1755,8 +1755,31 @@ return NULL; } +/** + * terminal_window_is_screen_active: + * @screen : a #TerminalScreen. + * + * Return value: TRUE if @screen is active. + **/ +gboolean +terminal_window_is_screen_active (TerminalScreen *screen) +{ + TerminalWindow *window = NULL; + GtkNotebook *notebook; + gint page_num; + + window = g_object_get_data (G_OBJECT (screen), I_("terminal-window")); + _terminal_return_val_if_fail (TERMINAL_IS_WINDOW (window), FALSE); + notebook = GTK_NOTEBOOK (window->notebook); + page_num = gtk_notebook_get_current_page (notebook); + if (G_LIKELY (page_num >= 0)) + return (TERMINAL_SCREEN (gtk_notebook_get_nth_page (notebook, page_num)) == screen); + else + return FALSE; +} + /** * terminal_window_set_startup_id: * @window Index: terminal/terminal-window.h =================================================================== --- terminal/terminal-window.h (revision 26875) +++ terminal/terminal-window.h (working copy) @@ -23,6 +23,7 @@ #define __TERMINAL_WINDOW_H__ #include +#include G_BEGIN_DECLS; @@ -69,6 +70,8 @@ GList *terminal_window_get_restart_command (TerminalWindow *window); +gboolean terminal_window_is_screen_active (TerminalScreen *screen); + G_END_DECLS; #endif /* !__TERMINAL_WINDOW_H__ */