Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -751,6 +751,32 @@ public static int getKeyCodeForChar(char c) {
return application._getKeyCodeForChar(c);
}

/**
* The default implementation bridges to the existing getKeyCodeForChar call. Platform
* instances are expected to override this call.
*/
protected boolean _getKeyCanGenerateCharacter(int hardwareCode, int vkCode, char c) {
if (vkCode != com.sun.glass.events.KeyEvent.VK_UNDEFINED) {
return getKeyCodeForChar(c) == vkCode;
}
return false;
}

/**
* Returns true if the key is capable of producing the given Unicode
* character. The call will be provided enough information to identify the
* key, either a vkCode that is not VK_UNDEFINED or a hardwareCode that is
* non-negative or both.
*
* @param hardwareCode the platform-specific key identifier
* @param vkCode the JavaFX key code
* @param c the character
* @return true if the key can generate the character
*/
public final boolean getKeyCanGenerateCharacter(int hardwareCode, int vkCode, char c) {
return _getKeyCanGenerateCharacter(hardwareCode, vkCode, c);
}

protected int _isKeyLocked(int keyCode) {
// Overridden in subclasses
return KeyEvent.KEY_LOCK_UNKNOWN;
Expand Down
22 changes: 16 additions & 6 deletions modules/javafx.graphics/src/main/java/com/sun/glass/ui/View.java
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,11 @@ public abstract class View {
public static class EventHandler {
public void handleViewEvent(View view, long time, int type) {
}
public void handleKeyEvent(View view, long time, int action,
int keyCode, char[] keyChars, int modifiers) {
public boolean handleKeyEvent(View view, long time, int action,
int keyCode, char[] keyChars, int modifiers, int hardwareCode)
{
/* Event was not consumed */
return false;
}
public void handleMenuEvent(View view, int x, int y, int xAbs,
int yAbs, boolean isKeyboardTrigger) {
Expand Down Expand Up @@ -536,11 +539,13 @@ private void handleViewEvent(long time, int type) {
}
}

private void handleKeyEvent(long time, int action,
int keyCode, char[] keyChars, int modifiers) {
private boolean handleKeyEvent(long time, int action,
int keyCode, char[] keyChars, int modifiers, int hardwareCode) {
if (this.eventHandler != null) {
this.eventHandler.handleKeyEvent(this, time, action, keyCode, keyChars, modifiers);
return this.eventHandler.handleKeyEvent(this, time, action, keyCode,
keyChars, modifiers, hardwareCode);
}
return false;
}

private void handleMouseEvent(long time, int type, int button, int x, int y,
Expand Down Expand Up @@ -963,7 +968,12 @@ protected void notifyScroll(int x, int y, int xAbs, int yAbs,
}

protected void notifyKey(int type, int keyCode, char[] keyChars, int modifiers) {
handleKeyEvent(System.nanoTime(), type, keyCode, keyChars, modifiers);
handleKeyEvent(System.nanoTime(), type, keyCode, keyChars, modifiers, -1);
}

// Returns true iff event was consumed
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are some places where it's written "iff", I'm not sure if it's intentional or a typo.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

iff is an abbreviation for "if and only if". It's a bit formal but I noticed it was used in other internal API comments and JavaDocs. I think I removed all of these when I resubmitted this code as part of #1126.

protected boolean notifyKeyEx(int type, int keyCode, char[] keyChars, int modifiers, int hardwareCode) {
return handleKeyEvent(System.nanoTime(), type, keyCode, keyChars, modifiers, hardwareCode);
}

protected void notifyInputMethod(String text, int[] clauseBoundary,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -462,7 +462,14 @@ protected boolean _supportsInputMethods() {
}

@Override
protected native int _getKeyCodeForChar(char c);
protected int _getKeyCodeForChar(char c) {
// Linux has transitioned to getKeyCanGenerateCharacter so this
// should never be called.
return 0;
}

@Override
protected native boolean _getKeyCanGenerateCharacter(int hardwareCode, int vkCode, char c);

@Override
protected native int _isKeyLocked(int keyCode);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,8 @@ public static void enableInputMethodEvents(Scene scene, boolean enable) {
sceneAccessor.enableInputMethodEvents(scene, enable);
}

public static void processKeyEvent(Scene scene, KeyEvent e) {
sceneAccessor.processKeyEvent(scene, e);
public static boolean processKeyEvent(Scene scene, KeyEvent e) {
return sceneAccessor.processKeyEvent(scene, e);
}

public static void processMouseEvent(Scene scene, MouseEvent e) {
Expand Down Expand Up @@ -118,7 +118,7 @@ public static SceneAccessor getSceneAccessor() {
public interface SceneAccessor {
void enableInputMethodEvents(Scene scene, boolean enable);

void processKeyEvent(Scene scene, KeyEvent e);
boolean processKeyEvent(Scene scene, KeyEvent e);

void processMouseEvent(Scene scene, MouseEvent e);

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/*
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/

package com.sun.javafx.scene.input;

import com.sun.javafx.util.Utils;
import javafx.scene.input.KeyEvent;

/**
* Used to access internal methods of KeyEvent.
*/
public class KeyEventHelper {

private static KeyEventAccessor keyEventAccessor;

static {
Utils.forceInit(KeyEvent.class);
}

private KeyEventHelper() {
}

public static void setHardwareCode(KeyEvent keyEvent, int hardwareCode) {
keyEventAccessor.setHardwareCode(keyEvent, hardwareCode);
}

public static int getHardwareCode(KeyEvent keyEvent) {
return keyEventAccessor.getHardwareCode(keyEvent);
}

public static void setKeyEventAccessor(final KeyEventAccessor newAccessor) {
if (keyEventAccessor != null) {
throw new IllegalStateException();
}

keyEventAccessor = newAccessor;
}

public interface KeyEventAccessor {
void setHardwareCode(KeyEvent keyEvent, int hardwareCode);
int getHardwareCode(KeyEvent keyEvent);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,11 @@ public void mouseEvent(EventType<MouseEvent> type, double x, double y, double sc

/**
* Pass a key event to the scene to handle
*
* @param keyEvent The key event
* @return true iff the event was consumed
*/
public void keyEvent(KeyEvent keyEvent);
public boolean keyEvent(KeyEvent keyEvent);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could we update javadoc to explain when it returns true?


/**
* Pass an input method event to the scene to handle
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -703,6 +703,15 @@ protected static final double clampStopOffset(double offset) {
float dashOffset);

public abstract int getKeyCodeForChar(String character);
/**
* The default implementation bridges into the existing getKeyCodeForChar call.
*/
public boolean getKeyCanGenerateCharacter(KeyEvent event, String character) {
if (event.getCode() != KeyCode.UNDEFINED) {
return getKeyCodeForChar(character) == event.getCode().getCode();
}
return false;
}
public abstract Dimension2D getBestCursorSize(int preferredWidth, int preferredHeight);
public abstract int getMaximumCursorColors();
public abstract PathElement[] convertShapeToFXPath(Object shape);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
import com.sun.javafx.collections.TrackableObservableList;
import com.sun.javafx.logging.PulseLogger;
import static com.sun.javafx.logging.PulseLogger.PULSE_LOGGING_ENABLED;
import com.sun.javafx.scene.input.KeyEventHelper;
import com.sun.javafx.scene.input.KeyCodeMap;

import javafx.collections.ListChangeListener;
Expand Down Expand Up @@ -147,22 +148,25 @@ private static EventType<javafx.scene.input.KeyEvent> keyEventType(int glassType
}

private final KeyEventNotification keyNotification = new KeyEventNotification();
private class KeyEventNotification implements PrivilegedAction<Void> {
private class KeyEventNotification implements PrivilegedAction<Boolean> {
View view;
long time;
int type;
int key;
char[] chars;
int modifiers;
int hardwareCode;

private KeyCode lastKeyCode;

@Override
public Void run() {
public Boolean run() {
if (PULSE_LOGGING_ENABLED) {
PulseLogger.newInput(keyEventType(type).toString());
}
WindowStage stage = scene.getWindowStage();
Boolean consumed = Boolean.FALSE;

try {
boolean shiftDown = (modifiers & KeyEvent.MODIFIER_SHIFT) != 0;
boolean controlDown = (modifiers & KeyEvent.MODIFIER_CONTROL) != 0;
Expand All @@ -177,6 +181,7 @@ public Void run() {
str, text,
KeyCodeMap.valueOf(key) ,
shiftDown, controlDown, altDown, metaDown);
KeyEventHelper.setHardwareCode(keyEvent, hardwareCode);

KeyCode keyCode = KeyCodeMap.valueOf(key);
switch (type) {
Expand Down Expand Up @@ -215,7 +220,8 @@ public Void run() {
}
}
if (scene.sceneListener != null) {
scene.sceneListener.keyEvent(keyEvent);
if (scene.sceneListener.keyEvent(keyEvent))
consumed = Boolean.TRUE;
}
break;
default:
Expand All @@ -231,22 +237,23 @@ public Void run() {
PulseLogger.newInput(null);
}
}
return null;
return consumed;
}
}

@SuppressWarnings("removal")
@Override public void handleKeyEvent(View view, long time, int type, int key,
char[] chars, int modifiers)
@Override public boolean handleKeyEvent(View view, long time, int type, int key,
char[] chars, int modifiers, int hardwareCode)
{
keyNotification.view = view;
keyNotification.time = time;
keyNotification.type = type;
keyNotification.key = key;
keyNotification.chars = chars;
keyNotification.modifiers = modifiers;
keyNotification.hardwareCode = hardwareCode;

QuantumToolkit.runWithoutRenderLock(() -> {
return QuantumToolkit.runWithoutRenderLock(() -> {
return AccessController.doPrivileged(keyNotification, scene.getAccessControlContext());
});
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@
import com.sun.javafx.perf.PerformanceTracker;
import com.sun.javafx.runtime.async.AbstractRemoteResource;
import com.sun.javafx.runtime.async.AsyncOperationListener;
import com.sun.javafx.scene.input.KeyEventHelper;
import com.sun.javafx.scene.text.TextLayoutFactory;
import com.sun.javafx.sg.prism.NGNode;
import com.sun.javafx.tk.CompletionListener;
Expand Down Expand Up @@ -1086,6 +1087,20 @@ public Shape createStrokedShape(Shape shape,
: com.sun.glass.events.KeyEvent.VK_UNDEFINED;
}

// The Quantum version of this call knows that we may have the hardware key code
// available.
@Override public boolean getKeyCanGenerateCharacter(KeyEvent keyEvent, String character) {
int hardwareCode = KeyEventHelper.getHardwareCode(keyEvent);
if (keyEvent.getCode() != KeyCode.UNDEFINED || hardwareCode != -1) {
if (character.length() == 1)
return Application.GetApplication().getKeyCanGenerateCharacter(
hardwareCode,
keyEvent.getCode().getCode(),
character.charAt(0));
}
return false;
}

@Override public PathElement[] convertShapeToFXPath(Object shape) {
if (shape == null) {
return new PathElement[0];
Expand Down
16 changes: 10 additions & 6 deletions modules/javafx.graphics/src/main/java/javafx/scene/Scene.java
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
import com.sun.javafx.css.StyleManager;
import com.sun.javafx.cursor.CursorFrame;
import com.sun.javafx.event.EventQueue;
import com.sun.javafx.event.EventUtil;
import com.sun.javafx.geom.PickRay;
import com.sun.javafx.geom.Vec3d;
import com.sun.javafx.geom.transform.BaseTransform;
Expand Down Expand Up @@ -397,8 +398,8 @@ public void enableInputMethodEvents(Scene scene, boolean enable) {
}

@Override
public void processKeyEvent(Scene scene, KeyEvent e) {
scene.processKeyEvent(e);
public boolean processKeyEvent(Scene scene, KeyEvent e) {
return scene.processKeyEvent(e);
}

@Override
Expand Down Expand Up @@ -2178,7 +2179,10 @@ private void focusIneligible(Node node) {
traverse(node, Direction.NEXT, TraversalMethod.DEFAULT);
}

void processKeyEvent(KeyEvent e) {
/**
* @return true iff the event was consumed
*/
boolean processKeyEvent(KeyEvent e) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

would be nice to have a one-line javadoc explaining when it returns true

if (dndGesture != null) {
if (!dndGesture.processKey(e)) {
dndGesture = null;
Expand All @@ -2191,7 +2195,7 @@ void processKeyEvent(KeyEvent e) {

// send the key event to the current focus owner or to scene if
// the focus owner is not set
Event.fireEvent(eventTarget, e);
return EventUtil.fireEvent(eventTarget, e) == null;
}

void requestFocus(Node node, boolean focusVisible) {
Expand Down Expand Up @@ -2710,9 +2714,9 @@ public void mouseEvent(EventType<MouseEvent> type, double x, double y, double sc


@Override
public void keyEvent(KeyEvent keyEvent)
public boolean keyEvent(KeyEvent keyEvent)
{
processKeyEvent(keyEvent);
return processKeyEvent(keyEvent);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,12 +109,8 @@ public KeyCharacterCombination(final @NamedArg("character") String character,
*/
@Override
public boolean match(final KeyEvent event) {
if (event.getCode() == KeyCode.UNDEFINED) {
return false;
}
return (event.getCode().getCode()
== Toolkit.getToolkit().getKeyCodeForChar(getCharacter()))
&& super.match(event);
return (super.match(event) &&
Toolkit.getToolkit().getKeyCanGenerateCharacter(event, getCharacter()));
}

/**
Expand Down
Loading