kicad-developers team mailing list archive
-
kicad-developers team
-
Mailing list archive
-
Message #22836
Re: [PATCH] Fix (Ctrl)+(ASCII control key) hotkey handling
Updated patch - quite a few changes. First I noticed I was inadvertently
trapping some keys I shouldn't (try using Ctrl+S with the original
patch...), and then I decided to tackle the old "bug" that certain key
combinations, like Shift+Tab, cannot be used.
To make sure hotkeys are recognized equally everywhere, I took the code
I originally wrote for the hotkey editor widget to handle wxEVT_CHAR and
wxEVT_CHAR_HOOK keypress events "intelligently" and factored it out into
a separate class to be used in other places. I then pulled it into
EDA_DRAW_PANEL and EDA_DRAW_PANEL_GAL to replace the existing keycode
rewriting code (which originally was just "if hotkey is in WXK_CONTROL_A
through WXK_CONTROL_Z, remap to Ctrl + A..Z").
With this patch, all 'standard' combinations of keys on a US keyboard
should be usable, support for international keys is the same as before.
Let me know if you find any combinations that don't work.
Please test! This is platform-dependent stuff - it's the same
platform-dependent stuff as before, but I need to make sure I haven't
added regressions. I've tested on Linux and Win10; more thorough testing
even on those same platforms is welcome.
On Wed, Jan 20, 2016 at 10:44:36PM -0500, Chris Pavlina wrote:
> There is an old bug that people turned up while testing my new hotkey
> editor, attached is a patch that fixes it. This patch pokes into the
> main hotkey handling code, so I really want as many people to test it as
> possible - it's a relatively minor bug, I don't want to go introducing
> twelve regressions to fix one small bug. Here's what I want to keep an
> eye out for:
>
> - Hotkeys (Ctrl+Tab), (Tab), and (Ctrl+I) are all independent and
> distinguished from each other, both in the hotkey editor and in actual
> use. Make sure all of them work, and make sure none of them answers
> for the others.
>
> - Hotkeys that are *not* handled by the main hotkey code (for example,
> menu keys like Alt+F to call up the File menu) are not affected.
>
> - Behavior on OSX, with its weird Ctrl mapping, is not broken (or, at
> least, is no more broken than usual ;)
>
> I have tested on Linux and Windows 10, though more thorough testing on
> those platforms is welcome.
>
> Patch/bug summary:
>
> [PATCH] Fix (Ctrl)+(ASCII control key) hotkey handling
>
> wxWidgets has quirks with how it handles these keys. For example, in
> wxEVT_CHAR, Ctrl+Tab and Ctrl+I are indistinguishable.
>
> - Modify the special wxEVT_CHAR_HOOK handler from WIDGET_HOTKEY_LIST to
> handle this case as well as the other funny cases it already handles.
>
> - Factor this handler out into a function in hotkeys_basic.h for use
> elsewhere.
>
> - Add this handler to the central hotkey handler, remove existing
> (buggy) ASCII control key handling.
>
> Thanks for testing.
>
> -- Chris
diff --git a/common/draw_panel.cpp b/common/draw_panel.cpp
index 063c5db..5418f4c 100644
--- a/common/draw_panel.cpp
+++ b/common/draw_panel.cpp
@@ -3,7 +3,7 @@
*
* Copyright (C) 2009 Jean-Pierre Charras, jean-pierre.charras@xxxxxxxxxxxxxxxxx
* Copyright (C) 2007-2011 Wayne Stambaugh <stambaughw@xxxxxxxxxxx>
- * Copyright (C) 1992-2015 KiCad Developers, see AUTHORS.txt for contributors.
+ * Copyright (C) 1992-2016 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -77,7 +77,7 @@ BEGIN_EVENT_TABLE( EDA_DRAW_PANEL, wxScrolledWindow )
#endif
EVT_MOUSE_EVENTS( EDA_DRAW_PANEL::OnMouseEvent )
EVT_CHAR( EDA_DRAW_PANEL::OnKeyEvent )
- EVT_CHAR_HOOK( EDA_DRAW_PANEL::OnCharHook )
+ EVT_CHAR_HOOK( EDA_DRAW_PANEL::OnKeyEvent )
EVT_PAINT( EDA_DRAW_PANEL::OnPaint )
EVT_ERASE_BACKGROUND( EDA_DRAW_PANEL::OnEraseBackground )
EVT_SCROLLWIN( EDA_DRAW_PANEL::OnScroll )
@@ -1381,59 +1381,27 @@ void EDA_DRAW_PANEL::OnMouseEvent( wxMouseEvent& event )
}
-
-void EDA_DRAW_PANEL::OnCharHook( wxKeyEvent& event )
-{
- event.Skip();
-}
-
void EDA_DRAW_PANEL::OnKeyEvent( wxKeyEvent& event )
{
- int localkey;
- wxPoint pos;
+ if( !m_hkfilter.should_process( event ) )
+ {
+ return;
+ }
- localkey = event.GetKeyCode();
+ wxPoint pos;
+ EDA_KEY key = MapKeypressToKeycode( event );
- switch( localkey )
+ if( key == GR_KEY_NONE )
{
- default:
- break;
-
- case WXK_ESCAPE:
+ // escape key
m_abortRequest = true;
if( IsMouseCaptured() )
EndMouseCapture();
else
EndMouseCapture( ID_NO_TOOL_SELECTED, m_defaultCursor, wxEmptyString );
- break;
}
- /* Normalize keys code to easily handle keys from Ctrl+A to Ctrl+Z
- * They have an ascii code from 1 to 27 remapped
- * to GR_KB_CTRL + 'A' to GR_KB_CTRL + 'Z'
- */
- if( event.ControlDown() && localkey >= WXK_CONTROL_A && localkey <= WXK_CONTROL_Z )
- localkey += 'A' - 1;
-
- /* Disallow shift for keys that have two keycodes on them (e.g. number and
- * punctuation keys) leaving only the "letter keys" of A-Z.
- * Then, you can have, e.g. Ctrl-5 and Ctrl-% (GB layout)
- * and Ctrl-( and Ctrl-5 (FR layout).
- * Otherwise, you'd have to have to say Ctrl-Shift-5 on a FR layout
- */
- bool keyIsLetter = ( localkey >= 'A' && localkey <= 'Z' ) ||
- ( localkey >= 'a' && localkey <= 'z' );
-
- if( event.ShiftDown() && ( keyIsLetter || localkey > 256 ) )
- localkey |= GR_KB_SHIFT;
-
- if( event.ControlDown() )
- localkey |= GR_KB_CTRL;
-
- if( event.AltDown() )
- localkey |= GR_KB_ALT;
-
INSTALL_UNBUFFERED_DC( DC, this );
// Some key commands use the current mouse position: refresh it.
@@ -1444,8 +1412,10 @@ void EDA_DRAW_PANEL::OnKeyEvent( wxKeyEvent& event )
GetParent()->SetMousePosition( pos );
- if( !GetParent()->GeneralControl( &DC, pos, localkey ) )
- event.Skip();
+ if( !GetParent()->GeneralControl( &DC, pos, key ) )
+ {
+ m_hkfilter.skip( event );
+ }
}
diff --git a/common/draw_panel_gal.cpp b/common/draw_panel_gal.cpp
index c060ab5..50bd478 100644
--- a/common/draw_panel_gal.cpp
+++ b/common/draw_panel_gal.cpp
@@ -82,7 +82,7 @@ EDA_DRAW_PANEL_GAL::EDA_DRAW_PANEL_GAL( wxWindow* aParentWindow, wxWindowID aWin
wxEVT_LEFT_UP, wxEVT_LEFT_DOWN, wxEVT_LEFT_DCLICK,
wxEVT_RIGHT_UP, wxEVT_RIGHT_DOWN, wxEVT_RIGHT_DCLICK,
wxEVT_MIDDLE_UP, wxEVT_MIDDLE_DOWN, wxEVT_MIDDLE_DCLICK,
- wxEVT_MOTION, wxEVT_MOUSEWHEEL, wxEVT_CHAR,
+ wxEVT_MOTION, wxEVT_MOUSEWHEEL, wxEVT_CHAR, wxEVT_CHAR_HOOK,
#ifdef USE_OSX_MAGNIFY_EVENT
wxEVT_MAGNIFY,
#endif
diff --git a/common/hotkeys_basic.cpp b/common/hotkeys_basic.cpp
index 04dfd7f..171933c 100644
--- a/common/hotkeys_basic.cpp
+++ b/common/hotkeys_basic.cpp
@@ -509,7 +509,7 @@ void DisplayHotkeyList( EDA_BASE_FRAME* aFrame, struct EDA_HOTKEY_CONFIG* aDescL
* @param aList = pointer to a EDA_HOTKEY list of commands
* @return the corresponding EDA_HOTKEY pointer from the EDA_HOTKEY List
*/
-EDA_HOTKEY* GetDescriptorFromHotkey( int aKey, EDA_HOTKEY** aList )
+EDA_HOTKEY* GetDescriptorFromHotkey( EDA_KEY aKey, EDA_HOTKEY** aList )
{
for( ; *aList != NULL; aList++ )
{
@@ -844,3 +844,142 @@ void AddHotkeyConfigMenu( wxMenu* aMenu )
_( "Hotkeys configuration and preferences" ),
KiBitmap( hotkeys_xpm ) );
}
+
+
+EDA_HOTKEY_HOOK_FILTER::EDA_HOTKEY_HOOK_FILTER()
+{
+ m_skip_evtchar = false;
+}
+
+
+bool EDA_HOTKEY_HOOK_FILTER::should_process_in_hook( wxKeyEvent& aEvent )
+{
+ // On certain platforms, EVT_CHAR_HOOK is the only handler that receives
+ // certain "special" keys. However, it doesn't always receive "normal"
+ // keys correctly. For example, with a US keyboard, it sees ? as shift+/.
+ //
+ // Untangling these incorrect keys would be too much trouble, so we bind
+ // both events, and simply skip the EVT_CHAR_HOOK if it receives a
+ // "normal" key.
+
+ const enum wxKeyCode skipped_keys[] =
+ {
+ WXK_NONE, WXK_SHIFT, WXK_ALT, WXK_CONTROL, WXK_CAPITAL,
+ WXK_NUMLOCK, WXK_SCROLL, WXK_RAW_CONTROL
+ };
+
+ int key = aEvent.GetKeyCode();
+
+ for( size_t i = 0; i < DIM( skipped_keys ); ++i )
+ {
+ if( key == skipped_keys[i] )
+ return false;
+ }
+
+ // Some control keys map to Ctrl+letter (e.g. Tab is Ctrl+I) in OnChar,
+ // but not OnCharHook. This leads to incorrect recognition of
+ // Ctrl+controlkey (e.g. Ctrl+Tab is seen as just Ctrl+I). Detect
+ // this and handle here instead.
+
+ bool ctrl_alphakey = ( ( key >= 'A' && key <= 'Z' ) || ( key >= 'a' && key <= 'z' ) )
+ && aEvent.ControlDown();
+
+ bool ctrl_ctrlkey = ( key >= WXK_CONTROL_A && key <= WXK_CONTROL_Z )
+ && aEvent.ControlDown();
+
+ return !( key <= 255 && isprint( key ) && !isspace( key ) && !ctrl_ctrlkey && !ctrl_alphakey );
+}
+
+
+void EDA_HOTKEY_HOOK_FILTER::allow_char_hook_propagation( wxKeyEvent& aEvent )
+{
+ // Let EVT_CHAR handle this one
+ aEvent.DoAllowNextEvent();
+
+ skip( aEvent );
+}
+
+
+bool EDA_HOTKEY_HOOK_FILTER::should_process( wxKeyEvent& aEvent )
+{
+ if( aEvent.GetEventType() == wxEVT_CHAR_HOOK )
+ {
+ m_skip_evtchar = should_process_in_hook( aEvent );
+
+ // Windows quirk: do NOT let the \t wxEVT_CHAR_HOOK produce
+ // wxEVT_CHAR. In some dialogs (particularly empty ones, see
+ // the dialog used for hotkey detection in WIDGET_HOTKEY_LIST),
+ // this will cause the application to freeze.
+ if( aEvent.GetKeyCode() != '\t' )
+ allow_char_hook_propagation( aEvent );
+ return m_skip_evtchar;
+ }
+ else
+ {
+ wxASSERT( aEvent.GetEventType() == wxEVT_CHAR );
+ if( !m_skip_evtchar )
+ {
+ return true;
+ }
+ else
+ {
+ aEvent.Skip();
+ return false;
+ }
+ }
+}
+
+
+void EDA_HOTKEY_HOOK_FILTER::skip( wxKeyEvent& aEvent )
+{
+ if( aEvent.GetEventType() == wxEVT_CHAR_HOOK )
+ {
+ // On Windows, wxEvent::Skip must NOT be called.
+ // On Linux and OSX, wxEvent::Skip MUST be called.
+ // No, I don't know why.
+#ifndef __WXMSW__
+ aEvent.Skip();
+#endif
+ }
+ else
+ {
+ aEvent.Skip();
+ }
+
+}
+
+
+EDA_KEY MapKeypressToKeycode( const wxKeyEvent& aEvent )
+{
+ EDA_KEY key = ( EDA_KEY ) aEvent.GetKeyCode();
+
+ if( key == WXK_ESCAPE )
+ {
+ return GR_KEY_NONE;
+ }
+ else
+ {
+ if( key >= 'a' && key <= 'z' ) // convert to uppercase
+ key = key + ('A' - 'a');
+
+ /* Disallow shift for keys that have two keycodes on them (e.g. number and
+ * punctuation keys) leaving only the "letter keys" of A-Z.
+ * Then, you can have, e.g. Ctrl-5 and Ctrl-% (GB layout)
+ * and Ctrl-( and Ctrl-5 (FR layout).
+ * Otherwise, you'd have to have to say Ctrl-Shift-5 on a FR layout
+ */
+ bool keyIsLetter = key >= 'A' && key <= 'Z';
+ bool keyIsControl = key >= WXK_CONTROL_A && key <= WXK_CONTROL_Z;
+
+ if( aEvent.ShiftDown() && ( keyIsLetter || keyIsControl || key > 256 ) )
+ key |= GR_KB_SHIFT;
+
+ if( aEvent.ControlDown() )
+ key |= GR_KB_CTRL;
+
+ if( aEvent.AltDown() )
+ key |= GR_KB_ALT;
+
+ return key;
+ }
+}
diff --git a/common/tool/tool_dispatcher.cpp b/common/tool/tool_dispatcher.cpp
index 97127ce..99c6a28 100644
--- a/common/tool/tool_dispatcher.cpp
+++ b/common/tool/tool_dispatcher.cpp
@@ -2,6 +2,7 @@
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2013 CERN
+ * Copyright (C) 2016 KiCad Developers, see CHANGELOG.TXT for contributors.
* @author Tomasz Wlostowski <tomasz.wlostowski@xxxxxxx>
*
* This program is free software; you can redistribute it and/or
@@ -291,32 +292,20 @@ void TOOL_DISPATCHER::DispatchWxEvent( wxEvent& aEvent )
}
// Keyboard handling
- else if( type == wxEVT_CHAR )
+ else if( type == wxEVT_CHAR || type == wxEVT_CHAR_HOOK )
{
wxKeyEvent* ke = static_cast<wxKeyEvent*>( &aEvent );
- int key = ke->GetKeyCode();
- int mods = decodeModifiers( ke );
- if( mods & MD_CTRL )
+ if( m_hkfilter.should_process( *ke ) )
{
-#if !wxCHECK_VERSION( 2, 9, 0 )
- // I really look forward to the day when we will use only one version of wxWidgets..
- const int WXK_CONTROL_A = 1;
- const int WXK_CONTROL_Z = 26;
-#endif
+ int key = ke->GetKeyCode();
+ int mods = decodeModifiers( ke );
- // wxWidgets have a quirk related to Ctrl+letter hot keys handled by CHAR_EVT
- // http://docs.wxwidgets.org/trunk/classwx_key_event.html:
- // "char events for ASCII letters in this case carry codes corresponding to the ASCII
- // value of Ctrl-Latter, i.e. 1 for Ctrl-A, 2 for Ctrl-B and so on until 26 for Ctrl-Z."
- if( key >= WXK_CONTROL_A && key <= WXK_CONTROL_Z )
- key += 'A' - 1;
+ if( key == WXK_ESCAPE ) // ESC is the special key for cancelling tools
+ evt = TOOL_EVENT( TC_COMMAND, TA_CANCEL_TOOL );
+ else
+ evt = TOOL_EVENT( TC_KEYBOARD, TA_KEY_PRESSED, key | mods );
}
-
- if( key == WXK_ESCAPE ) // ESC is the special key for cancelling tools
- evt = TOOL_EVENT( TC_COMMAND, TA_CANCEL_TOOL );
- else
- evt = TOOL_EVENT( TC_KEYBOARD, TA_KEY_PRESSED, key | mods );
}
if( evt )
diff --git a/common/widgets/widget_hotkey_list.cpp b/common/widgets/widget_hotkey_list.cpp
index 3813670..ecc3e4b 100644
--- a/common/widgets/widget_hotkey_list.cpp
+++ b/common/widgets/widget_hotkey_list.cpp
@@ -84,6 +84,7 @@ public:
class HK_PROMPT_DIALOG : public DIALOG_SHIM
{
wxKeyEvent m_event;
+ EDA_HOTKEY_HOOK_FILTER m_hkfilter;
public:
HK_PROMPT_DIALOG( wxWindow* aParent, wxWindowID aId, const wxString& aTitle,
@@ -145,61 +146,21 @@ public:
// Binding both EVT_CHAR and EVT_CHAR_HOOK ensures that all key events,
// including specials like Tab and Return, are received, particularly
// on MSW.
- panel->Bind( wxEVT_CHAR, &HK_PROMPT_DIALOG::OnChar, this );
- panel->Bind( wxEVT_CHAR_HOOK, &HK_PROMPT_DIALOG::OnCharHook, this );
+ panel->Bind( wxEVT_CHAR, &HK_PROMPT_DIALOG::OnKeyEvent, this );
+ panel->Bind( wxEVT_CHAR_HOOK, &HK_PROMPT_DIALOG::OnKeyEvent, this );
}
- void OnCharHook( wxKeyEvent& aEvent )
+ void OnKeyEvent( wxKeyEvent& aEvent )
{
- // On certain platforms, EVT_CHAR_HOOK is the only handler that receives
- // certain "special" keys. However, it doesn't always receive "normal"
- // keys correctly. For example, with a US keyboard, it sees ? as shift+/.
- //
- // Untangling these incorrect keys would be too much trouble, so we bind
- // both events, and simply skip the EVT_CHAR_HOOK if it receives a
- // "normal" key.
-
- const enum wxKeyCode skipped_keys[] =
+ if( m_hkfilter.should_process( aEvent ) )
{
- WXK_NONE, WXK_SHIFT, WXK_ALT, WXK_CONTROL, WXK_CAPITAL,
- WXK_NUMLOCK, WXK_SCROLL, WXK_RAW_CONTROL
- };
-
- int key = aEvent.GetKeyCode();
-
- for( size_t i = 0; i < sizeof( skipped_keys ) / sizeof( skipped_keys[0] ); ++i )
- {
- if( key == skipped_keys[i] )
- return;
- }
-
- if( key <= 255 && isprint( key ) && !isspace( key ) )
- {
- // Let EVT_CHAR handle this one
- aEvent.DoAllowNextEvent();
-
- // On Windows, wxEvent::Skip must NOT be called.
- // On Linux and OSX, wxEvent::Skip MUST be called.
- // No, I don't know why.
-#ifndef __WXMSW__
- aEvent.Skip();
-#endif
- }
- else
- {
- OnChar( aEvent );
+ m_event = aEvent;
+ EndFlexible( wxID_OK );
}
}
- void OnChar( wxKeyEvent& aEvent )
- {
- m_event = aEvent;
- EndFlexible( wxID_OK );
- }
-
-
/**
* End the dialog whether modal or quasimodal
*/
@@ -302,7 +263,7 @@ void WIDGET_HOTKEY_LIST::EditItem( wxTreeListItem aItem )
wxString current_key = GetItemText( aItem, 1 );
wxKeyEvent key_event = HK_PROMPT_DIALOG::PromptForKey( GetParent(), name, current_key );
- long key = MapKeypressToKeycode( key_event );
+ EDA_KEY key = MapKeypressToKeycode( key_event );
if( hkdata && key )
{
@@ -438,7 +399,7 @@ void WIDGET_HOTKEY_LIST::OnSize( wxSizeEvent& aEvent )
}
-bool WIDGET_HOTKEY_LIST::CheckKeyConflicts( long aKey, const wxString& aSectionTag,
+bool WIDGET_HOTKEY_LIST::CheckKeyConflicts( EDA_KEY aKey, const wxString& aSectionTag,
EDA_HOTKEY** aConfKey, EDA_HOTKEY_CONFIG** aConfSect )
{
EDA_HOTKEY* conflicting_key = NULL;
@@ -632,43 +593,3 @@ bool WIDGET_HOTKEY_LIST::TransferDataFromControl()
return true;
}
-
-
-long WIDGET_HOTKEY_LIST::MapKeypressToKeycode( const wxKeyEvent& aEvent )
-{
- long key = aEvent.GetKeyCode();
-
- if( key == WXK_ESCAPE )
- {
- return 0;
- }
- else
- {
- if( key >= 'a' && key <= 'z' ) // convert to uppercase
- key = key + ('A' - 'a');
-
- // Remap Ctrl A (=1+GR_KB_CTRL) to Ctrl Z(=26+GR_KB_CTRL)
- // to GR_KB_CTRL+'A' .. GR_KB_CTRL+'Z'
- if( aEvent.ControlDown() && key >= WXK_CONTROL_A && key <= WXK_CONTROL_Z )
- key += 'A' - 1;
-
- /* Disallow shift for keys that have two keycodes on them (e.g. number and
- * punctuation keys) leaving only the "letter keys" of A-Z.
- * Then, you can have, e.g. Ctrl-5 and Ctrl-% (GB layout)
- * and Ctrl-( and Ctrl-5 (FR layout).
- * Otherwise, you'd have to have to say Ctrl-Shift-5 on a FR layout
- */
- bool keyIsLetter = key >= 'A' && key <= 'Z';
-
- if( aEvent.ShiftDown() && ( keyIsLetter || key > 256 ) )
- key |= GR_KB_SHIFT;
-
- if( aEvent.ControlDown() )
- key |= GR_KB_CTRL;
-
- if( aEvent.AltDown() )
- key |= GR_KB_ALT;
-
- return key;
- }
-}
diff --git a/include/class_drawpanel.h b/include/class_drawpanel.h
index 8c386f0..571346b 100644
--- a/include/class_drawpanel.h
+++ b/include/class_drawpanel.h
@@ -3,7 +3,7 @@
*
* Copyright (C) 2004 Jean-Pierre Charras, jaen-pierre.charras@xxxxxxxxxxxxxxxxxx
* Copyright (C) 2011 Wayne Stambaugh <stambaughw@xxxxxxxxxxx>
- * Copyright (C) 1992-2011 KiCad Developers, see AUTHORS.txt for contributors.
+ * Copyright (C) 1992-2016 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -34,7 +34,7 @@
#include <colors.h>
#include <base_struct.h>
#include <gr_basic.h>
-
+#include <hotkeys_basic.h>
class BASE_SCREEN;
class PCB_SCREEN;
@@ -116,6 +116,9 @@ private:
/// >= 0 (or >= n) if a block can start
int m_canStartBlock;
+ /// Hotkey event filter, for handling key events
+ EDA_HOTKEY_HOOK_FILTER m_hkfilter;
+
public:
EDA_DRAW_PANEL( EDA_DRAW_FRAME* parent, int id, const wxPoint& pos, const wxSize& size );
@@ -270,7 +273,6 @@ public:
void OnMouseEntering( wxMouseEvent& aEvent );
void OnMouseLeaving( wxMouseEvent& event );
void OnKeyEvent( wxKeyEvent& event );
- void OnCharHook( wxKeyEvent& event );
void OnPan( wxCommandEvent& event );
diff --git a/include/hotkeys_basic.h b/include/hotkeys_basic.h
index 089fcce..abd62ba 100644
--- a/include/hotkeys_basic.h
+++ b/include/hotkeys_basic.h
@@ -57,7 +57,7 @@ extern wxString g_CommonSectionTag;
class EDA_HOTKEY
{
public:
- int m_KeyCode; // Key code (ascii value for ascii keys or wxWidgets code for function key
+ EDA_KEY m_KeyCode; // Key code (ascii value for ascii keys or wxWidgets code for function key
wxString m_InfoMsg; // info message.
int m_Idcommand; // internal id for the corresponding command (see hotkey_id_commnand list)
int m_IdMenuEvent; // id to call the corresponding event (if any) (see id.h)
@@ -203,7 +203,7 @@ void DisplayHotkeyList( EDA_BASE_FRAME* aFrame, struct EDA_HOTKEY_CONFIG* aList
* @param aList = pointer to a EDA_HOTKEY list of commands
* @return the corresponding EDA_HOTKEY pointer from the EDA_HOTKEY List
*/
-EDA_HOTKEY* GetDescriptorFromHotkey( int aKey, EDA_HOTKEY** aList );
+EDA_HOTKEY* GetDescriptorFromHotkey( EDA_KEY aKey, EDA_HOTKEY** aList );
/**
* Function GetDescriptorFromCommand
@@ -244,4 +244,57 @@ enum common_hotkey_id_commnand {
HK_COMMON_END
};
+/**
+ * Class EDA_HOTKEY_HOOK_FILTER
+ *
+ * Check if a key received by wxEVT_CHAR_HOOK is a "special" key that has to be
+ * handled at wxEVT_CHAR_HOOK rather than wxEVT_CHAR. This is the case for
+ * combinations like Ctrl+Tab, which are indistinguishable from Ctrl+I in
+ * wxEVT_CHAR. Other events must be handled in wxEVT_CHAR instead, as
+ * wxEVT_CHAR_HOOK handled them before input method filters have been applied.
+ * An example implementation is:
+ *
+ * void OnKeyEvent( wxKeyEvent& aEvent ) // reponds to wxEVT_CHAR and wxEVT_CHAR_HOOK
+ * {
+ * static EDA_HOTKEY_HOOK_FILTER filter;
+ *
+ * if( !filter.should_process( aEvent ) )
+ * {
+ * return;
+ * }
+ *
+ * ......
+ *
+ * if( something )
+ * {
+ * filter.skip( aEvent );
+ * }
+ * }
+ *
+ */
+class EDA_HOTKEY_HOOK_FILTER
+{
+ bool m_skip_evtchar;
+
+ static bool should_process_in_hook( wxKeyEvent &aEvent );
+
+ static void allow_char_hook_propagation( wxKeyEvent &aEvent );
+
+public:
+ EDA_HOTKEY_HOOK_FILTER();
+
+ /**
+ * Analyze an event and determine whether it should be processed.
+ */
+ bool should_process( wxKeyEvent& aEvent );
+
+ /**
+ * Skip event. Use this instead of wxEvent::Skip, as the behavior
+ * of that for wxEVT_CHAR_HOOK is platform-dependent.
+ */
+ static void skip( wxKeyEvent& aEvent );
+};
+
+EDA_KEY MapKeypressToKeycode( const wxKeyEvent& aEvent );
+
#endif // HOTKEYS_BASIC_H
diff --git a/include/tool/tool_dispatcher.h b/include/tool/tool_dispatcher.h
index cf6e852..ff1e0b5 100644
--- a/include/tool/tool_dispatcher.h
+++ b/include/tool/tool_dispatcher.h
@@ -2,6 +2,7 @@
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2013 CERN
+ * Copyright (C) 2016 KiCad Developers, see CHANGELOG.TXT for contributors.
* @author Tomasz Wlostowski <tomasz.wlostowski@xxxxxxx>
*
* This program is free software; you can redistribute it and/or
@@ -26,6 +27,7 @@
#define __TOOL_DISPATCHER_H
#include <vector>
+#include <hotkeys_basic.h>
#include <wx/event.h>
#include <tool/tool_event.h>
@@ -130,6 +132,9 @@ private:
///> Instance of tool manager that cooperates with the dispatcher.
TOOL_MANAGER* m_toolMgr;
+
+ ///> Hotkey filter instance for handling keypress events
+ EDA_HOTKEY_HOOK_FILTER m_hkfilter;
};
#endif
diff --git a/include/widgets/widget_hotkey_list.h b/include/widgets/widget_hotkey_list.h
index bfaf010..a29264d 100644
--- a/include/widgets/widget_hotkey_list.h
+++ b/include/widgets/widget_hotkey_list.h
@@ -130,7 +130,7 @@ protected:
* @param aConfKey - if not NULL, outparam getting the key this one conflicts with
* @param aConfSect - if not NULL, outparam getting the section this one conflicts with
*/
- bool CheckKeyConflicts( long aKey, const wxString& aSectionTag,
+ bool CheckKeyConflicts( EDA_KEY aKey, const wxString& aSectionTag,
EDA_HOTKEY** aConfKey, EDA_HOTKEY_CONFIG** aConfSect );
/**
@@ -191,12 +191,6 @@ public:
* @return true iff the operation was successful
*/
bool TransferDataFromControl();
-
- /**
- * Static method MapKeypressToKeycode
- * Map a keypress event to the correct key code for use as a hotkey.
- */
- static long MapKeypressToKeycode( const wxKeyEvent& aEvent );
};
#endif // __widget_hotkey_list__
Follow ups
References