diff --git a/common/dialogs/panel_common_settings.cpp b/common/dialogs/panel_common_settings.cpp
index b9db7dbfe7..70c08fcab6 100644
--- a/common/dialogs/panel_common_settings.cpp
+++ b/common/dialogs/panel_common_settings.cpp
@@ -127,6 +127,8 @@ bool PANEL_COMMON_SETTINGS::TransferDataFromWindow()
     commonSettings->m_Backup.min_interval       = m_backupMinInterval->GetValue() * 60;
     commonSettings->m_Backup.limit_total_size   = m_backupLimitTotalSize->GetValue() * 1024 * 1024;
 
+    commonSettings->m_Session.remember_open_files = m_cbRememberOpenFiles->GetValue();
+
     Pgm().SetEditorName( m_textEditorPath->GetValue() );
 
     Pgm().SetPdfBrowserName( m_PDFViewerPath->GetValue() );
@@ -195,6 +197,8 @@ void PANEL_COMMON_SETTINGS::applySettingsToPanel( COMMON_SETTINGS& aSettings )
     m_warpMouseOnMove->SetValue( aSettings.m_Input.warp_mouse_on_move );
     m_NonImmediateActions->SetValue( !aSettings.m_Input.immediate_actions );
 
+    m_cbRememberOpenFiles->SetValue( aSettings.m_Session.remember_open_files );
+
     m_cbBackupEnabled->SetValue( aSettings.m_Backup.enabled );
     m_cbBackupAutosave->SetValue( aSettings.m_Backup.backup_on_autosave );
     m_backupLimitTotalFiles->SetValue( aSettings.m_Backup.limit_total_files );
diff --git a/common/dialogs/panel_common_settings_base.cpp b/common/dialogs/panel_common_settings_base.cpp
index 986a205c46..f165d54ca7 100644
--- a/common/dialogs/panel_common_settings_base.cpp
+++ b/common/dialogs/panel_common_settings_base.cpp
@@ -278,6 +278,18 @@ PANEL_COMMON_SETTINGS_BASE::PANEL_COMMON_SETTINGS_BASE( wxWindow* parent, wxWind
 
 	rightSizer->Add( sbSizer41, 1, wxALL|wxEXPAND, 5 );
 
+	wxStaticBoxSizer* sbSizer5;
+	sbSizer5 = new wxStaticBoxSizer( new wxStaticBox( this, wxID_ANY, _("Session") ), wxVERTICAL );
+
+	m_cbRememberOpenFiles = new wxCheckBox( sbSizer5->GetStaticBox(), wxID_ANY, _("Remember open files for next project launch"), wxDefaultPosition, wxDefaultSize, 0 );
+	m_cbRememberOpenFiles->SetValue(true);
+	m_cbRememberOpenFiles->SetToolTip( _("If checked, launching a project will also launch tools such as eeschema and pcbnew with previously open files") );
+
+	sbSizer5->Add( m_cbRememberOpenFiles, 0, wxALL, 5 );
+
+
+	rightSizer->Add( sbSizer5, 0, wxALL|wxEXPAND, 5 );
+
 
 	bPanelSizer->Add( rightSizer, 0, wxEXPAND|wxALL, 5 );
 
diff --git a/common/dialogs/panel_common_settings_base.fbp b/common/dialogs/panel_common_settings_base.fbp
index 71093ecd6d..98270f8903 100644
--- a/common/dialogs/panel_common_settings_base.fbp
+++ b/common/dialogs/panel_common_settings_base.fbp
@@ -67,7 +67,7 @@
                             <property name="border">10</property>
                             <property name="flag">wxEXPAND|wxALL</property>
                             <property name="proportion">0</property>
-                            <object class="wxGridBagSizer" expanded="1">
+                            <object class="wxGridBagSizer" expanded="0">
                                 <property name="empty_cell_size">-1,2</property>
                                 <property name="flexible_direction">wxBOTH</property>
                                 <property name="growablecols">1</property>
@@ -78,7 +78,7 @@
                                 <property name="non_flexible_grow_mode">wxFLEX_GROWMODE_SPECIFIED</property>
                                 <property name="permission">none</property>
                                 <property name="vgap">4</property>
-                                <object class="gbsizeritem" expanded="1">
+                                <object class="gbsizeritem" expanded="0">
                                     <property name="border">5</property>
                                     <property name="colspan">1</property>
                                     <property name="column">0</property>
@@ -142,14 +142,14 @@
                                         <property name="wrap">-1</property>
                                     </object>
                                 </object>
-                                <object class="gbsizeritem" expanded="1">
+                                <object class="gbsizeritem" expanded="0">
                                     <property name="border">5</property>
                                     <property name="colspan">1</property>
                                     <property name="column">1</property>
                                     <property name="flag">wxEXPAND</property>
                                     <property name="row">0</property>
                                     <property name="rowspan">1</property>
-                                    <object class="wxBoxSizer" expanded="1">
+                                    <object class="wxBoxSizer" expanded="0">
                                         <property name="minimum_size"></property>
                                         <property name="name">bSizer6</property>
                                         <property name="orient">wxHORIZONTAL</property>
@@ -279,14 +279,14 @@
                                         </object>
                                     </object>
                                 </object>
-                                <object class="gbsizeritem" expanded="1">
+                                <object class="gbsizeritem" expanded="0">
                                     <property name="border">5</property>
                                     <property name="colspan">1</property>
                                     <property name="column">0</property>
                                     <property name="flag">wxALIGN_CENTER_VERTICAL</property>
                                     <property name="row">1</property>
                                     <property name="rowspan">1</property>
-                                    <object class="wxStaticText" expanded="1">
+                                    <object class="wxStaticText" expanded="0">
                                         <property name="BottomDockable">1</property>
                                         <property name="LeftDockable">1</property>
                                         <property name="RightDockable">1</property>
@@ -343,14 +343,14 @@
                                         <property name="wrap">-1</property>
                                     </object>
                                 </object>
-                                <object class="gbsizeritem" expanded="1">
+                                <object class="gbsizeritem" expanded="0">
                                     <property name="border">5</property>
                                     <property name="colspan">1</property>
                                     <property name="column">1</property>
                                     <property name="flag">wxALIGN_CENTER_VERTICAL</property>
                                     <property name="row">1</property>
                                     <property name="rowspan">1</property>
-                                    <object class="wxSpinCtrl" expanded="1">
+                                    <object class="wxSpinCtrl" expanded="0">
                                         <property name="BottomDockable">1</property>
                                         <property name="LeftDockable">1</property>
                                         <property name="RightDockable">1</property>
@@ -408,23 +408,23 @@
                                         <property name="window_style"></property>
                                     </object>
                                 </object>
-                                <object class="gbsizeritem" expanded="1">
+                                <object class="gbsizeritem" expanded="0">
                                     <property name="border">5</property>
                                     <property name="colspan">1</property>
                                     <property name="column">1</property>
                                     <property name="flag">wxEXPAND</property>
                                     <property name="row">2</property>
                                     <property name="rowspan">1</property>
-                                    <object class="wxBoxSizer" expanded="1">
+                                    <object class="wxBoxSizer" expanded="0">
                                         <property name="minimum_size"></property>
                                         <property name="name">bSizer5</property>
                                         <property name="orient">wxHORIZONTAL</property>
                                         <property name="permission">none</property>
-                                        <object class="sizeritem" expanded="1">
+                                        <object class="sizeritem" expanded="0">
                                             <property name="border">5</property>
                                             <property name="flag">wxALIGN_CENTER_VERTICAL</property>
                                             <property name="proportion">0</property>
-                                            <object class="wxSpinCtrl" expanded="1">
+                                            <object class="wxSpinCtrl" expanded="0">
                                                 <property name="BottomDockable">1</property>
                                                 <property name="LeftDockable">1</property>
                                                 <property name="RightDockable">1</property>
@@ -482,11 +482,11 @@
                                                 <property name="window_style"></property>
                                             </object>
                                         </object>
-                                        <object class="sizeritem" expanded="1">
+                                        <object class="sizeritem" expanded="0">
                                             <property name="border">5</property>
                                             <property name="flag">wxALIGN_CENTER_VERTICAL|wxLEFT|wxRIGHT</property>
                                             <property name="proportion">0</property>
-                                            <object class="wxStaticText" expanded="1">
+                                            <object class="wxStaticText" expanded="0">
                                                 <property name="BottomDockable">1</property>
                                                 <property name="LeftDockable">1</property>
                                                 <property name="RightDockable">1</property>
@@ -545,14 +545,14 @@
                                         </object>
                                     </object>
                                 </object>
-                                <object class="gbsizeritem" expanded="1">
+                                <object class="gbsizeritem" expanded="0">
                                     <property name="border">5</property>
                                     <property name="colspan">1</property>
                                     <property name="column">0</property>
                                     <property name="flag">wxALIGN_CENTER_VERTICAL</property>
                                     <property name="row">4</property>
                                     <property name="rowspan">1</property>
-                                    <object class="wxStaticText" expanded="1">
+                                    <object class="wxStaticText" expanded="0">
                                         <property name="BottomDockable">1</property>
                                         <property name="LeftDockable">1</property>
                                         <property name="RightDockable">1</property>
@@ -609,14 +609,14 @@
                                         <property name="wrap">-1</property>
                                     </object>
                                 </object>
-                                <object class="gbsizeritem" expanded="1">
+                                <object class="gbsizeritem" expanded="0">
                                     <property name="border">5</property>
                                     <property name="colspan">2</property>
                                     <property name="column">1</property>
                                     <property name="flag">wxALIGN_CENTER_VERTICAL|wxEXPAND</property>
                                     <property name="row">4</property>
                                     <property name="rowspan">1</property>
-                                    <object class="wxChoice" expanded="1">
+                                    <object class="wxChoice" expanded="0">
                                         <property name="BottomDockable">1</property>
                                         <property name="LeftDockable">1</property>
                                         <property name="RightDockable">1</property>
@@ -676,14 +676,14 @@
                                         <property name="window_style"></property>
                                     </object>
                                 </object>
-                                <object class="gbsizeritem" expanded="1">
+                                <object class="gbsizeritem" expanded="0">
                                     <property name="border">5</property>
                                     <property name="colspan">1</property>
                                     <property name="column">0</property>
                                     <property name="flag">wxALIGN_CENTER_VERTICAL</property>
                                     <property name="row">6</property>
                                     <property name="rowspan">1</property>
-                                    <object class="wxStaticText" expanded="1">
+                                    <object class="wxStaticText" expanded="0">
                                         <property name="BottomDockable">1</property>
                                         <property name="LeftDockable">1</property>
                                         <property name="RightDockable">1</property>
@@ -740,14 +740,14 @@
                                         <property name="wrap">-1</property>
                                     </object>
                                 </object>
-                                <object class="gbsizeritem" expanded="1">
+                                <object class="gbsizeritem" expanded="0">
                                     <property name="border">5</property>
                                     <property name="colspan">2</property>
                                     <property name="column">1</property>
                                     <property name="flag">wxALIGN_CENTER_VERTICAL|wxEXPAND</property>
                                     <property name="row">6</property>
                                     <property name="rowspan">1</property>
-                                    <object class="wxChoice" expanded="1">
+                                    <object class="wxChoice" expanded="0">
                                         <property name="BottomDockable">1</property>
                                         <property name="LeftDockable">1</property>
                                         <property name="RightDockable">1</property>
@@ -807,14 +807,14 @@
                                         <property name="window_style"></property>
                                     </object>
                                 </object>
-                                <object class="gbsizeritem" expanded="1">
+                                <object class="gbsizeritem" expanded="0">
                                     <property name="border">5</property>
                                     <property name="colspan">1</property>
                                     <property name="column">0</property>
                                     <property name="flag">wxALIGN_CENTER_VERTICAL|wxTOP</property>
                                     <property name="row">2</property>
                                     <property name="rowspan">1</property>
-                                    <object class="wxStaticText" expanded="1">
+                                    <object class="wxStaticText" expanded="0">
                                         <property name="BottomDockable">1</property>
                                         <property name="LeftDockable">1</property>
                                         <property name="RightDockable">1</property>
@@ -877,7 +877,7 @@
                             <property name="border">5</property>
                             <property name="flag">wxEXPAND|wxALL</property>
                             <property name="proportion">0</property>
-                            <object class="wxStaticBoxSizer" expanded="1">
+                            <object class="wxStaticBoxSizer" expanded="0">
                                 <property name="id">wxID_ANY</property>
                                 <property name="label">Helper Applications</property>
                                 <property name="minimum_size"></property>
@@ -885,11 +885,11 @@
                                 <property name="orient">wxHORIZONTAL</property>
                                 <property name="parent">1</property>
                                 <property name="permission">none</property>
-                                <object class="sizeritem" expanded="1">
+                                <object class="sizeritem" expanded="0">
                                     <property name="border">5</property>
                                     <property name="flag">wxBOTTOM|wxLEFT|wxRIGHT|wxEXPAND</property>
                                     <property name="proportion">1</property>
-                                    <object class="wxGridBagSizer" expanded="1">
+                                    <object class="wxGridBagSizer" expanded="0">
                                         <property name="empty_cell_size">-1,5</property>
                                         <property name="flexible_direction">wxBOTH</property>
                                         <property name="growablecols">1</property>
@@ -900,14 +900,14 @@
                                         <property name="non_flexible_grow_mode">wxFLEX_GROWMODE_SPECIFIED</property>
                                         <property name="permission">none</property>
                                         <property name="vgap">3</property>
-                                        <object class="gbsizeritem" expanded="1">
+                                        <object class="gbsizeritem" expanded="0">
                                             <property name="border">4</property>
                                             <property name="colspan">1</property>
                                             <property name="column">0</property>
                                             <property name="flag">wxALIGN_CENTER_VERTICAL</property>
                                             <property name="row">0</property>
                                             <property name="rowspan">1</property>
-                                            <object class="wxStaticText" expanded="1">
+                                            <object class="wxStaticText" expanded="0">
                                                 <property name="BottomDockable">1</property>
                                                 <property name="LeftDockable">1</property>
                                                 <property name="RightDockable">1</property>
@@ -964,14 +964,14 @@
                                                 <property name="wrap">-1</property>
                                             </object>
                                         </object>
-                                        <object class="gbsizeritem" expanded="1">
+                                        <object class="gbsizeritem" expanded="0">
                                             <property name="border">8</property>
                                             <property name="colspan">1</property>
                                             <property name="column">1</property>
                                             <property name="flag">wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxEXPAND</property>
                                             <property name="row">0</property>
                                             <property name="rowspan">1</property>
-                                            <object class="wxTextCtrl" expanded="1">
+                                            <object class="wxTextCtrl" expanded="0">
                                                 <property name="BottomDockable">1</property>
                                                 <property name="LeftDockable">1</property>
                                                 <property name="RightDockable">1</property>
@@ -1031,14 +1031,14 @@
                                                 <property name="window_style"></property>
                                             </object>
                                         </object>
-                                        <object class="gbsizeritem" expanded="1">
+                                        <object class="gbsizeritem" expanded="0">
                                             <property name="border">5</property>
                                             <property name="colspan">1</property>
                                             <property name="column">2</property>
                                             <property name="flag">wxALIGN_CENTER_VERTICAL|wxEXPAND|wxTOP|wxBOTTOM</property>
                                             <property name="row">0</property>
                                             <property name="rowspan">1</property>
-                                            <object class="wxBitmapButton" expanded="1">
+                                            <object class="wxBitmapButton" expanded="0">
                                                 <property name="BottomDockable">1</property>
                                                 <property name="LeftDockable">1</property>
                                                 <property name="RightDockable">1</property>
@@ -1107,14 +1107,14 @@
                                                 <event name="OnButtonClick">OnTextEditorClick</event>
                                             </object>
                                         </object>
-                                        <object class="gbsizeritem" expanded="1">
+                                        <object class="gbsizeritem" expanded="0">
                                             <property name="border">4</property>
                                             <property name="colspan">3</property>
                                             <property name="column">0</property>
                                             <property name="flag"></property>
                                             <property name="row">3</property>
                                             <property name="rowspan">1</property>
-                                            <object class="wxRadioButton" expanded="1">
+                                            <object class="wxRadioButton" expanded="0">
                                                 <property name="BottomDockable">1</property>
                                                 <property name="LeftDockable">1</property>
                                                 <property name="RightDockable">1</property>
@@ -1174,14 +1174,14 @@
                                                 <property name="window_style"></property>
                                             </object>
                                         </object>
-                                        <object class="gbsizeritem" expanded="1">
+                                        <object class="gbsizeritem" expanded="0">
                                             <property name="border">4</property>
                                             <property name="colspan">1</property>
                                             <property name="column">0</property>
                                             <property name="flag">wxALIGN_CENTER_VERTICAL</property>
                                             <property name="row">4</property>
                                             <property name="rowspan">1</property>
-                                            <object class="wxRadioButton" expanded="1">
+                                            <object class="wxRadioButton" expanded="0">
                                                 <property name="BottomDockable">1</property>
                                                 <property name="LeftDockable">1</property>
                                                 <property name="RightDockable">1</property>
@@ -1241,14 +1241,14 @@
                                                 <property name="window_style"></property>
                                             </object>
                                         </object>
-                                        <object class="gbsizeritem" expanded="1">
+                                        <object class="gbsizeritem" expanded="0">
                                             <property name="border">8</property>
                                             <property name="colspan">1</property>
                                             <property name="column">1</property>
                                             <property name="flag">wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxEXPAND</property>
                                             <property name="row">4</property>
                                             <property name="rowspan">1</property>
-                                            <object class="wxTextCtrl" expanded="1">
+                                            <object class="wxTextCtrl" expanded="0">
                                                 <property name="BottomDockable">1</property>
                                                 <property name="LeftDockable">1</property>
                                                 <property name="RightDockable">1</property>
@@ -1309,14 +1309,14 @@
                                                 <event name="OnUpdateUI">onUpdateUIPdfPath</event>
                                             </object>
                                         </object>
-                                        <object class="gbsizeritem" expanded="1">
+                                        <object class="gbsizeritem" expanded="0">
                                             <property name="border">5</property>
                                             <property name="colspan">1</property>
                                             <property name="column">2</property>
                                             <property name="flag">wxALIGN_CENTER_VERTICAL|wxEXPAND|wxTOP|wxBOTTOM</property>
                                             <property name="row">4</property>
                                             <property name="rowspan">1</property>
-                                            <object class="wxBitmapButton" expanded="1">
+                                            <object class="wxBitmapButton" expanded="0">
                                                 <property name="BottomDockable">1</property>
                                                 <property name="LeftDockable">1</property>
                                                 <property name="RightDockable">1</property>
@@ -2914,6 +2914,84 @@
                                 </object>
                             </object>
                         </object>
+                        <object class="sizeritem" expanded="1">
+                            <property name="border">5</property>
+                            <property name="flag">wxALL|wxEXPAND</property>
+                            <property name="proportion">0</property>
+                            <object class="wxStaticBoxSizer" expanded="1">
+                                <property name="id">wxID_ANY</property>
+                                <property name="label">Session</property>
+                                <property name="minimum_size"></property>
+                                <property name="name">sbSizer5</property>
+                                <property name="orient">wxVERTICAL</property>
+                                <property name="parent">1</property>
+                                <property name="permission">none</property>
+                                <object class="sizeritem" expanded="1">
+                                    <property name="border">5</property>
+                                    <property name="flag">wxALL</property>
+                                    <property name="proportion">0</property>
+                                    <object class="wxCheckBox" expanded="1">
+                                        <property name="BottomDockable">1</property>
+                                        <property name="LeftDockable">1</property>
+                                        <property name="RightDockable">1</property>
+                                        <property name="TopDockable">1</property>
+                                        <property name="aui_layer"></property>
+                                        <property name="aui_name"></property>
+                                        <property name="aui_position"></property>
+                                        <property name="aui_row"></property>
+                                        <property name="best_size"></property>
+                                        <property name="bg"></property>
+                                        <property name="caption"></property>
+                                        <property name="caption_visible">1</property>
+                                        <property name="center_pane">0</property>
+                                        <property name="checked">1</property>
+                                        <property name="close_button">1</property>
+                                        <property name="context_help"></property>
+                                        <property name="context_menu">1</property>
+                                        <property name="default_pane">0</property>
+                                        <property name="dock">Dock</property>
+                                        <property name="dock_fixed">0</property>
+                                        <property name="docking">Left</property>
+                                        <property name="enabled">1</property>
+                                        <property name="fg"></property>
+                                        <property name="floatable">1</property>
+                                        <property name="font"></property>
+                                        <property name="gripper">0</property>
+                                        <property name="hidden">0</property>
+                                        <property name="id">wxID_ANY</property>
+                                        <property name="label">Remember open files for next project launch</property>
+                                        <property name="max_size"></property>
+                                        <property name="maximize_button">0</property>
+                                        <property name="maximum_size"></property>
+                                        <property name="min_size"></property>
+                                        <property name="minimize_button">0</property>
+                                        <property name="minimum_size"></property>
+                                        <property name="moveable">1</property>
+                                        <property name="name">m_cbRememberOpenFiles</property>
+                                        <property name="pane_border">1</property>
+                                        <property name="pane_position"></property>
+                                        <property name="pane_size"></property>
+                                        <property name="permission">protected</property>
+                                        <property name="pin_button">1</property>
+                                        <property name="pos"></property>
+                                        <property name="resize">Resizable</property>
+                                        <property name="show">1</property>
+                                        <property name="size"></property>
+                                        <property name="style"></property>
+                                        <property name="subclass">; ; forward_declare</property>
+                                        <property name="toolbar_pane">0</property>
+                                        <property name="tooltip">If checked, launching a project will also launch tools such as eeschema and pcbnew with previously open files</property>
+                                        <property name="validator_data_type"></property>
+                                        <property name="validator_style">wxFILTER_NONE</property>
+                                        <property name="validator_type">wxDefaultValidator</property>
+                                        <property name="validator_variable"></property>
+                                        <property name="window_extra_style"></property>
+                                        <property name="window_name"></property>
+                                        <property name="window_style"></property>
+                                    </object>
+                                </object>
+                            </object>
+                        </object>
                     </object>
                 </object>
             </object>
diff --git a/common/dialogs/panel_common_settings_base.h b/common/dialogs/panel_common_settings_base.h
index 023129b6b9..3fb7609b79 100644
--- a/common/dialogs/panel_common_settings_base.h
+++ b/common/dialogs/panel_common_settings_base.h
@@ -81,6 +81,7 @@ class PANEL_COMMON_SETTINGS_BASE : public RESETTABLE_PANEL
 		wxStaticText* m_staticText16;
 		wxSpinCtrl* m_backupLimitTotalSize;
 		wxStaticText* m_staticText17;
+		wxCheckBox* m_cbRememberOpenFiles;
 
 		// Virtual event handlers, overide them in your derived class
 		virtual void OnTextEditorClick( wxCommandEvent& event ) { event.Skip(); }
diff --git a/common/eda_base_frame.cpp b/common/eda_base_frame.cpp
index 53b27af089..7d780a445d 100644
--- a/common/eda_base_frame.cpp
+++ b/common/eda_base_frame.cpp
@@ -36,6 +36,7 @@
 #include <settings/app_settings.h>
 #include <settings/common_settings.h>
 #include <settings/settings_manager.h>
+#include <project/project_local_settings.h>
 #include <tool/action_manager.h>
 #include <tool/action_menu.h>
 #include <tool/actions.h>
@@ -85,7 +86,8 @@ EDA_BASE_FRAME::EDA_BASE_FRAME( wxWindow* aParent, FRAME_T aFrameType,
         m_autoSaveInterval(-1 ),
         m_UndoRedoCountMax( DEFAULT_MAX_UNDO_ITEMS ),
         m_userUnits( EDA_UNITS::MILLIMETRES ),
-        m_shuttingDown( false )
+        m_isClosing( false ),
+        m_isNonUserClose( false )
 {
     m_autoSaveTimer = new wxTimer( this, ID_AUTO_SAVE_TIMER );
     m_mruPath       = wxStandardPaths::Get().GetDocumentsDir();
@@ -146,12 +148,30 @@ void EDA_BASE_FRAME::windowClosing( wxCloseEvent& event )
         return;
     }
 
-    APP_SETTINGS_BASE* cfg = config();
 
-    if( cfg )
-        SaveSettings( cfg );    // virtual, wxFrame specific
+    if( event.GetId() == wxEVT_QUERY_END_SESSION 
+        || event.GetId() == wxEVT_END_SESSION )
+    {
+        // End session means the OS is going to terminate us
+        m_isNonUserClose = true;
+    }
 
-    event.Skip();       // we did not "handle" the event, only eavesdropped on it.
+    if( canCloseWindow( event ) )
+    {
+        m_isClosing = true;
+        APP_SETTINGS_BASE* cfg = config();
+
+        if( cfg )
+            SaveSettings( cfg );    // virtual, wxFrame specific
+
+        doCloseWindow();
+
+        Destroy();
+    }
+    else
+    {
+        event.Veto();
+    }
 }
 
 
@@ -430,15 +450,25 @@ void EDA_BASE_FRAME::CommonSettingsChanged( bool aEnvVarsChanged, bool aTextVars
 }
 
 
-void EDA_BASE_FRAME::LoadWindowSettings( WINDOW_SETTINGS* aCfg )
+void EDA_BASE_FRAME::LoadWindowState( const wxString& aFileName )
 {
-    m_FramePos.x  = aCfg->pos_x;
-    m_FramePos.y  = aCfg->pos_y;
-    m_FrameSize.x = aCfg->size_x;
-    m_FrameSize.y = aCfg->size_y;
+    const PROJECT_FILE_STATE* state = Prj().GetLocalSettings().GetFileState( aFileName );
+    if( state != nullptr )
+    {
+        LoadWindowState( state->window );
+    }
+}
+
+
+void EDA_BASE_FRAME::LoadWindowState( const WINDOW_STATE& aState )
+{
+    m_FramePos.x  = aState.pos_x;
+    m_FramePos.y  = aState.pos_y;
+    m_FrameSize.x = aState.size_x;
+    m_FrameSize.y = aState.size_y;
 
     wxLogTrace( traceDisplayLocation, "Config position (%d, %d) with size (%d, %d)",
-            m_FramePos.x, m_FramePos.y, m_FrameSize.x, m_FrameSize.y );
+        m_FramePos.x, m_FramePos.y, m_FrameSize.x, m_FrameSize.y );
 
     // Ensure minimum size is set if the stored config was zero-initialized
     if( m_FrameSize.x < s_minsize_x || m_FrameSize.y < s_minsize_y )
@@ -451,7 +481,7 @@ void EDA_BASE_FRAME::LoadWindowSettings( WINDOW_SETTINGS* aCfg )
 
     wxLogTrace( traceDisplayLocation, "Number of displays: %d", wxDisplay::GetCount() );
 
-    if( aCfg->display >= wxDisplay::GetCount() )
+    if( aState.display >= wxDisplay::GetCount() )
     {
         wxLogTrace( traceDisplayLocation, "Previous display not found" );
 
@@ -459,7 +489,7 @@ void EDA_BASE_FRAME::LoadWindowSettings( WINDOW_SETTINGS* aCfg )
         // Warning wxDisplay has 2 ctor variants. the parameter needs a type:
         const unsigned int index = 0;
         wxDisplay display( index );
-        wxRect    clientSize = display.GetClientArea();
+        wxRect    clientSize = display.GetGeometry();
 
         m_FramePos = wxDefaultPosition;
 
@@ -475,11 +505,11 @@ void EDA_BASE_FRAME::LoadWindowSettings( WINDOW_SETTINGS* aCfg )
         wxPoint upperRight( m_FramePos.x + m_FrameSize.x, m_FramePos.y );
         wxPoint upperLeft( m_FramePos.x, m_FramePos.y );
 
-        wxDisplay display( aCfg->display );
-        wxRect clientSize  = display.GetClientArea();
+        wxDisplay display( aState.display );
+        wxRect clientSize = display.GetClientArea();
 
-// The percentage size (represented in decimal) of the region around the screen's border where
-// an upper corner is not allowed
+        // The percentage size (represented in decimal) of the region around the screen's border where
+        // an upper corner is not allowed
 #define SCREEN_BORDER_REGION 0.10
 
         int yLim      = clientSize.y + ( clientSize.height * ( 1.0 - SCREEN_BORDER_REGION ) );
@@ -523,11 +553,17 @@ void EDA_BASE_FRAME::LoadWindowSettings( WINDOW_SETTINGS* aCfg )
     m_NormalFramePos  = m_FramePos;
 
     // Maximize if we were maximized before
-    if( aCfg->maximized )
+    if( aState.maximized )
     {
         wxLogTrace( traceDisplayLocation, "Maximizing window" );
         Maximize();
     }
+}
+
+
+void EDA_BASE_FRAME::LoadWindowSettings( const WINDOW_SETTINGS* aCfg )
+{
+    LoadWindowState( aCfg->state );
 
     if( m_hasAutoSave )
         m_autoSaveInterval = Pgm().GetCommonSettings()->m_System.autosave_interval;
@@ -560,12 +596,12 @@ void EDA_BASE_FRAME::SaveWindowSettings( WINDOW_SETTINGS* aCfg )
         m_FramePos  = GetPosition();
     }
 
-    aCfg->pos_x     = m_FramePos.x;
-    aCfg->pos_y     = m_FramePos.y;
-    aCfg->size_x    = m_FrameSize.x;
-    aCfg->size_y    = m_FrameSize.y;
-    aCfg->maximized = IsMaximized();
-    aCfg->display   = wxDisplay::GetFromWindow( this );
+    aCfg->state.pos_x     = m_FramePos.x;
+    aCfg->state.pos_y     = m_FramePos.y;
+    aCfg->state.size_x    = m_FrameSize.x;
+    aCfg->state.size_y    = m_FrameSize.y;
+    aCfg->state.maximized = IsMaximized();
+    aCfg->state.display   = wxDisplay::GetFromWindow( this );
 
     wxLogTrace( traceDisplayLocation, "Saving window maximized: %s", IsMaximized() ? "true" : "false" );
     wxLogTrace( traceDisplayLocation, "Saving config position (%d, %d) with size (%d, %d)",
@@ -602,6 +638,12 @@ void EDA_BASE_FRAME::SaveSettings( APP_SETTINGS_BASE* aCfg )
 {
     SaveWindowSettings( GetWindowSettings( aCfg ) );
 
+    bool fileOpen = m_isClosing && m_isNonUserClose;
+
+    wxFileName rfn( GetCurrentFileName() );
+    rfn.MakeRelativeTo( Prj().GetProjectPath() );
+    Prj().GetLocalSettings().SaveFileState( rfn.GetFullPath(), &aCfg->m_Window, fileOpen );
+
     // Save the recently used files list
     if( m_fileHistory )
     {
@@ -657,7 +699,7 @@ void EDA_BASE_FRAME::UpdateFileHistory( const wxString& FullFileName, FILE_HISTO
     aFileHistory->AddFileToHistory( FullFileName );
 
     // Update the menubar to update the file history menu
-    if( !m_shuttingDown && GetMenuBar() )
+    if( !m_isClosing && GetMenuBar() )
     {
         ReCreateMenuBar();
         GetMenuBar()->Refresh();
diff --git a/common/kiway.cpp b/common/kiway.cpp
index d936bfec77..820f7050f7 100644
--- a/common/kiway.cpp
+++ b/common/kiway.cpp
@@ -409,7 +409,7 @@ bool KIWAY::PlayerClose( FRAME_T aFrameType, bool doForce )
     if( frame == NULL ) // Already closed
         return true;
 
-    if( frame->Close( doForce ) )
+    if( frame->NonUserClose( doForce ) )
         return true;
 
     return false;
diff --git a/common/kiway_player.cpp b/common/kiway_player.cpp
index 51f2fc362b..0b5cda02ea 100644
--- a/common/kiway_player.cpp
+++ b/common/kiway_player.cpp
@@ -45,7 +45,8 @@ KIWAY_PLAYER::KIWAY_PLAYER( KIWAY* aKiway, wxWindow* aParent, FRAME_T aFrameType
         long aStyle, const wxString& aWdoName ) :
     EDA_BASE_FRAME( aParent, aFrameType, aTitle, aPos, aSize, aStyle, aWdoName, aKiway ),
     m_modal( false ),
-    m_modal_loop( 0 ), m_modal_resultant_parent( 0 )
+    m_modal_loop( 0 ),
+    m_modal_resultant_parent( 0 )
 {
     m_modal_ret_val = 0;
 }
diff --git a/common/project/project_local_settings.cpp b/common/project/project_local_settings.cpp
index 56967fd784..4cf4dfe51a 100644
--- a/common/project/project_local_settings.cpp
+++ b/common/project/project_local_settings.cpp
@@ -103,24 +103,17 @@ PROJECT_LOCAL_SETTINGS::PROJECT_LOCAL_SETTINGS( PROJECT* aProject, const wxStrin
                 if( aVal.empty() || !aVal.is_object() )
                     return;
 
-                auto setIfPresent =
-                        [&aVal]( const std::string& aKey, bool& aTarget )
-                        {
-                            if( aVal.contains( aKey ) && aVal.at( aKey ).is_boolean() )
-                                aTarget = aVal.at( aKey ).get<bool>();
-                        };
-
-                setIfPresent( "lockedItems", m_SelectionFilter.lockedItems );
-                setIfPresent( "footprints", m_SelectionFilter.footprints );
-                setIfPresent( "text", m_SelectionFilter.text );
-                setIfPresent( "tracks", m_SelectionFilter.tracks );
-                setIfPresent( "vias", m_SelectionFilter.vias );
-                setIfPresent( "pads", m_SelectionFilter.pads );
-                setIfPresent( "graphics", m_SelectionFilter.graphics );
-                setIfPresent( "zones", m_SelectionFilter.zones );
-                setIfPresent( "keepouts", m_SelectionFilter.keepouts );
-                setIfPresent( "dimensions", m_SelectionFilter.dimensions );
-                setIfPresent( "otherItems", m_SelectionFilter.otherItems );
+                SetIfPresent( aVal, "lockedItems", m_SelectionFilter.lockedItems );
+                SetIfPresent( aVal, "footprints", m_SelectionFilter.footprints );
+                SetIfPresent( aVal, "text", m_SelectionFilter.text );
+                SetIfPresent( aVal, "tracks", m_SelectionFilter.tracks );
+                SetIfPresent( aVal, "vias", m_SelectionFilter.vias );
+                SetIfPresent( aVal, "pads", m_SelectionFilter.pads );
+                SetIfPresent( aVal, "graphics", m_SelectionFilter.graphics );
+                SetIfPresent( aVal, "zones", m_SelectionFilter.zones );
+                SetIfPresent( aVal, "keepouts", m_SelectionFilter.keepouts );
+                SetIfPresent( aVal, "dimensions", m_SelectionFilter.dimensions );
+                SetIfPresent( aVal, "otherItems", m_SelectionFilter.otherItems );
             },
             {
                 { "lockedItems", true },
@@ -163,6 +156,65 @@ PROJECT_LOCAL_SETTINGS::PROJECT_LOCAL_SETTINGS( PROJECT* aProject, const wxStrin
             &m_ZoneDisplayMode, ZONE_DISPLAY_MODE::SHOW_FILLED, ZONE_DISPLAY_MODE::SHOW_OUTLINED,
             ZONE_DISPLAY_MODE::SHOW_FILLED ) );
 #endif
+
+    m_params.emplace_back( new PARAM_LAMBDA<nlohmann::json>( "project.files",
+            [&]() -> nlohmann::json
+            {
+                nlohmann::json ret = nlohmann::json::array();
+
+                for( PROJECT_FILE_STATE& fileState : m_files )
+                {
+                    nlohmann::json file;
+                    file["name"] = fileState.fileName;
+                    file["open"] = fileState.open;
+
+                    nlohmann::json window;
+                    window["maximized"] = fileState.window.maximized;
+                    window["size_x"]    = fileState.window.size_x;
+                    window["size_y"]    = fileState.window.size_y;
+                    window["pos_x"]     = fileState.window.pos_x;
+                    window["pos_y"]     = fileState.window.pos_y;
+                    window["display"]   = fileState.window.display;
+
+                    file["window"] = window;
+
+                    ret.push_back( file );
+                }
+
+                return ret;
+            },
+            [&]( const nlohmann::json& aVal )
+            {
+                if( !aVal.is_array() || aVal.empty() )
+                {
+                    return;
+                }
+
+                for( const nlohmann::json& file : aVal )
+                {
+                    PROJECT_FILE_STATE fileState;
+                    try
+                    {
+                        SetIfPresent( file, "name", fileState.fileName );
+                        SetIfPresent( file, "open", fileState.open );
+                        SetIfPresent( file, "window.size_x", fileState.window.size_x );
+                        SetIfPresent( file, "window.size_y", fileState.window.size_y );
+                        SetIfPresent( file, "window.pos_x", fileState.window.pos_x );
+                        SetIfPresent( file, "window.pos_y", fileState.window.pos_y );
+                        SetIfPresent( file, "window.maximized", fileState.window.maximized );
+                        SetIfPresent( file, "window.display", fileState.window.display );
+
+                        m_files.push_back( fileState );
+                    }
+                    catch( ... )
+                    {
+                        // Non-integer or out of range entry in the array; ignore
+                    }
+                }
+
+            },
+            {
+            } ) );
 }
 
 
@@ -229,3 +281,50 @@ bool PROJECT_LOCAL_SETTINGS::migrateSchema1to2()
     
     return true;
 }
+
+
+const PROJECT_FILE_STATE* PROJECT_LOCAL_SETTINGS::GetFileState( const wxString& aFileName )
+{
+    auto it = std::find_if( m_files.begin(), m_files.end(), 
+                            [&aFileName]( const PROJECT_FILE_STATE &a )
+                            {
+                                return a.fileName == aFileName;
+                            } );
+
+    if( it != m_files.end() )
+    {
+        return &( *it );
+    }
+
+    return nullptr;
+}
+
+
+void PROJECT_LOCAL_SETTINGS::SaveFileState( const wxString& aFileName, const WINDOW_SETTINGS* aWindowCfg, 
+                                            bool aOpen )
+{
+    auto it = std::find_if( m_files.begin(), m_files.end(),
+                            [&aFileName]( const PROJECT_FILE_STATE& a ) 
+                            { 
+                                return a.fileName == aFileName; 
+                            } );
+
+    if( it == m_files.end() )
+    {
+        PROJECT_FILE_STATE fileState;
+        fileState.fileName = aFileName;
+
+        m_files.push_back( fileState );
+
+        it = m_files.end() - 1;
+    }
+
+    ( *it ).window = aWindowCfg->state;
+    ( *it ).open   = aOpen;
+}
+
+
+void PROJECT_LOCAL_SETTINGS::ClearFileState()
+{
+    m_files.clear();
+}
\ No newline at end of file
diff --git a/common/settings/app_settings.cpp b/common/settings/app_settings.cpp
index b281aa14fe..9d1d31b3ea 100644
--- a/common/settings/app_settings.cpp
+++ b/common/settings/app_settings.cpp
@@ -262,23 +262,23 @@ bool APP_SETTINGS_BASE::migrateWindowConfig( wxConfigBase* aCfg, const std::stri
 void APP_SETTINGS_BASE::addParamsForWindow( WINDOW_SETTINGS* aWindow, const std::string& aJsonPath )
 {
     m_params.emplace_back( new PARAM<bool>( aJsonPath + ".maximized",
-            &aWindow->maximized, false ) );
+            &aWindow->state.maximized, false ) );
 
     m_params.emplace_back( new PARAM<wxString>( aJsonPath + ".mru_path",
             &aWindow->mru_path, "" ) );
 
-    m_params.emplace_back( new PARAM<int>( aJsonPath + ".size_x", &aWindow->size_x, 0 ) );
+    m_params.emplace_back( new PARAM<int>( aJsonPath + ".size_x", &aWindow->state.size_x, 0 ) );
 
-    m_params.emplace_back( new PARAM<int>( aJsonPath + ".size_y", &aWindow->size_y, 0 ) );
+    m_params.emplace_back( new PARAM<int>( aJsonPath + ".size_y", &aWindow->state.size_y, 0 ) );
 
     m_params.emplace_back( new PARAM<wxString>( aJsonPath + ".perspective",
             &aWindow->perspective, "" ) );
 
-    m_params.emplace_back( new PARAM<int>( aJsonPath + ".pos_x", &aWindow->pos_x, 0 ) );
+    m_params.emplace_back( new PARAM<int>( aJsonPath + ".pos_x", &aWindow->state.pos_x, 0 ) );
 
-    m_params.emplace_back( new PARAM<int>( aJsonPath + ".pos_y", &aWindow->pos_y, 0 ) );
+    m_params.emplace_back( new PARAM<int>( aJsonPath + ".pos_y", &aWindow->state.pos_y, 0 ) );
 
-    m_params.emplace_back( new PARAM<unsigned int>( aJsonPath + ".display", &aWindow->display, 0 ) );
+    m_params.emplace_back( new PARAM<unsigned int>( aJsonPath + ".display", &aWindow->state.display, 0 ) );
 
     m_params.emplace_back( new PARAM_LIST<double>( aJsonPath + ".zoom_factors",
             &aWindow->zoom_factors, {} ) );
diff --git a/common/settings/common_settings.cpp b/common/settings/common_settings.cpp
index a6ca18dabc..27c33c4bc5 100644
--- a/common/settings/common_settings.cpp
+++ b/common/settings/common_settings.cpp
@@ -176,6 +176,8 @@ COMMON_SETTINGS::COMMON_SETTINGS() :
     m_params.emplace_back( new PARAM<int>( "system.clear_3d_cache_interval",
             &m_System.clear_3d_cache_interval, 30 ) );
 
+    m_params.emplace_back( new PARAM<bool>( "session.remember_open_files",
+        &m_Session.remember_open_files, false ) );
 }
 
 
diff --git a/common/settings/json_settings.cpp b/common/settings/json_settings.cpp
index bf73f781ec..3af724c933 100644
--- a/common/settings/json_settings.cpp
+++ b/common/settings/json_settings.cpp
@@ -448,6 +448,66 @@ nlohmann::json::json_pointer JSON_SETTINGS::PointerFromString( std::string aPath
 }
 
 
+bool JSON_SETTINGS::SetIfPresent( const nlohmann::json& aObj, const std::string& aPath, 
+                                  wxString& aTarget )
+{
+    nlohmann::json::json_pointer ptr = PointerFromString( aPath );
+
+    if( aObj.contains( ptr ) && aObj.at( ptr ).is_string() )
+    {
+        aTarget = aObj.at( ptr ).get<wxString>();
+        return true;
+    }
+
+    return false;
+}
+
+
+bool JSON_SETTINGS::SetIfPresent( const nlohmann::json& aObj, const std::string& aPath, 
+                                  bool& aTarget )
+{
+    nlohmann::json::json_pointer ptr = PointerFromString( aPath );
+
+    if( aObj.contains( ptr ) && aObj.at( ptr ).is_boolean() )
+    {
+        aTarget = aObj.at( ptr ).get<bool>();
+        return true;
+    }
+
+    return false;
+}
+
+
+bool JSON_SETTINGS::SetIfPresent( const nlohmann::json& aObj, const std::string& aPath, 
+                                  int& aTarget )
+{
+    nlohmann::json::json_pointer ptr = PointerFromString( aPath );
+
+    if( aObj.contains( ptr ) && aObj.at( ptr ).is_number_integer() )
+    {
+        aTarget = aObj.at( ptr ).get<int>();
+        return true;
+    }
+
+    return false;
+}
+
+
+bool JSON_SETTINGS::SetIfPresent( const nlohmann::json& aObj, const std::string& aPath, 
+                                  unsigned int& aTarget )
+{
+    nlohmann::json::json_pointer ptr = PointerFromString( aPath );
+
+    if( aObj.contains( ptr ) && aObj.at( ptr ).is_number_unsigned() )
+    {
+        aTarget = aObj.at( ptr ).get<unsigned int>();
+        return true;
+    }
+
+    return false;
+}
+
+
 template<typename ValueType>
 bool JSON_SETTINGS::fromLegacy( wxConfigBase* aConfig, const std::string& aKey,
                              const std::string& aDest )
diff --git a/cvpcb/cvpcb_mainframe.cpp b/cvpcb/cvpcb_mainframe.cpp
index a039d9ccbe..8f865263af 100644
--- a/cvpcb/cvpcb_mainframe.cpp
+++ b/cvpcb/cvpcb_mainframe.cpp
@@ -307,7 +307,6 @@ void CVPCB_MAINFRAME::setupEventHandlers()
             }, wxID_CANCEL );
 
     // Connect the handlers for the close events
-    Bind( wxEVT_CLOSE_WINDOW, &CVPCB_MAINFRAME::OnCloseWindow, this );
     Bind( wxEVT_MENU,
             [this]( wxCommandEvent& )
             {
@@ -336,26 +335,30 @@ void CVPCB_MAINFRAME::setupEventHandlers()
 }
 
 
-void CVPCB_MAINFRAME::OnCloseWindow( wxCloseEvent& aEvent )
+bool CVPCB_MAINFRAME::canCloseWindow( wxCloseEvent& aEvent )
 {
     if( m_modified )
     {
         // Shutdown blocks must be determined and vetoed as early as possible
         if( SupportsShutdownBlockReason() && aEvent.GetId() == wxEVT_QUERY_END_SESSION )
         {
-            aEvent.Veto();
-            return;
+            return false;
         }
 
         if( !HandleUnsavedChanges( this, _( "Symbol to Footprint links have been modified. "
                                             "Save changes?" ),
                                    [&]()->bool { return SaveFootprintAssociation( false ); } ) )
         {
-            aEvent.Veto();
-            return;
+            return false;
         }
     }
 
+    return true;
+}
+
+
+void CVPCB_MAINFRAME::doCloseWindow()
+{
     // Close module display frame
     if( GetFootprintViewerFrame() )
         GetFootprintViewerFrame()->Close( true );
@@ -364,10 +367,6 @@ void CVPCB_MAINFRAME::OnCloseWindow( wxCloseEvent& aEvent )
 
     // clear highlight symbol in schematic:
     SendMessageToEESCHEMA( true );
-
-    // Skip the close event. Looks like needed to have the close event sent to the
-    // root class EDA_BASE_FRAME, and save config
-    aEvent.Skip();
 }
 
 
diff --git a/cvpcb/cvpcb_mainframe.h b/cvpcb/cvpcb_mainframe.h
index b93ec763fb..60db20d772 100644
--- a/cvpcb/cvpcb_mainframe.h
+++ b/cvpcb/cvpcb_mainframe.h
@@ -181,12 +181,8 @@ public:
      */
     void OnSelectComponent( wxListEvent& event );
 
-    /**
-     * OnCloseWindow
-     *
-     * Called by a close event to close the window
-     */
-    void OnCloseWindow( wxCloseEvent& Event );
+    bool canCloseWindow( wxCloseEvent& aCloseEvent ) override;
+    void doCloseWindow() override;
 
     /*
      * Functions to rebuild the toolbars and menubars
diff --git a/cvpcb/display_footprints_frame.cpp b/cvpcb/display_footprints_frame.cpp
index 74480d4421..21c8dfa5e6 100644
--- a/cvpcb/display_footprints_frame.cpp
+++ b/cvpcb/display_footprints_frame.cpp
@@ -219,7 +219,7 @@ void DISPLAY_FOOTPRINTS_FRAME::setupUIConditions()
 }
 
 
-void DISPLAY_FOOTPRINTS_FRAME::OnCloseWindow( wxCloseEvent& event )
+void DISPLAY_FOOTPRINTS_FRAME::doCloseWindow()
 {
     Destroy();
 }
diff --git a/cvpcb/display_footprints_frame.h b/cvpcb/display_footprints_frame.h
index 28eb61c384..9178446052 100644
--- a/cvpcb/display_footprints_frame.h
+++ b/cvpcb/display_footprints_frame.h
@@ -47,7 +47,7 @@ public:
     DISPLAY_FOOTPRINTS_FRAME( KIWAY* aKiway, wxWindow* aParent );
     ~DISPLAY_FOOTPRINTS_FRAME() override;
 
-    void    OnCloseWindow( wxCloseEvent& Event ) override;
+    void    doCloseWindow() override;
 
     void    ReCreateHToolbar() override;
     void    ReCreateVToolbar() override;
diff --git a/eeschema/eeschema_settings.cpp b/eeschema/eeschema_settings.cpp
index b2d56b4eb7..7f8352e7c4 100644
--- a/eeschema/eeschema_settings.cpp
+++ b/eeschema/eeschema_settings.cpp
@@ -250,22 +250,22 @@ EESCHEMA_SETTINGS::EESCHEMA_SETTINGS() :
             &m_PlotPanel.hpgl_origin, false ) );
 
     m_params.emplace_back( new PARAM<int>( "simulator.window.pos_x",
-            &m_Simulator.window.pos_x, 0 ) );
+            &m_Simulator.window.state.pos_x, 0 ) );
 
     m_params.emplace_back( new PARAM<int>( "simulator.window.pos_y",
-            &m_Simulator.window.pos_y, 0 ) );
+            &m_Simulator.window.state.pos_y, 0 ) );
 
     m_params.emplace_back( new PARAM<int>( "simulator.window.size_x",
-            &m_Simulator.window.size_x, 500 ) );
+            &m_Simulator.window.state.size_x, 500 ) );
 
     m_params.emplace_back( new PARAM<int>( "simulator.window.size_y",
-            &m_Simulator.window.size_y, 400 ) );
+            &m_Simulator.window.state.size_y, 400 ) );
 
     m_params.emplace_back( new PARAM<unsigned int>( "simulator.window.display",
-            &m_Simulator.window.display, 0 ) );
+            &m_Simulator.window.state.display, 0 ) );
 
     m_params.emplace_back( new PARAM<bool>( "simulator.window.maximized",
-            &m_Simulator.window.maximized, false ) );
+            &m_Simulator.window.state.maximized, false ) );
 
     m_params.emplace_back( new PARAM<wxString>( "simulator.window.perspective",
             &m_Simulator.window.perspective, "" ) );
@@ -307,22 +307,22 @@ EESCHEMA_SETTINGS::EESCHEMA_SETTINGS() :
             &m_RescueNeverShow, false ) );
 
     m_params.emplace_back( new PARAM<int>( "lib_view.window.pos_x",
-            &m_LibViewPanel.window.pos_x, 0 ) );
+            &m_LibViewPanel.window.state.pos_x, 0 ) );
 
     m_params.emplace_back( new PARAM<int>( "lib_view.window.pos_y",
-            &m_LibViewPanel.window.pos_y, 0 ) );
+            &m_LibViewPanel.window.state.pos_y, 0 ) );
 
     m_params.emplace_back( new PARAM<int>( "lib_view.window.size_x",
-            &m_LibViewPanel.window.size_x, 500 ) );
+            &m_LibViewPanel.window.state.size_x, 500 ) );
 
     m_params.emplace_back( new PARAM<int>( "lib_view.window.size_y",
-            &m_LibViewPanel.window.size_y, 400 ) );
+            &m_LibViewPanel.window.state.size_y, 400 ) );
 
     m_params.emplace_back( new PARAM<unsigned int>( "lib_view.window.display",
-            &m_LibViewPanel.window.display, 0 ) );
+            &m_LibViewPanel.window.state.display, 0 ) );
 
     m_params.emplace_back( new PARAM<bool>( "lib_view.window.maximized",
-            &m_LibViewPanel.window.maximized, false ) );
+            &m_LibViewPanel.window.state.maximized, false ) );
 
     m_params.emplace_back( new PARAM<wxString>( "lib_view.window.perspective",
             &m_LibViewPanel.window.perspective, "" ) );
diff --git a/eeschema/files-io.cpp b/eeschema/files-io.cpp
index db56ebb64a..6057ce0c1b 100644
--- a/eeschema/files-io.cpp
+++ b/eeschema/files-io.cpp
@@ -320,6 +320,10 @@ bool SCH_EDIT_FRAME::OpenProjectFiles( const std::vector<wxString>& aFileSet, in
     // update some of the needed schematic settings such as drawing defaults
     LoadProjectSettings();
 
+    wxFileName rfn( GetCurrentFileName() );
+    rfn.MakeRelativeTo( Prj().GetProjectPath() );
+    LoadWindowState( rfn.GetFullPath() );
+
     SetShutdownBlockReason( _( "Schematic file changes are unsaved" ) );
     if( Kiface().IsSingle() )
     {
diff --git a/eeschema/libedit/lib_edit_frame.cpp b/eeschema/libedit/lib_edit_frame.cpp
index e600f70edb..a99d8f8e99 100644
--- a/eeschema/libedit/lib_edit_frame.cpp
+++ b/eeschema/libedit/lib_edit_frame.cpp
@@ -71,7 +71,6 @@
 bool LIB_EDIT_FRAME::          m_showDeMorgan    = false;
 
 BEGIN_EVENT_TABLE( LIB_EDIT_FRAME, EDA_DRAW_FRAME )
-    EVT_CLOSE( LIB_EDIT_FRAME::OnCloseWindow )
     EVT_SIZE( LIB_EDIT_FRAME::OnSize )
 
     EVT_COMBOBOX( ID_LIBEDIT_SELECT_PART_NUMBER, LIB_EDIT_FRAME::OnSelectUnit )
@@ -431,20 +430,27 @@ void LIB_EDIT_FRAME::setupUIConditions()
 }
 
 
-void LIB_EDIT_FRAME::OnCloseWindow( wxCloseEvent& aEvent )
+bool LIB_EDIT_FRAME::canCloseWindow(wxCloseEvent& aEvent)
 {
     // Shutdown blocks must be determined and vetoed as early as possible
     if( SupportsShutdownBlockReason() && aEvent.GetId() == wxEVT_QUERY_END_SESSION
-            && IsContentModified() )
+        && IsContentModified() )
     {
-        aEvent.Veto();
-        return;
+        return false;
     }
 
-    if( saveAllLibraries( true ) )
-        Destroy();
-    else
-        aEvent.Veto();
+    if( !saveAllLibraries( true ) )
+    {
+        return false;
+    }
+
+    return true;
+}
+
+
+void LIB_EDIT_FRAME::doCloseWindow()
+{
+    Destroy();
 }
 
 
diff --git a/eeschema/libedit/lib_edit_frame.h b/eeschema/libedit/lib_edit_frame.h
index 07427d85af..18fa49223f 100644
--- a/eeschema/libedit/lib_edit_frame.h
+++ b/eeschema/libedit/lib_edit_frame.h
@@ -213,7 +213,8 @@ public:
     void UpdateAfterSymbolProperties( wxString* aOldName = nullptr );
     void RebuildSymbolUnitsList();
 
-    void OnCloseWindow( wxCloseEvent& Event );
+    bool canCloseWindow( wxCloseEvent& aCloseEvent ) override;
+    void doCloseWindow() override;
     void OnExitKiCad( wxCommandEvent& event );
     void ReCreateHToolbar() override;
     void ReCreateVToolbar() override;
diff --git a/eeschema/sch_edit_frame.cpp b/eeschema/sch_edit_frame.cpp
index 891220de44..a84123f435 100644
--- a/eeschema/sch_edit_frame.cpp
+++ b/eeschema/sch_edit_frame.cpp
@@ -191,7 +191,6 @@ BEGIN_EVENT_TABLE( SCH_EDIT_FRAME, EDA_DRAW_FRAME )
     EVT_SOCKET( ID_EDA_SOCKET_EVENT_SERV, EDA_DRAW_FRAME::OnSockRequestServer )
     EVT_SOCKET( ID_EDA_SOCKET_EVENT, EDA_DRAW_FRAME::OnSockRequest )
 
-    EVT_CLOSE( SCH_EDIT_FRAME::OnCloseWindow )
     EVT_SIZE( SCH_EDIT_FRAME::OnSize )
 
     EVT_MENU_RANGE( ID_FILE1, ID_FILEMAX, SCH_EDIT_FRAME::OnLoadFile )
@@ -576,40 +575,39 @@ void SCH_EDIT_FRAME::HardRedraw()
 }
 
 
-void SCH_EDIT_FRAME::OnCloseWindow( wxCloseEvent& aEvent )
+bool SCH_EDIT_FRAME::canCloseWindow( wxCloseEvent& aEvent )
 {
     // Shutdown blocks must be determined and vetoed as early as possible
     if( SupportsShutdownBlockReason() && aEvent.GetId() == wxEVT_QUERY_END_SESSION
-            && Schematic().GetSheets().IsModified() )
+        && Schematic().GetSheets().IsModified() )
     {
-        aEvent.Veto();
-        return;
+        return false;
     }
 
     if( Kiface().IsSingle() )
     {
         LIB_EDIT_FRAME* libeditFrame = (LIB_EDIT_FRAME*) Kiway().Player( FRAME_SCH_LIB_EDITOR, false );
         if( libeditFrame && !libeditFrame->Close() )   // Can close component editor?
-            return;
+            return false;
 
         LIB_VIEW_FRAME* viewlibFrame = (LIB_VIEW_FRAME*) Kiway().Player( FRAME_SCH_VIEWER, false );
         if( viewlibFrame && !viewlibFrame->Close() )   // Can close component viewer?
-            return;
+            return false;
 
         viewlibFrame = (LIB_VIEW_FRAME*) Kiway().Player( FRAME_SCH_VIEWER_MODAL, false );
 
         if( viewlibFrame && !viewlibFrame->Close() )   // Can close modal component viewer?
-            return;
+            return false;
     }
 
     SIM_PLOT_FRAME* simFrame = (SIM_PLOT_FRAME*) Kiway().Player( FRAME_SIMULATOR, false );
 
     if( simFrame && !simFrame->Close() )   // Can close the simulator?
-        return;
+        return false;
 
     // We may have gotten multiple events; don't clean up twice
     if( !Schematic().IsValid() )
-        return;
+        return false;
 
     SCH_SHEET_LIST sheetlist = Schematic().GetSheets();
 
@@ -621,15 +619,17 @@ void SCH_EDIT_FRAME::OnCloseWindow( wxCloseEvent& aEvent )
         if( !HandleUnsavedChanges( this, wxString::Format( msg, fileName.GetFullName() ),
                                    [&]()->bool { return SaveProject(); } ) )
         {
-            aEvent.Veto();
-            return;
+            return false;
         }
     }
 
-    //
-    // OK, we're really closing now.  No more returns after this.
-    //
-    m_shuttingDown = true;
+    return true;
+}
+
+
+void SCH_EDIT_FRAME::doCloseWindow()
+{
+    SCH_SHEET_LIST sheetlist = Schematic().GetSheets();
 
     // Shutdown all running tools ( and commit any pending change )
     if( m_toolManager )
diff --git a/eeschema/sch_edit_frame.h b/eeschema/sch_edit_frame.h
index 6f09237a19..ca471e4327 100644
--- a/eeschema/sch_edit_frame.h
+++ b/eeschema/sch_edit_frame.h
@@ -166,8 +166,6 @@ public:
 
     SCHEMATIC& Schematic() const;
 
-    void OnCloseWindow( wxCloseEvent& Event );
-
     /**
      * Allow edit frame to show/hide hidden pins.
      */
@@ -628,6 +626,9 @@ private:
 
     void OnClearFileHistory( wxCommandEvent& aEvent );
 
+    bool canCloseWindow( wxCloseEvent& aCloseEvent ) override;
+    void doCloseWindow() override;
+
     /**
      * Set the main window title bar text.
      *
diff --git a/eeschema/sim/sim_plot_frame.cpp b/eeschema/sim/sim_plot_frame.cpp
index 19de776c07..b081863110 100644
--- a/eeschema/sim/sim_plot_frame.cpp
+++ b/eeschema/sim/sim_plot_frame.cpp
@@ -166,7 +166,6 @@ SIM_PLOT_FRAME::SIM_PLOT_FRAME( KIWAY* aKiway, wxWindow* aParent )
 
     updateNetlistExporter();
 
-    Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( SIM_PLOT_FRAME::onClose ), NULL, this );
     Connect( EVT_SIM_UPDATE, wxCommandEventHandler( SIM_PLOT_FRAME::onSimUpdate ), NULL, this );
     Connect( EVT_SIM_REPORT, wxCommandEventHandler( SIM_PLOT_FRAME::onSimReport ), NULL, this );
     Connect( EVT_SIM_STARTED, wxCommandEventHandler( SIM_PLOT_FRAME::onSimStarted ), NULL, this );
@@ -1409,7 +1408,7 @@ void SIM_PLOT_FRAME::onShowNetlist( wxCommandEvent& event )
 }
 
 
-void SIM_PLOT_FRAME::onClose( wxCloseEvent& aEvent )
+void SIM_PLOT_FRAME::doCloseWindow()
 {
     SaveSettings( config() );
 
diff --git a/eeschema/sim/sim_plot_frame.h b/eeschema/sim/sim_plot_frame.h
index 65cceef1c9..c24a0f72ec 100644
--- a/eeschema/sim/sim_plot_frame.h
+++ b/eeschema/sim/sim_plot_frame.h
@@ -328,7 +328,7 @@ private:
     void onTune( wxCommandEvent& event );
     void onShowNetlist( wxCommandEvent& event );
 
-    void onClose( wxCloseEvent& aEvent );
+    void doCloseWindow() override;
 
     void onCursorUpdate( wxCommandEvent& aEvent );
     void onSimUpdate( wxCommandEvent& aEvent );
diff --git a/gerbview/gerbview_frame.cpp b/gerbview/gerbview_frame.cpp
index 0998d1d7d8..0261a03fe5 100644
--- a/gerbview/gerbview_frame.cpp
+++ b/gerbview/gerbview_frame.cpp
@@ -222,8 +222,10 @@ GERBVIEW_FRAME::~GERBVIEW_FRAME()
 }
 
 
-void GERBVIEW_FRAME::OnCloseWindow( wxCloseEvent& Event )
+void GERBVIEW_FRAME::doCloseWindow()
 {
+    // No more vetos
+    m_isClosing = true;
     GetCanvas()->StopDrawing();
     GetCanvas()->GetView()->Clear();
 
diff --git a/gerbview/gerbview_frame.h b/gerbview/gerbview_frame.h
index a75c520ed5..85bf07f606 100644
--- a/gerbview/gerbview_frame.h
+++ b/gerbview/gerbview_frame.h
@@ -212,7 +212,7 @@ public:
     GERBVIEW_FRAME( KIWAY* aKiway, wxWindow* aParent );
     ~GERBVIEW_FRAME();
 
-    void OnCloseWindow( wxCloseEvent& Event );
+    void doCloseWindow() override;
 
     bool OpenProjectFiles( const std::vector<wxString>& aFileSet, int aCtl ) override;
 
diff --git a/include/eda_base_frame.h b/include/eda_base_frame.h
index 39acb537ae..d75e5c65b0 100644
--- a/include/eda_base_frame.h
+++ b/include/eda_base_frame.h
@@ -79,6 +79,7 @@ class SETTINGS_MANAGER;
 class APP_SETTINGS_BASE;
 class WX_INFOBAR;
 struct WINDOW_SETTINGS;
+struct WINDOW_STATE;
 
 enum id_librarytype {
     LIBRARY_TYPE_EESCHEMA,
@@ -163,10 +164,11 @@ protected:
 
     EDA_UNITS       m_userUnits;
 
-    bool            m_shuttingDown;
-
     // Map containing the UI update handlers registered with wx for each action
     std::map<int, UIUpdateHandler> m_uiUpdateMap;
+    bool            m_isClosing;            // Set by the close window event handler after frames are asked if they can close
+                                            // Allows other functions when called to know our state is cleanup
+    bool            m_isNonUserClose;       // Set by NonUserClose() to indicate that the user did not request the current close
 
     ///> Default style flags used for wxAUI toolbars
     static constexpr int KICAD_AUI_TB_STYLE = wxAUI_TB_DEFAULT_STYLE | wxAUI_TB_PLAIN_BACKGROUND;
@@ -206,6 +208,9 @@ protected:
      */
     virtual bool doAutoSave();
 
+    virtual bool canCloseWindow( wxCloseEvent& aCloseEvent ) { return true; }
+    virtual void doCloseWindow() { }
+
     /**
      * Called when when the units setting has changed to allow for any derived classes
      * to handle refreshing and controls that have units based measurements in them.  The
@@ -351,12 +356,14 @@ public:
      */
     virtual void InstallPreferences( PAGED_DIALOG* , PANEL_HOTKEYS_EDITOR* ) { }
 
+
+    void LoadWindowState( const wxString& aFileName );
     /**
      * Loads window settings from the given settings object
      * Normally called by LoadSettings unless the window in question is a child window that
      * stores its settings somewhere other than APP_SETTINGS_BASE::m_Window
      */
-    void LoadWindowSettings( WINDOW_SETTINGS* aCfg );
+    void LoadWindowSettings( const WINDOW_SETTINGS* aCfg );
 
     /**
      * Saves window settings to the given settings object
@@ -389,6 +396,11 @@ public:
      */
     virtual WINDOW_SETTINGS* GetWindowSettings( APP_SETTINGS_BASE* aCfg );
 
+    /**
+    * Load frame state info from a configuration file
+    */
+    virtual void LoadWindowState( const WINDOW_STATE& aState );
+
     /**
      * @return a base name prefix used in Load/Save settings to build the full name of keys
      * used in config.
@@ -644,6 +656,8 @@ public:
     virtual int GetRedoCommandCount() const { return m_redoList.m_CommandsList.size(); }
 
     int GetMaxUndoItems() const { return m_UndoRedoCountMax; }
+
+    bool NonUserClose( bool aForce ) { m_isNonUserClose = true; return Close( aForce ); };
 };
 
 
diff --git a/include/pcb_base_frame.h b/include/pcb_base_frame.h
index 174b7fccbf..475887f0ac 100644
--- a/include/pcb_base_frame.h
+++ b/include/pcb_base_frame.h
@@ -211,7 +211,6 @@ public:
     void FocusOnItem( BOARD_ITEM* aItem );
 
     // General
-    virtual void OnCloseWindow( wxCloseEvent& Event ) = 0;
     virtual void ReCreateOptToolbar() override { }
     virtual void ShowChangedLanguage() override;
     virtual void ReCreateMenuBar() override;
diff --git a/include/project/project_local_settings.h b/include/project/project_local_settings.h
index 8cfb853588..3545be01ed 100644
--- a/include/project/project_local_settings.h
+++ b/include/project/project_local_settings.h
@@ -25,9 +25,18 @@
 #include <project/board_project_settings.h>
 #include <settings/json_settings.h>
 #include <wildcards_and_files_ext.h>
+#include <settings/app_settings.h>
 
 class PROJECT;
 
+struct PROJECT_FILE_STATE
+{
+    wxString fileName;
+    bool open;
+    struct WINDOW_STATE window;
+};
+
+
 /**
  * The project local settings are things that are attached to a particular project, but also might
  * be particular to a certain user editing that project, or change quickly, and therefore may not
@@ -80,6 +89,13 @@ private:
 
 public:
 
+    /**
+     * Project scope
+     */
+
+    /// File based state
+    std::vector<PROJECT_FILE_STATE> m_files;
+
     /**
      * Board settings
      */
@@ -118,6 +134,12 @@ public:
 
     /// State of the selection filter widget
     SELECTION_FILTER_OPTIONS m_SelectionFilter;
+
+    void SaveFileState( const wxString& aFileName, const WINDOW_SETTINGS* aWindowCfg, bool aOpen );
+
+    const PROJECT_FILE_STATE* GetFileState( const wxString& aFileName );
+
+    void ClearFileState();
 };
 
 #endif
diff --git a/include/settings/app_settings.h b/include/settings/app_settings.h
index 0295aaf656..ca19a36588 100644
--- a/include/settings/app_settings.h
+++ b/include/settings/app_settings.h
@@ -61,21 +61,27 @@ struct GRID_SETTINGS
     int style;
 };
 
+/**
+* Stores the window positioning/state
+*/
+struct WINDOW_STATE
+{
+    bool maximized;
+    int size_x;
+    int size_y;
+    int pos_x;
+    int pos_y;
+    unsigned int display;
+};
 
 /**
  * Stores the common settings that are saved and loaded for each window / frame
  */
 struct WINDOW_SETTINGS
 {
-    bool maximized;
+    WINDOW_STATE state;
     wxString mru_path;
-    int size_x;
-    int size_y;
     wxString perspective;
-    int pos_x;
-    int pos_y;
-    unsigned int display;
-
     std::vector<double> zoom_factors;
 
     CURSOR_SETTINGS cursor;
diff --git a/include/settings/common_settings.h b/include/settings/common_settings.h
index 5bcbb746c0..32b19a4754 100644
--- a/include/settings/common_settings.h
+++ b/include/settings/common_settings.h
@@ -80,6 +80,11 @@ public:
         int opengl_aa_mode;
     };
 
+    struct SESSION
+    {
+        bool remember_open_files;
+    };
+
     struct SYSTEM
     {
         int autosave_interval;
@@ -114,6 +119,8 @@ public:
 
     GRAPHICS m_Graphics;
 
+    SESSION m_Session;
+
     SYSTEM m_System;
 
     // TODO: These may not want to be in common
diff --git a/include/settings/json_settings.h b/include/settings/json_settings.h
index 83b7df1efc..c72682fc18 100644
--- a/include/settings/json_settings.h
+++ b/include/settings/json_settings.h
@@ -184,6 +184,37 @@ c     * @return true if the file was saved
     */
     static nlohmann::json::json_pointer PointerFromString( std::string aPath );
 
+    /**
+    * Sets the given string if the given key/path is present
+    * @param aObj is the source object
+    * @param aTarget is the storage destination
+    * @return True if set, false if not
+    */
+    static bool SetIfPresent( const nlohmann::json& aObj, const std::string& aPath, wxString& aTarget );
+
+    /**
+    * Sets the given bool if the given key/path is present
+    * @param aObj is the source object
+    * @param aTarget is the storage destination
+    * @return True if set, false if not
+    */
+    static bool SetIfPresent( const nlohmann::json& aObj, const std::string& aPath, bool& aTarget );
+
+    /**
+    * Sets the given int if the given key/path is present
+    * @param aObj is the source object
+    * @param aTarget is the storage destination
+    * @return True if set, false if not
+    */
+    static bool SetIfPresent( const nlohmann::json& aObj, const std::string& aPath, int& aTarget );
+
+    /**
+    * Sets the given unsigned int if the given key/path is present
+    * @param aObj is the source object
+    * @param aTarget is the storage destination
+    * @return True if set, false if not
+    */
+    static bool SetIfPresent( const nlohmann::json& aObj, const std::string& aPath, unsigned int& aTarget );
 protected:
 
     /**
diff --git a/kicad/kicad_manager_frame.cpp b/kicad/kicad_manager_frame.cpp
index 480b56e585..af729654eb 100644
--- a/kicad/kicad_manager_frame.cpp
+++ b/kicad/kicad_manager_frame.cpp
@@ -38,6 +38,7 @@
 #include <launch_ext.h>
 #include <panel_hotkeys_editor.h>
 #include <reporter.h>
+#include <project/project_local_settings.h>
 #include <settings/common_settings.h>
 #include <settings/settings_manager.h>
 #include <tool/action_manager.h>
@@ -48,6 +49,7 @@
 #include <tools/kicad_manager_actions.h>
 #include <tools/kicad_manager_control.h>
 #include <wildcards_and_files_ext.h>
+#include <widgets/app_progress_dialog.h>
 
 #ifdef __WXMAC__
 #include <MacTypes.h>
@@ -65,7 +67,7 @@
 BEGIN_EVENT_TABLE( KICAD_MANAGER_FRAME, EDA_BASE_FRAME )
     // Window events
     EVT_SIZE( KICAD_MANAGER_FRAME::OnSize )
-    EVT_CLOSE( KICAD_MANAGER_FRAME::OnCloseWindow )
+    EVT_IDLE( KICAD_MANAGER_FRAME::OnIdle )
 
     // Menu events
     EVT_MENU( wxID_EXIT, KICAD_MANAGER_FRAME::OnExit )
@@ -322,7 +324,7 @@ void KICAD_MANAGER_FRAME::OnSize( wxSizeEvent& event )
 }
 
 
-void KICAD_MANAGER_FRAME::OnCloseWindow( wxCloseEvent& aEvent )
+void KICAD_MANAGER_FRAME::doCloseWindow()
 {
 #ifdef _WINDOWS_
     // For some obscure reason, on Windows, when killing Kicad from the Windows task manager
@@ -344,8 +346,6 @@ void KICAD_MANAGER_FRAME::OnCloseWindow( wxCloseEvent& aEvent )
     KICAD_SETTINGS* settings = kicadSettings();
     settings->m_OpenProjects = GetSettingsManager()->GetOpenProjects();
 
-    aEvent.SetCanVeto( true );
-
     if( CloseProject( true ) )
     {
         m_leftWin->Show( false );
@@ -367,7 +367,6 @@ void KICAD_MANAGER_FRAME::OnExit( wxCommandEvent& event )
 
 bool KICAD_MANAGER_FRAME::CloseProject( bool aSave )
 {
-
     if( !Kiway().PlayersClose( false ) )
         return false;
 
@@ -414,6 +413,8 @@ void KICAD_MANAGER_FRAME::LoadProject( const wxFileName& aProjectFileName )
 
     Pgm().GetSettingsManager().LoadProject( aProjectFileName.GetFullPath() );
 
+    LoadWindowState( aProjectFileName.GetFullName() );
+
     if( aProjectFileName.IsDirWritable() )
         SetMruPath( Prj().GetProjectPath() ); // Only set MRU path if we have write access. Why?
 
@@ -431,6 +432,7 @@ void KICAD_MANAGER_FRAME::LoadProject( const wxFileName& aProjectFileName )
     PrintPrjInfo();
 
     KIPLATFORM::APP::RegisterApplicationRestart( aProjectFileName.GetFullPath() );
+    m_openSavedWindows = true;
 }
 
 
@@ -513,6 +515,8 @@ void KICAD_MANAGER_FRAME::CreateNewProject( const wxFileName& aProjectFileName,
     }
 
     UpdateFileHistory( aProjectFileName.GetFullPath() );
+
+    m_openSavedWindows = true;
 }
 
 
@@ -648,3 +652,55 @@ bool KICAD_MANAGER_FRAME::IsProjectActive()
 {
     return m_active_project;
 }
+
+void KICAD_MANAGER_FRAME::OnIdle( wxIdleEvent& aEvent )
+{
+    /**
+     * We start loading the saved previously open windows on idle to avoid locking up the GUI earlier in project loading
+     * This gives us the visual effect of a opened KiCad project but with a "busy" progress reporter
+     */
+    if( m_openSavedWindows )
+    {
+        m_openSavedWindows = false;
+        if ( Pgm().GetCommonSettings()->m_Session.remember_open_files )
+        {
+            int previousOpenCount = std::count_if( Prj().GetLocalSettings().m_files.begin(), 
+                                                   Prj().GetLocalSettings().m_files.end(),
+                                                   [&]( const PROJECT_FILE_STATE& f )
+                                                   {
+                                                       return !f.fileName.EndsWith( ProjectFileExtension ) && f.open;
+                                                   } );
+            if ( previousOpenCount > 0 )
+            {
+                APP_PROGRESS_DIALOG progressReporter( _( "Restoring session" ), wxEmptyString, previousOpenCount, this );
+
+                int i = 0;
+                for( const PROJECT_FILE_STATE& file : Prj().GetLocalSettings().m_files )
+                {
+                    if( file.open )
+                    {
+                        progressReporter.Update(
+                            i++, wxString::Format( _( "Restoring \"%s\"" ), file.fileName ) );
+
+                        wxFileName fn( file.fileName );
+                        if( fn.GetExt() == LegacySchematicFileExtension
+                                || fn.GetExt() == KiCadSchematicFileExtension )
+                        {
+                            GetToolManager()->RunAction( KICAD_MANAGER_ACTIONS::editSchematic, true );
+                        }
+                        else if( fn.GetExt() == LegacyPcbFileExtension
+                                 || fn.GetExt() == KiCadPcbFileExtension )
+                        {
+                            GetToolManager()->RunAction( KICAD_MANAGER_ACTIONS::editPCB, true );
+                        }
+                    }
+
+                    wxYield();
+                }
+            }
+        }
+
+        // clear file states regardless if we opened windows or not due to setting
+        Prj().GetLocalSettings().ClearFileState();
+    }
+}
\ No newline at end of file
diff --git a/kicad/kicad_manager_frame.h b/kicad/kicad_manager_frame.h
index f2de35d7e2..89250b041f 100644
--- a/kicad/kicad_manager_frame.h
+++ b/kicad/kicad_manager_frame.h
@@ -83,7 +83,9 @@ public:
 
     ~KICAD_MANAGER_FRAME();
 
-    void OnCloseWindow( wxCloseEvent& Event );
+    void OnIdle( wxIdleEvent& event );
+
+    void doCloseWindow() override;
     void OnSize( wxSizeEvent& event );
 
     void OnArchiveFiles( wxCommandEvent& event );
@@ -197,6 +199,8 @@ private:
 
     void language_change( wxCommandEvent& event );
 
+    bool m_openSavedWindows;
+
 private:
     TREE_PROJECT_FRAME* m_leftWin;
     ACTION_TOOLBAR*     m_launcher;
diff --git a/pagelayout_editor/pl_editor_frame.cpp b/pagelayout_editor/pl_editor_frame.cpp
index 08b9f7bfba..11e4308aa3 100644
--- a/pagelayout_editor/pl_editor_frame.cpp
+++ b/pagelayout_editor/pl_editor_frame.cpp
@@ -62,7 +62,6 @@
 #include <settings/settings_manager.h>
 
 BEGIN_EVENT_TABLE( PL_EDITOR_FRAME, EDA_DRAW_FRAME )
-    EVT_CLOSE( PL_EDITOR_FRAME::OnCloseWindow )
     EVT_MENU( wxID_CLOSE, PL_EDITOR_FRAME::OnExit )
     EVT_MENU( wxID_EXIT, PL_EDITOR_FRAME::OnExit )
 
@@ -329,29 +328,33 @@ void PL_EDITOR_FRAME::OnExit( wxCommandEvent& aEvent )
 }
 
 
-void PL_EDITOR_FRAME::OnCloseWindow( wxCloseEvent& aEvent )
+bool PL_EDITOR_FRAME::canCloseWindow( wxCloseEvent& aEvent )
 {
     // Shutdown blocks must be determined and vetoed as early as possible
     if( SupportsShutdownBlockReason() && aEvent.GetId() == wxEVT_QUERY_END_SESSION
             && IsContentModified() )
     {
-        aEvent.Veto();
-        return;
+        return false;
     }
 
     if( IsContentModified() )
     {
         wxFileName filename = GetCurrentFileName();
-        wxString msg = _( "Save changes to \"%s\" before closing?" );
+        wxString   msg      = _( "Save changes to \"%s\" before closing?" );
 
         if( !HandleUnsavedChanges( this, wxString::Format( msg, filename.GetFullName() ),
-                                   [&]()->bool { return saveCurrentPageLayout(); } ) )
+                                   [&]() -> bool { return saveCurrentPageLayout(); } ) )
         {
-            aEvent.Veto();
-            return;
+            return false;
         }
     }
 
+    return true;
+}
+
+
+void PL_EDITOR_FRAME::doCloseWindow()
+{
     // do not show the window because we do not want any paint event
     Show( false );
 
diff --git a/pagelayout_editor/pl_editor_frame.h b/pagelayout_editor/pl_editor_frame.h
index e7550693cd..0518680bd4 100644
--- a/pagelayout_editor/pl_editor_frame.h
+++ b/pagelayout_editor/pl_editor_frame.h
@@ -108,11 +108,8 @@ public:
      */
     void OnExit( wxCommandEvent& aEvent );
 
-    /*
-     * Function OnCloseWindow
-     * Event handler for the close event
-     */
-    void OnCloseWindow( wxCloseEvent& aEvent );
+    bool canCloseWindow( wxCloseEvent& aCloseEvent ) override;
+    void doCloseWindow() override;
 
     // The Tool Framework initalization
     void setupTools();
diff --git a/pcbnew/footprint_edit_frame.cpp b/pcbnew/footprint_edit_frame.cpp
index 70e04ab249..b8391b3983 100644
--- a/pcbnew/footprint_edit_frame.cpp
+++ b/pcbnew/footprint_edit_frame.cpp
@@ -77,7 +77,6 @@
 
 
 BEGIN_EVENT_TABLE( FOOTPRINT_EDIT_FRAME, PCB_BASE_FRAME )
-    EVT_CLOSE( FOOTPRINT_EDIT_FRAME::OnCloseWindow )
     EVT_MENU( wxID_CLOSE, FOOTPRINT_EDIT_FRAME::CloseModuleEditor )
     EVT_MENU( wxID_EXIT, FOOTPRINT_EDIT_FRAME::OnExitKiCad )
 
@@ -536,7 +535,7 @@ const BOX2I FOOTPRINT_EDIT_FRAME::GetDocumentExtents() const
 }
 
 
-void FOOTPRINT_EDIT_FRAME::OnCloseWindow( wxCloseEvent& aEvent )
+bool FOOTPRINT_EDIT_FRAME::canCloseWindow( wxCloseEvent& aEvent )
 {
     if( IsContentModified() )
     {
@@ -544,7 +543,7 @@ void FOOTPRINT_EDIT_FRAME::OnCloseWindow( wxCloseEvent& aEvent )
         if( SupportsShutdownBlockReason() && aEvent.GetId() == wxEVT_QUERY_END_SESSION )
         {
             aEvent.Veto();
-            return;
+            return false;
         }
 
         wxString footprintName = GetBoard()->GetFirstModule()->GetFPID().GetLibItemName();
@@ -557,10 +556,17 @@ void FOOTPRINT_EDIT_FRAME::OnCloseWindow( wxCloseEvent& aEvent )
                                    } ) )
         {
             aEvent.Veto();
-            return;
+            return false;
         }
     }
 
+    return true;
+}
+
+
+void FOOTPRINT_EDIT_FRAME::doCloseWindow()
+{
+    // No more vetos
     GetCanvas()->SetEventDispatcher( NULL );
     GetCanvas()->StopDrawing();
 
@@ -573,9 +579,6 @@ void FOOTPRINT_EDIT_FRAME::OnCloseWindow( wxCloseEvent& aEvent )
     Pgm().GetSettingsManager().FlushAndRelease( GetSettings() );
 
     Clear_Pcb( false );
-
-    // Close the editor
-    aEvent.Skip();
 }
 
 
diff --git a/pcbnew/footprint_edit_frame.h b/pcbnew/footprint_edit_frame.h
index 489cbb07f7..b9198e1199 100644
--- a/pcbnew/footprint_edit_frame.h
+++ b/pcbnew/footprint_edit_frame.h
@@ -89,7 +89,8 @@ public:
 
     const BOX2I GetDocumentExtents() const override;
 
-    void OnCloseWindow( wxCloseEvent& Event ) override;
+    bool canCloseWindow( wxCloseEvent& Event ) override;
+    void doCloseWindow() override;
     void CloseModuleEditor( wxCommandEvent& Event );
     void OnExitKiCad( wxCommandEvent& aEvent );
 
diff --git a/pcbnew/footprint_viewer_frame.cpp b/pcbnew/footprint_viewer_frame.cpp
index 369cc15c3b..22ba68d356 100644
--- a/pcbnew/footprint_viewer_frame.cpp
+++ b/pcbnew/footprint_viewer_frame.cpp
@@ -69,7 +69,6 @@ using namespace std::placeholders;
 
 BEGIN_EVENT_TABLE( FOOTPRINT_VIEWER_FRAME, EDA_DRAW_FRAME )
     // Window events
-    EVT_CLOSE( FOOTPRINT_VIEWER_FRAME::OnCloseWindow )
     EVT_SIZE( FOOTPRINT_VIEWER_FRAME::OnSize )
     EVT_ACTIVATE( FOOTPRINT_VIEWER_FRAME::OnActivate )
 
@@ -334,7 +333,7 @@ void FOOTPRINT_VIEWER_FRAME::setupUIConditions()
 }
 
 
-void FOOTPRINT_VIEWER_FRAME::OnCloseWindow( wxCloseEvent& Event )
+void FOOTPRINT_VIEWER_FRAME::doCloseWindow()
 {
     // A workaround to avoid flicker, in modal mode when modview frame is destroyed,
     // when the aui toolbar is not docked (i.e. shown in a miniframe)
diff --git a/pcbnew/footprint_viewer_frame.h b/pcbnew/footprint_viewer_frame.h
index ce68a5abf6..3de478c1f6 100644
--- a/pcbnew/footprint_viewer_frame.h
+++ b/pcbnew/footprint_viewer_frame.h
@@ -121,7 +121,7 @@ private:
      */
     void UpdateTitle();
 
-    void OnCloseWindow( wxCloseEvent& Event ) override;
+    void doCloseWindow() override;
     void CloseFootprintViewer( wxCommandEvent& event );
     void OnExitKiCad( wxCommandEvent& event );
 
diff --git a/pcbnew/footprint_wizard_frame.cpp b/pcbnew/footprint_wizard_frame.cpp
index 6d204d63bb..448bb2b3f4 100644
--- a/pcbnew/footprint_wizard_frame.cpp
+++ b/pcbnew/footprint_wizard_frame.cpp
@@ -58,7 +58,6 @@
 BEGIN_EVENT_TABLE( FOOTPRINT_WIZARD_FRAME, EDA_DRAW_FRAME )
 
     // Window events
-    EVT_CLOSE( FOOTPRINT_WIZARD_FRAME::OnCloseWindow )
     EVT_SIZE( FOOTPRINT_WIZARD_FRAME::OnSize )
     EVT_ACTIVATE( FOOTPRINT_WIZARD_FRAME::OnActivate )
 
@@ -248,7 +247,7 @@ FOOTPRINT_WIZARD_FRAME::~FOOTPRINT_WIZARD_FRAME()
 }
 
 
-void FOOTPRINT_WIZARD_FRAME::OnCloseWindow( wxCloseEvent& Event )
+void FOOTPRINT_WIZARD_FRAME::doCloseWindow()
 {
     SaveSettings( config() );
 
diff --git a/pcbnew/footprint_wizard_frame.h b/pcbnew/footprint_wizard_frame.h
index 84486bd542..be4358209b 100644
--- a/pcbnew/footprint_wizard_frame.h
+++ b/pcbnew/footprint_wizard_frame.h
@@ -180,7 +180,7 @@ private:
     void                DisplayWizardInfos();
 
 
-    void                OnCloseWindow( wxCloseEvent& Event ) override;
+    void                doCloseWindow() override;
     void                ReCreateHToolbar() override;
     void                ReCreateVToolbar() override;
     void                ClickOnPageList( wxCommandEvent& event );
diff --git a/pcbnew/pcb_base_edit_frame.cpp b/pcbnew/pcb_base_edit_frame.cpp
index 49b5fd8014..696f05bf7c 100644
--- a/pcbnew/pcb_base_edit_frame.cpp
+++ b/pcbnew/pcb_base_edit_frame.cpp
@@ -63,7 +63,7 @@ PCB_BASE_EDIT_FRAME::~PCB_BASE_EDIT_FRAME()
 }
 
 
-void PCB_BASE_EDIT_FRAME::OnCloseWindow( wxCloseEvent& aEvent )
+void PCB_BASE_EDIT_FRAME::doCloseWindow()
 {
     SETTINGS_MANAGER* mgr = GetSettingsManager();
 
diff --git a/pcbnew/pcb_base_edit_frame.h b/pcbnew/pcb_base_edit_frame.h
index 8bdcf4bfb8..8db9dea673 100644
--- a/pcbnew/pcb_base_edit_frame.h
+++ b/pcbnew/pcb_base_edit_frame.h
@@ -47,7 +47,7 @@ public:
 
     bool TryBefore( wxEvent& aEvent ) override;
 
-    void OnCloseWindow( wxCloseEvent& aEvent ) override;
+    void doCloseWindow() override;
 
     /**
      * If a library name is given, creates a new footprint library in the project folder
diff --git a/pcbnew/pcb_edit_frame.cpp b/pcbnew/pcb_edit_frame.cpp
index f5a48068cd..ae821e8f24 100644
--- a/pcbnew/pcb_edit_frame.cpp
+++ b/pcbnew/pcb_edit_frame.cpp
@@ -109,7 +109,7 @@ BEGIN_EVENT_TABLE( PCB_EDIT_FRAME, PCB_BASE_FRAME )
     EVT_CHOICE( ID_ON_ZOOM_SELECT, PCB_EDIT_FRAME::OnSelectZoom )
     EVT_CHOICE( ID_ON_GRID_SELECT, PCB_EDIT_FRAME::OnSelectGrid )
 
-    EVT_CLOSE( PCB_EDIT_FRAME::OnCloseWindow )
+    EVT_SIZE( PCB_EDIT_FRAME::OnSize )
 
     EVT_TOOL( ID_MENU_RECOVER_BOARD_AUTOSAVE, PCB_EDIT_FRAME::Files_io )
 
@@ -789,20 +789,19 @@ void PCB_EDIT_FRAME::ResolveDRCExclusions()
 }
 
 
-void PCB_EDIT_FRAME::OnCloseWindow( wxCloseEvent& aEvent )
+bool PCB_EDIT_FRAME::canCloseWindow( wxCloseEvent& aEvent )
 {
     // Shutdown blocks must be determined and vetoed as early as possible
     if( SupportsShutdownBlockReason() && aEvent.GetId() == wxEVT_QUERY_END_SESSION
-            && IsContentModified() )
+        && IsContentModified() )
     {
-        aEvent.Veto();
-        return;
+        return false;
     }
 
     // First close the DRC dialog.  For some reason, if the board editor frame is destroyed
     // when the DRC dialog currently open, Pcbnew crashes, at least on Windows.
     DIALOG_DRC* open_dlg = static_cast<DIALOG_DRC*>(
-                                        wxWindow::FindWindowByName( DIALOG_DRC_WINDOW_NAME ) );
+        wxWindow::FindWindowByName( DIALOG_DRC_WINDOW_NAME ) );
 
     if( open_dlg )
         open_dlg->Close( true );
@@ -813,15 +812,17 @@ void PCB_EDIT_FRAME::OnCloseWindow( wxCloseEvent& aEvent )
         wxString msg = _( "Save changes to \"%s\" before closing?" );
 
         if( !HandleUnsavedChanges( this, wxString::Format( msg, fileName.GetFullName() ),
-                                   [&]()->bool { return Files_io_from_id( ID_SAVE_BOARD ); } ) )
+            [&]()->bool { return Files_io_from_id( ID_SAVE_BOARD ); } ) )
         {
-            aEvent.Veto();
-            return;
+            return false;
         }
     }
 
-    m_shuttingDown = true;
+    return true;
+}
 
+void PCB_EDIT_FRAME::doCloseWindow()
+{
     // On Windows 7 / 32 bits, on OpenGL mode only, Pcbnew crashes
     // when closing this frame if a footprint was selected, and the footprint editor called
     // to edit this footprint, and when closing pcbnew if this footprint is still selected
@@ -873,10 +874,7 @@ void PCB_EDIT_FRAME::OnCloseWindow( wxCloseEvent& aEvent )
     // want any paint event
     Show( false );
 
-    PCB_BASE_EDIT_FRAME::OnCloseWindow( aEvent );
-
-    // Close frame:
-    aEvent.Skip();
+    PCB_BASE_EDIT_FRAME::doCloseWindow();
 }
 
 
diff --git a/pcbnew/pcb_edit_frame.h b/pcbnew/pcb_edit_frame.h
index 61a978e927..e08cde8fe5 100644
--- a/pcbnew/pcb_edit_frame.h
+++ b/pcbnew/pcb_edit_frame.h
@@ -240,6 +240,9 @@ protected:
      */
     bool fixEagleNets( const std::unordered_map<wxString, wxString>& aRemap );
 
+    bool canCloseWindow( wxCloseEvent& aCloseEvent ) override;
+    void doCloseWindow() override;
+
     // protected so that PCB::IFACE::CreateWindow() is the only factory.
     PCB_EDIT_FRAME( KIWAY* aKiway, wxWindow* aParent );
 
@@ -422,7 +425,6 @@ public:
      */
     void ResolveDRCExclusions();
 
-    void OnCloseWindow( wxCloseEvent& Event ) override;
     void Process_Special_Functions( wxCommandEvent& event );
     void Tracks_and_Vias_Size_Event( wxCommandEvent& event );
 
diff --git a/pcbnew/pcbnew_config.cpp b/pcbnew/pcbnew_config.cpp
index 51c5e7fb85..065e20f53b 100644
--- a/pcbnew/pcbnew_config.cpp
+++ b/pcbnew/pcbnew_config.cpp
@@ -144,6 +144,10 @@ bool PCB_EDIT_FRAME::LoadProjectSettings()
     if( GetBoard()->GetDesignSettings().IsLayerEnabled( localSettings.m_ActiveLayer ) )
         SetActiveLayer( localSettings.m_ActiveLayer );
 
+    wxFileName fn( GetCurrentFileName() );
+    fn.MakeRelativeTo( Prj().GetProjectPath() );
+    LoadWindowState( fn.GetFullPath() );
+
     return true;
 }