Skip to content

Commit

Permalink
Possible fix to repeat events on Linux
Browse files Browse the repository at this point in the history
  • Loading branch information
Earthcomputer committed Jul 4, 2016
1 parent 0ca4dc5 commit f5f8643
Showing 1 changed file with 119 additions and 147 deletions.
266 changes: 119 additions & 147 deletions src/net/earthcomputer/stepfish/util/Keyboard.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,33 +7,31 @@
import java.util.Map;
import java.util.Set;

public class Keyboard extends KeyAdapter
{

public class Keyboard extends KeyAdapter {

private static final Keyboard INSTANCE = new Keyboard();

private final Map<Integer, Set<String>> keyBindingsCodeToName = new HashMap<Integer, Set<String>>();
private final Map<String, Set<Integer>> keyBindingsNameToCode = new HashMap<String, Set<Integer>>();
private final Set<Integer> keysPressed = new HashSet<Integer>();
private final Set<Integer> keysReleased = new HashSet<Integer>();
private final Set<Integer> keysDown = new HashSet<Integer>();
private final Set<Integer> pendingKeysPressed = new HashSet<Integer>();
private final Set<Integer> pendingKeysReleased = new HashSet<Integer>();
private final Map<Integer, Integer> ticksSinceKeyReleased = new HashMap<Integer, Integer>();
private boolean enableRepeatEvents = false;


private static final int TICKS_FOR_KEY_RELEASE = 1;

private final Object SYNC_LOCK = new Object();

private Keyboard()
{

private Keyboard() {
}

public static Keyboard instance()
{

public static Keyboard instance() {
return INSTANCE;
}

public static void registerKeyBindings()
{

public static void registerKeyBindings() {
bindKey(KeyEvent.VK_LEFT, "moveLeft");
bindKey(KeyEvent.VK_A, "moveLeft");
bindKey(KeyEvent.VK_RIGHT, "moveRight");
Expand All @@ -45,217 +43,191 @@ public static void registerKeyBindings()
bindKey(KeyEvent.VK_UP, "scrollUp");
bindKey(KeyEvent.VK_DOWN, "scrollDown");
}

public static void bindKey(int keyCode, String name)
{

public static void bindKey(int keyCode, String name) {
INSTANCE.doBindKey(keyCode, name);
}

private void doBindKey(int keyCode, String name)
{
if(!keyBindingsCodeToName.containsKey(keyCode))
{

private void doBindKey(int keyCode, String name) {
if (!keyBindingsCodeToName.containsKey(keyCode)) {
keyBindingsCodeToName.put(keyCode, new HashSet<String>());
}
keyBindingsCodeToName.get(keyCode).add(name);

if(!keyBindingsNameToCode.containsKey(name))
{

if (!keyBindingsNameToCode.containsKey(name)) {
keyBindingsNameToCode.put(name, new HashSet<Integer>());
}
keyBindingsNameToCode.get(name).add(keyCode);
}

public static boolean isKeyPressed(String keyBinding)
{

public static boolean isKeyPressed(String keyBinding) {
return INSTANCE.doIsKeyPressed(keyBinding);
}

private boolean doIsKeyPressed(String keyBinding)
{

private boolean doIsKeyPressed(String keyBinding) {
Set<Integer> possibleKeys = keyBindingsNameToCode.get(keyBinding);
if(possibleKeys == null){ return false; }
synchronized(SYNC_LOCK)
{
for(Integer keyPressed : keysPressed)
{
if(possibleKeys.contains(keyPressed)){ return true; }
if (possibleKeys == null) {
return false;
}
synchronized (SYNC_LOCK) {
for (Integer keyPressed : keysPressed) {
if (possibleKeys.contains(keyPressed)) {
return true;
}
}
}
return false;
}

public static boolean isKeyReleased(String keyBinding)
{

public static boolean isKeyReleased(String keyBinding) {
return INSTANCE.doIsKeyReleased(keyBinding);
}

private boolean doIsKeyReleased(String keyBinding)
{

private boolean doIsKeyReleased(String keyBinding) {
Set<Integer> possibleKeys = keyBindingsNameToCode.get(keyBinding);
if(possibleKeys == null){ return false; }
synchronized(SYNC_LOCK)
{
for(Integer keyReleased : keysReleased)
{
if(possibleKeys.contains(keyReleased)){ return true; }
if (possibleKeys == null) {
return false;
}
synchronized (SYNC_LOCK) {
for (Integer keyReleased : keysReleased) {
if (possibleKeys.contains(keyReleased)) {
return true;
}
}
}
return false;
}

public static boolean isKeyDown(String keyBinding)
{

public static boolean isKeyDown(String keyBinding) {
return INSTANCE.doIsKeyDown(keyBinding);
}

private boolean doIsKeyDown(String keyBinding)
{

private boolean doIsKeyDown(String keyBinding) {
Set<Integer> possibleKeys = keyBindingsNameToCode.get(keyBinding);
if(possibleKeys == null){ return false; }
synchronized(SYNC_LOCK)
{
for(Integer keyDown : keysDown)
{
if(possibleKeys.contains(keyDown)){ return true; }
if (possibleKeys == null) {
return false;
}
synchronized (SYNC_LOCK) {
for (Integer keyDown : keysDown) {
if (possibleKeys.contains(keyDown)) {
return true;
}
}
}
return false;
}

public static void pressKey(int keyCode)
{

public static void pressKey(int keyCode) {
INSTANCE.doPressKey(keyCode);
}

private void doPressKey(int keyCode)
{
synchronized(SYNC_LOCK)
{
if(enableRepeatEvents || !keysDown.contains(keyCode)) pendingKeysPressed.add(keyCode);

private void doPressKey(int keyCode) {
synchronized (SYNC_LOCK) {
if (enableRepeatEvents || !keysDown.contains(keyCode))
pendingKeysPressed.add(keyCode);
}
}

public static void pressKey(String keyBinding)
{

public static void pressKey(String keyBinding) {
INSTANCE.doPressKey(keyBinding);
}

private void doPressKey(String keyBinding)
{
if(keyBindingsNameToCode.containsKey(keyBinding))
{
for(Integer key : keyBindingsNameToCode.get(keyBinding))
{

private void doPressKey(String keyBinding) {
if (keyBindingsNameToCode.containsKey(keyBinding)) {
for (Integer key : keyBindingsNameToCode.get(keyBinding)) {
doPressKey(key);
}
}
}

public static void releaseKey(int keyCode)
{

public static void releaseKey(int keyCode) {
INSTANCE.doReleaseKey(keyCode);
}

private void doReleaseKey(int keyCode)
{
synchronized(SYNC_LOCK)
{
pendingKeysReleased.add(keyCode);

private void doReleaseKey(int keyCode) {
synchronized (SYNC_LOCK) {
ticksSinceKeyReleased.put(keyCode, 0);
}
}

public static void releaseKey(String keyBinding)
{

public static void releaseKey(String keyBinding) {
INSTANCE.doReleaseKey(keyBinding);
}

private void doReleaseKey(String keyBinding)
{
if(keyBindingsNameToCode.containsKey(keyBinding))
{
for(Integer key : keyBindingsNameToCode.get(keyBinding))
{

private void doReleaseKey(String keyBinding) {
if (keyBindingsNameToCode.containsKey(keyBinding)) {
for (Integer key : keyBindingsNameToCode.get(keyBinding)) {
doReleaseKey(key);
}
}
}

public static void clearKeys()
{

public static void clearKeys() {
INSTANCE.doClearKeys();
}
private void doClearKeys()
{
synchronized(SYNC_LOCK)
{
pendingKeysReleased.addAll(keysDown);

private void doClearKeys() {
synchronized (SYNC_LOCK) {
for (Integer keyDown : keysDown) {
ticksSinceKeyReleased.put(keyDown, TICKS_FOR_KEY_RELEASE);
}
}
}

public static void enableRepeatEvents()
{

public static void enableRepeatEvents() {
INSTANCE.doEnableRepeatEvents();
}

private void doEnableRepeatEvents()
{
synchronized(SYNC_LOCK)
{

private void doEnableRepeatEvents() {
synchronized (SYNC_LOCK) {
enableRepeatEvents = true;
}
}

public static void disableRepeatEvents()
{

public static void disableRepeatEvents() {
INSTANCE.doDisableRepeatEvents();
}

private void doDisableRepeatEvents()
{
synchronized(SYNC_LOCK)
{

private void doDisableRepeatEvents() {
synchronized (SYNC_LOCK) {
enableRepeatEvents = false;
}
}

public static void updateTick()
{

public static void updateTick() {
INSTANCE.doUpdateTick();
}

private void doUpdateTick()
{
synchronized(SYNC_LOCK)
{

private void doUpdateTick() {
synchronized (SYNC_LOCK) {
keysPressed.clear();
for(Integer key : pendingKeysPressed)
{
for (Integer key : pendingKeysPressed) {
keysPressed.add(key);
keysDown.add(key);
}
pendingKeysPressed.clear();

keysReleased.clear();
for(Integer key : pendingKeysReleased)
{
keysReleased.add(key);
keysDown.remove(key);
Map<Integer, Integer> ticksSinceKeyReleasedCopy = new HashMap<Integer, Integer>(ticksSinceKeyReleased);
for (Map.Entry<Integer, Integer> time : ticksSinceKeyReleasedCopy.entrySet()) {
if (enableRepeatEvents || time.getValue() >= TICKS_FOR_KEY_RELEASE) {
keysReleased.add(time.getKey());
keysDown.remove(time.getKey());
ticksSinceKeyReleased.remove(time.getKey());
} else {
ticksSinceKeyReleased.put(time.getKey(), time.getValue() + 1);
}
}
pendingKeysReleased.clear();
}
}

@Override
public void keyPressed(KeyEvent event)
{
public void keyPressed(KeyEvent event) {
doPressKey(event.getKeyCode());
}

@Override
public void keyReleased(KeyEvent event)
{
public void keyReleased(KeyEvent event) {
doReleaseKey(event.getKeyCode());
}
}

0 comments on commit f5f8643

Please sign in to comment.