diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt
index dea6f4036a..8e3e66057d 100644
--- a/common/CMakeLists.txt
+++ b/common/CMakeLists.txt
@@ -437,6 +437,7 @@ set( COMMON_SRCS
     tool/grid_menu.cpp
     tool/picker_tool.cpp
     tool/selection.cpp
+    tool/selection_tool.cpp
     tool/selection_conditions.cpp
     tool/tool_action.cpp
     tool/tool_base.cpp
diff --git a/common/hotkey_store.cpp b/common/hotkey_store.cpp
index 46f1aa083a..e11cd1ffee 100644
--- a/common/hotkey_store.cpp
+++ b/common/hotkey_store.cpp
@@ -44,19 +44,16 @@ static PSEUDO_ACTION* g_gesturePseudoActions[] = {
     new PSEUDO_ACTION( _( "Pan Up/Down" ), MD_SHIFT + PSEUDO_WXK_WHEEL ),
     new PSEUDO_ACTION( _( "Finish Drawing" ), PSEUDO_WXK_DBLCLICK ),
 #ifdef __WXOSX_MAC__
-    new PSEUDO_ACTION( _( "Show Clarify Selection Menu" ), MD_ALT + PSEUDO_WXK_CLICK ),
     new PSEUDO_ACTION( _( "Add to Selection" ), MD_SHIFT + PSEUDO_WXK_CLICK ),
     new PSEUDO_ACTION( _( "Toggle Selection State" ), MD_CTRL + PSEUDO_WXK_CLICK ),
     new PSEUDO_ACTION( _( "Remove from Selection" ), MD_SHIFT + MD_CTRL + PSEUDO_WXK_CLICK ),
 #else
-    new PSEUDO_ACTION( _( "Show Clarify Selection Menu" ), MD_CTRL + PSEUDO_WXK_CLICK ),
     new PSEUDO_ACTION( _( "Add to Selection" ), MD_SHIFT + PSEUDO_WXK_CLICK ),
     new PSEUDO_ACTION( _( "Toggle Selection State" ), MD_ALT + PSEUDO_WXK_CLICK ),
     new PSEUDO_ACTION( _( "Remove from Selection" ), MD_SHIFT + MD_ALT + PSEUDO_WXK_CLICK ),
 #endif
     new PSEUDO_ACTION( _( "Ignore Grid Snaps" ), MD_CTRL ),
     new PSEUDO_ACTION( _( "Ignore Other Snaps" ), MD_SHIFT ),
-    new PSEUDO_ACTION( _( "Ignore H/V/45 Constraints" ), MD_SHIFT )
 };
 
 static PSEUDO_ACTION* g_standardPlatformCommands[] = {
diff --git a/common/tool/actions.cpp b/common/tool/actions.cpp
index 94bc8502bb..1c6f8aded2 100644
--- a/common/tool/actions.cpp
+++ b/common/tool/actions.cpp
@@ -665,3 +665,5 @@ const TOOL_EVENT EVENTS::SelectedItemsMoved( TC_MESSAGE, TA_ACTION, "common.Inte
 const TOOL_EVENT EVENTS::InhibitSelectionEditing( TC_MESSAGE, TA_ACTION, "common.Interactive.inhibit" );
 const TOOL_EVENT EVENTS::UninhibitSelectionEditing( TC_MESSAGE, TA_ACTION, "common.Interactive.uninhibit" );
 
+const TOOL_EVENT EVENTS::DisambiguatePoint( TC_MESSAGE, TA_ACTION, "common.Interactive.disambiguate" );
+
diff --git a/common/tool/selection_tool.cpp b/common/tool/selection_tool.cpp
new file mode 100644
index 0000000000..6153aa3369
--- /dev/null
+++ b/common/tool/selection_tool.cpp
@@ -0,0 +1,58 @@
+/*
+ * This program source code file is part of KiCad, a free EDA CAD application.
+ *
+ * Copyright (C) 2021 KiCad Developers, see CHANGELOG.TXT for contributors.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 3
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, you may find one here:
+ * http://www.gnu.org/licenses/gpl-3.0.html
+ * or you may search the http://www.gnu.org website for the version 3 license,
+ * or you may write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+#include <tool/selection_tool.h>
+
+
+
+SELECTION_TOOL::SELECTION_TOOL() :
+    m_additive( false ),
+    m_subtractive( false ),
+    m_exclusive_or( false ),
+    m_multiple( false ),
+    m_skip_heuristics( false ),
+    m_highlight_modifier( false ),
+    m_drag_additive( false ),
+    m_drag_subtractive( false )
+{
+}
+
+void SELECTION_TOOL::setModifiersState( bool aShiftState, bool aCtrlState, bool aAltState )
+{
+    // Set the configuration of m_additive, m_subtractive, m_exclusive_or
+    // from the state of modifier keys SHIFT, CTRL, ALT
+
+    // on left click, a selection is made, depending on modifiers ALT, SHIFT, CTRL:
+    // ALT key cannot be used on MSW because of a conflict with the system menu
+    // for this reason, we do not use the ALT key modifier.
+
+    // Drag is more forgiving and allows either Ctrl+drag or Shift+Drag to add to the selection
+
+    m_subtractive        = aCtrlState && aShiftState && !aAltState;
+    m_additive           = !aCtrlState && aShiftState && !aAltState;
+    m_exclusive_or       = false;
+    m_highlight_modifier = aCtrlState && !aShiftState && !aAltState;
+
+    m_drag_additive      = ( aCtrlState || aShiftState ) && ! aAltState;
+    m_drag_subtractive   = aCtrlState && aShiftState && !aAltState;
+}
diff --git a/eeschema/tools/ee_selection_tool.cpp b/eeschema/tools/ee_selection_tool.cpp
index 23c0a964b9..b444bb1343 100644
--- a/eeschema/tools/ee_selection_tool.cpp
+++ b/eeschema/tools/ee_selection_tool.cpp
@@ -107,11 +107,6 @@ SELECTION_CONDITION EE_CONDITIONS::SingleMultiUnitSymbol = []( const SELECTION&
 EE_SELECTION_TOOL::EE_SELECTION_TOOL() :
         TOOL_INTERACTIVE( "eeschema.InteractiveSelection" ),
         m_frame( nullptr ),
-        m_additive( false ),
-        m_subtractive( false ),
-        m_exclusive_or( false ),
-        m_multiple( false ),
-        m_skip_heuristics( false ),
         m_nonModifiedCursor( KICURSOR::ARROW ),
         m_isSymbolEditor( false ),
         m_isSymbolViewer( false ),
@@ -228,6 +223,9 @@ bool EE_SELECTION_TOOL::Init()
     menu.AddSeparator( 1000 );
     m_frame->AddStandardSubMenus( m_menu );
 
+    m_disambiguateTimer.SetOwner( this );
+    Connect( wxEVT_TIMER, wxTimerEventHandler( EE_SELECTION_TOOL::onDisambiguationExpire ), nullptr, this );
+
     return true;
 }
 
@@ -322,55 +320,6 @@ const KICAD_T movableSymbolAliasItems[] =
 };
 
 
-void EE_SELECTION_TOOL::setModifiersState( bool aShiftState, bool aCtrlState, bool aAltState )
-{
-    // Set the configuration of m_additive, m_subtractive, m_exclusive_or
-    // from the state of modifier keys SHIFT, CTRL, ALT and the OS
-
-    // on left click, a selection is made, depending on modifiers ALT, SHIFT, CTRL:
-    // Due to the fact ALT key modifier cannot be used freely on Windows and Linux,
-    // actions are different on OSX and others OS
-    // Especially, ALT key cannot be used to force showing the full selection choice
-    // context menu (the menu is immediately closed on Windows )
-    //
-    // No modifier = select items and deselect previous selection
-    // ALT (on OSX) = skip heuristic and show full selection choice
-    // ALT (on others) = exclusive OR of selected items (inverse selection)
-    //
-    // CTRL/CMD (on OSX) = exclusive OR of selected items (inverse selection)
-    // CTRL (on others) = skip heuristic and show full selection choice
-    //
-    // SHIFT = add selected items to the current selection
-    //
-    // CTRL/CMD+SHIFT (on OSX) = remove selected items to the current selection
-    // CTRL+SHIFT (on others) = unused (can be used for a new action)
-    //
-    // CTRL/CMT+ALT (on OSX) = unused (can be used for a new action)
-    // CTRL+ALT (on others) = do nothing (same as no modifier)
-    //
-    // SHIFT+ALT (on OSX) =  do nothing (same as no modifier)
-    // SHIFT+ALT (on others) = remove selected items to the current selection
-
-#ifdef __WXOSX_MAC__
-    m_subtractive     = aCtrlState && aShiftState && !aAltState;
-    m_additive        = aShiftState && !aCtrlState && !aAltState;
-    m_exclusive_or    = aCtrlState && !aShiftState && !aAltState;
-    m_skip_heuristics = aAltState && !aShiftState && !aCtrlState;
-
-#else
-    m_subtractive  = aShiftState && !aCtrlState && aAltState;
-    m_additive     = aShiftState && !aCtrlState && !aAltState;
-    m_exclusive_or = !aShiftState && !aCtrlState && aAltState;
-
-    // Is the user requesting that the selection list include all possible
-    // items without removing less likely selection candidates
-    // Cannot use the Alt key on windows or the disambiguation context menu is immediately
-    // dismissed rendering it useless.
-    m_skip_heuristics = aCtrlState && !aShiftState && !aAltState;
-#endif
-}
-
-
 int EE_SELECTION_TOOL::Main( const TOOL_EVENT& aEvent )
 {
     m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::ARROW );
@@ -394,9 +343,26 @@ int EE_SELECTION_TOOL::Main( const TOOL_EVENT& aEvent )
         MOUSE_DRAG_ACTION drag_action = m_frame->GetDragAction();
         EE_GRID_HELPER grid( m_toolMgr );
 
-        // Single click? Select single object
-        if( evt->IsClick( BUT_LEFT ) )
+        if( evt->IsMouseDown( BUT_LEFT ) )
         {
+            // Avoid triggering when running under other tools
+            if( m_toolMgr->GetCurrentTool() == this )
+                m_disambiguateTimer.StartOnce( 500 );
+        }
+        // Single click? Select single object
+        else if( evt->IsClick( BUT_LEFT ) )
+        {
+            // If the timer has stopped, then we have already run the disambiguate routine
+            // and we don't want to register an extra click here
+            if( !m_disambiguateTimer.IsRunning() )
+            {
+                evt->SetPassEvent();
+                continue;
+            }
+
+            m_disambiguateTimer.Stop();
+
+
             if( SCH_EDIT_FRAME* schframe = dynamic_cast<SCH_EDIT_FRAME*>( m_frame ) )
                 schframe->FocusOnItem( nullptr );
 
@@ -468,6 +434,8 @@ int EE_SELECTION_TOOL::Main( const TOOL_EVENT& aEvent )
         }
         else if( evt->IsClick( BUT_RIGHT ) )
         {
+            m_disambiguateTimer.Stop();
+
             // right click? if there is any object - show the context menu
             bool selectionCancelled = false;
 
@@ -529,6 +497,8 @@ int EE_SELECTION_TOOL::Main( const TOOL_EVENT& aEvent )
         }
         else if( evt->IsDblClick( BUT_MIDDLE ) )
         {
+            m_disambiguateTimer.Stop();
+
             // Middle double click?  Do zoom to fit or zoom to objects
             if( evt->Modifier( MD_CTRL ) ) // Is CTRL key down?
                 m_toolMgr->RunAction( ACTIONS::zoomFitObjects, true );
@@ -537,6 +507,8 @@ int EE_SELECTION_TOOL::Main( const TOOL_EVENT& aEvent )
         }
         else if( evt->IsDrag( BUT_LEFT ) )
         {
+            m_disambiguateTimer.Stop();
+
             // Is another tool already moving a new object?  Don't allow a drag start
             if( !m_selection.Empty() && m_selection[0]->HasFlag( IS_NEW | IS_MOVING ) )
             {
@@ -589,6 +561,8 @@ int EE_SELECTION_TOOL::Main( const TOOL_EVENT& aEvent )
         }
         else if( evt->Category() == TC_COMMAND && evt->Action() == TA_CHOICE_MENU_CHOICE )
         {
+            m_disambiguateTimer.Stop();
+
             // context sub-menu selection?  Handle unit selection or bus unfolding
             if( evt->GetCommandId().get() >= ID_POPUP_SCH_SELECT_UNIT_CMP
                 && evt->GetCommandId().get() <= ID_POPUP_SCH_SELECT_UNIT_SYM_MAX )
@@ -609,6 +583,8 @@ int EE_SELECTION_TOOL::Main( const TOOL_EVENT& aEvent )
         }
         else if( evt->IsCancelInteractive() )
         {
+            m_disambiguateTimer.Stop();
+
             if( SCH_EDIT_FRAME* schframe = dynamic_cast<SCH_EDIT_FRAME*>( m_frame ) )
                 schframe->FocusOnItem( nullptr );
 
@@ -738,6 +714,8 @@ int EE_SELECTION_TOOL::Main( const TOOL_EVENT& aEvent )
         }
     }
 
+    m_disambiguateTimer.Stop();
+
     // Shutting down; clear the selection
     m_selection.Clear();
 
@@ -745,6 +723,25 @@ int EE_SELECTION_TOOL::Main( const TOOL_EVENT& aEvent )
 }
 
 
+int EE_SELECTION_TOOL::disambiguateCursor( const TOOL_EVENT& aEvent )
+{
+    VECTOR2I pos = m_toolMgr->GetMousePosition();
+
+    m_skip_heuristics = true;
+    SelectPoint( pos, EE_COLLECTOR::AllItems, nullptr, nullptr, false, m_additive, m_subtractive,
+            m_exclusive_or );
+    m_skip_heuristics = false;
+
+    return 0;
+}
+
+
+void EE_SELECTION_TOOL::onDisambiguationExpire( wxTimerEvent& aEvent )
+{
+    m_toolMgr->ProcessEvent( EVENTS::DisambiguatePoint );
+}
+
+
 void EE_SELECTION_TOOL::OnIdle( wxIdleEvent& aEvent )
 {
     if( m_frame->ToolStackIsEmpty() && !m_multiple )
@@ -846,10 +843,7 @@ bool EE_SELECTION_TOOL::selectPoint( EE_COLLECTOR& aCollector, EDA_ITEM** aItem,
     // If still more than one item we're going to have to ask the user.
     if( aCollector.GetCount() > 1 )
     {
-        // Must call selectionMenu via RunAction() to avoid event-loop contention
-        m_toolMgr->RunAction( EE_ACTIONS::selectionMenu, true, &aCollector );
-
-        if( aCollector.m_MenuCancelled )
+        if( !doSelectionMenu( &aCollector ) || aCollector.m_MenuCancelled )
         {
             if( aSelectionCancelledFlag )
                 *aSelectionCancelledFlag = true;
@@ -1196,15 +1190,15 @@ bool EE_SELECTION_TOOL::selectMultiple()
 
         if( evt->IsDrag( BUT_LEFT ) )
         {
-            if( !m_additive && !m_subtractive && !m_exclusive_or )
+            if( !m_drag_additive && !m_drag_subtractive )
                 ClearSelection();
 
             // Start drawing a selection box
             area.SetOrigin( evt->DragOrigin() );
             area.SetEnd( evt->Position() );
-            area.SetAdditive( m_additive );
-            area.SetSubtractive( m_subtractive );
-            area.SetExclusiveOr( m_exclusive_or );
+            area.SetAdditive( m_drag_additive );
+            area.SetSubtractive( m_drag_subtractive );
+            area.SetExclusiveOr( false );
 
             view->SetVisible( &area, true );
             view->Update( &area );
@@ -1904,6 +1898,8 @@ void EE_SELECTION_TOOL::setTransitions()
     Go( &EE_SELECTION_TOOL::SelectionMenu,       EE_ACTIONS::selectionMenu.MakeEvent() );
 
     Go( &EE_SELECTION_TOOL::SelectAll,           EE_ACTIONS::selectAll.MakeEvent() );
+
+    Go( &EE_SELECTION_TOOL::disambiguateCursor,  EVENTS::DisambiguatePoint );
 }
 
 
diff --git a/eeschema/tools/ee_selection_tool.h b/eeschema/tools/ee_selection_tool.h
index e4d25d0b66..93359c467f 100644
--- a/eeschema/tools/ee_selection_tool.h
+++ b/eeschema/tools/ee_selection_tool.h
@@ -25,7 +25,7 @@
 #ifndef KICAD_SCH_SELECTION_TOOL_H
 #define KICAD_SCH_SELECTION_TOOL_H
 
-#include <tool/tool_interactive.h>
+#include <tool/selection_tool.h>
 #include <tool/action_menu.h>
 #include <tool/tool_menu.h>
 #include <tools/ee_selection.h>
@@ -52,7 +52,7 @@ public:
 };
 
 
-class EE_SELECTION_TOOL : public TOOL_INTERACTIVE
+class EE_SELECTION_TOOL : public SELECTION_TOOL, public TOOL_INTERACTIVE
 {
 public:
     EE_SELECTION_TOOL();
@@ -226,6 +226,18 @@ private:
      */
     bool doSelectionMenu( EE_COLLECTOR* aItems );
 
+    /**
+     * Start the process to show our disambiguation menu once the user has kept
+     * the mouse down for the minimum time
+     * @param aEvent
+     */
+    void onDisambiguationExpire( wxTimerEvent& aEvent );
+
+    /**
+     * Handle disambiguation actions including displaying the menu.
+     */
+    int disambiguateCursor( const TOOL_EVENT& aEvent );
+
     /**
      * Take necessary action mark an item as selected.
      *
@@ -272,23 +284,10 @@ private:
     void setTransitions() override;
 
 private:
-    /**
-     * Set the configuration of m_additive, m_subtractive, m_exclusive_or, m_skip_heuristics
-     * from the state of modifier keys SHIFT, CTRL, ALT and depending on the OS
-     */
-    void setModifiersState( bool aShiftState, bool aCtrlState, bool aAltState );
 
     SCH_BASE_FRAME* m_frame;             // Pointer to the parent frame
     EE_SELECTION    m_selection;         // Current state of selection
 
-    bool            m_additive;          // Items should be added to sel (instead of replacing)
-    bool            m_subtractive;       // Items should be removed from sel
-    bool            m_exclusive_or;      // Items' selection state should be toggled
-    bool            m_multiple;          // Multiple selection mode is active
-    bool            m_skip_heuristics;   // Show disambuguation menu for all items under the
-                                         // cursor rather than trying to narrow them down first
-                                         // using heuristics
-
     KICURSOR        m_nonModifiedCursor; // Cursor in the absence of shift/ctrl/alt
 
     bool            m_isSymbolEditor;    // True when the symbol editor is the parent frame
diff --git a/gerbview/tools/gerbview_selection_tool.cpp b/gerbview/tools/gerbview_selection_tool.cpp
index 21a8681bfa..629cae2ec3 100644
--- a/gerbview/tools/gerbview_selection_tool.cpp
+++ b/gerbview/tools/gerbview_selection_tool.cpp
@@ -114,10 +114,7 @@ private:
 
 GERBVIEW_SELECTION_TOOL::GERBVIEW_SELECTION_TOOL() :
         TOOL_INTERACTIVE( "gerbview.InteractiveSelection" ),
-        m_frame( nullptr ),
-        m_additive( false ),
-        m_subtractive( false ),
-        m_exclusive_or( false )
+        m_frame( nullptr )
 {
     m_preliminary = true;
 }
@@ -194,14 +191,9 @@ int GERBVIEW_SELECTION_TOOL::Main( const TOOL_EVENT& aEvent )
         if( m_frame->ToolStackIsEmpty() )
             m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::ARROW );
 
-        m_additive = m_subtractive = m_exclusive_or = false;
-
-        if( evt->Modifier( MD_SHIFT ) && evt->Modifier( MD_CTRL ) )
-            m_subtractive = true;
-        else if( evt->Modifier( MD_SHIFT ) )
-            m_additive = true;
-        else if( evt->Modifier( MD_CTRL ) )
-            m_exclusive_or = true;
+        // on left click, a selection is made, depending on modifiers ALT, SHIFT, CTRL:
+        setModifiersState( evt->Modifier( MD_SHIFT ), evt->Modifier( MD_CTRL ),
+                           evt->Modifier( MD_ALT ) );
 
         // single click? Select single object
         if( evt->IsClick( BUT_LEFT ) )
diff --git a/gerbview/tools/gerbview_selection_tool.h b/gerbview/tools/gerbview_selection_tool.h
index e93835de7c..d33c0ea76e 100644
--- a/gerbview/tools/gerbview_selection_tool.h
+++ b/gerbview/tools/gerbview_selection_tool.h
@@ -26,6 +26,7 @@
 #include <tool/tool_interactive.h>
 #include <tool/action_menu.h>
 #include <tool/selection_conditions.h>
+#include <tool/selection_tool.h>
 #include <tool/tool_menu.h>
 #include <tools/gerbview_selection.h>
 #include <gerbview_frame.h>
@@ -42,7 +43,7 @@ namespace KIGFX
 /**
  * Selection tool for GerbView, based on the one in Pcbnew
  */
-class GERBVIEW_SELECTION_TOOL : public TOOL_INTERACTIVE
+class GERBVIEW_SELECTION_TOOL : public SELECTION_TOOL, public TOOL_INTERACTIVE
 {
 public:
     GERBVIEW_SELECTION_TOOL();
@@ -150,9 +151,6 @@ private:
     GERBVIEW_FRAME* m_frame;        // Pointer to the parent frame.
     GERBVIEW_SELECTION m_selection; // Current state of selection.
 
-    bool m_additive;                // Items should be added to selection (instead of replacing)
-    bool m_subtractive;             // Items should be removed from selection
-    bool m_exclusive_or;            // Items' selection state should be toggled
     bool m_preliminary;             // Determines if the selection is preliminary or final.
 };
 
diff --git a/include/tool/actions.h b/include/tool/actions.h
index 7e24e9c6f7..9b46d23f51 100644
--- a/include/tool/actions.h
+++ b/include/tool/actions.h
@@ -209,6 +209,9 @@ public:
     ///< Used to inform tools that the selection should temporarily be non-editable
     const static TOOL_EVENT InhibitSelectionEditing;
     const static TOOL_EVENT UninhibitSelectionEditing;
+
+    ///< Used to inform tool that it should display the disambiguation menu
+    const static TOOL_EVENT DisambiguatePoint;
 };
 
 #endif // __ACTIONS_H
diff --git a/include/tool/selection_tool.h b/include/tool/selection_tool.h
new file mode 100644
index 0000000000..ec7cc25a17
--- /dev/null
+++ b/include/tool/selection_tool.h
@@ -0,0 +1,60 @@
+/*
+ * This program source code file is part of KiCad, a free EDA CAD application.
+ *
+ * Copyright (C) 2021 KiCad Developers, see CHANGELOG.TXT for contributors.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 3
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, you may find one here:
+ * http://www.gnu.org/licenses/gpl-3.0.html
+ * or you may search the http://www.gnu.org website for the version 3 license,
+ * or you may write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+#pragma once
+#ifndef INCLUDE_TOOL_SELECTION_TOOL_H_
+#define INCLUDE_TOOL_SELECTION_TOOL_H_
+
+
+#include <tool/tool_interactive.h>
+#include <wx/timer.h>
+
+class SELECTION_TOOL : public wxEvtHandler
+{
+public:
+    SELECTION_TOOL();
+    ~SELECTION_TOOL(){};
+
+
+protected:
+    /**
+     * Set the configuration of m_additive, m_subtractive, m_exclusive_or, m_skip_heuristics
+     * from the state of modifier keys SHIFT, CTRL, ALT and depending on the OS
+     */
+    void setModifiersState( bool aShiftState, bool aCtrlState, bool aAltState );
+
+    bool            m_additive;          // Items should be added to sel (instead of replacing)
+    bool            m_subtractive;       // Items should be removed from sel
+    bool            m_exclusive_or;      // Items' selection state should be toggled
+    bool            m_multiple;          // Multiple selection mode is active
+    bool            m_skip_heuristics;   // Show disambuguation menu for all items under the
+                                         // cursor rather than trying to narrow them down first
+                                         // using heuristics
+    bool            m_highlight_modifier;// select highlight net on left click
+    bool            m_drag_additive;     // Add multiple items to selection
+    bool            m_drag_subtractive;  // Remove multiple from selection
+
+    wxTimer         m_disambiguateTimer; // Timer to show the disambiguate menu
+};
+
+#endif /* INCLUDE_TOOL_SELECTION_TOOL_H_ */
diff --git a/include/tool/tool_event.h b/include/tool/tool_event.h
index c75603d1dd..601977e977 100644
--- a/include/tool/tool_event.h
+++ b/include/tool/tool_event.h
@@ -287,6 +287,11 @@ public:
         return m_actions == TA_MOUSE_DRAG && ( m_mouseButtons & aButtonMask ) == m_mouseButtons;
     }
 
+    bool IsMouseDown( int aButtonMask = BUT_ANY ) const
+    {
+        return m_actions == TA_MOUSE_DOWN && ( m_mouseButtons & aButtonMask ) == m_mouseButtons;
+    }
+
     bool IsMouseUp( int aButtonMask = BUT_ANY ) const
     {
         return m_actions == TA_MOUSE_UP && ( m_mouseButtons & aButtonMask ) == m_mouseButtons;
diff --git a/pagelayout_editor/tools/pl_selection_tool.cpp b/pagelayout_editor/tools/pl_selection_tool.cpp
index 0be8941b47..16ddd2fb1d 100644
--- a/pagelayout_editor/tools/pl_selection_tool.cpp
+++ b/pagelayout_editor/tools/pl_selection_tool.cpp
@@ -50,12 +50,7 @@
 
 PL_SELECTION_TOOL::PL_SELECTION_TOOL() :
         TOOL_INTERACTIVE( "plEditor.InteractiveSelection" ),
-        m_frame( nullptr ),
-        m_additive( false ),
-        m_subtractive( false ),
-        m_exclusive_or( false ),
-        m_multiple( false ),
-        m_skip_heuristics( false )
+        m_frame( nullptr )
 {
 }
 
@@ -75,6 +70,9 @@ bool PL_SELECTION_TOOL::Init()
     menu.AddSeparator( 1000 );
     m_frame->AddStandardSubMenus( m_menu );
 
+    m_disambiguateTimer.SetOwner( this );
+    Connect( wxEVT_TIMER, wxTimerEventHandler( PL_SELECTION_TOOL::onDisambiguationExpire ), nullptr, this );
+
     return true;
 }
 
@@ -107,79 +105,36 @@ int PL_SELECTION_TOOL::Main( const TOOL_EVENT& aEvent )
     while( TOOL_EVENT* evt = Wait() )
     {
         // on left click, a selection is made, depending on modifiers ALT, SHIFT, CTRL:
-        // Due to the fact ALT key modifier cannot be used freely on Winows and Linux,
-        // actions are different on OSX and others OS
-        // Especially, ALT key cannot be used to force showing the full selection choice
-        // context menu (the menu is immediately closed on Windows )
-        //
-        // No modifier = select items and deselect previous selection
-        // ALT (on OSX) = skip heuristic and show full selection choice
-        // ALT (on others) = exclusive OR of selected items (inverse selection)
-        //
-        // CTRL/CMD (on OSX) = exclusive OR of selected items (inverse selection)
-        // CTRL (on others) = skip heuristic and show full selection choice
-        //
-        // SHIFT = add selected items to the current selection
-        //
-        // CTRL/CMD+SHIFT (on OSX) = remove selected items to the current selection
-        // CTRL+SHIFT (on others) = unused (can be used for a new action)
-        //
-        // CTRL/CMT+ALT (on OSX) = unused (can be used for a new action)
-        // CTRL+ALT (on others) = do nothing (same as no modifier)
-        //
-        // SHIFT+ALT (on OSX) =  do nothing (same as no modifier)
-        // SHIFT+ALT (on others) = remove selected items to the current selection
-
-#ifdef __WXOSX_MAC__
-        m_subtractive = evt->Modifier( MD_CTRL ) &&
-                        evt->Modifier( MD_SHIFT ) &&
-                        !evt->Modifier( MD_ALT );
-
-        m_additive = evt->Modifier( MD_SHIFT ) &&
-                     !evt->Modifier( MD_CTRL ) &&
-                     !evt->Modifier( MD_ALT );
-
-        m_exclusive_or = evt->Modifier( MD_CTRL ) &&
-                         !evt->Modifier( MD_SHIFT ) &&
-                         !evt->Modifier( MD_ALT );
-
-        m_skip_heuristics = evt->Modifier( MD_ALT ) &&
-                            !evt->Modifier( MD_SHIFT ) &&
-                            !evt->Modifier( MD_CTRL );
-
-#else
-        m_subtractive = evt->Modifier( MD_SHIFT )
-                        && !evt->Modifier( MD_CTRL )
-                        && evt->Modifier( MD_ALT );
-
-        m_additive = evt->Modifier( MD_SHIFT )
-                     && !evt->Modifier( MD_CTRL )
-                     && !evt->Modifier( MD_ALT );
-
-        m_exclusive_or = !evt->Modifier( MD_SHIFT )
-                         && !evt->Modifier( MD_CTRL )
-                         && evt->Modifier( MD_ALT );
-
-        // Is the user requesting that the selection list include all possible
-        // items without removing less likely selection candidates
-        // Cannot use the Alt key on windows or the disambiguation context menu is immediately
-        // dismissed rendering it useless.
-        m_skip_heuristics = evt->Modifier( MD_CTRL )
-                            && !evt->Modifier( MD_SHIFT )
-                            && !evt->Modifier( MD_ALT );
-#endif
+        setModifiersState( evt->Modifier( MD_SHIFT ), evt->Modifier( MD_CTRL ),
+                           evt->Modifier( MD_ALT ) );
 
         bool modifier_enabled = m_subtractive || m_additive || m_exclusive_or;
 
-        // Single click? Select single object
-        if( evt->IsClick( BUT_LEFT ) )
+        if( evt->IsMouseDown( BUT_LEFT ) )
         {
+            // Avoid triggering when running under other tools
+            if( m_toolMgr->GetCurrentTool() == this )
+                m_disambiguateTimer.StartOnce( 500 );
+        }
+        // Single click? Select single object
+        else if( evt->IsClick( BUT_LEFT ) )
+        {
+            // If the timer has stopped, then we have already run the disambiguate routine
+            // and we don't want to register an extra click here
+            if( !m_disambiguateTimer.IsRunning() )
+            {
+                evt->SetPassEvent();
+                continue;
+            }
+
+            m_disambiguateTimer.Stop();
             SelectPoint( evt->Position() );
         }
 
         // right click? if there is any object - show the context menu
         else if( evt->IsClick( BUT_RIGHT ) )
         {
+            m_disambiguateTimer.Stop();
             bool selectionCancelled = false;
 
             if( m_selection.Empty() )
@@ -201,6 +156,8 @@ int PL_SELECTION_TOOL::Main( const TOOL_EVENT& aEvent )
         // drag with LMB? Select multiple objects (or at least draw a selection box) or drag them
         else if( evt->IsDrag( BUT_LEFT ) )
         {
+            m_disambiguateTimer.Stop();
+
             if( modifier_enabled || m_selection.Empty() )
             {
                 selectMultiple();
@@ -229,6 +186,7 @@ int PL_SELECTION_TOOL::Main( const TOOL_EVENT& aEvent )
 
         else if( evt->IsCancelInteractive() )
         {
+            m_disambiguateTimer.Stop();
             ClearSelection();
         }
 
@@ -269,6 +227,24 @@ int PL_SELECTION_TOOL::Main( const TOOL_EVENT& aEvent )
 }
 
 
+int PL_SELECTION_TOOL::disambiguateCursor( const TOOL_EVENT& aEvent )
+{
+    VECTOR2I pos = m_toolMgr->GetMousePosition();
+
+    m_skip_heuristics = true;
+    SelectPoint( pos );
+    m_skip_heuristics = false;
+
+    return 0;
+}
+
+
+void PL_SELECTION_TOOL::onDisambiguationExpire( wxTimerEvent& aEvent )
+{
+    m_toolMgr->ProcessEvent( EVENTS::DisambiguatePoint );
+}
+
+
 PL_SELECTION& PL_SELECTION_TOOL::GetSelection()
 {
     return m_selection;
@@ -302,8 +278,7 @@ void PL_SELECTION_TOOL::SelectPoint( const VECTOR2I& aWhere, bool* aSelectionCan
     // If still more than one item we're going to have to ask the user.
     if( collector.GetCount() > 1 )
     {
-        // Must call selectionMenu via RunAction() to avoid event-loop contention
-        m_toolMgr->RunAction( PL_ACTIONS::selectionMenu, true, &collector );
+        doSelectionMenu( &collector );
 
         if( collector.m_MenuCancelled )
         {
@@ -314,12 +289,18 @@ void PL_SELECTION_TOOL::SelectPoint( const VECTOR2I& aWhere, bool* aSelectionCan
         }
     }
 
-    if( !m_additive && !m_subtractive && !m_exclusive_or )
-        ClearSelection();
-
     bool anyAdded      = false;
     bool anySubtracted = false;
 
+
+    if( !m_additive && !m_subtractive && !m_exclusive_or )
+    {
+        if( collector.GetCount() == 0 )
+            anySubtracted = true;
+
+        ClearSelection();
+    }
+
     if( collector.GetCount() > 0 )
     {
         for( int i = 0; i < collector.GetCount(); ++i )
@@ -407,15 +388,15 @@ bool PL_SELECTION_TOOL::selectMultiple()
 
         if( evt->IsDrag( BUT_LEFT ) )
         {
-            if( !m_additive && !m_subtractive && !m_exclusive_or )
+            if( !m_drag_additive && !m_drag_subtractive )
                 ClearSelection();
 
             // Start drawing a selection box
             area.SetOrigin( evt->DragOrigin() );
             area.SetEnd( evt->Position() );
-            area.SetAdditive( m_additive );
-            area.SetSubtractive( m_subtractive );
-            area.SetExclusiveOr( m_exclusive_or );
+            area.SetAdditive( m_drag_additive );
+            area.SetSubtractive( m_drag_subtractive );
+            area.SetExclusiveOr( false );
 
             view->SetVisible( &area, true );
             view->Update( &area );
@@ -835,4 +816,6 @@ void PL_SELECTION_TOOL::setTransitions()
     Go( &PL_SELECTION_TOOL::RemoveItemFromSel,     PL_ACTIONS::removeItemFromSel.MakeEvent() );
     Go( &PL_SELECTION_TOOL::RemoveItemsFromSel,    PL_ACTIONS::removeItemsFromSel.MakeEvent() );
     Go( &PL_SELECTION_TOOL::SelectionMenu,         PL_ACTIONS::selectionMenu.MakeEvent() );
+
+    Go( &PL_SELECTION_TOOL::disambiguateCursor,    EVENTS::DisambiguatePoint );
 }
diff --git a/pagelayout_editor/tools/pl_selection_tool.h b/pagelayout_editor/tools/pl_selection_tool.h
index 2f795c8b92..fbdf117fb9 100644
--- a/pagelayout_editor/tools/pl_selection_tool.h
+++ b/pagelayout_editor/tools/pl_selection_tool.h
@@ -25,6 +25,7 @@
 #ifndef PL_SELECTION_TOOL_H
 #define PL_SELECTION_TOOL_H
 
+#include <tool/selection_tool.h>
 #include <tool/tool_interactive.h>
 #include <tool/tool_menu.h>
 #include "tools/pl_selection.h"
@@ -39,7 +40,7 @@ namespace KIGFX
 }
 
 
-class PL_SELECTION_TOOL : public TOOL_INTERACTIVE
+class PL_SELECTION_TOOL : public SELECTION_TOOL, public TOOL_INTERACTIVE
 {
 public:
     PL_SELECTION_TOOL();
@@ -133,6 +134,18 @@ private:
      */
     bool doSelectionMenu( COLLECTOR* aItems );
 
+    /**
+     * Start the process to show our disambiguation menu once the user has kept
+     * the mouse down for the minimum time
+     * @param aEvent
+     */
+    void onDisambiguationExpire( wxTimerEvent& aEvent );
+
+    /**
+     * Handle disambiguation actions including displaying the menu.
+     */
+    int disambiguateCursor( const TOOL_EVENT& aEvent );
+
     /**
      * Takes necessary action mark an item as selected.
      *
@@ -176,12 +189,6 @@ private:
 private:
     PL_EDITOR_FRAME* m_frame;   // Pointer to the parent frame
     PL_SELECTION m_selection;   // Current state of selection
-
-    bool m_additive;            // Items should be added to selection (instead of replacing)
-    bool m_subtractive;         // Items should be removed from selection
-    bool m_exclusive_or;        // Items' selection state should be toggled
-    bool m_multiple;            // Multiple selection mode is active
-    bool m_skip_heuristics;     // Heuristics are not allowed when choosing item under cursor
 };
 
 #endif //PL_SELECTION_TOOL_H
diff --git a/pcbnew/tools/board_inspection_tool.h b/pcbnew/tools/board_inspection_tool.h
index beed2eb67a..4788d2e899 100644
--- a/pcbnew/tools/board_inspection_tool.h
+++ b/pcbnew/tools/board_inspection_tool.h
@@ -106,8 +106,6 @@ public:
     }
 
 private:
-    ///< Event handler to recalculate dynamic ratsnest.
-    void ratsnestTimer( wxTimerEvent& aEvent );
 
     ///< Recalculate dynamic ratsnest for the current selection.
     void calculateSelectionRatsnest( const VECTOR2I& aDelta );
diff --git a/pcbnew/tools/pcb_selection_tool.cpp b/pcbnew/tools/pcb_selection_tool.cpp
index 9f115ee2e5..2adbe76861 100644
--- a/pcbnew/tools/pcb_selection_tool.cpp
+++ b/pcbnew/tools/pcb_selection_tool.cpp
@@ -55,6 +55,8 @@ using namespace std::placeholders;
 #include <connectivity/connectivity_data.h>
 #include <footprint_viewer_frame.h>
 #include <id.h>
+#include <wx/event.h>
+#include <wx/timer.h>
 #include <wx/log.h>
 #include "tool_event_utils.h"
 #include "pcb_selection_tool.h"
@@ -102,12 +104,6 @@ public:
 PCB_SELECTION_TOOL::PCB_SELECTION_TOOL() :
         PCB_TOOL_BASE( "pcbnew.InteractiveSelection" ),
         m_frame( nullptr ),
-        m_additive( false ),
-        m_subtractive( false ),
-        m_exclusive_or( false ),
-        m_multiple( false ),
-        m_skip_heuristics( false ),
-        m_highlight_modifier( false ),
         m_nonModifiedCursor( KICURSOR::ARROW ),
         m_enteredGroup( nullptr ),
         m_priv( std::make_unique<PRIV>() )
@@ -130,6 +126,8 @@ PCB_SELECTION_TOOL::~PCB_SELECTION_TOOL()
 {
     getView()->Remove( &m_selection );
     getView()->Remove( &m_enteredGroupOverlay );
+
+    Disconnect( wxEVT_TIMER, wxTimerEventHandler( PCB_SELECTION_TOOL::onDisambiguationExpire ), nullptr, this );
 }
 
 
@@ -176,6 +174,9 @@ bool PCB_SELECTION_TOOL::Init()
     if( frame )
         frame->AddStandardSubMenus( m_menu );
 
+    m_disambiguateTimer.SetOwner( this );
+    Connect( wxEVT_TIMER, wxTimerEventHandler( PCB_SELECTION_TOOL::onDisambiguationExpire ), nullptr, this );
+
     return true;
 }
 
@@ -212,55 +213,9 @@ void PCB_SELECTION_TOOL::Reset( RESET_REASON aReason )
 }
 
 
-void PCB_SELECTION_TOOL::setModifiersState( bool aShiftState, bool aCtrlState, bool aAltState )
+void PCB_SELECTION_TOOL::onDisambiguationExpire( wxTimerEvent& aEvent )
 {
-    // Set the configuration of m_additive, m_subtractive, m_exclusive_or
-    // from the state of modifier keys SHIFT, CTRL, ALT and the OS
-
-    // on left click, a selection is made, depending on modifiers ALT, SHIFT, CTRL:
-    // Due to the fact ALT key modifier cannot be used freely on Winows and Linux,
-    // actions are different on OSX and others OS
-    // Especially, ALT key cannot be used to force showing the full selection choice
-    // context menu (the menu is immediately closed on Windows )
-    //
-    // No modifier = select items and deselect previous selection
-    // ALT (on OSX) = skip heuristic and show full selection choice
-    // ALT (on others) = exclusive OR of selected items (inverse selection)
-    //
-    // CTRL (on OSX) = exclusive OR of selected items (inverse selection)
-    // CTRL (on others) = skip heuristic and show full selection choice
-    //
-    // SHIFT = add selected items to the current selection
-    //
-    // CTRL+SHIFT (on OSX) = remove selected items to the current selection
-    // CTRL+SHIFT (on others) = highlight net
-    //
-    // CTRL+ALT (on OSX) = highlight net
-    // CTRL+ALT (on others) = do nothing (same as no modifier)
-    //
-    // SHIFT+ALT (on OSX) =  do nothing (same as no modifier)
-    // SHIFT+ALT (on others) = remove selected items to the current selection
-
-#ifdef __WXOSX_MAC__
-    m_subtractive        = aCtrlState && aShiftState && !aAltState;
-    m_additive           = aShiftState && !aCtrlState && !aAltState;
-    m_exclusive_or       = aCtrlState && !aShiftState && !aAltState;
-    m_skip_heuristics    = aAltState && !aShiftState && !aCtrlState;
-    m_highlight_modifier = aCtrlState && aAltState && !aShiftState;
-
-#else
-    m_subtractive  = aShiftState && !aCtrlState && aAltState;
-    m_additive     = aShiftState && !aCtrlState && !aAltState;
-    m_exclusive_or = !aShiftState && !aCtrlState && aAltState;
-
-    // Is the user requesting that the selection list include all possible
-    // items without removing less likely selection candidates
-    // Cannot use the Alt key on windows or the disambiguation context menu is immediately
-    // dismissed rendering it useless.
-    m_skip_heuristics = aCtrlState && !aShiftState && !aAltState;
-
-    m_highlight_modifier = aCtrlState && aShiftState && !aAltState;
-#endif
+    m_toolMgr->ProcessEvent( EVENTS::DisambiguatePoint );
 }
 
 
@@ -307,19 +262,34 @@ int PCB_SELECTION_TOOL::Main( const TOOL_EVENT& aEvent )
         {
             evt->SetPassEvent();
         }
+        else if( evt->IsMouseDown( BUT_LEFT ) )
+        {
+            // Avoid triggering when running under other tools
+            if( m_toolMgr->GetCurrentTool() == this )
+                m_disambiguateTimer.StartOnce( 500 );
+        }
         else if( evt->IsClick( BUT_LEFT ) )
         {
-            // Single click? Select single object
-            if( m_highlight_modifier && brd_editor )
-                m_toolMgr->RunAction( PCB_ACTIONS::highlightNet, true );
-            else
+            // If there is no disambiguation, this routine is still running and will
+            // register a `click` event when released
+            if( m_disambiguateTimer.IsRunning() )
             {
-                m_frame->FocusOnItem( nullptr );
-                selectPoint( evt->Position() );
+                m_disambiguateTimer.Stop();
+
+                // Single click? Select single object
+                if( m_highlight_modifier && brd_editor )
+                    m_toolMgr->RunAction( PCB_ACTIONS::highlightNet, true );
+                else
+                {
+                    m_frame->FocusOnItem( nullptr );
+                    selectPoint( evt->Position() );
+                }
             }
         }
         else if( evt->IsClick( BUT_RIGHT ) )
         {
+            m_disambiguateTimer.Stop();
+
             // Right click? if there is any object - show the context menu
             bool selectionCancelled = false;
 
@@ -359,6 +329,8 @@ int PCB_SELECTION_TOOL::Main( const TOOL_EVENT& aEvent )
         }
         else if( evt->IsDrag( BUT_LEFT ) )
         {
+            m_disambiguateTimer.Stop();
+
             // Is another tool already moving a new object?  Don't allow a drag start
             if( !m_selection.Empty() && m_selection[0]->HasFlag( IS_NEW | IS_MOVING ) )
             {
@@ -439,6 +411,7 @@ int PCB_SELECTION_TOOL::Main( const TOOL_EVENT& aEvent )
         }
         else if( evt->IsCancel() )
         {
+            m_disambiguateTimer.Stop();
             m_frame->FocusOnItem( nullptr );
 
             if( m_enteredGroup )
@@ -472,6 +445,7 @@ int PCB_SELECTION_TOOL::Main( const TOOL_EVENT& aEvent )
 
     // Shutting down; clear the selection
     m_selection.Clear();
+    m_disambiguateTimer.Stop();
 
     return 0;
 }
@@ -822,7 +796,7 @@ bool PCB_SELECTION_TOOL::selectMultiple()
 
         if( evt->IsDrag( BUT_LEFT ) )
         {
-            if( !m_additive && !m_subtractive && !m_exclusive_or )
+            if( !m_drag_additive && !m_drag_subtractive )
             {
                 if( m_selection.GetSize() > 0 )
                 {
@@ -834,9 +808,9 @@ bool PCB_SELECTION_TOOL::selectMultiple()
             // Start drawing a selection box
             area.SetOrigin( evt->DragOrigin() );
             area.SetEnd( evt->Position() );
-            area.SetAdditive( m_additive );
-            area.SetSubtractive( m_subtractive );
-            area.SetExclusiveOr( m_exclusive_or );
+            area.SetAdditive( m_drag_additive );
+            area.SetSubtractive( m_drag_subtractive );
+            area.SetExclusiveOr( false );
 
             view->SetVisible( &area, true );
             view->Update( &area );
@@ -919,6 +893,19 @@ bool PCB_SELECTION_TOOL::selectMultiple()
 }
 
 
+int PCB_SELECTION_TOOL::disambiguateCursor( const TOOL_EVENT& aEvent )
+{
+    VECTOR2I pos = m_toolMgr->GetMousePosition();
+
+    m_skip_heuristics = true;
+    selectPoint( pos );
+    m_skip_heuristics = false;
+
+    return 0;
+}
+
+
+
 int PCB_SELECTION_TOOL::CursorSelection( const TOOL_EVENT& aEvent )
 {
     CLIENT_SELECTION_FILTER aClientFilter = aEvent.Parameter<CLIENT_SELECTION_FILTER>();
@@ -2587,7 +2574,7 @@ void PCB_SELECTION_TOOL::FilterCollectorForHierarchy( GENERAL_COLLECTOR& aCollec
         }
 
         // Footprints are a bit easier as they can't be nested.
-        if( parent && parent->GetFlags() & TEMP_SELECTED )
+        if( parent && ( parent->GetFlags() & TEMP_SELECTED ) )
         {
             // Remove children of selected items
             aCollector.Remove( item );
@@ -2654,4 +2641,6 @@ void PCB_SELECTION_TOOL::setTransitions()
     Go( &PCB_SELECTION_TOOL::updateSelection,     EVENTS::SelectedItemsMoved );
 
     Go( &PCB_SELECTION_TOOL::SelectAll,           ACTIONS::selectAll.MakeEvent() );
+
+    Go( &PCB_SELECTION_TOOL::disambiguateCursor,  EVENTS::DisambiguatePoint );
 }
diff --git a/pcbnew/tools/pcb_selection_tool.h b/pcbnew/tools/pcb_selection_tool.h
index b131dd35a4..514194929f 100644
--- a/pcbnew/tools/pcb_selection_tool.h
+++ b/pcbnew/tools/pcb_selection_tool.h
@@ -33,6 +33,7 @@
 #include <math/vector2d.h>
 #include <project/board_project_settings.h>
 #include <tool/action_menu.h>
+#include <tool/selection_tool.h>
 #include <tool/tool_menu.h>
 #include <tools/pcb_selection_conditions.h>
 #include <tools/pcb_tool_base.h>
@@ -60,7 +61,7 @@ typedef void (*CLIENT_SELECTION_FILTER)( const VECTOR2I&, GENERAL_COLLECTOR&, PC
  * - takes into account high-contrast & layer visibility settings
  * - invokes InteractiveEdit tool when user starts to drag selected items
  */
-class PCB_SELECTION_TOOL : public PCB_TOOL_BASE
+class PCB_SELECTION_TOOL : public SELECTION_TOOL, public PCB_TOOL_BASE
 {
 public:
     PCB_SELECTION_TOOL();
@@ -206,12 +207,6 @@ public:
     void FilterCollectedItems( GENERAL_COLLECTOR& aCollector );
 
 private:
-    /**
-     * Set the configuration of m_additive, m_subtractive, m_exclusive_or,
-     * m_skip_heuristics and m_highlight_modifier
-     * from the state of modifier keys SHIFT, CTRL, ALT and depending on the OS
-     */
-    void setModifiersState( bool aShiftState, bool aCtrlState, bool aAltState );
 
     /**
      * Select an item pointed by the parameter \a aWhere.
@@ -259,6 +254,18 @@ private:
      */
     bool doSelectionMenu( GENERAL_COLLECTOR* aItems );
 
+    /**
+     * Start the process to show our disambiguation menu once the user has kept
+     * the mouse down for the minimum time
+     * @param aEvent
+     */
+    void onDisambiguationExpire( wxTimerEvent& aEvent );
+
+    /**
+     * Handle disambiguation actions including displaying the menu.
+     */
+    int disambiguateCursor( const TOOL_EVENT& aEvent );
+
     /**
      * Expand the current track selection to the next boundary (junctions, pads, or all)
      */
@@ -374,14 +381,6 @@ private:
 
     SELECTION_FILTER_OPTIONS m_filter;
 
-    bool                     m_additive;             // Add to selection (instead of replacing)
-    bool                     m_subtractive;          // Remove from selection
-    bool                     m_exclusive_or;         // Items' selection state should be toggled
-    bool                     m_multiple;             // Multiple selection mode is active
-    bool                     m_skip_heuristics;      // Heuristics are not allowed when choosing
-                                                     // item under cursor
-    bool                     m_highlight_modifier;   // select highlight net on left click
-
     KICURSOR                 m_nonModifiedCursor;    // Cursor in the absence of shift/ctrl/alt
 
     PCB_GROUP*               m_enteredGroup;         // If non-null, selections are limited to