From bfce4f69019d2ddd2ffd4dbbacc8ef5d4f32f015 Mon Sep 17 00:00:00 2001 From: Vojtech Bubnik Date: Sun, 5 Dec 2021 09:09:34 +0100 Subject: [PATCH] Follow-up to 3622f06bed6175a337d2e20b5dc6ae9d770cb3cf Work around 3D scene focus after de-activation of the main window without having to resort to CallAfter(), which breaks on Linux with some window managers that follow mouser cursor. Fixes #5620 #6870 #6992 3622f06bed6175a337d2e20b5dc6ae9d770cb3cf was not a correct solution, it broke focus for non-modal windows. Fixes #7419 The actual issue seems to be caused by wxProgressDialog not playing well with modal dialogs closed just before wxProgressDialog opens. If wxProgressDialog parent was not a main frame, keyboard focus was not restored correctly after the wxProgressDialog closed. --- src/slic3r/GUI/GCodeViewer.cpp | 2 +- src/slic3r/GUI/GUI_ObjectList.cpp | 6 +++--- src/slic3r/GUI/MainFrame.cpp | 15 --------------- src/slic3r/GUI/MainFrame.hpp | 11 +---------- src/slic3r/GUI/Plater.cpp | 29 +---------------------------- src/slic3r/GUI/Plater.hpp | 10 ---------- 6 files changed, 6 insertions(+), 67 deletions(-) diff --git a/src/slic3r/GUI/GCodeViewer.cpp b/src/slic3r/GUI/GCodeViewer.cpp index cdc9c33a4fd..b86bd018d3c 100644 --- a/src/slic3r/GUI/GCodeViewer.cpp +++ b/src/slic3r/GUI/GCodeViewer.cpp @@ -1447,7 +1447,7 @@ void GCodeViewer::load_toolpaths(const GCodeProcessorResult& gcode_result) static const unsigned int progress_threshold = 1000; wxProgressDialog* progress_dialog = wxGetApp().is_gcode_viewer() ? new wxProgressDialog(_L("Generating toolpaths"), "...", - 100, wxGetApp().plater(), wxPD_AUTO_HIDE | wxPD_APP_MODAL) : nullptr; + 100, wxGetApp().mainframe, wxPD_AUTO_HIDE | wxPD_APP_MODAL) : nullptr; wxBusyCursor busy; diff --git a/src/slic3r/GUI/GUI_ObjectList.cpp b/src/slic3r/GUI/GUI_ObjectList.cpp index 7d689ff6a25..f4d27b0b27b 100644 --- a/src/slic3r/GUI/GUI_ObjectList.cpp +++ b/src/slic3r/GUI/GUI_ObjectList.cpp @@ -1446,7 +1446,7 @@ void ObjectList::load_part(ModelObject& model_object, std::vector& else wxGetApp().import_model(parent, input_files); - wxProgressDialog dlg(_L("Loading") + dots, "", 100, wxGetApp().plater(), wxPD_AUTO_HIDE); + wxProgressDialog dlg(_L("Loading") + dots, "", 100, wxGetApp().mainframe wxPD_AUTO_HIDE); wxBusyCursor busy; for (size_t i = 0; i < input_files.size(); ++i) { @@ -1506,7 +1506,7 @@ void ObjectList::load_modifier(ModelObject& model_object, std::vectorplater()->restore_keyboard_focus(); - return retval; -} -#endif - // // Called after the Preferences dialog is closed and the program settings are saved. // Update the UI based on the current preferences. diff --git a/src/slic3r/GUI/MainFrame.hpp b/src/slic3r/GUI/MainFrame.hpp index 9e09bf08846..951ed70a1d7 100644 --- a/src/slic3r/GUI/MainFrame.hpp +++ b/src/slic3r/GUI/MainFrame.hpp @@ -148,15 +148,6 @@ class MainFrame : public DPIFrame void update_title(); -#if defined(__linux__) || defined(_WIN32) - // wxWidgets callback to enable / disable window and all its children windows. - // called by wxWindowDisabler when entering / leaving modal dialog loop. - // Unfortunately the wxWindowDisabler calls Enable(true) after the wxEVT_ACTIVATE event is processed - // while MainFrame is not yet enabled, thus restoring focus in OnActivate() handler fails - // and we need to do it now. - bool Enable(bool enable = true) override; -#endif - void init_tabpanel(); void create_preset_tabs(); void add_created_tab(Tab* panel, const std::string& bmp_name = ""); @@ -211,7 +202,7 @@ class MainFrame : public DPIFrame SettingsDialog m_settings_dialog; DiffPresetDialog diff_dialog; wxWindow* m_plater_page{ nullptr }; - wxProgressDialog* m_progress_dialog { nullptr }; +// wxProgressDialog* m_progress_dialog { nullptr }; PrintHostQueueDialog* m_printhost_queue_dlg; // std::shared_ptr m_statusbar; diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index dd1ccb91f17..0485b00753d 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -2351,7 +2351,7 @@ std::vector Plater::priv::load_files(const std::vector& input_ } const auto loading = _L("Loading") + dots; - wxProgressDialog dlg(loading, "", 100, q, wxPD_AUTO_HIDE); + wxProgressDialog dlg(loading, "", 100, find_toplevel_parent(q), wxPD_AUTO_HIDE); wxBusyCursor busy; auto *new_model = (!load_model || one_by_one) ? nullptr : new Slic3r::Model(); @@ -6306,36 +6306,9 @@ void Plater::force_print_bed_update() void Plater::on_activate() { -#if defined(__linux__) || defined(_WIN32) - this->restore_keyboard_focus(); -#endif this->p->show_delayed_error_message(); } -#if defined(__linux__) || defined(_WIN32) -// wxWidgets callback to enable / disable window and all its children windows. -// called by wxProgressDialog when entering / leaving modal dialog loop. -// Unfortunately the wxProgressDialog calls Enable(true) after the wxEVT_ACTIVATE event is processed -// while MainFrame is not yet enabled, thus restoring focus in OnActivate() handler fails -// and we need to do it now. -bool Plater::Enable(bool enable) -{ - bool retval = wxPanel::Enable(enable); - if (enable && retval) - this->restore_keyboard_focus(); - return retval; -} -void Plater::restore_keyboard_focus() -{ - // Activating the main frame, and no window has keyboard focus. - // Set the keyboard focus to the visible Canvas3D. - if (this->p->view3D->IsShown() && wxWindow::FindFocus() != this->p->view3D->get_wxglcanvas()) - this->p->view3D->get_wxglcanvas()->SetFocus(); - else if (this->p->preview->IsShown() && wxWindow::FindFocus() != this->p->view3D->get_wxglcanvas()) - this->p->preview->get_wxglcanvas()->SetFocus(); -} -#endif // Linux or Windows - // Get vector of extruder colors considering filament color, if extruder color is undefined. std::vector Plater::get_extruder_colors_from_plater_config(const GCodeProcessorResult* const result) const { diff --git a/src/slic3r/GUI/Plater.hpp b/src/slic3r/GUI/Plater.hpp index 6d742a832c9..d3eead4ede6 100644 --- a/src/slic3r/GUI/Plater.hpp +++ b/src/slic3r/GUI/Plater.hpp @@ -149,16 +149,6 @@ class Plater: public wxPanel void render_project_state_debug_window() const; #endif // ENABLE_PROJECT_DIRTY_STATE_DEBUG_WINDOW -#if defined(__linux__) || defined(_WIN32) - // wxWidgets callback to enable / disable window and all its children windows. - // called by wxProgressDialog when entering / leaving modal dialog loop. - // Unfortunately the wxProgressDialog calls Enable(true) after the wxEVT_ACTIVATE event is processed - // while MainFrame is not yet enabled, thus restoring focus in OnActivate() handler fails - // and we need to do it now. - bool Enable(bool enable) override; - void restore_keyboard_focus(); -#endif - Sidebar& sidebar(); const Model& model() const; Model& model();