KiCad PCB EDA Suite
Loading...
Searching...
No Matches
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-2024 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 <core/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 wxFAIL_MSG( wxT( "unknown button" ) );
119 return false;
120 }
121 }
122};
123
124
126 m_toolMgr( aToolMgr ),
127 m_currentMenu( nullptr )
128{
129 m_sysDragMinX = wxSystemSettings::GetMetric( wxSYS_DRAG_X );
130 m_sysDragMinY = wxSystemSettings::GetMetric( wxSYS_DRAG_Y );
131
134
135 m_buttons.push_back( new BUTTON_STATE( BUT_LEFT, wxEVT_LEFT_DOWN,
136 wxEVT_LEFT_UP, wxEVT_LEFT_DCLICK ) );
137 m_buttons.push_back( new BUTTON_STATE( BUT_RIGHT, wxEVT_RIGHT_DOWN,
138 wxEVT_RIGHT_UP, wxEVT_RIGHT_DCLICK ) );
139 m_buttons.push_back( new BUTTON_STATE( BUT_MIDDLE, wxEVT_MIDDLE_DOWN,
140 wxEVT_MIDDLE_UP, wxEVT_MIDDLE_DCLICK ) );
141 m_buttons.push_back( new BUTTON_STATE( BUT_AUX1, wxEVT_AUX1_DOWN,
142 wxEVT_AUX1_UP, wxEVT_AUX1_DCLICK ) );
143 m_buttons.push_back( new BUTTON_STATE( BUT_AUX2, wxEVT_AUX2_DOWN,
144 wxEVT_AUX2_UP, wxEVT_AUX2_DCLICK ) );
145
146 ResetState();
147}
148
149
151{
152 for( BUTTON_STATE* st : m_buttons )
153 delete st;
154}
155
156
158{
159 for( BUTTON_STATE* st : m_buttons )
160 st->Reset();
161}
162
163
165{
166 return m_toolMgr->GetView();
167}
168
169
170bool TOOL_DISPATCHER::handleMouseButton( wxEvent& aEvent, int aIndex, bool aMotion )
171{
172 BUTTON_STATE* st = m_buttons[aIndex];
173 wxEventType type = aEvent.GetEventType();
174 std::optional<TOOL_EVENT> evt;
175 bool isClick = false;
176
177// bool up = type == st->upEvent;
178// bool down = type == st->downEvent;
179 bool up = false, down = false;
180 bool dblClick = type == st->dblClickEvent;
181 bool state = st->GetState();
182
183 if( !dblClick )
184 {
185 // Sometimes the dispatcher does not receive mouse button up event, so it stays
186 // in the dragging mode even if the mouse button is not held anymore
187 if( st->pressed && !state )
188 up = true;
189 // Don't apply same logic to down events as it kills touchpad tapping
190 else if( !st->pressed && type == st->downEvent )
191 down = true;
192 }
193
194 int mods = decodeModifiers( static_cast<wxMouseEvent*>( &aEvent ) );
195 int args = st->button | mods;
196
197 if( down ) // Handle mouse button press
198 {
199 st->downTimestamp = wxGetLocalTimeMillis();
200
201 if( !st->pressed ) // save the drag origin on the first click only
202 {
205 }
206
208 st->pressed = true;
209 evt = TOOL_EVENT( TC_MOUSE, TA_MOUSE_DOWN, args );
210 }
211 else if( up ) // Handle mouse button release
212 {
213 st->pressed = false;
214
215 if( st->dragging )
216 evt = TOOL_EVENT( TC_MOUSE, TA_MOUSE_UP, args );
217 else
218 isClick = true;
219
220 if( isClick )
221 evt = TOOL_EVENT( TC_MOUSE, TA_MOUSE_CLICK, args );
222
223 st->dragging = false;
224 }
225 else if( dblClick )
226 {
227 evt = TOOL_EVENT( TC_MOUSE, TA_MOUSE_DBLCLICK, args );
228 }
229
230 if( st->pressed && aMotion )
231 {
232 if( !st->dragging )
233 {
234#ifdef __WXMAC__
235 if( wxGetLocalTimeMillis() - st->downTimestamp > DragTimeThreshold )
236 st->dragging = true;
237#endif
239
240 if( abs( offset.x ) > m_sysDragMinX || abs( offset.y ) > m_sysDragMinY )
241 st->dragging = true;
242
243 }
244
245 if( st->dragging )
246 {
247 evt = TOOL_EVENT( TC_MOUSE, TA_MOUSE_DRAG, args );
248 evt->setMouseDragOrigin( st->dragOrigin );
249 evt->setMouseDelta( m_lastMousePos - st->dragOrigin );
250 }
251 }
252
253 if( evt )
254 {
255 evt->SetMousePosition( isClick ? st->downPosition : m_lastMousePos );
256 m_toolMgr->ProcessEvent( *evt );
257
258 return true;
259 }
260
261 return false;
262}
263
264
265// Helper function to know if a special key ( see key list ) should be captured
266// or if the event can be skipped
267// on Linux, the event must be passed to the GUI if they are not used by KiCad,
268// especially the wxEVENT_CHAR_HOOK, if it is not handled
269// Some keys have a predefined action in wxWidgets so, even if not used,
270// the even will be not skipped
271// the unused keys listed in isKeySpecialCode() will be not skipped
272bool isKeySpecialCode( int aKeyCode )
273{
274 // These keys have predefined actions (like move thumbtrack cursor),
275 // and we do not want these actions executed
276 const std::vector<enum wxKeyCode> special_keys =
277 {
278 WXK_PAGEUP, WXK_PAGEDOWN,
279 WXK_NUMPAD_PAGEUP, WXK_NUMPAD_PAGEDOWN
280 };
281
282 return alg::contains( special_keys, aKeyCode );
283}
284
285
286// Helper function to know if a key should be managed by DispatchWxEvent()
287// or if the event can be ignored and skipped because the key is only a modifier
288// that is not used alone in kicad
289static bool isKeyModifierOnly( int aKeyCode )
290{
291 static std::vector<enum wxKeyCode> special_keys =
292 {
293 WXK_CONTROL, WXK_RAW_CONTROL, WXK_SHIFT, WXK_ALT
294 };
295
296 return alg::contains( special_keys, aKeyCode );
297}
298
299
300static bool isMouseClick( wxEventType type )
301{
302 return type == wxEVT_LEFT_DOWN || type == wxEVT_LEFT_UP || type == wxEVT_LEFT_DCLICK
303 || type == wxEVT_MIDDLE_DOWN || type == wxEVT_MIDDLE_UP || type == wxEVT_MIDDLE_DCLICK
304 || type == wxEVT_RIGHT_DOWN || type == wxEVT_RIGHT_UP || type == wxEVT_RIGHT_DCLICK
305 || type == wxEVT_AUX1_DOWN || type == wxEVT_AUX1_UP || type == wxEVT_AUX1_DCLICK
306 || type == wxEVT_AUX2_DOWN || type == wxEVT_AUX2_UP || type == wxEVT_AUX2_DCLICK;
307}
308
309
310/* A helper class that convert some special key codes to an equivalent.
311 * WXK_NUMPAD_UP to WXK_UP,
312 * WXK_NUMPAD_DOWN to WXK_DOWN,
313 * WXK_NUMPAD_LEFT to WXK_LEFT,
314 * WXK_NUMPAD_RIGHT,
315 * WXK_NUMPAD_PAGEUP,
316 * WXK_NUMPAD_PAGEDOWN
317 * note:
318 * wxEVT_CHAR_HOOK does this conversion when it is skipped by firing a wxEVT_CHAR
319 * with this converted code, but we do not skip these key events because they also
320 * have default action (scroll the panel)
321 */
322int translateSpecialCode( int aKeyCode )
323{
324 switch( aKeyCode )
325 {
326 case WXK_NUMPAD_UP: return WXK_UP;
327 case WXK_NUMPAD_DOWN: return WXK_DOWN;
328 case WXK_NUMPAD_LEFT: return WXK_LEFT;
329 case WXK_NUMPAD_RIGHT: return WXK_RIGHT;
330 case WXK_NUMPAD_PAGEUP: return WXK_PAGEUP;
331 case WXK_NUMPAD_PAGEDOWN: return WXK_PAGEDOWN;
332 default: break;
333 };
334
335 return aKeyCode;
336}
337
338
339std::optional<TOOL_EVENT> TOOL_DISPATCHER::GetToolEvent( wxKeyEvent* aKeyEvent, bool* keyIsSpecial )
340{
341 std::optional<TOOL_EVENT> evt;
342 int key = aKeyEvent->GetKeyCode();
343 int unicode_key = aKeyEvent->GetUnicodeKey();
344
345 // This wxEVT_CHAR_HOOK event can be ignored: not useful in Kicad
346 if( isKeyModifierOnly( key ) )
347 {
348 aKeyEvent->Skip();
349 return evt;
350 }
351
352 wxLogTrace( kicadTraceKeyEvent, wxS( "TOOL_DISPATCHER::GetToolEvent %s" ), dump( *aKeyEvent ) );
353
354 // if the key event must be skipped, skip it here if the event is a wxEVT_CHAR_HOOK
355 // and do nothing.
356 *keyIsSpecial = isKeySpecialCode( key );
357
358 if( aKeyEvent->GetEventType() == wxEVT_CHAR_HOOK )
359 key = translateSpecialCode( key );
360
361 int mods = decodeModifiers( aKeyEvent );
362
363 if( mods & MD_CTRL )
364 {
365 // wxWidgets maps key codes related to Ctrl+letter handled by CHAR_EVT
366 // (http://docs.wxwidgets.org/trunk/classwx_key_event.html):
367 // char events for ASCII letters in this case carry codes corresponding to the ASCII
368 // value of Ctrl-Latter, i.e. 1 for Ctrl-A, 2 for Ctrl-B and so on until 26 for Ctrl-Z.
369 // They are remapped here to be more easy to handle in code
370 // Note also on OSX wxWidgets has a different behavior and the mapping is made
371 // only for ctrl+'A' to ctlr+'Z' (unicode code return 'A' to 'Z').
372 // Others OS return WXK_CONTROL_A to WXK_CONTROL_Z, and Ctrl+'M' returns the same code as
373 // the return key, so the remapping does not use the unicode key value.
374#ifdef __APPLE__
375 if( unicode_key >= 'A' && unicode_key <= 'Z' && key >= WXK_CONTROL_A && key <= WXK_CONTROL_Z )
376#else
377 ignore_unused( unicode_key );
378
379 if( key >= WXK_CONTROL_A && key <= WXK_CONTROL_Z )
380#endif
381 key += 'A' - 1;
382 }
383
384#ifdef __APPLE__
385 if( mods & MD_ALT )
386 {
387 // OSX maps a bunch of commonly used extended-ASCII characters onto the keyboard
388 // using the ALT key. Since we use ALT for some of our hotkeys, we need to map back
389 // to the underlying keys. The kVK_ANSI_* values come from Apple and are said to be
390 // hardware independent.
391 switch( aKeyEvent->GetRawKeyCode() )
392 {
393 case /* kVK_ANSI_1 */ 0x12: key = '1'; break;
394 case /* kVK_ANSI_2 */ 0x13: key = '2'; break;
395 case /* kVK_ANSI_3 */ 0x14: key = '3'; break;
396 case /* kVK_ANSI_4 */ 0x15: key = '4'; break;
397 case /* kVK_ANSI_6 */ 0x16: key = '6'; break;
398 case /* kVK_ANSI_5 */ 0x17: key = '5'; break;
399 case /* kVK_ANSI_Equal */ 0x18: key = '='; break;
400 case /* kVK_ANSI_9 */ 0x19: key = '9'; break;
401 case /* kVK_ANSI_7 */ 0x1A: key = '7'; break;
402 case /* kVK_ANSI_Minus */ 0x1B: key = '-'; break;
403 case /* kVK_ANSI_8 */ 0x1C: key = '8'; break;
404 case /* kVK_ANSI_0 */ 0x1D: key = '0'; break;
405 default: ;
406 }
407 }
408#endif
409
410 if( key == WXK_ESCAPE ) // ESC is the special key for canceling tools
411 evt = TOOL_EVENT( TC_COMMAND, TA_CANCEL_TOOL, WXK_ESCAPE );
412 else
413 evt = TOOL_EVENT( TC_KEYBOARD, TA_KEY_PRESSED, key | mods );
414
415 return evt;
416}
417
418
419void TOOL_DISPATCHER::DispatchWxEvent( wxEvent& aEvent )
420{
421 bool motion = false;
422 bool buttonEvents = false;
423 VECTOR2D pos;
424 std::optional<TOOL_EVENT> evt;
425 bool keyIsEscape = false; // True if the keypress was the escape key
426 bool keyIsSpecial = false; // True if the key is a special key code
427 wxWindow* focus = wxWindow::FindFocus();
428
429 // Required in win32 to ensure wxTimer events get scheduled in between other events
430 // Or else we may stall them out entirely and never get them during actions like rapid
431 // mouse moves.
433
434 wxEventType type = aEvent.GetEventType();
435
436 // Sometimes there is no window that has the focus (it happens when another PCB_BASE_FRAME
437 // is opened and is iconized on Windows).
438 // In this case, give the focus to the parent frame (GAL canvas itself does not accept the
439 // focus when iconized for some obscure reason)
440 if( focus == nullptr )
441 {
442 wxWindow* holderWindow = dynamic_cast<wxWindow*>( m_toolMgr->GetToolHolder() );
443
444#if defined( _WIN32 ) || defined( __WXGTK__ )
445 // Mouse events may trigger regardless of window status (windows feature)
446 // However we need to avoid focus fighting (especially modals)
447 if( holderWindow && KIPLATFORM::UI::IsWindowActive( holderWindow ) )
448#else
449 if( holderWindow )
450#endif
451 {
452 holderWindow->SetFocus();
453 }
454 }
455
456 if( isMouseClick( type ) )
457 {
459 m_toolMgr->GetToolHolder()->GetToolCanvas()->SetFocus();
460 }
461
462 // Mouse handling
463 // Note: wxEVT_LEFT_DOWN event must always be skipped.
464 if( type == wxEVT_MOTION || type == wxEVT_MOUSEWHEEL ||
465 type == wxEVT_MAGNIFY ||
466 isMouseClick( type ) ||
467 // Event issued when mouse retains position in screen coordinates,
468 // but changes in world coordinates (e.g. autopanning)
470 {
471 wxMouseEvent* me = static_cast<wxMouseEvent*>( &aEvent );
472 int mods = decodeModifiers( me );
473
475 {
478
479 if( pos != m_lastMousePos )
480 {
481 motion = true;
482 m_lastMousePos = pos;
483 }
484 }
485
486 for( unsigned int i = 0; i < m_buttons.size(); i++ )
487 buttonEvents |= handleMouseButton( aEvent, i, motion );
488
490 {
491 if( !buttonEvents && motion )
492 {
493 evt = TOOL_EVENT( TC_MOUSE, TA_MOUSE_MOTION, mods );
494 evt->SetMousePosition( pos );
495 }
496 }
497 }
498 else if( type == wxEVT_CHAR_HOOK || type == wxEVT_CHAR )
499 {
500 wxKeyEvent* ke = static_cast<wxKeyEvent*>( &aEvent );
501
502 wxLogTrace( kicadTraceKeyEvent, wxS( "TOOL_DISPATCHER::DispatchWxEvent %s" ), dump( *ke ) );
503
504 // Do not process wxEVT_CHAR_HOOK for a shift-modified key, as ACTION_MANAGER::RunHotKey
505 // will run the un-shifted key and that's not what we want. Wait to get the translated
506 // key from wxEVT_CHAR.
507 // See https://gitlab.com/kicad/code/kicad/-/issues/1809
508 if( type == wxEVT_CHAR_HOOK && ke->GetModifiers() == wxMOD_SHIFT )
509 {
510 aEvent.Skip();
511 return;
512 }
513
514 keyIsEscape = ( ke->GetKeyCode() == WXK_ESCAPE );
515
516 if( KIUI::IsInputControlFocused( focus ) )
517 {
518 bool enabled = KIUI::IsInputControlEditable( focus );
519
520 // Never process key events for tools when a text entry has focus
521 if( enabled )
522 {
523 aEvent.Skip();
524 return;
525 }
526 // Even if not enabled, allow a copy out
527 else if( ke->GetModifiers() == wxMOD_CONTROL && ke->GetKeyCode() == 'C' )
528 {
529 aEvent.Skip();
530 return;
531 }
532 }
533
534 evt = GetToolEvent( ke, &keyIsSpecial );
535 }
536 else if( type == wxEVT_MENU_OPEN || type == wxEVT_MENU_CLOSE || type == wxEVT_MENU_HIGHLIGHT )
537 {
538 wxMenuEvent* tmp = dynamic_cast<wxMenuEvent*>( &aEvent );
539
540 // Something is amiss if the event has these types and isn't a menu event, so bail out on
541 // its processing
542 if( !tmp )
543 {
544 aEvent.Skip();
545 return;
546 }
547
548 wxMenuEvent& menuEvent = *tmp;
549
550#if wxCHECK_VERSION( 3, 2, 0 )
551 // Forward the event to the menu for processing
552 if( ACTION_MENU* currentMenu = dynamic_cast<ACTION_MENU*>( menuEvent.GetMenu() ) )
553 currentMenu->OnMenuEvent( menuEvent );
554#else
555 //
556 // wxWidgets has several issues that we have to work around:
557 //
558 // 1) wxWidgets 3.0.x Windows has a bug where wxEVT_MENU_OPEN and wxEVT_MENU_HIGHLIGHT
559 // events are not captured by the ACTON_MENU menus. So we forward them here.
560 // (FWIW, this one is fixed in wxWidgets 3.1.x.)
561 //
562 // 2) wxWidgets doesn't pass the menu pointer for wxEVT_MENU_HIGHLIGHT events. So we
563 // store the menu pointer from the wxEVT_MENU_OPEN call.
564 //
565 // 3) wxWidgets has no way to tell whether a command is from a menu selection or a
566 // hotkey. So we keep track of menu highlighting so we can differentiate.
567 //
568
569 if( type == wxEVT_MENU_OPEN )
570 {
571 m_currentMenu = dynamic_cast<ACTION_MENU*>( menuEvent.GetMenu() );
572
573 if( m_currentMenu )
574 m_currentMenu->OnMenuEvent( menuEvent );
575 }
576 else if( type == wxEVT_MENU_HIGHLIGHT )
577 {
578 if( m_currentMenu )
579 m_currentMenu->OnMenuEvent( menuEvent );
580 }
581 else if( type == wxEVT_MENU_CLOSE )
582 {
583 if( m_currentMenu )
584 m_currentMenu->OnMenuEvent( menuEvent );
585
586 m_currentMenu = nullptr;
587 }
588#endif
589
590 aEvent.Skip();
591 }
592
593 bool handled = false;
594
595 if( evt )
596 {
597 wxLogTrace( kicadTraceToolStack, wxS( "TOOL_DISPATCHER::DispatchWxEvent %s" ), evt->Format() );
598
599 handled = m_toolMgr->ProcessEvent( *evt );
600
601 wxLogTrace( kicadTraceToolStack, wxS( "TOOL_DISPATCHER::DispatchWxEvent - Handled: %s %s" ),
602 ( handled ? wxS( "true" ) : wxS( "false" ) ), evt->Format() );
603 }
604
605 // pass the event to the GUI, it might still be interested in it
606 // Note wxEVT_CHAR_HOOK event is already skipped for special keys not used by KiCad
607 // and wxEVT_LEFT_DOWN must be always Skipped.
608 //
609 // On OS X, key events are always meant to be caught. An uncaught key event is assumed
610 // to be a user input error by OS X (as they are pressing keys in a context where nothing
611 // is there to catch the event). This annoyingly makes OS X beep and/or flash the screen
612 // in Pcbnew and the footprint editor any time a hotkey is used. The correct procedure is
613 // to NOT pass wxEVT_CHAR events to the GUI under OS X.
614 //
615 // On Windows, avoid to call wxEvent::Skip for special keys because some keys
616 // (PAGE_UP, PAGE_DOWN) have predefined actions (like move thumbtrack cursor), and we do
617 // not want these actions executed (most are handled by KiCad)
618
619 if( !evt || type == wxEVT_LEFT_DOWN )
620 aEvent.Skip();
621
622 // Not handled wxEVT_CHAR must be Skipped (sent to GUI).
623 // Otherwise accelerators and shortcuts in main menu or toolbars are not seen.
624 // Escape key presses are never skipped by the handler since they correspond to tool cancel
625 // events, and if they aren't skipped then they are propagated to other frames (which we
626 // don't want).
627 if( ( type == wxEVT_CHAR || type == wxEVT_CHAR_HOOK )
628 && !keyIsSpecial
629 && !handled
630 && !keyIsEscape )
631 {
632 aEvent.Skip();
633 }
634
635 wxLogTrace( kicadTraceToolStack, "TOOL_DISPATCHER::DispatchWxEvent - Wx event skipped: %s",
636 ( aEvent.GetSkipped() ? "true" : "false" ) );
637}
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:68
static const wxEventType EVT_REFRESH_MOUSE
virtual wxWindow * GetToolCanvas() const =0
Canvas access.
static const int DragDistanceThreshold
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()
Saves the state of key modifiers (Alt, Ctrl and so on).
int m_sysDragMinX
Mininum distance before drag is activated in the X axis.
bool handleMouseButton(wxEvent &aEvent, int aIndex, bool aMotion)
< Handles mouse related events (click, motion, dragging).
int m_sysDragMinY
Maximum distance before drag is activated in the Y axis.
VECTOR2D m_lastMousePosScreen
The last mouse cursor position (in screen coordinates).
static int decodeModifiers(const wxKeyboardState *aState)
TOOL_MANAGER * m_toolMgr
The menu from the main menubar currently shown (if any; nullptr otherwise)
TOOL_DISPATCHER(TOOL_MANAGER *aToolMgr)
std::vector< BUTTON_STATE * > m_buttons
Instance of tool manager that cooperates with the dispatcher.
VECTOR2D m_lastMousePos
The last mouse cursor position (in world coordinates).
ACTION_MENU * m_currentMenu
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:167
Master controller class:
Definition: tool_manager.h:57
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:397
KIGFX::VIEW_CONTROLS * GetViewControls() const
Definition: tool_manager.h:388
KIGFX::VIEW * GetView() const
Definition: tool_manager.h:386
const wxChar *const kicadTraceKeyEvent
Flag to enable wxKeyEvent debug tracing.
const wxChar *const kicadTraceToolStack
Flag to enable tracing of the tool handling stack.
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:95
bool IsWindowActive(wxWindow *aWindow)
Check to see if the given window is the currently active window (e.g.
Definition: gtk/ui.cpp:73
KICOMMON_API bool IsInputControlFocused(wxWindow *aFocus=nullptr)
Check if a input control has focus.
Definition: ui_common.cpp:260
KICOMMON_API bool IsInputControlEditable(wxWindow *aControl)
Check if a input control has focus.
Definition: ui_common.cpp:297
bool contains(const _Container &__container, _Value __value)
Returns true if the container contains the given value.
Definition: kicad_algo.h:100
< 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:66
@ TA_MOUSE_MOTION
Definition: tool_event.h:71
@ TA_MOUSE_UP
Definition: tool_event.h:68
@ TA_MOUSE_DRAG
Definition: tool_event.h:70
@ TA_MOUSE_DOWN
Definition: tool_event.h:69
@ TA_KEY_PRESSED
Definition: tool_event.h:75
@ TA_MOUSE_DBLCLICK
Definition: tool_event.h:67
@ TA_CANCEL_TOOL
Definition: tool_event.h:89
@ TC_COMMAND
Definition: tool_event.h:56
@ TC_MOUSE
Definition: tool_event.h:54
@ TC_KEYBOARD
Definition: tool_event.h:55
@ MD_ALT
Definition: tool_event.h:144
@ MD_CTRL
Definition: tool_event.h:143
TOOL_MOUSE_BUTTONS
Definition: tool_event.h:129
@ BUT_AUX1
Definition: tool_event.h:134
@ BUT_MIDDLE
Definition: tool_event.h:133
@ BUT_LEFT
Definition: tool_event.h:131
@ BUT_RIGHT
Definition: tool_event.h:132
@ BUT_AUX2
Definition: tool_event.h:135
wxString dump(const wxArrayString &aArray)
Debug helper for printing wxArrayString contents.
wxLogTrace helper definitions.
WX_VIEW_CONTROLS class definition.