KiCad PCB EDA Suite
tool_dispatcher.cpp
Go to the documentation of this file.
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright (C) 2013 CERN
5 * Copyright (C) 2013-2021 KiCad Developers, see CHANGELOG.txt for contributors.
6 * @author Tomasz Wlostowski <[email protected]>
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version 2
11 * of the License, or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, you may find one here:
20 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
21 * or you may search the http://www.gnu.org website for the version 2 license,
22 * or you may write to the Free Software Foundation, Inc.,
23 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
24 */
25
26#include <ignore.h>
27#include <macros.h>
28#include <trace_helpers.h>
29#include <tool/tool_manager.h>
31#include <tool/actions.h>
32#include <tool/action_manager.h>
33#include <tool/action_menu.h>
34#include <view/view.h>
36#include <eda_draw_frame.h>
37#include <core/kicad_algo.h>
38#include <optional>
39#include <wx/log.h>
40#include <wx/stc/stc.h>
41#include <wx/settings.h>
42#include <kiplatform/app.h>
43#include <kiplatform/ui.h>
44
47{
48 BUTTON_STATE( TOOL_MOUSE_BUTTONS aButton, const wxEventType& aDownEvent,
49 const wxEventType& aUpEvent, const wxEventType& aDblClickEvent ) :
50 dragging( false ),
51 pressed( false ),
52 button( aButton ),
53 downEvent( aDownEvent ),
54 upEvent( aUpEvent ),
55 dblClickEvent( aDblClickEvent )
56 {};
57
60
62 bool pressed;
63
66
69
72
75
77 wxEventType downEvent;
78
80 wxEventType upEvent;
81
83 wxEventType dblClickEvent;
84
86 wxLongLong downTimestamp;
87
89 void Reset()
90 {
91 dragging = false;
92 pressed = false;
93 }
94
96 bool GetState() const
97 {
98 wxMouseState mouseState = wxGetMouseState();
99
100 switch( button )
101 {
102 case BUT_LEFT:
103 return mouseState.LeftIsDown();
104
105 case BUT_MIDDLE:
106 return mouseState.MiddleIsDown();
107
108 case BUT_RIGHT:
109 return mouseState.RightIsDown();
110
111 case BUT_AUX1:
112 return mouseState.Aux1IsDown();
113
114 case BUT_AUX2:
115 return mouseState.Aux2IsDown();
116
117 default:
118 assert( false );
119 break;
120 }
121
122 return false;
123 }
124};
125
126
128 m_toolMgr( aToolMgr )
129{
130 m_sysDragMinX = wxSystemSettings::GetMetric( wxSYS_DRAG_X );
131 m_sysDragMinY = wxSystemSettings::GetMetric( wxSYS_DRAG_Y );
132
135
136 m_buttons.push_back( new BUTTON_STATE( BUT_LEFT, wxEVT_LEFT_DOWN,
137 wxEVT_LEFT_UP, wxEVT_LEFT_DCLICK ) );
138 m_buttons.push_back( new BUTTON_STATE( BUT_RIGHT, wxEVT_RIGHT_DOWN,
139 wxEVT_RIGHT_UP, wxEVT_RIGHT_DCLICK ) );
140 m_buttons.push_back( new BUTTON_STATE( BUT_MIDDLE, wxEVT_MIDDLE_DOWN,
141 wxEVT_MIDDLE_UP, wxEVT_MIDDLE_DCLICK ) );
142 m_buttons.push_back( new BUTTON_STATE( BUT_AUX1, wxEVT_AUX1_DOWN,
143 wxEVT_AUX1_UP, wxEVT_AUX1_DCLICK ) );
144 m_buttons.push_back( new BUTTON_STATE( BUT_AUX2, wxEVT_AUX2_DOWN,
145 wxEVT_AUX2_UP, wxEVT_AUX2_DCLICK ) );
146
147 ResetState();
148}
149
150
152{
153 for( BUTTON_STATE* st : m_buttons )
154 delete st;
155}
156
157
159{
160 for( BUTTON_STATE* st : m_buttons )
161 st->Reset();
162}
163
164
166{
167 return m_toolMgr->GetView();
168}
169
170
171bool TOOL_DISPATCHER::handleMouseButton( wxEvent& aEvent, int aIndex, bool aMotion )
172{
173 BUTTON_STATE* st = m_buttons[aIndex];
174 wxEventType type = aEvent.GetEventType();
175 std::optional<TOOL_EVENT> evt;
176 bool isClick = false;
177
178// bool up = type == st->upEvent;
179// bool down = type == st->downEvent;
180 bool up = false, down = false;
181 bool dblClick = type == st->dblClickEvent;
182 bool state = st->GetState();
183
184 if( !dblClick )
185 {
186 // Sometimes the dispatcher does not receive mouse button up event, so it stays
187 // in the dragging mode even if the mouse button is not held anymore
188 if( st->pressed && !state )
189 up = true;
190 // Don't apply same logic to down events as it kills touchpad tapping
191 else if( !st->pressed && type == st->downEvent )
192 down = true;
193 }
194
195 int mods = decodeModifiers( static_cast<wxMouseEvent*>( &aEvent ) );
196 int args = st->button | mods;
197
198 if( down ) // Handle mouse button press
199 {
200 st->downTimestamp = wxGetLocalTimeMillis();
201
202 if( !st->pressed ) // save the drag origin on the first click only
203 {
206 }
207
209 st->pressed = true;
210 evt = TOOL_EVENT( TC_MOUSE, TA_MOUSE_DOWN, args );
211 }
212 else if( up ) // Handle mouse button release
213 {
214 st->pressed = false;
215
216 if( st->dragging )
217 evt = TOOL_EVENT( TC_MOUSE, TA_MOUSE_UP, args );
218 else
219 isClick = true;
220
221 if( isClick )
222 evt = TOOL_EVENT( TC_MOUSE, TA_MOUSE_CLICK, args );
223
224 st->dragging = false;
225 }
226 else if( dblClick )
227 {
228 evt = TOOL_EVENT( TC_MOUSE, TA_MOUSE_DBLCLICK, args );
229 }
230
231 if( st->pressed && aMotion )
232 {
233 if( !st->dragging )
234 {
235#ifdef __WXMAC__
236 if( wxGetLocalTimeMillis() - st->downTimestamp > DragTimeThreshold )
237 st->dragging = true;
238#endif
240
241 if( abs( offset.x ) > m_sysDragMinX || abs( offset.y ) > m_sysDragMinY )
242 st->dragging = true;
243
244 }
245
246 if( st->dragging )
247 {
248 evt = TOOL_EVENT( TC_MOUSE, TA_MOUSE_DRAG, args );
249 evt->setMouseDragOrigin( st->dragOrigin );
250 evt->setMouseDelta( m_lastMousePos - st->dragOrigin );
251 }
252 }
253
254 if( evt )
255 {
256 evt->SetMousePosition( isClick ? st->downPosition : m_lastMousePos );
257 m_toolMgr->ProcessEvent( *evt );
258
259 return true;
260 }
261
262 return false;
263}
264
265
266// Helper function to know if a special key ( see key list ) should be captured
267// or if the event can be skipped
268// on Linux, the event must be passed to the GUI if they are not used by KiCad,
269// especially the wxEVENT_CHAR_HOOK, if it is not handled
270// Some keys have a predefined action in wxWidgets so, even if not used,
271// the even will be not skipped
272// the unused keys listed in isKeySpecialCode() will be not skipped
273bool isKeySpecialCode( int aKeyCode )
274{
275 // These keys have predefined actions (like move thumbtrack cursor),
276 // and we do not want these actions executed
277 const std::vector<enum wxKeyCode> special_keys =
278 {
279 WXK_PAGEUP, WXK_PAGEDOWN,
280 WXK_NUMPAD_PAGEUP, WXK_NUMPAD_PAGEDOWN
281 };
282
283 return alg::contains( special_keys, aKeyCode );
284}
285
286
287// Helper function to know if a key should be managed by DispatchWxEvent()
288// or if the event can be ignored and skipped because the key is only a modifier
289// that is not used alone in kicad
290static bool isKeyModifierOnly( int aKeyCode )
291{
292 static std::vector<enum wxKeyCode> special_keys =
293 {
294 WXK_CONTROL, WXK_RAW_CONTROL, WXK_SHIFT, WXK_ALT
295 };
296
297 return alg::contains( special_keys, aKeyCode );
298}
299
300
301static bool isMouseClick( wxEventType type )
302{
303 return type == wxEVT_LEFT_DOWN || type == wxEVT_LEFT_UP || type == wxEVT_LEFT_DCLICK
304 || type == wxEVT_MIDDLE_DOWN || type == wxEVT_MIDDLE_UP || type == wxEVT_MIDDLE_DCLICK
305 || type == wxEVT_RIGHT_DOWN || type == wxEVT_RIGHT_UP || type == wxEVT_RIGHT_DCLICK
306 || type == wxEVT_AUX1_DOWN || type == wxEVT_AUX1_UP || type == wxEVT_AUX1_DCLICK
307 || type == wxEVT_AUX2_DOWN || type == wxEVT_AUX2_UP || type == wxEVT_AUX2_DCLICK;
308}
309
310
311/* A helper class that convert some special key codes to an equivalent.
312 * WXK_NUMPAD_UP to WXK_UP,
313 * WXK_NUMPAD_DOWN to WXK_DOWN,
314 * WXK_NUMPAD_LEFT to WXK_LEFT,
315 * WXK_NUMPAD_RIGHT,
316 * WXK_NUMPAD_PAGEUP,
317 * WXK_NUMPAD_PAGEDOWN
318 * note:
319 * wxEVT_CHAR_HOOK does this conversion when it is skipped by firing a wxEVT_CHAR
320 * with this converted code, but we do not skip these key events because they also
321 * have default action (scroll the panel)
322 */
323int translateSpecialCode( int aKeyCode )
324{
325 switch( aKeyCode )
326 {
327 case WXK_NUMPAD_UP: return WXK_UP;
328 case WXK_NUMPAD_DOWN: return WXK_DOWN;
329 case WXK_NUMPAD_LEFT: return WXK_LEFT;
330 case WXK_NUMPAD_RIGHT: return WXK_RIGHT;
331 case WXK_NUMPAD_PAGEUP: return WXK_PAGEUP;
332 case WXK_NUMPAD_PAGEDOWN: return WXK_PAGEDOWN;
333 default: break;
334 };
335
336 return aKeyCode;
337}
338
339
340std::optional<TOOL_EVENT> TOOL_DISPATCHER::GetToolEvent( wxKeyEvent* aKeyEvent, bool* keyIsSpecial )
341{
342 std::optional<TOOL_EVENT> evt;
343 int key = aKeyEvent->GetKeyCode();
344 int unicode_key = aKeyEvent->GetUnicodeKey();
345
346 // This wxEVT_CHAR_HOOK event can be ignored: not useful in Kicad
347 if( isKeyModifierOnly( key ) )
348 {
349 aKeyEvent->Skip();
350 return evt;
351 }
352
353 wxLogTrace( kicadTraceKeyEvent, wxS( "TOOL_DISPATCHER::GetToolEvent %s" ), dump( *aKeyEvent ) );
354
355 // if the key event must be skipped, skip it here if the event is a wxEVT_CHAR_HOOK
356 // and do nothing.
357 *keyIsSpecial = isKeySpecialCode( key );
358
359 if( aKeyEvent->GetEventType() == wxEVT_CHAR_HOOK )
360 key = translateSpecialCode( key );
361
362 int mods = decodeModifiers( aKeyEvent );
363
364 if( mods & MD_CTRL )
365 {
366 // wxWidgets maps key codes related to Ctrl+letter handled by CHAR_EVT
367 // (http://docs.wxwidgets.org/trunk/classwx_key_event.html):
368 // char events for ASCII letters in this case carry codes corresponding to the ASCII
369 // value of Ctrl-Latter, i.e. 1 for Ctrl-A, 2 for Ctrl-B and so on until 26 for Ctrl-Z.
370 // They are remapped here to be more easy to handle in code
371 // Note also on OSX wxWidgets has a different behavior and the mapping is made
372 // only for ctrl+'A' to ctlr+'Z' (unicode code return 'A' to 'Z').
373 // Others OS return WXK_CONTROL_A to WXK_CONTROL_Z, and Ctrl+'M' returns the same code as
374 // the return key, so the remapping does not use the unicode key value.
375#ifdef __APPLE__
376 if( unicode_key >= 'A' && unicode_key <= 'Z' && key >= WXK_CONTROL_A && key <= WXK_CONTROL_Z )
377#else
378 ignore_unused( unicode_key );
379
380 if( key >= WXK_CONTROL_A && key <= WXK_CONTROL_Z )
381#endif
382 key += 'A' - 1;
383 }
384
385#ifdef __APPLE__
386 if( mods & MD_ALT )
387 {
388 // OSX maps a bunch of commonly used extended-ASCII characters onto the keyboard
389 // using the ALT key. Since we use ALT for some of our hotkeys, we need to map back
390 // to the underlying keys. The kVK_ANSI_* values come from Apple and are said to be
391 // hardware independent.
392 switch( aKeyEvent->GetRawKeyCode() )
393 {
394 case /* kVK_ANSI_1 */ 0x12: key = '1'; break;
395 case /* kVK_ANSI_2 */ 0x13: key = '2'; break;
396 case /* kVK_ANSI_3 */ 0x14: key = '3'; break;
397 case /* kVK_ANSI_4 */ 0x15: key = '4'; break;
398 case /* kVK_ANSI_6 */ 0x16: key = '6'; break;
399 case /* kVK_ANSI_5 */ 0x17: key = '5'; break;
400 case /* kVK_ANSI_Equal */ 0x18: key = '='; break;
401 case /* kVK_ANSI_9 */ 0x19: key = '9'; break;
402 case /* kVK_ANSI_7 */ 0x1A: key = '7'; break;
403 case /* kVK_ANSI_Minus */ 0x1B: key = '-'; break;
404 case /* kVK_ANSI_8 */ 0x1C: key = '8'; break;
405 case /* kVK_ANSI_0 */ 0x1D: key = '0'; break;
406 default: ;
407 }
408 }
409#endif
410
411 if( key == WXK_ESCAPE ) // ESC is the special key for canceling tools
412 evt = TOOL_EVENT( TC_COMMAND, TA_CANCEL_TOOL, WXK_ESCAPE );
413 else
414 evt = TOOL_EVENT( TC_KEYBOARD, TA_KEY_PRESSED, key | mods );
415
416 return evt;
417}
418
419
420void TOOL_DISPATCHER::DispatchWxEvent( wxEvent& aEvent )
421{
422 bool motion = false;
423 bool buttonEvents = false;
424 VECTOR2D pos;
425 std::optional<TOOL_EVENT> evt;
426 bool keyIsEscape = false; // True if the keypress was the escape key
427 bool keyIsSpecial = false; // True if the key is a special key code
428 wxWindow* focus = wxWindow::FindFocus();
429
430 // Required in win32 to ensure wxTimer events get scheduled in between other events
431 // Or else we may stall them out entirely and never get them during actions like rapid
432 // mouse moves.
434
435 wxEventType type = aEvent.GetEventType();
436
437 // Sometimes there is no window that has the focus (it happens when another PCB_BASE_FRAME
438 // is opened and is iconized on Windows).
439 // In this case, give the focus to the parent frame (GAL canvas itself does not accept the
440 // focus when iconized for some obscure reason)
441 if( focus == nullptr )
442 {
443 wxWindow* holderWindow = dynamic_cast<wxWindow*>( m_toolMgr->GetToolHolder() );
444
445#if defined( _WIN32 ) || defined( __WXGTK__ )
446 // Mouse events may trigger regardless of window status (windows feature)
447 // However we need to avoid focus fighting (especially modals)
448 if( holderWindow && KIPLATFORM::UI::IsWindowActive( holderWindow ) )
449#else
450 if( holderWindow )
451#endif
452 {
453 holderWindow->SetFocus();
454 }
455 }
456
457 if( isMouseClick( type ) )
458 {
460 m_toolMgr->GetToolHolder()->GetToolCanvas()->SetFocus();
461 }
462
463 // Mouse handling
464 // Note: wxEVT_LEFT_DOWN event must always be skipped.
465 if( type == wxEVT_MOTION || type == wxEVT_MOUSEWHEEL ||
466#if wxCHECK_VERSION( 3, 1, 0 ) || defined( USE_OSX_MAGNIFY_EVENT )
467 type == wxEVT_MAGNIFY ||
468#endif
469 isMouseClick( type ) ||
470 // Event issued when mouse retains position in screen coordinates,
471 // but changes in world coordinates (e.g. autopanning)
473 {
474 wxMouseEvent* me = static_cast<wxMouseEvent*>( &aEvent );
475 int mods = decodeModifiers( me );
476
478 {
481
482 if( pos != m_lastMousePos )
483 {
484 motion = true;
485 m_lastMousePos = pos;
486 }
487 }
488
489 for( unsigned int i = 0; i < m_buttons.size(); i++ )
490 buttonEvents |= handleMouseButton( aEvent, i, motion );
491
493 {
494 if( !buttonEvents && motion )
495 {
496 evt = TOOL_EVENT( TC_MOUSE, TA_MOUSE_MOTION, mods );
497 evt->SetMousePosition( pos );
498 }
499 }
500 }
501 else if( type == wxEVT_CHAR_HOOK || type == wxEVT_CHAR )
502 {
503 wxKeyEvent* ke = static_cast<wxKeyEvent*>( &aEvent );
504
505 wxLogTrace( kicadTraceKeyEvent, wxS( "TOOL_DISPATCHER::DispatchWxEvent %s" ), dump( *ke ) );
506
507 // Do not process wxEVT_CHAR_HOOK for a shift-modified key, as ACTION_MANAGER::RunHotKey
508 // will run the un-shifted key and that's not what we want. Wait to get the translated
509 // key from wxEVT_CHAR.
510 // See https://gitlab.com/kicad/code/kicad/-/issues/1809
511 if( type == wxEVT_CHAR_HOOK && ke->GetModifiers() == wxMOD_SHIFT )
512 {
513 aEvent.Skip();
514 return;
515 }
516
517 keyIsEscape = ( ke->GetKeyCode() == WXK_ESCAPE );
518
519 if( KIUI::IsInputControlFocused( focus ) )
520 {
521 bool enabled = KIUI::IsInputControlEditable( focus );
522
523 // Never process key events for tools when a text entry has focus
524 if( enabled )
525 {
526 aEvent.Skip();
527 return;
528 }
529 // Even if not enabled, allow a copy out
530 else if( ke->GetModifiers() == wxMOD_CONTROL && ke->GetKeyCode() == 'C' )
531 {
532 aEvent.Skip();
533 return;
534 }
535 }
536
537 evt = GetToolEvent( ke, &keyIsSpecial );
538 }
539 else if( type == wxEVT_MENU_OPEN || type == wxEVT_MENU_CLOSE || type == wxEVT_MENU_HIGHLIGHT )
540 {
541 //
542 // wxWidgets has several issues that we have to work around:
543 //
544 // 1) wxWidgets 3.0.x Windows has a bug where wxEVT_MENU_OPEN and wxEVT_MENU_HIGHLIGHT
545 // events are not captured by the ACTON_MENU menus. So we forward them here.
546 // (FWIW, this one is fixed in wxWidgets 3.1.x.)
547 //
548 // 2) wxWidgets doesn't pass the menu pointer for wxEVT_MENU_HIGHLIGHT events. So we
549 // store the menu pointer from the wxEVT_MENU_OPEN call.
550 //
551 // 3) wxWidgets has no way to tell whether a command is from a menu selection or a
552 // hotkey. So we keep track of menu highlighting so we can differentiate.
553 //
554
555 static ACTION_MENU* currentMenu;
556
557 wxMenuEvent& menuEvent = *dynamic_cast<wxMenuEvent*>( &aEvent );
558
559 if( type == wxEVT_MENU_OPEN )
560 {
561 currentMenu = dynamic_cast<ACTION_MENU*>( menuEvent.GetMenu() );
562
563 if( currentMenu )
564 currentMenu->OnMenuEvent( menuEvent );
565 }
566 else if( type == wxEVT_MENU_HIGHLIGHT )
567 {
568 if( currentMenu )
569 currentMenu->OnMenuEvent( menuEvent );
570 }
571 else if( type == wxEVT_MENU_CLOSE )
572 {
573 if( currentMenu )
574 currentMenu->OnMenuEvent( menuEvent );
575
576 currentMenu = nullptr;
577 }
578
579 aEvent.Skip();
580 }
581
582 bool handled = false;
583
584 if( evt )
585 {
586 wxLogTrace( kicadTraceToolStack, wxS( "TOOL_DISPATCHER::DispatchWxEvent %s" ), evt->Format() );
587
588 handled = m_toolMgr->ProcessEvent( *evt );
589
590 wxLogTrace( kicadTraceToolStack, wxS( "TOOL_DISPATCHER::DispatchWxEvent - Handled: %s %s" ),
591 ( handled ? wxS( "true" ) : wxS( "false" ) ), evt->Format() );
592 }
593
594 // pass the event to the GUI, it might still be interested in it
595 // Note wxEVT_CHAR_HOOK event is already skipped for special keys not used by KiCad
596 // and wxEVT_LEFT_DOWN must be always Skipped.
597 //
598 // On OS X, key events are always meant to be caught. An uncaught key event is assumed
599 // to be a user input error by OS X (as they are pressing keys in a context where nothing
600 // is there to catch the event). This annoyingly makes OS X beep and/or flash the screen
601 // in Pcbnew and the footprint editor any time a hotkey is used. The correct procedure is
602 // to NOT pass wxEVT_CHAR events to the GUI under OS X.
603 //
604 // On Windows, avoid to call wxEvent::Skip for special keys because some keys
605 // (PAGE_UP, PAGE_DOWN) have predefined actions (like move thumbtrack cursor), and we do
606 // not want these actions executed (most are handled by KiCad)
607
608 if( !evt || type == wxEVT_LEFT_DOWN )
609 aEvent.Skip();
610
611 // Not handled wxEVT_CHAR must be Skipped (sent to GUI).
612 // Otherwise accelerators and shortcuts in main menu or toolbars are not seen.
613 // Escape key presses are never skipped by the handler since they correspond to tool cancel
614 // events, and if they aren't skipped then they are propagated to other frames (which we
615 // don't want).
616 if( ( type == wxEVT_CHAR || type == wxEVT_CHAR_HOOK )
617 && !keyIsSpecial
618 && !handled
619 && !keyIsEscape )
620 {
621 aEvent.Skip();
622 }
623
624 wxLogTrace( kicadTraceToolStack, "TOOL_DISPATCHER::DispatchWxEvent - Wx event skipped: %s",
625 ( aEvent.GetSkipped() ? "true" : "false" ) );
626}
Defines the structure of a menu based on ACTIONs.
Definition: action_menu.h:49
void OnMenuEvent(wxMenuEvent &aEvent)
virtual VECTOR2D GetMousePosition(bool aWorldCoordinates=true) const =0
Return the current mouse pointer position.
Hold a (potentially large) number of VIEW_ITEMs and renders them on a graphics device provided by the...
Definition: view.h:69
static const wxEventType EVT_REFRESH_MOUSE
virtual wxWindow * GetToolCanvas() const =0
Canvas access.
static const int DragDistanceThreshold
Mininum distance before drag is activated in the X axis.
static const int DragTimeThreshold
< The time threshold for a mouse button press that distinguishes between a single mouse click and a b...
virtual void ResetState()
Bring the dispatcher to its initial state.
virtual void DispatchWxEvent(wxEvent &aEvent)
Process wxEvents (mostly UI events), translate them to TOOL_EVENTs, and make tools handle those.
KIGFX::VIEW * getView()
Instance of tool manager that cooperates with the dispatcher.
int m_sysDragMinX
Maximum distance before drag is activated in the Y axis.
bool handleMouseButton(wxEvent &aEvent, int aIndex, bool aMotion)
Saves the state of key modifiers (Alt, Ctrl and so on).
int m_sysDragMinY
Handles mouse related events (click, motion, dragging).
VECTOR2D m_lastMousePosScreen
State of mouse buttons.
static int decodeModifiers(const wxKeyboardState *aState)
Stores all the information regarding a mouse button state.
TOOL_MANAGER * m_toolMgr
TOOL_DISPATCHER(TOOL_MANAGER *aToolMgr)
std::vector< BUTTON_STATE * > m_buttons
Returns the instance of VIEW, used by the application.
VECTOR2D m_lastMousePos
The last mouse cursor position (in world coordinates).
std::optional< TOOL_EVENT > GetToolEvent(wxKeyEvent *aKeyEvent, bool *aSpecialKeyFlag)
Map a wxWidgets key event to a TOOL_EVENT.
virtual ~TOOL_DISPATCHER()
Generic, UI-independent tool event.
Definition: tool_event.h:156
Master controller class:
Definition: tool_manager.h:55
bool ProcessEvent(const TOOL_EVENT &aEvent)
Propagate an event to tools that requested events of matching type(s).
TOOLS_HOLDER * GetToolHolder() const
Definition: tool_manager.h:296
KIGFX::VIEW_CONTROLS * GetViewControls() const
Definition: tool_manager.h:287
KIGFX::VIEW * GetView() const
Definition: tool_manager.h:285
const wxChar *const kicadTraceToolStack
Flag to enable tracing of the tool handling stack.
const wxChar *const kicadTraceKeyEvent
Flag to enable wxKeyEvent debug tracing.
void ignore_unused(const T &)
Definition: ignore.h:24
This file contains miscellaneous commonly used macros and functions.
void ForceTimerMessagesToBeCreatedIfNecessary()
Forces wxTimers to fire more promptly on Win32.
Definition: gtk/app.cpp:88
bool IsWindowActive(wxWindow *aWindow)
Check to see if the given window is the currently active window (e.g.
Definition: gtk/ui.cpp:50
bool IsInputControlFocused(wxWindow *aFocus=nullptr)
Check if a input control has focus.
Definition: ui_common.cpp:265
bool IsInputControlEditable(wxWindow *aControl)
Check if a input control has focus.
Definition: ui_common.cpp:298
bool contains(const _Container &__container, _Value __value)
Returns true if the container contains the given value.
Definition: kicad_algo.h:99
EDA_ANGLE abs(const EDA_ANGLE &aAngle)
Definition: eda_angle.h:401
< Stores information about a mouse button state
VECTOR2D dragOrigin
Point where dragging has started (in screen coordinates).
wxEventType dblClickEvent
Time stamp for the last mouse button press event.
wxEventType upEvent
The type of wxEvent that determines mouse button double click.
VECTOR2D downPosition
Determines the mouse button for which information are stored.
bool dragging
Flag indicating that dragging is active for the given button.
bool pressed
Point where dragging has started (in world coordinates).
BUTTON_STATE(TOOL_MOUSE_BUTTONS aButton, const wxEventType &aDownEvent, const wxEventType &aUpEvent, const wxEventType &aDblClickEvent)
wxLongLong downTimestamp
Restores initial state.
TOOL_MOUSE_BUTTONS button
The type of wxEvent that determines mouse button press.
void Reset()
Checks the current state of the button.
wxEventType downEvent
The type of wxEvent that determines mouse button release.
VECTOR2D dragOriginScreen
Point where click event has occurred.
static bool isMouseClick(wxEventType type)
bool isKeySpecialCode(int aKeyCode)
int translateSpecialCode(int aKeyCode)
static bool isKeyModifierOnly(int aKeyCode)
@ TA_MOUSE_CLICK
Definition: tool_event.h:62
@ TA_MOUSE_MOTION
Definition: tool_event.h:67
@ TA_MOUSE_UP
Definition: tool_event.h:64
@ TA_MOUSE_DRAG
Definition: tool_event.h:66
@ TA_MOUSE_DOWN
Definition: tool_event.h:65
@ TA_KEY_PRESSED
Definition: tool_event.h:71
@ TA_MOUSE_DBLCLICK
Definition: tool_event.h:63
@ TA_CANCEL_TOOL
Definition: tool_event.h:85
@ TC_COMMAND
Definition: tool_event.h:52
@ TC_MOUSE
Definition: tool_event.h:50
@ TC_KEYBOARD
Definition: tool_event.h:51
@ MD_ALT
Definition: tool_event.h:140
@ MD_CTRL
Definition: tool_event.h:139
TOOL_MOUSE_BUTTONS
Definition: tool_event.h:125
@ BUT_AUX1
Definition: tool_event.h:130
@ BUT_MIDDLE
Definition: tool_event.h:129
@ BUT_LEFT
Definition: tool_event.h:127
@ BUT_RIGHT
Definition: tool_event.h:128
@ BUT_AUX2
Definition: tool_event.h:131
wxString dump(const wxArrayString &aArray)
Debug helper for printing wxArrayString contents.
wxLogTrace helper definitions.
WX_VIEW_CONTROLS class definition.