Skip to content

Commit

Permalink
Use XkbGetNamedIndicator on Linux instead of relying on the (unreliab…
Browse files Browse the repository at this point in the history
…le) GDK method.
  • Loading branch information
kevinrushforth committed Jan 25, 2021
1 parent cb0e10a commit c4961b1
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 19 deletions.
54 changes: 41 additions & 13 deletions modules/javafx.graphics/src/main/native-glass/gtk/glass_key.cpp
Expand Up @@ -29,6 +29,7 @@
#include <glib.h>
#include "glass_general.h"
#include <gdk/gdkkeysyms.h>
#include <X11/XKBlib.h>

static gboolean key_initialized = FALSE;
static GHashTable *keymap;
Expand Down Expand Up @@ -345,6 +346,25 @@ JNIEXPORT jint JNICALL Java_com_sun_glass_ui_gtk_GtkApplication__1getKeyCodeForC
return gdk_keyval_to_glass(keyval);
}

/*
* Function to determine whether the Xkb extention is available. This is a
* precaution against X protocol errors, although it should be available on all
* Linux systems.
*/

static Bool xkbInitialized = False;
static Bool xkbAvailable = False;

static Bool isXkbAvailable(Display *display) {
if (!xkbInitialized) {
int xkbMajor = XkbMajorVersion;
int xkbMinor = XkbMinorVersion;
xkbAvailable = XkbQueryExtension(display, NULL, NULL, NULL, &xkbMajor, &xkbMinor);
xkbInitialized = True;
}
return xkbAvailable;
}

/*
* Class: com_sun_glass_ui_gtk_GtkApplication
* Method: _isKeyLocked
Expand All @@ -353,28 +373,36 @@ JNIEXPORT jint JNICALL Java_com_sun_glass_ui_gtk_GtkApplication__1getKeyCodeForC
JNIEXPORT jint JNICALL Java_com_sun_glass_ui_gtk_GtkApplication__1isKeyLocked
(JNIEnv * env, jobject obj, jint keyCode)
{
#ifdef GLASS_GTK3
GdkKeymap *keyMap = gdk_keymap_get_default();
gboolean lockState = FALSE;
Display* display = gdk_x11_display_get_xdisplay(gdk_display_get_default());
if (!isXkbAvailable(display)) {
return com_sun_glass_events_KeyEvent_KEY_LOCK_UNKNOWN;
}

Atom atom = None;
switch (keyCode) {
case com_sun_glass_events_KeyEvent_VK_CAPS_LOCK:
lockState = gdk_keymap_get_caps_lock_state(keyMap);
atom = XInternAtom(display, "Caps Lock", True);
break;

case com_sun_glass_events_KeyEvent_VK_NUM_LOCK:
lockState = gdk_keymap_get_num_lock_state(keyMap);
atom = XInternAtom(display, "Num Lock", True);
break;
}

default:
return com_sun_glass_events_KeyEvent_KEY_LOCK_UNKNOWN;
if (atom == None) {
return com_sun_glass_events_KeyEvent_KEY_LOCK_UNKNOWN;
}
return lockState ? com_sun_glass_events_KeyEvent_KEY_LOCK_ON
: com_sun_glass_events_KeyEvent_KEY_LOCK_OFF;
#else /* GLASS_GTK3 */
// Caps Lock detection is not reliable in GTK 2, and Num Lock detection is
// only available in GTK 3.

Bool isLocked = False;
if (XkbGetNamedIndicator(display, atom, NULL, &isLocked, NULL, NULL)) {
if (isLocked) {
return com_sun_glass_events_KeyEvent_KEY_LOCK_ON;
} else {
return com_sun_glass_events_KeyEvent_KEY_LOCK_OFF;
}
}

return com_sun_glass_events_KeyEvent_KEY_LOCK_UNKNOWN;
#endif /* GLASS_GTK3 */
}

} // extern "C"
Expand Up @@ -100,10 +100,8 @@ public void testCanReadCapsLockState() {
// Check that we don't get an exception or a null optional.
Optional<Boolean> capsLockState = Platform.isKeyLocked(KeyCode.CAPS);
assertNotNull(capsLockState);
// A result should always be present on Windows and Mac
if (PlatformUtil.isWindows() || PlatformUtil.isMac()) {
assertTrue(capsLockState.isPresent());
}
// A result should always be present
assertTrue(capsLockState.isPresent());
});
}

Expand All @@ -113,10 +111,11 @@ public void testCanReadNumLockState() {
// Check that we don't get an exception or a null optional.
Optional<Boolean> numLockState = Platform.isKeyLocked(KeyCode.NUM_LOCK);
assertNotNull(numLockState);
// A result should always be present on Windows and never on Mac
if (PlatformUtil.isWindows()) {
// A result should always be present on Windows and Linux
if (PlatformUtil.isWindows() || PlatformUtil.isLinux()) {
assertTrue(numLockState.isPresent());
}
// A result should never be present on Mac
if (PlatformUtil.isMac()) {
assertFalse(numLockState.isPresent());
}
Expand Down

0 comments on commit c4961b1

Please sign in to comment.