KiCad PCB EDA Suite
tool_dispatcher.cpp
Go to the documentation of this file.
1 /*
2  * This program source code file is part of KiCad, a free EDA CAD application.
3  *
4  * Copyright (C) 2013 CERN
5  * Copyright (C) 2013-2021 KiCad Developers, see CHANGELOG.txt for contributors.
6  * @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
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 <macros.h>
27 #include <trace_helpers.h>
28 
29 #include <tool/tool_manager.h>
30 #include <tool/tools_holder.h>
31 #include <tool/tool_dispatcher.h>
32 #include <tool/actions.h>
33 #include <tool/action_manager.h>
34 #include <tool/action_menu.h>
35 #include <view/view.h>
36 #include <view/wx_view_controls.h>
37 
38 #include <class_draw_panel_gal.h>
39 #include <eda_draw_frame.h>
40 
41 #include <core/arraydim.h>
42 #include <core/optional.h>
43 #include <wx/log.h>
44 #include <wx/stc/stc.h>
45 #include <kiplatform/app.h>
46 #include <kiplatform/ui.h>
47 
50 {
51  BUTTON_STATE( TOOL_MOUSE_BUTTONS aButton, const wxEventType& aDownEvent,
52  const wxEventType& aUpEvent, const wxEventType& aDblClickEvent ) :
53  dragging( false ),
54  pressed( false ),
55  dragMaxDelta( 0.0f ),
56  button( aButton ),
57  downEvent( aDownEvent ),
58  upEvent( aUpEvent ),
59  dblClickEvent( aDblClickEvent )
60  {};
61 
63  bool dragging;
64 
66  bool pressed;
67 
70 
73 
76  double dragMaxDelta;
77 
80 
82  wxEventType downEvent;
83 
85  wxEventType upEvent;
86 
88  wxEventType dblClickEvent;
89 
91  wxLongLong downTimestamp;
92 
94  void Reset()
95  {
96  dragging = false;
97  pressed = false;
98  }
99 
101  bool GetState() const
102  {
103  wxMouseState mouseState = wxGetMouseState();
104 
105  switch( button )
106  {
107  case BUT_LEFT:
108  return mouseState.LeftIsDown();
109 
110  case BUT_MIDDLE:
111  return mouseState.MiddleIsDown();
112 
113  case BUT_RIGHT:
114  return mouseState.RightIsDown();
115 
116  default:
117  assert( false );
118  break;
119  }
120 
121  return false;
122  }
123 };
124 
125 
127  m_toolMgr( aToolMgr )
128 {
129  m_buttons.push_back( new BUTTON_STATE( BUT_LEFT, wxEVT_LEFT_DOWN,
130  wxEVT_LEFT_UP, wxEVT_LEFT_DCLICK ) );
131  m_buttons.push_back( new BUTTON_STATE( BUT_RIGHT, wxEVT_RIGHT_DOWN,
132  wxEVT_RIGHT_UP, wxEVT_RIGHT_DCLICK ) );
133  m_buttons.push_back( new BUTTON_STATE( BUT_MIDDLE, wxEVT_MIDDLE_DOWN,
134  wxEVT_MIDDLE_UP, wxEVT_MIDDLE_DCLICK ) );
135 
136  ResetState();
137 }
138 
139 
141 {
142  for( BUTTON_STATE* st : m_buttons )
143  delete st;
144 }
145 
146 
148 {
149  for( BUTTON_STATE* st : m_buttons )
150  st->Reset();
151 }
152 
153 
155 {
156  return m_toolMgr->GetView();
157 }
158 
159 
160 bool TOOL_DISPATCHER::handleMouseButton( wxEvent& aEvent, int aIndex, bool aMotion )
161 {
162  BUTTON_STATE* st = m_buttons[aIndex];
163  wxEventType type = aEvent.GetEventType();
164  OPT<TOOL_EVENT> evt;
165  bool isClick = false;
166 
167 // bool up = type == st->upEvent;
168 // bool down = type == st->downEvent;
169  bool up = false, down = false;
170  bool dblClick = type == st->dblClickEvent;
171  bool state = st->GetState();
172 
173  if( !dblClick )
174  {
175  // Sometimes the dispatcher does not receive mouse button up event, so it stays
176  // in the dragging mode even if the mouse button is not held anymore
177  if( st->pressed && !state )
178  up = true;
179  // Don't apply same logic to down events as it kills touchpad tapping
180  else if( !st->pressed && type == st->downEvent )
181  down = true;
182  }
183 
184  int mods = decodeModifiers( static_cast<wxMouseEvent*>( &aEvent ) );
185  int args = st->button | mods;
186 
187  if( down ) // Handle mouse button press
188  {
189  st->downTimestamp = wxGetLocalTimeMillis();
190 
191  if( !st->pressed ) // save the drag origin on the first click only
193 
195  st->dragMaxDelta = 0;
196  st->pressed = true;
197  evt = TOOL_EVENT( TC_MOUSE, TA_MOUSE_DOWN, args );
198  }
199  else if( up ) // Handle mouse button release
200  {
201  st->pressed = false;
202 
203  if( st->dragging )
204  {
205  wxLongLong t = wxGetLocalTimeMillis();
206 
207  // Determine if it was just a single click or beginning of dragging
208  if( t - st->downTimestamp < DragTimeThreshold &&
210  isClick = true;
211  else
212  evt = TOOL_EVENT( TC_MOUSE, TA_MOUSE_UP, args );
213  }
214  else
215  isClick = true;
216 
217  if( isClick )
218  evt = TOOL_EVENT( TC_MOUSE, TA_MOUSE_CLICK, args );
219 
220  st->dragging = false;
221  }
222  else if( dblClick )
223  {
224  evt = TOOL_EVENT( TC_MOUSE, TA_MOUSE_DBLCLICK, args );
225  }
226 
227  if( st->pressed && aMotion )
228  {
229  st->dragging = true;
230  double dragPixelDistance =
232  st->dragMaxDelta = std::max( st->dragMaxDelta, dragPixelDistance );
233 
234  wxLongLong t = wxGetLocalTimeMillis();
235 
237  {
238  evt = TOOL_EVENT( TC_MOUSE, TA_MOUSE_DRAG, args );
239  evt->setMouseDragOrigin( st->dragOrigin );
240  evt->setMouseDelta( m_lastMousePos - st->dragOrigin );
241  }
242  }
243 
244  if( evt )
245  {
246  evt->SetMousePosition( isClick ? st->downPosition : m_lastMousePos );
247  m_toolMgr->ProcessEvent( *evt );
248 
249  return true;
250  }
251 
252  return false;
253 }
254 
255 
256 // Helper function to know if a special key ( see key list ) should be captured
257 // or if the event can be skipped
258 // on Linux, the event must be passed to the GUI if they are not used by KiCad,
259 // especially the wxEVENT_CHAR_HOOK, if it is not handled
260 // Some keys have a predefined action in wxWidgets so, even if not used,
261 // the even will be not skipped
262 // the unused keys listed in isKeySpecialCode() will be not skipped
263 bool isKeySpecialCode( int aKeyCode )
264 {
265  // These keys have predefined actions (like move thumbtrack cursor),
266  // and we do not want these actions executed
267  const enum wxKeyCode special_keys[] =
268  {
269  WXK_PAGEUP, WXK_PAGEDOWN,
270  WXK_NUMPAD_PAGEUP, WXK_NUMPAD_PAGEDOWN
271  };
272 
273  bool isInList = false;
274 
275  for( unsigned ii = 0; ii < arrayDim( special_keys ) && !isInList; ii++ )
276  {
277  if( special_keys[ii] == aKeyCode )
278  isInList = true;
279  }
280 
281  return isInList;
282 }
283 
284 
285 // Helper function to know if a key should be managed by DispatchWxEvent()
286 // or if the event can be ignored and skipped because the key is only a modifier
287 // that is not used alone in kicad
288 static bool isKeyModifierOnly( int aKeyCode )
289 {
290  const enum wxKeyCode special_keys[] =
291  {
292  WXK_CONTROL, WXK_RAW_CONTROL, WXK_SHIFT,WXK_ALT
293  };
294 
295  bool isInList = false;
296 
297  for( unsigned ii = 0; ii < arrayDim( special_keys ) && !isInList; ii++ )
298  {
299  if( special_keys[ii] == aKeyCode )
300  isInList = true;
301  }
302 
303  return isInList;
304 }
305 
306 
307 static bool isMouseClick( wxEventType type )
308 {
309  return type == wxEVT_LEFT_DOWN || type == wxEVT_LEFT_UP || type == wxEVT_MIDDLE_DOWN
310  || type == wxEVT_MIDDLE_UP || type == wxEVT_RIGHT_DOWN || type == wxEVT_RIGHT_UP
311  || type == wxEVT_LEFT_DCLICK || type == wxEVT_MIDDLE_DCLICK
312  || type == wxEVT_RIGHT_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  */
328 int 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 
345 OPT<TOOL_EVENT> TOOL_DISPATCHER::GetToolEvent( wxKeyEvent* aKeyEvent, bool* keyIsSpecial )
346 {
347  OPT<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, "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  (void) unicode_key; //not used: avoid compil warning
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
418  else
419  evt = TOOL_EVENT( TC_KEYBOARD, TA_KEY_PRESSED, key | mods );
420 
421  return evt;
422 }
423 
424 
425 void TOOL_DISPATCHER::DispatchWxEvent( wxEvent& aEvent )
426 {
427  bool motion = false;
428  bool buttonEvents = false;
429  VECTOR2D pos;
430  OPT<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 )
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()->SetFocus();
466  }
467 
468  // Mouse handling
469  // Note: wxEVT_LEFT_DOWN event must always be skipped.
470  if( type == wxEVT_MOTION || type == wxEVT_MOUSEWHEEL ||
471 #if wxCHECK_VERSION( 3, 1, 0 ) || defined( USE_OSX_MAGNIFY_EVENT )
472  type == wxEVT_MAGNIFY ||
473 #endif
474  isMouseClick( type ) ||
475  // Event issued when mouse retains position in screen coordinates,
476  // but changes in world coordinates (e.g. autopanning)
478  {
479  wxMouseEvent* me = static_cast<wxMouseEvent*>( &aEvent );
480  int mods = decodeModifiers( me );
481 
482  if( m_toolMgr->GetViewControls() )
483  {
485 
486  if( pos != m_lastMousePos )
487  {
488  motion = true;
489  m_lastMousePos = pos;
490  }
491  }
492 
493  for( unsigned int i = 0; i < m_buttons.size(); i++ )
494  buttonEvents |= handleMouseButton( aEvent, i, motion );
495 
496  if( m_toolMgr->GetViewControls() )
497  {
498  if( !buttonEvents && motion )
499  {
500  evt = TOOL_EVENT( TC_MOUSE, TA_MOUSE_MOTION, mods );
501  evt->SetMousePosition( pos );
502  }
503  }
504  }
505  else if( type == wxEVT_CHAR_HOOK || type == wxEVT_CHAR )
506  {
507  wxKeyEvent* ke = static_cast<wxKeyEvent*>( &aEvent );
508 
509  wxLogTrace( kicadTraceKeyEvent, "TOOL_DISPATCHER::DispatchWxEvent %s", dump( *ke ) );
510 
511  // Do not process wxEVT_CHAR_HOOK for a shift-modified key, as ACTION_MANAGER::RunHotKey
512  // will run the un-shifted key and that's not what we want. Wait to get the translated
513  // key from wxEVT_CHAR.
514  // See https://gitlab.com/kicad/code/kicad/-/issues/1809
515  if( type == wxEVT_CHAR_HOOK && ke->GetModifiers() == wxMOD_SHIFT )
516  {
517  aEvent.Skip();
518  return;
519  }
520 
521  keyIsEscape = ( ke->GetKeyCode() == WXK_ESCAPE );
522 
523  if( KIUI::IsInputControlFocused( focus ) )
524  {
525  bool enabled = KIUI::IsInputControlEditable( focus );
526 
527  // Never process key events for tools when a text entry has focus
528  if( enabled )
529  {
530  aEvent.Skip();
531  return;
532  }
533  // Even if not enabled, allow a copy out
534  else if( ke->GetModifiers() == wxMOD_CONTROL && ke->GetKeyCode() == 'C' )
535  {
536  aEvent.Skip();
537  return;
538  }
539  }
540 
541  evt = GetToolEvent( ke, &keyIsSpecial );
542  }
543  else if( type == wxEVT_MENU_OPEN || type == wxEVT_MENU_CLOSE || type == wxEVT_MENU_HIGHLIGHT )
544  {
545  //
546  // wxWidgets has several issues that we have to work around:
547  //
548  // 1) wxWidgets 3.0.x Windows has a bug where wxEVT_MENU_OPEN and wxEVT_MENU_HIGHLIGHT
549  // events are not captured by the ACTON_MENU menus. So we forward them here.
550  // (FWIW, this one is fixed in wxWidgets 3.1.x.)
551  //
552  // 2) wxWidgets doesn't pass the menu pointer for wxEVT_MENU_HIGHLIGHT events. So we
553  // store the menu pointer from the wxEVT_MENU_OPEN call.
554  //
555  // 3) wxWidgets has no way to tell whether a command is from a menu selection or a
556  // hotkey. So we keep track of menu highlighting so we can differentiate.
557  //
558 
559  static ACTION_MENU* currentMenu;
560 
561  wxMenuEvent& menuEvent = *dynamic_cast<wxMenuEvent*>( &aEvent );
562 
563  if( type == wxEVT_MENU_OPEN )
564  {
565  currentMenu = dynamic_cast<ACTION_MENU*>( menuEvent.GetMenu() );
566 
567  if( currentMenu )
568  currentMenu->OnMenuEvent( menuEvent );
569  }
570  else if( type == wxEVT_MENU_HIGHLIGHT )
571  {
572  if( currentMenu )
573  currentMenu->OnMenuEvent( menuEvent );
574  }
575  else if( type == wxEVT_MENU_CLOSE )
576  {
577  if( currentMenu )
578  currentMenu->OnMenuEvent( menuEvent );
579 
580  currentMenu = nullptr;
581  }
582 
583  aEvent.Skip();
584  }
585 
586  bool handled = false;
587 
588  if( evt )
589  {
590  wxLogTrace( kicadTraceToolStack, "TOOL_DISPATCHER::DispatchWxEvent %s", evt->Format() );
591 
592  handled = m_toolMgr->ProcessEvent( *evt );
593 
594  wxLogTrace( kicadTraceToolStack, "TOOL_DISPATCHER::DispatchWxEvent - Handled: %s %s",
595  ( handled ? "true" : "false" ), evt->Format() );
596  }
597 
598  // pass the event to the GUI, it might still be interested in it
599  // Note wxEVT_CHAR_HOOK event is already skipped for special keys not used by KiCad
600  // and wxEVT_LEFT_DOWN must be always Skipped.
601  //
602  // On OS X, key events are always meant to be caught. An uncaught key event is assumed
603  // to be a user input error by OS X (as they are pressing keys in a context where nothing
604  // is there to catch the event). This annoyingly makes OS X beep and/or flash the screen
605  // in Pcbnew and the footprint editor any time a hotkey is used. The correct procedure is
606  // to NOT pass wxEVT_CHAR events to the GUI under OS X.
607  //
608  // On Windows, avoid to call wxEvent::Skip for special keys because some keys
609  // (PAGE_UP, PAGE_DOWN) have predefined actions (like move thumbtrack cursor), and we do
610  // not want these actions executed (most are handled by KiCad)
611 
612  if( !evt || type == wxEVT_LEFT_DOWN )
613  aEvent.Skip();
614 
615  // Not handled wxEVT_CHAR must be Skipped (sent to GUI).
616  // Otherwise accelerators and shortcuts in main menu or toolbars are not seen.
617  // Escape key presses are never skipped by the handler since they correspond to tool cancel
618  // events, and if they aren't skipped then they are propagated to other frames (which we
619  // don't want).
620  if( (type == wxEVT_CHAR || type == wxEVT_CHAR_HOOK)
621  && !keyIsSpecial
622  && !handled
623  && !keyIsEscape )
624  aEvent.Skip();
625 
626  wxLogTrace( kicadTraceToolStack, "TOOL_DISPATCHER::DispatchWxEvent - Wx event skipped: %s",
627  ( aEvent.GetSkipped() ? "true" : "false" ) );
628 }
VECTOR2D downPosition
Difference between drag origin point and current mouse position (expressed as distance in pixels).
KIGFX::VIEW * GetView() const
Definition: tool_manager.h:283
static int decodeModifiers(const wxKeyboardState *aState)
Stores all the information regarding a mouse button state.
double dragMaxDelta
Determines the mouse button for which information are stored.
BUTTON_STATE(TOOL_MOUSE_BUTTONS aButton, const wxEventType &aDownEvent, const wxEventType &aUpEvent, const wxEventType &aDblClickEvent)
virtual VECTOR2D GetMousePosition(bool aWorldCoordinates=true) const =0
Return the current mouse pointer position.
bool IsInputControlEditable(wxWindow *aControl)
Check if a input control has focus.
Definition: ui_common.cpp:250
static const wxEventType EVT_REFRESH_MOUSE
Defines the structure of a menu based on ACTIONs.
Definition: action_menu.h:48
int translateSpecialCode(int aKeyCode)
static bool isKeyModifierOnly(int aKeyCode)
static const int DragDistanceThreshold
Handles mouse related events (click, motion, dragging).
virtual ~TOOL_DISPATCHER()
virtual void ResetState()
Bring the dispatcher to its initial state.
bool dragging
Flag indicating that dragging is active for the given button.
VECTOR2D dragOrigin
Point where click event has occurred.
WX_VIEW_CONTROLS class definition.
void Reset()
Checks the current state of the button.
This file contains miscellaneous commonly used macros and functions.
Master controller class:
Definition: tool_manager.h:54
bool IsInputControlFocused(wxWindow *aFocus=nullptr)
Check if a input control has focus.
Definition: ui_common.cpp:217
< Stores information about a mouse button state
bool IsWindowActive(wxWindow *aWindow)
Check to see if the given window is the currently active window (e.g.
Definition: gtk/ui.cpp:50
wxString dump(const wxArrayString &aArray)
Debug helper for printing wxArrayString contents.
virtual wxWindow * GetToolCanvas() const =0
Canvas access.
wxEventType dblClickEvent
Time stamp for the last mouse button press event.
wxEventType downEvent
The type of wxEvent that determines mouse button release.
bool ProcessEvent(const TOOL_EVENT &aEvent)
Propagate an event to tools that requested events of matching type(s).
void ForceTimerMessagesToBeCreatedIfNecessary()
Forces wxTimers to fire more promptly on Win32.
Definition: gtk/app.cpp:88
virtual void DispatchWxEvent(wxEvent &aEvent)
Process wxEvents (mostly UI events), translate them to TOOL_EVENTs, and make tools handle those.
bool isKeySpecialCode(int aKeyCode)
Generic, UI-independent tool event.
Definition: tool_event.h:152
constexpr std::size_t arrayDim(T const (&)[N]) noexcept
Returns # of elements in an array.
Definition: arraydim.h:31
wxLogTrace helper definitions.
VECTOR2D m_lastMousePos
The last mouse cursor position (in world coordinates).
VECTOR2D ToScreen(const VECTOR2D &aCoord, bool aAbsolute=true) const
Convert a world space point/vector to a point/vector in screen space coordinates.
Definition: view.cpp:471
std::vector< BUTTON_STATE * > m_buttons
Returns the instance of VIEW, used by the application.
void OnMenuEvent(wxMenuEvent &aEvent)
TOOL_MOUSE_BUTTONS
Definition: tool_event.h:123
TOOLS_HOLDER * GetToolHolder() const
Definition: tool_manager.h:294
KIGFX::VIEW_CONTROLS * GetViewControls() const
Definition: tool_manager.h:285
OPT< TOOL_EVENT > GetToolEvent(wxKeyEvent *aKeyEvent, bool *aSpecialKeyFlag)
Map a wxWidgets key event to a TOOL_EVENT.
TOOL_DISPATCHER(TOOL_MANAGER *aToolMgr)
static bool isMouseClick(wxEventType type)
bool pressed
Point where dragging has started (in world coordinates).
const wxChar *const kicadTraceKeyEvent
Flag to enable wxKeyEvent debug tracing.
const wxChar *const kicadTraceToolStack
Flag to enable tracing of the tool handling stack.
boost::optional< T > OPT
Definition: optional.h:7
wxEventType upEvent
The type of wxEvent that determines mouse button double click.
T EuclideanNorm() const
Compute the Euclidean norm of the vector, which is defined as sqrt(x ** 2 + y ** 2).
Definition: vector2d.h:293
wxLongLong downTimestamp
Restores initial state.
static const int DragTimeThreshold
The distance threshold for mouse cursor that distinguishes between a single mouse click and a beginni...
Hold a (potentially large) number of VIEW_ITEMs and renders them on a graphics device provided by the...
Definition: view.h:68
TOOL_MOUSE_BUTTONS button
The type of wxEvent that determines mouse button press.
bool handleMouseButton(wxEvent &aEvent, int aIndex, bool aMotion)
Saves the state of key modifiers (Alt, Ctrl and so on).
KIGFX::VIEW * getView()
Instance of tool manager that cooperates with the dispatcher.
TOOL_MANAGER * m_toolMgr