diff --git a/src/client/java/uk/minersonline/RealisticComputers/RealisticComputersClient.java b/src/client/java/uk/minersonline/RealisticComputers/RealisticComputersClient.java index 1ebacd0..312760a 100644 --- a/src/client/java/uk/minersonline/RealisticComputers/RealisticComputersClient.java +++ b/src/client/java/uk/minersonline/RealisticComputers/RealisticComputersClient.java @@ -14,7 +14,7 @@ public class RealisticComputersClient implements ClientModInitializer { @Override public void onInitializeClient() { - ClientPlayNetworking.registerGlobalReceiver(ModNetworking.OPEN_VNC_SCREEN, (client, handler, buf, responseSender) -> { + ClientPlayNetworking.registerGlobalReceiver(ModNetworking.VNC_SCREEN_OPEN, (client, handler, buf, responseSender) -> { BlockPos terminalPosition = buf.readBlockPos(); client.execute(() -> { diff --git a/src/client/java/uk/minersonline/RealisticComputers/screen/VNCScreen.java b/src/client/java/uk/minersonline/RealisticComputers/screen/VNCScreen.java index d7cbe91..f3789d0 100644 --- a/src/client/java/uk/minersonline/RealisticComputers/screen/VNCScreen.java +++ b/src/client/java/uk/minersonline/RealisticComputers/screen/VNCScreen.java @@ -25,7 +25,7 @@ public void close() { this.client.setScreen(this.parent); PacketByteBuf buf = PacketByteBufs.create(); buf.writeBlockPos(this.terminalPosition); - ClientPlayNetworking.send(ModNetworking.CLOSE_VNC_SCREEN, buf); + ClientPlayNetworking.send(ModNetworking.VNC_SCREEN_CLOSE, buf); } } diff --git a/src/client/java/uk/minersonline/RealisticComputers/screen/VNCScreenLayout.java b/src/client/java/uk/minersonline/RealisticComputers/screen/VNCScreenLayout.java index dc3128a..8845a6e 100644 --- a/src/client/java/uk/minersonline/RealisticComputers/screen/VNCScreenLayout.java +++ b/src/client/java/uk/minersonline/RealisticComputers/screen/VNCScreenLayout.java @@ -15,6 +15,7 @@ public VNCScreenLayout() { screenWidget = new VNCScreenWidget(); root.add(screenWidget, 0, 0, 19, 12); + requestFocus(screenWidget); root.validate(this); } diff --git a/src/client/java/uk/minersonline/RealisticComputers/screen/VNCScreenWidget.java b/src/client/java/uk/minersonline/RealisticComputers/screen/VNCScreenWidget.java index 61340a2..0ad19d8 100644 --- a/src/client/java/uk/minersonline/RealisticComputers/screen/VNCScreenWidget.java +++ b/src/client/java/uk/minersonline/RealisticComputers/screen/VNCScreenWidget.java @@ -2,10 +2,16 @@ import io.github.cottonmc.cotton.gui.client.ScreenDrawing; import io.github.cottonmc.cotton.gui.widget.WWidget; +import io.github.cottonmc.cotton.gui.widget.data.InputResult; import io.github.cottonmc.cotton.gui.widget.data.Texture; +import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking; +import net.fabricmc.fabric.api.networking.v1.PacketByteBufs; import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.DrawContext; +import net.minecraft.network.PacketByteBuf; import net.minecraft.util.math.ColorHelper; +import uk.minersonline.RealisticComputers.ModNetworking; + public class VNCScreenWidget extends WWidget { private Texture image = null; @@ -25,10 +31,81 @@ public boolean canResize() { return true; } + @Override + public boolean canFocus() { + return true; + } + public void setImage(Texture image) { if (this.image != null) { MinecraftClient.getInstance().getTextureManager().destroyTexture(this.image.image()); } this.image = image; } + + @Override + public InputResult onKeyPressed(int ch, int key, int modifiers) { + PacketByteBuf buf = PacketByteBufs.create(); + buf.writeInt(ch); + buf.writeInt(modifiers); + buf.writeBoolean(true); + ClientPlayNetworking.send(ModNetworking.VNC_KEY, buf); + return super.onKeyPressed(ch, key, modifiers); + } + + @Override + public InputResult onKeyReleased(int ch, int key, int modifiers) { + PacketByteBuf buf = PacketByteBufs.create(); + buf.writeInt(ch); + buf.writeInt(modifiers); + buf.writeBoolean(false); + ClientPlayNetworking.send(ModNetworking.VNC_KEY, buf); + return super.onKeyReleased(ch, key, modifiers); + } + + @Override + public InputResult onMouseMove(int x, int y) { + requestFocus(); + PacketByteBuf buf = PacketByteBufs.create(); + buf.writeInt(x); + buf.writeInt(y); + ClientPlayNetworking.send(ModNetworking.VNC_MOUSE_MOVE, buf); + return super.onMouseMove(x, y); + } + + @Override + public InputResult onMouseUp(int x, int y, int button) { + requestFocus(); + PacketByteBuf buf = PacketByteBufs.create(); + buf.writeInt(x); + buf.writeInt(y); + if (button == 0) { + buf.writeInt(1); + } else if (button == 1) { + buf.writeInt(3); + } else { + buf.writeInt(2); + } + buf.writeBoolean(false); + ClientPlayNetworking.send(ModNetworking.VNC_MOUSE_MOVE, buf); + return super.onMouseUp(x, y, button); + } + + @Override + public InputResult onMouseDown(int x, int y, int button) { + requestFocus(); + PacketByteBuf buf = PacketByteBufs.create(); + buf.writeInt(x); + buf.writeInt(y); + if (button == 0) { + buf.writeInt(1); + } else if (button == 1) { + buf.writeInt(3); + } else { + buf.writeInt(2); + } + buf.writeBoolean(true); + ClientPlayNetworking.send(ModNetworking.VNC_MOUSE_MOVE, buf); + return super.onMouseDown(x, y, button); + } } diff --git a/src/main/java/uk/minersonline/RealisticComputers/ModNetworking.java b/src/main/java/uk/minersonline/RealisticComputers/ModNetworking.java index 00da5a2..526d43c 100644 --- a/src/main/java/uk/minersonline/RealisticComputers/ModNetworking.java +++ b/src/main/java/uk/minersonline/RealisticComputers/ModNetworking.java @@ -4,7 +4,11 @@ import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.util.Identifier; import net.minecraft.util.math.BlockPos; +import org.lwjgl.glfw.GLFW; +import uk.minersonline.RealisticComputers.utils.KeyUtils; +import java.awt.*; +import java.awt.event.KeyEvent; import java.util.HashMap; import java.util.Map; @@ -13,12 +17,15 @@ public class ModNetworking { public static Map openScreens = new HashMap<>(); public static Map openSessions = new HashMap<>(); - public static final Identifier OPEN_VNC_SCREEN = new Identifier(MOD_ID, "vnc_screen_open"); - public static final Identifier CLOSE_VNC_SCREEN = new Identifier(MOD_ID, "vnc_screen_close"); + public static final Identifier VNC_SCREEN_OPEN = new Identifier(MOD_ID, "vnc_screen_open"); + public static final Identifier VNC_SCREEN_CLOSE = new Identifier(MOD_ID, "vnc_screen_close"); public static final Identifier VNC_SCREEN_DATA = new Identifier(MOD_ID, "vnc_screen_data"); + public static final Identifier VNC_MOUSE_MOVE = new Identifier(MOD_ID, "vnc_mouse_move"); + public static final Identifier VNC_MOUSE_CLICK = new Identifier(MOD_ID, "vnc_mouse_click"); + public static final Identifier VNC_KEY = new Identifier(MOD_ID, "vnc_key"); public static void serverInit() { - ServerPlayNetworking.registerGlobalReceiver(CLOSE_VNC_SCREEN, (server, player, handler, buf, responseSender) -> { + ServerPlayNetworking.registerGlobalReceiver(VNC_SCREEN_CLOSE, (server, player, handler, buf, responseSender) -> { VNCSession session = openSessions.get(player); session.end(); try { @@ -32,5 +39,63 @@ public static void serverInit() { openScreens.put(player, null); RealisticComputers.LOGGER.info(player.getDisplayName().getString() + " has closed the vnc terminal at " + terminalPosition); }); + + ServerPlayNetworking.registerGlobalReceiver(VNC_MOUSE_MOVE, (server, player, handler, buf, responseSender) -> { + VNCSession session = openSessions.get(player); + if (session != null) { + int x = buf.readInt(); + int y = buf.readInt(); + session.sendMousePos(x, y); + } + }); + + ServerPlayNetworking.registerGlobalReceiver(VNC_MOUSE_CLICK, (server, player, handler, buf, responseSender) -> { + VNCSession session = openSessions.get(player); + if (session != null) { + int x = buf.readInt(); + int y = buf.readInt(); + int btn = buf.readInt(); + boolean pressed = buf.readBoolean(); + session.sendMouseClick(x, y, btn, pressed); + } + }); + + ServerPlayNetworking.registerGlobalReceiver(VNC_KEY, (server, player, handler, buf, responseSender) -> { + VNCSession session = openSessions.get(player); + if (session != null) { + int key = buf.readInt(); + int glfwModifiers = buf.readInt(); + boolean pressed = buf.readBoolean(); + + KeyEvent keyPressEvent; + boolean isChar = KeyUtils.isCharacterKey(key); + int modifiers = KeyUtils.getModifiers(glfwModifiers); + char type = KeyEvent.CHAR_UNDEFINED; + if (isChar) { + type = KeyUtils.getCharacterFromKeyCode(key, (glfwModifiers & GLFW.GLFW_MOD_SHIFT) != 0); + } + Component source = new Component() {}; + if (pressed) { + keyPressEvent = new KeyEvent( + source, + KeyEvent.KEY_PRESSED, + System.currentTimeMillis(), + modifiers, + KeyUtils.convertKey(key), + type + ); + } else { + keyPressEvent = new KeyEvent( + source, + KeyEvent.KEY_RELEASED, + System.currentTimeMillis(), + modifiers, + KeyUtils.convertKey(key), + type + ); + } + session.handleKey(keyPressEvent); + } + }); } } diff --git a/src/main/java/uk/minersonline/RealisticComputers/VNCSession.java b/src/main/java/uk/minersonline/RealisticComputers/VNCSession.java index a403cb7..c05490b 100644 --- a/src/main/java/uk/minersonline/RealisticComputers/VNCSession.java +++ b/src/main/java/uk/minersonline/RealisticComputers/VNCSession.java @@ -10,6 +10,7 @@ import uk.minersonline.RealisticComputers.utils.ImageUtils; import java.awt.*; +import java.awt.event.KeyEvent; import java.io.IOException; public class VNCSession extends Thread { @@ -59,4 +60,17 @@ public void end() { client.stop(); running = false; } + + public void sendMousePos(int x, int y) { + client.moveMouse(x, y); + } + + public void sendMouseClick(int x, int y, int btn, boolean pressed) { + client.moveMouse(x, y); + client.updateMouseButton(btn, pressed); + } + + public void handleKey(KeyEvent event) { + client.handleKeyEvent(event); + } } diff --git a/src/main/java/uk/minersonline/RealisticComputers/block/VNCTerminal.java b/src/main/java/uk/minersonline/RealisticComputers/block/VNCTerminal.java index 58e4ae9..3a32c96 100644 --- a/src/main/java/uk/minersonline/RealisticComputers/block/VNCTerminal.java +++ b/src/main/java/uk/minersonline/RealisticComputers/block/VNCTerminal.java @@ -67,7 +67,7 @@ public ActionResult onUse(BlockState state, World world, BlockPos pos, PlayerEnt if (!world.isClient()) { PacketByteBuf buf = PacketByteBufs.create(); buf.writeBlockPos(pos); - ServerPlayNetworking.send((ServerPlayerEntity) player, ModNetworking.OPEN_VNC_SCREEN, buf); + ServerPlayNetworking.send((ServerPlayerEntity) player, ModNetworking.VNC_SCREEN_OPEN, buf); ModNetworking.openScreens.put((ServerPlayerEntity) player, pos); VNCSession session = new VNCSession((ServerPlayerEntity) player); session.start(); diff --git a/src/main/java/uk/minersonline/RealisticComputers/utils/KeyUtils.java b/src/main/java/uk/minersonline/RealisticComputers/utils/KeyUtils.java new file mode 100644 index 0000000..e8bb546 --- /dev/null +++ b/src/main/java/uk/minersonline/RealisticComputers/utils/KeyUtils.java @@ -0,0 +1,225 @@ +package uk.minersonline.RealisticComputers.utils; + +import org.lwjgl.glfw.GLFW; +import java.awt.event.KeyEvent; + +public class KeyUtils { + public static int convertKey(int glfwKeyCode) { + return switch (glfwKeyCode) { + case GLFW.GLFW_KEY_UNKNOWN -> KeyEvent.VK_UNDEFINED; + case GLFW.GLFW_KEY_SPACE -> KeyEvent.VK_SPACE; + case GLFW.GLFW_KEY_APOSTROPHE -> KeyEvent.VK_QUOTE; + case GLFW.GLFW_KEY_COMMA -> KeyEvent.VK_COMMA; + case GLFW.GLFW_KEY_MINUS -> KeyEvent.VK_MINUS; + case GLFW.GLFW_KEY_PERIOD -> KeyEvent.VK_PERIOD; + case GLFW.GLFW_KEY_SLASH -> KeyEvent.VK_SLASH; + case GLFW.GLFW_KEY_0 -> KeyEvent.VK_0; + case GLFW.GLFW_KEY_1 -> KeyEvent.VK_1; + case GLFW.GLFW_KEY_2 -> KeyEvent.VK_2; + case GLFW.GLFW_KEY_3 -> KeyEvent.VK_3; + case GLFW.GLFW_KEY_4 -> KeyEvent.VK_4; + case GLFW.GLFW_KEY_5 -> KeyEvent.VK_5; + case GLFW.GLFW_KEY_6 -> KeyEvent.VK_6; + case GLFW.GLFW_KEY_7 -> KeyEvent.VK_7; + case GLFW.GLFW_KEY_8 -> KeyEvent.VK_8; + case GLFW.GLFW_KEY_9 -> KeyEvent.VK_9; + case GLFW.GLFW_KEY_SEMICOLON -> KeyEvent.VK_SEMICOLON; + case GLFW.GLFW_KEY_EQUAL, GLFW.GLFW_KEY_KP_EQUAL -> KeyEvent.VK_EQUALS; + case GLFW.GLFW_KEY_A -> KeyEvent.VK_A; + case GLFW.GLFW_KEY_B -> KeyEvent.VK_B; + case GLFW.GLFW_KEY_C -> KeyEvent.VK_C; + case GLFW.GLFW_KEY_D -> KeyEvent.VK_D; + case GLFW.GLFW_KEY_E -> KeyEvent.VK_E; + case GLFW.GLFW_KEY_F -> KeyEvent.VK_F; + case GLFW.GLFW_KEY_G -> KeyEvent.VK_G; + case GLFW.GLFW_KEY_H -> KeyEvent.VK_H; + case GLFW.GLFW_KEY_I -> KeyEvent.VK_I; + case GLFW.GLFW_KEY_J -> KeyEvent.VK_J; + case GLFW.GLFW_KEY_K -> KeyEvent.VK_K; + case GLFW.GLFW_KEY_L -> KeyEvent.VK_L; + case GLFW.GLFW_KEY_M -> KeyEvent.VK_M; + case GLFW.GLFW_KEY_N -> KeyEvent.VK_N; + case GLFW.GLFW_KEY_O -> KeyEvent.VK_O; + case GLFW.GLFW_KEY_P -> KeyEvent.VK_P; + case GLFW.GLFW_KEY_Q -> KeyEvent.VK_Q; + case GLFW.GLFW_KEY_R -> KeyEvent.VK_R; + case GLFW.GLFW_KEY_S -> KeyEvent.VK_S; + case GLFW.GLFW_KEY_T -> KeyEvent.VK_T; + case GLFW.GLFW_KEY_U -> KeyEvent.VK_U; + case GLFW.GLFW_KEY_V -> KeyEvent.VK_V; + case GLFW.GLFW_KEY_W -> KeyEvent.VK_W; + case GLFW.GLFW_KEY_X -> KeyEvent.VK_X; + case GLFW.GLFW_KEY_Y -> KeyEvent.VK_Y; + case GLFW.GLFW_KEY_Z -> KeyEvent.VK_Z; + case GLFW.GLFW_KEY_LEFT_BRACKET -> KeyEvent.VK_OPEN_BRACKET; + case GLFW.GLFW_KEY_BACKSLASH -> KeyEvent.VK_BACK_SLASH; + case GLFW.GLFW_KEY_RIGHT_BRACKET -> KeyEvent.VK_CLOSE_BRACKET; + case GLFW.GLFW_KEY_GRAVE_ACCENT -> KeyEvent.VK_BACK_QUOTE; + case GLFW.GLFW_KEY_ESCAPE -> KeyEvent.VK_ESCAPE; + case GLFW.GLFW_KEY_ENTER, GLFW.GLFW_KEY_KP_ENTER -> KeyEvent.VK_ENTER; + case GLFW.GLFW_KEY_TAB -> KeyEvent.VK_TAB; + case GLFW.GLFW_KEY_BACKSPACE -> KeyEvent.VK_BACK_SPACE; + case GLFW.GLFW_KEY_INSERT -> KeyEvent.VK_INSERT; + case GLFW.GLFW_KEY_DELETE -> KeyEvent.VK_DELETE; + case GLFW.GLFW_KEY_RIGHT -> KeyEvent.VK_RIGHT; + case GLFW.GLFW_KEY_LEFT -> KeyEvent.VK_LEFT; + case GLFW.GLFW_KEY_DOWN -> KeyEvent.VK_DOWN; + case GLFW.GLFW_KEY_UP -> KeyEvent.VK_UP; + case GLFW.GLFW_KEY_PAGE_UP -> KeyEvent.VK_PAGE_UP; + case GLFW.GLFW_KEY_PAGE_DOWN -> KeyEvent.VK_PAGE_DOWN; + case GLFW.GLFW_KEY_HOME -> KeyEvent.VK_HOME; + case GLFW.GLFW_KEY_END -> KeyEvent.VK_END; + case GLFW.GLFW_KEY_CAPS_LOCK -> KeyEvent.VK_CAPS_LOCK; + case GLFW.GLFW_KEY_SCROLL_LOCK -> KeyEvent.VK_SCROLL_LOCK; + case GLFW.GLFW_KEY_NUM_LOCK -> KeyEvent.VK_NUM_LOCK; + case GLFW.GLFW_KEY_PRINT_SCREEN -> KeyEvent.VK_PRINTSCREEN; + case GLFW.GLFW_KEY_PAUSE -> KeyEvent.VK_PAUSE; + case GLFW.GLFW_KEY_F1 -> KeyEvent.VK_F1; + case GLFW.GLFW_KEY_F2 -> KeyEvent.VK_F2; + case GLFW.GLFW_KEY_F3 -> KeyEvent.VK_F3; + case GLFW.GLFW_KEY_F4 -> KeyEvent.VK_F4; + case GLFW.GLFW_KEY_F5 -> KeyEvent.VK_F5; + case GLFW.GLFW_KEY_F6 -> KeyEvent.VK_F6; + case GLFW.GLFW_KEY_F7 -> KeyEvent.VK_F7; + case GLFW.GLFW_KEY_F8 -> KeyEvent.VK_F8; + case GLFW.GLFW_KEY_F9 -> KeyEvent.VK_F9; + case GLFW.GLFW_KEY_F10 -> KeyEvent.VK_F10; + case GLFW.GLFW_KEY_F11 -> KeyEvent.VK_F11; + case GLFW.GLFW_KEY_F12 -> KeyEvent.VK_F12; + case GLFW.GLFW_KEY_KP_0 -> KeyEvent.VK_NUMPAD0; + case GLFW.GLFW_KEY_KP_1 -> KeyEvent.VK_NUMPAD1; + case GLFW.GLFW_KEY_KP_2 -> KeyEvent.VK_NUMPAD2; + case GLFW.GLFW_KEY_KP_3 -> KeyEvent.VK_NUMPAD3; + case GLFW.GLFW_KEY_KP_4 -> KeyEvent.VK_NUMPAD4; + case GLFW.GLFW_KEY_KP_5 -> KeyEvent.VK_NUMPAD5; + case GLFW.GLFW_KEY_KP_6 -> KeyEvent.VK_NUMPAD6; + case GLFW.GLFW_KEY_KP_7 -> KeyEvent.VK_NUMPAD7; + case GLFW.GLFW_KEY_KP_8 -> KeyEvent.VK_NUMPAD8; + case GLFW.GLFW_KEY_KP_9 -> KeyEvent.VK_NUMPAD9; + case GLFW.GLFW_KEY_KP_DECIMAL -> KeyEvent.VK_DECIMAL; + case GLFW.GLFW_KEY_KP_DIVIDE -> KeyEvent.VK_DIVIDE; + case GLFW.GLFW_KEY_KP_MULTIPLY -> KeyEvent.VK_MULTIPLY; + case GLFW.GLFW_KEY_KP_SUBTRACT -> KeyEvent.VK_SUBTRACT; + case GLFW.GLFW_KEY_KP_ADD -> KeyEvent.VK_ADD; + case GLFW.GLFW_KEY_LEFT_SHIFT, GLFW.GLFW_KEY_RIGHT_SHIFT -> KeyEvent.VK_SHIFT; + case GLFW.GLFW_KEY_LEFT_CONTROL, GLFW.GLFW_KEY_RIGHT_CONTROL -> KeyEvent.VK_CONTROL; + case GLFW.GLFW_KEY_LEFT_ALT -> KeyEvent.VK_ALT; + case GLFW.GLFW_KEY_LEFT_SUPER, GLFW.GLFW_KEY_RIGHT_SUPER -> KeyEvent.VK_WINDOWS; + case GLFW.GLFW_KEY_RIGHT_ALT -> KeyEvent.VK_ALT_GRAPH; + // Add more cases for other keys as needed + default -> KeyEvent.VK_UNDEFINED; + }; + } + + public static boolean isCharacterKey(int glfwKeyCode) { + return switch (glfwKeyCode) { + case GLFW.GLFW_KEY_UNKNOWN, GLFW.GLFW_KEY_SPACE, GLFW.GLFW_KEY_APOSTROPHE, + GLFW.GLFW_KEY_COMMA, GLFW.GLFW_KEY_MINUS, GLFW.GLFW_KEY_PERIOD, + GLFW.GLFW_KEY_SLASH, GLFW.GLFW_KEY_SEMICOLON, GLFW.GLFW_KEY_EQUAL, + GLFW.GLFW_KEY_A, GLFW.GLFW_KEY_B, GLFW.GLFW_KEY_C, GLFW.GLFW_KEY_D, + GLFW.GLFW_KEY_E, GLFW.GLFW_KEY_F, GLFW.GLFW_KEY_G, GLFW.GLFW_KEY_H, + GLFW.GLFW_KEY_I, GLFW.GLFW_KEY_J, GLFW.GLFW_KEY_K, GLFW.GLFW_KEY_L, + GLFW.GLFW_KEY_M, GLFW.GLFW_KEY_N, GLFW.GLFW_KEY_O, GLFW.GLFW_KEY_P, + GLFW.GLFW_KEY_Q, GLFW.GLFW_KEY_R, GLFW.GLFW_KEY_S, GLFW.GLFW_KEY_T, + GLFW.GLFW_KEY_U, GLFW.GLFW_KEY_V, GLFW.GLFW_KEY_W, GLFW.GLFW_KEY_X, + GLFW.GLFW_KEY_Y, GLFW.GLFW_KEY_Z, GLFW.GLFW_KEY_LEFT_BRACKET, + GLFW.GLFW_KEY_BACKSLASH, GLFW.GLFW_KEY_RIGHT_BRACKET, + GLFW.GLFW_KEY_GRAVE_ACCENT, GLFW.GLFW_KEY_WORLD_1, + GLFW.GLFW_KEY_WORLD_2, GLFW.GLFW_KEY_KP_0, GLFW.GLFW_KEY_KP_1, + GLFW.GLFW_KEY_KP_2, GLFW.GLFW_KEY_KP_3, GLFW.GLFW_KEY_KP_4, + GLFW.GLFW_KEY_KP_5, GLFW.GLFW_KEY_KP_6, GLFW.GLFW_KEY_KP_7, + GLFW.GLFW_KEY_KP_8, GLFW.GLFW_KEY_KP_9, GLFW.GLFW_KEY_KP_DECIMAL, + GLFW.GLFW_KEY_0, GLFW.GLFW_KEY_1, GLFW.GLFW_KEY_2, + GLFW.GLFW_KEY_3, GLFW.GLFW_KEY_4, GLFW.GLFW_KEY_5, + GLFW.GLFW_KEY_6, GLFW.GLFW_KEY_7, GLFW.GLFW_KEY_8, GLFW.GLFW_KEY_9, + GLFW.GLFW_KEY_KP_DIVIDE, GLFW.GLFW_KEY_KP_MULTIPLY, + GLFW.GLFW_KEY_KP_SUBTRACT, GLFW.GLFW_KEY_KP_ADD, + GLFW.GLFW_KEY_KP_ENTER, GLFW.GLFW_KEY_KP_EQUAL -> true; + default -> false; + }; + } + + public static char getCharacterFromKeyCode(int glfwKeyCode, boolean shift) { + char character = switch (glfwKeyCode) { + case GLFW.GLFW_KEY_A -> shift ? 'A' : 'a'; + case GLFW.GLFW_KEY_B -> shift ? 'B' : 'b'; + case GLFW.GLFW_KEY_C -> shift ? 'C' : 'c'; + case GLFW.GLFW_KEY_D -> shift ? 'D' : 'd'; + case GLFW.GLFW_KEY_E -> shift ? 'E' : 'e'; + case GLFW.GLFW_KEY_F -> shift ? 'F' : 'f'; + case GLFW.GLFW_KEY_G -> shift ? 'G' : 'g'; + case GLFW.GLFW_KEY_H -> shift ? 'H' : 'h'; + case GLFW.GLFW_KEY_I -> shift ? 'I' : 'i'; + case GLFW.GLFW_KEY_J -> shift ? 'J' : 'j'; + case GLFW.GLFW_KEY_K -> shift ? 'K' : 'k'; + case GLFW.GLFW_KEY_L -> shift ? 'L' : 'l'; + case GLFW.GLFW_KEY_M -> shift ? 'M' : 'm'; + case GLFW.GLFW_KEY_N -> shift ? 'N' : 'n'; + case GLFW.GLFW_KEY_O -> shift ? 'O' : 'o'; + case GLFW.GLFW_KEY_P -> shift ? 'P' : 'p'; + case GLFW.GLFW_KEY_Q -> shift ? 'Q' : 'q'; + case GLFW.GLFW_KEY_R -> shift ? 'R' : 'r'; + case GLFW.GLFW_KEY_S -> shift ? 'S' : 's'; + case GLFW.GLFW_KEY_T -> shift ? 'T' : 't'; + case GLFW.GLFW_KEY_U -> shift ? 'U' : 'u'; + case GLFW.GLFW_KEY_V -> shift ? 'V' : 'v'; + case GLFW.GLFW_KEY_W -> shift ? 'W' : 'w'; + case GLFW.GLFW_KEY_X -> shift ? 'X' : 'x'; + case GLFW.GLFW_KEY_Y -> shift ? 'Y' : 'y'; + case GLFW.GLFW_KEY_Z -> shift ? 'Z' : 'z'; + case GLFW.GLFW_KEY_SPACE -> ' '; + case GLFW.GLFW_KEY_APOSTROPHE -> shift ? '"' : '\''; + case GLFW.GLFW_KEY_COMMA -> shift ? '<' : ','; + case GLFW.GLFW_KEY_MINUS -> shift ? '_' : '-'; + case GLFW.GLFW_KEY_PERIOD -> shift ? '>' : '.'; + case GLFW.GLFW_KEY_SLASH -> shift ? '?' : '/'; + case GLFW.GLFW_KEY_SEMICOLON -> shift ? ':' : ';'; + case GLFW.GLFW_KEY_EQUAL -> shift ? '+' : '='; + case GLFW.GLFW_KEY_LEFT_BRACKET -> shift ? '{' : '['; + case GLFW.GLFW_KEY_BACKSLASH -> shift ? '|' : '\\'; + case GLFW.GLFW_KEY_RIGHT_BRACKET -> shift ? '}' : ']'; + case GLFW.GLFW_KEY_GRAVE_ACCENT -> shift ? '~' : '`'; + case GLFW.GLFW_KEY_WORLD_1, GLFW.GLFW_KEY_WORLD_2 -> '\0'; + case GLFW.GLFW_KEY_KP_0, GLFW.GLFW_KEY_0 -> '0'; + case GLFW.GLFW_KEY_KP_1, GLFW.GLFW_KEY_1 -> '1'; + case GLFW.GLFW_KEY_KP_2, GLFW.GLFW_KEY_2 -> '2'; + case GLFW.GLFW_KEY_KP_3, GLFW.GLFW_KEY_3 -> '3'; + case GLFW.GLFW_KEY_KP_4, GLFW.GLFW_KEY_4 -> '4'; + case GLFW.GLFW_KEY_KP_5, GLFW.GLFW_KEY_5 -> '5'; + case GLFW.GLFW_KEY_KP_6, GLFW.GLFW_KEY_6 -> '6'; + case GLFW.GLFW_KEY_KP_7, GLFW.GLFW_KEY_7 -> '7'; + case GLFW.GLFW_KEY_KP_8, GLFW.GLFW_KEY_8 -> '8'; + case GLFW.GLFW_KEY_KP_9, GLFW.GLFW_KEY_9 -> '9'; + case GLFW.GLFW_KEY_KP_DECIMAL -> '.'; + case GLFW.GLFW_KEY_KP_DIVIDE -> '/'; + case GLFW.GLFW_KEY_KP_MULTIPLY -> '*'; + case GLFW.GLFW_KEY_KP_SUBTRACT -> '-'; + case GLFW.GLFW_KEY_KP_ADD -> '+'; + case GLFW.GLFW_KEY_KP_ENTER, GLFW.GLFW_KEY_ENTER -> '\n'; + case GLFW.GLFW_KEY_BACKSPACE -> '\b'; + case GLFW.GLFW_KEY_TAB -> '\t'; + default -> '\0'; + }; + + return character; + } + + public static int getModifiers(int glfwModifiers) { + int awtModifiers = 0; + + if ((glfwModifiers & GLFW.GLFW_MOD_SHIFT) != 0) { + awtModifiers |= KeyEvent.SHIFT_MASK; + } + if ((glfwModifiers & GLFW.GLFW_MOD_CONTROL) != 0) { + awtModifiers |= KeyEvent.CTRL_MASK; + } + if ((glfwModifiers & GLFW.GLFW_MOD_ALT) != 0) { + awtModifiers |= KeyEvent.ALT_MASK; + } + if ((glfwModifiers & GLFW.GLFW_MOD_SUPER) != 0) { + awtModifiers |= KeyEvent.META_MASK; + } + + return awtModifiers; + } +}