diff --git a/common/eda_base_frame.cpp b/common/eda_base_frame.cpp
index 75eb3e9dc0..293dc5553a 100644
--- a/common/eda_base_frame.cpp
+++ b/common/eda_base_frame.cpp
@@ -291,7 +291,7 @@ void EDA_BASE_FRAME::ReCreateMenuBar()
 void EDA_BASE_FRAME::AddStandardHelpMenu( wxMenuBar* aMenuBar )
 {
     COMMON_CONTROL* commonControl = m_toolManager->GetTool<COMMON_CONTROL>();
-    ACTION_MENU*    helpMenu = new ACTION_MENU();
+    ACTION_MENU*    helpMenu = new ACTION_MENU( false );
 
     helpMenu->SetTool( commonControl );
 
diff --git a/common/eda_draw_frame.cpp b/common/eda_draw_frame.cpp
index ff9a7ec72e..63f1e6c699 100644
--- a/common/eda_draw_frame.cpp
+++ b/common/eda_draw_frame.cpp
@@ -39,6 +39,7 @@
 #include <wx/snglinst.h>
 #include <view/view.h>
 #include <tool/tool_manager.h>
+#include <tool/action_manager.h>
 #include <tool/tool_dispatcher.h>
 #include <tool/actions.h>
 #include <wx/clipbrd.h>
@@ -359,7 +360,6 @@ void EDA_DRAW_FRAME::AddStandardSubMenus( TOOL_MENU& aToolMenu )
 
 void EDA_DRAW_FRAME::DisplayToolMsg( const wxString& msg )
 {
-    m_toolMsg = msg;
     SetStatusText( msg, 5 );
 }
 
@@ -418,6 +418,55 @@ void EDA_DRAW_FRAME::OnSize( wxSizeEvent& SizeEv )
 }
 
 
+void EDA_DRAW_FRAME::SetTool( const std::string& actionName )
+{
+    if( !m_toolStack.empty() )
+        m_toolStack.pop_back();
+
+    PushTool( actionName );
+}
+
+
+void EDA_DRAW_FRAME::PushTool( const std::string& actionName )
+{
+    m_toolStack.push_back( actionName );
+
+    TOOL_ACTION* action = m_toolManager->GetActionManager()->FindAction( actionName );
+
+    if( action )
+        DisplayToolMsg( action->GetLabel() );
+    else
+        DisplayToolMsg( actionName );
+}
+
+
+void EDA_DRAW_FRAME::PopTool()
+{
+    m_toolStack.pop_back();
+
+    if( !m_toolStack.empty() )
+    {
+        TOOL_ACTION* action = m_toolManager->GetActionManager()->FindAction( m_toolStack.back() );
+
+        if( action )
+        {
+            TOOL_EVENT evt = action->MakeEvent();
+            evt.SetHasPosition( false );
+            GetToolManager()->PostEvent( evt );
+        }
+    }
+    else
+        DisplayToolMsg( ACTIONS::selectionTool.GetName() );
+}
+
+
+void EDA_DRAW_FRAME::ClearToolStack()
+{
+    m_toolStack.clear();
+    DisplayToolMsg( ACTIONS::selectionTool.GetName() );
+}
+
+
 void EDA_DRAW_FRAME::SetToolID( int aId, int aCursor, const wxString& aToolMsg )
 {
     // Keep default cursor in toolbars
diff --git a/common/tool/action_menu.cpp b/common/tool/action_menu.cpp
index 36e94cb7cb..981fd83e77 100644
--- a/common/tool/action_menu.cpp
+++ b/common/tool/action_menu.cpp
@@ -38,12 +38,13 @@
 using namespace std::placeholders;
 
 
-ACTION_MENU::ACTION_MENU() :
+ACTION_MENU::ACTION_MENU( bool isContextMenu ) :
     m_dirty( true ),
     m_titleDisplayed( false ),
+    m_isContextMenu( isContextMenu ),
+    m_icon( nullptr ),
     m_selected( -1 ),
-    m_tool( nullptr ),
-    m_icon( nullptr )
+    m_tool( nullptr )
 {
     setupEvents();
 }
@@ -70,7 +71,7 @@ void ACTION_MENU::SetIcon( const BITMAP_OPAQUE* aIcon )
 
 void ACTION_MENU::setupEvents()
 {
-// See wxWidgets hack in EDA_DRAW_FRAME::OnMenuOpen().
+// See wxWidgets hack in EDA_BASE_FRAME::OnMenuOpen().
 //    Connect( wxEVT_MENU_OPEN, wxMenuEventHandler( ACTION_MENU::OnMenuEvent ), NULL, this );
 //    Connect( wxEVT_MENU_HIGHLIGHT, wxMenuEventHandler( ACTION_MENU::OnMenuEvent ), NULL, this );
 
@@ -276,7 +277,7 @@ ACTION_MENU* ACTION_MENU::Clone() const
 
 ACTION_MENU* ACTION_MENU::create() const
 {
-    ACTION_MENU* menu = new ACTION_MENU();
+    ACTION_MENU* menu = new ACTION_MENU( false );
 
     wxASSERT_MSG( typeid( *this ) == typeid( *menu ),
             wxString::Format( "You need to override create() method for class %s", typeid(*this).name() ) );
@@ -296,12 +297,11 @@ void ACTION_MENU::updateHotKeys()
 {
     TOOL_MANAGER* toolMgr = getToolManager();
 
-    for( std::map<int, const TOOL_ACTION*>::const_iterator it = m_toolActions.begin();
-            it != m_toolActions.end(); ++it )
+    for( auto& ii : m_toolActions )
     {
-        int id = it->first;
-        const TOOL_ACTION& action = *it->second;
-        int key = toolMgr->GetHotKey( action ) & ~MD_MODIFIER_MASK;
+        int                id = ii.first;
+        const TOOL_ACTION& action = *ii.second;
+        int                key = toolMgr->GetHotKey( action ) & ~MD_MODIFIER_MASK;
 
         if( key )
         {
@@ -328,27 +328,33 @@ void ACTION_MENU::updateHotKeys()
 
 void ACTION_MENU::OnMenuEvent( wxMenuEvent& aEvent )
 {
+    // wxWidgets doesn't tell us when a menu command was generated from a hotkey or from
+    // a menu selection.  It's important to us because a hotkey can be an immediate action
+    // while the menu selection can not (as it has no associated position).
+    //
+    // We get around this by storing the last highlighted menuId.  If it matches the command
+    // id then we know this is a menu selection.  (You might think we could use the menuOpen
+    // menuClose events, but these are actually generated for hotkeys as well.)
+    static int highlightId = 0;
+
     OPT_TOOL_EVENT evt;
     wxString menuText;
 
     wxEventType type = aEvent.GetEventType();
 
-    if( type == wxEVT_MENU_OPEN && m_dirty )
+    if( type == wxEVT_MENU_OPEN )
     {
-        if( m_tool )
+        if( m_dirty && m_tool )
             getToolManager()->RunAction( ACTIONS::updateMenu, true, this );
 
+        highlightId = 0;
         aEvent.Skip();
-        return;
     }
-
-    // When the currently chosen item in the menu is changed, an update event is issued.
-    // For example, the selection tool can use this to dynamically highlight the current item
-    // from selection clarification popup.
     else if( type == wxEVT_MENU_HIGHLIGHT )
-        evt = TOOL_EVENT( TC_COMMAND, TA_CONTEXT_MENU_UPDATE, aEvent.GetId() );
-
-    // One of menu entries was selected..
+    {
+        highlightId = aEvent.GetId();
+        evt = TOOL_EVENT( TC_COMMAND, TA_CHOICE_MENU_UPDATE, aEvent.GetId() );
+    }
     else if( type == wxEVT_COMMAND_MENU_SELECTED )
     {
         // Store the selected position, so it can be checked by the tools
@@ -410,7 +416,7 @@ void ACTION_MENU::OnMenuEvent( wxMenuEvent& aEvent )
               )
             {
                 menuText = GetLabelText( aEvent.GetId() );
-                evt = TOOL_EVENT( TC_COMMAND, TA_CONTEXT_MENU_CHOICE, m_selected, AS_GLOBAL,
+                evt = TOOL_EVENT( TC_COMMAND, TA_CHOICE_MENU_CHOICE, m_selected, AS_GLOBAL,
                                   &menuText );
             }
         }
@@ -420,6 +426,9 @@ void ACTION_MENU::OnMenuEvent( wxMenuEvent& aEvent )
     // clients that don't supply a tool will have to check GetSelected() themselves
     if( evt && m_tool )
     {
+        if( highlightId == aEvent.GetId() && !m_isContextMenu )
+            evt->SetHasPosition( false );
+
         //aEvent.StopPropagation();
         if( m_tool->GetManager() )
             m_tool->GetManager()->ProcessEvent( *evt );
diff --git a/common/tool/action_toolbar.cpp b/common/tool/action_toolbar.cpp
index 7fb1c5afc5..5697b35430 100644
--- a/common/tool/action_toolbar.cpp
+++ b/common/tool/action_toolbar.cpp
@@ -109,7 +109,7 @@ void ACTION_TOOLBAR::onToolEvent( wxAuiToolBarEvent& aEvent )
     // forward the action/update event to the TOOL_MANAGER
     if( evt && m_toolManager )
     {
-        //aEvent.StopPropagation();
+        evt->SetHasPosition( false );
         m_toolManager->ProcessEvent( *evt );
     }
     else
diff --git a/common/tool/conditional_menu.cpp b/common/tool/conditional_menu.cpp
index f2d1f390b0..f0b0a54f31 100644
--- a/common/tool/conditional_menu.cpp
+++ b/common/tool/conditional_menu.cpp
@@ -29,7 +29,7 @@
 
 
 CONDITIONAL_MENU::CONDITIONAL_MENU( bool isContextMenu, TOOL_INTERACTIVE* aTool ) :
-        m_isContextMenu( isContextMenu )
+        ACTION_MENU( isContextMenu )
 {
     m_tool = aTool;
 }
@@ -100,9 +100,11 @@ void CONDITIONAL_MENU::AddSeparator( const SELECTION_CONDITION& aCondition, int
 
 SELECTION g_resolveDummySelection;
 
+
 void CONDITIONAL_MENU::Resolve()
 {
     Evaluate( g_resolveDummySelection );
+    UpdateAll();
 
     runOnSubmenus( [] ( ACTION_MENU* aMenu ) {
         CONDITIONAL_MENU* conditionalMenu = dynamic_cast<CONDITIONAL_MENU*>( aMenu );
diff --git a/common/tool/grid_menu.cpp b/common/tool/grid_menu.cpp
index 680450d820..daabb0f5bc 100644
--- a/common/tool/grid_menu.cpp
+++ b/common/tool/grid_menu.cpp
@@ -33,7 +33,9 @@
 #include <functional>
 using namespace std::placeholders;
 
-GRID_MENU::GRID_MENU( EDA_DRAW_FRAME* aParent ) : m_parent( aParent )
+GRID_MENU::GRID_MENU( EDA_DRAW_FRAME* aParent ) :
+        ACTION_MENU( true ),
+        m_parent( aParent )
 {
     BASE_SCREEN* screen = m_parent->GetScreen();
 
diff --git a/common/tool/tool_event.cpp b/common/tool/tool_event.cpp
index 0ff32d6c9c..6217d2b4ac 100644
--- a/common/tool/tool_event.cpp
+++ b/common/tool/tool_event.cpp
@@ -73,27 +73,27 @@ const std::string TOOL_EVENT::Format() const
 
     const FlagString actions[] =
     {
-        { TA_MOUSE_CLICK,           "click"               },
-        { TA_MOUSE_DBLCLICK,        "double click"        },
-        { TA_MOUSE_UP,              "button-up"           },
-        { TA_MOUSE_DOWN,            "button-down"         },
-        { TA_MOUSE_DRAG,            "drag"                },
-        { TA_MOUSE_MOTION,          "motion"              },
-        { TA_MOUSE_WHEEL,           "wheel"               },
-        { TA_KEY_PRESSED,           "key-pressed"         },
-        { TA_VIEW_REFRESH,          "view-refresh"        },
-        { TA_VIEW_ZOOM,             "view-zoom"           },
-        { TA_VIEW_PAN,              "view-pan"            },
-        { TA_VIEW_DIRTY,            "view-dirty"          },
-        { TA_CHANGE_LAYER,          "change-layer"        },
-        { TA_CANCEL_TOOL,           "cancel-tool"         },
-        { TA_CONTEXT_MENU_UPDATE,   "context-menu-update" },
-        { TA_CONTEXT_MENU_CHOICE,   "context-menu-choice" },
-        { TA_UNDO_REDO_PRE,         "undo-redo-pre"       },
-        { TA_UNDO_REDO_POST,        "undo-redo-post"      },
-        { TA_ACTION,                "action"              },
-        { TA_ACTIVATE,              "activate"            },
-        { 0,                        ""                    }
+        { TA_MOUSE_CLICK,        "click"               },
+        { TA_MOUSE_DBLCLICK,     "double click"        },
+        { TA_MOUSE_UP,           "button-up"           },
+        { TA_MOUSE_DOWN,         "button-down"         },
+        { TA_MOUSE_DRAG,         "drag"                },
+        { TA_MOUSE_MOTION,       "motion"              },
+        { TA_MOUSE_WHEEL,        "wheel"               },
+        { TA_KEY_PRESSED,        "key-pressed"         },
+        { TA_VIEW_REFRESH,       "view-refresh"        },
+        { TA_VIEW_ZOOM,          "view-zoom"           },
+        { TA_VIEW_PAN,           "view-pan"            },
+        { TA_VIEW_DIRTY,         "view-dirty"          },
+        { TA_CHANGE_LAYER,       "change-layer"        },
+        { TA_CANCEL_TOOL,        "cancel-tool"         },
+        { TA_CHOICE_MENU_UPDATE, "choice-menu-update"  },
+        { TA_CHOICE_MENU_CHOICE, "choice-menu-choice"  },
+        { TA_UNDO_REDO_PRE,      "undo-redo-pre"       },
+        { TA_UNDO_REDO_POST,     "undo-redo-post"      },
+        { TA_ACTION,             "action"              },
+        { TA_ACTIVATE,           "activate"            },
+        { 0,                     ""                    }
     };
 
     const FlagString buttons[] =
diff --git a/common/tool/tool_manager.cpp b/common/tool/tool_manager.cpp
index deb20cc65e..bad4d5e005 100644
--- a/common/tool/tool_manager.cpp
+++ b/common/tool/tool_manager.cpp
@@ -522,7 +522,7 @@ void TOOL_MANAGER::dispatchInternal( const TOOL_EVENT& aEvent )
         TOOL_STATE* st = m_toolIdIndex[*it];
 
         // forward context menu events to the tool that created the menu
-        if( aEvent.IsMenu() )
+        if( aEvent.IsChoiceMenu() )
         {
             if( *it != m_menuOwner )
                 continue;
@@ -699,7 +699,7 @@ void TOOL_MANAGER::DispatchContextMenu( const TOOL_EVENT& aEvent )
         // Otherwise notify the tool of a cancelled menu
         else
         {
-            TOOL_EVENT evt( TC_COMMAND, TA_CONTEXT_MENU_CHOICE, -1 );
+            TOOL_EVENT evt( TC_COMMAND, TA_CHOICE_MENU_CHOICE, -1 );
             evt.SetParameter( m );
             dispatchInternal( evt );
         }
@@ -708,7 +708,7 @@ void TOOL_MANAGER::DispatchContextMenu( const TOOL_EVENT& aEvent )
         m_warpMouseAfterContextMenu = true;
 
         // Notify the tools that menu has been closed
-        TOOL_EVENT evt( TC_COMMAND, TA_CONTEXT_MENU_CLOSED );
+        TOOL_EVENT evt( TC_COMMAND, TA_CHOICE_MENU_CLOSED );
         evt.SetParameter( m );
         dispatchInternal( evt );
 
diff --git a/common/tool/zoom_menu.cpp b/common/tool/zoom_menu.cpp
index 61a9b0e40b..0b043991bd 100644
--- a/common/tool/zoom_menu.cpp
+++ b/common/tool/zoom_menu.cpp
@@ -32,7 +32,9 @@
 #include <functional>
 using namespace std::placeholders;
 
-ZOOM_MENU::ZOOM_MENU( EDA_DRAW_FRAME* aParent ) : m_parent( aParent )
+ZOOM_MENU::ZOOM_MENU( EDA_DRAW_FRAME* aParent ) :
+        ACTION_MENU( true ),
+        m_parent( aParent )
 {
     BASE_SCREEN* screen = aParent->GetScreen();
 
diff --git a/cvpcb/tools/cvpcb_selection_tool.cpp b/cvpcb/tools/cvpcb_selection_tool.cpp
index 0cb2fdb1e2..b7905f3e7e 100644
--- a/cvpcb/tools/cvpcb_selection_tool.cpp
+++ b/cvpcb/tools/cvpcb_selection_tool.cpp
@@ -93,7 +93,7 @@ int CVPCB_SELECTION_TOOL::Main( const TOOL_EVENT& aEvent )
             clearSelection();
         }
 
-        else if( evt->Action() == TA_CONTEXT_MENU_CLOSED )
+        else if( evt->Action() == TA_CHOICE_MENU_CLOSED )
         {
             m_menu.CloseContextMenu( evt );
         }
diff --git a/eeschema/cross-probing.cpp b/eeschema/cross-probing.cpp
index b1ca462bcc..f502ea8e0a 100644
--- a/eeschema/cross-probing.cpp
+++ b/eeschema/cross-probing.cpp
@@ -76,7 +76,7 @@ void SCH_EDIT_FRAME::ExecuteRemoteCommand( const char* cmdline )
 
     if( strcmp( idcmd, "$NET:" ) == 0 )
     {
-        if( GetToolId() == ID_HIGHLIGHT_TOOL )
+        if( GetCurrentToolName() == EE_ACTIONS::highlightNetCursor.GetName() )
         {
             m_SelectedNetName = FROM_UTF8( text );
 
diff --git a/eeschema/eeschema_id.h b/eeschema/eeschema_id.h
index e76f2f75d2..ec7f21a800 100644
--- a/eeschema/eeschema_id.h
+++ b/eeschema/eeschema_id.h
@@ -58,38 +58,10 @@ enum id_eeschema_frm
 
     /* Schematic editor main menubar IDs. */
     ID_RESCUE_CACHED,
-    ID_EDIT_SYM_LIB_TABLE,
     ID_REMAP_SYMBOLS,
 
     /* Schematic editor horizontal toolbar IDs */
     ID_BACKANNO_ITEMS,
-
-    /* Schematic editor vertical toolbar IDs */
-    ID_HIGHLIGHT_TOOL,
-    ID_PLACE_SYMBOL_TOOL,
-    ID_PLACE_POWER_TOOL,
-    ID_BUS_TOOL,
-    ID_WIRE_TOOL,
-    ID_BUSTOBUS_ENTRY_TOOL,
-    ID_WIRETOBUS_ENTRY_TOOL,
-    ID_LABEL_TOOL,
-    ID_GLOBALLABEL_TOOL,
-    ID_HIERLABEL_TOOL,
-    ID_IMPORT_SHEETPIN_TOOL,
-    ID_SHEETPIN_TOOL,
-    ID_NOCONNECT_TOOL,
-    ID_JUNCTION_TOOL,
-    ID_SHEET_TOOL,
-    ID_SCHEMATIC_TEXT_TOOL,
-    ID_SCHEMATIC_LINE_TOOL,
-    ID_PLACE_IMAGE_TOOL,
-    ID_DELETE_TOOL,
-
-    ID_SCH_MOVE,
-    ID_SCH_DRAG,
-    ID_SCH_UNFOLD_BUS,
-
-    ID_HOTKEY_HIGHLIGHT,
     ID_ADD_PART_TO_SCHEMATIC,
 
     /* Library editor horizontal toolbar IDs. */
@@ -97,16 +69,8 @@ enum id_eeschema_frm
     ID_LIBEDIT_SELECT_PART_NUMBER,
 
     /* Library editor vertical toolbar IDs. */
-    ID_SYMBOL_PIN_TOOL,
-    ID_SYMBOL_LINE_TOOL,
-    ID_SYMBOL_ARC_TOOL,
-    ID_SYMBOL_CIRCLE_TOOL,
-    ID_SYMBOL_RECT_TOOL,
-    ID_SYMBOL_TEXT_TOOL,
-    ID_SYMBOL_ANCHOR_TOOL,
     ID_LIBEDIT_IMPORT_BODY_BUTT,
     ID_LIBEDIT_EXPORT_BODY_BUTT,
-    ID_LIBEDIT_DELETE_ITEM_BUTT,
 
     /* Library editor menubar IDs */
     ID_LIBEDIT_GEN_PNG_FILE,
diff --git a/eeschema/libedit/lib_edit_frame.cpp b/eeschema/libedit/lib_edit_frame.cpp
index 68931e9235..83b4352bbf 100644
--- a/eeschema/libedit/lib_edit_frame.cpp
+++ b/eeschema/libedit/lib_edit_frame.cpp
@@ -448,18 +448,16 @@ void LIB_EDIT_FRAME::SetCurPart( LIB_PART* aPart )
 void LIB_EDIT_FRAME::OnImportBody( wxCommandEvent& aEvent )
 {
     m_toolManager->DeactivateTool();
-    SetToolID( ID_LIBEDIT_IMPORT_BODY_BUTT, GetCanvas()->GetDefaultCursor(), _( "Import" ) );
     LoadOneSymbol();
-    SetNoToolSelected();
+    m_drawToolBar->ToggleTool( ID_LIBEDIT_IMPORT_BODY_BUTT, false );
 }
 
 
 void LIB_EDIT_FRAME::OnExportBody( wxCommandEvent& aEvent )
 {
     m_toolManager->DeactivateTool();
-    SetToolID( ID_LIBEDIT_EXPORT_BODY_BUTT, GetCanvas()->GetDefaultCursor(), _( "Export" ) );
     SaveOneSymbol();
-    SetNoToolSelected();
+    m_drawToolBar->ToggleTool( ID_LIBEDIT_EXPORT_BODY_BUTT, false );
 }
 
 
diff --git a/eeschema/libedit/menubar_libedit.cpp b/eeschema/libedit/menubar_libedit.cpp
index f4fc9b2a71..33ce380b62 100644
--- a/eeschema/libedit/menubar_libedit.cpp
+++ b/eeschema/libedit/menubar_libedit.cpp
@@ -72,7 +72,7 @@ void LIB_EDIT_FRAME::ReCreateMenuBar()
     fileMenu->AddItem( EE_ACTIONS::importSymbol,     EE_CONDITIONS::ShowAlways );
 
     // Export submenu
-    ACTION_MENU* submenuExport = new ACTION_MENU();
+    ACTION_MENU* submenuExport = new ACTION_MENU( false );
     submenuExport->SetTool( selTool );
     submenuExport->SetTitle( _( "Export" ) );
     submenuExport->SetIcon( export_xpm );
diff --git a/eeschema/libedit/toolbars_libedit.cpp b/eeschema/libedit/toolbars_libedit.cpp
index 78ccd532e7..312d9b696a 100644
--- a/eeschema/libedit/toolbars_libedit.cpp
+++ b/eeschema/libedit/toolbars_libedit.cpp
@@ -187,13 +187,15 @@ void LIB_EDIT_FRAME::SyncToolbars()
     m_optionsToolBar->Toggle( EE_ACTIONS::showComponentTree,   IsSearchTreeShown() );
     m_optionsToolBar->Refresh();
 
-    m_drawToolBar->Toggle( EE_ACTIONS::selectionTool,       GetToolId() == ID_NO_TOOL_SELECTED );
-    m_drawToolBar->Toggle( EE_ACTIONS::placeSymbolPin,      GetToolId() == ID_SYMBOL_PIN_TOOL );
-    m_drawToolBar->Toggle( EE_ACTIONS::placeSymbolText,     GetToolId() == ID_SYMBOL_TEXT_TOOL );
-    m_drawToolBar->Toggle( EE_ACTIONS::drawSymbolRectangle, GetToolId() == ID_SYMBOL_RECT_TOOL );
-    m_drawToolBar->Toggle( EE_ACTIONS::drawSymbolCircle,    GetToolId() == ID_SYMBOL_CIRCLE_TOOL );
-    m_drawToolBar->Toggle( EE_ACTIONS::drawSymbolArc,       GetToolId() == ID_SYMBOL_ARC_TOOL );
-    m_drawToolBar->Toggle( EE_ACTIONS::drawSymbolLines,     GetToolId() == ID_SYMBOL_LINE_TOOL );
-    m_drawToolBar->Toggle( EE_ACTIONS::placeSymbolAnchor,   GetToolId() == ID_SYMBOL_ANCHOR_TOOL );
+#define TOGGLE_TOOL( tool ) m_drawToolBar->Toggle( tool, GetCurrentToolName() == tool.GetName() )
+
+    TOGGLE_TOOL( EE_ACTIONS::selectionTool );
+    TOGGLE_TOOL( EE_ACTIONS::placeSymbolPin );
+    TOGGLE_TOOL( EE_ACTIONS::placeSymbolText );
+    TOGGLE_TOOL( EE_ACTIONS::drawSymbolRectangle );
+    TOGGLE_TOOL( EE_ACTIONS::drawSymbolCircle );
+    TOGGLE_TOOL( EE_ACTIONS::drawSymbolArc );
+    TOGGLE_TOOL( EE_ACTIONS::drawSymbolLines );
+    TOGGLE_TOOL( EE_ACTIONS::deleteItemCursor );
     m_drawToolBar->Refresh();
 }
diff --git a/eeschema/menubar.cpp b/eeschema/menubar.cpp
index 71da454ea4..41d2d7217b 100644
--- a/eeschema/menubar.cpp
+++ b/eeschema/menubar.cpp
@@ -61,7 +61,7 @@ void SCH_EDIT_FRAME::ReCreateMenuBar()
         if( openRecentMenu )
             Kiface().GetFileHistory().RemoveMenu( openRecentMenu );
 
-        openRecentMenu = new ACTION_MENU();
+        openRecentMenu = new ACTION_MENU( false );
         openRecentMenu->SetTool( selTool );
         openRecentMenu->SetTitle( _( "Open Recent" ) );
         openRecentMenu->SetIcon( recent_xpm );
@@ -92,7 +92,7 @@ void SCH_EDIT_FRAME::ReCreateMenuBar()
     fileMenu->AddSeparator();
 
     // Import submenu
-    ACTION_MENU* submenuImport = new ACTION_MENU();
+    ACTION_MENU* submenuImport = new ACTION_MENU( false );
     submenuImport->SetTool( selTool );
     submenuImport->SetTitle( _( "Import" ) );
     submenuImport->SetIcon( import_xpm );
@@ -105,7 +105,7 @@ void SCH_EDIT_FRAME::ReCreateMenuBar()
 
 
     // Export submenu
-    ACTION_MENU* submenuExport = new ACTION_MENU();
+    ACTION_MENU* submenuExport = new ACTION_MENU( false );
     submenuExport->SetTool( selTool );
     submenuExport->SetTitle( _( "Export" ) );
     submenuExport->SetIcon( export_xpm );
@@ -234,7 +234,7 @@ void SCH_EDIT_FRAME::ReCreateMenuBar()
     placeMenu->AddItem( EE_ACTIONS::placeGlobalLabel,       EE_CONDITIONS::ShowAlways );
 
     placeMenu->AddSeparator();
-    placeMenu->AddItem( EE_ACTIONS::placeHierarchicalLabel, EE_CONDITIONS::ShowAlways );
+    placeMenu->AddItem( EE_ACTIONS::placeHierLabel, EE_CONDITIONS::ShowAlways );
     placeMenu->AddItem( EE_ACTIONS::drawSheet,              EE_CONDITIONS::ShowAlways );
     placeMenu->AddItem( EE_ACTIONS::importSheetPin,         EE_CONDITIONS::ShowAlways );
     placeMenu->AddItem( EE_ACTIONS::placeSheetPin,          EE_CONDITIONS::ShowAlways );
diff --git a/eeschema/sch_base_frame.cpp b/eeschema/sch_base_frame.cpp
index f4e95e5e37..fc4bda0153 100644
--- a/eeschema/sch_base_frame.cpp
+++ b/eeschema/sch_base_frame.cpp
@@ -36,6 +36,7 @@
 #include <viewlib_frame.h>
 #include <sch_base_frame.h>
 #include <symbol_lib_table.h>
+#include <tool/action_toolbar.h>
 #include <tool/tool_manager.h>
 #include <tool/tool_dispatcher.h>
 #include <tools/ee_actions.h>
@@ -438,3 +439,14 @@ void SCH_BASE_FRAME::SyncView()
     GetCanvas()->GetGAL()->SetGridSize( VECTOR2D( gs.x, gs.y ));
     GetCanvas()->GetView()->UpdateAllItems( KIGFX::ALL );
 }
+
+
+std::string SCH_BASE_FRAME::GetCurrentToolName()
+{
+    if( m_toolStack.empty() )
+        return EE_ACTIONS::selectionTool.GetName();
+    else
+        return m_toolStack.back();
+}
+
+
diff --git a/eeschema/sch_base_frame.h b/eeschema/sch_base_frame.h
index 550f004f68..fbd2e1fbd7 100644
--- a/eeschema/sch_base_frame.h
+++ b/eeschema/sch_base_frame.h
@@ -302,6 +302,8 @@ public:
 
     void HardRedraw() override;
 
+    std::string GetCurrentToolName();
+
     /**
      * Add an item to the screen (and view)
      * aScreen is the screen the item is located on, if not the current screen
diff --git a/eeschema/toolbars_sch_editor.cpp b/eeschema/toolbars_sch_editor.cpp
index e9ca6be507..edd10ee3f2 100644
--- a/eeschema/toolbars_sch_editor.cpp
+++ b/eeschema/toolbars_sch_editor.cpp
@@ -130,7 +130,7 @@ void SCH_EDIT_FRAME::ReCreateVToolbar()
     m_drawToolBar->Add( EE_ACTIONS::placeJunction,          ACTION_TOOLBAR::TOGGLE );
     m_drawToolBar->Add( EE_ACTIONS::placeLabel,             ACTION_TOOLBAR::TOGGLE );
     m_drawToolBar->Add( EE_ACTIONS::placeGlobalLabel,       ACTION_TOOLBAR::TOGGLE );
-    m_drawToolBar->Add( EE_ACTIONS::placeHierarchicalLabel, ACTION_TOOLBAR::TOGGLE );
+    m_drawToolBar->Add( EE_ACTIONS::placeHierLabel, ACTION_TOOLBAR::TOGGLE );
     m_drawToolBar->Add( EE_ACTIONS::drawSheet,              ACTION_TOOLBAR::TOGGLE );
     m_drawToolBar->Add( EE_ACTIONS::importSheetPin,         ACTION_TOOLBAR::TOGGLE );
     m_drawToolBar->Add( EE_ACTIONS::placeSheetPin,          ACTION_TOOLBAR::TOGGLE );
@@ -168,7 +168,7 @@ void SCH_EDIT_FRAME::ReCreateOptToolbar()
 
 
 void SCH_EDIT_FRAME::SyncToolbars()
-{
+{    
     KIGFX::GAL_DISPLAY_OPTIONS& galOpts = GetGalDisplayOptions();
     SCH_SHEET_LIST              sheetList( g_RootSheet );
 
@@ -186,25 +186,27 @@ void SCH_EDIT_FRAME::SyncToolbars()
     m_optionsToolBar->Toggle( EE_ACTIONS::toggleForceHV,       GetForceHVLines() );
     m_optionsToolBar->Refresh();
 
-    m_drawToolBar->Toggle( EE_ACTIONS::selectionTool,          GetToolId() == ID_NO_TOOL_SELECTED );
-    m_drawToolBar->Toggle( EE_ACTIONS::highlightNetCursor,     GetToolId() == ID_HIGHLIGHT_TOOL );
-    m_drawToolBar->Toggle( EE_ACTIONS::placeSymbol,            GetToolId() == ID_COMPONENT_BUTT );
-    m_drawToolBar->Toggle( EE_ACTIONS::placePower,             GetToolId() == ID_PLACE_POWER_TOOL );
-    m_drawToolBar->Toggle( EE_ACTIONS::drawWire,               GetToolId() == ID_WIRE_TOOL );
-    m_drawToolBar->Toggle( EE_ACTIONS::drawBus,                GetToolId() == ID_BUS_TOOL );
-    m_drawToolBar->Toggle( EE_ACTIONS::placeBusWireEntry,      GetToolId() == ID_WIRETOBUS_ENTRY_TOOL );
-    m_drawToolBar->Toggle( EE_ACTIONS::placeBusBusEntry,       GetToolId() == ID_BUSTOBUS_ENTRY_TOOL );
-    m_drawToolBar->Toggle( EE_ACTIONS::placeNoConnect,         GetToolId() == ID_NOCONNECT_TOOL );
-    m_drawToolBar->Toggle( EE_ACTIONS::placeJunction,          GetToolId() == ID_JUNCTION_TOOL );
-    m_drawToolBar->Toggle( EE_ACTIONS::placeLabel,             GetToolId() == ID_LABEL_TOOL );
-    m_drawToolBar->Toggle( EE_ACTIONS::placeGlobalLabel,       GetToolId() == ID_GLOBALLABEL_TOOL );
-    m_drawToolBar->Toggle( EE_ACTIONS::placeHierarchicalLabel, GetToolId() == ID_HIERLABEL_TOOL );
-    m_drawToolBar->Toggle( EE_ACTIONS::drawSheet,              GetToolId() == ID_SHEET_TOOL );
-    m_drawToolBar->Toggle( EE_ACTIONS::importSheetPin,         GetToolId() == ID_IMPORT_SHEETPIN_TOOL );
-    m_drawToolBar->Toggle( EE_ACTIONS::placeSheetPin,          GetToolId() == ID_SHEETPIN_TOOL );
-    m_drawToolBar->Toggle( EE_ACTIONS::drawLines,              GetToolId() == ID_SCHEMATIC_LINE_TOOL );
-    m_drawToolBar->Toggle( EE_ACTIONS::placeSchematicText,     GetToolId() == ID_SCHEMATIC_TEXT_TOOL );
-    m_drawToolBar->Toggle( EE_ACTIONS::placeImage,             GetToolId() == ID_PLACE_IMAGE_TOOL );
-    m_drawToolBar->Toggle( EE_ACTIONS::deleteItemCursor,       GetToolId() == ID_DELETE_TOOL );
+#define TOGGLE_TOOL( tool ) m_drawToolBar->Toggle( tool, GetCurrentToolName() == tool.GetName() )
+
+    TOGGLE_TOOL( ACTIONS::selectionTool );
+    TOGGLE_TOOL( EE_ACTIONS::highlightNetCursor );
+    TOGGLE_TOOL( EE_ACTIONS::placeSymbol );
+    TOGGLE_TOOL( EE_ACTIONS::placePower );
+    TOGGLE_TOOL( EE_ACTIONS::drawWire );
+    TOGGLE_TOOL( EE_ACTIONS::drawBus );
+    TOGGLE_TOOL( EE_ACTIONS::placeBusWireEntry );
+    TOGGLE_TOOL( EE_ACTIONS::placeBusBusEntry );
+    TOGGLE_TOOL( EE_ACTIONS::placeNoConnect );
+    TOGGLE_TOOL( EE_ACTIONS::placeJunction );
+    TOGGLE_TOOL( EE_ACTIONS::placeLabel );
+    TOGGLE_TOOL( EE_ACTIONS::placeGlobalLabel );
+    TOGGLE_TOOL( EE_ACTIONS::placeHierLabel );
+    TOGGLE_TOOL( EE_ACTIONS::drawSheet );
+    TOGGLE_TOOL( EE_ACTIONS::importSheetPin );
+    TOGGLE_TOOL( EE_ACTIONS::placeSheetPin );
+    TOGGLE_TOOL( EE_ACTIONS::drawLines );
+    TOGGLE_TOOL( EE_ACTIONS::placeSchematicText );
+    TOGGLE_TOOL( EE_ACTIONS::placeImage );
+    TOGGLE_TOOL( EE_ACTIONS::deleteItemCursor );
     m_drawToolBar->Refresh();
 }
diff --git a/eeschema/tools/ee_actions.h b/eeschema/tools/ee_actions.h
index 8079879767..a933652ac9 100644
--- a/eeschema/tools/ee_actions.h
+++ b/eeschema/tools/ee_actions.h
@@ -76,9 +76,7 @@ public:
     static TOOL_ACTION pickerTool;
     static TOOL_ACTION placeSymbol;
     static TOOL_ACTION placePower;
-    static TOOL_ACTION startWire;
     static TOOL_ACTION drawWire;
-    static TOOL_ACTION startBus;
     static TOOL_ACTION drawBus;
     static TOOL_ACTION unfoldBus;
     static TOOL_ACTION placeNoConnect;
@@ -87,12 +85,11 @@ public:
     static TOOL_ACTION placeBusBusEntry;
     static TOOL_ACTION placeLabel;
     static TOOL_ACTION placeGlobalLabel;
-    static TOOL_ACTION placeHierarchicalLabel;
+    static TOOL_ACTION placeHierLabel;
     static TOOL_ACTION drawSheet;
     static TOOL_ACTION placeSheetPin;
     static TOOL_ACTION importSheetPin;
     static TOOL_ACTION placeSchematicText;
-    static TOOL_ACTION startLines;
     static TOOL_ACTION drawLines;
     static TOOL_ACTION placeImage;
     static TOOL_ACTION finishLineWireOrBus;
@@ -129,12 +126,6 @@ public:
     static TOOL_ACTION showDeMorganStandard;
     static TOOL_ACTION showDeMorganAlternate;
     static TOOL_ACTION editSymbolUnit;
-    static TOOL_ACTION addJunction;
-    static TOOL_ACTION addLabel;
-    static TOOL_ACTION addGlobalLabel;
-    static TOOL_ACTION addHierLabel;
-    static TOOL_ACTION addSheetPin;
-    static TOOL_ACTION addImportedSheetPin;
     static TOOL_ACTION toShapeSlash;
     static TOOL_ACTION toShapeBackslash;
     static TOOL_ACTION toLabel;
diff --git a/eeschema/tools/ee_inspection_tool.cpp b/eeschema/tools/ee_inspection_tool.cpp
index 28eee7470b..6d8f14c432 100644
--- a/eeschema/tools/ee_inspection_tool.cpp
+++ b/eeschema/tools/ee_inspection_tool.cpp
@@ -170,8 +170,7 @@ void EE_INSPECTION_TOOL::checkPart( LIB_PART* aPart )
 
         dup_error++;
 
-        /* TODO I dare someone to find a way to make happy translators on
-           this thing! Lorenzo */
+        /* TODO I dare someone to find a way to make happy translators on this thing! Lorenzo */
 
         msg = wxString::Format( _( "<b>Duplicate pin %s</b> \"%s\" at location <b>(%.3f, %.3f)</b>"
                                    " conflicts with pin %s \"%s\" at location <b>(%.3f, %.3f)</b>" ),
@@ -271,7 +270,7 @@ int EE_INSPECTION_TOOL::ShowDatasheet( const TOOL_EVENT& aEvent )
 
         if( part->GetAliasCount() > 1 )
         {
-            ACTION_MENU  popup;
+            ACTION_MENU  popup( true );
             wxString     msg;
             int          id = 0;
 
diff --git a/eeschema/tools/ee_picker_tool.cpp b/eeschema/tools/ee_picker_tool.cpp
index 3dcc0a40c8..688fabaa23 100644
--- a/eeschema/tools/ee_picker_tool.cpp
+++ b/eeschema/tools/ee_picker_tool.cpp
@@ -125,7 +125,6 @@ int EE_PICKER_TOOL::Main( const TOOL_EVENT& aEvent )
 
     resetPicker();
     controls->ForceCursorPosition( false );
-    getEditFrame<SCH_BASE_FRAME>()->SetNoToolSelected();
 
     return 0;
 }
diff --git a/eeschema/tools/ee_point_editor.cpp b/eeschema/tools/ee_point_editor.cpp
index b1cb694604..36db8cfc81 100644
--- a/eeschema/tools/ee_point_editor.cpp
+++ b/eeschema/tools/ee_point_editor.cpp
@@ -267,8 +267,6 @@ int EE_POINT_EDITOR::Main( const TOOL_EVENT& aEvent )
 
     KIGFX::VIEW_CONTROLS* controls = getViewControls();
     KIGFX::VIEW*          view = getView();
-    int                   savedToolID = m_frame->GetToolId();
-    wxString              savedToolMsg = m_frame->GetToolMsg();
     EDA_ITEM*             item = (EDA_ITEM*) selection.Front();
 
     controls->ShowCursor( true );
@@ -286,21 +284,14 @@ int EE_POINT_EDITOR::Main( const TOOL_EVENT& aEvent )
     // Main loop: keep receiving events
     while( OPT_TOOL_EVENT evt = Wait() )
     {
-        if( !m_editPoints
-             || evt->Matches( EVENTS::ClearedEvent )
-             || evt->Matches( EVENTS::UnselectedEvent )
-             || evt->Matches( EVENTS::SelectedEvent ) )
-        {
+        if( !m_editPoints || TOOL_EVT_UTILS::IsSelectionEvent( evt.get() ) )
             break;
-        }
 
         if ( !inDrag )
             updateEditedPoint( *evt );
 
         if( evt->IsDrag( BUT_LEFT ) && m_editedPoint )
         {
-            m_frame->SetToolID( ID_DRAG_POINT, -1, _( "Drag Point" ) );
-
             if( !inDrag )
             {
                 saveItemsToUndo();
@@ -318,8 +309,6 @@ int EE_POINT_EDITOR::Main( const TOOL_EVENT& aEvent )
         else if( evt->IsMouseUp( BUT_LEFT ) )
         {
             controls->SetAutoPan( false );
-            m_frame->SetToolID( savedToolID, -1, savedToolMsg );
-
             inDrag = false;
 
             m_toolMgr->PassEvent();
@@ -333,7 +322,6 @@ int EE_POINT_EDITOR::Main( const TOOL_EVENT& aEvent )
                 modified = false;
             }
 
-            m_frame->SetToolID( savedToolID, -1, savedToolMsg );
             break;
         }
 
@@ -348,7 +336,6 @@ int EE_POINT_EDITOR::Main( const TOOL_EVENT& aEvent )
 
     controls->SetAutoPan( false );
     controls->CaptureCursor( false );
-    m_frame->SetToolID( savedToolID, -1, savedToolMsg );
 
     if( m_editPoints )
     {
diff --git a/eeschema/tools/ee_selection_tool.cpp b/eeschema/tools/ee_selection_tool.cpp
index ee4ca95e32..5e05efdbfd 100644
--- a/eeschema/tools/ee_selection_tool.cpp
+++ b/eeschema/tools/ee_selection_tool.cpp
@@ -214,8 +214,8 @@ bool EE_SELECTION_TOOL::Init()
     menu.AddItem( EE_ACTIONS::leaveSheet,         belowRootSheetCondition, 1 );
 
     menu.AddSeparator( EE_CONDITIONS::Empty, 100 );
-    menu.AddItem( EE_ACTIONS::startWire,          schEditCondition && EE_CONDITIONS::Empty, 100 );
-    menu.AddItem( EE_ACTIONS::startBus,           schEditCondition && EE_CONDITIONS::Empty, 100 );
+    menu.AddItem( EE_ACTIONS::drawWire,           schEditCondition && EE_CONDITIONS::Empty, 100 );
+    menu.AddItem( EE_ACTIONS::drawBus,            schEditCondition && EE_CONDITIONS::Empty, 100 );
 
     menu.AddSeparator( SCH_WIRE_BUS_TOOL::IsDrawingWire, 100 );
     menu.AddItem( EE_ACTIONS::finishWire,         SCH_WIRE_BUS_TOOL::IsDrawingWire, 100 );
@@ -225,14 +225,14 @@ bool EE_SELECTION_TOOL::Init()
 
     menu.AddSeparator( EE_CONDITIONS::NotEmpty, 200 );
     menu.AddItem( EE_ACTIONS::selectConnection,   wireOrBusSelection && EE_CONDITIONS::Idle, 250 );
-    menu.AddItem( EE_ACTIONS::addJunction,        wireOrBusSelection && EE_CONDITIONS::Idle, 250 );
-    menu.AddItem( EE_ACTIONS::addLabel,           wireOrBusSelection && EE_CONDITIONS::Idle, 250 );
-    menu.AddItem( EE_ACTIONS::addGlobalLabel,     wireOrBusSelection && EE_CONDITIONS::Idle, 250 );
-    menu.AddItem( EE_ACTIONS::addHierLabel,       wireOrBusSelection && EE_CONDITIONS::Idle, 250 );
+    menu.AddItem( EE_ACTIONS::placeJunction,      wireOrBusSelection && EE_CONDITIONS::Idle, 250 );
+    menu.AddItem( EE_ACTIONS::placeLabel,         wireOrBusSelection && EE_CONDITIONS::Idle, 250 );
+    menu.AddItem( EE_ACTIONS::placeGlobalLabel,   wireOrBusSelection && EE_CONDITIONS::Idle, 250 );
+    menu.AddItem( EE_ACTIONS::placeHierLabel,     wireOrBusSelection && EE_CONDITIONS::Idle, 250 );
     menu.AddItem( EE_ACTIONS::breakWire,          wireSelection && EE_CONDITIONS::Idle, 250 );
     menu.AddItem( EE_ACTIONS::breakBus,           busSelection && EE_CONDITIONS::Idle, 250 );
-    menu.AddItem( EE_ACTIONS::addSheetPin,        sheetSelection && EE_CONDITIONS::Idle, 250 );
-    menu.AddItem( EE_ACTIONS::addImportedSheetPin,sheetSelection && EE_CONDITIONS::Idle, 250 );
+    menu.AddItem( EE_ACTIONS::placeSheetPin,      sheetSelection && EE_CONDITIONS::Idle, 250 );
+    menu.AddItem( EE_ACTIONS::importSheetPin,     sheetSelection && EE_CONDITIONS::Idle, 250 );
 
     menu.AddSeparator( havePartCondition && EE_CONDITIONS::Empty, 400 );
     menu.AddItem( EE_ACTIONS::symbolProperties,   havePartCondition && EE_CONDITIONS::Empty, 400 );
@@ -293,6 +293,15 @@ int EE_SELECTION_TOOL::UpdateMenu( const TOOL_EVENT& aEvent )
 }
 
 
+int EE_SELECTION_TOOL::SelectionTool( const TOOL_EVENT& aEvent )
+{
+    // Since the selection tool is always running underneath the toolStack, all we need to
+    // do is clear the stack.
+    m_frame->ClearToolStack();
+    return 0;
+}
+
+
 int EE_SELECTION_TOOL::Main( const TOOL_EVENT& aEvent )
 {
     const KICAD_T movableItems[] =
@@ -335,7 +344,7 @@ int EE_SELECTION_TOOL::Main( const TOOL_EVENT& aEvent )
         {
             // JEY TODO: this is a hack, but I can't figure out why it's needed to
             // keep from getting the first click when running the Place Symbol tool.
-            if( m_frame->GetToolId() != ID_NO_TOOL_SELECTED )
+            if( m_frame->GetCurrentToolName() != EE_ACTIONS::selectionTool.GetName() )
                 continue;
 
             if( evt->Modifier( MD_CTRL ) && dynamic_cast<SCH_EDIT_FRAME*>( m_frame ) )
@@ -415,7 +424,7 @@ int EE_SELECTION_TOOL::Main( const TOOL_EVENT& aEvent )
         }
 
         // context sub-menu selection?  Handle unit selection or bus unfolding
-        else if( evt->Category() == TC_COMMAND && evt->Action() == TA_CONTEXT_MENU_CHOICE )
+        else if( evt->Category() == TC_COMMAND && evt->Action() == TA_CHOICE_MENU_CHOICE )
         {
             if( evt->GetCommandId().get() >= ID_POPUP_SCH_SELECT_UNIT_CMP
                 && evt->GetCommandId().get() <= ID_POPUP_SCH_SELECT_UNIT_CMP_MAX )
@@ -446,7 +455,7 @@ int EE_SELECTION_TOOL::Main( const TOOL_EVENT& aEvent )
             ClearSelection();
         }
 
-        else if( evt->Action() == TA_CONTEXT_MENU_CLOSED )
+        else if( evt->Action() == TA_CHOICE_MENU_CLOSED )
         {
             m_menu.CloseContextMenu( evt );
         }
@@ -995,7 +1004,7 @@ int EE_SELECTION_TOOL::SelectionMenu( const TOOL_EVENT& aEvent )
 bool EE_SELECTION_TOOL::doSelectionMenu( EE_COLLECTOR* aCollector )
 {
     EDA_ITEM*   current = nullptr;
-    ACTION_MENU menu;
+    ACTION_MENU menu( true );
 
     int limit = std::min( MAX_SELECT_ITEM_IDS, aCollector->GetCount() );
 
@@ -1018,7 +1027,7 @@ bool EE_SELECTION_TOOL::doSelectionMenu( EE_COLLECTOR* aCollector )
 
     while( OPT_TOOL_EVENT evt = Wait() )
     {
-        if( evt->Action() == TA_CONTEXT_MENU_UPDATE )
+        if( evt->Action() == TA_CHOICE_MENU_UPDATE )
         {
             if( current )
                 unhighlight( current, BRIGHTENED );
@@ -1036,7 +1045,7 @@ bool EE_SELECTION_TOOL::doSelectionMenu( EE_COLLECTOR* aCollector )
                 current = NULL;
             }
         }
-        else if( evt->Action() == TA_CONTEXT_MENU_CHOICE )
+        else if( evt->Action() == TA_CHOICE_MENU_CHOICE )
         {
             if( current )
                 unhighlight( current, BRIGHTENED );
@@ -1315,6 +1324,7 @@ void EE_SELECTION_TOOL::setTransitions()
     Go( &EE_SELECTION_TOOL::UpdateMenu,          ACTIONS::updateMenu.MakeEvent() );
 
     Go( &EE_SELECTION_TOOL::Main,                EE_ACTIONS::selectionActivate.MakeEvent() );
+    Go( &EE_SELECTION_TOOL::SelectionTool,       ACTIONS::selectionTool.MakeEvent() );
     Go( &EE_SELECTION_TOOL::SelectNode,          EE_ACTIONS::selectNode.MakeEvent() );
     Go( &EE_SELECTION_TOOL::SelectConnection,    EE_ACTIONS::selectConnection.MakeEvent() );
     Go( &EE_SELECTION_TOOL::ClearSelection,      EE_ACTIONS::clearSelection.MakeEvent() );
diff --git a/eeschema/tools/ee_selection_tool.h b/eeschema/tools/ee_selection_tool.h
index e3739819c4..f08fa31cba 100644
--- a/eeschema/tools/ee_selection_tool.h
+++ b/eeschema/tools/ee_selection_tool.h
@@ -74,6 +74,11 @@ public:
      */
     int Main( const TOOL_EVENT& aEvent );
 
+    /*
+     * Main() is always running, so this just clears the frame's tool stack.
+     */
+    int SelectionTool( const TOOL_EVENT& aEvent );
+
     /**
      * Function GetSelection()
      *
diff --git a/eeschema/tools/lib_drawing_tools.cpp b/eeschema/tools/lib_drawing_tools.cpp
index 65896a3451..16df7e06c6 100644
--- a/eeschema/tools/lib_drawing_tools.cpp
+++ b/eeschema/tools/lib_drawing_tools.cpp
@@ -24,12 +24,8 @@
 #include <ee_actions.h>
 #include <lib_edit_frame.h>
 #include <sch_view.h>
-#include <class_draw_panel_gal.h>
-#include <project.h>
-#include <id.h>
 #include <eeschema_id.h>
 #include <confirm.h>
-#include <view/view_group.h>
 #include <view/view_controls.h>
 #include <view/view.h>
 #include <tool/tool_manager.h>
@@ -97,11 +93,6 @@ LIB_DRAWING_TOOLS::LIB_DRAWING_TOOLS() :
 }
 
 
-LIB_DRAWING_TOOLS::~LIB_DRAWING_TOOLS()
-{
-}
-
-
 bool LIB_DRAWING_TOOLS::Init()
 {
     EE_TOOL_BASE::Init();
@@ -119,19 +110,41 @@ bool LIB_DRAWING_TOOLS::Init()
 
 int LIB_DRAWING_TOOLS::PlacePin( const TOOL_EVENT& aEvent )
 {
-    m_frame->SetToolID( ID_SYMBOL_PIN_TOOL, wxCURSOR_PENCIL, _( "Add pin" ) );
-    return doTwoClickPlace( LIB_PIN_T );
+    if( aEvent.HasPosition() )
+    {
+        m_frame->PushTool( aEvent.GetCommandStr().get() );
+        doTwoClickPlace( LIB_PIN_T, true );
+        m_frame->PopTool();
+    }
+    else
+    {
+        m_frame->SetTool( aEvent.GetCommandStr().get() );
+        doTwoClickPlace( LIB_PIN_T, false );
+    }
+
+    return 0;
 }
 
 
 int LIB_DRAWING_TOOLS::PlaceText( const TOOL_EVENT& aEvent )
 {
-    m_frame->SetToolID( ID_SYMBOL_TEXT_TOOL, wxCURSOR_PENCIL, _( "Add text" ) );
-    return doTwoClickPlace( LIB_TEXT_T );
+    if( aEvent.HasPosition() )
+    {
+        m_frame->PushTool( aEvent.GetCommandStr().get() );
+        doTwoClickPlace( LIB_TEXT_T, true );
+        m_frame->PopTool();
+    }
+    else
+    {
+        m_frame->SetTool( aEvent.GetCommandStr().get() );
+        doTwoClickPlace( LIB_TEXT_T, false );
+    }
+
+    return 0;
 }
 
 
-int LIB_DRAWING_TOOLS::doTwoClickPlace( KICAD_T aType )
+int LIB_DRAWING_TOOLS::doTwoClickPlace( KICAD_T aType, bool aImmediateMode )
 {
     LIB_PIN_TOOL* pinTool = aType == LIB_PIN_T ? m_toolMgr->GetTool<LIB_PIN_TOOL>() : nullptr;
     VECTOR2I      cursorPos;
@@ -142,6 +155,10 @@ int LIB_DRAWING_TOOLS::doTwoClickPlace( KICAD_T aType )
 
     Activate();
 
+    // Prime the pump
+    if( aImmediateMode )
+        m_toolMgr->RunAction( ACTIONS::cursorClick );
+
     // Main loop: keep receiving events
     while( OPT_TOOL_EVENT evt = Wait() )
     {
@@ -156,10 +173,13 @@ int LIB_DRAWING_TOOLS::doTwoClickPlace( KICAD_T aType )
                 delete item;
                 item = nullptr;
 
-                if( !evt->IsActivate() )
+                if( !evt->IsActivate() && !aImmediateMode )
                     continue;
             }
 
+            if( !evt->IsActivate() && !aImmediateMode )
+                m_frame->PopTool();
+
             break;
         }
 
@@ -240,6 +260,9 @@ int LIB_DRAWING_TOOLS::doTwoClickPlace( KICAD_T aType )
 
                 m_frame->RebuildView();
                 m_frame->OnModify();
+
+                if( aImmediateMode )
+                    break;
             }
         }
         else if( evt->IsClick( BUT_RIGHT ) )
@@ -263,32 +286,34 @@ int LIB_DRAWING_TOOLS::doTwoClickPlace( KICAD_T aType )
         getViewControls()->CaptureCursor( !!item );
     }
 
-    m_frame->SetNoToolSelected();
-
     return 0;
 }
 
 
 int LIB_DRAWING_TOOLS::DrawShape( const TOOL_EVENT& aEvent )
 {
+    KICAD_T type = TYPE_NOT_INIT;
+
     // We might be running as the same shape in another co-routine.  Make sure that one
     // gets whacked.
     m_toolMgr->DeactivateTool();
 
     if( aEvent.IsAction( &EE_ACTIONS::drawSymbolArc ) )
-        m_frame->SetToolID( ID_SYMBOL_ARC_TOOL, wxCURSOR_PENCIL, _( "Draw Arc" ) );
+        type = LIB_ARC_T;
     else if( aEvent.IsAction( &EE_ACTIONS::drawSymbolCircle ) )
-        m_frame->SetToolID( ID_SYMBOL_CIRCLE_TOOL, wxCURSOR_PENCIL, _( "Draw Circle" ) );
+        type = LIB_CIRCLE_T;
     else if( aEvent.IsAction( &EE_ACTIONS::drawSymbolLines ) )
-        m_frame->SetToolID( ID_SYMBOL_LINE_TOOL, wxCURSOR_PENCIL, _( "Draw Lines" ) );
+        type = LIB_POLYLINE_T;
     else if( aEvent.IsAction( &EE_ACTIONS::drawSymbolRectangle ) )
-        m_frame->SetToolID( ID_SYMBOL_RECT_TOOL, wxCURSOR_PENCIL, _( "Draw Rectangle" ) );
+        type = LIB_RECTANGLE_T;
     else
         wxCHECK_MSG( false, 0, "Unknown action in LIB_DRAWING_TOOLS::DrawShape()" );
 
     m_toolMgr->RunAction( EE_ACTIONS::clearSelection, true );
     getViewControls()->ShowCursor( true );
 
+    m_frame->SetTool( aEvent.GetCommandStr().get() );
+
     Activate();
 
     LIB_PART* part = m_frame->GetCurPart();
@@ -313,6 +338,9 @@ int LIB_DRAWING_TOOLS::DrawShape( const TOOL_EVENT& aEvent )
                     continue;
             }
 
+            if( !evt->IsActivate() )
+                m_frame->PopTool();
+
             break;
         }
 
@@ -323,12 +351,12 @@ int LIB_DRAWING_TOOLS::DrawShape( const TOOL_EVENT& aEvent )
 
             m_toolMgr->RunAction( EE_ACTIONS::clearSelection, true );
 
-            switch( m_frame->GetToolId() )
+            switch( type )
             {
-            case ID_SYMBOL_ARC_TOOL:    item = new LIB_ARC( part );       break;
-            case ID_SYMBOL_CIRCLE_TOOL: item = new LIB_CIRCLE( part );    break;
-            case ID_SYMBOL_LINE_TOOL:   item = new LIB_POLYLINE( part );  break;
-            case ID_SYMBOL_RECT_TOOL:   item = new LIB_RECTANGLE( part ); break;
+            case LIB_ARC_T:       item = new LIB_ARC( part );       break;
+            case LIB_CIRCLE_T:    item = new LIB_CIRCLE( part );    break;
+            case LIB_POLYLINE_T:  item = new LIB_POLYLINE( part );  break;
+            case LIB_RECTANGLE_T: item = new LIB_RECTANGLE( part ); break;
             }
 
             item->SetWidth( LIB_EDIT_FRAME::g_LastLineWidth );
@@ -393,15 +421,13 @@ int LIB_DRAWING_TOOLS::DrawShape( const TOOL_EVENT& aEvent )
         getViewControls()->CaptureCursor( !!item );
     }
 
-    m_frame->SetNoToolSelected();
-
     return 0;
 }
 
 
 int LIB_DRAWING_TOOLS::PlaceAnchor( const TOOL_EVENT& aEvent )
 {
-    m_frame->SetToolID( ID_SYMBOL_ANCHOR_TOOL, wxCURSOR_PENCIL, _( "Move symbol anchor" ) );
+    m_frame->PushTool( aEvent.GetCommandStr().get() );
 
     getViewControls()->ShowCursor( true );
     getViewControls()->SetSnapping( true );
@@ -441,7 +467,7 @@ int LIB_DRAWING_TOOLS::PlaceAnchor( const TOOL_EVENT& aEvent )
         }
     }
 
-    m_frame->SetNoToolSelected();
+    m_frame->PopTool();
 
     return 0;
 }
diff --git a/eeschema/tools/lib_drawing_tools.h b/eeschema/tools/lib_drawing_tools.h
index 6e0d27e998..f74b8f212f 100644
--- a/eeschema/tools/lib_drawing_tools.h
+++ b/eeschema/tools/lib_drawing_tools.h
@@ -40,7 +40,7 @@ class LIB_DRAWING_TOOLS : public EE_TOOL_BASE<LIB_EDIT_FRAME>
 {
 public:
     LIB_DRAWING_TOOLS();
-    ~LIB_DRAWING_TOOLS();
+    ~LIB_DRAWING_TOOLS() override { }
 
     /// @copydoc TOOL_INTERACTIVE::Init()
     bool Init() override;
@@ -54,7 +54,7 @@ public:
 
 private:
 
-    int doTwoClickPlace( KICAD_T aType );
+    int doTwoClickPlace( KICAD_T aType, bool aImmediateMode );
 
     ///> Sets up handlers for various events.
     void setTransitions() override;
diff --git a/eeschema/tools/lib_edit_tool.cpp b/eeschema/tools/lib_edit_tool.cpp
index 9c2a711124..99a4859b10 100644
--- a/eeschema/tools/lib_edit_tool.cpp
+++ b/eeschema/tools/lib_edit_tool.cpp
@@ -30,7 +30,6 @@
 #include <ee_actions.h>
 #include <bitmaps.h>
 #include <confirm.h>
-#include <base_struct.h>
 #include <sch_view.h>
 #include <lib_edit_frame.h>
 #include <eeschema_id.h>
@@ -49,11 +48,6 @@ LIB_EDIT_TOOL::LIB_EDIT_TOOL() :
 }
 
 
-LIB_EDIT_TOOL::~LIB_EDIT_TOOL()
-{
-}
-
-
 bool LIB_EDIT_TOOL::Init()
 {
     EE_TOOL_BASE::Init();
@@ -63,7 +57,6 @@ bool LIB_EDIT_TOOL::Init()
 
     wxASSERT_MSG( drawingTools, "eeschema.SymbolDrawing tool is not available" );
 
-    //
     // Add edit actions to the move tool menu
     //
     if( moveTool )
@@ -85,7 +78,6 @@ bool LIB_EDIT_TOOL::Init()
         moveMenu.AddItem( ACTIONS::duplicate,          EE_CONDITIONS::NotEmpty, 300 );
     }
 
-    //
     // Add editing actions to the drawing tool menu
     //
     CONDITIONAL_MENU& drawMenu = drawingTools->GetToolMenu().GetMenu();
@@ -98,7 +90,6 @@ bool LIB_EDIT_TOOL::Init()
 
     drawMenu.AddItem( EE_ACTIONS::properties,          EE_CONDITIONS::Count( 1 ), 200 );
 
-    //
     // Add editing actions to the selection tool menu
     //
     CONDITIONAL_MENU& selToolMenu = m_selectionTool->GetToolMenu().GetMenu();
@@ -302,16 +293,18 @@ static bool deleteItem( SCH_BASE_FRAME* aFrame, const VECTOR2D& aPosition )
 
 int LIB_EDIT_TOOL::DeleteItemCursor( const TOOL_EVENT& aEvent )
 {
+    m_frame->SetTool( aEvent.GetCommandStr().get() );
+    m_frame->GetCanvas()->SetCurrentCursor( wxCURSOR_BULLSEYE );
     Activate();
 
     EE_PICKER_TOOL* picker = m_toolMgr->GetTool<EE_PICKER_TOOL>();
     wxCHECK( picker, 0 );
 
-    m_frame->SetToolID( ID_LIBEDIT_DELETE_ITEM_BUTT, wxCURSOR_BULLSEYE, _( "Delete item" ) );
     picker->SetClickHandler( std::bind( deleteItem, m_frame, std::placeholders::_1 ) );
     picker->Activate();
     Wait();
 
+    m_frame->GetCanvas()->SetCurrentCursor( wxCURSOR_ARROW );
     return 0;
 }
 
diff --git a/eeschema/tools/lib_edit_tool.h b/eeschema/tools/lib_edit_tool.h
index 0f834a0320..6d1442bcdc 100644
--- a/eeschema/tools/lib_edit_tool.h
+++ b/eeschema/tools/lib_edit_tool.h
@@ -34,7 +34,7 @@ class LIB_EDIT_TOOL : public EE_TOOL_BASE<LIB_EDIT_FRAME>
 {
 public:
     LIB_EDIT_TOOL();
-    ~LIB_EDIT_TOOL();
+    ~LIB_EDIT_TOOL() override { }
 
     /// @copydoc TOOL_INTERACTIVE::Init()
     bool Init() override;
diff --git a/eeschema/tools/lib_move_tool.cpp b/eeschema/tools/lib_move_tool.cpp
index e6585d389e..613117b868 100644
--- a/eeschema/tools/lib_move_tool.cpp
+++ b/eeschema/tools/lib_move_tool.cpp
@@ -41,11 +41,6 @@ LIB_MOVE_TOOL::LIB_MOVE_TOOL() :
 }
 
 
-LIB_MOVE_TOOL::~LIB_MOVE_TOOL()
-{
-}
-
-
 bool LIB_MOVE_TOOL::Init()
 {
     EE_TOOL_BASE::Init();
@@ -88,7 +83,7 @@ int LIB_MOVE_TOOL::Main( const TOOL_EVENT& aEvent )
     if( selection.Empty() )
         return 0;
 
-    m_frame->SetToolID( ID_SCH_MOVE, wxCURSOR_DEFAULT, _( "Move Items" ) );
+    m_frame->PushTool( aEvent.GetCommandStr().get() );
 
     Activate();
     controls->ShowCursor( true );
@@ -269,22 +264,22 @@ int LIB_MOVE_TOOL::Main( const TOOL_EVENT& aEvent )
     if( !chain_commands )
         m_moveOffset = { 0, 0 };
 
-    m_moveInProgress = false;
-    m_frame->SetNoToolSelected();
-
-    selection.ClearReferencePoint();
-
     for( auto item : selection )
         item->ClearEditFlags();
 
     if( unselect )
         m_toolMgr->RunAction( EE_ACTIONS::clearSelection, true );
+    else
+        selection.ClearReferencePoint();
 
     if( restore_state )
         m_frame->RollbackPartFromUndo();
     else
         m_frame->OnModify();
 
+    m_moveInProgress = false;
+    m_frame->PopTool();
+
     return 0;
 }
 
diff --git a/eeschema/tools/lib_move_tool.h b/eeschema/tools/lib_move_tool.h
index 98bfc9ae29..25e384a93b 100644
--- a/eeschema/tools/lib_move_tool.h
+++ b/eeschema/tools/lib_move_tool.h
@@ -35,7 +35,7 @@ class LIB_MOVE_TOOL : public EE_TOOL_BASE<LIB_EDIT_FRAME>
 {
 public:
     LIB_MOVE_TOOL();
-    ~LIB_MOVE_TOOL();
+    ~LIB_MOVE_TOOL() override { }
 
     /// @copydoc TOOL_INTERACTIVE::Init()
     bool Init() override;
diff --git a/eeschema/tools/lib_pin_tool.cpp b/eeschema/tools/lib_pin_tool.cpp
index f4dad1f4d2..0212790dde 100644
--- a/eeschema/tools/lib_pin_tool.cpp
+++ b/eeschema/tools/lib_pin_tool.cpp
@@ -95,11 +95,6 @@ LIB_PIN_TOOL::LIB_PIN_TOOL() :
 }
 
 
-LIB_PIN_TOOL::~LIB_PIN_TOOL()
-{
-}
-
-
 bool LIB_PIN_TOOL::Init()
 {
     EE_TOOL_BASE::Init();
diff --git a/eeschema/tools/lib_pin_tool.h b/eeschema/tools/lib_pin_tool.h
index 195b33cd8b..087106828c 100644
--- a/eeschema/tools/lib_pin_tool.h
+++ b/eeschema/tools/lib_pin_tool.h
@@ -35,7 +35,7 @@ class LIB_PIN_TOOL : public EE_TOOL_BASE<LIB_EDIT_FRAME>
 {
 public:
     LIB_PIN_TOOL();
-    ~LIB_PIN_TOOL();
+    ~LIB_PIN_TOOL() override { }
 
     /// @copydoc TOOL_INTERACTIVE::Init()
     bool Init() override;
diff --git a/eeschema/tools/sch_drawing_tools.cpp b/eeschema/tools/sch_drawing_tools.cpp
index d0c489a437..5eb23a53c0 100644
--- a/eeschema/tools/sch_drawing_tools.cpp
+++ b/eeschema/tools/sch_drawing_tools.cpp
@@ -24,7 +24,6 @@
 #include "sch_drawing_tools.h"
 #include "ee_selection_tool.h"
 #include <ee_actions.h>
-
 #include <sch_edit_frame.h>
 #include <sch_view.h>
 #include <class_draw_panel_gal.h>
@@ -90,8 +89,8 @@ TOOL_ACTION EE_ACTIONS::placeLabel( "eeschema.InteractiveDrawing.placeLabel",
         _( "Add Label" ), _( "Add a net label" ),
         add_line_label_xpm, AF_ACTIVATE );
 
-TOOL_ACTION EE_ACTIONS::placeHierarchicalLabel( "eeschema.InteractiveDrawing.placeHierarchicalLabel",
-        AS_GLOBAL, 
+TOOL_ACTION EE_ACTIONS::placeHierLabel( "eeschema.InteractiveDrawing.placeHierarchicalLabel",
+        AS_GLOBAL,
         'H', LEGACY_HK_NAME( "Add Hierarchical Label" ),
         _( "Add Hierarchical Label" ), _( "Add a hierarchical sheet label" ),
         add_hierarchical_label_xpm, AF_ACTIVATE );
@@ -134,36 +133,6 @@ TOOL_ACTION EE_ACTIONS::finishSheet( "eeschema.InteractiveDrawing.finishSheet",
         _( "Finish Sheet" ), _( "Finish drawing sheet" ),
         checked_ok_xpm, AF_NONE );
 
-TOOL_ACTION EE_ACTIONS::addJunction( "eeschema.InteractiveEditing.addJunction",
-        AS_GLOBAL, 0, "",
-        _( "Add Junction" ), _( "Add a wire or bus junction" ),
-        add_junction_xpm, AF_NONE );
-
-TOOL_ACTION EE_ACTIONS::addLabel( "eeschema.InteractiveEditing.addLabel",
-        AS_GLOBAL, 0, "",
-        _( "Add Label" ), _( "Add a label to a wire or bus" ),
-        add_line_label_xpm, AF_NONE );
-
-TOOL_ACTION EE_ACTIONS::addGlobalLabel( "eeschema.InteractiveEditing.addGlobalLabel",
-        AS_GLOBAL, 0, "",
-        _( "Add Global Label" ), _( "Add a global label to a wire or bus" ),
-        add_glabel_xpm, AF_NONE );
-
-TOOL_ACTION EE_ACTIONS::addHierLabel( "eeschema.InteractiveEditing.addHierLabel",
-        AS_GLOBAL, 0, "",
-        _( "Add Hierarchical Label" ), _( "Add a hierarchical label to a wire or bus" ),
-        add_hierarchical_label_xpm, AF_NONE );
-
-TOOL_ACTION EE_ACTIONS::addSheetPin( "eeschema.InteractiveEditing.addSheetPin",
-        AS_GLOBAL, 0, "",
-        _( "Add Sheet Pin" ), _( "Add a sheet pin to the selected sheet" ),
-        add_hierarchical_label_xpm, AF_NONE );
-
-TOOL_ACTION EE_ACTIONS::addImportedSheetPin( "eeschema.InteractiveEditing.addImportedSheetPin",
-        AS_GLOBAL, 0, "",
-        _( "Add Imported Sheet Pin" ), _( "Add an imported sheet pin" ),
-        add_hierarchical_label_xpm, AF_NONE );
-
 
 SCH_DRAWING_TOOLS::SCH_DRAWING_TOOLS() :
     EE_TOOL_BASE<SCH_EDIT_FRAME>( "eeschema.InteractiveDrawing" )
@@ -171,11 +140,6 @@ SCH_DRAWING_TOOLS::SCH_DRAWING_TOOLS() :
 }
 
 
-SCH_DRAWING_TOOLS::~SCH_DRAWING_TOOLS()
-{
-}
-
-
 bool SCH_DRAWING_TOOLS::Init()
 {
     EE_TOOL_BASE::Init();
@@ -191,157 +155,83 @@ bool SCH_DRAWING_TOOLS::Init()
 }
 
 
-int SCH_DRAWING_TOOLS::AddJunction( const TOOL_EVENT& aEvent )
-{
-    EE_SELECTION& selection = m_selectionTool->GetSelection();
-    SCH_LINE*     wire = dynamic_cast<SCH_LINE*>( selection.Front() );
-
-    m_toolMgr->RunAction( EE_ACTIONS::clearSelection, true );
-
-    if( wire )
-    {
-        SEG seg( wire->GetStartPoint(), wire->GetEndPoint() );
-        VECTOR2I nearest = seg.NearestPoint( getViewControls()->GetCursorPosition() );
-        getViewControls()->SetCrossHairCursorPosition( nearest, false );
-    }
-
-    getViewControls()->WarpCursor( getViewControls()->GetCursorPosition(), true );
-    SCH_JUNCTION* junction = m_frame->AddJunction( (wxPoint) getViewControls()->GetCursorPosition() );
-    m_selectionTool->AddItemToSel( junction );
-
-    return 0;
-}
-
-
-int SCH_DRAWING_TOOLS::AddLabel( const TOOL_EVENT& aEvent )
-{
-    m_toolMgr->RunAction( EE_ACTIONS::clearSelection, true );
-
-    int layer = LAYER_NOTES;
-
-    if( aEvent.IsAction( &EE_ACTIONS::addLabel ) )
-        layer = LAYER_LOCLABEL;
-    else if( aEvent.IsAction( &EE_ACTIONS::addGlobalLabel ) )
-        layer = LAYER_GLOBLABEL;
-    else if( aEvent.IsAction( &EE_ACTIONS::addHierLabel ) )
-        layer = LAYER_HIERLABEL;
-
-    SCH_ITEM* item = m_frame->CreateNewText( layer );
-    m_frame->AddItemToScreenAndUndoList( item );
-    m_selectionTool->AddItemToSel( item );
-
-    return 0;
-}
-
-
-int SCH_DRAWING_TOOLS::AddSheetPin( const TOOL_EVENT& aEvent )
-{
-    EE_SELECTION&  selection = m_selectionTool->GetSelection();
-    SCH_SHEET*     sheet = dynamic_cast<SCH_SHEET*>( selection.Front() );
-    SCH_HIERLABEL* label = nullptr;
-
-    if( !sheet )
-        return 0;
-
-    m_toolMgr->RunAction( EE_ACTIONS::clearSelection, true );
-
-    if( aEvent.IsAction( &EE_ACTIONS::addImportedSheetPin ) )
-    {
-        label = m_frame->ImportHierLabel( sheet );
-
-        if( !label )
-        {
-            m_statusPopup.reset( new STATUS_TEXT_POPUP( m_frame ) );
-            m_statusPopup->SetText( _( "No new hierarchical labels found." ) );
-            m_statusPopup->Move( wxGetMousePosition() + wxPoint( 20, 20 ) );
-            m_statusPopup->PopupFor( 2000 );
-            return 0;
-        }
-    }
-
-    SCH_SHEET_PIN* pin = m_frame->CreateSheetPin( sheet, label );
-    m_frame->AddItemToScreenAndUndoList( pin );
-    m_selectionTool->AddItemToSel( pin );
-
-    return 0;
-}
-
-
-// History lists for PlaceSymbol()
+// History lists for PlaceComponent()
 static SCH_BASE_FRAME::HISTORY_LIST s_SymbolHistoryList;
 static SCH_BASE_FRAME::HISTORY_LIST s_PowerHistoryList;
 
 
-int SCH_DRAWING_TOOLS::PlaceSymbol( const TOOL_EVENT& aEvent )
-{
-    SCH_COMPONENT* component = aEvent.Parameter<SCH_COMPONENT*>();
-
-    m_frame->SetToolID( ID_PLACE_SYMBOL_TOOL, wxCURSOR_PENCIL, _( "Add Symbol" ) );
-
-    return doPlaceComponent( component, nullptr, s_SymbolHistoryList );
-}
-
-
-int SCH_DRAWING_TOOLS::PlacePower( const TOOL_EVENT& aEvent )
+int SCH_DRAWING_TOOLS::PlaceComponent(  const TOOL_EVENT& aEvent  )
 {
     SCH_COMPONENT* component = aEvent.Parameter<SCH_COMPONENT*>();
+    bool           immediateMode = component || aEvent.HasPosition();
     SCHLIB_FILTER  filter;
+    SCH_BASE_FRAME::HISTORY_LIST* historyList = nullptr;
 
-    filter.FilterPowerParts( true );
-    m_frame->SetToolID( ID_PLACE_POWER_TOOL, wxCURSOR_PENCIL, _( "Add Power" ) );
+    if( aEvent.IsAction( &EE_ACTIONS::placeSymbol ) )
+        historyList = &s_SymbolHistoryList;
+    else if (aEvent.IsAction( &EE_ACTIONS::placePower ) )
+    {
+        historyList = &s_PowerHistoryList;
+        filter.FilterPowerParts( true );
+    }
+    else
+        wxFAIL_MSG( "PlaceCompontent(): unexpected request" );
 
-    return doPlaceComponent( component, &filter, s_PowerHistoryList );
-}
-
-
-int SCH_DRAWING_TOOLS::doPlaceComponent( SCH_COMPONENT* aComponent, SCHLIB_FILTER* aFilter,
-                                         SCH_BASE_FRAME::HISTORY_LIST& aHistoryList )
-{
-    VECTOR2I cursorPos = getViewControls()->GetCursorPosition();
     getViewControls()->ShowCursor( true );
 
+    // If a component was passed in get it ready for placement.
+    if( component )
+    {
+        component->SetFlags( IS_NEW | IS_MOVED );
+
+        m_toolMgr->RunAction( EE_ACTIONS::clearSelection, true );
+        m_selectionTool->AddItemToSel( component );
+    }
+
+    if( immediateMode )
+        m_frame->PushTool( aEvent.GetCommandStr().get() );
+    else
+        m_frame->SetTool( aEvent.GetCommandStr().get() );
+
     Activate();
 
-    // If a component was passed in get it ready for placement.
-    if( aComponent )
-    {
-        aComponent->SetFlags( IS_NEW | IS_MOVED );
-
-        m_toolMgr->RunAction( EE_ACTIONS::clearSelection, true );
-        m_selectionTool->AddItemToSel( aComponent );
-
-        // Queue up a refresh event so we don't have to wait for the next mouse-moved event
+    // Prime the pump
+    if( component )
         m_toolMgr->RunAction( EE_ACTIONS::refreshPreview );
-    }
+    else if( immediateMode )
+        m_toolMgr->RunAction( EE_ACTIONS::cursorClick );
 
     // Main loop: keep receiving events
     while( OPT_TOOL_EVENT evt = Wait() )
     {
-        cursorPos = getViewControls()->GetCursorPosition( !evt->Modifier( MD_ALT ) );
+        VECTOR2I cursorPos = getViewControls()->GetCursorPosition( !evt->Modifier( MD_ALT ) );
 
         if( TOOL_EVT_UTILS::IsCancelInteractive( evt.get() ) )
         {
-            if( aComponent )
+            if( component )
             {
                 m_toolMgr->RunAction( EE_ACTIONS::clearSelection, true );
                 m_view->ClearPreview();
-                delete aComponent;
-                aComponent = nullptr;
+                delete component;
+                component = nullptr;
 
-                if( !evt->IsActivate() )
+                if( !evt->IsActivate() && !immediateMode )
                     continue;
             }
 
+            if( !evt->IsActivate() && !immediateMode )
+                m_frame->PopTool();
+
             break;
         }
         else if( evt->IsClick( BUT_LEFT ) )
         {
-            if( !aComponent )
+            if( !component )
             {
                 m_toolMgr->RunAction( EE_ACTIONS::clearSelection, true );
 
                 // Pick the module to be placed
-                auto sel = m_frame->SelectCompFromLibTree( aFilter, aHistoryList, true, 1, 1,
+                auto sel = m_frame->SelectCompFromLibTree( &filter, *historyList, true, 1, 1,
                                                            m_frame->GetShowFootprintPreviews());
 
                 // Restore cursor after dialog
@@ -352,25 +242,25 @@ int SCH_DRAWING_TOOLS::doPlaceComponent( SCH_COMPONENT* aComponent, SCHLIB_FILTE
                 if( !part )
                     continue;
 
-                aComponent = new SCH_COMPONENT( *part, g_CurrentSheet, sel, (wxPoint) cursorPos );
-                aComponent->SetFlags( IS_NEW | IS_MOVED );
+                component = new SCH_COMPONENT( *part, g_CurrentSheet, sel, (wxPoint) cursorPos );
+                component->SetFlags( IS_NEW | IS_MOVED );
 
                 // Be sure the link to the corresponding LIB_PART is OK:
-                aComponent->Resolve( *m_frame->Prj().SchSymbolLibTable() );
+                component->Resolve( *m_frame->Prj().SchSymbolLibTable() );
 
                 if( m_frame->GetAutoplaceFields() )
-                    aComponent->AutoplaceFields( /* aScreen */ NULL, /* aManual */ false );
+                    component->AutoplaceFields( /* aScreen */ NULL, /* aManual */ false );
 
-                m_frame->SaveCopyForRepeatItem( aComponent );
+                m_frame->SaveCopyForRepeatItem( component );
 
                 m_view->ClearPreview();
-                m_view->AddToPreview( aComponent->Clone() );
-                m_selectionTool->AddItemToSel( aComponent );
+                m_view->AddToPreview( component->Clone() );
+                m_selectionTool->AddItemToSel( component );
             }
             else
             {
-                m_frame->AddItemToScreenAndUndoList( aComponent );
-                aComponent = nullptr;
+                m_frame->AddItemToScreenAndUndoList( component );
+                component = nullptr;
 
                 m_view->ClearPreview();
             }
@@ -378,39 +268,40 @@ int SCH_DRAWING_TOOLS::doPlaceComponent( SCH_COMPONENT* aComponent, SCHLIB_FILTE
         else if( evt->IsClick( BUT_RIGHT ) )
         {
             // Warp after context menu only if dragging...
-            if( !aComponent )
+            if( !component )
                 m_toolMgr->VetoContextMenuMouseWarp();
 
             m_menu.ShowContextMenu( m_selectionTool->GetSelection() );
         }
-        else if( evt->Category() == TC_COMMAND && evt->Action() == TA_CONTEXT_MENU_CHOICE )
+        else if( evt->Category() == TC_COMMAND && evt->Action() == TA_CHOICE_MENU_CHOICE )
         {
             if( evt->GetCommandId().get() >= ID_POPUP_SCH_SELECT_UNIT_CMP
                 && evt->GetCommandId().get() <= ID_POPUP_SCH_SELECT_UNIT_CMP_MAX )
             {
                 int unit = evt->GetCommandId().get() - ID_POPUP_SCH_SELECT_UNIT_CMP;
 
-                if( aComponent )
+                if( component )
                 {
-                    m_frame->SelectUnit( aComponent, unit );
+                    m_frame->SelectUnit( component, unit );
                     m_toolMgr->RunAction( EE_ACTIONS::refreshPreview );
                 }
             }
         }
-        else if( aComponent && ( evt->IsAction( &EE_ACTIONS::refreshPreview )
-                              || evt->IsMotion() ) )
+        else if( component && ( evt->IsAction( &EE_ACTIONS::refreshPreview )
+                             || evt->IsMotion() ) )
         {
-            aComponent->SetPosition( (wxPoint)cursorPos );
+            component->SetPosition( (wxPoint)cursorPos );
             m_view->ClearPreview();
-            m_view->AddToPreview( aComponent->Clone() );
+            m_view->AddToPreview( component->Clone() );
         }
 
         // Enable autopanning and cursor capture only when there is a module to be placed
-        getViewControls()->SetAutoPan( !!aComponent );
-        getViewControls()->CaptureCursor( !!aComponent );
+        getViewControls()->SetAutoPan( !!component );
+        getViewControls()->CaptureCursor( !!component );
     }
 
-    m_frame->SetNoToolSelected();
+    if( immediateMode )
+        m_frame->PopTool();
 
     return 0;
 }
@@ -419,16 +310,18 @@ int SCH_DRAWING_TOOLS::doPlaceComponent( SCH_COMPONENT* aComponent, SCHLIB_FILTE
 int SCH_DRAWING_TOOLS::PlaceImage( const TOOL_EVENT& aEvent )
 {
     SCH_BITMAP* image = aEvent.Parameter<SCH_BITMAP*>();
+    bool        immediateMode = image || aEvent.HasPosition();
 
-    m_frame->SetToolID( ID_PLACE_IMAGE_TOOL, wxCURSOR_PENCIL, _( "Add image" ) );
+    if( immediateMode )
+        m_frame->PushTool( aEvent.GetCommandStr().get() );
+    else
+        m_frame->SetTool( aEvent.GetCommandStr().get() );
 
     VECTOR2I cursorPos = getViewControls()->GetCursorPosition();
 
     m_toolMgr->RunAction( EE_ACTIONS::clearSelection, true );
     getViewControls()->ShowCursor( true );
 
-    Activate();
-
     // Add all the drawable parts to preview
     if( image )
     {
@@ -437,6 +330,14 @@ int SCH_DRAWING_TOOLS::PlaceImage( const TOOL_EVENT& aEvent )
         m_view->AddToPreview( image->Clone() );
     }
 
+    Activate();
+
+    // Prime the pump
+    if( image )
+        m_toolMgr->RunAction( EE_ACTIONS::refreshPreview );
+    else if( immediateMode )
+        m_toolMgr->RunAction( ACTIONS::cursorClick );
+
     // Main loop: keep receiving events
     while( OPT_TOOL_EVENT evt = Wait() )
     {
@@ -451,10 +352,13 @@ int SCH_DRAWING_TOOLS::PlaceImage( const TOOL_EVENT& aEvent )
                 delete image;
                 image = nullptr;
 
-                if( !evt->IsActivate() )
+                if( !evt->IsActivate() && !immediateMode )
                     continue;
             }
 
+            if( !evt->IsActivate() && !immediateMode )
+                m_frame->PopTool();
+
             break;
         }
         else if( evt->IsClick( BUT_LEFT ) )
@@ -502,6 +406,9 @@ int SCH_DRAWING_TOOLS::PlaceImage( const TOOL_EVENT& aEvent )
                 image = nullptr;
 
                 m_view->ClearPreview();
+
+                if( immediateMode )
+                    break;
             }
         }
         else if( evt->IsClick( BUT_RIGHT ) )
@@ -526,50 +433,65 @@ int SCH_DRAWING_TOOLS::PlaceImage( const TOOL_EVENT& aEvent )
         getViewControls()->CaptureCursor( !!image );
     }
 
-    m_frame->SetNoToolSelected();
+    if( immediateMode )
+        m_frame->PopTool();
 
     return 0;
 }
 
 
-int SCH_DRAWING_TOOLS::PlaceNoConnect( const TOOL_EVENT& aEvent )
+int SCH_DRAWING_TOOLS::SingleClickPlace( const TOOL_EVENT& aEvent )
 {
-    m_frame->SetToolID( ID_NOCONNECT_TOOL, wxCURSOR_PENCIL, _( "Add no connect" ) );
-    return doSingleClickPlace( SCH_NO_CONNECT_T );
-}
+    bool     immediateMode = aEvent.HasPosition();
+    wxPoint  cursorPos;
+    KICAD_T  type = TYPE_NOT_INIT;
 
+    if( aEvent.IsAction( &EE_ACTIONS::placeNoConnect ) )
+        type = SCH_NO_CONNECT_T;
+    else if( aEvent.IsAction( &EE_ACTIONS::placeJunction ) )
+    {
+        if( immediateMode )
+        {
+            EE_SELECTION& selection = m_selectionTool->GetSelection();
+            SCH_LINE*     wire = dynamic_cast<SCH_LINE*>( selection.Front() );
 
-int SCH_DRAWING_TOOLS::PlaceJunction( const TOOL_EVENT& aEvent )
-{
-    m_frame->SetToolID( ID_JUNCTION_TOOL, wxCURSOR_PENCIL, _( "Add junction" ) );
-    return doSingleClickPlace( SCH_JUNCTION_T );
-}
+            if( wire )
+            {
+                SEG seg( wire->GetStartPoint(), wire->GetEndPoint() );
+                VECTOR2I nearest = seg.NearestPoint( getViewControls()->GetCursorPosition() );
+                getViewControls()->SetCrossHairCursorPosition( nearest, false );
+                getViewControls()->WarpCursor( getViewControls()->GetCursorPosition(), true );
+            }
+        }
 
-
-int SCH_DRAWING_TOOLS::PlaceBusWireEntry( const TOOL_EVENT& aEvent )
-{
-    m_frame->SetToolID( ID_WIRETOBUS_ENTRY_TOOL, wxCURSOR_PENCIL, _( "Add wire to bus entry" ) );
-    return doSingleClickPlace( SCH_BUS_WIRE_ENTRY_T );
-}
-
-
-int SCH_DRAWING_TOOLS::PlaceBusBusEntry( const TOOL_EVENT& aEvent )
-{
-    m_frame->SetToolID( ID_BUSTOBUS_ENTRY_TOOL, wxCURSOR_PENCIL, _( "Add bus to bus entry" ) );
-    return doSingleClickPlace( SCH_BUS_BUS_ENTRY_T );
-}
-
-
-int SCH_DRAWING_TOOLS::doSingleClickPlace( KICAD_T aType )
-{
-    wxPoint cursorPos;
+        type = SCH_JUNCTION_T;
+    }
+    else if( aEvent.IsAction( &EE_ACTIONS::placeHierLabel ) )
+        type = SCH_HIER_LABEL_T;
+    else if( aEvent.IsAction( &EE_ACTIONS::placeSheetPin ) )
+        type = SCH_SHEET_PIN_T;
+    else if( aEvent.IsAction( &EE_ACTIONS::placeBusWireEntry ) )
+        type = SCH_BUS_WIRE_ENTRY_T;
+    else if( aEvent.IsAction( &EE_ACTIONS::placeBusBusEntry ) )
+        type = SCH_BUS_BUS_ENTRY_T;
+    else
+        wxFAIL_MSG( "SingleClickPlace(): unexpected request" );
 
     m_toolMgr->RunAction( EE_ACTIONS::clearSelection, true );
     getViewControls()->ShowCursor( true );
     getViewControls()->SetSnapping( true );
 
+    if( immediateMode )
+        m_frame->PushTool( aEvent.GetCommandStr().get() );
+    else
+        m_frame->SetTool( aEvent.GetCommandStr().get() );
+
     Activate();
 
+    // Prime the pump
+    if( immediateMode )
+        m_toolMgr->RunAction( ACTIONS::cursorClick );
+
     // Main loop: keep receiving events
     while( OPT_TOOL_EVENT evt = Wait() )
     {
@@ -577,15 +499,18 @@ int SCH_DRAWING_TOOLS::doSingleClickPlace( KICAD_T aType )
 
         if( TOOL_EVT_UTILS::IsCancelInteractive( evt.get() ) )
         {
+            if( !evt->IsActivate() && !immediateMode )
+                m_frame->PopTool();
+
             break;
         }
         else if( evt->IsClick( BUT_LEFT ) )
         {
             SCH_ITEM* item = nullptr;
 
-            if( !m_frame->GetScreen()->GetItem( cursorPos, 0, aType ) )
+            if( !m_frame->GetScreen()->GetItem( cursorPos, 0, type ) )
             {
-                switch( aType )
+                switch( type )
                 {
                 case SCH_NO_CONNECT_T:
                     item = new SCH_NO_CONNECT( cursorPos );
@@ -599,8 +524,6 @@ int SCH_DRAWING_TOOLS::doSingleClickPlace( KICAD_T aType )
                 case SCH_BUS_BUS_ENTRY_T:
                     item = new SCH_BUS_BUS_ENTRY( cursorPos, g_lastBusEntryShape );
                     break;
-                default:
-                    wxFAIL_MSG( "doSingleClickPlace(): unknown type" );
                 }
             }
 
@@ -615,6 +538,9 @@ int SCH_DRAWING_TOOLS::doSingleClickPlace( KICAD_T aType )
                 m_frame->TestDanglingEnds();
                 m_frame->OnModify();
             }
+
+            if( immediateMode )
+                break;
         }
         else if( evt->IsClick( BUT_RIGHT ) )
         {
@@ -622,68 +548,52 @@ int SCH_DRAWING_TOOLS::doSingleClickPlace( KICAD_T aType )
         }
     }
 
-    m_frame->SetNoToolSelected();
+    if( immediateMode )
+        m_frame->PopTool();
 
     return 0;
 }
 
 
-int SCH_DRAWING_TOOLS::PlaceLabel( const TOOL_EVENT& aEvent )
+int SCH_DRAWING_TOOLS::TwoClickPlace( const TOOL_EVENT& aEvent )
 {
-    m_frame->SetToolID( ID_LABEL_TOOL, wxCURSOR_PENCIL, _( "Add net label" ) );
-    return doTwoClickPlace( SCH_LABEL_T );
-}
-
-
-int SCH_DRAWING_TOOLS::PlaceGlobalLabel( const TOOL_EVENT& aEvent )
-{
-    m_frame->SetToolID( ID_GLOBALLABEL_TOOL, wxCURSOR_PENCIL, _( "Add global label" ) );
-    return doTwoClickPlace( SCH_GLOBAL_LABEL_T );
-}
-
-
-int SCH_DRAWING_TOOLS::PlaceHierarchicalLabel( const TOOL_EVENT& aEvent )
-{
-    m_frame->SetToolID( ID_HIERLABEL_TOOL, wxCURSOR_PENCIL, _( "Add hierarchical label" ) );
-    return doTwoClickPlace( SCH_HIER_LABEL_T );
-}
-
-
-int SCH_DRAWING_TOOLS::PlaceSheetPin( const TOOL_EVENT& aEvent )
-{
-    m_frame->SetToolID( ID_SHEETPIN_TOOL, wxCURSOR_PENCIL, _( "Add sheet pins" ) );
-    return doTwoClickPlace( SCH_SHEET_PIN_T );
-}
-
-
-int SCH_DRAWING_TOOLS::ImportSheetPin( const TOOL_EVENT& aEvent )
-{
-    m_frame->SetToolID( ID_IMPORT_SHEETPIN_TOOL, wxCURSOR_PENCIL, _( "Import sheet pins" ) );
-    return doTwoClickPlace( SCH_SHEET_PIN_T );
-}
-
-
-int SCH_DRAWING_TOOLS::PlaceSchematicText( const TOOL_EVENT& aEvent )
-{
-    m_frame->SetToolID( ID_SCHEMATIC_TEXT_TOOL, wxCURSOR_PENCIL, _( "Add text" ) );
-    return doTwoClickPlace( SCH_TEXT_T );
-}
-
-
-int SCH_DRAWING_TOOLS::doTwoClickPlace( KICAD_T aType )
-{
-    VECTOR2I  cursorPos;
     EDA_ITEM* item = nullptr;
+    bool      immediateMode = aEvent.HasPosition();
+    KICAD_T   type = TYPE_NOT_INIT;
+
+    if( aEvent.IsAction( &EE_ACTIONS::placeLabel ) )
+        type = SCH_LABEL_T;
+    else if( aEvent.IsAction( &EE_ACTIONS::placeGlobalLabel ) )
+        type = SCH_GLOBAL_LABEL_T;
+    else if( aEvent.IsAction( &EE_ACTIONS::placeHierLabel ) )
+        type = SCH_HIER_LABEL_T;
+    else if( aEvent.IsAction( &EE_ACTIONS::placeSheetPin ) )
+        type = SCH_SHEET_PIN_T;
+    else if( aEvent.IsAction( &EE_ACTIONS::importSheetPin ) )
+        type = SCH_SHEET_PIN_T;
+    else if( aEvent.IsAction( &EE_ACTIONS::placeSchematicText ) )
+        type = SCH_TEXT_T;
+    else
+        wxFAIL_MSG( "TwoClickPlace(): unexpected request" );
 
     m_toolMgr->RunAction( EE_ACTIONS::clearSelection, true );
     getViewControls()->ShowCursor( true );
 
+    if( immediateMode )
+        m_frame->PushTool( aEvent.GetCommandStr().get() );
+    else
+        m_frame->SetTool( aEvent.GetCommandStr().get() );
+
     Activate();
 
+    // Prime the pump
+    if( immediateMode )
+        m_toolMgr->RunAction( ACTIONS::cursorClick );
+
     // Main loop: keep receiving events
     while( OPT_TOOL_EVENT evt = Wait() )
     {
-        cursorPos = getViewControls()->GetCursorPosition( !evt->Modifier( MD_ALT ) );
+        VECTOR2I cursorPos = getViewControls()->GetCursorPosition( !evt->Modifier( MD_ALT ) );
 
         if( TOOL_EVT_UTILS::IsCancelInteractive( evt.get() ) )
         {
@@ -694,10 +604,13 @@ int SCH_DRAWING_TOOLS::doTwoClickPlace( KICAD_T aType )
                 delete item;
                 item = nullptr;
 
-                if( !evt->IsActivate() )
+                if( !evt->IsActivate() && !immediateMode )
                     continue;
             }
 
+            if( !evt->IsActivate() && !immediateMode )
+                m_frame->PopTool();
+
             break;
         }
         else if( evt->IsClick( BUT_LEFT ) )
@@ -707,7 +620,7 @@ int SCH_DRAWING_TOOLS::doTwoClickPlace( KICAD_T aType )
             {
                 m_toolMgr->RunAction( EE_ACTIONS::clearSelection, true );
 
-                switch( aType )
+                switch( type )
                 {
                 case SCH_LABEL_T:
                     item = m_frame->CreateNewText( LAYER_LOCLABEL );
@@ -735,7 +648,7 @@ int SCH_DRAWING_TOOLS::doTwoClickPlace( KICAD_T aType )
                         break;
                     }
 
-                    if( m_frame->GetToolId() == ID_IMPORT_SHEETPIN_TOOL )
+                    if( aEvent.IsAction( &EE_ACTIONS::importSheetPin ) )
                     {
                         label = m_frame->ImportHierLabel( sheet );
 
@@ -752,8 +665,6 @@ int SCH_DRAWING_TOOLS::doTwoClickPlace( KICAD_T aType )
                     item = m_frame->CreateSheetPin( sheet, label );
                     break;
                 }
-                default:
-                    wxFAIL_MSG( "doTwoClickPlace(): unknown type" );
                 }
 
                 // Restore cursor after dialog
@@ -778,6 +689,9 @@ int SCH_DRAWING_TOOLS::doTwoClickPlace( KICAD_T aType )
                 item = nullptr;
 
                 m_view->ClearPreview();
+
+                if( immediateMode )
+                    break;
             }
         }
         else if( evt->IsClick( BUT_RIGHT ) )
@@ -815,7 +729,8 @@ int SCH_DRAWING_TOOLS::doTwoClickPlace( KICAD_T aType )
         getViewControls()->CaptureCursor( !!item );
     }
 
-    m_frame->SetNoToolSelected();
+    if( immediateMode )
+        m_frame->PopTool();
 
     return 0;
 }
@@ -823,14 +738,23 @@ int SCH_DRAWING_TOOLS::doTwoClickPlace( KICAD_T aType )
 
 int SCH_DRAWING_TOOLS::DrawSheet( const TOOL_EVENT& aEvent )
 {
-    m_frame->SetToolID( ID_SHEET_TOOL, wxCURSOR_PENCIL, _( "Add sheet" ) );
+    SCH_SHEET* sheet = nullptr;
+    bool       immediateMode = aEvent.HasPosition();
+
     m_toolMgr->RunAction( EE_ACTIONS::clearSelection, true );
     getViewControls()->ShowCursor( true );
 
-    SCH_SHEET* sheet = nullptr;
+    if( immediateMode )
+        m_frame->PushTool( aEvent.GetCommandStr().get() );
+    else
+        m_frame->SetTool( aEvent.GetCommandStr().get() );
 
     Activate();
 
+    // Prime the pump
+    if( immediateMode )
+        m_toolMgr->RunAction( ACTIONS::cursorClick );
+
     // Main loop: keep receiving events
     while( auto evt = Wait() )
     {
@@ -846,10 +770,13 @@ int SCH_DRAWING_TOOLS::DrawSheet( const TOOL_EVENT& aEvent )
                 delete sheet;
                 sheet = nullptr;
 
-                if( !evt->IsActivate() )
+                if( !evt->IsActivate() && !immediateMode )
                     continue;
             }
 
+            if( !evt->IsActivate() && !immediateMode )
+                m_frame->PopTool();
+
             break;
         }
 
@@ -884,6 +811,9 @@ int SCH_DRAWING_TOOLS::DrawSheet( const TOOL_EVENT& aEvent )
             }
 
             sheet = nullptr;
+
+            if( immediateMode )
+                break;
         }
 
         else if( sheet && ( evt->IsAction( &EE_ACTIONS::refreshPreview )
@@ -908,7 +838,8 @@ int SCH_DRAWING_TOOLS::DrawSheet( const TOOL_EVENT& aEvent )
         getViewControls()->CaptureCursor( !!sheet );
     }
 
-    m_frame->SetNoToolSelected();
+    if( immediateMode )
+        m_frame->PopTool();
 
     return 0;
 }
@@ -929,25 +860,18 @@ void SCH_DRAWING_TOOLS::sizeSheet( SCH_SHEET* aSheet, VECTOR2I aPos )
 
 void SCH_DRAWING_TOOLS::setTransitions()
 {
-    Go( &SCH_DRAWING_TOOLS::PlaceSymbol,           EE_ACTIONS::placeSymbol.MakeEvent() );
-    Go( &SCH_DRAWING_TOOLS::PlacePower,            EE_ACTIONS::placePower.MakeEvent() );
-    Go( &SCH_DRAWING_TOOLS::PlaceNoConnect,        EE_ACTIONS::placeNoConnect.MakeEvent() );
-    Go( &SCH_DRAWING_TOOLS::PlaceJunction,         EE_ACTIONS::placeJunction.MakeEvent() );
-    Go( &SCH_DRAWING_TOOLS::PlaceBusWireEntry,     EE_ACTIONS::placeBusWireEntry.MakeEvent() );
-    Go( &SCH_DRAWING_TOOLS::PlaceBusBusEntry,      EE_ACTIONS::placeBusBusEntry.MakeEvent() );
-    Go( &SCH_DRAWING_TOOLS::PlaceLabel,            EE_ACTIONS::placeLabel.MakeEvent() );
-    Go( &SCH_DRAWING_TOOLS::PlaceHierarchicalLabel,EE_ACTIONS::placeHierarchicalLabel.MakeEvent() );
-    Go( &SCH_DRAWING_TOOLS::PlaceGlobalLabel,      EE_ACTIONS::placeGlobalLabel.MakeEvent() );
-    Go( &SCH_DRAWING_TOOLS::DrawSheet,             EE_ACTIONS::drawSheet.MakeEvent() );
-    Go( &SCH_DRAWING_TOOLS::PlaceSheetPin,         EE_ACTIONS::placeSheetPin.MakeEvent() );
-    Go( &SCH_DRAWING_TOOLS::ImportSheetPin,        EE_ACTIONS::importSheetPin.MakeEvent() );
-    Go( &SCH_DRAWING_TOOLS::PlaceSchematicText,    EE_ACTIONS::placeSchematicText.MakeEvent() );
-    Go( &SCH_DRAWING_TOOLS::PlaceImage,            EE_ACTIONS::placeImage.MakeEvent() );
-
-    Go( &SCH_DRAWING_TOOLS::AddJunction,           EE_ACTIONS::addJunction.MakeEvent() );
-    Go( &SCH_DRAWING_TOOLS::AddLabel,              EE_ACTIONS::addLabel.MakeEvent() );
-    Go( &SCH_DRAWING_TOOLS::AddLabel,              EE_ACTIONS::addGlobalLabel.MakeEvent() );
-    Go( &SCH_DRAWING_TOOLS::AddLabel,              EE_ACTIONS::addHierLabel.MakeEvent() );
-    Go( &SCH_DRAWING_TOOLS::AddSheetPin,           EE_ACTIONS::addSheetPin.MakeEvent() );
-    Go( &SCH_DRAWING_TOOLS::AddSheetPin,           EE_ACTIONS::addImportedSheetPin.MakeEvent() );
+    Go( &SCH_DRAWING_TOOLS::PlaceComponent,      EE_ACTIONS::placeSymbol.MakeEvent() );
+    Go( &SCH_DRAWING_TOOLS::PlaceComponent,      EE_ACTIONS::placePower.MakeEvent() );
+    Go( &SCH_DRAWING_TOOLS::SingleClickPlace,    EE_ACTIONS::placeNoConnect.MakeEvent() );
+    Go( &SCH_DRAWING_TOOLS::SingleClickPlace,    EE_ACTIONS::placeJunction.MakeEvent() );
+    Go( &SCH_DRAWING_TOOLS::SingleClickPlace,    EE_ACTIONS::placeBusWireEntry.MakeEvent() );
+    Go( &SCH_DRAWING_TOOLS::SingleClickPlace,    EE_ACTIONS::placeBusBusEntry.MakeEvent() );
+    Go( &SCH_DRAWING_TOOLS::TwoClickPlace,       EE_ACTIONS::placeLabel.MakeEvent() );
+    Go( &SCH_DRAWING_TOOLS::TwoClickPlace,       EE_ACTIONS::placeHierLabel.MakeEvent() );
+    Go( &SCH_DRAWING_TOOLS::TwoClickPlace,       EE_ACTIONS::placeGlobalLabel.MakeEvent() );
+    Go( &SCH_DRAWING_TOOLS::DrawSheet,           EE_ACTIONS::drawSheet.MakeEvent() );
+    Go( &SCH_DRAWING_TOOLS::TwoClickPlace,       EE_ACTIONS::placeSheetPin.MakeEvent() );
+    Go( &SCH_DRAWING_TOOLS::TwoClickPlace,       EE_ACTIONS::importSheetPin.MakeEvent() );
+    Go( &SCH_DRAWING_TOOLS::TwoClickPlace,       EE_ACTIONS::placeSchematicText.MakeEvent() );
+    Go( &SCH_DRAWING_TOOLS::PlaceImage,          EE_ACTIONS::placeImage.MakeEvent() );
 }
diff --git a/eeschema/tools/sch_drawing_tools.h b/eeschema/tools/sch_drawing_tools.h
index 01c7a9598c..c83965394f 100644
--- a/eeschema/tools/sch_drawing_tools.h
+++ b/eeschema/tools/sch_drawing_tools.h
@@ -46,39 +46,19 @@ class SCH_DRAWING_TOOLS : public EE_TOOL_BASE<SCH_EDIT_FRAME>
 {
 public:
     SCH_DRAWING_TOOLS();
-    ~SCH_DRAWING_TOOLS();
+    ~SCH_DRAWING_TOOLS() override { }
 
     /// @copydoc TOOL_INTERACTIVE::Init()
     bool Init() override;
 
-    int AddJunction( const TOOL_EVENT& aEvent );
-    int AddLabel( const TOOL_EVENT& aEvent );
-    int AddSheetPin( const TOOL_EVENT& aEvent );
-
-    int PlaceSymbol( const TOOL_EVENT& aEvent );
-    int PlacePower( const TOOL_EVENT& aEvent );
-    int PlaceNoConnect( const TOOL_EVENT& aEvent );
-    int PlaceJunction( const TOOL_EVENT& aEvent );
-    int PlaceBusWireEntry( const TOOL_EVENT& aEvent );
-    int PlaceBusBusEntry( const TOOL_EVENT& aEvent );
-    int PlaceLabel( const TOOL_EVENT& aEvent );
-    int PlaceGlobalLabel( const TOOL_EVENT& aEvent );
-    int PlaceHierarchicalLabel( const TOOL_EVENT& aEvent );
+    int PlaceComponent( const TOOL_EVENT& aEvent );
+    int SingleClickPlace( const TOOL_EVENT& aEvent );
+    int TwoClickPlace( const TOOL_EVENT& aEvent );
     int DrawSheet( const TOOL_EVENT& aEvent );
-    int PlaceSheetPin( const TOOL_EVENT& aEvent );
-    int ImportSheetPin( const TOOL_EVENT& aEvent );
-    int PlaceSchematicText( const TOOL_EVENT& aEvent );
     int PlaceImage( const TOOL_EVENT& aEvent );
 
 private:
 
-    int doPlaceComponent( SCH_COMPONENT* aComponent, SCHLIB_FILTER* aFilter,
-                          SCH_BASE_FRAME::HISTORY_LIST& aHistoryList );
-
-    int doSingleClickPlace( KICAD_T aType );
-
-    int doTwoClickPlace( KICAD_T aType );
-
     void sizeSheet( SCH_SHEET* aSheet, VECTOR2I aPos );
 
     ///> Sets up handlers for various events.
diff --git a/eeschema/tools/sch_edit_tool.cpp b/eeschema/tools/sch_edit_tool.cpp
index 8d27c1609e..22369c9dc1 100644
--- a/eeschema/tools/sch_edit_tool.cpp
+++ b/eeschema/tools/sch_edit_tool.cpp
@@ -175,7 +175,7 @@ TOOL_ACTION EE_ACTIONS::pinTable( "eeschema.InteractiveEdit.pinTable",
 
 TOOL_ACTION EE_ACTIONS::deleteItemCursor( "eeschema.InteractiveEdit.deleteTool",
         AS_GLOBAL, 0, "",
-        _( "Delete Items" ), _( "Delete clicked items" ),
+        _( "Delete Tool" ), _( "Delete clicked items" ),
         delete_xpm, AF_ACTIVATE );
 
 TOOL_ACTION EE_ACTIONS::breakWire( "eeschema.InteractiveEdit.breakWire",
@@ -195,7 +195,8 @@ char g_lastBusEntryShape = '/';
 class SYMBOL_UNIT_MENU : public ACTION_MENU
 {
 public:
-    SYMBOL_UNIT_MENU()
+    SYMBOL_UNIT_MENU() :
+        ACTION_MENU( true )
     {
         SetIcon( component_select_unit_xpm );
         SetTitle( _( "Symbol Unit" ) );
@@ -268,14 +269,14 @@ bool SCH_EDIT_TOOL::Init()
     wxASSERT_MSG( drawingTools, "eeshema.InteractiveDrawing tool is not available" );
 
     auto sheetTool = [ this ] ( const SELECTION& aSel ) {
-        return ( m_frame->GetToolId() == ID_SHEET_TOOL );
+        return ( m_frame->GetCurrentToolName() == EE_ACTIONS::drawSheet.GetName() );
     };
 
     auto anyTextTool = [ this ] ( const SELECTION& aSel ) {
-        return ( m_frame->GetToolId() == ID_LABEL_TOOL
-              || m_frame->GetToolId() == ID_GLOBALLABEL_TOOL
-              || m_frame->GetToolId() == ID_HIERLABEL_TOOL
-              || m_frame->GetToolId() == ID_SCHEMATIC_TEXT_TOOL );
+        return ( m_frame->GetCurrentToolName() == EE_ACTIONS::placeLabel.GetName()
+              || m_frame->GetCurrentToolName() == EE_ACTIONS::placeGlobalLabel.GetName()
+              || m_frame->GetCurrentToolName() == EE_ACTIONS::placeHierLabel.GetName()
+              || m_frame->GetCurrentToolName() == EE_ACTIONS::placeSchematicText.GetName() );
     };
 
     auto duplicateCondition = [] ( const SELECTION& aSel ) {
@@ -1057,16 +1058,18 @@ static bool deleteItem( SCH_BASE_FRAME* aFrame, const VECTOR2D& aPosition )
 
 int SCH_EDIT_TOOL::DeleteItemCursor( const TOOL_EVENT& aEvent )
 {
+    m_frame->SetTool( aEvent.GetCommandStr().get() );
+    m_frame->GetCanvas()->SetCurrentCursor( wxCURSOR_BULLSEYE );
     Activate();
 
     EE_PICKER_TOOL* picker = m_toolMgr->GetTool<EE_PICKER_TOOL>();
     wxCHECK( picker, 0 );
 
-    m_frame->SetToolID( ID_DELETE_TOOL, wxCURSOR_BULLSEYE, _( "Delete item" ) );
     picker->SetClickHandler( std::bind( deleteItem, m_frame, std::placeholders::_1 ) );
     picker->Activate();
     Wait();
 
+    m_frame->GetCanvas()->SetCurrentCursor( wxCURSOR_ARROW );
     return 0;
 }
 
diff --git a/eeschema/tools/sch_edit_tool.h b/eeschema/tools/sch_edit_tool.h
index 59da101186..61503bf33a 100644
--- a/eeschema/tools/sch_edit_tool.h
+++ b/eeschema/tools/sch_edit_tool.h
@@ -60,11 +60,7 @@ public:
 
     int CleanupSheetPins( const TOOL_EVENT& aEvent );
 
-    /**
-     * Function DoDelete()
-     *
-     * Deletes the selected items, or the item under the cursor.
-     */
+    ///> Deletes the selected items, or the item under the cursor.
     int DoDelete( const TOOL_EVENT& aEvent );
 
     ///> Runs the deletion tool.
diff --git a/eeschema/tools/sch_editor_control.cpp b/eeschema/tools/sch_editor_control.cpp
index b254e80d35..eb8f5c893e 100644
--- a/eeschema/tools/sch_editor_control.cpp
+++ b/eeschema/tools/sch_editor_control.cpp
@@ -795,7 +795,7 @@ int SCH_EDITOR_CONTROL::HighlightNetCursor( const TOOL_EVENT& aEvent )
     EE_PICKER_TOOL* picker = m_toolMgr->GetTool<EE_PICKER_TOOL>();
     assert( picker );
 
-    m_frame->SetToolID( ID_HIGHLIGHT_TOOL, wxCURSOR_HAND, _( "Highlight specific net" ) );
+    m_frame->SetTool( aEvent.GetCommandStr().get() );
     picker->SetClickHandler( std::bind( highlightNet, m_toolMgr, std::placeholders::_1 ) );
     picker->Activate();
     Wait();
diff --git a/eeschema/tools/sch_move_tool.cpp b/eeschema/tools/sch_move_tool.cpp
index 8081bb9688..d4d9a311cb 100644
--- a/eeschema/tools/sch_move_tool.cpp
+++ b/eeschema/tools/sch_move_tool.cpp
@@ -64,11 +64,6 @@ SCH_MOVE_TOOL::SCH_MOVE_TOOL() :
 }
 
 
-SCH_MOVE_TOOL::~SCH_MOVE_TOOL()
-{
-}
-
-
 bool SCH_MOVE_TOOL::Init()
 {
     EE_TOOL_BASE::Init();
@@ -83,7 +78,6 @@ bool SCH_MOVE_TOOL::Init()
         return true;
     };
 
-    //
     // Add move actions to the selection tool menu
     //
     CONDITIONAL_MENU& selToolMenu = m_selectionTool->GetToolMenu().GetMenu();
@@ -95,7 +89,6 @@ bool SCH_MOVE_TOOL::Init()
 }
 
 
-
 /* TODO - Tom/Jeff
   - add preferences option "Move origin: always cursor / item origin"
   - add preferences option "Default drag action: drag items / move"
@@ -139,10 +132,7 @@ int SCH_MOVE_TOOL::Main( const TOOL_EVENT& aEvent )
     else
         return 0;
 
-    if( m_isDragOperation )
-        m_frame->SetToolID( ID_SCH_DRAG, wxCURSOR_DEFAULT, _( "Drag Items" ) );
-    else
-        m_frame->SetToolID( ID_SCH_MOVE, wxCURSOR_DEFAULT, _( "Move Items" ) );
+    m_frame->PushTool( aEvent.GetCommandStr().get() );
 
     if( m_moveInProgress )
     {
@@ -349,7 +339,7 @@ int SCH_MOVE_TOOL::Main( const TOOL_EVENT& aEvent )
                 if( item->GetParent() && item->GetParent()->IsSelected() )
                     continue;
 
-                moveItem( item, delta, m_frame->GetToolId() == ID_SCH_DRAG );
+                moveItem( item, delta, m_isDragOperation );
                 updateView( item );
             }
 
@@ -396,7 +386,7 @@ int SCH_MOVE_TOOL::Main( const TOOL_EVENT& aEvent )
                 chain_commands = true;
                 break;
             }
-            else if( evt->Action() == TA_CONTEXT_MENU_CHOICE )
+            else if( evt->Action() == TA_CHOICE_MENU_CHOICE )
             {
                 if( evt->GetCommandId().get() >= ID_POPUP_SCH_SELECT_UNIT_CMP
                     && evt->GetCommandId().get() <= ID_POPUP_SCH_SELECT_UNIT_CMP_MAX )
@@ -439,8 +429,6 @@ int SCH_MOVE_TOOL::Main( const TOOL_EVENT& aEvent )
     if( !chain_commands )
         m_moveOffset = { 0, 0 };
 
-    m_moveInProgress = false;
-    m_frame->SetNoToolSelected();
     m_anchorPos.reset();
 
     for( EDA_ITEM* item : selection )
@@ -470,6 +458,8 @@ int SCH_MOVE_TOOL::Main( const TOOL_EVENT& aEvent )
     }
 
     m_dragAdditions.clear();
+    m_moveInProgress = false;
+    m_frame->PopTool();
 
     return 0;
 }
diff --git a/eeschema/tools/sch_move_tool.h b/eeschema/tools/sch_move_tool.h
index 9b0a8663bc..9de23e889c 100644
--- a/eeschema/tools/sch_move_tool.h
+++ b/eeschema/tools/sch_move_tool.h
@@ -36,7 +36,7 @@ class SCH_MOVE_TOOL : public EE_TOOL_BASE<SCH_EDIT_FRAME>
 {
 public:
     SCH_MOVE_TOOL();
-    ~SCH_MOVE_TOOL();
+    ~SCH_MOVE_TOOL() override { }
 
     /// @copydoc TOOL_INTERACTIVE::Init()
     bool Init() override;
diff --git a/eeschema/tools/sch_wire_bus_tool.cpp b/eeschema/tools/sch_wire_bus_tool.cpp
index 0f3fe20827..733c834b79 100644
--- a/eeschema/tools/sch_wire_bus_tool.cpp
+++ b/eeschema/tools/sch_wire_bus_tool.cpp
@@ -42,62 +42,47 @@
 #include <sch_sheet.h>
 #include <advanced_config.h>
 
-TOOL_ACTION EE_ACTIONS::startWire( "eeschema.WireBusDrawing.startWire",
-        AS_GLOBAL, 0, "",
-        _( "Start Wire" ), _( "Start drawing a wire" ),
-        add_line_xpm, AF_ACTIVATE );
-
-TOOL_ACTION EE_ACTIONS::drawWire( "eeschema.WireBusDrawing.drawWires",
+TOOL_ACTION EE_ACTIONS::drawWire( "eeschema.InteractiveDrawingLineWireBus.drawWires",
         AS_GLOBAL, 
         'W', LEGACY_HK_NAME( "Begin Wire" ),
         _( "Add Wire" ), _( "Add a wire" ),
         add_line_xpm, AF_ACTIVATE );
 
-TOOL_ACTION EE_ACTIONS::startBus( "eeschema.WireBusDrawing.startBus",
-        AS_GLOBAL, 0, "",
-        _( "Start Bus" ), _( "Start drawing a bus" ),
-        add_bus_xpm, AF_ACTIVATE );
-
-TOOL_ACTION EE_ACTIONS::drawBus( "eeschema.WireBusDrawing.drawBusses",
+TOOL_ACTION EE_ACTIONS::drawBus( "eeschema.InteractiveDrawingLineWireBus.drawBusses",
         AS_GLOBAL, 
         'B', LEGACY_HK_NAME( "Begin Bus" ),
         _( "Add Bus" ), _( "Add a bus" ),
         add_bus_xpm, AF_ACTIVATE );
 
-TOOL_ACTION EE_ACTIONS::unfoldBus( "eeschema.WireBusDrawing.unfoldBus",
+TOOL_ACTION EE_ACTIONS::unfoldBus( "eeschema.InteractiveDrawingLineWireBus.unfoldBus",
         AS_GLOBAL, 
         'C', LEGACY_HK_NAME( "Unfold from Bus" ),
         _( "Unfold from Bus" ), _( "Break a wire out of a bus" ),
         nullptr, AF_ACTIVATE );
 
-TOOL_ACTION EE_ACTIONS::startLines( "eeschema.WireBusDrawing.startLines",
-        AS_GLOBAL, 0,  "",
-        _( "Begin Lines" ), _( "Start drawing connected graphic lines" ),
-        add_line_xpm, AF_ACTIVATE );
-
-TOOL_ACTION EE_ACTIONS::drawLines( "eeschema.WireBusDrawing.drawLines",
+TOOL_ACTION EE_ACTIONS::drawLines( "eeschema.InteractiveDrawingLineWireBus.drawLines",
         AS_GLOBAL, 
         'I', LEGACY_HK_NAME( "Add Graphic PolyLine" ),
         _( "Add Lines" ), _( "Add connected graphic lines" ),
         add_dashed_line_xpm, AF_ACTIVATE );
 
-TOOL_ACTION EE_ACTIONS::finishLineWireOrBus( "eeschema.WireBusDrawing.finishLineWireOrBus",
+TOOL_ACTION EE_ACTIONS::finishLineWireOrBus( "eeschema.InteractiveDrawingLineWireBus.finish",
         AS_GLOBAL, 
         'K', LEGACY_HK_NAME( "End Line Wire Bus" ),
         _( "Finish Wire or Bus" ), _( "Complete drawing at current segment" ),
         checked_ok_xpm, AF_NONE );
 
-TOOL_ACTION EE_ACTIONS::finishWire( "eeschema.WireBusDrawing.finishWire",
+TOOL_ACTION EE_ACTIONS::finishWire( "eeschema.InteractiveDrawingLineWireBus.finishWire",
         AS_GLOBAL, 0,  "",
         _( "Finish Wire" ), _( "Complete wire with current segment" ),
         checked_ok_xpm, AF_NONE );
 
-TOOL_ACTION EE_ACTIONS::finishBus( "eeschema.WireBusDrawing.finishBus",
+TOOL_ACTION EE_ACTIONS::finishBus( "eeschema.InteractiveDrawingLineWireBus.finishBus",
         AS_GLOBAL, 0,  "",
         _( "Finish Bus" ), _( "Complete bus with current segment" ),
         checked_ok_xpm, AF_NONE );
 
-TOOL_ACTION EE_ACTIONS::finishLine( "eeschema.WireBusDrawing.finishLine",
+TOOL_ACTION EE_ACTIONS::finishLine( "eeschema.InteractiveDrawingLineWireBus.finishLine",
         AS_GLOBAL, 0,  "",
         _( "Finish Lines" ), _( "Complete connected lines with current segment" ),
         checked_ok_xpm, AF_NONE );
@@ -107,6 +92,7 @@ class BUS_UNFOLD_MENU : public ACTION_MENU
 {
 public:
     BUS_UNFOLD_MENU() :
+        ACTION_MENU( true ),
         m_showTitle( false )
     {
         SetIcon( add_line2bus_xpm );
@@ -176,7 +162,7 @@ private:
 
             if( member->Type() == CONNECTION_BUS )
             {
-                ACTION_MENU* submenu = new ACTION_MENU;
+                ACTION_MENU* submenu = new ACTION_MENU( true );
                 AppendSubMenu( submenu, name );
 
                 for( const auto& sub_member : member->Members() )
@@ -197,7 +183,7 @@ private:
 
 
 SCH_WIRE_BUS_TOOL::SCH_WIRE_BUS_TOOL() :
-    EE_TOOL_BASE<SCH_EDIT_FRAME>( "eeschema.WireBusDrawing" )
+    EE_TOOL_BASE<SCH_EDIT_FRAME>( "eeschema.InteractiveDrawingLineWireBus" )
 {
     m_busUnfold = {};
 }
@@ -215,11 +201,12 @@ bool SCH_WIRE_BUS_TOOL::Init()
     EE_TOOL_BASE::Init();
 
     auto wireOrBusTool = [ this ] ( const SELECTION& aSel ) {
-        return ( m_frame->GetToolId() == ID_WIRE_TOOL || m_frame->GetToolId() == ID_BUS_TOOL );
+        return ( m_frame->GetCurrentToolName() == EE_ACTIONS::drawWire.GetName()
+              || m_frame->GetCurrentToolName() == EE_ACTIONS::drawBus.GetName() );
     };
 
     auto lineTool = [ this ] ( const SELECTION& aSel ) {
-        return ( m_frame->GetToolId() == ID_SCHEMATIC_LINE_TOOL );
+        return ( m_frame->GetCurrentToolName() == EE_ACTIONS::drawLines.GetName() );
     };
 
     auto belowRootSheetCondition = [] ( const SELECTION& aSel ) {
@@ -230,15 +217,14 @@ bool SCH_WIRE_BUS_TOOL::Init()
 
     auto& ctxMenu = m_menu.GetMenu();
 
-    //
     // Build the tool menu
     //
-    ctxMenu.AddItem( EE_ACTIONS::leaveSheet,    belowRootSheetCondition, 2 );
+    ctxMenu.AddItem( EE_ACTIONS::leaveSheet,         belowRootSheetCondition, 2 );
 
     ctxMenu.AddSeparator( E_C::ShowAlways, 10 );
-    ctxMenu.AddItem( EE_ACTIONS::startWire,          wireOrBusTool && E_C::Idle, 10 );
-    ctxMenu.AddItem( EE_ACTIONS::startBus,           wireOrBusTool && E_C::Idle, 10 );
-    ctxMenu.AddItem( EE_ACTIONS::startLines,         lineTool && E_C::Idle, 10 );
+    ctxMenu.AddItem( EE_ACTIONS::drawWire,           wireOrBusTool && E_C::Idle, 10 );
+    ctxMenu.AddItem( EE_ACTIONS::drawBus,            wireOrBusTool && E_C::Idle, 10 );
+    ctxMenu.AddItem( EE_ACTIONS::drawLines,          lineTool && E_C::Idle, 10 );
     ctxMenu.AddItem( EE_ACTIONS::finishWire,         IsDrawingWire, 10 );
     ctxMenu.AddItem( EE_ACTIONS::finishBus,          IsDrawingBus, 10 );
     ctxMenu.AddItem( EE_ACTIONS::finishLine,         IsDrawingLine, 10 );
@@ -246,13 +232,13 @@ bool SCH_WIRE_BUS_TOOL::Init()
     std::shared_ptr<BUS_UNFOLD_MENU> busUnfoldMenu = std::make_shared<BUS_UNFOLD_MENU>();
     busUnfoldMenu->SetTool( this );
     m_menu.AddSubMenu( busUnfoldMenu );
-    ctxMenu.AddMenu( busUnfoldMenu.get(), EE_CONDITIONS::Idle, 10 );
+    ctxMenu.AddMenu( busUnfoldMenu.get(),            EE_CONDITIONS::Idle, 10 );
 
     ctxMenu.AddSeparator( wireOrBusTool && EE_CONDITIONS::Idle, 100 );
-    ctxMenu.AddItem( EE_ACTIONS::addJunction,        wireOrBusTool && E_C::Idle, 100 );
-    ctxMenu.AddItem( EE_ACTIONS::addLabel,           wireOrBusTool && E_C::Idle, 100 );
-    ctxMenu.AddItem( EE_ACTIONS::addGlobalLabel,     wireOrBusTool && E_C::Idle, 100 );
-    ctxMenu.AddItem( EE_ACTIONS::addHierLabel,       wireOrBusTool && E_C::Idle, 100 );
+    ctxMenu.AddItem( EE_ACTIONS::placeJunction,      wireOrBusTool && E_C::Idle, 100 );
+    ctxMenu.AddItem( EE_ACTIONS::placeLabel,         wireOrBusTool && E_C::Idle, 100 );
+    ctxMenu.AddItem( EE_ACTIONS::placeGlobalLabel,   wireOrBusTool && E_C::Idle, 100 );
+    ctxMenu.AddItem( EE_ACTIONS::placeHierLabel,     wireOrBusTool && E_C::Idle, 100 );
     ctxMenu.AddItem( EE_ACTIONS::breakWire,          wireOrBusTool && E_C::Idle, 100 );
     ctxMenu.AddItem( EE_ACTIONS::breakBus,           wireOrBusTool && E_C::Idle, 100 );
 
@@ -260,7 +246,6 @@ bool SCH_WIRE_BUS_TOOL::Init()
     ctxMenu.AddItem( EE_ACTIONS::selectNode,         wireOrBusTool && E_C::Idle, 200 );
     ctxMenu.AddItem( EE_ACTIONS::selectConnection,   wireOrBusTool && E_C::Idle, 200 );
 
-    //
     // Add bus unfolding to the selection tool
     //
     CONDITIONAL_MENU& selToolMenu = m_selectionTool->GetToolMenu().GetMenu();
@@ -268,7 +253,7 @@ bool SCH_WIRE_BUS_TOOL::Init()
     std::shared_ptr<BUS_UNFOLD_MENU> selBusUnfoldMenu = std::make_shared<BUS_UNFOLD_MENU>();
     selBusUnfoldMenu->SetTool( m_selectionTool );
     m_selectionTool->GetToolMenu().AddSubMenu( selBusUnfoldMenu );
-    selToolMenu.AddMenu( selBusUnfoldMenu.get(), busSelection && E_C::Idle, 100 );
+    selToolMenu.AddMenu( selBusUnfoldMenu.get(),     busSelection && E_C::Idle, 100 );
 
     return true;
 }
@@ -310,67 +295,43 @@ bool SCH_WIRE_BUS_TOOL::IsDrawingLineWireOrBus( const SELECTION& aSelection )
 }
 
 
-/*
- * Immediate action: start drawing a wire.  Does not select the wire tool.
- */
-int SCH_WIRE_BUS_TOOL::StartWire( const TOOL_EVENT& aEvent )
-{
-    m_toolMgr->RunAction( EE_ACTIONS::clearSelection, true );
-
-    Activate();
-
-    getViewControls()->WarpCursor( getViewControls()->GetCursorPosition(), true );
-    SCH_LINE* segment = startSegments( LAYER_WIRE, getViewControls()->GetCursorPosition() );
-    return doDrawSegments( LAYER_WIRE, segment );
-}
-
-
-/*
- * Tool action: first call selects the tool; subsequent calls start wires.
- */
 int SCH_WIRE_BUS_TOOL::DrawWires( const TOOL_EVENT& aEvent )
 {
-    if( m_frame->GetToolId() == ID_WIRE_TOOL )
-        return StartWire( aEvent );
-    else
+    if( aEvent.HasPosition() )  // Start drawing
     {
-        m_frame->SetToolID( ID_WIRE_TOOL, wxCURSOR_PENCIL, _( "Add wire" ) );
-        m_toolMgr->RunAction( EE_ACTIONS::clearSelection, true );
+        getViewControls()->WarpCursor( getViewControls()->GetCursorPosition(), true );
 
-        return doDrawSegments( LAYER_WIRE, nullptr );
+        m_frame->PushTool( aEvent.GetCommandStr().get() );
+        doDrawSegments( LAYER_WIRE, nullptr, true );
+        m_frame->PopTool();
     }
+    else                        // Invoke the tool
+    {
+        m_frame->SetTool( aEvent.GetCommandStr().get() );
+        doDrawSegments( LAYER_WIRE, nullptr, false );
+    }
+
+    return 0;
 }
 
 
-/*
- * Immediate action: start drawing a bus.  Does not select the bus tool.
- */
-int SCH_WIRE_BUS_TOOL::StartBus( const TOOL_EVENT& aEvent )
-{
-    m_toolMgr->RunAction( EE_ACTIONS::clearSelection, true );
-
-    Activate();
-
-    getViewControls()->WarpCursor( getViewControls()->GetCursorPosition(), true );
-    SCH_LINE* segment = startSegments( LAYER_BUS, getViewControls()->GetCursorPosition() );
-    return doDrawSegments( LAYER_BUS, segment );
-}
-
-
-/*
- * Tool action: first call selects the tool; subsequent calls start busses.
- */
 int SCH_WIRE_BUS_TOOL::DrawBusses( const TOOL_EVENT& aEvent )
 {
-    if( m_frame->GetToolId() == ID_BUS_TOOL )
-        return StartBus( aEvent );
-    else
+    if( aEvent.HasPosition() )  // Start drawing
     {
-        m_frame->SetToolID( ID_BUS_TOOL, wxCURSOR_PENCIL, _( "Add bus" ) );
-        m_toolMgr->RunAction( EE_ACTIONS::clearSelection, true );
+        getViewControls()->WarpCursor( getViewControls()->GetCursorPosition(), true );
 
-        return doDrawSegments( LAYER_BUS, nullptr );
+        m_frame->PushTool( aEvent.GetCommandStr().get() );
+        doDrawSegments( LAYER_BUS, nullptr, true );
+        m_frame->PopTool();
     }
+    else                        // Invoke the tool
+    {
+        m_frame->SetTool( aEvent.GetCommandStr().get() );
+        doDrawSegments( LAYER_BUS, nullptr, false );
+    }
+
+    return 0;
 }
 
 
@@ -399,7 +360,7 @@ int SCH_WIRE_BUS_TOOL::UnfoldBus( const TOOL_EVENT& aEvent )
 
         while( OPT_TOOL_EVENT evt = Wait() )
         {
-            if( evt->Action() == TA_CONTEXT_MENU_CHOICE )
+            if( evt->Action() == TA_CHOICE_MENU_CHOICE )
             {
                 OPT<int> id = evt->GetCommandId();
 
@@ -419,15 +380,12 @@ int SCH_WIRE_BUS_TOOL::UnfoldBus( const TOOL_EVENT& aEvent )
 
     // If we have an unfolded wire to draw, then draw it
     if( segment )
-        return doDrawSegments( LAYER_WIRE, segment );
+    {
+        m_frame->PushTool( aEvent.GetCommandStr().get() );
+        doDrawSegments( LAYER_WIRE, segment, true );
+        m_frame->PopTool();
+    }
 
-    // If we came from one of our tools then re-enter it in the idle state
-    if( m_frame->GetToolId() == ID_WIRE_TOOL )
-        return doDrawSegments( LAYER_WIRE, nullptr );
-    else if( m_frame->GetToolId() == ID_BUS_TOOL )
-        return doDrawSegments( LAYER_BUS, nullptr );
-
-    m_frame->SetNoToolSelected();
     return 0;
 }
 
@@ -455,33 +413,23 @@ SCH_LINE* SCH_WIRE_BUS_TOOL::doUnfoldBus( const wxString& aNet )
 }
 
 
-/*
- * Immediate action: start drawing a line.  Does not select the line tool.
- */
-int SCH_WIRE_BUS_TOOL::StartLine( const TOOL_EVENT& aEvent)
-{
-    m_toolMgr->RunAction( EE_ACTIONS::clearSelection, true );
-
-    getViewControls()->WarpCursor( getViewControls()->GetCursorPosition(), true );
-    SCH_LINE* segment = startSegments( LAYER_NOTES, getViewControls()->GetCursorPosition() );
-    return doDrawSegments( LAYER_BUS, segment );
-}
-
-
-/*
- * Tool action: first call selects the tool; subsequent calls start lines.
- */
 int SCH_WIRE_BUS_TOOL::DrawLines( const TOOL_EVENT& aEvent)
 {
-    if( m_frame->GetToolId() == ID_SCHEMATIC_LINE_TOOL )
-        return StartLine( aEvent );
-    else
+    if( aEvent.HasPosition() )  // Start drawing
     {
-        m_frame->SetToolID( ID_SCHEMATIC_LINE_TOOL, wxCURSOR_PENCIL, _( "Add lines" ) );
-        m_toolMgr->RunAction( EE_ACTIONS::clearSelection, true );
+        getViewControls()->WarpCursor( getViewControls()->GetCursorPosition(), true );
 
-        return doDrawSegments( LAYER_NOTES, nullptr );
+        m_frame->PushTool( aEvent.GetCommandStr().get() );
+        doDrawSegments( LAYER_NOTES, nullptr, true );
+        m_frame->PopTool();
     }
+    else                        // Invoke the tool
+    {
+        m_frame->SetTool( aEvent.GetCommandStr().get() );
+        doDrawSegments( LAYER_NOTES, nullptr, false );
+    }
+
+    return 0;
 }
 
 
@@ -577,16 +525,19 @@ static void computeBreakPoint( SCH_SCREEN* aScreen, SCH_LINE* aSegment, wxPoint&
 }
 
 
-int SCH_WIRE_BUS_TOOL::doDrawSegments( int aType, SCH_LINE* aSegment )
+int SCH_WIRE_BUS_TOOL::doDrawSegments( int aType, SCH_LINE* aSegment, bool aImmediateMode )
 {
     bool        forceHV = m_frame->GetForceHVLines();
     SCH_SCREEN* screen = m_frame->GetScreen();
     wxPoint     cursorPos;
 
+    m_toolMgr->RunAction( EE_ACTIONS::clearSelection, true );
     getViewControls()->ShowCursor( true );
 
-    if( aSegment == nullptr )
-        Activate();
+    Activate();
+
+    if( aImmediateMode && !aSegment )
+        m_toolMgr->RunAction( ACTIONS::cursorClick );
 
     // Main loop: keep receiving events
     while( OPT_TOOL_EVENT evt = Wait() )
@@ -618,21 +569,12 @@ int SCH_WIRE_BUS_TOOL::doDrawSegments( int aType, SCH_LINE* aSegment )
                 m_view->ClearPreview();
                 m_view->ShowPreview( false );
 
-                if( !evt->IsActivate() )
+                if( !evt->IsActivate() && !aImmediateMode )
                     continue;
             }
 
-            if( ( evt->IsAction( &EE_ACTIONS::drawWire ) && aType == LAYER_WIRE )
-                    || ( evt->IsAction( &EE_ACTIONS::drawBus ) && aType == LAYER_BUS )
-                    || ( evt->IsAction( &EE_ACTIONS::unfoldBus ) && aType == LAYER_WIRE ) )
-            {
-                // Don't reset tool.  If we do the next command will think it needs to
-                // re-select the tool rather than start a wire or bus.
-            }
-            else
-            {
-                m_frame->SetNoToolSelected();
-            }
+            if( !evt->IsActivate() && !aImmediateMode )
+                m_frame->PopTool();
 
             break;
         }
@@ -650,7 +592,7 @@ int SCH_WIRE_BUS_TOOL::doDrawSegments( int aType, SCH_LINE* aSegment )
                 aSegment = nullptr;
             }
 
-            if( m_frame->GetToolId() == ID_NO_TOOL_SELECTED )
+            if( aImmediateMode )
                 break;
         }
         //------------------------------------------------------------------------
@@ -682,7 +624,7 @@ int SCH_WIRE_BUS_TOOL::doDrawSegments( int aType, SCH_LINE* aSegment )
                     finishSegments();
                     aSegment = nullptr;
 
-                    if( m_frame->GetToolId() == ID_NO_TOOL_SELECTED )
+                    if( aImmediateMode )
                         break;
                 }
                 else
@@ -707,7 +649,7 @@ int SCH_WIRE_BUS_TOOL::doDrawSegments( int aType, SCH_LINE* aSegment )
                 finishSegments();
                 aSegment = nullptr;
 
-                if( m_frame->GetToolId() == ID_NO_TOOL_SELECTED )
+                if( aImmediateMode )
                     break;
             }
         }
@@ -777,7 +719,7 @@ int SCH_WIRE_BUS_TOOL::doDrawSegments( int aType, SCH_LINE* aSegment )
 
             m_menu.ShowContextMenu( m_selectionTool->GetSelection() );
         }
-        else if( evt->Category() == TC_COMMAND && evt->Action() == TA_CONTEXT_MENU_CHOICE )
+        else if( evt->Category() == TC_COMMAND && evt->Action() == TA_CHOICE_MENU_CHOICE )
         {
             if( evt->GetCommandId().get() >= ID_POPUP_SCH_UNFOLD_BUS
                 && evt->GetCommandId().get() <= ID_POPUP_SCH_UNFOLD_BUS_END )
@@ -996,9 +938,5 @@ void SCH_WIRE_BUS_TOOL::setTransitions()
     Go( &SCH_WIRE_BUS_TOOL::DrawBusses,     EE_ACTIONS::drawBus.MakeEvent() );
     Go( &SCH_WIRE_BUS_TOOL::DrawLines,      EE_ACTIONS::drawLines.MakeEvent() );
 
-    Go( &SCH_WIRE_BUS_TOOL::StartWire,      EE_ACTIONS::startWire.MakeEvent() );
-    Go( &SCH_WIRE_BUS_TOOL::StartBus,       EE_ACTIONS::startBus.MakeEvent() );
-    Go( &SCH_WIRE_BUS_TOOL::StartLine,      EE_ACTIONS::startLines.MakeEvent() );
-
     Go( &SCH_WIRE_BUS_TOOL::UnfoldBus,      EE_ACTIONS::unfoldBus.MakeEvent() );
 }
diff --git a/eeschema/tools/sch_wire_bus_tool.h b/eeschema/tools/sch_wire_bus_tool.h
index ba7ede4e61..e9fdb99137 100644
--- a/eeschema/tools/sch_wire_bus_tool.h
+++ b/eeschema/tools/sch_wire_bus_tool.h
@@ -65,18 +65,6 @@ public:
     /// @copydoc TOOL_INTERACTIVE::Init()
     bool Init() override;
 
-    /*
-     * These are the immediate actions.  They start drawing at the mouse location.  They
-     * do not select the tool.
-     */
-    int StartWire( const TOOL_EVENT& aEvent );
-    int StartBus( const TOOL_EVENT& aEvent );
-    int StartLine( const TOOL_EVENT& aEvent );
-
-    /*
-     * These are the two-step actions.  They select the tool on the first call, and start
-     * drawing on subsequent calls.
-     */
     int DrawWires( const TOOL_EVENT& aEvent );
     int DrawBusses( const TOOL_EVENT& aEvent );
     int DrawLines( const TOOL_EVENT& aEvent );
@@ -90,7 +78,7 @@ public:
     static bool IsDrawingLineWireOrBus( const SELECTION& aSelection );
 
 private:
-    int doDrawSegments( int aType, SCH_LINE* aSegment );
+    int doDrawSegments( int aType, SCH_LINE* aSegment, bool aImmediateMode );
     SCH_LINE* startSegments( int aType, const VECTOR2D& aPos );
     SCH_LINE* doUnfoldBus( const wxString& aNet );
     void finishSegments();
diff --git a/gerbview/menubar.cpp b/gerbview/menubar.cpp
index cd94e1dd47..23ee2b8adc 100644
--- a/gerbview/menubar.cpp
+++ b/gerbview/menubar.cpp
@@ -56,7 +56,7 @@ void GERBVIEW_FRAME::ReCreateMenuBar()
     if( openRecentGbrMenu )
         Kiface().GetFileHistory().RemoveMenu( openRecentGbrMenu );
 
-    openRecentGbrMenu = new ACTION_MENU();
+    openRecentGbrMenu = new ACTION_MENU( false );
     openRecentGbrMenu->SetTool( selTool );
     openRecentGbrMenu->SetTitle( _( "Open Recent Gerber" ) );
     openRecentGbrMenu->SetIcon( recent_xpm );
@@ -68,7 +68,7 @@ void GERBVIEW_FRAME::ReCreateMenuBar()
     if( openRecentDrlMenu )
         m_drillFileHistory.RemoveMenu( openRecentDrlMenu );
 
-    openRecentDrlMenu = new ACTION_MENU();
+    openRecentDrlMenu = new ACTION_MENU( false );
     openRecentDrlMenu->SetTool( selTool );
     openRecentDrlMenu->SetTitle( _( "Open Recent Drill File" ) );
     openRecentDrlMenu->SetIcon( recent_xpm );
@@ -80,7 +80,7 @@ void GERBVIEW_FRAME::ReCreateMenuBar()
     if( openRecentJobMenu )
         m_jobFileHistory.RemoveMenu( openRecentJobMenu );
 
-    openRecentJobMenu = new ACTION_MENU();
+    openRecentJobMenu = new ACTION_MENU( false );
     openRecentJobMenu->SetTool( selTool );
     openRecentJobMenu->SetTitle( _( "Open Recent Job" ) );
 
@@ -92,7 +92,7 @@ void GERBVIEW_FRAME::ReCreateMenuBar()
     if( openRecentZipMenu )
         m_zipFileHistory.RemoveMenu( openRecentZipMenu );
 
-    openRecentZipMenu = new ACTION_MENU();
+    openRecentZipMenu = new ACTION_MENU( false );
     openRecentZipMenu->SetTool( selTool );
     openRecentZipMenu->SetTitle( _( "Open Recent Zip" ) );
     openRecentZipMenu->SetIcon( recent_xpm );
@@ -223,7 +223,7 @@ void GERBVIEW_FRAME::ReCreateMenuBar()
 
     //-- Tools menu -------------------------------------------------------
     //
-    ACTION_MENU* toolsMenu = new ACTION_MENU();
+    ACTION_MENU* toolsMenu = new ACTION_MENU( false );
 
     toolsMenu->Add( _( "&List DCodes..." ), _( "List D-codes defined in Gerber files" ),
                     ID_GERBVIEW_SHOW_LIST_DCODES, show_dcodenumber_xpm );
diff --git a/gerbview/tools/gerbview_selection_tool.cpp b/gerbview/tools/gerbview_selection_tool.cpp
index 8fcf5a38f5..0a9d5ef106 100644
--- a/gerbview/tools/gerbview_selection_tool.cpp
+++ b/gerbview/tools/gerbview_selection_tool.cpp
@@ -59,10 +59,11 @@ TOOL_ACTION GERBVIEW_ACTIONS::selectionClear( "gerbview.InteractiveSelection.Cle
         AS_GLOBAL );
 
 
-class HIGHLIGHT_MENU: public ACTION_MENU
+class HIGHLIGHT_MENU : public ACTION_MENU
 {
 public:
-    HIGHLIGHT_MENU()
+    HIGHLIGHT_MENU() :
+        ACTION_MENU( true )
     {
         SetIcon( net_highlight_schematic_xpm );
         SetTitle( _( "Highlight" ) );
@@ -240,7 +241,7 @@ int GERBVIEW_SELECTION_TOOL::Main( const TOOL_EVENT& aEvent )
             clearSelection();
         }
 
-        else if( evt->Action() == TA_CONTEXT_MENU_CLOSED )
+        else if( evt->Action() == TA_CHOICE_MENU_CLOSED )
         {
             m_menu.CloseContextMenu( evt );
         }
@@ -601,7 +602,7 @@ EDA_ITEM* GERBVIEW_SELECTION_TOOL::disambiguationMenu( GERBER_COLLECTOR* aCollec
 {
     EDA_ITEM* current = NULL;
     KIGFX::VIEW_GROUP highlightGroup;
-    ACTION_MENU menu;
+    ACTION_MENU menu( true );
 
     highlightGroup.SetLayer( LAYER_SELECT_OVERLAY );
     getView()->Add( &highlightGroup );
@@ -623,7 +624,7 @@ EDA_ITEM* GERBVIEW_SELECTION_TOOL::disambiguationMenu( GERBER_COLLECTOR* aCollec
 
     while( OPT_TOOL_EVENT evt = Wait() )
     {
-        if( evt->Action() == TA_CONTEXT_MENU_UPDATE )
+        if( evt->Action() == TA_CHOICE_MENU_UPDATE )
         {
             if( current )
             {
@@ -649,7 +650,7 @@ EDA_ITEM* GERBVIEW_SELECTION_TOOL::disambiguationMenu( GERBER_COLLECTOR* aCollec
                 current = NULL;
             }
         }
-        else if( evt->Action() == TA_CONTEXT_MENU_CHOICE )
+        else if( evt->Action() == TA_CHOICE_MENU_CHOICE )
         {
             OPT<int> id = evt->GetCommandId();
 
diff --git a/include/eda_draw_frame.h b/include/eda_draw_frame.h
index 1739dc0407..8540cb0cf1 100644
--- a/include/eda_draw_frame.h
+++ b/include/eda_draw_frame.h
@@ -84,7 +84,6 @@ class EDA_DRAW_FRAME : public KIWAY_PLAYER
 {
     ///< Id of active button on the vertical toolbar.
     int                 m_toolId;
-    wxString            m_toolMsg;
 
     BASE_SCREEN*        m_currentScreen;      ///< current used SCREEN
 
@@ -117,8 +116,12 @@ protected:
     TOOL_DISPATCHER* m_toolDispatcher;
 
     /// Tool ID of previously active draw tool bar button.
-    int              m_lastDrawToolId;
+    int              m_lastDrawToolId;  // JEY TODO: remove this; it doesn't work in modern toolset anyway
 
+    std::deque<std::string> m_toolStack;    // stack of user-level "tools".  Used to temporarily
+                                            // invoke an immediate-mode action.  Note that these
+                                            // are "tools" in the UI sense, which are actually
+                                            // TOOL_ACTIONs internally
 
     bool             m_showBorderAndTitleBlock;   /// Show the worksheet (border and title block).
     long             m_firstRunDialogSetting;     /// Show first run dialog on startup
@@ -300,6 +303,16 @@ public:
     virtual void ReCreateVToolbar() = 0;
     virtual void ReCreateAuxiliaryToolbar() { }
 
+    /**
+     * The definition of "tool" is different at the user level.  The implementation uses
+     * a single TOOL_BASE derived class to implement several user "tools", such as rectangle
+     * and circle, or wire and bus.  So each user-level tool is actually a TOOL_ACTION.
+     */
+    virtual void SetTool( const std::string& actionName );
+    virtual void PushTool( const std::string& actionName );
+    virtual void PopTool();
+    virtual void ClearToolStack();
+
     /**
      * Set the tool command ID to \a aId and sets the cursor to \a aCursor.
      *
@@ -467,7 +480,6 @@ public:
                          COLOR4D aColor = COLOR4D::UNSPECIFIED );
 
     void            DisplayToolMsg( const wxString& msg );
-    wxString        GetToolMsg() { return m_toolMsg; }
 
     /**
      * Called when modifying the page settings.
diff --git a/include/tool/action_menu.h b/include/tool/action_menu.h
index 8f53378a16..9bd35bd5f5 100644
--- a/include/tool/action_menu.h
+++ b/include/tool/action_menu.h
@@ -44,9 +44,9 @@ class ACTION_MENU : public wxMenu
 {
 public:
     ///> Default constructor
-    ACTION_MENU();
+    ACTION_MENU( bool isContextMenu );
 
-    virtual ~ACTION_MENU();
+    ~ACTION_MENU() override;
 
     ACTION_MENU( const ACTION_MENU& aMenu ) = delete;
     ACTION_MENU& operator=( const ACTION_MENU& aMenu ) = delete;
@@ -209,15 +209,17 @@ protected:
     ///> Checks if any of submenus contains a TOOL_ACTION with a specific ID.
     OPT_TOOL_EVENT findToolAction( int aId );
 
-    ///> Menu requires updating before display.
-    bool m_dirty;
+    bool m_dirty;               // Menu requires update before display
 
-    ///> Flag indicating that the menu title was set up.
     bool m_titleDisplayed;
+    bool m_isContextMenu;
 
     ///> Menu title
     wxString m_title;
 
+    ///> Optional icon
+    const BITMAP_OPAQUE* m_icon;
+
     ///> Stores the id number of selected item.
     int m_selected;
 
@@ -233,9 +235,6 @@ protected:
     ///> List of submenus.
     std::list<ACTION_MENU*> m_submenus;
 
-    ///> Optional icon
-    const BITMAP_OPAQUE* m_icon;
-
     friend class TOOL_INTERACTIVE;
 };
 
diff --git a/include/tool/conditional_menu.h b/include/tool/conditional_menu.h
index f15ea6b052..b9a86cb340 100644
--- a/include/tool/conditional_menu.h
+++ b/include/tool/conditional_menu.h
@@ -240,10 +240,6 @@ private:
     ///> Inserts the entry, preserving the requested order.
     void addEntry( ENTRY aEntry );
 
-    ///> Context menus include only items that resolve to true;
-    ///> Regular menus enable only menu items that resolve to true.
-    bool             m_isContextMenu;
-
     ///> List of all menu entries.
     std::list<ENTRY> m_entries;
 };
diff --git a/include/tool/tool_event.h b/include/tool/tool_event.h
index 48f7e089b8..f313389d94 100644
--- a/include/tool/tool_event.h
+++ b/include/tool/tool_event.h
@@ -88,16 +88,16 @@ enum TOOL_ACTIONS
 
     // Context menu update. Issued whenever context menu is open and the user hovers the mouse
     // over one of choices. Used in dynamic highligting in disambiguation menu
-    TA_CONTEXT_MENU_UPDATE  = 0x4000,
+    TA_CHOICE_MENU_UPDATE   = 0x4000,
 
     // Context menu choice. Sent if the user picked something from the context menu or
     // closed it without selecting anything.
-    TA_CONTEXT_MENU_CHOICE  = 0x8000,
+    TA_CHOICE_MENU_CHOICE   = 0x8000,
 
     // Context menu is closed, no matter whether anything has been chosen or not.
-    TA_CONTEXT_MENU_CLOSED  = 0x10000,
+    TA_CHOICE_MENU_CLOSED   = 0x10000,
 
-    TA_CONTEXT_MENU = TA_CONTEXT_MENU_UPDATE | TA_CONTEXT_MENU_CHOICE | TA_CONTEXT_MENU_CLOSED,
+    TA_CHOICE_MENU = TA_CHOICE_MENU_UPDATE | TA_CHOICE_MENU_CHOICE | TA_CHOICE_MENU_CLOSED,
 
     // This event is sent *before* undo/redo command is performed.
     TA_UNDO_REDO_PRE        = 0x20000,
@@ -183,10 +183,13 @@ public:
         m_mouseButtons( 0 ),
         m_keyCode( 0 ),
         m_modifiers( 0 ),
-        m_param( aParameter ) {}
+        m_param( aParameter )
+    {
+        m_hasPosition = ( aCategory == TC_MOUSE || aCategory == TC_COMMAND );
+    }
 
     TOOL_EVENT( TOOL_EVENT_CATEGORY aCategory, TOOL_ACTIONS aAction, int aExtraParam,
-            TOOL_ACTION_SCOPE aScope = AS_GLOBAL, void* aParameter = NULL ) :
+            TOOL_ACTION_SCOPE aScope = AS_GLOBAL, void* aParameter = nullptr ) :
         m_category( aCategory ),
         m_actions( aAction ),
         m_scope( aScope ),
@@ -212,11 +215,13 @@ public:
         {
             m_modifiers = aExtraParam & MD_MODIFIER_MASK;
         }
+
+        m_hasPosition = ( aCategory == TC_MOUSE || aCategory == TC_COMMAND );
     }
 
     TOOL_EVENT( TOOL_EVENT_CATEGORY aCategory, TOOL_ACTIONS aAction,
             const std::string& aExtraParam, TOOL_ACTION_SCOPE aScope = AS_GLOBAL,
-            void* aParameter = NULL ) :
+            void* aParameter = nullptr ) :
         m_category( aCategory ),
         m_actions( aAction ),
         m_scope( aScope ),
@@ -227,25 +232,20 @@ public:
     {
         if( aCategory == TC_COMMAND || aCategory == TC_MESSAGE )
             m_commandStr = aExtraParam;
+
+        m_hasPosition = ( aCategory == TC_MOUSE || aCategory == TC_COMMAND );
     }
 
     ///> Returns the category (eg. mouse/keyboard/action) of an event..
-    TOOL_EVENT_CATEGORY Category() const
-    {
-        return m_category;
-    }
+    TOOL_EVENT_CATEGORY Category() const { return m_category; }
 
     ///> Returns more specific information about the type of an event.
-    TOOL_ACTIONS Action() const
-    {
-        return m_actions;
-    }
+    TOOL_ACTIONS Action() const { return m_actions; }
 
-    ///> Returns if it this event has a valid position (true for mouse events)
-    bool HasPosition() const
-    {
-        return m_category == TC_MOUSE || m_category == TC_COMMAND;
-    }
+    ///> Returns if it this event has a valid position (true for mouse events and context-menu
+    ///> or hotkey-based command events)
+    bool HasPosition() const { return m_hasPosition; }
+    void SetHasPosition( bool aHasPosition ) { m_hasPosition = aHasPosition; }
 
     ///> Returns information about difference between current mouse cursor position and the place
     ///> where dragging has started.
@@ -307,9 +307,9 @@ public:
         return m_actions & ( TA_UNDO_REDO_PRE | TA_UNDO_REDO_POST );
     }
 
-    bool IsMenu() const
+    bool IsChoiceMenu() const
     {
-        return m_actions & TA_CONTEXT_MENU;
+        return m_actions & TA_CHOICE_MENU;
     }
 
     ///> Returns information about key modifiers state (Ctrl, Alt, etc.)
@@ -456,6 +456,7 @@ private:
     TOOL_EVENT_CATEGORY m_category;
     TOOL_ACTIONS m_actions;
     TOOL_ACTION_SCOPE m_scope;
+    bool m_hasPosition;
 
     ///> Difference between mouse cursor position and
     ///> the point where dragging event has started
@@ -518,9 +519,11 @@ public:
 
     OPT<const TOOL_EVENT&> Matches( const TOOL_EVENT& aEvent ) const
     {
-        for( const_iterator i = m_events.begin(); i != m_events.end(); ++i )
-            if( i->Matches( aEvent ) )
-                return *i;
+        for( const TOOL_EVENT& event : m_events )
+        {
+            if( event.Matches( aEvent ) )
+                return event;
+        }
 
         return OPT<const TOOL_EVENT&>();
     }
@@ -569,11 +572,8 @@ public:
     {
         m_events.clear();
 
-        for( std::deque<TOOL_EVENT>::const_iterator i = aEventList.m_events.begin();
-             i != aEventList.m_events.end(); ++i )
-        {
-            m_events.push_back( *i );
-        }
+        for( const TOOL_EVENT& event : aEventList.m_events )
+            m_events.push_back( event );
 
         return *this;
     }
diff --git a/kicad/menubar.cpp b/kicad/menubar.cpp
index f7f6d20908..b4eaf128f4 100644
--- a/kicad/menubar.cpp
+++ b/kicad/menubar.cpp
@@ -53,7 +53,7 @@ void KICAD_MANAGER_FRAME::ReCreateMenuBar()
     if( openRecentMenu )
         PgmTop().GetFileHistory().RemoveMenu( openRecentMenu );
 
-    openRecentMenu = new ACTION_MENU();
+    openRecentMenu = new ACTION_MENU( false );
     openRecentMenu->SetTool( controlTool );
     openRecentMenu->SetTitle( _( "Open Recent" ) );
     openRecentMenu->SetIcon( recent_xpm );
diff --git a/pagelayout_editor/menubar.cpp b/pagelayout_editor/menubar.cpp
index d10e1d6e0d..a2f86a6356 100644
--- a/pagelayout_editor/menubar.cpp
+++ b/pagelayout_editor/menubar.cpp
@@ -58,7 +58,7 @@ void PL_EDITOR_FRAME::ReCreateMenuBar()
     //
     CONDITIONAL_MENU* fileMenu = new CONDITIONAL_MENU( false, selTool );
 
-    openRecentMenu = new ACTION_MENU();
+    openRecentMenu = new ACTION_MENU( false );
     openRecentMenu->SetTool( selTool );
     openRecentMenu->SetTitle( _( "Open Recent" ) );
     openRecentMenu->SetIcon( recent_xpm );
diff --git a/pagelayout_editor/tools/pl_point_editor.cpp b/pagelayout_editor/tools/pl_point_editor.cpp
index 585ec0fe6b..6fb0b68292 100644
--- a/pagelayout_editor/tools/pl_point_editor.cpp
+++ b/pagelayout_editor/tools/pl_point_editor.cpp
@@ -163,8 +163,6 @@ int PL_POINT_EDITOR::Main( const TOOL_EVENT& aEvent )
 
     KIGFX::VIEW_CONTROLS* controls = getViewControls();
     KIGFX::VIEW*          view = getView();
-    int                   savedToolID = m_frame->GetToolId();
-    wxString              savedToolMsg = m_frame->GetToolMsg();
     EDA_ITEM*             item = (EDA_ITEM*) selection.Front();
 
     controls->ShowCursor( true );
@@ -182,11 +180,16 @@ int PL_POINT_EDITOR::Main( const TOOL_EVENT& aEvent )
     // Main loop: keep receiving events
     while( OPT_TOOL_EVENT evt = Wait() )
     {
-        if( !m_editPoints
-             || evt->Matches( EVENTS::ClearedEvent )
-             || evt->Matches( EVENTS::UnselectedEvent )
-             || evt->Matches( EVENTS::SelectedEvent ) )
+        if( !m_editPoints || evt->IsCancel() || TOOL_EVT_UTILS::IsSelectionEvent( evt.get() ) )
         {
+            if( inDrag )      // Restore the last change
+            {
+                m_frame->PopTool();
+                m_frame->RollbackFromUndo();
+                inDrag = false;
+                modified = false;
+            }
+
             break;
         }
 
@@ -195,12 +198,11 @@ int PL_POINT_EDITOR::Main( const TOOL_EVENT& aEvent )
 
         if( evt->IsDrag( BUT_LEFT ) && m_editedPoint )
         {
-            m_frame->SetToolID( ID_DRAG_POINT, -1, _( "Drag Point" ) );
-
             if( !inDrag )
             {
                 m_frame->SaveCopyInUndoList();
                 controls->ForceCursorPosition( false );
+                m_frame->PushTool( _( "Drag Point" ).ToStdString() );
                 inDrag = true;
                 modified = true;
             }
@@ -214,25 +216,12 @@ int PL_POINT_EDITOR::Main( const TOOL_EVENT& aEvent )
         else if( evt->IsMouseUp( BUT_LEFT ) )
         {
             controls->SetAutoPan( false );
-            m_frame->SetToolID( savedToolID, -1, savedToolMsg );
-
+            m_frame->PopTool();
             inDrag = false;
 
             m_toolMgr->PassEvent();
         }
 
-        else if( evt->IsCancel() )
-        {
-            if( inDrag )      // Restore the last change
-            {
-                m_frame->RollbackFromUndo();
-                modified = false;
-            }
-
-            m_frame->SetToolID( savedToolID, -1, savedToolMsg );
-            break;
-        }
-
         else
         {
             m_toolMgr->PassEvent();
@@ -244,7 +233,6 @@ int PL_POINT_EDITOR::Main( const TOOL_EVENT& aEvent )
 
     controls->SetAutoPan( false );
     controls->CaptureCursor( false );
-    m_frame->SetToolID( savedToolID, -1, savedToolMsg );
 
     if( m_editPoints )
     {
diff --git a/pagelayout_editor/tools/pl_selection_tool.cpp b/pagelayout_editor/tools/pl_selection_tool.cpp
index 5836aa047c..4507c00ba0 100644
--- a/pagelayout_editor/tools/pl_selection_tool.cpp
+++ b/pagelayout_editor/tools/pl_selection_tool.cpp
@@ -211,7 +211,7 @@ int PL_SELECTION_TOOL::Main( const TOOL_EVENT& aEvent )
             ClearSelection();
         }
 
-        else if( evt->Action() == TA_CONTEXT_MENU_CLOSED )
+        else if( evt->Action() == TA_CHOICE_MENU_CLOSED )
         {
             m_menu.CloseContextMenu( evt );
         }
@@ -528,7 +528,7 @@ int PL_SELECTION_TOOL::SelectionMenu( const TOOL_EVENT& aEvent )
 bool PL_SELECTION_TOOL::doSelectionMenu( COLLECTOR* aCollector )
 {
     EDA_ITEM*   current = nullptr;
-    ACTION_MENU menu;
+    ACTION_MENU menu( true );
 
     int limit = std::min( MAX_SELECT_ITEM_IDS, aCollector->GetCount() );
 
@@ -551,7 +551,7 @@ bool PL_SELECTION_TOOL::doSelectionMenu( COLLECTOR* aCollector )
 
     while( OPT_TOOL_EVENT evt = Wait() )
     {
-        if( evt->Action() == TA_CONTEXT_MENU_UPDATE )
+        if( evt->Action() == TA_CHOICE_MENU_UPDATE )
         {
             if( current )
                 unhighlight( current, BRIGHTENED );
@@ -569,7 +569,7 @@ bool PL_SELECTION_TOOL::doSelectionMenu( COLLECTOR* aCollector )
                 current = NULL;
             }
         }
-        else if( evt->Action() == TA_CONTEXT_MENU_CHOICE )
+        else if( evt->Action() == TA_CHOICE_MENU_CHOICE )
         {
             if( current )
                 unhighlight( current, BRIGHTENED );
diff --git a/pcbnew/menubar_footprint_editor.cpp b/pcbnew/menubar_footprint_editor.cpp
index 42162aed71..73d9a8fe37 100644
--- a/pcbnew/menubar_footprint_editor.cpp
+++ b/pcbnew/menubar_footprint_editor.cpp
@@ -78,7 +78,7 @@ void FOOTPRINT_EDIT_FRAME::ReCreateMenuBar()
 
     fileMenu->AddSeparator();
 
-    ACTION_MENU* submenuImport = new ACTION_MENU();
+    ACTION_MENU* submenuImport = new ACTION_MENU( false );
     submenuImport->SetTool( selTool );
     submenuImport->SetTitle( _( "Import" ) );
     submenuImport->SetIcon( import_xpm );
diff --git a/pcbnew/menubar_pcb_editor.cpp b/pcbnew/menubar_pcb_editor.cpp
index f4a48f6746..ed53ef5808 100644
--- a/pcbnew/menubar_pcb_editor.cpp
+++ b/pcbnew/menubar_pcb_editor.cpp
@@ -68,7 +68,7 @@ void PCB_EDIT_FRAME::ReCreateMenuBar()
         if( openRecentMenu )
             Kiface().GetFileHistory().RemoveMenu( openRecentMenu );
 
-        openRecentMenu = new ACTION_MENU();
+        openRecentMenu = new ACTION_MENU( false );
         openRecentMenu->SetTool( selTool );
         openRecentMenu->SetTitle( _( "Open Recent" ) );
         openRecentMenu->SetIcon( recent_xpm );
@@ -112,7 +112,7 @@ void PCB_EDIT_FRAME::ReCreateMenuBar()
                        undo_xpm,                     SELECTION_CONDITIONS::ShowAlways );
 
     // Import submenu
-    ACTION_MENU* submenuImport = new ACTION_MENU();
+    ACTION_MENU* submenuImport = new ACTION_MENU( false );
     submenuImport->SetTool( selTool );
     submenuImport->SetTitle( _( "Import" ) );
     submenuImport->SetIcon( import_xpm );
@@ -126,7 +126,7 @@ void PCB_EDIT_FRAME::ReCreateMenuBar()
     fileMenu->AddMenu( submenuImport,                SELECTION_CONDITIONS::ShowAlways );
 
     // Export submenu
-    ACTION_MENU* submenuExport = new ACTION_MENU();
+    ACTION_MENU* submenuExport = new ACTION_MENU( false );
     submenuExport->SetTool( selTool );
     submenuExport->SetTitle( _( "Export" ) );
     submenuExport->SetIcon( export_xpm );
@@ -151,7 +151,7 @@ void PCB_EDIT_FRAME::ReCreateMenuBar()
     fileMenu->AddMenu( submenuExport,                SELECTION_CONDITIONS::ShowAlways );
 
     // Fabrication Outputs submenu
-    ACTION_MENU* submenuFabOutputs = new ACTION_MENU();
+    ACTION_MENU* submenuFabOutputs = new ACTION_MENU( false );
     submenuFabOutputs->SetTool( selTool );
     submenuFabOutputs->SetTitle( _( "Fabrication Outputs" ) );
     submenuFabOutputs->SetIcon( fabrication_xpm );
@@ -174,7 +174,7 @@ void PCB_EDIT_FRAME::ReCreateMenuBar()
     fileMenu->AddItem( ACTIONS::plot,                SELECTION_CONDITIONS::ShowAlways );
 
     // Archive submenu
-    ACTION_MENU* submenuArchive = new ACTION_MENU();
+    ACTION_MENU* submenuArchive = new ACTION_MENU( false );
     submenuArchive->SetTool( selTool );
     submenuArchive->SetTitle( _( "Archive Footprints" ) );
     submenuArchive->SetIcon( library_archive_xpm );
@@ -389,7 +389,7 @@ void PCB_EDIT_FRAME::ReCreateMenuBar()
 
     placeMenu->AddSeparator();
 
-    ACTION_MENU* autoplaceSubmenu = new ACTION_MENU;
+    ACTION_MENU* autoplaceSubmenu = new ACTION_MENU( false );
     autoplaceSubmenu->SetTitle( _( "Auto-Place Footprints" ) );
     autoplaceSubmenu->SetTool( selTool );
     autoplaceSubmenu->SetIcon( mode_module_xpm );
@@ -449,7 +449,7 @@ void PCB_EDIT_FRAME::ReCreateMenuBar()
 #endif
 
 #if defined(KICAD_SCRIPTING) && defined(KICAD_SCRIPTING_ACTION_MENU)
-    ACTION_MENU* submenuActionPlugins = new ACTION_MENU();
+    ACTION_MENU* submenuActionPlugins = new ACTION_MENU( false );
     submenuActionPlugins->SetTool( selTool );
     submenuActionPlugins->SetTitle( _( "External Plugins" ) );
     submenuActionPlugins->SetIcon( hammer_xpm );
diff --git a/pcbnew/router/length_tuner_tool.cpp b/pcbnew/router/length_tuner_tool.cpp
index a8b34689e8..cdee19e4e8 100644
--- a/pcbnew/router/length_tuner_tool.cpp
+++ b/pcbnew/router/length_tuner_tool.cpp
@@ -94,7 +94,8 @@ LENGTH_TUNER_TOOL::LENGTH_TUNER_TOOL() :
 class TUNER_TOOL_MENU : public ACTION_MENU
 {
 public:
-    TUNER_TOOL_MENU()
+    TUNER_TOOL_MENU() :
+        ACTION_MENU( true )
     {
         SetTitle( _( "Length Tuner" ) );
         SetIcon( router_len_tuner_xpm );
diff --git a/pcbnew/router/router_tool.cpp b/pcbnew/router/router_tool.cpp
index c00c5cf362..358ee1388b 100644
--- a/pcbnew/router/router_tool.cpp
+++ b/pcbnew/router/router_tool.cpp
@@ -226,10 +226,11 @@ ROUTER_TOOL::ROUTER_TOOL() :
 }
 
 
-class TRACK_WIDTH_MENU: public ACTION_MENU
+class TRACK_WIDTH_MENU : public ACTION_MENU
 {
 public:
     TRACK_WIDTH_MENU( PCB_EDIT_FRAME& aFrame ) :
+        ACTION_MENU( true ),
         m_frame( aFrame )
     {
         SetIcon( width_track_via_xpm );
@@ -354,10 +355,11 @@ private:
 };
 
 
-class DIFF_PAIR_MENU: public ACTION_MENU
+class DIFF_PAIR_MENU : public ACTION_MENU
 {
 public:
     DIFF_PAIR_MENU( PCB_EDIT_FRAME& aFrame ) :
+        ACTION_MENU( true ),
         m_frame( aFrame )
     {
         SetIcon( width_track_via_xpm );
@@ -448,6 +450,7 @@ class ROUTER_TOOL_MENU : public ACTION_MENU
 {
 public:
     ROUTER_TOOL_MENU( PCB_EDIT_FRAME& aFrame, PNS::ROUTER_MODE aMode ) :
+        ACTION_MENU( true ),
         m_frame( aFrame ), m_mode( aMode ), m_trackViaMenu( aFrame ), m_diffPairMenu( aFrame ),
         m_zoomMenu( &aFrame ), m_gridMenu( &aFrame )
     {
diff --git a/pcbnew/tools/drawing_tool.cpp b/pcbnew/tools/drawing_tool.cpp
index cc7ab43e56..9a52c57114 100644
--- a/pcbnew/tools/drawing_tool.cpp
+++ b/pcbnew/tools/drawing_tool.cpp
@@ -103,7 +103,7 @@ TOOL_ACTION PCB_ACTIONS::drawDimension( "pcbnew.InteractiveDrawing.dimension",
 TOOL_ACTION PCB_ACTIONS::drawZone( "pcbnew.InteractiveDrawing.zone",
         AS_GLOBAL,
 #ifdef __WXOSX_MAC__
-        GR_KB_ALT + 'Z',
+        MD_ALT + 'Z',
 #else
         MD_SHIFT + MD_CTRL + 'Z',
 #endif
diff --git a/pcbnew/tools/pad_tool.cpp b/pcbnew/tools/pad_tool.cpp
index e165816d38..e58048ce8c 100644
--- a/pcbnew/tools/pad_tool.cpp
+++ b/pcbnew/tools/pad_tool.cpp
@@ -70,7 +70,8 @@ public:
 
     using SHOW_FUNCTOR = std::function<bool()>;
 
-    PAD_CONTEXT_MENU( bool aEditingFootprint, SHOW_FUNCTOR aHaveGlobalPadSetting ):
+    PAD_CONTEXT_MENU( bool aEditingFootprint, SHOW_FUNCTOR aHaveGlobalPadSetting ) :
+        ACTION_MENU( true ),
         m_editingFootprint( aEditingFootprint ),
         m_haveGlobalPadSettings( std::move( aHaveGlobalPadSetting ) )
     {
diff --git a/pcbnew/tools/pcb_editor_control.cpp b/pcbnew/tools/pcb_editor_control.cpp
index 041a6011c7..f79b4a136c 100644
--- a/pcbnew/tools/pcb_editor_control.cpp
+++ b/pcbnew/tools/pcb_editor_control.cpp
@@ -256,7 +256,8 @@ TOOL_ACTION PCB_ACTIONS::flipBoard( "pcbnew.Control.flipBoard",
 class ZONE_CONTEXT_MENU : public ACTION_MENU
 {
 public:
-    ZONE_CONTEXT_MENU()
+    ZONE_CONTEXT_MENU() :
+        ACTION_MENU( true )
     {
         SetIcon( add_zone_xpm );
         SetTitle( _( "Zones" ) );
@@ -315,7 +316,8 @@ private:
 class LOCK_CONTEXT_MENU : public ACTION_MENU
 {
 public:
-    LOCK_CONTEXT_MENU()
+    LOCK_CONTEXT_MENU() :
+        ACTION_MENU( true )
     {
         SetIcon( locked_xpm );
         SetTitle( _( "Locking" ) );
diff --git a/pcbnew/tools/placement_tool.cpp b/pcbnew/tools/placement_tool.cpp
index 9fc5953438..f9c2e0c61b 100644
--- a/pcbnew/tools/placement_tool.cpp
+++ b/pcbnew/tools/placement_tool.cpp
@@ -101,7 +101,7 @@ bool ALIGN_DISTRIBUTE_TOOL::Init()
     m_frame = getEditFrame<PCB_BASE_FRAME>();
 
     // Create a context menu and make it available through selection tool
-    m_placementMenu = new ACTION_MENU;
+    m_placementMenu = new ACTION_MENU( true );
     m_placementMenu->SetTool( this );
     m_placementMenu->SetIcon( align_items_xpm );
     m_placementMenu->SetTitle( _( "Align/Distribute" ) );
diff --git a/pcbnew/tools/selection_tool.cpp b/pcbnew/tools/selection_tool.cpp
index 15005e8fe6..49d55b771d 100644
--- a/pcbnew/tools/selection_tool.cpp
+++ b/pcbnew/tools/selection_tool.cpp
@@ -133,10 +133,11 @@ TOOL_ACTION PCB_ACTIONS::filterSelection( "pcbnew.InteractiveSelection.FilterSel
         _( "Filter Selection..." ), _( "Filter the types of items in the selection" ),
         options_generic_xpm );
 
-class SELECT_MENU: public ACTION_MENU
+class SELECT_MENU : public ACTION_MENU
 {
 public:
-    SELECT_MENU()
+    SELECT_MENU() :
+        ACTION_MENU( true )
     {
         SetTitle( _( "Select" ) );
         SetIcon( options_generic_xpm );
@@ -364,7 +365,7 @@ int SELECTION_TOOL::Main( const TOOL_EVENT& aEvent )
             m_toolMgr->RunAction( PCB_ACTIONS::clearHighlight, true );
         }
 
-        else if( evt->Action() == TA_CONTEXT_MENU_CLOSED )
+        else if( evt->Action() == TA_CHOICE_MENU_CLOSED )
         {
             m_menu.CloseContextMenu( evt );
         }
@@ -1405,7 +1406,7 @@ bool SELECTION_TOOL::doSelectionMenu( GENERAL_COLLECTOR* aCollector, const wxStr
 {
     BOARD_ITEM*      current = nullptr;
     PCBNEW_SELECTION highlightGroup;
-    ACTION_MENU      menu;
+    ACTION_MENU      menu( true );
 
     highlightGroup.SetLayer( LAYER_SELECT_OVERLAY );
     getView()->Add( &highlightGroup );
@@ -1431,7 +1432,7 @@ bool SELECTION_TOOL::doSelectionMenu( GENERAL_COLLECTOR* aCollector, const wxStr
 
     while( OPT_TOOL_EVENT evt = Wait() )
     {
-        if( evt->Action() == TA_CONTEXT_MENU_UPDATE )
+        if( evt->Action() == TA_CHOICE_MENU_UPDATE )
         {
             if( current )
                 unhighlight( current, BRIGHTENED, highlightGroup );
@@ -1449,7 +1450,7 @@ bool SELECTION_TOOL::doSelectionMenu( GENERAL_COLLECTOR* aCollector, const wxStr
                 current = NULL;
             }
         }
-        else if( evt->Action() == TA_CONTEXT_MENU_CHOICE )
+        else if( evt->Action() == TA_CHOICE_MENU_CHOICE )
         {
             if( current )
                 unhighlight( current, BRIGHTENED, highlightGroup );