Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix handling of Ctrl+Alt vs AltGr on Windows #107

Merged
merged 1 commit into from
Jan 11, 2024
Merged
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
4 changes: 2 additions & 2 deletions build.gradle
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
//version: 1704650211
//version: 1704751096
/*
DO NOT CHANGE THIS FILE!
Also, you may replace this file at any time if there is an update available.
Expand Down Expand Up @@ -786,7 +786,7 @@ dependencies {
java17Dependencies("com.github.GTNewHorizons:lwjgl3ify:${lwjgl3ifyVersion}")
}
if (modId != 'hodgepodge') {
java17Dependencies('com.github.GTNewHorizons:Hodgepodge:2.3.35')
java17Dependencies('com.github.GTNewHorizons:Hodgepodge:2.4.4')
}

java17PatchDependencies("com.github.GTNewHorizons:lwjgl3ify:${lwjgl3ifyVersion}:forgePatches") {transitive = false}
Expand Down
12 changes: 12 additions & 0 deletions src/main/java/me/eigenraven/lwjgl3ify/core/Config.java
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,8 @@ public class Config {
public static boolean INPUT_INVERT_WHEEL = false;
public static boolean INPUT_INVERT_X_WHEEL = false;
public static double INPUT_SCROLL_SPEED = 1.0;
public static boolean INPUT_CTRL_ALT_TEXT = false;
public static boolean INPUT_ALTGR_ESCAPE_CODES = false;

public static String X11_CLASS_NAME = "minecraft";
public static String COCOA_FRAME_NAME = "minecraft";
Expand Down Expand Up @@ -195,6 +197,16 @@ public static void reloadConfigObject() {
+0.05f,
+20.0f,
"Scrolling speed multiplier");
INPUT_CTRL_ALT_TEXT = config.getBoolean(
"ctrlAltText",
CATEGORY_INPUT,
INPUT_CTRL_ALT_TEXT,
"Allow text character input when Ctrl+Left Alt are pressed (disables special escape code handling for this combination of keys)");
INPUT_ALTGR_ESCAPE_CODES = config.getBoolean(
"altGrEscapeCodes",
CATEGORY_INPUT,
INPUT_ALTGR_ESCAPE_CODES,
"Allows AltGr use in Ctrl+key special key combinations (disables text character input handling when AltGr is pressed)");

OPENGL_DEBUG_CONTEXT = config.getBoolean(
"debugContext",
Expand Down
67 changes: 64 additions & 3 deletions src/main/java/org/lwjglx/opengl/Display.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,11 @@

import java.awt.Canvas;
import java.awt.event.KeyEvent;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.nio.ByteBuffer;
import java.nio.IntBuffer;
import java.util.HashMap;

import org.lwjgl.glfw.GLFW;
import org.lwjgl.glfw.GLFWCharCallback;
Expand Down Expand Up @@ -65,6 +68,8 @@ public class Display {
private static boolean cancelNextChar = false;
private static Keyboard.KeyEvent ingredientKeyEvent;
private static ByteBuffer[] savedIcons;
private static boolean lastAltIsRightAlt = false;
private static HashMap<Integer, String> glfwKeycodeNames = new HashMap<>();

static {
Sys.initialize(); // init using dummy sys method
Expand All @@ -78,6 +83,20 @@ public class Display {
int monitorRefreshRate = vidmode.refreshRate();

desktopDisplayMode = new DisplayMode(monitorWidth, monitorHeight, monitorBitPerPixel, monitorRefreshRate);

try {
Class<GLFW> glfwClass = GLFW.class;
for (Field f : glfwClass.getFields()) {
if (f.getName()
.startsWith("GLFW_KEY_") && f.getType() == int.class
&& Modifier.isStatic(f.getModifiers())) {
int value = f.getInt(null);
glfwKeycodeNames.put(value, f.getName());
}
}
} catch (ReflectiveOperationException e) {
// ignore
}
}

/**
Expand Down Expand Up @@ -165,25 +184,67 @@ public static void create() {
public void invoke(long window, int key, int scancode, int action, int mods) {
if (Config.DEBUG_PRINT_KEY_EVENTS) {
Lwjgl3ify.LOG.info(
"[DEBUG-KEY] key window:{} key:{} scancode:{} action:{} mods:{} charname:{} naive-char:{}",
"[DEBUG-KEY] key window:{} key:{} ({}) scancode:{} action:{} mods:{} charname:{} naive-char:{}",
window,
key,
glfwKeycodeNames.getOrDefault(key, "unknown"),
scancode,
action,
action == GLFW_PRESS ? "PRESS" : (action == GLFW_RELEASE ? "RELEASE" : "REPEAT"),
mods,
KeyEvent.getKeyText(KeyCodes.lwjglToAwt(KeyCodes.glfwToLwjgl(key))),
(key >= 32 && key < 127) ? ((char) key) : '?');
}
cancelNextChar = false;
if (action == GLFW_PRESS) {
if (key == GLFW_KEY_LEFT_ALT) {
lastAltIsRightAlt = false;
} else if (key == GLFW_KEY_RIGHT_ALT) {
lastAltIsRightAlt = true;
}
}
if (key > GLFW_KEY_SPACE && key <= GLFW_KEY_GRAVE_ACCENT) { // Handle keys have a char. Exclude space to
// avoid extra input when switching IME

/*
* AltGr and LAlt require special consideration.
* On Windows, AltGr and Ctrl+Alt send the same `mods` value of ALT|CTRL in this event.
* This means that to distinguish potential text input from special key combos we have to look at
* the last pressed Alt key side.
* Ctrl combos have to send a (key & 0x1f) ASCII Escape code to work correctly with a lot of older
* mods, but this obviously breaks text input.
* Therefore, we assume text input with AltGr, and control combination input with Left Alt, but both
* can be switched in the config if the player desires.
*/
final boolean isAlt = (GLFW_MOD_ALT & mods) != 0;
final boolean isAltGr = lastAltIsRightAlt;
final boolean ctrlGraphicalMode;
if (isAlt) {
if (isAltGr) {
ctrlGraphicalMode = !Config.INPUT_ALTGR_ESCAPE_CODES;
} else {
// is left alt
ctrlGraphicalMode = Config.INPUT_CTRL_ALT_TEXT;
}
if (ctrlGraphicalMode) {
Keyboard.addGlfwKeyEvent(window, key, scancode, action, mods, (char) (key & 0x1f));
}
} else {
ctrlGraphicalMode = false;
}

if ((GLFW_MOD_SUPER & mods) != 0) {
Keyboard.addGlfwKeyEvent(window, key, scancode, action, mods, (char) key);
if (Platform.get() != Platform.MACOSX) {
// MacOS doesn't send a char event for Cmd+KEY presses, but other platforms do.
cancelNextChar = true;
}
} else if ((GLFW_MOD_CONTROL & mods) != 0) { // Handle ctrl + x/c/v.
} else if ((GLFW_MOD_CONTROL & mods) != 0 && !ctrlGraphicalMode) { // Handle ctrl + x/c/v.
if (Config.DEBUG_PRINT_KEY_EVENTS) {
Lwjgl3ify.LOG.info(
"[DEBUG-KEY] Handling key as escape code, skipping next char input. isAlt:{} isAltGr:{}",
isAlt,
isAltGr);
}
Keyboard.addGlfwKeyEvent(window, key, scancode, action, mods, (char) (key & 0x1f));
cancelNextChar = true; // Cancel char event from ctrl key since its already handled here
} else if (action > 0) { // Delay press and repeat key event to actual char input. There is ALWAYS a
Expand Down