From 33553ed1419ea430a466eff91ff7648b01da76bc Mon Sep 17 00:00:00 2001 From: Dominique Martinet Date: Tue, 2 Nov 2021 10:07:59 +0900 Subject: [PATCH 1/3] gtk/window: generate WXK_NONE key event for unknown keys There are still plenty of X11 keys which have no WXK mapping and might be useful for applications to act upon. Instead of trying to remap all of them, generate a WXK_NONE key event and let applications deal with it using GetRawKeyCode() if appropriate. --- src/gtk/window.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/gtk/window.cpp b/src/gtk/window.cpp index dbee540948..eef89819f8 100644 --- a/src/gtk/window.cpp +++ b/src/gtk/window.cpp @@ -1080,12 +1080,12 @@ wxTranslateGTKKeyEventToWx(wxKeyEvent& event, event.m_uniChar = event.m_keyCode; } - // sending unknown key events doesn't really make sense + // sending a WXK_NONE key and let app deal with it the RawKeyCode if required if ( !key_code && !event.m_uniChar ) - return false; + event.m_keyCode = WXK_NONE; #else if (!key_code) - return false; + event.m_keyCode = WXK_NONE; #endif // wxUSE_UNICODE // now fill all the other fields From 307aaf83d84db9a6197d1a76b915ec45098466a5 Mon Sep 17 00:00:00 2001 From: Dominique Martinet Date: Tue, 2 Nov 2021 10:09:14 +0900 Subject: [PATCH 2/3] gtk/window: cleanup dead code around wxTranslateGTKKeyEventToWx The previous commit made wxTranslateGTKKeyEventToWx never fail, so make it void and remove all dead code resulting from the lack of failure. --- src/gtk/window.cpp | 82 ++++++++++++++++++---------------------------- 1 file changed, 32 insertions(+), 50 deletions(-) diff --git a/src/gtk/window.cpp b/src/gtk/window.cpp index eef89819f8..a68dae6d12 100644 --- a/src/gtk/window.cpp +++ b/src/gtk/window.cpp @@ -961,7 +961,7 @@ static void wxFillOtherKeyEventFields(wxKeyEvent& event, } -static bool +static void wxTranslateGTKKeyEventToWx(wxKeyEvent& event, wxWindowGTK *win, GdkEventKey *gdk_event) @@ -1090,8 +1090,6 @@ wxTranslateGTKKeyEventToWx(wxKeyEvent& event, // now fill all the other fields wxFillOtherKeyEventFields(event, win, gdk_event); - - return true; } @@ -1181,55 +1179,46 @@ gtk_window_key_press_callback( GtkWidget *WXUNUSED(widget), wxKeyEvent event( wxEVT_KEY_DOWN ); bool ret = false; - bool return_after_IM = false; - if( wxTranslateGTKKeyEventToWx(event, win, gdk_event) ) + wxTranslateGTKKeyEventToWx(event, win, gdk_event); + // Send the CHAR_HOOK event first + if ( SendCharHookEvent(event, win) ) { - // Send the CHAR_HOOK event first - if ( SendCharHookEvent(event, win) ) - { - // Don't do anything at all with this event any more. - return TRUE; - } + // Don't do anything at all with this event any more. + return TRUE; + } - // Next check for accelerators. + // Next check for accelerators. #if wxUSE_ACCEL - wxWindowGTK *ancestor = win; - while (ancestor) + wxWindowGTK *ancestor = win; + while (ancestor) + { + int command = ancestor->GetAcceleratorTable()->GetCommand( event ); + if (command != -1) { - int command = ancestor->GetAcceleratorTable()->GetCommand( event ); - if (command != -1) + wxCommandEvent menu_event( wxEVT_MENU, command ); + ret = ancestor->HandleWindowEvent( menu_event ); + + if ( !ret ) { - wxCommandEvent menu_event( wxEVT_MENU, command ); - ret = ancestor->HandleWindowEvent( menu_event ); - - if ( !ret ) - { - // if the accelerator wasn't handled as menu event, try - // it as button click (for compatibility with other - // platforms): - wxCommandEvent button_event( wxEVT_BUTTON, command ); - ret = ancestor->HandleWindowEvent( button_event ); - } - - break; + // if the accelerator wasn't handled as menu event, try + // it as button click (for compatibility with other + // platforms): + wxCommandEvent button_event( wxEVT_BUTTON, command ); + ret = ancestor->HandleWindowEvent( button_event ); } - if (ancestor->IsTopNavigationDomain(wxWindow::Navigation_Accel)) - break; - ancestor = ancestor->GetParent(); + + break; } + if (ancestor->IsTopNavigationDomain(wxWindow::Navigation_Accel)) + break; + ancestor = ancestor->GetParent(); + } #endif // wxUSE_ACCEL - // If not an accelerator, then emit KEY_DOWN event - if ( !ret ) - ret = win->HandleWindowEvent( event ); - } - else - { - // Return after IM processing as we cannot do - // anything with it anyhow. - return_after_IM = true; - } + // If not an accelerator, then emit KEY_DOWN event + if ( !ret ) + ret = win->HandleWindowEvent( event ); if ( !ret ) { @@ -1252,9 +1241,6 @@ gtk_window_key_press_callback( GtkWidget *WXUNUSED(widget), } } - if (return_after_IM) - return FALSE; - // Only send wxEVT_CHAR event if not processed yet. Thus, ALT-x // will only be sent if it is not in an accelerator table. if (!ret) @@ -1382,11 +1368,7 @@ gtk_window_key_release_callback( GtkWidget * WXUNUSED(widget), wxPROCESS_EVENT_ONCE(GdkEventKey, gdk_event); wxKeyEvent event( wxEVT_KEY_UP ); - if ( !wxTranslateGTKKeyEventToWx(event, win, gdk_event) ) - { - // unknown key pressed, ignore (the event would be useless anyhow) - return FALSE; - } + wxTranslateGTKKeyEventToWx(event, win, gdk_event); return win->GTKProcessEvent(event); } From 5f0749f4fdc45a0f4cdb36d71616414ef4282e4b Mon Sep 17 00:00:00 2001 From: Dominique Martinet Date: Fri, 5 Nov 2021 09:46:28 +0900 Subject: [PATCH 3/3] Document generation of WXK_NONE key events for unknown keys Add a paragraph for keys where GetUnicodeKey and GetKeyCode both return WXK_NONE, that GetRawKeyCode is platform specific, and that such keys generate no wxEVT_CHAR event. --- interface/wx/event.h | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/interface/wx/event.h b/interface/wx/event.h index 9dde8ccf63..2744138c18 100644 --- a/interface/wx/event.h +++ b/interface/wx/event.h @@ -1321,20 +1321,26 @@ enum wxKeyCategoryFlags This event class contains information about key press and release events. The main information carried by this event is the key being pressed or - released. It can be accessed using either GetKeyCode() function or - GetUnicodeKey(). For the printable characters, the latter should be used as - it works for any keys, including non-Latin-1 characters that can be entered - when using national keyboard layouts. GetKeyCode() should be used to handle + released. It can be accessed using one of GetUnicodeKey(), GetKeyCode() + or GetRawKeyCode() functions. + For the printable characters, GetUnicodeKey() should be used as it works + for any keys, including non-Latin-1 characters that can be entered when + using national keyboard layouts. GetKeyCode() should be used to handle special characters (such as cursor arrows keys or @c HOME or @c INS and so on) which correspond to ::wxKeyCode enum elements above the @c WXK_START constant. While GetKeyCode() also returns the character code for Latin-1 keys for compatibility, it doesn't work for Unicode characters in general - and will return @c WXK_NONE for any non-Latin-1 ones. For this reason, it's - recommended to always use GetUnicodeKey() and only fall back to GetKeyCode() - if GetUnicodeKey() returned @c WXK_NONE meaning that the event corresponds - to a non-printable special keys. + and will return @c WXK_NONE for any non-Latin-1 ones. + If both GetUnicodeKey() and GetKeyCode() return @c WXK_NONE then the key + has no @c WXK_xxx mapping and GetRawKeyCode() can be used to distinguish + between keys, but raw key codes are platform specific. + For these reasons, it is recommended to always use GetUnicodeKey() and + only fall back to GetKeyCode() if GetUnicodeKey() returned @c WXK_NONE, + meaning that the event corresponds to a non-printable special keys, then + optionally check GetRawKeyCode() if GetKeyCode() also returned @c WXK_NONE + or simply ignore that key. - While both of these functions can be used with the events of @c + While these three functions can be used with the events of @c wxEVT_KEY_DOWN, @c wxEVT_KEY_UP and @c wxEVT_CHAR types, the values returned by them are different for the first two events and the last one. For the latter, the key returned corresponds to the character that would @@ -1368,6 +1374,10 @@ enum wxKeyCategoryFlags can be used to retrieve the key code as GetKeyCode() just returns @c WXK_NONE in this case. + Also, note that @c wxEVT_CHAR events are not generated for keys which do + not have a wxWidgets mapping, so GetRawKeyCode() should never be required + for this event. + To summarize: you should handle @c wxEVT_CHAR if you need the translated key and @c wxEVT_KEY_DOWN if you only need the value of the key itself, independent of the current keyboard state.