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