Fix wxKeyEvent::GetKeyCode() for non-US keyboard layouts
Use the key code corresponding to the key in the US keyboard layout for the key down/up events even when not actually using US layout, as this is much more useful than simply returning 0 as was done before. It also is compatible with the behaviour of the other ports. See #17643, #23379, #23410. (cherry picked from commit 2c0f6a2aa0c8d0650d1f856aa279ce7495925c17)
This commit is contained in:
parent
171369203f
commit
87ae8d5aa7
@ -61,7 +61,7 @@ case $(uname -s) in
|
||||
extra_deps='libwebkit2gtk-4.0-dev libgspell-1-dev'
|
||||
;;
|
||||
2) libtoolkit_dev=libgtk2.0-dev
|
||||
extra_deps='libwebkitgtk-dev'
|
||||
extra_deps='libwebkitgtk-dev libxkbcommon-dev'
|
||||
;;
|
||||
*) echo 'Please specify wxGTK_VERSION explicitly.' >&2
|
||||
exit 1
|
||||
|
96
configure
vendored
96
configure
vendored
@ -955,6 +955,8 @@ GSPELL_LIBS
|
||||
GSPELL_CFLAGS
|
||||
LIBSECRET_LIBS
|
||||
LIBSECRET_CFLAGS
|
||||
XKBCOMMON_LIBS
|
||||
XKBCOMMON_CFLAGS
|
||||
GXX_VERSION
|
||||
LIBICONV
|
||||
CXXFLAGS_VISIBILITY
|
||||
@ -1436,6 +1438,8 @@ WAYLAND_EGL_CFLAGS
|
||||
WAYLAND_EGL_LIBS
|
||||
MesaGL_CFLAGS
|
||||
MesaGL_LIBS
|
||||
XKBCOMMON_CFLAGS
|
||||
XKBCOMMON_LIBS
|
||||
LIBSECRET_CFLAGS
|
||||
LIBSECRET_LIBS
|
||||
GSPELL_CFLAGS
|
||||
@ -2478,6 +2482,10 @@ Some influential environment variables:
|
||||
MesaGL_CFLAGS
|
||||
C compiler flags for MesaGL, overriding pkg-config
|
||||
MesaGL_LIBS linker flags for MesaGL, overriding pkg-config
|
||||
XKBCOMMON_CFLAGS
|
||||
C compiler flags for XKBCOMMON, overriding pkg-config
|
||||
XKBCOMMON_LIBS
|
||||
linker flags for XKBCOMMON, overriding pkg-config
|
||||
LIBSECRET_CFLAGS
|
||||
C compiler flags for LIBSECRET, overriding pkg-config
|
||||
LIBSECRET_LIBS
|
||||
@ -38043,6 +38051,94 @@ $as_echo "$as_me: WARNING: wxFileSystemWatcher won't be available on this platfo
|
||||
fi
|
||||
fi
|
||||
|
||||
if test "$wxUSE_GTK" = 1; then
|
||||
if test "$USE_WIN32" != 1 -a "$USE_DARWIN" != 1; then
|
||||
|
||||
pkg_failed=no
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for XKBCOMMON" >&5
|
||||
$as_echo_n "checking for XKBCOMMON... " >&6; }
|
||||
|
||||
if test -n "$PKG_CONFIG"; then
|
||||
if test -n "$XKBCOMMON_CFLAGS"; then
|
||||
pkg_cv_XKBCOMMON_CFLAGS="$XKBCOMMON_CFLAGS"
|
||||
else
|
||||
if test -n "$PKG_CONFIG" && \
|
||||
{ { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"xkbcommon\""; } >&5
|
||||
($PKG_CONFIG --exists --print-errors "xkbcommon") 2>&5
|
||||
ac_status=$?
|
||||
$as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
|
||||
test $ac_status = 0; }; then
|
||||
pkg_cv_XKBCOMMON_CFLAGS=`$PKG_CONFIG --cflags "xkbcommon" 2>/dev/null`
|
||||
else
|
||||
pkg_failed=yes
|
||||
fi
|
||||
fi
|
||||
else
|
||||
pkg_failed=untried
|
||||
fi
|
||||
if test -n "$PKG_CONFIG"; then
|
||||
if test -n "$XKBCOMMON_LIBS"; then
|
||||
pkg_cv_XKBCOMMON_LIBS="$XKBCOMMON_LIBS"
|
||||
else
|
||||
if test -n "$PKG_CONFIG" && \
|
||||
{ { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"xkbcommon\""; } >&5
|
||||
($PKG_CONFIG --exists --print-errors "xkbcommon") 2>&5
|
||||
ac_status=$?
|
||||
$as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
|
||||
test $ac_status = 0; }; then
|
||||
pkg_cv_XKBCOMMON_LIBS=`$PKG_CONFIG --libs "xkbcommon" 2>/dev/null`
|
||||
else
|
||||
pkg_failed=yes
|
||||
fi
|
||||
fi
|
||||
else
|
||||
pkg_failed=untried
|
||||
fi
|
||||
|
||||
|
||||
|
||||
if test $pkg_failed = yes; then
|
||||
|
||||
if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
|
||||
_pkg_short_errors_supported=yes
|
||||
else
|
||||
_pkg_short_errors_supported=no
|
||||
fi
|
||||
if test $_pkg_short_errors_supported = yes; then
|
||||
XKBCOMMON_PKG_ERRORS=`$PKG_CONFIG --short-errors --errors-to-stdout --print-errors "xkbcommon"`
|
||||
else
|
||||
XKBCOMMON_PKG_ERRORS=`$PKG_CONFIG --errors-to-stdout --print-errors "xkbcommon"`
|
||||
fi
|
||||
# Put the nasty error message in config.log where it belongs
|
||||
echo "$XKBCOMMON_PKG_ERRORS" >&5
|
||||
|
||||
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: libxkbcommon not found, key codes in key events may be incorrect" >&5
|
||||
$as_echo "$as_me: WARNING: libxkbcommon not found, key codes in key events may be incorrect" >&2;}
|
||||
|
||||
|
||||
elif test $pkg_failed = untried; then
|
||||
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: libxkbcommon not found, key codes in key events may be incorrect" >&5
|
||||
$as_echo "$as_me: WARNING: libxkbcommon not found, key codes in key events may be incorrect" >&2;}
|
||||
|
||||
|
||||
else
|
||||
XKBCOMMON_CFLAGS=$pkg_cv_XKBCOMMON_CFLAGS
|
||||
XKBCOMMON_LIBS=$pkg_cv_XKBCOMMON_LIBS
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
|
||||
$as_echo "yes" >&6; }
|
||||
|
||||
CFLAGS="$XKBCOMMON_CFLAGS $CFLAGS"
|
||||
CXXFLAGS="$XKBCOMMON_CFLAGS $CXXFLAGS"
|
||||
GUI_TK_LIBRARY="$GUI_TK_LIBRARY $XKBCOMMON_LIBS"
|
||||
$as_echo "#define HAVE_XKBCOMMON 1" >>confdefs.h
|
||||
|
||||
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
|
||||
if test "$wxUSE_SECRETSTORE" = "yes"; then
|
||||
if test "$WXGTK1" = "1"; then
|
||||
|
19
configure.in
19
configure.in
@ -5688,6 +5688,25 @@ if test "$wxUSE_FSWATCHER" = "yes"; then
|
||||
fi
|
||||
fi
|
||||
|
||||
dnl ---------------------------------------------------------------------------
|
||||
dnl xkbcommon library for key code translations in wxGTK
|
||||
dnl ---------------------------------------------------------------------------
|
||||
if test "$wxUSE_GTK" = 1; then
|
||||
if test "$USE_WIN32" != 1 -a "$USE_DARWIN" != 1; then
|
||||
PKG_CHECK_MODULES(XKBCOMMON, [xkbcommon],
|
||||
[
|
||||
CFLAGS="$XKBCOMMON_CFLAGS $CFLAGS"
|
||||
CXXFLAGS="$XKBCOMMON_CFLAGS $CXXFLAGS"
|
||||
GUI_TK_LIBRARY="$GUI_TK_LIBRARY $XKBCOMMON_LIBS"
|
||||
AC_DEFINE(HAVE_XKBCOMMON)
|
||||
],
|
||||
[
|
||||
AC_MSG_WARN([libxkbcommon not found, key codes in key events may be incorrect])
|
||||
]
|
||||
)
|
||||
fi
|
||||
fi
|
||||
|
||||
dnl ---------------------------------------------------------------------------
|
||||
dnl Secret storage
|
||||
dnl ---------------------------------------------------------------------------
|
||||
|
@ -253,6 +253,7 @@ All (GUI):
|
||||
|
||||
wxGTK:
|
||||
|
||||
- Fix key codes with Shift/on non-US keyboards (Ivan Sorokin, #17643, #23379).
|
||||
- Dramatically optimize adding many items to wxChoice (Ian McInerney, #23443).
|
||||
- Improve document wxGLCanvas::CreateSurface() (Dan Gudmundsson, #23366).
|
||||
- Fix loading WebKit2 extension when using wxWebView (Scott Talbert, #23497).
|
||||
|
@ -1246,6 +1246,9 @@
|
||||
/* Define if setpriority() is available. */
|
||||
#undef HAVE_SETPRIORITY
|
||||
|
||||
/* Define if xkbcommon is available */
|
||||
#undef HAVE_XKBCOMMON
|
||||
|
||||
/* Define if xlocale.h header file exists. */
|
||||
#undef HAVE_XLOCALE_H
|
||||
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include "wx/settings.h"
|
||||
#include "wx/msgdlg.h"
|
||||
#include "wx/math.h"
|
||||
#include "wx/module.h"
|
||||
#endif
|
||||
|
||||
#include "wx/display.h"
|
||||
@ -54,6 +55,12 @@ using namespace wxGTKImpl;
|
||||
typedef guint KeySym;
|
||||
#endif
|
||||
|
||||
// Use libxkbcommon for key code translation if we need and have it.
|
||||
#if (defined (GDK_WINDOWING_X11) || defined (GDK_WINDOWING_WAYLAND)) && defined (HAVE_XKBCOMMON)
|
||||
#define wxHAS_XKB
|
||||
#include <xkbcommon/xkbcommon.h>
|
||||
#endif
|
||||
|
||||
#ifdef __WXGTK4__
|
||||
#define wxGTK_HAS_COMPOSITING_SUPPORT 0
|
||||
#else
|
||||
@ -225,6 +232,85 @@ static wxWindowGTK *gs_deferredFocusOut = NULL;
|
||||
GdkEvent *g_lastMouseEvent = NULL;
|
||||
int g_lastButtonNumber = 0;
|
||||
|
||||
#ifdef wxHAS_XKB
|
||||
namespace
|
||||
{
|
||||
|
||||
// Global data used for raw key codes translation.
|
||||
class XkbData
|
||||
{
|
||||
public:
|
||||
XkbData()
|
||||
{
|
||||
m_ctx = NULL;
|
||||
m_keymap = NULL;
|
||||
m_state = NULL;
|
||||
}
|
||||
|
||||
// Get the state pointer allocating it on demand if necessary.
|
||||
xkb_state* GetState()
|
||||
{
|
||||
if ( !m_state )
|
||||
{
|
||||
m_ctx = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
|
||||
struct xkb_rule_names names = {0};
|
||||
names.layout = "us";
|
||||
m_keymap = xkb_keymap_new_from_names(m_ctx, &names, XKB_KEYMAP_COMPILE_NO_FLAGS);
|
||||
m_state = xkb_state_new(m_keymap);
|
||||
}
|
||||
|
||||
return m_state;
|
||||
}
|
||||
|
||||
// Called by wxXKBModule::OnExit() to free all our data.
|
||||
void Free()
|
||||
{
|
||||
if ( m_state )
|
||||
{
|
||||
xkb_state_unref(m_state);
|
||||
m_state = NULL;
|
||||
}
|
||||
|
||||
if ( m_keymap )
|
||||
{
|
||||
xkb_keymap_unref(m_keymap);
|
||||
m_keymap = NULL;
|
||||
}
|
||||
|
||||
if ( m_ctx )
|
||||
{
|
||||
xkb_context_unref(m_ctx);
|
||||
m_ctx = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
xkb_context *m_ctx;
|
||||
xkb_keymap *m_keymap;
|
||||
xkb_state *m_state;
|
||||
|
||||
wxDECLARE_NO_COPY_CLASS(XkbData);
|
||||
};
|
||||
|
||||
XkbData gs_xkbData;
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
// wxXKBModule: used for freeing global xkb data
|
||||
class wxXKBModule : public wxModule
|
||||
{
|
||||
public:
|
||||
bool OnInit() wxOVERRIDE { return true; }
|
||||
void OnExit() wxOVERRIDE { gs_xkbData.Free(); }
|
||||
|
||||
private:
|
||||
wxDECLARE_DYNAMIC_CLASS(wxXKBModule);
|
||||
};
|
||||
|
||||
wxIMPLEMENT_DYNAMIC_CLASS(wxXKBModule, wxModule);
|
||||
|
||||
#endif // wxHAS_XKB
|
||||
|
||||
#ifdef __WXGTK3__
|
||||
static GList* gs_sizeRevalidateList;
|
||||
static GSList* gs_setSizeRequestList;
|
||||
@ -1028,7 +1114,38 @@ wxTranslateGTKKeyEventToWx(wxKeyEvent& event,
|
||||
: wxT("press"),
|
||||
static_cast<unsigned long>(keysym));
|
||||
|
||||
long key_code = wxTranslateKeySymToWXKey(keysym, false /* !isChar */);
|
||||
long key_code = 0;
|
||||
|
||||
#ifdef wxHAS_XKB
|
||||
if ( gdk_keyval_to_unicode(gdk_event->keyval) )
|
||||
{
|
||||
// If the event has the corresponding Unicode char, let us set key_code
|
||||
// to character that is generated by that key in the US keyboard layout
|
||||
// (as wxMSW does and because it's useful to be able to identify the
|
||||
// key independently of the current keyboard layout).
|
||||
char key_code_str[64];
|
||||
xkb_state_key_get_utf8(gs_xkbData.GetState(),
|
||||
gdk_event->hardware_keycode,
|
||||
key_code_str,
|
||||
sizeof(key_code_str));
|
||||
if ( strlen(key_code_str) == 1 )
|
||||
{
|
||||
key_code = key_code_str[0];
|
||||
|
||||
// If key_code is a Latin char, it should be in upper register to
|
||||
// match the other ports.
|
||||
if (islower(key_code))
|
||||
{
|
||||
key_code = toupper(key_code);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // wxHAS_XKB
|
||||
|
||||
if ( !key_code )
|
||||
{
|
||||
key_code = wxTranslateKeySymToWXKey(keysym, false /* !isChar */);
|
||||
}
|
||||
|
||||
if ( !key_code )
|
||||
{
|
||||
@ -1308,16 +1425,29 @@ gtk_window_key_press_callback( GtkWidget *WXUNUSED(widget),
|
||||
}
|
||||
}
|
||||
|
||||
if ( key_code )
|
||||
const guint32 uniChar = gdk_keyval_to_unicode(keysym);
|
||||
if ( key_code || uniChar )
|
||||
{
|
||||
wxKeyEvent eventChar(wxEVT_CHAR, event);
|
||||
|
||||
wxLogTrace(TRACE_KEYS, wxT("Char event: %ld"), key_code);
|
||||
|
||||
eventChar.m_keyCode = key_code;
|
||||
if ( event.ControlDown() && isalpha(event.m_keyCode) )
|
||||
{
|
||||
// Ctrl+letter is handled specially by AdjustCharEventKeyCodes().
|
||||
eventChar.m_keyCode = event.m_keyCode;
|
||||
#if wxUSE_UNICODE
|
||||
eventChar.m_uniChar = gdk_keyval_to_unicode(key_code);
|
||||
eventChar.m_uniChar = event.m_uniChar;
|
||||
#endif // wxUSE_UNICODE
|
||||
}
|
||||
else
|
||||
{
|
||||
// use Unicode values
|
||||
eventChar.m_keyCode = key_code;
|
||||
#if wxUSE_UNICODE
|
||||
eventChar.m_uniChar = uniChar;
|
||||
#endif // wxUSE_UNICODE
|
||||
}
|
||||
|
||||
wxLogTrace(TRACE_KEYS, wxT("Char event: %ld"), eventChar.m_keyCode);
|
||||
|
||||
AdjustCharEventKeyCodes(eventChar);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user