diff --git a/src/slic3r/GUI/3DBed.cpp b/src/slic3r/GUI/3DBed.cpp
index dce7c4c99..a0f842d26 100644
--- a/src/slic3r/GUI/3DBed.cpp
+++ b/src/slic3r/GUI/3DBed.cpp
@@ -191,7 +191,6 @@ Bed3D::Bed3D()
     : m_type(Custom)
     , m_custom_texture("")
     , m_custom_model("")
-    , m_requires_canvas_update(false)
     , m_vbo_id(0)
     , m_scale_factor(1.0f)
 {
@@ -438,6 +437,7 @@ void Bed3D::render_texture(const std::string& filename, bool bottom, GLCanvas3D&
                     render_default(bottom);
                     return;
                 }
+                canvas.request_extra_frame();
             }
 
             // starts generating the main texture, compression will run asynchronously
@@ -457,6 +457,7 @@ void Bed3D::render_texture(const std::string& filename, bool bottom, GLCanvas3D&
                     render_default(bottom);
                     return;
                 }
+                canvas.request_extra_frame();
             }
 
             // starts generating the main texture, compression will run asynchronously
@@ -481,13 +482,9 @@ void Bed3D::render_texture(const std::string& filename, bool bottom, GLCanvas3D&
         if (m_temp_texture.get_id() != 0)
             m_temp_texture.reset();
 
-        m_requires_canvas_update = true;
-    }
-    else if (m_requires_canvas_update && m_texture.all_compressed_data_sent_to_gpu())
-        m_requires_canvas_update = false;
+        canvas.request_extra_frame();
 
-    if (m_texture.all_compressed_data_sent_to_gpu() && canvas.is_keeping_dirty())
-        canvas.stop_keeping_dirty();
+    }
 
     if (m_triangles.get_vertices_count() > 0)
     {
diff --git a/src/slic3r/GUI/3DBed.hpp b/src/slic3r/GUI/3DBed.hpp
index 19ecddc0a..cd2de862e 100644
--- a/src/slic3r/GUI/3DBed.hpp
+++ b/src/slic3r/GUI/3DBed.hpp
@@ -86,8 +86,6 @@ private:
     mutable GLTexture m_texture;
     // temporary texture shown until the main texture has still no levels compressed
     mutable GLTexture m_temp_texture;
-    // used to trigger 3D scene update once all compressed textures have been sent to GPU
-    mutable bool m_requires_canvas_update;
     mutable Shader m_shader;
     mutable unsigned int m_vbo_id;
     mutable GLBed m_model;
diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp
index 71ce173df..a28bb61f2 100644
--- a/src/slic3r/GUI/GLCanvas3D.cpp
+++ b/src/slic3r/GUI/GLCanvas3D.cpp
@@ -1398,7 +1398,7 @@ GLCanvas3D::GLCanvas3D(wxGLCanvas* canvas, Bed3D& bed, Camera& camera, GLToolbar
     , m_gizmos(*this)
     , m_use_clipping_planes(false)
     , m_sidebar_field("")
-    , m_keep_dirty(false)
+    , m_extra_frame_requested(false)
     , m_config(nullptr)
     , m_process(nullptr)
     , m_model(nullptr)
@@ -1636,8 +1636,6 @@ void GLCanvas3D::bed_shape_changed()
     refresh_camera_scene_box();
     m_camera.requires_zoom_to_bed = true;
     m_dirty = true;
-    if (m_bed.is_prusa())
-        start_keeping_dirty();
 }
 
 void GLCanvas3D::set_color_by(const std::string& value)
@@ -2632,10 +2630,11 @@ void GLCanvas3D::on_idle(wxIdleEvent& evt)
 
     _refresh_if_shown_on_screen();
 
-    if (m_keep_dirty || mouse3d_controller_applied)
+    if (m_extra_frame_requested || mouse3d_controller_applied)
     {
         m_dirty = true;
         evt.RequestMore();
+        m_extra_frame_requested = false;
     }
     else
         m_dirty = false;
diff --git a/src/slic3r/GUI/GLCanvas3D.hpp b/src/slic3r/GUI/GLCanvas3D.hpp
index 2ff65052a..bd31527b1 100644
--- a/src/slic3r/GUI/GLCanvas3D.hpp
+++ b/src/slic3r/GUI/GLCanvas3D.hpp
@@ -436,7 +436,9 @@ private:
     bool m_use_clipping_planes;
     mutable SlaCap m_sla_caps[2];
     std::string m_sidebar_field;
-    bool m_keep_dirty;
+    // when true renders an extra frame by not resetting m_dirty to false
+    // see request_extra_frame()
+    bool m_extra_frame_requested;
 
     mutable GLVolumeCollection m_volumes;
     Selection m_selection;
@@ -664,9 +666,7 @@ public:
     void set_cursor(ECursorType type);
     void msw_rescale();
 
-    bool is_keeping_dirty() const { return m_keep_dirty; }
-    void start_keeping_dirty() { m_keep_dirty = true; }
-    void stop_keeping_dirty() { m_keep_dirty = false; }
+    void request_extra_frame() { m_extra_frame_requested = true; }
 
     int get_main_toolbar_item_id(const std::string& name) const { return m_main_toolbar.get_item_id(name); }
     void force_main_toolbar_left_action(int item_id) { m_main_toolbar.force_left_action(item_id, *this); }
diff --git a/src/slic3r/GUI/Gizmos/GLGizmoCut.cpp b/src/slic3r/GUI/Gizmos/GLGizmoCut.cpp
index 4406b1bf5..e98446749 100644
--- a/src/slic3r/GUI/Gizmos/GLGizmoCut.cpp
+++ b/src/slic3r/GUI/Gizmos/GLGizmoCut.cpp
@@ -136,12 +136,25 @@ void GLGizmoCut::on_render_for_picking() const
 
 void GLGizmoCut::on_render_input_window(float x, float y, float bottom_limit)
 {
-    const float approx_height = m_imgui->scaled(11.0f);
-    y = std::min(y, bottom_limit - approx_height);
-    m_imgui->set_next_window_pos(x, y, ImGuiCond_Always);
+    static float last_y = 0.0f;
+    static float last_h = 0.0f;
 
     m_imgui->begin(_(L("Cut")), ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoCollapse);
 
+    // adjust window position to avoid overlap the view toolbar
+    float win_h = ImGui::GetWindowHeight();
+    y = std::min(y, bottom_limit - win_h);
+    ImGui::SetWindowPos(ImVec2(x, y), ImGuiCond_Always);
+    if ((last_h != win_h) || (last_y != y))
+    {
+        // ask canvas for another frame to render the window in the correct position
+        m_parent.request_extra_frame();
+        if (last_h != win_h)
+            last_h = win_h;
+        if (last_y != y)
+            last_y = y;
+    }
+
     ImGui::AlignTextToFramePadding();
     m_imgui->text("Z");
     ImGui::SameLine();
diff --git a/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp b/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp
index 849977464..a0e84d490 100644
--- a/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp
+++ b/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp
@@ -686,6 +686,9 @@ void GLGizmoSlaSupports::make_line_segments() const
 
 void GLGizmoSlaSupports::on_render_input_window(float x, float y, float bottom_limit)
 {
+    static float last_y = 0.0f;
+    static float last_h = 0.0f;
+
     if (!m_model_object)
         return;
 
@@ -697,11 +700,22 @@ RENDER_AGAIN:
     //ImGui::SetNextWindowPos(ImVec2(x, y - std::max(0.f, y+window_size.y-bottom_limit) ));
     //ImGui::SetNextWindowSize(ImVec2(window_size));
     
-    const float approx_height = m_imgui->scaled(18.0f);
-    y = std::min(y, bottom_limit - approx_height);
-    m_imgui->set_next_window_pos(x, y, ImGuiCond_Always);
     m_imgui->begin(on_get_name(), ImGuiWindowFlags_NoMove | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoCollapse);
 
+    // adjust window position to avoid overlap the view toolbar
+    float win_h = ImGui::GetWindowHeight();
+    y = std::min(y, bottom_limit - win_h);
+    ImGui::SetWindowPos(ImVec2(x, y), ImGuiCond_Always);
+    if ((last_h != win_h) || (last_y != y))
+    {
+        // ask canvas for another frame to render the window in the correct position
+        m_parent.request_extra_frame();
+        if (last_h != win_h)
+            last_h = win_h;
+        if (last_y != y)
+            last_y = y;
+    }
+
     // First calculate width of all the texts that are could possibly be shown. We will decide set the dialog width based on that:
 
     const float settings_sliders_left = std::max(m_imgui->calc_text_size(m_desc.at("minimal_distance")).x, m_imgui->calc_text_size(m_desc.at("points_density")).x) + m_imgui->scaled(1.f);