diff --git a/src/libslic3r/SLA/Hollowing.cpp b/src/libslic3r/SLA/Hollowing.cpp
index ecc42b889..2a9662e85 100644
--- a/src/libslic3r/SLA/Hollowing.cpp
+++ b/src/libslic3r/SLA/Hollowing.cpp
@@ -119,7 +119,7 @@ Contour3D DrainHole::to_mesh() const
 {
     auto r = double(radius);
     auto h = double(height);
-    sla::Contour3D hole = sla::cylinder(r, h);
+    sla::Contour3D hole = sla::cylinder(r, h, steps);
     Eigen::Quaterniond q;
     q.setFromTwoVectors(Vec3d{0., 0., 1.}, normal.cast<double>());
     for(auto& p : hole.points) p = q * p + pos.cast<double>();
diff --git a/src/libslic3r/SLA/Hollowing.hpp b/src/libslic3r/SLA/Hollowing.hpp
index b3375ed1a..cc7d310ea 100644
--- a/src/libslic3r/SLA/Hollowing.hpp
+++ b/src/libslic3r/SLA/Hollowing.hpp
@@ -34,6 +34,9 @@ struct DrainHole
     DrainHole(Vec3f p, Vec3f n, float r, float h)
         : pos(p), normal(n), radius(r), height(h)
     {}
+
+    DrainHole(const DrainHole& rhs) :
+        DrainHole(rhs.pos, rhs.normal, rhs.radius, rhs.height) {}
     
     bool operator==(const DrainHole &sp) const;
     
@@ -50,6 +53,8 @@ struct DrainHole
     {
         ar(pos, normal, radius, height);
     }
+
+    static constexpr size_t steps = 32;
 };
 
 using DrainHoles = std::vector<DrainHole>;
diff --git a/src/slic3r/GUI/Gizmos/GLGizmoBase.cpp b/src/slic3r/GUI/Gizmos/GLGizmoBase.cpp
index c237198a9..daf7e1fd1 100644
--- a/src/slic3r/GUI/Gizmos/GLGizmoBase.cpp
+++ b/src/slic3r/GUI/Gizmos/GLGizmoBase.cpp
@@ -384,7 +384,7 @@ bool CommonGizmosData::update_from_backend(GLCanvas3D& canvas, ModelObject* mode
     if (! recent_update)
         recent_update = m_print_object_idx < 0 && old_po_idx >= 0;
 
-    return m_print_object_idx < 0 ? old_po_idx >=0 : false;
+    return recent_update;
 }
 
 
diff --git a/src/slic3r/GUI/Gizmos/GLGizmoHollow.cpp b/src/slic3r/GUI/Gizmos/GLGizmoHollow.cpp
index 11a78fd60..87a4960ee 100644
--- a/src/slic3r/GUI/Gizmos/GLGizmoHollow.cpp
+++ b/src/slic3r/GUI/Gizmos/GLGizmoHollow.cpp
@@ -12,7 +12,6 @@
 #include "slic3r/GUI/PresetBundle.hpp"
 #include "libslic3r/SLAPrint.hpp"
 #include "libslic3r/TriangleMesh.hpp"
-#include "libslic3r/MeshBoolean.hpp"
 
 
 namespace Slic3r {
@@ -59,8 +58,11 @@ void GLGizmoHollow::set_sla_support_data(ModelObject*, const Selection&)
 {
     if (m_c->recent_update) {
 
-        if (m_c->m_model_object)
+        if (m_c->m_model_object) {
             reload_cache();
+            if (m_c->has_drilled_mesh())
+                m_holes_in_drilled_mesh = m_c->m_model_object->sla_drain_holes;
+        }
 
         if (m_state == On) {
             m_parent.toggle_model_objects_visibility(false);
@@ -344,18 +346,25 @@ bool GLGizmoHollow::unproject_on_mesh(const Vec2d& mouse_pos, std::pair<Vec3f, V
     // The raycaster query
     Vec3f hit;
     Vec3f normal;
-    if (m_c->m_mesh_raycaster->unproject_on_mesh(mouse_pos, trafo.get_matrix(), camera, hit, normal, m_c->m_clipping_plane.get())) {
-
-        // User is about to manipulate a hole. If the gizmo currently shows drilled mesh,
-        // invalidate slaposDrillHoles so it returns to normal. To do this, hackishly
-        // add a hole, force SLAPrint::apply call that will invalidate the step because
-        // of it and then remove the hole again.
+    if (m_c->m_mesh_raycaster->unproject_on_mesh(
+            mouse_pos,
+            trafo.get_matrix(),
+            camera,
+            hit,
+            normal,
+            m_c->m_clipping_plane_distance != 0.f ? m_c->m_clipping_plane.get() : nullptr))
+    {
         if (m_c->has_drilled_mesh()) {
-            m_c->m_model_object->sla_drain_holes.push_back(sla::DrainHole());
-            m_selected.push_back(false);
-            m_parent.post_event(SimpleEvent(EVT_GLCANVAS_FORCE_UPDATE));
-            wxGetApp().CallAfter([this] { m_c->m_model_object->sla_drain_holes.pop_back(); m_selected.pop_back(); });
-            return false;
+            // in this case the raycaster sees the hollowed and drilled mesh.
+            // if the point lies on the surface created by the hole, we want
+            // to ignore it.
+            for (const sla::DrainHole& hole : m_holes_in_drilled_mesh) {
+                sla::DrainHole outer(hole);
+                outer.radius *= 1.001f;
+                outer.height *= 1.001f;
+                if (outer.is_inside(hit))
+                    return false;
+            }
         }
 
         // Return both the point and the facet normal.
@@ -527,8 +536,6 @@ void GLGizmoHollow::delete_selected_points()
         }
     }
 
-    m_parent.post_event(SimpleEvent(EVT_GLCANVAS_FORCE_UPDATE));
-
     select_point(NoPoints);
 }
 
diff --git a/src/slic3r/GUI/Gizmos/GLGizmoHollow.hpp b/src/slic3r/GUI/Gizmos/GLGizmoHollow.hpp
index c0e518e4d..2daf28b2a 100644
--- a/src/slic3r/GUI/Gizmos/GLGizmoHollow.hpp
+++ b/src/slic3r/GUI/Gizmos/GLGizmoHollow.hpp
@@ -70,6 +70,7 @@ private:
     float m_quality_stash = 0.5f;
     float m_closing_d_stash = 2.f;
     Vec3f m_hole_before_drag = Vec3f::Zero();
+    sla::DrainHoles m_holes_in_drilled_mesh;
 
     sla::DrainHoles m_holes_stash;
 
diff --git a/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp b/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp
index 5130b7a9a..05f33ae52 100644
--- a/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp
+++ b/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp
@@ -408,7 +408,14 @@ bool GLGizmoSlaSupports::unproject_on_mesh(const Vec2d& mouse_pos, std::pair<Vec
     // The raycaster query
     Vec3f hit;
     Vec3f normal;
-    if (m_c->m_mesh_raycaster->unproject_on_mesh(mouse_pos, trafo.get_matrix(), camera, hit, normal, m_c->m_clipping_plane.get())) {
+    if (m_c->m_mesh_raycaster->unproject_on_mesh(
+            mouse_pos,
+            trafo.get_matrix(),
+            camera,
+            hit,
+            normal,
+            m_c->m_clipping_plane_distance != 0.f ? m_c->m_clipping_plane.get() : nullptr))
+    {
         // Check whether the hit is in a hole
         bool in_hole = false;
         // In case the hollowed and drilled mesh is available, we can allow