Implement more aggressive re-entrancy blocking for drawing tools.

A similar strategy was already implemented in Eeschema.

Also adds some safety around clearing of autopan and mouse capture.

Fixes https://gitlab.com/kicad/code/kicad/issues/6909
This commit is contained in:
Jeff Young 2021-06-20 11:02:44 +01:00
parent 19f76ae77c
commit b72545a432
8 changed files with 106 additions and 10 deletions

View File

@ -353,11 +353,13 @@ int SCH_DRAWING_TOOLS::PlaceSymbol( const TOOL_EVENT& aEvent )
evt->SetPassEvent();
}
// Enable autopanning and cursor capture only when there is a footprint to be placed
// Enable autopanning and cursor capture only when there is a symbol to be placed
getViewControls()->SetAutoPan( symbol != nullptr );
getViewControls()->CaptureCursor( symbol != nullptr );
}
getViewControls()->SetAutoPan( false );
getViewControls()->CaptureCursor( false );
m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::ARROW );
m_inPlaceSymbol = false;
return 0;
@ -569,11 +571,13 @@ int SCH_DRAWING_TOOLS::PlaceImage( const TOOL_EVENT& aEvent )
evt->SetPassEvent();
}
// Enable autopanning and cursor capture only when there is a footprint to be placed
// Enable autopanning and cursor capture only when there is an image to be placed
getViewControls()->SetAutoPan( image != nullptr );
getViewControls()->CaptureCursor( image != nullptr );
}
getViewControls()->SetAutoPan( false );
getViewControls()->CaptureCursor( false );
m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::ARROW );
m_inPlaceImage = false;
return 0;
@ -1221,13 +1225,15 @@ int SCH_DRAWING_TOOLS::TwoClickPlace( const TOOL_EVENT& aEvent )
evt->SetPassEvent();
}
// Enable autopanning and cursor capture only when there is a footprint to be placed
// Enable autopanning and cursor capture only when there is an item to be placed
controls->SetAutoPan( item != nullptr );
controls->CaptureCursor( item != nullptr );
}
m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::ARROW );
controls->SetAutoPan( false );
controls->CaptureCursor( false );
controls->ForceCursorPosition( false );
m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::ARROW );
m_inTwoClickPlace = false;
return 0;
}
@ -1407,6 +1413,8 @@ int SCH_DRAWING_TOOLS::DrawSheet( const TOOL_EVENT& aEvent )
getViewControls()->CaptureCursor( sheet != nullptr );
}
getViewControls()->SetAutoPan( false );
getViewControls()->CaptureCursor( false );
m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::ARROW );
m_inDrawSheet = false;
return 0;

View File

@ -771,6 +771,8 @@ int SCH_LINE_WIRE_BUS_TOOL::doDrawSegments( const std::string& aTool, int aType,
controls->CaptureCursor( segment != nullptr );
}
controls->SetAutoPan( false );
controls->CaptureCursor( false );
m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::ARROW );
controls->ForceCursorPosition( false );
return 0;

View File

@ -253,6 +253,8 @@ int SYMBOL_EDITOR_DRAWING_TOOLS::TwoClickPlace( const TOOL_EVENT& aEvent )
getViewControls()->CaptureCursor( item != nullptr );
}
getViewControls()->SetAutoPan( false );
getViewControls()->CaptureCursor( false );
m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::ARROW );
return 0;
}
@ -414,6 +416,8 @@ int SYMBOL_EDITOR_DRAWING_TOOLS::DrawShape( const TOOL_EVENT& aEvent )
getViewControls()->CaptureCursor( item != nullptr );
}
getViewControls()->SetAutoPan( false );
getViewControls()->CaptureCursor( false );
m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::ARROW );
return 0;
}

View File

@ -212,6 +212,8 @@ int PL_DRAWING_TOOLS::PlaceItem( const TOOL_EVENT& aEvent )
getViewControls()->CaptureCursor( item != nullptr );
}
getViewControls()->SetAutoPan( false );
getViewControls()->CaptureCursor( false );
m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::ARROW );
return 0;
}
@ -332,6 +334,8 @@ int PL_DRAWING_TOOLS::DrawShape( const TOOL_EVENT& aEvent )
getViewControls()->CaptureCursor( item != nullptr );
}
getViewControls()->SetAutoPan( false );
getViewControls()->CaptureCursor( false );
m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::ARROW );
m_frame->PopTool( tool );
return 0;

View File

@ -177,7 +177,9 @@ protected:
BOARD_EDITOR_CONTROL::BOARD_EDITOR_CONTROL() :
PCB_TOOL_BASE( "pcbnew.EditorControl" ),
m_frame( nullptr )
m_frame( nullptr ),
m_inPlaceFootprint( false ),
m_inPlaceTarget( false )
{
m_placeOrigin = std::make_unique<KIGFX::ORIGIN_VIEWITEM>(
KIGFX::COLOR4D( 0.8, 0.0, 0.0, 1.0 ),
@ -916,6 +918,11 @@ int BOARD_EDITOR_CONTROL::ViaSizeDec( const TOOL_EVENT& aEvent )
int BOARD_EDITOR_CONTROL::PlaceFootprint( const TOOL_EVENT& aEvent )
{
if( m_inPlaceFootprint )
return 0;
else
m_inPlaceFootprint = true;
FOOTPRINT* fp = aEvent.Parameter<FOOTPRINT*>();
KIGFX::VIEW_CONTROLS* controls = getViewControls();
BOARD_COMMIT commit( m_frame );
@ -1073,11 +1080,15 @@ int BOARD_EDITOR_CONTROL::PlaceFootprint( const TOOL_EVENT& aEvent )
}
// Enable autopanning and cursor capture only when there is a footprint to be placed
controls->SetAutoPan( !!fp );
controls->CaptureCursor( !!fp );
controls->SetAutoPan( fp != nullptr );
controls->CaptureCursor( fp != nullptr );
}
controls->SetAutoPan( false );
controls->CaptureCursor( false );
m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::ARROW );
m_inPlaceFootprint = false;
return 0;
}
@ -1161,6 +1172,11 @@ int BOARD_EDITOR_CONTROL::modifyLockSelected( MODIFY_MODE aMode )
int BOARD_EDITOR_CONTROL::PlaceTarget( const TOOL_EVENT& aEvent )
{
if( m_inPlaceTarget )
return 0;
else
m_inPlaceTarget = true;
KIGFX::VIEW* view = getView();
KIGFX::VIEW_CONTROLS* controls = getViewControls();
BOARD* board = getModel<BOARD>();
@ -1267,6 +1283,8 @@ int BOARD_EDITOR_CONTROL::PlaceTarget( const TOOL_EVENT& aEvent )
view->Remove( &preview );
m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::ARROW );
m_inPlaceTarget = false;
return 0;
}

View File

@ -124,9 +124,12 @@ private:
///< Set up handlers for various events.
void setTransitions() override;
PCB_EDIT_FRAME* m_frame; ///< Pointer to the currently used edit frame.
private:
PCB_EDIT_FRAME* m_frame;
bool m_inPlaceFootprint; // Re-entrancy guard.
bool m_inPlaceTarget; // Re-entrancy guard.
std::unique_ptr<KIGFX::ORIGIN_VIEWITEM> m_placeOrigin; ///< Place & drill origin marker
std::unique_ptr<KIGFX::ORIGIN_VIEWITEM> m_placeOrigin;
static const int WIDTH_STEP; ///< How does line width change after one -/+ key press.
};

View File

@ -157,7 +157,8 @@ DRAWING_TOOL::DRAWING_TOOL() :
m_board( nullptr ),
m_frame( nullptr ),
m_mode( MODE::NONE ),
m_lineWidth( 1 )
m_lineWidth( 1 ),
m_inDrawingTool( false )
{
}
@ -246,6 +247,11 @@ int DRAWING_TOOL::DrawLine( const TOOL_EVENT& aEvent )
if( m_isFootprintEditor && !m_frame->GetModel() )
return 0;
if( m_inDrawingTool )
return 0;
else
m_inDrawingTool = true;
FOOTPRINT* parentFootprint = dynamic_cast<FOOTPRINT*>( m_frame->GetModel() );
PCB_SHAPE* line = m_isFootprintEditor ? new FP_SHAPE( parentFootprint ) : new PCB_SHAPE;
BOARD_COMMIT commit( m_frame );
@ -283,6 +289,7 @@ int DRAWING_TOOL::DrawLine( const TOOL_EVENT& aEvent )
line->SetFlags( IS_NEW );
}
m_inDrawingTool = false;
return 0;
}
@ -292,6 +299,11 @@ int DRAWING_TOOL::DrawRectangle( const TOOL_EVENT& aEvent )
if( m_isFootprintEditor && !m_frame->GetModel() )
return 0;
if( m_inDrawingTool )
return 0;
else
m_inDrawingTool = true;
FOOTPRINT* parentFootprint = dynamic_cast<FOOTPRINT*>( m_frame->GetModel() );
PCB_SHAPE* rect = m_isFootprintEditor ? new FP_SHAPE( parentFootprint ) : new PCB_SHAPE;
BOARD_COMMIT commit( m_frame );
@ -329,6 +341,7 @@ int DRAWING_TOOL::DrawRectangle( const TOOL_EVENT& aEvent )
startingPoint = NULLOPT;
}
m_inDrawingTool = false;
return 0;
}
@ -338,6 +351,11 @@ int DRAWING_TOOL::DrawCircle( const TOOL_EVENT& aEvent )
if( m_isFootprintEditor && !m_frame->GetModel() )
return 0;
if( m_inDrawingTool )
return 0;
else
m_inDrawingTool = true;
FOOTPRINT* parentFootprint = dynamic_cast<FOOTPRINT*>( m_frame->GetModel() );
PCB_SHAPE* circle = m_isFootprintEditor ? new FP_SHAPE( parentFootprint ) : new PCB_SHAPE;
BOARD_COMMIT commit( m_frame );
@ -375,6 +393,7 @@ int DRAWING_TOOL::DrawCircle( const TOOL_EVENT& aEvent )
startingPoint = NULLOPT;
}
m_inDrawingTool = false;
return 0;
}
@ -384,6 +403,11 @@ int DRAWING_TOOL::DrawArc( const TOOL_EVENT& aEvent )
if( m_isFootprintEditor && !m_frame->GetModel() )
return 0;
if( m_inDrawingTool )
return 0;
else
m_inDrawingTool = true;
FOOTPRINT* parentFootprint = dynamic_cast<FOOTPRINT*>( m_frame->GetModel() );
PCB_SHAPE* arc = m_isFootprintEditor ? new FP_SHAPE( parentFootprint ) : new PCB_SHAPE;
BOARD_COMMIT commit( m_frame );
@ -416,6 +440,7 @@ int DRAWING_TOOL::DrawArc( const TOOL_EVENT& aEvent )
immediateMode = false;
}
m_inDrawingTool = false;
return 0;
}
@ -425,6 +450,11 @@ int DRAWING_TOOL::PlaceText( const TOOL_EVENT& aEvent )
if( m_isFootprintEditor && !m_frame->GetModel() )
return 0;
if( m_inDrawingTool )
return 0;
else
m_inDrawingTool = true;
BOARD_ITEM* text = NULL;
const BOARD_DESIGN_SETTINGS& dsnSettings = m_frame->GetDesignSettings();
BOARD_COMMIT commit( m_frame );
@ -637,8 +667,12 @@ int DRAWING_TOOL::PlaceText( const TOOL_EVENT& aEvent )
}
}
m_controls->SetAutoPan( false );
m_controls->CaptureCursor( false );
m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::ARROW );
m_frame->SetMsgPanel( board() );
m_inDrawingTool = false;
return 0;
}
@ -657,6 +691,11 @@ int DRAWING_TOOL::DrawDimension( const TOOL_EVENT& aEvent )
if( m_isFootprintEditor && !m_frame->GetModel() )
return 0;
if( m_inDrawingTool )
return 0;
else
m_inDrawingTool = true;
enum DIMENSION_STEPS
{
SET_ORIGIN = 0,
@ -1080,6 +1119,8 @@ int DRAWING_TOOL::DrawDimension( const TOOL_EVENT& aEvent )
m_view->Remove( &preview );
m_frame->SetMsgPanel( board() );
m_inDrawingTool = false;
return 0;
}
@ -1089,6 +1130,11 @@ int DRAWING_TOOL::PlaceImportedGraphics( const TOOL_EVENT& aEvent )
if( !m_frame->GetModel() )
return 0;
if( m_inDrawingTool )
return 0;
else
m_inDrawingTool = true;
// Note: PlaceImportedGraphics() will convert PCB_SHAPE_T and PCB_TEXT_T to footprint
// items if needed
DIALOG_IMPORT_GFX dlg( m_frame, m_isFootprintEditor );
@ -1236,7 +1282,10 @@ int DRAWING_TOOL::PlaceImportedGraphics( const TOOL_EVENT& aEvent )
m_view->Remove( &preview );
m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::ARROW );
m_inDrawingTool = false;
m_frame->PopTool( tool );
return 0;
}
@ -1248,6 +1297,11 @@ int DRAWING_TOOL::SetAnchor( const TOOL_EVENT& aEvent )
if( !m_frame->GetModel() )
return 0;
if( m_inDrawingTool )
return 0;
else
m_inDrawingTool = true;
SCOPED_DRAW_MODE scopedDrawMode( m_mode, MODE::ANCHOR );
PCB_GRID_HELPER grid( m_toolMgr, m_frame->GetMagneticItemsSettings() );
@ -1312,6 +1366,8 @@ int DRAWING_TOOL::SetAnchor( const TOOL_EVENT& aEvent )
}
m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::ARROW );
m_inDrawingTool = false;
return 0;
}

View File

@ -269,6 +269,7 @@ private:
BOARD* m_board;
PCB_BASE_EDIT_FRAME* m_frame;
MODE m_mode;
bool m_inDrawingTool; // Re-entrancy guard
unsigned int m_lineWidth; // Current line width for multi-segment drawing
static const unsigned int WIDTH_STEP; // Amount of width change for one -/+ key press