Skip to content
This repository has been archived by the owner on Jul 24, 2024. It is now read-only.
/ jfx11u Public archive

Commit

Permalink
8259680: Need API to query states of CAPS LOCK and NUM LOCK keys
Browse files Browse the repository at this point in the history
Reviewed-by: arapte, pbansal
  • Loading branch information
kevinrushforth committed Feb 1, 2021
1 parent db6941d commit 217a8cb
Show file tree
Hide file tree
Showing 15 changed files with 446 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,13 @@ public class KeyEvent {
@Native public final static int MODIFIER_BUTTON_BACK = 1 << 8;
@Native public final static int MODIFIER_BUTTON_FORWARD = 1 << 9;

/*
* Key lock state
*/
@Native public static final int KEY_LOCK_OFF = 0;
@Native public static final int KEY_LOCK_ON = 1;
@Native public static final int KEY_LOCK_UNKNOWN = -1;

/*
* Key event key codes.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
import java.util.List;
import java.util.Map;
import java.util.LinkedList;
import java.util.Optional;

public abstract class Application {

Expand Down Expand Up @@ -744,4 +745,22 @@ public final boolean supportsSystemMenu() {
public static int getKeyCodeForChar(char c) {
return application._getKeyCodeForChar(c);
}

protected int _isKeyLocked(int keyCode) {
// Overridden in subclasses
return KeyEvent.KEY_LOCK_UNKNOWN;
}

public final Optional<Boolean> isKeyLocked(int keyCode) {
checkEventThread();
int lockState = _isKeyLocked(keyCode);
switch (lockState) {
case KeyEvent.KEY_LOCK_OFF:
return Optional.of(false);
case KeyEvent.KEY_LOCK_ON:
return Optional.of(true);
default:
return Optional.empty();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -478,4 +478,7 @@ protected boolean _supportsInputMethods() {
@Override
protected native int _getKeyCodeForChar(char c);

@Override
protected native int _isKeyLocked(int keyCode);

}
Original file line number Diff line number Diff line change
Expand Up @@ -391,4 +391,7 @@ public String getDataDirectory() {

@Override
protected native int _getKeyCodeForChar(char c);

@Override
protected native int _isKeyLocked(int keyCode);
}
Original file line number Diff line number Diff line change
Expand Up @@ -358,4 +358,7 @@ public String getDataDirectory() {

@Override
protected native int _getKeyCodeForChar(char c);

@Override
protected native int _isKeyLocked(int keyCode);
}
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@
import com.sun.scenario.animation.AbstractPrimaryTimer;
import com.sun.scenario.effect.FilterContext;
import com.sun.scenario.effect.Filterable;
import java.util.Optional;

/**
* A stubbed out Toolkit that provides no useful implementation. This is used
Expand Down Expand Up @@ -371,6 +372,11 @@ public KeyCode getPlatformShortcutKey() {
throw new UnsupportedOperationException("Not supported yet.");
}

@Override
public Optional<Boolean> isKeyLocked(KeyCode keyCode) {
throw new UnsupportedOperationException("Not supported yet.");
}

@Override
public FileChooserResult showFileChooser(TKStage ownerWindow,
String title,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@
import com.sun.scenario.effect.Color4f;
import com.sun.scenario.effect.FilterContext;
import com.sun.scenario.effect.Filterable;
import java.util.Optional;


public abstract class Toolkit {
Expand Down Expand Up @@ -873,6 +874,13 @@ public KeyCode getPlatformShortcutKey() {
return PlatformUtil.isMac() ? KeyCode.META : KeyCode.CONTROL;
}

/**
* Returns the lock state for the given keyCode.
* @param keyCode the keyCode to check
* @return the lock state for the given keyCode.
*/
public abstract Optional<Boolean> isKeyLocked(KeyCode keyCode);

public abstract FileChooserResult showFileChooser(
TKStage ownerWindow,
String title,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@
import com.sun.javafx.logging.PulseLogger;
import static com.sun.javafx.logging.PulseLogger.PULSE_LOGGING_ENABLED;
import com.sun.javafx.scene.input.DragboardHelper;
import java.util.Optional;

public final class QuantumToolkit extends Toolkit {

Expand Down Expand Up @@ -1236,6 +1237,24 @@ public boolean isMSAASupported() {
return GraphicsPipeline.getPipeline().isMSAASupported();
}

// Returns the glass keycode for the given JavaFX KeyCode.
// This method only converts lock state KeyCode values
private int toGlassKeyCode(KeyCode keyCode) {
switch (keyCode) {
case CAPS:
return com.sun.glass.events.KeyEvent.VK_CAPS_LOCK;
case NUM_LOCK:
return com.sun.glass.events.KeyEvent.VK_NUM_LOCK;
default:
return com.sun.glass.events.KeyEvent.VK_UNDEFINED;
}
}

@Override
public Optional<Boolean> isKeyLocked(KeyCode keyCode) {
return Application.GetApplication().isKeyLocked(toGlassKeyCode(keyCode));
}

static TransferMode clipboardActionToTransferMode(final int action) {
switch (action) {
case Clipboard.ACTION_NONE:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,12 @@

package javafx.application;

import com.sun.javafx.application.PlatformImpl;
import com.sun.javafx.tk.Toolkit;
import java.util.Optional;
import javafx.beans.property.ReadOnlyBooleanProperty;
import javafx.beans.property.ReadOnlyBooleanWrapper;
import com.sun.javafx.application.PlatformImpl;
import javafx.scene.input.KeyCode;

/**
* Application platform support class.
Expand Down Expand Up @@ -329,6 +331,43 @@ public static void exitNestedEventLoop(Object key, Object rval) {
Toolkit.getToolkit().exitNestedEventLoop(key, rval);
}

/**
* Returns a flag indicating whether the key corresponding to {@code keyCode}
* is in the locked (or "on") state.
* {@code keyCode} must be one of: {@link KeyCode#CAPS} or
* {@link KeyCode#NUM_LOCK}.
* If the underlying system is not able to determine the state of the
* specified {@code keyCode}, an empty {@code Optional} is returned.
* If the keyboard attached to the system doesn't have the specified key,
* an {@code Optional} containing {@code false} is returned.
* This method must be called on the JavaFX Application thread.
*
* @param keyCode the {@code KeyCode} of the lock state to query
*
* @return the lock state of the key corresponding to {@code keyCode},
* or an empty {@code Optional} if the system cannot determine its state
*
* @throws IllegalArgumentException if {@code keyCode} is not one of the
* valid {@code KeyCode} values
*
* @throws IllegalStateException if this method is called on a thread
* other than the JavaFX Application Thread
*
* @since 17
*/
public static Optional<Boolean> isKeyLocked(KeyCode keyCode) {
Toolkit.getToolkit().checkFxUserThread();

switch (keyCode) {
case CAPS:
case NUM_LOCK:
break;
default:
throw new IllegalArgumentException("Invalid KeyCode");
}
return Toolkit.getToolkit().isKeyLocked(keyCode);
}

/**
* Checks whether a nested event loop is running, returning true to indicate
* that one is, and false if there are no nested event loops currently
Expand Down
60 changes: 60 additions & 0 deletions modules/javafx.graphics/src/main/native-glass/gtk/glass_key.cpp
Original file line number Diff line number Diff line change
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,4 +346,63 @@ 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
* Signature: (I)I
*/
JNIEXPORT jint JNICALL Java_com_sun_glass_ui_gtk_GtkApplication__1isKeyLocked
(JNIEnv * env, jobject obj, jint keyCode)
{
Display* display = gdk_x11_display_get_xdisplay(gdk_display_get_default());
if (!isXkbAvailable(display)) {
return com_sun_glass_events_KeyEvent_KEY_LOCK_UNKNOWN;
}

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

case com_sun_glass_events_KeyEvent_VK_NUM_LOCK:
keyCodeAtom = XInternAtom(display, "Num Lock", True);
break;
}

if (keyCodeAtom == None) {
return com_sun_glass_events_KeyEvent_KEY_LOCK_UNKNOWN;
}

Bool isLocked = False;
if (XkbGetNamedIndicator(display, keyCodeAtom, 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;
}

} // extern "C"
22 changes: 22 additions & 0 deletions modules/javafx.graphics/src/main/native-glass/mac/GlassKey.m
Original file line number Diff line number Diff line change
Expand Up @@ -396,3 +396,25 @@ BOOL GetMacKey(jint javaKeyCode, unsigned short *outMacKeyCode)
return [GlassApplication getKeyCodeForChar:c];
}

/*
* Class: com_sun_glass_ui_mac_MacApplication
* Method: _isKeyLocked
* Signature: (I)I
*/
JNIEXPORT jint JNICALL Java_com_sun_glass_ui_mac_MacApplication__1isKeyLocked
(JNIEnv * env, jobject obj, jint keyCode)
{
NSUInteger mask = 0;
switch (keyCode) {
case com_sun_glass_events_KeyEvent_VK_CAPS_LOCK:
mask = NSEventModifierFlagCapsLock;
break;

// Caps lock is the only locking key supported on macOS
default:
return com_sun_glass_events_KeyEvent_KEY_LOCK_UNKNOWN;
}
NSUInteger modifierFlags = [NSEvent modifierFlags];
return (modifierFlags & mask) ? com_sun_glass_events_KeyEvent_KEY_LOCK_ON
: com_sun_glass_events_KeyEvent_KEY_LOCK_OFF;
}
22 changes: 22 additions & 0 deletions modules/javafx.graphics/src/main/native-glass/win/KeyTable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -247,5 +247,27 @@ JNIEXPORT jint JNICALL Java_com_sun_glass_ui_win_WinApplication__1getKeyCodeForC
return WindowsKeyToJavaKey(vkey);
}

/*
* Class: com_sun_glass_ui_win_WinApplication
* Method: _isKeyLocked
* Signature: (I)I
*/
JNIEXPORT jint JNICALL Java_com_sun_glass_ui_win_WinApplication__1isKeyLocked
(JNIEnv * env, jobject obj, jint keyCode)
{
SHORT keyState = 0;
switch (keyCode) {
case com_sun_glass_events_KeyEvent_VK_CAPS_LOCK:
keyState = ::GetKeyState(VK_CAPITAL);
break;

case com_sun_glass_events_KeyEvent_VK_NUM_LOCK:
keyState = ::GetKeyState(VK_NUMLOCK);
break;

default:
return com_sun_glass_events_KeyEvent_KEY_LOCK_UNKNOWN;
}
return (keyState & 0x1) ? com_sun_glass_events_KeyEvent_KEY_LOCK_ON
: com_sun_glass_events_KeyEvent_KEY_LOCK_OFF;
}
Original file line number Diff line number Diff line change
Expand Up @@ -750,6 +750,11 @@ public KeyCode getPlatformShortcutKey() {
return platformShortcutKey;
}

@Override
public Optional<Boolean> isKeyLocked(KeyCode keyCode) {
return Optional.empty();
}

private DndDelegate dndDelegate;
public void setDndDelegate(DndDelegate dndDelegate) {
this.dndDelegate = dndDelegate;
Expand Down
Loading

0 comments on commit 217a8cb

Please sign in to comment.