From 14c54b3f14f94f362f4ecff0e82a90cda7ec1178 Mon Sep 17 00:00:00 2001 From: lenemter Date: Mon, 29 Dec 2025 21:28:12 +0900 Subject: [PATCH 1/2] Cleanup handling of tab icons --- src/Application.vala | 18 ++++++++++-------- src/MainWindow.vala | 2 +- src/Widgets/TerminalView.vala | 14 ++++++++++++++ src/Widgets/TerminalWidget.vala | 9 +++++---- 4 files changed, 30 insertions(+), 13 deletions(-) diff --git a/src/Application.vala b/src/Application.vala index b6d05f26b6..4b99071590 100644 --- a/src/Application.vala +++ b/src/Application.vala @@ -174,21 +174,23 @@ public class Terminal.Application : Gtk.Application { return; } - var process_string = _("Process completed"); - var process_icon = new ThemedIcon ("process-completed-symbolic"); + var notification_title = _("Process completed"); + var notification_icon = new ThemedIcon ("process-completed-symbolic"); + var tab_state = TerminalWidget.TabState.COMPLETED; if (exit_status != 0) { - process_string = _("Process exited with errors"); - process_icon = new ThemedIcon ("process-error-symbolic"); + notification_title = _("Process exited with errors"); + notification_icon = new ThemedIcon ("process-error-symbolic"); + tab_state = ERROR; } if (terminal != terminal.main_window.current_terminal) { - terminal.tab.icon = process_icon; + terminal.tab_state = tab_state; } if (!(get_active_window ().is_active)) { - var notification = new Notification (process_string); + var notification = new Notification (notification_title); notification.set_body (process); - notification.set_icon (process_icon); + notification.set_icon (notification_icon); notification.set_default_action_and_target_value ("app.process-finished", new Variant.string (id)); send_notification ("process-finished-%s".printf (id), notification); @@ -215,7 +217,7 @@ public class Terminal.Application : Gtk.Application { return; } - terminal.tab.icon = null; + terminal.tab_state = NONE; withdraw_notification ("process-finished-%s".printf (id)); terminal.main_window.disconnect (tab_change_handler); diff --git a/src/MainWindow.vala b/src/MainWindow.vala index ceea78b6a4..23aaff19be 100644 --- a/src/MainWindow.vala +++ b/src/MainWindow.vala @@ -303,7 +303,7 @@ namespace Terminal { return; } - term.tab.icon = null; // Assume only process icons are set + term.tab_state = NONE; }); notebook.tab_bar.bind_property ("tabs-revealed", new_tab_revealer, "reveal-child", SYNC_CREATE | INVERT_BOOLEAN); diff --git a/src/Widgets/TerminalView.vala b/src/Widgets/TerminalView.vala index dcafe77c17..c6696b95a8 100644 --- a/src/Widgets/TerminalView.vala +++ b/src/Widgets/TerminalView.vala @@ -169,6 +169,20 @@ public class Terminal.TerminalView : Granite.Bin { terminal_widget.bind_property ("current-working-directory", tab, "tooltip"); terminal_widget.tab = tab; + terminal_widget.notify["tab-state"].connect (() => { + switch (terminal_widget.tab_state) { + case NONE: + tab.icon = null; + break; + case COMPLETED: + tab.icon = new ThemedIcon ("process-completed-symbolic"); + break; + case ERROR: + tab.icon = new ThemedIcon ("process-error-symbolic"); + break; + } + }); + //Set correct label now to avoid race when spawning shell terminal_widget.set_font (term_font); diff --git a/src/Widgets/TerminalWidget.vala b/src/Widgets/TerminalWidget.vala index 81807a5de2..35b0796ff9 100644 --- a/src/Widgets/TerminalWidget.vala +++ b/src/Widgets/TerminalWidget.vala @@ -5,10 +5,10 @@ namespace Terminal { public class TerminalWidget : Vte.Terminal { - enum DropTargets { - URILIST, - STRING, - TEXT + public enum TabState { + NONE, + COMPLETED, + ERROR } internal const string DEFAULT_LABEL = _("Terminal"); @@ -18,6 +18,7 @@ namespace Terminal { static int terminal_id_counter = 0; private bool init_complete; public bool resized {get; set;} + public TabState tab_state { get; set; default = NONE; } GLib.Pid child_pid; GLib.Pid fg_pid; From 3955869bfbb70a5780a6282e00351697dc771bfd Mon Sep 17 00:00:00 2001 From: lenemter Date: Mon, 29 Dec 2025 22:15:16 +0900 Subject: [PATCH 2/2] Add tab indicator for working terminal tab --- src/Application.vala | 2 ++ src/MainWindow.vala | 4 +++- src/Widgets/TerminalView.vala | 3 +++ src/Widgets/TerminalWidget.vala | 10 ++++++++++ 4 files changed, 18 insertions(+), 1 deletion(-) diff --git a/src/Application.vala b/src/Application.vala index 4b99071590..64a30a7dd7 100644 --- a/src/Application.vala +++ b/src/Application.vala @@ -185,6 +185,8 @@ public class Terminal.Application : Gtk.Application { if (terminal != terminal.main_window.current_terminal) { terminal.tab_state = tab_state; + } else if (terminal.tab_state == WORKING) { + terminal.tab_state = NONE; } if (!(get_active_window ().is_active)) { diff --git a/src/MainWindow.vala b/src/MainWindow.vala index 23aaff19be..1e73b61b3b 100644 --- a/src/MainWindow.vala +++ b/src/MainWindow.vala @@ -303,7 +303,9 @@ namespace Terminal { return; } - term.tab_state = NONE; + if (term.tab_state != WORKING) { + term.tab_state = NONE; + } }); notebook.tab_bar.bind_property ("tabs-revealed", new_tab_revealer, "reveal-child", SYNC_CREATE | INVERT_BOOLEAN); diff --git a/src/Widgets/TerminalView.vala b/src/Widgets/TerminalView.vala index c6696b95a8..dfa7de52a8 100644 --- a/src/Widgets/TerminalView.vala +++ b/src/Widgets/TerminalView.vala @@ -170,8 +170,11 @@ public class Terminal.TerminalView : Granite.Bin { terminal_widget.tab = tab; terminal_widget.notify["tab-state"].connect (() => { + tab.loading = terminal_widget.tab_state == WORKING; + switch (terminal_widget.tab_state) { case NONE: + case WORKING: tab.icon = null; break; case COMPLETED: diff --git a/src/Widgets/TerminalWidget.vala b/src/Widgets/TerminalWidget.vala index 35b0796ff9..7d401abc62 100644 --- a/src/Widgets/TerminalWidget.vala +++ b/src/Widgets/TerminalWidget.vala @@ -7,6 +7,7 @@ namespace Terminal { public class TerminalWidget : Vte.Terminal { public enum TabState { NONE, + WORKING, COMPLETED, ERROR } @@ -233,6 +234,7 @@ namespace Terminal { notify["width-request"].connect (() => resized = true); contents_changed.connect (on_contents_changed); child_exited.connect (on_child_exited); + window_title_changed.connect (on_window_title_changed); ulong once = 0; once = realize.connect (() => { clipboard = Gdk.Display.get_default ().get_clipboard (); @@ -784,6 +786,14 @@ namespace Terminal { fg_pid = -1; } + private void on_window_title_changed () { + if (has_foreground_process ()) { + tab_state = WORKING; + } + + // Application.dbus_register handles resetting the state + } + public void kill_fg () { int fg_pid; if (this.try_get_foreground_pid (out fg_pid)) {