Skip to content

Commit

Permalink
Fix clear and reset actions when ongoing foreground process (#823)
Browse files Browse the repository at this point in the history
* Confirm kill fg process before clear or reset; DRY

* Use feed_child ()

* Add `<Shift>` to clear and reset accels

* Ignore clear screen action if terminal has foreground process

---------

Co-authored-by: Jeremy Wootten <jeremy@Proteus-EL07R6-9b3c42bb.localdomain>
  • Loading branch information
jeremypw and Jeremy Wootten authored Dec 18, 2024
1 parent 38b731d commit 3c84bcb
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 85 deletions.
39 changes: 9 additions & 30 deletions src/Dialogs/ForegroundProcessDialog.vala
Original file line number Diff line number Diff line change
Expand Up @@ -20,42 +20,21 @@
public class Terminal.ForegroundProcessDialog : Granite.MessageDialog {
public string button_label { get; construct; }

public ForegroundProcessDialog (MainWindow parent) {
public ForegroundProcessDialog (
MainWindow parent,
string primary_text,
string button_label
) {
Object (
transient_for: parent,
primary_text: _("Are you sure you want to close this tab?"),
secondary_text:
_("There is an active process on this tab.") + " " +
_("If you close it, the process will end."),
buttons: Gtk.ButtonsType.CANCEL,
button_label: _("Close Tab")
);
}

public ForegroundProcessDialog.before_close (MainWindow parent) {
Object (
transient_for: parent,
primary_text: _("Are you sure you want to quit Terminal?"),
secondary_text:
_("There is an active process on this terminal.") + " " +
_("If you quit Terminal, the process will end."),
buttons: Gtk.ButtonsType.CANCEL,
button_label: _("Quit Terminal")
);
}

public ForegroundProcessDialog.before_tab_reload (MainWindow parent) {
Object (
transient_for: parent,
primary_text: _("Are you sure you want to reload this tab?"),
secondary_text:
_("There is an active process on this tab. If you reload it, the process will end."),
buttons: Gtk.ButtonsType.CANCEL,
button_label: _("Reload Tab")
primary_text: primary_text,
button_label: button_label,
buttons: Gtk.ButtonsType.CANCEL
);
}

construct {
secondary_text = _("There is an active process on this tab. If you continue, the process will end.");
image_icon = new ThemedIcon ("dialog-warning");

var close_button = add_button (button_label, Gtk.ResponseType.ACCEPT);
Expand Down
42 changes: 12 additions & 30 deletions src/MainWindow.vala
Original file line number Diff line number Diff line change
Expand Up @@ -368,10 +368,13 @@ namespace Terminal {
if (term == null) {
confirmed = true;
} else {
confirmed = confirm_close_tab (term);
confirmed = term.confirm_kill_fg_process (
_("Are you sure you want to close this tab?"),
_("Close Tab")
);
}

if (confirmed) {
if (confirmed && term != null) {
if (!term.child_has_exited) {
term.term_ps ();
}
Expand Down Expand Up @@ -530,23 +533,6 @@ namespace Terminal {
}
}

public bool confirm_close_tab (TerminalWidget terminal_widget) {
if (terminal_widget.has_foreground_process ()) {
var dialog = new ForegroundProcessDialog (this);
if (dialog.run () == Gtk.ResponseType.ACCEPT) {
dialog.destroy ();
terminal_widget.kill_fg ();
} else {
dialog.destroy ();
return false;
}
}

//Names checked in page_detached handler

return true;
}

private void on_tab_reordered (Hdy.TabPage tab, int new_pos) {
save_opened_terminals (true, true);
}
Expand Down Expand Up @@ -893,18 +879,14 @@ namespace Terminal {

for (int i = 0; i < notebook.n_pages; i++) {
var term = get_term_widget (notebook.tab_view.get_nth_page (i));
if (term.has_foreground_process ()) {
var dialog = new ForegroundProcessDialog.before_close (this);
if (dialog.run () == Gtk.ResponseType.ACCEPT) {
term.kill_fg ();
dialog.destroy ();
} else {
dialog.destroy ();
return true;
}
if (term.confirm_kill_fg_process (
_("Are you sure you want to quit Terminal?"),
_("Quit Terminal"))
) {
tabs_to_terminate.append (term);
} else {
return true;
}

tabs_to_terminate.append (term);
}

foreach (var t in tabs_to_terminate) {
Expand Down
73 changes: 48 additions & 25 deletions src/Widgets/TerminalWidget.vala
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,8 @@ namespace Terminal {

public const string[] ACCELS_COPY = { "<Control><Shift>C", null };
public const string[] ACCELS_COPY_OUTPUT = { "<Alt>C", null };
public const string[] ACCELS_CLEAR_SCREEN = { "<Control>L", null };
public const string[] ACCELS_RESET = { "<Control>K", null };
public const string[] ACCELS_CLEAR_SCREEN = { "<Control><Shift>L", null };
public const string[] ACCELS_RESET = { "<Control><Shift>K", null };
public const string[] ACCELS_PASTE = { "<Control><Shift>V", null };
public const string[] ACCELS_RELOAD = { "<Control><Shift>R", "<Ctrl>F5", null };
public const string[] ACCELS_SCROLL_TO_COMMAND = { "<Alt>Up", null };
Expand Down Expand Up @@ -505,16 +505,50 @@ namespace Terminal {
clipboard.set_text (output, output.length);
}

public bool confirm_kill_fg_process (
string primary_text,
string button_label
) {
if (has_foreground_process ()) {
var dialog = new ForegroundProcessDialog (
(MainWindow) get_toplevel (),
primary_text,
button_label
);

if (dialog.run () == Gtk.ResponseType.ACCEPT) {
dialog.destroy ();
kill_fg ();
} else {
dialog.destroy ();
return false;
}
}

return true;
}

private void action_clear_screen () {
debug ("Clear screen only");
// Should we clear scrollback too?
run_program ("clear -x", null);
if (has_foreground_process ()) {
// We cannot guarantee the terminal is left in sensible state if we
// kill foreground process so ignore clear screen request
return;
}

// We keep the scrollback history, just clear the screen
// We know there is no foreground process so we can just feed the command in
feed_child ("clear -x\n".data);
}

private void action_reset () {
debug ("Reset");
// This also clears the screen and the scrollback
run_program ("reset", null);
if (confirm_kill_fg_process (
_("Are you sure you want to reset the terminal?"),
_("Reset"))
) {
// This also clears the screen and the scrollback
// We know there is no foreground process so we can just feed the command in
feed_child ("reset\n".data);
}
}

protected override void paste_clipboard () {
Expand Down Expand Up @@ -895,25 +929,14 @@ namespace Terminal {
public void reload () {
var old_loc = get_shell_location ();

if (has_foreground_process ()) {
var dialog = new ForegroundProcessDialog.before_tab_reload ((MainWindow) get_toplevel ());
dialog.response.connect ((res) => {
if (res == Gtk.ResponseType.ACCEPT) {
Posix.kill (child_pid, Posix.Signal.TERM);
reset (true, true);
active_shell (old_loc);
}

dialog.destroy ();
});
if (confirm_kill_fg_process (
_("Are you sure you want to reload this tab?"),
_("Reload Tab"))
) {

dialog.present ();
return;
reset (true, true);
active_shell (old_loc);
}

Posix.kill (child_pid, Posix.Signal.TERM);
reset (true, true);
active_shell (old_loc);
}

private void check_cwd_changed () {
Expand Down

0 comments on commit 3c84bcb

Please sign in to comment.