From 1033fb048dec849906f76ece25f154e6a61fde4e Mon Sep 17 00:00:00 2001 From: Scott Talbert Date: Fri, 2 Sep 2016 20:38:00 -0400 Subject: [PATCH] Fix wxGetKeyState() on non-X11 wxGTK backends (e.g., Wayland) wxGetKeyState() does not currently work on non-X11 GTK backends, and in some cases it has been reported to crash. It seems that the most likely use case for wxGetKeyState() is to query the modifier keys, so on non-X11 backends, use GTK+ calls to retrieve the modifier key state. Non-modifier keys are not currently implemented, update the documentation to mention this. Closes https://github.com/wxWidgets/wxWidgets/pull/320 --- interface/wx/utils.h | 3 +++ src/unix/utilsx11.cpp | 58 ++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 60 insertions(+), 1 deletion(-) diff --git a/interface/wx/utils.h b/interface/wx/utils.h index 4b640351dc..12c433a3f3 100644 --- a/interface/wx/utils.h +++ b/interface/wx/utils.h @@ -372,6 +372,9 @@ wxString wxGetDisplayName(); Even though there are virtual key codes defined for mouse buttons, they cannot be used with this function currently. + In wxGTK, this function can be only used with modifier keys (@c WXK_ALT, @c + WXK_CONTROL and @c WXK_SHIFT) when not using X11 backend currently. + @header{wx/utils.h} */ bool wxGetKeyState(wxKeyCode key); diff --git a/src/unix/utilsx11.cpp b/src/unix/utilsx11.cpp index 1f1febc8d4..bcac79cf09 100644 --- a/src/unix/utilsx11.cpp +++ b/src/unix/utilsx11.cpp @@ -2535,7 +2535,7 @@ int wxUnicodeCharXToWX(WXKeySym keySym) // check current state of a key // ---------------------------------------------------------------------------- -bool wxGetKeyState(wxKeyCode key) +static bool wxGetKeyStateX11(wxKeyCode key) { wxASSERT_MSG(key != WXK_LBUTTON && key != WXK_RBUTTON && key != WXK_MBUTTON, wxT("can't use wxGetKeyState() for mouse buttons")); @@ -2582,6 +2582,62 @@ bool wxGetKeyState(wxKeyCode key) #endif // !defined(__WXGTK__) || defined(GDK_WINDOWING_X11) +// We need to use GDK functions when using wxGTK with a non-X11 backend, the +// X11 code above can't work in this case. +#ifdef __WXGTK__ + +// gdk_keymap_get_modifier_state() is only available since 3.4 +#if GTK_CHECK_VERSION(3,4,0) + +#define wxHAS_GETKEYSTATE_GTK + +static bool wxGetKeyStateGTK(wxKeyCode key) +{ + if (gtk_check_version(3,4,0) != NULL) + return false; + + GdkDisplay* display = gdk_window_get_display(wxGetTopLevelGDK()); + GdkKeymap* keymap = gdk_keymap_get_for_display(display); + guint state = gdk_keymap_get_modifier_state(keymap); + guint mask = 0; + switch (key) + { + case WXK_ALT: + mask = GDK_MOD1_MASK; + break; + + case WXK_CONTROL: + mask = GDK_CONTROL_MASK; + break; + + case WXK_SHIFT: + mask = GDK_SHIFT_MASK; + break; + + default: + wxASSERT_MSG(wxS("Unsupported key, only modifiers can be used")); + return false; + } + return state & mask; +} + +#endif // GTK+ 3.4 +#endif // __WXGTK__ + +bool wxGetKeyState(wxKeyCode key) +{ +#ifdef wxHAS_GETKEYSTATE_GTK + GdkDisplay* display = gdk_window_get_display(wxGetTopLevelGDK()); + const char* name = g_type_name(G_TYPE_FROM_INSTANCE(display)); + if (strcmp(name, "GdkX11Display") != 0) + { + return wxGetKeyStateGTK(key); + } +#endif // GTK+ 3.4+ + + return wxGetKeyStateX11(key); +} + // ---------------------------------------------------------------------------- // Launch document with default app // ----------------------------------------------------------------------------