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 The 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
27
28#include <bit>
29#include <optional>
30
31#include <wx/log.h>
32#include <wx/stc/stc.h>
33#include <wx/settings.h>
34
35#include <core/ignore.h>
36#include <macros.h>
37#include <trace_helpers.h>
38#include <tool/tool_manager.h>
39#include <tool/actions.h>
40#include <tool/action_manager.h>
41#include <tool/action_menu.h>
42#include <view/view.h>
44#include <eda_draw_frame.h>
45#include <core/kicad_algo.h>
46
47#include <kiplatform/app.h>
48#include <kiplatform/ui.h>
49
50
53{
54 BUTTON_STATE( TOOL_MOUSE_BUTTONS aButton, const wxEventType& aDownEvent,
55 const wxEventType& aUpEvent, const wxEventType& aDblClickEvent ) :
56 dragging( false ),
57 pressed( false ),
58 button( aButton ),
59 downEvent( aDownEvent ),
60 upEvent( aUpEvent ),
61 dblClickEvent( aDblClickEvent )
62 {};
63
66
68 bool pressed;
69
72
75
78
81
83 wxEventType downEvent;
84
86 wxEventType upEvent;
87
89 wxEventType dblClickEvent;
90
92 wxLongLong downTimestamp;
93
95 void Reset()
96 {
97 dragging = false;
98 pressed = false;
99 }
100
102 bool GetState() const
103 {
104 wxMouseState mouseState = wxGetMouseState();
105
106 switch( button )
107 {
108 case BUT_LEFT:
109 return mouseState.LeftIsDown();
110
111 case BUT_MIDDLE:
112 return mouseState.MiddleIsDown();
113
114 case BUT_RIGHT:
115 return mouseState.RightIsDown();
116
117 case BUT_AUX1:
118 return mouseState.Aux1IsDown();
119
120 case BUT_AUX2:
121 return mouseState.Aux2IsDown();
122
123 default:
124 wxFAIL_MSG( wxT( "unknown button" ) );
125 return false;
126 }
127 }
128};
129
130
132 m_toolMgr( aToolMgr )
133{
134 m_sysDragMinX = wxSystemSettings::GetMetric( wxSYS_DRAG_X );
135 m_sysDragMinY = wxSystemSettings::GetMetric( wxSYS_DRAG_Y );
136
139
140 m_buttons.push_back( new BUTTON_STATE( BUT_LEFT, wxEVT_LEFT_DOWN,
141 wxEVT_LEFT_UP, wxEVT_LEFT_DCLICK ) );
142 m_buttons.push_back( new BUTTON_STATE( BUT_RIGHT, wxEVT_RIGHT_DOWN,
143 wxEVT_RIGHT_UP, wxEVT_RIGHT_DCLICK ) );
144 m_buttons.push_back( new BUTTON_STATE( BUT_MIDDLE, wxEVT_MIDDLE_DOWN,
145 wxEVT_MIDDLE_UP, wxEVT_MIDDLE_DCLICK ) );
146 m_buttons.push_back( new BUTTON_STATE( BUT_AUX1, wxEVT_AUX1_DOWN,
147 wxEVT_AUX1_UP, wxEVT_AUX1_DCLICK ) );
148 m_buttons.push_back( new BUTTON_STATE( BUT_AUX2, wxEVT_AUX2_DOWN,
149 wxEVT_AUX2_UP, wxEVT_AUX2_DCLICK ) );
150
151 ResetState();
152}
153
154
156{
157 for( BUTTON_STATE* st : m_buttons )
158 delete st;
159}
160
161
163{
164 for( BUTTON_STATE* st : m_buttons )
165 st->Reset();
166}
167
168
170{
171 return m_toolMgr->GetView();
172}
173
174
175bool TOOL_DISPATCHER::handleMouseButton( wxEvent& aEvent, int aIndex, bool aMotion )
176{
177 BUTTON_STATE* st = m_buttons[aIndex];
178 wxEventType type = aEvent.GetEventType();
179 std::optional<TOOL_EVENT> evt;
180 bool isClick = false;
181
182// bool up = type == st->upEvent;
183// bool down = type == st->downEvent;
184 bool up = false, down = false;
185 bool dblClick = type == st->dblClickEvent;
186 bool state = st->GetState();
187
188 if( !dblClick )
189 {
190 // Sometimes the dispatcher does not receive mouse button up event, so it stays
191 // in the dragging mode even if the mouse button is not held anymore
192 if( st->pressed && !state )
193 up = true;
194 // Don't apply same logic to down events as it kills touchpad tapping
195 else if( !st->pressed && type == st->downEvent )
196 down = true;
197 }
198
199 int mods = decodeModifiers( static_cast<wxMouseEvent*>( &aEvent ) );
200 int args = st->button | mods;
201
202 if( down ) // Handle mouse button press
203 {
204 st->downTimestamp = wxGetLocalTimeMillis();
205
206 if( !st->pressed ) // save the drag origin on the first click only
207 {
210 }
211
213 st->pressed = true;
214 evt = TOOL_EVENT( TC_MOUSE, TA_MOUSE_DOWN, args );
215 }
216 else if( up ) // Handle mouse button release
217 {
218 st->pressed = false;
219
220 if( st->dragging )
221 evt = TOOL_EVENT( TC_MOUSE, TA_MOUSE_UP, args );
222 else
223 isClick = true;
224
225 if( isClick )
226 evt = TOOL_EVENT( TC_MOUSE, TA_MOUSE_CLICK, args );
227
228 st->dragging = false;
229 }
230 else if( dblClick )
231 {
232 evt = TOOL_EVENT( TC_MOUSE, TA_MOUSE_DBLCLICK, args );
233 }
234
235 if( st->pressed && aMotion )
236 {
237 if( !st->dragging )
238 {
239#ifdef __WXMAC__
240 if( wxGetLocalTimeMillis() - st->downTimestamp > DragTimeThreshold )
241 st->dragging = true;
242#endif
244
245 if( abs( offset.x ) > m_sysDragMinX || abs( offset.y ) > m_sysDragMinY )
246 st->dragging = true;
247
248 }
249
250 if( st->dragging )
251 {
252 evt = TOOL_EVENT( TC_MOUSE, TA_MOUSE_DRAG, args );
253 evt->setMouseDragOrigin( st->dragOrigin );
254 evt->setMouseDelta( m_lastMousePos - st->dragOrigin );
255 }
256 }
257
258 if( evt )
259 {
260 evt->SetMousePosition( isClick ? st->downPosition : m_lastMousePos );
261 m_toolMgr->ProcessEvent( *evt );
262
263 return true;
264 }
265
266 return false;
267}
268
269
278bool isKeySpecialCode( int aKeyCode )
279{
280 // These keys have predefined actions (like move thumbtrack cursor),
281 // and we do not want these actions executed
282 const std::vector<enum wxKeyCode> special_keys =
283 {
284 WXK_PAGEUP, WXK_PAGEDOWN,
285 WXK_NUMPAD_PAGEUP, WXK_NUMPAD_PAGEDOWN
286 };
287
288 return alg::contains( special_keys, aKeyCode );
289}
290
291
296static bool isKeyModifierOnly( int aKeyCode )
297{
298 static std::vector<enum wxKeyCode> special_keys =
299 {
300 WXK_CONTROL, WXK_RAW_CONTROL, WXK_SHIFT, WXK_ALT
301 };
302
303 return alg::contains( special_keys, aKeyCode );
304}
305
306
307static bool isMouseClick( wxEventType type )
308{
309 return type == wxEVT_LEFT_DOWN || type == wxEVT_LEFT_UP || type == wxEVT_LEFT_DCLICK
310 || type == wxEVT_MIDDLE_DOWN || type == wxEVT_MIDDLE_UP || type == wxEVT_MIDDLE_DCLICK
311 || type == wxEVT_RIGHT_DOWN || type == wxEVT_RIGHT_UP || type == wxEVT_RIGHT_DCLICK
312 || type == wxEVT_AUX1_DOWN || type == wxEVT_AUX1_UP || type == wxEVT_AUX1_DCLICK
313 || type == wxEVT_AUX2_DOWN || type == wxEVT_AUX2_UP || type == wxEVT_AUX2_DCLICK;
314}
315
316
331int translateSpecialCode( int aKeyCode )
332{
333 switch( aKeyCode )
334 {
335 case WXK_NUMPAD_UP: return WXK_UP;
336 case WXK_NUMPAD_DOWN: return WXK_DOWN;
337 case WXK_NUMPAD_LEFT: return WXK_LEFT;
338 case WXK_NUMPAD_RIGHT: return WXK_RIGHT;
339 case WXK_NUMPAD_PAGEUP: return WXK_PAGEUP;
340 case WXK_NUMPAD_PAGEDOWN: return WXK_PAGEDOWN;
341 default: break;
342 };
343
344 return aKeyCode;
345}
346
347
348std::optional<TOOL_EVENT> TOOL_DISPATCHER::GetToolEvent( wxKeyEvent* aKeyEvent, bool* keyIsSpecial )
349{
350 std::optional<TOOL_EVENT> evt;
351 int key = aKeyEvent->GetKeyCode();
352 int unicode_key = aKeyEvent->GetUnicodeKey();
353
354 // This wxEVT_CHAR_HOOK event can be ignored: not useful in KiCad
355 if( isKeyModifierOnly( key ) )
356 {
357 aKeyEvent->Skip();
358 return evt;
359 }
360
361 wxLogTrace( kicadTraceKeyEvent, wxS( "TOOL_DISPATCHER::GetToolEvent %s" ), dump( *aKeyEvent ) );
362
363 // if the key event must be skipped, skip it here if the event is a wxEVT_CHAR_HOOK
364 // and do nothing.
365 *keyIsSpecial = isKeySpecialCode( key );
366
367 if( aKeyEvent->GetEventType() == wxEVT_CHAR_HOOK )
368 key = translateSpecialCode( key );
369
370 int mods = decodeModifiers( aKeyEvent );
371
372 if( mods & MD_CTRL )
373 {
374 // wxWidgets maps key codes related to Ctrl+letter handled by CHAR_EVT
375 // (http://docs.wxwidgets.org/trunk/classwx_key_event.html):
376 // char events for ASCII letters in this case carry codes corresponding to the ASCII
377 // value of Ctrl-Latter, i.e. 1 for Ctrl-A, 2 for Ctrl-B and so on until 26 for Ctrl-Z.
378 // They are remapped here to be more easy to handle in code
379 // Note also on OSX wxWidgets has a different behavior and the mapping is made
380 // only for ctrl+'A' to ctlr+'Z' (unicode code return 'A' to 'Z').
381 // Others OS return WXK_CONTROL_A to WXK_CONTROL_Z, and Ctrl+'M' returns the same code as
382 // the return key, so the remapping does not use the unicode key value.
383#ifdef __APPLE__
384 if( unicode_key >= 'A' && unicode_key <= 'Z' && key >= WXK_CONTROL_A && key <= WXK_CONTROL_Z )
385#else
386 ignore_unused( unicode_key );
387
388 if( key >= WXK_CONTROL_A && key <= WXK_CONTROL_Z )
389#endif
390 key += 'A' - 1;
391 }
392
393#ifdef __APPLE__
394 if( mods & MD_ALT )
395 {
396 // OSX maps a bunch of commonly used extended-ASCII characters onto the keyboard
397 // using the ALT key. Since we use ALT for some of our hotkeys, we need to map back
398 // to the underlying keys. The kVK_ANSI_* values come from Apple and are said to be
399 // hardware independent.
400 switch( aKeyEvent->GetRawKeyCode() )
401 {
402 case /* kVK_ANSI_1 */ 0x12: key = '1'; break;
403 case /* kVK_ANSI_2 */ 0x13: key = '2'; break;
404 case /* kVK_ANSI_3 */ 0x14: key = '3'; break;
405 case /* kVK_ANSI_4 */ 0x15: key = '4'; break;
406 case /* kVK_ANSI_6 */ 0x16: key = '6'; break;
407 case /* kVK_ANSI_5 */ 0x17: key = '5'; break;
408 case /* kVK_ANSI_Equal */ 0x18: key = '='; break;
409 case /* kVK_ANSI_9 */ 0x19: key = '9'; break;
410 case /* kVK_ANSI_7 */ 0x1A: key = '7'; break;
411 case /* kVK_ANSI_Minus */ 0x1B: key = '-'; break;
412 case /* kVK_ANSI_8 */ 0x1C: key = '8'; break;
413 case /* kVK_ANSI_0 */ 0x1D: key = '0'; break;
414 default: ;
415 }
416 }
417#endif
418
419 if( key == WXK_ESCAPE ) // ESC is the special key for canceling tools
420 evt = TOOL_EVENT( TC_COMMAND, TA_CANCEL_TOOL, WXK_ESCAPE );
421 else
422 evt = TOOL_EVENT( TC_KEYBOARD, TA_KEY_PRESSED, key | mods );
423
424 return evt;
425}
426
427
428void TOOL_DISPATCHER::DispatchWxEvent( wxEvent& aEvent )
429{
430 bool motion = false;
431 bool buttonEvents = false;
432 VECTOR2D pos;
433 std::optional<TOOL_EVENT> evt;
434 bool keyIsEscape = false; // True if the keypress was the escape key
435 bool keyIsSpecial = false; // True if the key is a special key code
436 wxWindow* focus = wxWindow::FindFocus();
437
438 // Required in win32 to ensure wxTimer events get scheduled in between other events
439 // Or else we may stall them out entirely and never get them during actions like rapid
440 // mouse moves.
442
443 wxEventType type = aEvent.GetEventType();
444
445 // Sometimes there is no window that has the focus (it happens when another PCB_BASE_FRAME
446 // is opened and is iconized on Windows).
447 // In this case, give the focus to the parent frame (GAL canvas itself does not accept the
448 // focus when iconized for some obscure reason)
449 if( focus == nullptr )
450 {
451 wxWindow* holderWindow = dynamic_cast<wxWindow*>( m_toolMgr->GetToolHolder() );
452
453#if defined( _WIN32 ) || defined( __WXGTK__ )
454 // Mouse events may trigger regardless of window status (windows feature)
455 // However we need to avoid focus fighting (especially modals)
456 if( holderWindow && KIPLATFORM::UI::IsWindowActive( holderWindow ) )
457#else
458 if( holderWindow )
459#endif
460 {
461 holderWindow->SetFocus();
462 }
463 }
464
465 if( isMouseClick( type ) )
466 {
468 !m_toolMgr->GetToolHolder()->GetToolCanvas()->HasFocus() )
469 {
470 m_toolMgr->GetToolHolder()->GetToolCanvas()->SetFocus();
471 }
472 }
473
474 // Mouse handling
475 // Note: wxEVT_LEFT_DOWN event must always be skipped.
476 if( type == wxEVT_MOTION || type == wxEVT_MOUSEWHEEL ||
477 type == wxEVT_MAGNIFY ||
478 isMouseClick( type ) ||
479 // Event issued when mouse retains position in screen coordinates,
480 // but changes in world coordinates (e.g. autopanning)
482 {
483 wxMouseEvent* me = static_cast<wxMouseEvent*>( &aEvent );
484 int mods = decodeModifiers( me );
485
487 {
490
491 if( pos != m_lastMousePos )
492 {
493 motion = true;
494 m_lastMousePos = pos;
495 }
496 }
497
498 for( unsigned int i = 0; i < m_buttons.size(); i++ )
499 buttonEvents |= handleMouseButton( aEvent, i, motion );
500
502 {
503 if( !buttonEvents && motion )
504 {
505 evt = TOOL_EVENT( TC_MOUSE, TA_MOUSE_MOTION, mods );
506 evt->SetMousePosition( pos );
507 }
508 }
509
510 // We only handle wheel events that aren't for the view control.
511 // Events with zero or one modifier are reserved for view control.
512 // When using WX_VIEW_CONTROLS, these will already be handled, but
513 // we still shouldn't consume such events if we get them (e.g. for
514 // when WX_VIEW_CONTROLS is not in use, like in the 3D viewer)
515 if( !evt && me->GetWheelRotation() != 0 )
516 {
517 const unsigned modBits =
518 static_cast<unsigned>( mods ) & ( MD_CTRL | MD_ALT | MD_SHIFT );
519 const bool shouldHandle = std::popcount( modBits ) > 1;
520
521 if( shouldHandle )
522 {
523 evt = TOOL_EVENT( TC_MOUSE, TA_MOUSE_WHEEL, mods );
524 evt->SetParameter<int>( me->GetWheelRotation() );
525 }
526 }
527 }
528 else if( type == wxEVT_CHAR_HOOK || type == wxEVT_CHAR )
529 {
530 wxKeyEvent* ke = static_cast<wxKeyEvent*>( &aEvent );
531
532 wxLogTrace( kicadTraceKeyEvent, wxS( "TOOL_DISPATCHER::DispatchWxEvent %s" ), dump( *ke ) );
533
534 // Do not process wxEVT_CHAR_HOOK for a shift-modified key, as ACTION_MANAGER::RunHotKey
535 // will run the un-shifted key and that's not what we want. Wait to get the translated
536 // key from wxEVT_CHAR.
537 // See https://gitlab.com/kicad/code/kicad/-/issues/1809
538 if( type == wxEVT_CHAR_HOOK && ke->GetModifiers() == wxMOD_SHIFT )
539 {
540 aEvent.Skip();
541 return;
542 }
543
544 keyIsEscape = ( ke->GetKeyCode() == WXK_ESCAPE );
545
546 if( KIUI::IsInputControlFocused( focus ) )
547 {
548 bool enabled = KIUI::IsInputControlEditable( focus );
549
550 // Never process key events for tools when a text entry has focus
551 if( enabled )
552 {
553 aEvent.Skip();
554 return;
555 }
556 // Even if not enabled, allow a copy out
557 else if( ke->GetModifiers() == wxMOD_CONTROL && ke->GetKeyCode() == 'C' )
558 {
559 aEvent.Skip();
560 return;
561 }
562 }
563
564 evt = GetToolEvent( ke, &keyIsSpecial );
565 }
566 else if( type == wxEVT_MENU_OPEN || type == wxEVT_MENU_CLOSE || type == wxEVT_MENU_HIGHLIGHT )
567 {
568 wxMenuEvent* tmp = dynamic_cast<wxMenuEvent*>( &aEvent );
569
570 // Something is amiss if the event has these types and isn't a menu event, so bail out on
571 // its processing
572 if( !tmp )
573 {
574 aEvent.Skip();
575 return;
576 }
577
578 wxMenuEvent& menuEvent = *tmp;
579
580#if wxCHECK_VERSION( 3, 2, 0 )
581 // Forward the event to the menu for processing
582 if( ACTION_MENU* currentMenu = dynamic_cast<ACTION_MENU*>( menuEvent.GetMenu() ) )
583 currentMenu->OnMenuEvent( menuEvent );
584#else
585 //
586 // wxWidgets has several issues that we have to work around:
587 //
588 // 1) wxWidgets 3.0.x Windows has a bug where wxEVT_MENU_OPEN and wxEVT_MENU_HIGHLIGHT
589 // events are not captured by the ACTON_MENU menus. So we forward them here.
590 // (FWIW, this one is fixed in wxWidgets 3.1.x.)
591 //
592 // 2) wxWidgets doesn't pass the menu pointer for wxEVT_MENU_HIGHLIGHT events. So we
593 // store the menu pointer from the wxEVT_MENU_OPEN call.
594 //
595 // 3) wxWidgets has no way to tell whether a command is from a menu selection or a
596 // hotkey. So we keep track of menu highlighting so we can differentiate.
597 //
598
599 static ACTION_MENU* currentMenu;
600
601 if( type == wxEVT_MENU_OPEN )
602 {
603 currentMenu = dynamic_cast<ACTION_MENU*>( menuEvent.GetMenu() );
604
605 if( currentMenu )
606 currentMenu->OnMenuEvent( menuEvent );
607 }
608 else if( type == wxEVT_MENU_HIGHLIGHT )
609 {
610 if( currentMenu )
611 currentMenu->OnMenuEvent( menuEvent );
612 }
613 else if( type == wxEVT_MENU_CLOSE )
614 {
615 if( currentMenu )
616 currentMenu->OnMenuEvent( menuEvent );
617
618 currentMenu = nullptr;
619 }
620#endif
621
622 aEvent.Skip();
623 }
624
625 bool handled = false;
626
627 if( evt )
628 {
629 wxLogTrace( kicadTraceToolStack, wxS( "TOOL_DISPATCHER::DispatchWxEvent %s" ),
630 evt->Format() );
631
632 handled = m_toolMgr->ProcessEvent( *evt );
633
634 wxLogTrace( kicadTraceToolStack,
635 wxS( "TOOL_DISPATCHER::DispatchWxEvent - Handled: %s %s" ),
636 ( handled ? wxS( "true" ) : wxS( "false" ) ), evt->Format() );
637 }
638
639 // pass the event to the GUI, it might still be interested in it
640 // Note wxEVT_CHAR_HOOK event is already skipped for special keys not used by KiCad
641 // and wxEVT_LEFT_DOWN must be always Skipped.
642 //
643 // On OS X, key events are always meant to be caught. An uncaught key event is assumed
644 // to be a user input error by OS X (as they are pressing keys in a context where nothing
645 // is there to catch the event). This annoyingly makes OS X beep and/or flash the screen
646 // in Pcbnew and the footprint editor any time a hotkey is used. The correct procedure is
647 // to NOT pass wxEVT_CHAR events to the GUI under OS X.
648 //
649 // On Windows, avoid to call wxEvent::Skip for special keys because some keys
650 // (PAGE_UP, PAGE_DOWN) have predefined actions (like move thumbtrack cursor), and we do
651 // not want these actions executed (most are handled by KiCad)
652
653 if( !evt || type == wxEVT_LEFT_DOWN )
654 aEvent.Skip();
655
656 // Not handled wxEVT_CHAR must be Skipped (sent to GUI).
657 // Otherwise accelerators and shortcuts in main menu or toolbars are not seen.
658 // Escape key presses are never skipped by the handler since they correspond to tool cancel
659 // events, and if they aren't skipped then they are propagated to other frames (which we
660 // don't want).
661 if( ( type == wxEVT_CHAR || type == wxEVT_CHAR_HOOK )
662 && !keyIsSpecial
663 && !handled
664 && !keyIsEscape )
665 {
666 aEvent.Skip();
667 }
668
669 wxLogTrace( kicadTraceToolStack, "TOOL_DISPATCHER::DispatchWxEvent - Wx event skipped: %s",
670 ( aEvent.GetSkipped() ? "true" : "false" ) );
671}
672
673// LocalWords: EDA CERN CHANGELOG txt Tomasz Wlostowski wxEvent WXK
674// LocalWords: MERCHANTABILITY bool upEvent downEvent touchpad Ctrl
675// LocalWords: wxEVENT isKeySpecialCode thumbtrack DispatchWxEvent
676// LocalWords: NUMPAD PAGEUP PAGEDOWN wxEVT EVT OSX ctrl ctlr kVK
677// LocalWords: unicode ESC keypress wxTimer iconized autopanning WX
678// LocalWords: un Wx
Define 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:67
static const wxEventType EVT_REFRESH_MOUSE
Event that forces mouse move event in the dispatcher (eg.
virtual wxWindow * GetToolCanvas() const =0
Canvas access.
static const int DragDistanceThreshold
The distance threshold for mouse cursor that distinguishes between a single mouse click and a beginni...
static const int DragTimeThreshold
The time threshold for a mouse button press that distinguishes between a single mouse click and a beg...
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()
Returns the instance of VIEW, used by the application.
int m_sysDragMinX
Minimum 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)
Saves the state of key modifiers (Alt, Ctrl and so on).
TOOL_MANAGER * m_toolMgr
Instance of tool manager that cooperates with the dispatcher.
TOOL_DISPATCHER(TOOL_MANAGER *aToolMgr)
std::vector< BUTTON_STATE * > m_buttons
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:168
Master controller class:
Definition: tool_manager.h:62
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:402
KIGFX::VIEW_CONTROLS * GetViewControls() const
Definition: tool_manager.h:393
KIGFX::VIEW * GetView() const
Definition: tool_manager.h:391
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: unix/app.cpp:95
bool IsWindowActive(wxWindow *aWindow)
Check to see if the given window is the currently active window (e.g.
Definition: wxgtk/ui.cpp:130
KICOMMON_API bool IsInputControlFocused(wxWindow *aFocus=nullptr)
Check if a input control has focus.
Definition: ui_common.cpp:264
KICOMMON_API bool IsInputControlEditable(wxWindow *aControl)
Check if a input control has focus.
Definition: ui_common.cpp:301
bool contains(const _Container &__container, _Value __value)
Returns true if the container contains the given value.
Definition: kicad_algo.h:100
Store information about a mouse button state.
VECTOR2D dragOrigin
Point where dragging has started (in world coordinates).
wxEventType dblClickEvent
The type of wxEvent that determines mouse button double click.
wxEventType upEvent
The type of wxEvent that determines mouse button release.
VECTOR2D downPosition
Point where click event has occurred.
bool dragging
Flag indicating that dragging is active for the given button.
bool GetState() const
Checks the current state of the button.
bool pressed
Flag indicating that the given button is pressed.
BUTTON_STATE(TOOL_MOUSE_BUTTONS aButton, const wxEventType &aDownEvent, const wxEventType &aUpEvent, const wxEventType &aDblClickEvent)
wxLongLong downTimestamp
Time stamp for the last mouse button press event.
TOOL_MOUSE_BUTTONS button
Determines the mouse button for which information are stored.
void Reset()
Restores initial state.
wxEventType downEvent
The type of wxEvent that determines mouse button press.
VECTOR2D dragOriginScreen
Point where dragging has started (in screen coordinates).
static bool isMouseClick(wxEventType type)
bool isKeySpecialCode(int aKeyCode)
Helper to know if a special key ( see key list ) should be captured.
int translateSpecialCode(int aKeyCode)
Convert some special key codes to an equivalent.
static bool isKeyModifierOnly(int aKeyCode)
Helper to know if a key should be managed by DispatchWxEvent() or if the event can be ignored and ski...
@ TA_MOUSE_CLICK
Definition: tool_event.h:67
@ TA_MOUSE_MOTION
Definition: tool_event.h:72
@ TA_MOUSE_UP
Definition: tool_event.h:69
@ TA_MOUSE_DRAG
Definition: tool_event.h:71
@ TA_MOUSE_DOWN
Definition: tool_event.h:70
@ TA_KEY_PRESSED
Definition: tool_event.h:76
@ TA_MOUSE_DBLCLICK
Definition: tool_event.h:68
@ TA_MOUSE_WHEEL
Definition: tool_event.h:73
@ TA_CANCEL_TOOL
Tool cancel event.
Definition: tool_event.h:90
@ TC_COMMAND
Definition: tool_event.h:57
@ TC_MOUSE
Definition: tool_event.h:55
@ TC_KEYBOARD
Definition: tool_event.h:56
@ MD_ALT
Definition: tool_event.h:145
@ MD_CTRL
Definition: tool_event.h:144
@ MD_SHIFT
Definition: tool_event.h:143
TOOL_MOUSE_BUTTONS
Definition: tool_event.h:130
@ BUT_AUX1
Definition: tool_event.h:135
@ BUT_MIDDLE
Definition: tool_event.h:134
@ BUT_LEFT
Definition: tool_event.h:132
@ BUT_RIGHT
Definition: tool_event.h:133
@ BUT_AUX2
Definition: tool_event.h:136
wxString dump(const wxArrayString &aArray)
Debug helper for printing wxArrayString contents.
wxLogTrace helper definitions.
WX_VIEW_CONTROLS class definition.