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