diff --git a/pcbnew/autorouter/autoplace_tool.cpp b/pcbnew/autorouter/autoplace_tool.cpp
index 3d9abae342..34e32c195d 100644
--- a/pcbnew/autorouter/autoplace_tool.cpp
+++ b/pcbnew/autorouter/autoplace_tool.cpp
@@ -23,7 +23,10 @@
 
 
 #include <board_commit.h>
+#include <dialogs/dialog_locked_items_query.h>
+#include <tool/tool_manager.h>
 #include <tools/pcb_actions.h>
+#include <tools/pcb_selection_tool.h>
 #include <widgets/wx_infobar.h>
 #include <widgets/wx_progress_reporters.h>
 
@@ -59,7 +62,7 @@ static int refreshCallback( FOOTPRINT* aFootprint )
 }
 
 
-int AUTOPLACE_TOOL::autoplace( std::vector<FOOTPRINT*>& aFootprints, bool aPlaceOffboard )
+int AUTOPLACE_TOOL::autoplace( std::vector<FOOTPRINT*>& aFootprints )
 {
     BOX2I bbox = board()->GetBoardEdgesBoundingBox();
 
@@ -73,6 +76,35 @@ int AUTOPLACE_TOOL::autoplace( std::vector<FOOTPRINT*>& aFootprints, bool aPlace
         return 0;
     }
 
+    int locked_count = std::count_if( aFootprints.begin(), aFootprints.end(),
+                   [](FOOTPRINT* fp) { return fp->IsLocked(); } );
+
+    if( locked_count > 0 )
+    {
+        DIALOG_LOCKED_ITEMS_QUERY dlg( frame(), locked_count );
+
+        switch( dlg.ShowModal() )
+        {
+        case wxID_OK:
+            // Remove locked items from aFootprints
+            aFootprints.erase( std::remove_if( aFootprints.begin(), aFootprints.end(),
+                                               []( FOOTPRINT* fp )
+                                               {
+                                                   return fp->IsLocked();
+                                               } ),
+                               aFootprints.end() );
+            break;
+
+        case wxID_CANCEL:
+            // cancel operation
+            return 0;
+
+        case wxID_APPLY:
+            // Proceed with all items (do nothing)
+            break;
+        }
+    }
+
     Activate();
 
     AR_AUTOPLACER autoplacer( board() );
@@ -89,7 +121,7 @@ int AUTOPLACE_TOOL::autoplace( std::vector<FOOTPRINT*>& aFootprints, bool aPlace
             std::make_unique<WX_PROGRESS_REPORTER>( frame(), _( "Autoplace Components" ), 1 );
 
     autoplacer.SetProgressReporter( progressReporter.get() );
-    auto result = autoplacer.AutoplaceFootprints( aFootprints, &commit, aPlaceOffboard );
+    auto result = autoplacer.AutoplaceFootprints( aFootprints, &commit, false );
 
     if( result == AR_COMPLETED )
         commit.Push( _( "Autoplace components" ) );
@@ -107,18 +139,30 @@ int AUTOPLACE_TOOL::autoplaceSelected( const TOOL_EVENT& aEvent )
     for( EDA_ITEM* item : selection() )
     {
         if( item->Type() == PCB_FOOTPRINT_T )
-            footprints.push_back( static_cast<FOOTPRINT*>( item ) );
+        {
+            FOOTPRINT* footprint = static_cast<FOOTPRINT*>( item );
+            footprints.push_back( footprint );
+        }
     }
 
-    return autoplace( footprints, false );
+    return autoplace( footprints );
 }
 
 
 int AUTOPLACE_TOOL::autoplaceOffboard( const TOOL_EVENT& aEvent )
 {
+    SHAPE_POLY_SET boardShape;
+    board()->GetBoardPolygonOutlines( boardShape );
+
     std::vector<FOOTPRINT*> footprints;
 
-    return autoplace( footprints, true );
+    for( FOOTPRINT* footprint : board()->Footprints() )
+    {
+        if( !boardShape.Contains( footprint->GetPosition() ) )
+            footprints.push_back( footprint );
+    }
+
+    return autoplace( footprints );
 }
 
 
diff --git a/pcbnew/autorouter/autoplace_tool.h b/pcbnew/autorouter/autoplace_tool.h
index 2958dd9db8..321aeabf77 100644
--- a/pcbnew/autorouter/autoplace_tool.h
+++ b/pcbnew/autorouter/autoplace_tool.h
@@ -40,7 +40,7 @@ public:
     void setTransitions() override;
 
 private:
-    int autoplace( std::vector<FOOTPRINT*>& aFootprints, bool aPlaceOffboard );
+    int autoplace( std::vector<FOOTPRINT*>& aFootprints );
 
     int autoplaceSelected( const TOOL_EVENT& aEvent );
     int autoplaceOffboard( const TOOL_EVENT& aEvent );