diff --git a/src/uxbox/data/shapes.cljs b/src/uxbox/data/shapes.cljs
index 0b5d52978..bcade26bb 100644
--- a/src/uxbox/data/shapes.cljs
+++ b/src/uxbox/data/shapes.cljs
@@ -13,7 +13,6 @@
             [uxbox.state :as st]
             [uxbox.state.shapes :as stsh]
             [uxbox.schema :as sc]
-            [uxbox.xforms :as xf]
             [uxbox.data.pages :as udp]
             [uxbox.util.geom.point :as gpt]
             [uxbox.util.data :refer (index-of)]))
@@ -294,23 +293,43 @@
           (update-in state [:workspace :selected] disj id)
           (update-in state [:workspace :selected] conj id))))))
 
+;; --- Select Shapes
+
+(defn- not-blocked-group?
+  "Check if the shape is a blocked group."
+  [shape]
+  (and (not (:blocked shape))
+       (= :builtin/group (:type shape))))
+
+(defn- has-blocked-parent?
+  "Check if shape has blocked parent."
+  [shape]
+  (sh/parent-satisfies? shape :blocked))
+
+(defn- has-locked-parent?
+  [shape]
+  (sh/parent-satisfies? shape :locked))
+
+(defrecord SelectShapes [selrect]
+  rs/UpdateEvent
+  (-apply-update [_ state]
+    (let [pageid (get-in state [:workspace :page])
+          xform (comp (filter #(= (:page %) pageid))
+                      (remove :hidden)
+                      (remove :blocked)
+                      (remove not-blocked-group?)
+                      (remove has-locked-parent?)
+                      (remove has-blocked-parent?)
+                      (map sh/outer-rect')
+                      (filter #(sh/contained-in? % selrect))
+                      (map :id))]
+      (->> (into #{} xform (vals (:shapes-by-id state)))
+           (assoc-in state [:workspace :selected])))))
+
 (defn select-shapes
   "Select shapes that matches the select rect."
   [selrect]
-  (reify
-    rs/UpdateEvent
-    (-apply-update [_ state]
-      (let [pageid (get-in state [:workspace :page])
-            xf (comp
-                (filter #(= (:page %) pageid))
-                (remove :hidden)
-                (remove #(and (not (:blocked %)) (= (:type %) :builtin/group)))
-                (remove #(and (not= % (sh/resolve-parent %)) (:blocked (sh/resolve-parent %))))
-                (map sh/outer-rect')
-                (filter #(sh/contained-in? % selrect))
-                (map :id))]
-        (->> (into #{} xf (vals (:shapes-by-id state)))
-             (assoc-in state [:workspace :selected]))))))
+  (SelectShapes. selrect))
 
 ;; --- Events (implicit) (for selected)
 
diff --git a/src/uxbox/shapes.cljs b/src/uxbox/shapes.cljs
index 1e49d63c8..cb4c44bef 100644
--- a/src/uxbox/shapes.cljs
+++ b/src/uxbox/shapes.cljs
@@ -498,6 +498,18 @@
     (resolve-parent (get-in @st/state [:shapes-by-id group]))
     shape))
 
+(defn parent-satisfies?
+  "Resolve the first parent that satisfies a condition."
+  [{:keys [group] :as shape} pred]
+  (let [shapes-by-id (:shapes-by-id @st/state)]
+    (if group
+      (loop [parent (get shapes-by-id group)]
+        (cond
+          (pred parent) true
+          (:group parent) (recur (get shapes-by-id (:group parent)))
+          :else false))
+      false)))
+
 (defn contained-in?
   "Check if a shape is contained in the
   provided selection rect."