Merge pull request #76085 from spanzeri/better_remember_editor_window

Remember editor window mode, screen, size and position on restart
This commit is contained in:
Rémi Verschelde 2024-08-26 23:27:55 +02:00
commit b34aa7b44d
No known key found for this signature in database
GPG Key ID: C3336907360768E1
5 changed files with 114 additions and 1 deletions

View File

@ -701,6 +701,9 @@
<member name="interface/editor/project_manager_screen" type="int" setter="" getter=""> <member name="interface/editor/project_manager_screen" type="int" setter="" getter="">
The preferred monitor to display the project manager. The preferred monitor to display the project manager.
</member> </member>
<member name="interface/editor/remember_window_size_and_position" type="bool" setter="" getter="">
If [code]true[/code], the editor window will remember its size, position, and which screen it was displayed on across restarts.
</member>
<member name="interface/editor/save_each_scene_on_quit" type="bool" setter="" getter=""> <member name="interface/editor/save_each_scene_on_quit" type="bool" setter="" getter="">
If [code]false[/code], the editor will save all scenes when confirming the [b]Save[/b] action when quitting the editor or quitting to the project list. If [code]true[/code], the editor will ask to save each scene individually. If [code]false[/code], the editor will save all scenes when confirming the [b]Save[/b] action when quitting the editor or quitting to the project list. If [code]true[/code], the editor will ask to save each scene individually.
</member> </member>

View File

@ -702,6 +702,8 @@ void EditorNode::_notification(int p_what) {
last_system_base_color = DisplayServer::get_singleton()->get_base_color(); last_system_base_color = DisplayServer::get_singleton()->get_base_color();
DisplayServer::get_singleton()->set_system_theme_change_callback(callable_mp(this, &EditorNode::_check_system_theme_changed)); DisplayServer::get_singleton()->set_system_theme_change_callback(callable_mp(this, &EditorNode::_check_system_theme_changed));
get_viewport()->connect("size_changed", callable_mp(this, &EditorNode::_viewport_resized));
/* DO NOT LOAD SCENES HERE, WAIT FOR FILE SCANNING AND REIMPORT TO COMPLETE */ /* DO NOT LOAD SCENES HERE, WAIT FOR FILE SCANNING AND REIMPORT TO COMPLETE */
} break; } break;
@ -730,6 +732,7 @@ void EditorNode::_notification(int p_what) {
FileAccess::set_file_close_fail_notify_callback(nullptr); FileAccess::set_file_close_fail_notify_callback(nullptr);
log->deinit(); // Do not get messages anymore. log->deinit(); // Do not get messages anymore.
editor_data.clear_edited_scenes(); editor_data.clear_edited_scenes();
get_viewport()->disconnect("size_changed", callable_mp(this, &EditorNode::_viewport_resized));
} break; } break;
case NOTIFICATION_READY: { case NOTIFICATION_READY: {
@ -1240,6 +1243,13 @@ void EditorNode::_reload_project_settings() {
void EditorNode::_vp_resized() { void EditorNode::_vp_resized() {
} }
void EditorNode::_viewport_resized() {
Window *w = get_window();
if (w) {
was_window_windowed_last = w->get_mode() == Window::MODE_WINDOWED;
}
}
void EditorNode::_titlebar_resized() { void EditorNode::_titlebar_resized() {
DisplayServer::get_singleton()->window_set_window_buttons_offset(Vector2i(title_bar->get_global_position().y + title_bar->get_size().y / 2, title_bar->get_global_position().y + title_bar->get_size().y / 2), DisplayServer::MAIN_WINDOW_ID); DisplayServer::get_singleton()->window_set_window_buttons_offset(Vector2i(title_bar->get_global_position().y + title_bar->get_size().y / 2, title_bar->get_global_position().y + title_bar->get_size().y / 2), DisplayServer::MAIN_WINDOW_ID);
const Vector3i &margin = DisplayServer::get_singleton()->window_get_safe_title_margins(DisplayServer::MAIN_WINDOW_ID); const Vector3i &margin = DisplayServer::get_singleton()->window_get_safe_title_margins(DisplayServer::MAIN_WINDOW_ID);
@ -5220,6 +5230,7 @@ void EditorNode::_save_editor_layout() {
editor_dock_manager->save_docks_to_config(config, "docks"); editor_dock_manager->save_docks_to_config(config, "docks");
_save_open_scenes_to_config(config); _save_open_scenes_to_config(config);
_save_central_editor_layout_to_config(config); _save_central_editor_layout_to_config(config);
_save_window_settings_to_config(config, "EditorWindow");
editor_data.get_plugin_window_layout(config); editor_data.get_plugin_window_layout(config);
config->save(EditorPaths::get_singleton()->get_project_settings_dir().path_join("editor_layout.cfg")); config->save(EditorPaths::get_singleton()->get_project_settings_dir().path_join("editor_layout.cfg"));
@ -5339,6 +5350,38 @@ void EditorNode::_load_central_editor_layout_from_config(Ref<ConfigFile> p_confi
} }
} }
void EditorNode::_save_window_settings_to_config(Ref<ConfigFile> p_layout, const String &p_section) {
Window *w = get_window();
if (w) {
p_layout->set_value(p_section, "screen", w->get_current_screen());
Window::Mode mode = w->get_mode();
switch (mode) {
case Window::MODE_WINDOWED:
p_layout->set_value(p_section, "mode", "windowed");
p_layout->set_value(p_section, "size", w->get_size());
break;
case Window::MODE_FULLSCREEN:
case Window::MODE_EXCLUSIVE_FULLSCREEN:
p_layout->set_value(p_section, "mode", "fullscreen");
break;
case Window::MODE_MINIMIZED:
if (was_window_windowed_last) {
p_layout->set_value(p_section, "mode", "windowed");
p_layout->set_value(p_section, "size", w->get_size());
} else {
p_layout->set_value(p_section, "mode", "maximized");
}
break;
default:
p_layout->set_value(p_section, "mode", "maximized");
break;
}
p_layout->set_value(p_section, "position", w->get_position());
}
}
void EditorNode::_load_open_scenes_from_config(Ref<ConfigFile> p_layout) { void EditorNode::_load_open_scenes_from_config(Ref<ConfigFile> p_layout) {
if (!bool(EDITOR_GET("interface/scene_tabs/restore_scenes_on_load"))) { if (!bool(EDITOR_GET("interface/scene_tabs/restore_scenes_on_load"))) {
return; return;

View File

@ -499,6 +499,8 @@ private:
SurfaceUpgradeDialog *surface_upgrade_dialog = nullptr; SurfaceUpgradeDialog *surface_upgrade_dialog = nullptr;
bool run_surface_upgrade_tool = false; bool run_surface_upgrade_tool = false;
bool was_window_windowed_last = false;
static EditorBuildCallback build_callbacks[MAX_BUILD_CALLBACKS]; static EditorBuildCallback build_callbacks[MAX_BUILD_CALLBACKS];
static EditorPluginInitializeCallback plugin_init_callbacks[MAX_INIT_CALLBACKS]; static EditorPluginInitializeCallback plugin_init_callbacks[MAX_INIT_CALLBACKS];
static int build_callback_count; static int build_callback_count;
@ -580,6 +582,7 @@ private:
void _show_messages(); void _show_messages();
void _vp_resized(); void _vp_resized();
void _titlebar_resized(); void _titlebar_resized();
void _viewport_resized();
void _update_undo_redo_allowed(); void _update_undo_redo_allowed();
@ -651,6 +654,8 @@ private:
void _save_central_editor_layout_to_config(Ref<ConfigFile> p_config_file); void _save_central_editor_layout_to_config(Ref<ConfigFile> p_config_file);
void _load_central_editor_layout_from_config(Ref<ConfigFile> p_config_file); void _load_central_editor_layout_from_config(Ref<ConfigFile> p_config_file);
void _save_window_settings_to_config(Ref<ConfigFile> p_layout, const String &p_section);
void _save_open_scenes_to_config(Ref<ConfigFile> p_layout); void _save_open_scenes_to_config(Ref<ConfigFile> p_layout);
void _load_open_scenes_from_config(Ref<ConfigFile> p_layout); void _load_open_scenes_from_config(Ref<ConfigFile> p_layout);

View File

@ -452,6 +452,7 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) {
_initial_set("interface/editor/separate_distraction_mode", false); _initial_set("interface/editor/separate_distraction_mode", false);
_initial_set("interface/editor/automatically_open_screenshots", true); _initial_set("interface/editor/automatically_open_screenshots", true);
EDITOR_SETTING_USAGE(Variant::BOOL, PROPERTY_HINT_NONE, "interface/editor/single_window_mode", false, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED) EDITOR_SETTING_USAGE(Variant::BOOL, PROPERTY_HINT_NONE, "interface/editor/single_window_mode", false, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED)
_initial_set("interface/editor/remember_window_size_and_position", true);
_initial_set("interface/editor/mouse_extra_buttons_navigate_history", true); _initial_set("interface/editor/mouse_extra_buttons_navigate_history", true);
_initial_set("interface/editor/save_each_scene_on_quit", true); // Regression _initial_set("interface/editor/save_each_scene_on_quit", true); // Regression
EDITOR_SETTING(Variant::BOOL, PROPERTY_HINT_NONE, "interface/editor/save_on_focus_loss", false, "") EDITOR_SETTING(Variant::BOOL, PROPERTY_HINT_NONE, "interface/editor/save_on_focus_loss", false, "")

View File

@ -197,6 +197,7 @@ static bool found_project = false;
static bool auto_build_solutions = false; static bool auto_build_solutions = false;
static String debug_server_uri; static String debug_server_uri;
static bool wait_for_import = false; static bool wait_for_import = false;
static bool restore_editor_window_layout = true;
#ifndef DISABLE_DEPRECATED #ifndef DISABLE_DEPRECATED
static int converter_max_kb_file = 4 * 1024; // 4MB static int converter_max_kb_file = 4 * 1024; // 4MB
static int converter_max_line_length = 100000; static int converter_max_line_length = 100000;
@ -2718,6 +2719,7 @@ Error Main::setup2(bool p_show_boot_logo) {
bool prefer_wayland_found = false; bool prefer_wayland_found = false;
bool prefer_wayland = false; bool prefer_wayland = false;
bool remember_window_size_and_position_found = false;
if (editor) { if (editor) {
screen_property = "interface/editor/editor_screen"; screen_property = "interface/editor/editor_screen";
@ -2733,7 +2735,7 @@ Error Main::setup2(bool p_show_boot_logo) {
prefer_wayland_found = true; prefer_wayland_found = true;
} }
while (!screen_found || !prefer_wayland_found) { while (!screen_found || !prefer_wayland_found || !remember_window_size_and_position_found) {
assign = Variant(); assign = Variant();
next_tag.fields.clear(); next_tag.fields.clear();
next_tag.name = String(); next_tag.name = String();
@ -2753,6 +2755,11 @@ Error Main::setup2(bool p_show_boot_logo) {
prefer_wayland = value; prefer_wayland = value;
prefer_wayland_found = true; prefer_wayland_found = true;
} }
if (!remember_window_size_and_position_found && assign == "interface/editor/remember_window_size_and_position") {
restore_editor_window_layout = value;
remember_window_size_and_position_found = true;
}
} }
} }
@ -2775,6 +2782,34 @@ Error Main::setup2(bool p_show_boot_logo) {
} }
} }
bool has_command_line_window_override = init_use_custom_pos || init_use_custom_screen || init_windowed;
if (editor && !has_command_line_window_override && restore_editor_window_layout) {
Ref<ConfigFile> config;
config.instantiate();
// Load and amend existing config if it exists.
Error err = config->load(EditorPaths::get_singleton()->get_project_settings_dir().path_join("editor_layout.cfg"));
if (err == OK) {
init_screen = config->get_value("EditorWindow", "screen", init_screen);
String mode = config->get_value("EditorWindow", "mode", "maximized");
window_size = config->get_value("EditorWindow", "size", window_size);
if (mode == "windowed") {
window_mode = DisplayServer::WINDOW_MODE_WINDOWED;
init_windowed = true;
} else if (mode == "fullscreen") {
window_mode = DisplayServer::WINDOW_MODE_FULLSCREEN;
init_fullscreen = true;
} else {
window_mode = DisplayServer::WINDOW_MODE_MAXIMIZED;
init_maximized = true;
}
if (init_windowed) {
init_use_custom_pos = true;
init_custom_pos = config->get_value("EditorWindow", "position", Vector2i(0, 0));
}
}
}
OS::get_singleton()->benchmark_end_measure("Startup", "Initialize Early Settings"); OS::get_singleton()->benchmark_end_measure("Startup", "Initialize Early Settings");
} }
#endif #endif
@ -2919,6 +2954,30 @@ Error Main::setup2(bool p_show_boot_logo) {
OS::get_singleton()->benchmark_end_measure("Servers", "Display"); OS::get_singleton()->benchmark_end_measure("Servers", "Display");
} }
#ifdef TOOLS_ENABLED
// If the editor is running in windowed mode, ensure the window rect fits
// the screen in case screen count or position has changed.
if (editor && init_windowed) {
// We still need to check we are actually in windowed mode, because
// certain platform might only support one fullscreen window.
if (DisplayServer::get_singleton()->window_get_mode() == DisplayServer::WINDOW_MODE_WINDOWED) {
Vector2i current_size = DisplayServer::get_singleton()->window_get_size();
Vector2i current_pos = DisplayServer::get_singleton()->window_get_position();
int screen = DisplayServer::get_singleton()->window_get_current_screen();
Rect2i screen_rect = DisplayServer::get_singleton()->screen_get_usable_rect(screen);
Vector2i adjusted_end = screen_rect.get_end().min(current_pos + current_size);
Vector2i adjusted_pos = screen_rect.get_position().max(adjusted_end - current_size);
Vector2i adjusted_size = DisplayServer::get_singleton()->window_get_min_size().max(adjusted_end - adjusted_pos);
if (current_pos != adjusted_end || current_size != adjusted_size) {
DisplayServer::get_singleton()->window_set_position(adjusted_pos);
DisplayServer::get_singleton()->window_set_size(adjusted_size);
}
}
}
#endif
if (GLOBAL_GET("debug/settings/stdout/print_fps") || print_fps) { if (GLOBAL_GET("debug/settings/stdout/print_fps") || print_fps) {
// Print requested V-Sync mode at startup to diagnose the printed FPS not going above the monitor refresh rate. // Print requested V-Sync mode at startup to diagnose the printed FPS not going above the monitor refresh rate.
switch (window_vsync_mode) { switch (window_vsync_mode) {
@ -3979,6 +4038,8 @@ int Main::start() {
if (editor_embed_subwindows) { if (editor_embed_subwindows) {
sml->get_root()->set_embedding_subwindows(true); sml->get_root()->set_embedding_subwindows(true);
} }
restore_editor_window_layout = EditorSettings::get_singleton()->get_setting(
"interface/editor/remember_window_size_and_position");
} }
#endif #endif