From ce75a5856124c6db79a53b8af49301a6d3a961ba Mon Sep 17 00:00:00 2001 From: Jeremy Wootten Date: Mon, 30 Jun 2025 11:17:43 +0100 Subject: [PATCH 1/5] Improve function naming --- src/MainWindow.vala | 8 ++++---- src/Widgets/DocumentView.vala | 10 +++++----- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/MainWindow.vala b/src/MainWindow.vala index 10e02af368..a9bd75bae0 100644 --- a/src/MainWindow.vala +++ b/src/MainWindow.vala @@ -845,7 +845,7 @@ namespace Scratch { } } - private void update_saved_state () { + private void update_window_state_setting () { // Save window state var state = get_window ().get_state (); if (Gdk.WindowState.MAXIMIZED in state) { @@ -872,9 +872,9 @@ namespace Scratch { } // For exit cleanup - private void handle_quit () { - document_view.save_opened_files (); - update_saved_state (); + public void before_quit () { + document_view.update_opened_files_setting (); + update_window_state_setting (); } public void set_default_zoom () { diff --git a/src/Widgets/DocumentView.vala b/src/Widgets/DocumentView.vala index 30fa7f56cd..9b572e1efe 100644 --- a/src/Widgets/DocumentView.vala +++ b/src/Widgets/DocumentView.vala @@ -133,7 +133,7 @@ public class Scratch.Widgets.DocumentView : Gtk.Box { var should_close = doc.do_close.end (res); // Ensure removed doc is saved by handling this first if (!is_closing) { - save_opened_files (); + update_opened_files_setting (); } //`page-detached` handler will perform rest of necessary cleanup tab_view.close_page_finish (tab, should_close); @@ -337,7 +337,7 @@ public class Scratch.Widgets.DocumentView : Gtk.Box { if (range != SelectionRange.EMPTY) { Idle.add_full (GLib.Priority.LOW, () => { // This helps ensures new tab is drawn before opening document. current_document.source_view.select_range (range); - save_opened_files (); + update_opened_files_setting (); return false; }); @@ -364,7 +364,7 @@ public class Scratch.Widgets.DocumentView : Gtk.Box { doc.source_view.cursor_position = cursor_position; } - save_opened_files (); + update_opened_files_setting (); } public void next_document () { @@ -399,7 +399,7 @@ public class Scratch.Widgets.DocumentView : Gtk.Box { } } - public void save_opened_files () { + public void update_opened_files_setting () { if (privacy_settings.get_boolean ("remember-recent-files")) { var vb = new VariantBuilder (new VariantType ("a(si)")); docs.foreach ((doc) => { @@ -542,7 +542,7 @@ public class Scratch.Widgets.DocumentView : Gtk.Box { current_document = doc; } - save_opened_files (); + update_opened_files_setting (); } private unowned Hdy.TabView? on_doc_to_new_window (Hdy.TabView tab_view) { From e34c9190bc21874074d7b83f27b81823e2411e9c Mon Sep 17 00:00:00 2001 From: Jeremy Wootten Date: Mon, 30 Jun 2025 11:18:57 +0100 Subject: [PATCH 2/5] Allow Application to handle window quit request --- src/Application.vala | 35 +++++++++++++++++++++++++++++++++++ src/MainWindow.vala | 9 ++------- 2 files changed, 37 insertions(+), 7 deletions(-) diff --git a/src/Application.vala b/src/Application.vala index afbf15e31f..78ae34713c 100644 --- a/src/Application.vala +++ b/src/Application.vala @@ -199,6 +199,41 @@ namespace Scratch { return windows.length () > 0 ? windows.last ().data as MainWindow : null; } + public async void handle_quit_window (MainWindow window_to_close) { + if (!yield window_to_close.check_unsaved_changes ()) { + return; + } + + unowned List windows = get_windows (); + var n_windows = windows.length (); + + if (n_windows == 1) { + // Close app as usual + window_to_close.before_quit (); // Update settings + quit (); + } else { + // Find window to move docs into + unowned var windows_head = windows.first (); + var target_window = (MainWindow)(windows_head.data); + if (target_window == window_to_close) { + target_window = (MainWindow)(windows_head.next.data); + } + + // Reopen each doc in target window (we know they have been saved) + var doc_list = window_to_close.document_view.docs.copy (); + foreach (var doc in doc_list) { + var new_doc = new Services.Document ( + target_window.actions, + doc.file + ); + yield target_window.open_document (new_doc, false); + } + + remove_window (window_to_close); + window_to_close.destroy (); + } + } + public static int main (string[] args) { return new Application ().run (args); } diff --git a/src/MainWindow.vala b/src/MainWindow.vala index a9bd75bae0..b08067e655 100644 --- a/src/MainWindow.vala +++ b/src/MainWindow.vala @@ -808,7 +808,7 @@ namespace Scratch { } // Check that there no unsaved changes and all saves are successful - private async bool check_unsaved_changes () { + public async bool check_unsaved_changes () { document_view.is_closing = true; foreach (var doc in document_view.docs) { if (!yield (doc.do_close (true))) { @@ -962,12 +962,7 @@ namespace Scratch { } private void action_quit () { - handle_quit (); - check_unsaved_changes.begin ((obj, res) => { - if (check_unsaved_changes.end (res)) { - app.quit (); - } - }); + app.handle_quit_window (this); } private void action_open () { From b167f532c036026dadf45e1d1f36445a49ddf45b Mon Sep 17 00:00:00 2001 From: Jeremy Wootten Date: Wed, 13 Aug 2025 13:39:45 +0100 Subject: [PATCH 3/5] Do not move docs to another window --- src/Application.vala | 18 +----------------- 1 file changed, 1 insertion(+), 17 deletions(-) diff --git a/src/Application.vala b/src/Application.vala index 78ae34713c..bd907ccb3c 100644 --- a/src/Application.vala +++ b/src/Application.vala @@ -212,23 +212,7 @@ namespace Scratch { window_to_close.before_quit (); // Update settings quit (); } else { - // Find window to move docs into - unowned var windows_head = windows.first (); - var target_window = (MainWindow)(windows_head.data); - if (target_window == window_to_close) { - target_window = (MainWindow)(windows_head.next.data); - } - - // Reopen each doc in target window (we know they have been saved) - var doc_list = window_to_close.document_view.docs.copy (); - foreach (var doc in doc_list) { - var new_doc = new Services.Document ( - target_window.actions, - doc.file - ); - yield target_window.open_document (new_doc, false); - } - + // Just close window - we have already checked whether any docs need saving remove_window (window_to_close); window_to_close.destroy (); } From 8a117e7a22791732d1914d11d02871ac276f991c Mon Sep 17 00:00:00 2001 From: Jeremy Wootten Date: Wed, 13 Aug 2025 13:40:10 +0100 Subject: [PATCH 4/5] Handle new docs differently if not closing last window --- src/Application.vala | 8 +++----- src/MainWindow.vala | 6 +++--- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/src/Application.vala b/src/Application.vala index bd907ccb3c..61204c7810 100644 --- a/src/Application.vala +++ b/src/Application.vala @@ -200,13 +200,11 @@ namespace Scratch { } public async void handle_quit_window (MainWindow window_to_close) { - if (!yield window_to_close.check_unsaved_changes ()) { - return; - } - unowned List windows = get_windows (); var n_windows = windows.length (); - + if (!yield window_to_close.check_unsaved_changes (n_windows == 1)) { + return; + } if (n_windows == 1) { // Close app as usual window_to_close.before_quit (); // Update settings diff --git a/src/MainWindow.vala b/src/MainWindow.vala index b08067e655..1e2dc31b23 100644 --- a/src/MainWindow.vala +++ b/src/MainWindow.vala @@ -208,7 +208,7 @@ namespace Scratch { action_accelerators.set (ACTION_FIND_GLOBAL + "::", "f"); action_accelerators.set (ACTION_OPEN, "o"); action_accelerators.set (ACTION_OPEN_FOLDER, "o"); - action_accelerators.set (ACTION_REVERT, "o"); + action_accelerators.set (ACTION_REVERT, "r"); action_accelerators.set (ACTION_SAVE, "s"); action_accelerators.set (ACTION_SAVE_AS, "s"); action_accelerators.set (ACTION_GO_TO, "i"); @@ -808,10 +808,10 @@ namespace Scratch { } // Check that there no unsaved changes and all saves are successful - public async bool check_unsaved_changes () { + public async bool check_unsaved_changes (bool app_closing) { document_view.is_closing = true; foreach (var doc in document_view.docs) { - if (!yield (doc.do_close (true))) { + if (!yield (doc.do_close (app_closing))) { document_view.current_document = doc; return false; } From 2d41ce562101c205fb75942f7357275bf1840843 Mon Sep 17 00:00:00 2001 From: Jeremy Wootten Date: Wed, 13 Aug 2025 18:38:21 +0100 Subject: [PATCH 5/5] Separate action to close app and close window --- src/Application.vala | 31 +++++++++++++++++++++++-------- src/MainWindow.vala | 19 +++++++++++++------ 2 files changed, 36 insertions(+), 14 deletions(-) diff --git a/src/Application.vala b/src/Application.vala index 61204c7810..277c66ce40 100644 --- a/src/Application.vala +++ b/src/Application.vala @@ -199,21 +199,36 @@ namespace Scratch { return windows.length () > 0 ? windows.last ().data as MainWindow : null; } - public async void handle_quit_window (MainWindow window_to_close) { + public async void handle_quit_app () { + unowned List windows; + windows = get_windows (); + //NOTE This yields the last opened window at head of list (may change in future?) + while (windows.length () > 0) { + if (!yield handle_quit_window ((MainWindow) (windows.first ().data))) { + return; + } + + windows = get_windows (); + } + + return; + } + + public async bool handle_quit_window (MainWindow window_to_close) { unowned List windows = get_windows (); var n_windows = windows.length (); if (!yield window_to_close.check_unsaved_changes (n_windows == 1)) { - return; + return false; } + if (n_windows == 1) { - // Close app as usual window_to_close.before_quit (); // Update settings - quit (); - } else { - // Just close window - we have already checked whether any docs need saving - remove_window (window_to_close); - window_to_close.destroy (); } + // Just destroy window - we have already checked whether any docs need saving + // When the last window is removed and destroyed the app quits. + remove_window (window_to_close); + window_to_close.destroy (); + return true; } public static int main (string[] args) { diff --git a/src/MainWindow.vala b/src/MainWindow.vala index 1e2dc31b23..dc02086080 100644 --- a/src/MainWindow.vala +++ b/src/MainWindow.vala @@ -99,7 +99,8 @@ namespace Scratch { public const string ACTION_TO_UPPER_CASE = "action-to-upper-case"; public const string ACTION_DUPLICATE = "action-duplicate"; public const string ACTION_FULLSCREEN = "action-fullscreen"; - public const string ACTION_QUIT = "action-quit"; + public const string ACTION_QUIT = "action-quit-app"; + public const string ACTION_CLOSE_WINDOW = "action-close-window"; public const string ACTION_ZOOM_DEFAULT = "action-zoom-default"; public const string ACTION_ZOOM_IN = "action-zoom-in"; public const string ACTION_ZOOM_OUT = "action-zoom-out"; @@ -159,7 +160,8 @@ namespace Scratch { { ACTION_TO_UPPER_CASE, action_to_upper_case }, { ACTION_DUPLICATE, action_duplicate }, { ACTION_FULLSCREEN, action_fullscreen }, - { ACTION_QUIT, action_quit }, + { ACTION_QUIT, action_quit_app }, + { ACTION_CLOSE_WINDOW, action_close_window }, { ACTION_ZOOM_DEFAULT, action_set_default_zoom }, { ACTION_ZOOM_IN, action_zoom_in }, { ACTION_ZOOM_OUT, action_zoom_out}, @@ -223,6 +225,7 @@ namespace Scratch { action_accelerators.set (ACTION_DUPLICATE, "d"); action_accelerators.set (ACTION_FULLSCREEN, "F11"); action_accelerators.set (ACTION_QUIT, "q"); + action_accelerators.set (ACTION_CLOSE_WINDOW, "F4"); action_accelerators.set (ACTION_ZOOM_DEFAULT, "0"); action_accelerators.set (ACTION_ZOOM_DEFAULT, "KP_0"); action_accelerators.set (ACTION_ZOOM_IN, "plus"); @@ -720,7 +723,7 @@ namespace Scratch { } protected override bool delete_event (Gdk.EventAny event) { - action_quit (); + action_close_window (); return true; } @@ -867,7 +870,7 @@ namespace Scratch { // SIGTERM/SIGINT Handling public bool quit_source_func () { - action_quit (); + action_quit_app (); return false; } @@ -961,8 +964,12 @@ namespace Scratch { preferences_dialog.present (); } - private void action_quit () { - app.handle_quit_window (this); + private void action_close_window () { + app.handle_quit_window.begin (this); + } + + private void action_quit_app () { + app.handle_quit_app.begin (); } private void action_open () {