diff --git a/core/src/main/java/com/seibel/lod/core/config/gui/AbstractScreen.java b/core/src/main/java/com/seibel/lod/core/config/gui/AbstractScreen.java index dcbd4f1f6..e81cbfd96 100644 --- a/core/src/main/java/com/seibel/lod/core/config/gui/AbstractScreen.java +++ b/core/src/main/java/com/seibel/lod/core/config/gui/AbstractScreen.java @@ -10,6 +10,7 @@ import java.util.List; * @author coolGi */ public abstract class AbstractScreen { + public long minecraftWindow; public int width; public int height; public int mouseX = 0; diff --git a/core/src/main/java/com/seibel/lod/core/config/gui/EmbeddedFrameUtil.java b/core/src/main/java/com/seibel/lod/core/config/gui/EmbeddedFrameUtil.java new file mode 100644 index 000000000..5202a468c --- /dev/null +++ b/core/src/main/java/com/seibel/lod/core/config/gui/EmbeddedFrameUtil.java @@ -0,0 +1,143 @@ +package com.seibel.lod.core.config.gui; + +import org.lwjgl.system.*; +import org.lwjgl.system.jawt.JAWT; +import org.lwjgl.system.macosx.*; + +import java.awt.*; +import java.lang.reflect.*; +import java.util.regex.*; + +import static org.lwjgl.glfw.GLFWNativeCocoa.*; +import static org.lwjgl.glfw.GLFWNativeWin32.*; +import static org.lwjgl.glfw.GLFWNativeX11.*; +import static org.lwjgl.system.JNI.*; +import static org.lwjgl.system.jawt.JAWTFunctions.*; +import static org.lwjgl.system.macosx.ObjCRuntime.*; + +// Some of the code is from https://github.com/LWJGL/lwjgl3/blob/master/modules/samples/src/test/java/org/lwjgl/demo/system/jawt/EmbeddedFrameUtil.java +// which is licensed under https://www.lwjgl.org/license + +public final class EmbeddedFrameUtil { + + private static final int JAVA_VERSION; + + private static final JAWT awt; + + static { + Pattern p = Pattern.compile("^(?:1[.])?([1-9][0-9]*)[.-]"); + Matcher m = p.matcher(System.getProperty("java.version")); + + if (!m.find()) { + throw new IllegalStateException("Failed to parse java.version"); + } + + JAVA_VERSION = Integer.parseInt(m.group(1)); + + awt = JAWT.calloc(); + awt.version(JAVA_VERSION < 9 ? JAWT_VERSION_1_4 : JAWT_VERSION_9); + if (!JAWT_GetAWT(awt)) { + throw new RuntimeException("GetAWT failed"); + } + } + + private static String getEmbeddedFrameImpl() { + switch (Platform.get()) { + case LINUX: + return "sun.awt.X11.XEmbeddedFrame"; + case MACOSX: + return "sun.lwawt.macosx.CViewEmbeddedFrame"; + case WINDOWS: + return "sun.awt.windows.WEmbeddedFrame"; + default: + throw new IllegalStateException(); + } + } + + private static long getEmbeddedFrameHandle(long window) { + switch (Platform.get()) { + case LINUX: + return glfwGetX11Window(window); + case MACOSX: + long objc_msgSend = ObjCRuntime.getLibrary().getFunctionAddress("objc_msgSend"); + return invokePPP(glfwGetCocoaWindow(window), sel_getUid("contentView"), objc_msgSend); + case WINDOWS: + return glfwGetWin32Window(window); + default: + throw new IllegalStateException(); + } + } + + public static Frame embeddedFrameCreate(long window) { + if (JAVA_VERSION < 9) { + try { + @SuppressWarnings("unchecked") + Class EmdeddedFrame = (Class)Class.forName(getEmbeddedFrameImpl()); + Constructor c = EmdeddedFrame.getConstructor(long.class); + + return c.newInstance(getEmbeddedFrameHandle(window)); + } catch (Exception e) { + throw new RuntimeException(e); + } + } else { + return nJAWT_CreateEmbeddedFrame(getEmbeddedFrameHandle(window), awt.CreateEmbeddedFrame()); + } + } + + static void embeddedFrameSynthesizeWindowActivation(Frame embeddedFrame, boolean doActivate) { + if (JAVA_VERSION < 9) { + try { + embeddedFrame + .getClass() + .getMethod("synthesizeWindowActivation", boolean.class) + .invoke(embeddedFrame, doActivate); + } catch (Exception e) { + throw new RuntimeException(e); + } + } else { + JAWT_SynthesizeWindowActivation(embeddedFrame, doActivate, awt.SynthesizeWindowActivation()); + } + } + + public static void embeddedFrameSetBounds(Frame embeddedFrame, int x, int y, int width, int height) { + if (JAVA_VERSION < 9) { + try { + Method setLocationPrivate = embeddedFrame + .getClass() + .getSuperclass() + .getDeclaredMethod("setBoundsPrivate", int.class, int.class, int.class, int.class); + setLocationPrivate.setAccessible(true); + setLocationPrivate.invoke(embeddedFrame, x, y, width, height); + } catch (Exception e) { + throw new RuntimeException(e); + } + } else { + JAWT_SetBounds(embeddedFrame, x, y, width, height, awt.SetBounds()); + } + } + + // The code below is by Ran + + public static void hideFrame(Frame embeddedFrame) { + if (embeddedFrame != null) { + embeddedFrame.setVisible(false); + embeddedFrameSynthesizeWindowActivation(embeddedFrame, false); + } + } + + public static void showFrame(Frame embeddedFrame) { + if (embeddedFrame != null) { + embeddedFrameSynthesizeWindowActivation(embeddedFrame, true); + embeddedFrame.setVisible(true); + } + } + + public static void placeAtCenter(Frame embeddedFrame, int windowWidth, int windowHeight, int frameWidth, int frameHeight, float scale) { + float scaleFactor = (100.0F - scale) / 100.0F; + float newWidth = frameWidth * scaleFactor; + float newHeight = frameHeight * scaleFactor; + float newX = (windowWidth - newWidth) / 2F; + float newY = (windowHeight - newHeight) / 2F; + embeddedFrameSetBounds(embeddedFrame, Math.round(newX), Math.round(newY), Math.round(newWidth), Math.round(newHeight)); + } +} \ No newline at end of file diff --git a/core/src/main/java/com/seibel/lod/core/config/gui/JavaFXConfigScreen.java b/core/src/main/java/com/seibel/lod/core/config/gui/JavaFXConfigScreen.java index 46bcfa0b0..55b02d74f 100644 --- a/core/src/main/java/com/seibel/lod/core/config/gui/JavaFXConfigScreen.java +++ b/core/src/main/java/com/seibel/lod/core/config/gui/JavaFXConfigScreen.java @@ -1,13 +1,40 @@ package com.seibel.lod.core.config.gui; +import javax.swing.*; +import java.awt.*; + public class JavaFXConfigScreen extends AbstractScreen { + static { + System.setProperty("java.awt.headless", "false"); + } + @Override public void init() { - + Frame frame = EmbeddedFrameUtil.embeddedFrameCreate(this.minecraftWindow); + frame.add(new ExampleScreen()); + EmbeddedFrameUtil.placeAtCenter(frame, this.width, this.height, 100, 100, 1); } + public class ExampleScreen extends JComponent { + public ExampleScreen() { + setLayout(new GridBagLayout()); + GridBagConstraints constraints = new GridBagConstraints(); + constraints.fill = GridBagConstraints.HORIZONTAL; + constraints.weightx = 0.5; + constraints.gridx = 0; + constraints.gridy = 0; + add(new JLabel("Hello World!"), constraints); + } + } + + @Override public void render(float delta) { } + + @Override + public void onClose() { + + } } diff --git a/core/src/main/java/com/seibel/lod/core/jar/DarkModeDetector.java b/core/src/main/java/com/seibel/lod/core/jar/DarkModeDetector.java index 122d5c3e8..db0e7e403 100644 --- a/core/src/main/java/com/seibel/lod/core/jar/DarkModeDetector.java +++ b/core/src/main/java/com/seibel/lod/core/jar/DarkModeDetector.java @@ -3,8 +3,6 @@ package com.seibel.lod.core.jar; import java.io.*; import java.util.regex.Pattern; -import static com.seibel.lod.core.jar.JarMain.getOperatingSystem; - /** * A fork of iris'is dark mode detector (https://github.com/IrisShaders/Iris-Installer/blob/master/src/main/java/net/hypercubemc/iris_installer/DarkModeDetector.java) * Which is a fork of HanSolo's dark mode detector (https://gist.github.com/HanSolo/7cf10b86efff8ca2845bf5ec2dd0fe1d) @@ -21,7 +19,7 @@ public class DarkModeDetector { private static final String DARK_THEME_CMD = REGQUERY_UTIL + "\"HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize\"" + " /v AppsUseLightTheme"; public static boolean isDarkMode() { - switch (getOperatingSystem()) { + switch (JarUtils.getOperatingSystem()) { case WINDOWS: return isWindowsDarkMode(); case MACOS: diff --git a/core/src/main/java/com/seibel/lod/core/jar/JarMain.java b/core/src/main/java/com/seibel/lod/core/jar/JarMain.java index 524ecbb8b..6d2e606c5 100644 --- a/core/src/main/java/com/seibel/lod/core/jar/JarMain.java +++ b/core/src/main/java/com/seibel/lod/core/jar/JarMain.java @@ -81,21 +81,4 @@ public class JarMain extends Application { return; } } - - - - - public enum OperatingSystem {WINDOWS, MACOS, LINUX, NONE} // Easy to use enum for the 3 main os's - public static OperatingSystem getOperatingSystem() { // Get the os and turn it into that enum - String os = System.getProperty("os.name").toLowerCase(); - if (os.contains("win")) { - return OperatingSystem.WINDOWS; - } else if (os.contains("mac")) { - return OperatingSystem.MACOS; - } else if (os.contains("nix") || os.contains("nux")) { - return OperatingSystem.LINUX; - } else { - return OperatingSystem.NONE; - } - } } diff --git a/core/src/main/java/com/seibel/lod/core/jar/JarUtils.java b/core/src/main/java/com/seibel/lod/core/jar/JarUtils.java index c79aceece..d071f8f84 100644 --- a/core/src/main/java/com/seibel/lod/core/jar/JarUtils.java +++ b/core/src/main/java/com/seibel/lod/core/jar/JarUtils.java @@ -103,4 +103,19 @@ public class JarUtils { //return complete hash return sb.toString(); } + + + public enum OperatingSystem {WINDOWS, MACOS, LINUX, NONE} // Easy to use enum for the 3 main os's + public static OperatingSystem getOperatingSystem() { // Get the os and turn it into that enum + String os = System.getProperty("os.name").toLowerCase(); + if (os.contains("win")) { + return OperatingSystem.WINDOWS; + } else if (os.contains("mac")) { + return OperatingSystem.MACOS; + } else if (os.contains("nix") || os.contains("nux")) { + return OperatingSystem.LINUX; + } else { + return OperatingSystem.NONE; + } + } }