From 8841f3da32b4332674825e3de8db0f37b5fe4183 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=ADn=20Capello?= Date: Thu, 30 Mar 2023 15:44:40 -0300 Subject: [PATCH] Move window relayout before inserting the window to the manager (fix #3746) This is necessary to prevent the manager to invalidate a window whose relayout is not finished. This can happen when a script opens a new window when another is currently opening. For instance a script whose canvas.onpaint handler opens another dialog. --- src/app/ui/preview_editor.cpp | 9 ++++++++- src/app/ui/preview_editor.h | 4 ++++ src/ui/manager.cpp | 16 ++++++++++------ 3 files changed, 22 insertions(+), 7 deletions(-) diff --git a/src/app/ui/preview_editor.cpp b/src/app/ui/preview_editor.cpp index 9c9c28f15..a4de3b19a 100644 --- a/src/app/ui/preview_editor.cpp +++ b/src/app/ui/preview_editor.cpp @@ -183,6 +183,7 @@ PreviewEditorWindow::PreviewEditorWindow() , m_refFrame(0) , m_aniSpeed(1.0) , m_relatedEditor(nullptr) + , m_opening(false) { setAutoRemap(false); setWantFocus(false); @@ -343,6 +344,9 @@ Editor* PreviewEditorWindow::previewEditor() const void PreviewEditorWindow::updateUsingEditor(Editor* editor) { + if (m_opening) + return; + if (!m_isEnabled || !editor) { hideWindow(); m_relatedEditor = nullptr; @@ -357,8 +361,11 @@ void PreviewEditorWindow::updateUsingEditor(Editor* editor) Doc* document = editor->document(); Editor* miniEditor = (m_docView ? m_docView->editor(): nullptr); - if (!isVisible()) + if (!isVisible()) { + m_opening = true; openWindow(); + m_opening = false; + } // Document preferences used to store the preferred zoom/scroll point auto& docPref = Preferences::instance().document(document); diff --git a/src/app/ui/preview_editor.h b/src/app/ui/preview_editor.h index ec7d20c7e..8d3c9e162 100644 --- a/src/app/ui/preview_editor.h +++ b/src/app/ui/preview_editor.h @@ -70,6 +70,10 @@ namespace app { doc::frame_t m_refFrame; double m_aniSpeed; Editor* m_relatedEditor; + // This flag indicates that the preview editor is being opened, it is used to avoid + // an infinite recursive loop when PreviewEditorWindow::updateUsingEditor calls the + // openWindow() method. + bool m_opening; }; } // namespace app diff --git a/src/ui/manager.cpp b/src/ui/manager.cpp index 5dc48fd83..d916a5c94 100644 --- a/src/ui/manager.cpp +++ b/src/ui/manager.cpp @@ -1334,6 +1334,16 @@ void Manager::_openWindow(Window* window, bool center) freeFocus(); } + // Relayout before inserting the window to the list of children widgets prevents + // the manager to invalidate a window currently being laid out when + // ui::Manager::getDefault()->invalidate() is called. This situation could happen, + // for instance, when a script opens a dialog whose canvas.onpaint handler opens + // another dialog, because the onpaint handler is executed during window layout. + if (center) + window->centerWindow(parentDisplay); + else + window->layout(); + // Add the window to manager. insertChild(0, window); @@ -1343,12 +1353,6 @@ void Manager::_openWindow(Window* window, bool center) window->sendMessage(&msg); } - // Relayout - if (center) - window->centerWindow(parentDisplay); - else - window->layout(); - // If the window already was set a display, we don't setup it // (i.e. in the case of combobox popup/window the display field is // set to the same display where the ComboBox widget is located)