From 87f924ce8eaf9e104dbc0c864071b920dfbb1854 Mon Sep 17 00:00:00 2001 From: deechael Date: Mon, 7 Oct 2024 13:12:26 +0800 Subject: [PATCH] refactor: replaced dirty solution with real exclusive fullscreen --- .../deechael/concentration/config/Config.java | 10 ++ .../concentration/mixin/MainMixin.java | 11 ++ .../concentration/util/Accessors.java | 15 ++ .../main/resources/concentration.mixins.json | 1 + .../config/ConcentrationConfigFabric.java | 5 + .../concentration/fabric/mixin/GLFWMixin.java | 156 ++++++++++-------- .../fabric/mixin/WindowMixin.java | 142 ++++++++-------- .../config/ConcentrationConfigForge.java | 5 + .../forge/mixin/WindowMixin.java | 148 ++++++++--------- gradle.properties | 2 +- .../neoforge/ConcentrationNeoForge.java | 1 - .../ConcentrationNeoForgeMixinPlugin.java | 4 +- .../config/ConcentrationConfigNeoForge.java | 11 +- .../neoforge/mixin/WindowMixin.java | 148 ++++++++--------- 14 files changed, 367 insertions(+), 292 deletions(-) create mode 100644 common/src/main/java/net/deechael/concentration/mixin/MainMixin.java create mode 100644 common/src/main/java/net/deechael/concentration/util/Accessors.java diff --git a/common/src/main/java/net/deechael/concentration/config/Config.java b/common/src/main/java/net/deechael/concentration/config/Config.java index 2fb52e5..f08c345 100644 --- a/common/src/main/java/net/deechael/concentration/config/Config.java +++ b/common/src/main/java/net/deechael/concentration/config/Config.java @@ -4,10 +4,20 @@ import net.deechael.concentration.FullscreenMode; public interface Config { + boolean customized(); + FullscreenMode getFullscreenMode(); void setFullscreenMode(FullscreenMode fullscreenMode); void save(); + static boolean isBorderless() { + return ConfigProvider.INSTANCE.ensureLoaded().getFullscreenMode() == FullscreenMode.BORDERLESS; + } + + static boolean isCustomized() { + return ConfigProvider.INSTANCE.ensureLoaded().customized(); + } + } diff --git a/common/src/main/java/net/deechael/concentration/mixin/MainMixin.java b/common/src/main/java/net/deechael/concentration/mixin/MainMixin.java new file mode 100644 index 0000000..4235ad5 --- /dev/null +++ b/common/src/main/java/net/deechael/concentration/mixin/MainMixin.java @@ -0,0 +1,11 @@ +package net.deechael.concentration.mixin; + +import net.minecraft.client.main.Main; +import org.spongepowered.asm.mixin.Mixin; + +@Mixin(Main.class) +public class MainMixin { + + + +} diff --git a/common/src/main/java/net/deechael/concentration/util/Accessors.java b/common/src/main/java/net/deechael/concentration/util/Accessors.java new file mode 100644 index 0000000..395dc75 --- /dev/null +++ b/common/src/main/java/net/deechael/concentration/util/Accessors.java @@ -0,0 +1,15 @@ +package net.deechael.concentration.util; + +import net.deechael.concentration.mixin.accessor.WindowAccessor; +import net.minecraft.client.Minecraft; + +public final class Accessors { + + public static WindowAccessor window() { + return ((WindowAccessor) (Object) Minecraft.getInstance().getWindow()); + } + + private Accessors() { + } + +} diff --git a/common/src/main/resources/concentration.mixins.json b/common/src/main/resources/concentration.mixins.json index 51c6753..f1dc87f 100644 --- a/common/src/main/resources/concentration.mixins.json +++ b/common/src/main/resources/concentration.mixins.json @@ -7,6 +7,7 @@ "mixins": [], "client": [ "KeyboardHandlerMixin", + "MainMixin", "VideoSettingsScreenMixin", "accessor.WindowAccessor" ], diff --git a/fabric/src/main/java/net/deechael/concentration/fabric/config/ConcentrationConfigFabric.java b/fabric/src/main/java/net/deechael/concentration/fabric/config/ConcentrationConfigFabric.java index 326ad93..a62b976 100644 --- a/fabric/src/main/java/net/deechael/concentration/fabric/config/ConcentrationConfigFabric.java +++ b/fabric/src/main/java/net/deechael/concentration/fabric/config/ConcentrationConfigFabric.java @@ -43,6 +43,11 @@ public class ConcentrationConfigFabric implements Config { public int height = 600; public FullscreenMode fullscreen = FullscreenMode.BORDERLESS; + @Override + public boolean customized() { + return this.customized; + } + @Override public FullscreenMode getFullscreenMode() { return this.fullscreen; diff --git a/fabric/src/main/java/net/deechael/concentration/fabric/mixin/GLFWMixin.java b/fabric/src/main/java/net/deechael/concentration/fabric/mixin/GLFWMixin.java index 9b3ff1b..4bcc019 100644 --- a/fabric/src/main/java/net/deechael/concentration/fabric/mixin/GLFWMixin.java +++ b/fabric/src/main/java/net/deechael/concentration/fabric/mixin/GLFWMixin.java @@ -5,12 +5,16 @@ import com.mojang.blaze3d.platform.VideoMode; import com.mojang.blaze3d.platform.Window; import net.deechael.concentration.ConcentrationConstants; import net.deechael.concentration.FullscreenMode; +import net.deechael.concentration.config.Config; import net.deechael.concentration.fabric.ConcentrationFabricCaching; import net.deechael.concentration.fabric.config.ConcentrationConfigFabric; import net.deechael.concentration.mixin.accessor.WindowAccessor; import net.minecraft.client.Minecraft; import org.lwjgl.glfw.GLFW; +import org.lwjgl.glfw.GLFWNativeWin32; +import org.lwjgl.system.windows.User32; import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @@ -27,112 +31,94 @@ public class GLFWMixin { ConcentrationConstants.LOGGER.info("================= [Concentration Start] ================="); ConcentrationConstants.LOGGER.info("Trying to modify window monitor"); - // Monitor is 0 means the game is windowed mode, so the expression means if is toggling to fullscreen + Window windowInstance = Minecraft.getInstance().getWindow(); + WindowAccessor accessor = (WindowAccessor) (Object) windowInstance; + + if (windowInstance.isFullscreen()) + if (monitor == 0L) + monitor = windowInstance.findBestMonitor().getMonitor(); + + Monitor monitorInstance = accessor.getScreenManager().getMonitor(monitor); + ConcentrationConstants.LOGGER.info("Current fullscreen monitor is {}", monitor); + if (monitor != 0L) { + VideoMode currentMode = monitorInstance.getCurrentMode(); ConcentrationConstants.LOGGER.info("Modifying window size limits"); - GLFW.glfwSetWindowSizeLimits(window, 0, 0, width, height); + GLFW.glfwSetWindowSizeLimits(window, 0, 0, currentMode.getWidth(), currentMode.getHeight()); } - // Because whether in fullscreen mode or windowed mode - // The final step is same - // So I extracted the value then execute the final step + long finalMonitor; + int finalWidth; int finalHeight; int finalX; int finalY; - Window windowInstance = Minecraft.getInstance().getWindow(); - WindowAccessor accessor = (WindowAccessor) (Object) windowInstance; - if (windowInstance != null && windowInstance.isFullscreen()) { + VideoMode currentMode = monitorInstance.getCurrentMode(); + ConcentrationConfigFabric config = ConcentrationConfigFabric.getInstance(); - // If the game started with fullscreen mode, when switching to windowed mode, it will be forced to move to the primary monitor - // Though size and position isn't be set at initialization, but I think the window should be at the initial monitor - // So save the monitor and use the monitor value when the size isn't cached ConcentrationFabricCaching.lastMonitor = monitor; - // Lock caching, because when switching back, the window will be once resized to the maximum value and the cache value will be wrong - // Position won't be affected, so it doesn't need lock ConcentrationFabricCaching.cacheSizeLock = true; ConcentrationConstants.LOGGER.info("Locked size caching"); if (config.fullscreen == FullscreenMode.NATIVE) { ConcentrationConstants.LOGGER.info("Fullscreen mode is native, apply now!"); - if (monitor == 0L) - monitor = windowInstance.findBestMonitor().getMonitor(); - finalExecute(window, monitor, xpos, ypos, width, height, -1); - ConcentrationConstants.LOGGER.info("================= [Concentration End] ================="); - return; - } - - ConcentrationConstants.LOGGER.info("Trying to switch to borderless fullscreen mode"); - - // Get the monitor the user want to use and get the relative position in the system - // The monitor is always non-null because when switching fullscreen mode, there must be a monitor to put the window - Monitor monitorInstance = accessor.getScreenManager().getMonitor(monitor); - ConcentrationConstants.LOGGER.info("Current fullscreen monitor is {}", monitor); - - // Remove the title bar to prevent that user can see the title bar if they put their monitors vertically connected - GLFW.glfwSetWindowAttrib(window, GLFW.GLFW_DECORATED, GLFW.GLFW_FALSE); - ConcentrationConstants.LOGGER.info("Trying to remove the title bar"); - - if (ConcentrationConfigFabric.getInstance().customized) { - - ConcentrationConstants.LOGGER.info("Customization enabled, so replace the fullscreen size with customized size"); - finalX = config.x + (config.related ? monitorInstance.getX() : 0); - finalY = config.y - (config.height == height ? 1 : 0) + (config.related ? monitorInstance.getY() : 0); - finalWidth = config.width; - finalHeight = config.height + (config.height == height ? 1 : 0); - } else { - // If we make the window not decorated and set the window size exactly the same with the screen size, it will become native fullscreen mode - // to prevent this, I enlarge the height by 1 pixel and move up the window by 1 pixel which won't affect anything (unless you have a screen - // which is added above the monitor which holds the game) and will have a good experience - // Actually this is a little bit dirty, needs to find a better way to solve it + finalMonitor = monitor; finalX = monitorInstance.getX(); - finalY = monitorInstance.getY() - 1; - finalWidth = width; - finalHeight = height + 1; - } + finalY = monitorInstance.getY(); + finalWidth = currentMode.getWidth(); + finalHeight = currentMode.getHeight(); + ConcentrationConstants.LOGGER.info("================= [Concentration End] ================="); + } else { + ConcentrationConstants.LOGGER.info("Trying to switch to borderless fullscreen mode"); - accessor.setX(finalX); - accessor.setY(finalY); - accessor.setWidth(finalWidth); - accessor.setHeight(finalHeight); + /*if (ConcentrationConfigFabric.getInstance().customized) { + ConcentrationConstants.LOGGER.info("Customization enabled, so replace the fullscreen size with customized size"); + finalX = config.x + (config.related ? monitorInstance.getX() : 0); + finalY = config.y - (config.height == height ? 1 : 0) + (config.related ? monitorInstance.getY() : 0); + finalWidth = config.width; + finalHeight = config.height + (config.height == height ? 1 : 0); + } else */ + { + finalMonitor = monitor; + finalX = monitorInstance.getX(); + finalY = monitorInstance.getY(); + finalWidth = currentMode.getWidth(); + finalHeight = currentMode.getHeight(); + } + + accessor.setX(finalX); + accessor.setY(finalY); + accessor.setWidth(finalWidth); + accessor.setHeight(finalHeight); + } } else { ConcentrationConstants.LOGGER.info("Trying to switch to windowed mode"); - // Re-add the title bar so user can move the window and minimize, maximize and close the window - ConcentrationConstants.LOGGER.info("Trying to add title bar back"); - GLFW.glfwSetWindowAttrib(window, GLFW.GLFW_DECORATED, GLFW.GLFW_TRUE); + finalMonitor = 0L; ConcentrationConstants.LOGGER.info("Trying to use cached value to resize the window"); - // Make sure that Concentration has cached position and size, because position size won't be cached when the game starting in fullscreen mode finalWidth = ConcentrationFabricCaching.cachedSize ? ConcentrationFabricCaching.cachedWidth : width; finalHeight = ConcentrationFabricCaching.cachedSize ? ConcentrationFabricCaching.cachedHeight : height; - // To make sure that even starting with fullscreen mode can also make the window stay at the current monitor - // So I set two ways to ensure the position if (ConcentrationFabricCaching.cachedPos) { - // If Concentration cached the pos, use the cached value finalX = ConcentrationFabricCaching.cachedX; finalY = ConcentrationFabricCaching.cachedY; } else if (ConcentrationFabricCaching.lastMonitor != -1) { - // or else maybe the game started with fullscreen mode, so I don't need to care about the size - // only need to make sure that the position is in the correct monitor - Monitor monitorInstance = accessor.getScreenManager().getMonitor(ConcentrationFabricCaching.lastMonitor); - VideoMode videoMode = monitorInstance.getCurrentMode(); + Monitor lastMonitor = accessor.getScreenManager().getMonitor(ConcentrationFabricCaching.lastMonitor); + VideoMode videoMode = lastMonitor.getCurrentMode(); finalX = (videoMode.getWidth() - finalWidth) / 2; finalY = (videoMode.getHeight() - finalHeight) / 2; } else { - // if both value are missed, use the default value to prevent errors finalX = xpos; finalY = ypos; } - // Unlock caching, because user can change the window size now ConcentrationFabricCaching.cacheSizeLock = false; ConcentrationConstants.LOGGER.info("Unlocked size caching"); } @@ -140,12 +126,52 @@ public class GLFWMixin { ConcentrationConstants.LOGGER.info("Window size: {}, {}, position: {}, {}", finalWidth, finalHeight, finalX, finalY); ConcentrationConstants.LOGGER.info("Trying to resize and reposition the window"); - finalExecute(window, 0L, finalX, finalY, finalWidth, finalHeight, -1); + finalExecute(window, finalMonitor, finalX, finalY, finalWidth, finalHeight, -1); + + if (windowInstance.isFullscreen() && !(Config.isBorderless() && Config.isCustomized())) { + GLFW.glfwSetWindowAttrib(windowInstance.getWindow(), 0x20006, 1); + + long hWnd = GLFWNativeWin32.glfwGetWin32Window(windowInstance.getWindow()); + if (hWnd != 0) { + User32.SetWindowPos( + hWnd, + User32.HWND_TOPMOST, + windowInstance.getX(), + windowInstance.getY(), + windowInstance.getScreenWidth(), + windowInstance.getScreenHeight(), + 1027 + ); + User32.SetWindowLongPtr(hWnd, -16, 0x960A0000L); + User32.SetWindowLongPtr(hWnd, -20, 0x40010L); + } + + if (Config.isBorderless()) { + GLFW.glfwSetWindowAttrib(windowInstance.getWindow(), 0x20006, 0); + + if (System.getProperty("os.name").contains("Windows")) { + if (hWnd != 0) { + User32.SetWindowPos( + hWnd, + User32.HWND_NOTOPMOST, + windowInstance.getX(), + windowInstance.getY(), + windowInstance.getScreenWidth(), + windowInstance.getScreenHeight(), + 1027 + ); + User32.SetWindowLongPtr(hWnd, -16, 369229824); + User32.SetWindowLongPtr(hWnd, -20, 34340880); + } + } + } + } ConcentrationConstants.LOGGER.info("================= [Concentration End] ================="); ci.cancel(); } + @Unique private static void finalExecute(long window, long monitor, int xpos, int ypos, int width, int height, int refreshRate) { long __functionAddress = GLFW.Functions.SetWindowMonitor; if (CHECKS) { diff --git a/fabric/src/main/java/net/deechael/concentration/fabric/mixin/WindowMixin.java b/fabric/src/main/java/net/deechael/concentration/fabric/mixin/WindowMixin.java index 31e4b01..abf9541 100644 --- a/fabric/src/main/java/net/deechael/concentration/fabric/mixin/WindowMixin.java +++ b/fabric/src/main/java/net/deechael/concentration/fabric/mixin/WindowMixin.java @@ -6,9 +6,12 @@ import com.mojang.blaze3d.platform.VideoMode; import com.mojang.blaze3d.platform.Window; import net.deechael.concentration.ConcentrationConstants; import net.deechael.concentration.FullscreenMode; +import net.deechael.concentration.config.Config; import net.deechael.concentration.fabric.ConcentrationFabricCaching; import net.deechael.concentration.fabric.config.ConcentrationConfigFabric; import org.lwjgl.glfw.GLFW; +import org.lwjgl.glfw.GLFWNativeWin32; +import org.lwjgl.system.windows.User32; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; @@ -41,6 +44,10 @@ public abstract class WindowMixin { @Shadow private int height; + @Shadow + @Final + private long window; + @Inject(method = "onMove", at = @At("HEAD")) private void inject$onMove$head(long window, int x, int y, CallbackInfo ci) { if (!this.fullscreen) { @@ -66,19 +73,21 @@ public abstract class WindowMixin { } @Redirect(method = "setMode", at = @At(value = "INVOKE", remap = false, target = "Lorg/lwjgl/glfw/GLFW;glfwSetWindowMonitor(JJIIIII)V")) - private void redirect$glfwSetWindowMonitor(long window, long monitor, int xpos, int ypos, int width, int height, int refreshRate) { + private void redirect$glfwSetWindowMonitor(long window, long monitor, int xpos, int ypos, int ignored$width, int ignored$height, int ignored$refreshRate) { ConcentrationConstants.LOGGER.info("================= [Concentration Start] ================="); ConcentrationConstants.LOGGER.info("Trying to modify window monitor"); - // Monitor is 0 means the game is windowed mode, so the expression means if is toggling to fullscreen + Monitor monitorInstance = this.screenManager.getMonitor(monitor); + ConcentrationConstants.LOGGER.info("Current fullscreen monitor is {}", monitor); + if (monitor != 0L) { + VideoMode currentMode = monitorInstance.getCurrentMode(); ConcentrationConstants.LOGGER.info("Modifying window size limits"); - GLFW.glfwSetWindowSizeLimits(window, 0, 0, width, height); + GLFW.glfwSetWindowSizeLimits(window, 0, 0, currentMode.getWidth(), currentMode.getHeight()); } - // Because whether in fullscreen mode or windowed mode - // The final step is same - // So I extracted the value then execute the final step + long finalMonitor; + int finalWidth; int finalHeight; @@ -86,90 +95,67 @@ public abstract class WindowMixin { int finalY; if (this.fullscreen) { + VideoMode currentMode = monitorInstance.getCurrentMode(); + ConcentrationConfigFabric config = ConcentrationConfigFabric.getInstance(); - // If the game started with fullscreen mode, when switching to windowed mode, it will be forced to move to the primary monitor - // Though size and position isn't be set at initialization, but I think the window should be at the initial monitor - // So save the monitor and use the monitor value when the size isn't cached ConcentrationFabricCaching.lastMonitor = monitor; - // Lock caching, because when switching back, the window will be once resized to the maximum value and the cache value will be wrong - // Position won't be affected, so it doesn't need lock ConcentrationFabricCaching.cacheSizeLock = true; ConcentrationConstants.LOGGER.info("Locked size caching"); if (config.fullscreen == FullscreenMode.NATIVE) { - ConcentrationConstants.LOGGER.info("Fullscreen mode is native, apply now!"); - GLFW.glfwSetWindowMonitor(window, monitor, xpos, ypos, width, height, -1); - ConcentrationConstants.LOGGER.info("================= [Concentration End] ================="); - return; - } - - ConcentrationConstants.LOGGER.info("Trying to switch to borderless fullscreen mode"); - - // Get the monitor the user want to use and get the relative position in the system - // The monitor is always non-null because when switching fullscreen mode, there must be a monitor to put the window - Monitor monitorInstance = this.screenManager.getMonitor(monitor); - ConcentrationConstants.LOGGER.info("Current fullscreen monitor is {}", monitor); - - // Remove the title bar to prevent that user can see the title bar if they put their monitors vertically connected - GLFW.glfwSetWindowAttrib(window, GLFW.GLFW_DECORATED, GLFW.GLFW_FALSE); - ConcentrationConstants.LOGGER.info("Trying to remove the title bar"); - - if (ConcentrationConfigFabric.getInstance().customized) { - ConcentrationConstants.LOGGER.info("Customization enabled, so replace the fullscreen size with customized size"); - finalX = config.x + (config.related ? monitorInstance.getX() : 0); - finalY = config.y - (config.height == height ? 1 : 0) + (config.related ? monitorInstance.getY() : 0); - finalWidth = config.width; - finalHeight = config.height + (config.height == height ? 1 : 0); - } else { - // If we make the window not decorated and set the window size exactly the same with the screen size, it will become native fullscreen mode - // to prevent this, I enlarge the height by 1 pixel and move up the window by 1 pixel which won't affect anything (unless you have a screen - // which is added above the monitor which holds the game) and will have a good experience - // Actually this is a little bit dirty, needs to find a better way to solve it + ConcentrationConstants.LOGGER.info("Fullscreen mode is native"); + finalMonitor = monitor; finalX = monitorInstance.getX(); - finalY = monitorInstance.getY() - 1; - finalWidth = width; - finalHeight = height + 1; - } + finalY = monitorInstance.getY(); + finalWidth = currentMode.getWidth(); + finalHeight = currentMode.getHeight(); + } else { + ConcentrationConstants.LOGGER.info("Trying to switch to borderless fullscreen mode"); - this.x = finalX; - this.y = finalY; - this.width = finalWidth; - this.height = finalHeight; + /*if (ConcentrationConfigFabric.getInstance().customized) { + GLFW.glfwSetWindowAttrib(window, GLFW.GLFW_DECORATED, GLFW.GLFW_FALSE); + finalMonitor = 0L; + ConcentrationConstants.LOGGER.info("Customization enabled, so replace the fullscreen size with customized size"); + finalX = config.x + (config.related ? monitorInstance.getX() : 0); + finalY = config.y - (config.height == height ? 1 : 0) + (config.related ? monitorInstance.getY() : 0); + finalWidth = config.width; + finalHeight = config.height + (config.height == height ? 1 : 0); + } else */ + { + finalMonitor = monitor; + finalX = monitorInstance.getX(); + finalY = monitorInstance.getY(); + finalWidth = currentMode.getWidth(); + finalHeight = currentMode.getHeight(); + } + this.x = finalX; + this.y = finalY; + this.width = finalWidth; + this.height = finalHeight; + } } else { ConcentrationConstants.LOGGER.info("Trying to switch to windowed mode"); - - // Re-add the title bar so user can move the window and minimize, maximize and close the window - ConcentrationConstants.LOGGER.info("Trying to add title bar back"); - GLFW.glfwSetWindowAttrib(window, GLFW.GLFW_DECORATED, GLFW.GLFW_TRUE); + finalMonitor = 0L; ConcentrationConstants.LOGGER.info("Trying to use cached value to resize the window"); - // Make sure that Concentration has cached position and size, because position size won't be cached when the game starting in fullscreen mode finalWidth = ConcentrationFabricCaching.cachedSize ? ConcentrationFabricCaching.cachedWidth : width; finalHeight = ConcentrationFabricCaching.cachedSize ? ConcentrationFabricCaching.cachedHeight : height; - // To make sure that even starting with fullscreen mode can also make the window stay at the current monitor - // So I set two ways to ensure the position if (ConcentrationFabricCaching.cachedPos) { - // If Concentration cached the pos, use the cached value finalX = ConcentrationFabricCaching.cachedX; finalY = ConcentrationFabricCaching.cachedY; - } else if (ConcentrationFabricCaching.lastMonitor != -1) { - // or else maybe the game started with fullscreen mode, so I don't need to care about the size - // only need to make sure that the position is in the correct monitor - Monitor monitorInstance = this.screenManager.getMonitor(ConcentrationFabricCaching.lastMonitor); - VideoMode videoMode = monitorInstance.getCurrentMode(); + } else if (ConcentrationFabricCaching.lastMonitor != -1 && this.screenManager.getMonitor(ConcentrationFabricCaching.lastMonitor) != null) { + Monitor lastMonitor = this.screenManager.getMonitor(ConcentrationFabricCaching.lastMonitor); + VideoMode videoMode = lastMonitor.getCurrentMode(); finalX = (videoMode.getWidth() - finalWidth) / 2; finalY = (videoMode.getHeight() - finalHeight) / 2; } else { - // if both value are missed, use the default value to prevent errors finalX = xpos; finalY = ypos; } - - // Unlock caching, because user can change the window size now ConcentrationFabricCaching.cacheSizeLock = false; ConcentrationConstants.LOGGER.info("Unlocked size caching"); } @@ -177,14 +163,32 @@ public abstract class WindowMixin { ConcentrationConstants.LOGGER.info("Window size: {}, {}, position: {}, {}", finalWidth, finalHeight, finalX, finalY); ConcentrationConstants.LOGGER.info("Trying to resize and reposition the window"); - GLFW.glfwSetWindowMonitor(window, 0L, finalX, finalY, finalWidth, finalHeight, -1); + GLFW.glfwSetWindowMonitor(window, finalMonitor, finalX, finalY, finalWidth, finalHeight, -1); + + if (this.fullscreen && !(Config.isBorderless() && Config.isCustomized())) { + GLFW.glfwSetWindowAttrib(this.window, 0x20006, 1); + + long hWnd = GLFWNativeWin32.glfwGetWin32Window(this.window); + if (hWnd != 0) { + User32.SetWindowPos(hWnd, User32.HWND_TOPMOST, this.x, this.y, this.width, this.height, 1027); + User32.SetWindowLongPtr(hWnd, -16, 0x960A0000L); + User32.SetWindowLongPtr(hWnd, -20, 0x40010L); + } + + if (Config.isBorderless()) { + GLFW.glfwSetWindowAttrib(this.window, 0x20006, 0); + + if (System.getProperty("os.name").contains("Windows")) { + if (hWnd != 0) { + User32.SetWindowPos(hWnd, User32.HWND_NOTOPMOST, this.x, this.y, this.width, this.height, 1027); + User32.SetWindowLongPtr(hWnd, -16, 369229824); + User32.SetWindowLongPtr(hWnd, -20, 34340880); + } + } + } + } ConcentrationConstants.LOGGER.info("================= [Concentration End] ================="); } - @Redirect(method = "setMode", at = @At(value = "INVOKE", remap = false, target = "Lorg/lwjgl/glfw/GLFW;glfwGetWindowMonitor(J)J")) - private long redirect$glfwGetWindowMonitor(long window) { - return 1L; - } - } \ No newline at end of file diff --git a/forge/src/main/java/net/deechael/concentration/forge/config/ConcentrationConfigForge.java b/forge/src/main/java/net/deechael/concentration/forge/config/ConcentrationConfigForge.java index 12c328b..a4fc8ce 100644 --- a/forge/src/main/java/net/deechael/concentration/forge/config/ConcentrationConfigForge.java +++ b/forge/src/main/java/net/deechael/concentration/forge/config/ConcentrationConfigForge.java @@ -71,6 +71,11 @@ public final class ConcentrationConfigForge implements Config { private ConcentrationConfigForge() { } + @Override + public boolean customized() { + return CUSTOMIZED.get(); + } + @Override public FullscreenMode getFullscreenMode() { return FULLSCREEN.get(); diff --git a/forge/src/main/java/net/deechael/concentration/forge/mixin/WindowMixin.java b/forge/src/main/java/net/deechael/concentration/forge/mixin/WindowMixin.java index 2c00c32..220bbd4 100644 --- a/forge/src/main/java/net/deechael/concentration/forge/mixin/WindowMixin.java +++ b/forge/src/main/java/net/deechael/concentration/forge/mixin/WindowMixin.java @@ -6,8 +6,11 @@ import com.mojang.blaze3d.platform.VideoMode; import com.mojang.blaze3d.platform.Window; import net.deechael.concentration.ConcentrationConstants; import net.deechael.concentration.FullscreenMode; +import net.deechael.concentration.config.Config; import net.deechael.concentration.forge.config.ConcentrationConfigForge; import org.lwjgl.glfw.GLFW; +import org.lwjgl.glfw.GLFWNativeWin32; +import org.lwjgl.system.windows.User32; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; @@ -41,6 +44,9 @@ public abstract class WindowMixin { @Shadow private int height; + @Shadow + @Final + private long window; @Unique private long concentration$lastMonitor = -1; @@ -89,15 +95,17 @@ public abstract class WindowMixin { ConcentrationConstants.LOGGER.info("================= [Concentration Start] ================="); ConcentrationConstants.LOGGER.info("Trying to modify window monitor"); - // Monitor is 0 means the game is windowed mode, so the expression means if is toggling to fullscreen + Monitor monitorInstance = this.screenManager.getMonitor(monitor); + ConcentrationConstants.LOGGER.info("Current fullscreen monitor is {}", monitor); + if (monitor != 0L) { + VideoMode currentMode = monitorInstance.getCurrentMode(); ConcentrationConstants.LOGGER.info("Modifying window size limits"); - GLFW.glfwSetWindowSizeLimits(window, 0, 0, width, height); + GLFW.glfwSetWindowSizeLimits(window, 0, 0, currentMode.getWidth(), currentMode.getHeight()); } - // Because whether in fullscreen mode or windowed mode - // The final step is same - // So I extracted the value then execute the final step + long finalMonitor; + int finalWidth; int finalHeight; @@ -105,97 +113,71 @@ public abstract class WindowMixin { int finalY; if (this.fullscreen) { + VideoMode currentMode = monitorInstance.getCurrentMode(); ConcentrationConfigForge.ensureLoaded(); - // If the game started with fullscreen mode, when switching to windowed mode, it will be forced to move to the primary monitor - // Though size and position isn't be set at initialization, but I think the window should be at the initial monitor - // So save the monitor and use the monitor value when the size isn't cached this.concentration$lastMonitor = monitor; - // Lock caching, because when switching back, the window will be once resized to the maximum value and the cache value will be wrong - // Position won't be affected, so it doesn't need lock this.concentration$cacheSizeLock = true; ConcentrationConstants.LOGGER.info("Locked size caching"); if (ConcentrationConfigForge.FULLSCREEN.get() == FullscreenMode.NATIVE) { ConcentrationConstants.LOGGER.info("Fullscreen mode is native, apply now!"); - GLFW.glfwSetWindowMonitor(window, monitor, xpos, ypos, width, height, -1); - ConcentrationConstants.LOGGER.info("================= [Concentration End] ================="); - return; - } - - ConcentrationConstants.LOGGER.info("Trying to switch to borderless fullscreen mode"); - - // Get the monitor the user want to use and get the relative position in the system - // The monitor is always non-null because when switching fullscreen mode, there must be a monitor to put the window - Monitor monitorInstance = this.screenManager.getMonitor(monitor); - ConcentrationConstants.LOGGER.info("Current fullscreen monitor is {}", monitor); - - // Remove the title bar to prevent that user can see the title bar if they put their monitors vertically connected - GLFW.glfwSetWindowAttrib(window, GLFW.GLFW_DECORATED, GLFW.GLFW_FALSE); - ConcentrationConstants.LOGGER.info("Trying to remove the title bar"); - - if (ConcentrationConfigForge.CUSTOMIZED.get()) { - final boolean related = ConcentrationConfigForge.RELATED.get(); - final int configX = ConcentrationConfigForge.X.get(); - final int configY = ConcentrationConfigForge.Y.get(); - final int configWidth = ConcentrationConfigForge.WIDTH.get(); - final int configHeight = ConcentrationConfigForge.HEIGHT.get(); - - ConcentrationConstants.LOGGER.info("Customization enabled, so replace the fullscreen size with customized size"); - - finalX = configX + (related ? monitorInstance.getX() : 0); - finalY = configY - (configHeight == height ? 1 : 0) + (related ? monitorInstance.getY() : 0); - finalWidth = configWidth; - finalHeight = configHeight + (configHeight == height ? 1 : 0); - } else { - // If we make the window not decorated and set the window size exactly the same with the screen size, it will become native fullscreen mode - // to prevent this, I enlarge the height by 1 pixel and move up the window by 1 pixel which won't affect anything (unless you have a screen - // which is added above the monitor which holds the game) and will have a good experience - // Actually this is a little bit dirty, needs to find a better way to solve it + finalMonitor = monitor; finalX = monitorInstance.getX(); - finalY = monitorInstance.getY() - 1; - finalWidth = width; - finalHeight = height + 1; - } + finalY = monitorInstance.getY(); + finalWidth = currentMode.getWidth(); + finalHeight = currentMode.getHeight(); + } else { + ConcentrationConstants.LOGGER.info("Trying to switch to borderless fullscreen mode"); - this.x = finalX; - this.y = finalY; - this.width = finalWidth; - this.height = finalHeight; + /*if (ConcentrationConfigForge.CUSTOMIZED.get()) { + final boolean related = ConcentrationConfigForge.RELATED.get(); + final int configX = ConcentrationConfigForge.X.get(); + final int configY = ConcentrationConfigForge.Y.get(); + final int configWidth = ConcentrationConfigForge.WIDTH.get(); + final int configHeight = ConcentrationConfigForge.HEIGHT.get(); + + ConcentrationConstants.LOGGER.info("Customization enabled, so replace the fullscreen size with customized size"); + + finalX = configX + (related ? monitorInstance.getX() : 0); + finalY = configY - (configHeight == height ? 1 : 0) + (related ? monitorInstance.getY() : 0); + finalWidth = configWidth; + finalHeight = configHeight + (configHeight == height ? 1 : 0); + } else */ + { + finalMonitor = monitor; + finalX = monitorInstance.getX(); + finalY = monitorInstance.getY(); + finalWidth = currentMode.getWidth(); + finalHeight = currentMode.getHeight(); + } + this.x = finalX; + this.y = finalY; + this.width = finalWidth; + this.height = finalHeight; + } } else { ConcentrationConstants.LOGGER.info("Trying to switch to windowed mode"); - - // Re-add the title bar so user can move the window and minimize, maximize and close the window - ConcentrationConstants.LOGGER.info("Trying to add title bar back"); - GLFW.glfwSetWindowAttrib(window, GLFW.GLFW_DECORATED, GLFW.GLFW_TRUE); + finalMonitor = 0L; ConcentrationConstants.LOGGER.info("Trying to use cached value to resize the window"); - // Make sure that Concentration has cached position and size, because position size won't be cached when the game starting in fullscreen mode finalWidth = concentration$cachedSize ? concentration$cachedWidth : width; finalHeight = concentration$cachedSize ? concentration$cachedHeight : height; - // To make sure that even starting with fullscreen mode can also make the window stay at the current monitor - // So I set two ways to ensure the position if (this.concentration$cachedPos) { - // If Concentration cached the pos, use the cached value finalX = concentration$cachedX; finalY = concentration$cachedY; - } else if (this.concentration$lastMonitor != -1) { - // or else maybe the game started with fullscreen mode, so I don't need to care about the size - // only need to make sure that the position is in the correct monitor - Monitor monitorInstance = this.screenManager.getMonitor(this.concentration$lastMonitor); - VideoMode videoMode = monitorInstance.getCurrentMode(); + } else if (this.concentration$lastMonitor != -1 && this.screenManager.getMonitor(this.concentration$lastMonitor) != null) { + Monitor lastMonitor = this.screenManager.getMonitor(this.concentration$lastMonitor); + VideoMode videoMode = lastMonitor.getCurrentMode(); finalX = (videoMode.getWidth() - finalWidth) / 2; finalY = (videoMode.getHeight() - finalHeight) / 2; } else { - // if both value are missed, use the default value to prevent errors finalX = xpos; finalY = ypos; } - - // Unlock caching, because user can change the window size now this.concentration$cacheSizeLock = false; ConcentrationConstants.LOGGER.info("Unlocked size caching"); } @@ -203,14 +185,32 @@ public abstract class WindowMixin { ConcentrationConstants.LOGGER.info("Window size: {}, {}, position: {}, {}", finalWidth, finalHeight, finalX, finalY); ConcentrationConstants.LOGGER.info("Trying to resize and reposition the window"); - GLFW.glfwSetWindowMonitor(window, 0L, finalX, finalY, finalWidth, finalHeight, -1); + GLFW.glfwSetWindowMonitor(window, finalMonitor, finalX, finalY, finalWidth, finalHeight, -1); + + if (this.fullscreen && !(Config.isBorderless() && Config.isCustomized())) { + GLFW.glfwSetWindowAttrib(this.window, 0x20006, 1); + + long hWnd = GLFWNativeWin32.glfwGetWin32Window(this.window); + if (hWnd != 0) { + User32.SetWindowPos(hWnd, User32.HWND_TOPMOST, this.x, this.y, this.width, this.height, 1027); + User32.SetWindowLongPtr(hWnd, -16, 0x960A0000L); + User32.SetWindowLongPtr(hWnd, -20, 0x40010L); + } + + if (Config.isBorderless()) { + GLFW.glfwSetWindowAttrib(this.window, 0x20006, 0); + + if (System.getProperty("os.name").contains("Windows")) { + if (hWnd != 0) { + User32.SetWindowPos(hWnd, User32.HWND_NOTOPMOST, this.x, this.y, this.width, this.height, 1027); + User32.SetWindowLongPtr(hWnd, -16, 369229824); + User32.SetWindowLongPtr(hWnd, -20, 34340880); + } + } + } + } ConcentrationConstants.LOGGER.info("================= [Concentration End] ================="); } - @Redirect(method = "setMode", at = @At(value = "INVOKE", remap = false, target = "Lorg/lwjgl/glfw/GLFW;glfwGetWindowMonitor(J)J")) - private long redirect$glfwGetWindowMonitor(long window) { - return 1L; - } - } \ No newline at end of file diff --git a/gradle.properties b/gradle.properties index d59d83e..b60df2e 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,4 @@ -version=2.0.1 +version=2.1.0 group=net.deechael.concentration java_version=21 diff --git a/neoforge/src/main/java/net/deechael/concentration/neoforge/ConcentrationNeoForge.java b/neoforge/src/main/java/net/deechael/concentration/neoforge/ConcentrationNeoForge.java index b59107d..2a19b47 100644 --- a/neoforge/src/main/java/net/deechael/concentration/neoforge/ConcentrationNeoForge.java +++ b/neoforge/src/main/java/net/deechael/concentration/neoforge/ConcentrationNeoForge.java @@ -5,7 +5,6 @@ import net.deechael.concentration.ConcentrationConstants; import net.deechael.concentration.config.ConcentrationConfigScreen; import net.deechael.concentration.neoforge.compat.EmbeddiumCompat; import net.deechael.concentration.neoforge.config.ConcentrationConfigNeoForge; -import net.minecraft.client.Minecraft; import net.minecraft.client.OptionInstance; import net.minecraft.client.gui.screens.Screen; import net.minecraft.network.chat.Component; diff --git a/neoforge/src/main/java/net/deechael/concentration/neoforge/ConcentrationNeoForgeMixinPlugin.java b/neoforge/src/main/java/net/deechael/concentration/neoforge/ConcentrationNeoForgeMixinPlugin.java index acd2a82..5fc02cc 100644 --- a/neoforge/src/main/java/net/deechael/concentration/neoforge/ConcentrationNeoForgeMixinPlugin.java +++ b/neoforge/src/main/java/net/deechael/concentration/neoforge/ConcentrationNeoForgeMixinPlugin.java @@ -26,8 +26,8 @@ public class ConcentrationNeoForgeMixinPlugin implements IMixinConfigPlugin { @Override public boolean shouldApplyMixin(String targetClassName, String mixinClassName) { - return mixinClassName.equals("net.deechael.concentration.fabric.mixin.WindowMixin") - || (!ModList.get().isLoaded("embeddium") && checkSodium(mixinClassName)); + return mixinClassName.equals("net.deechael.concentration.fabric.mixin.WindowMixin") + || (!ModList.get().isLoaded("embeddium") && checkSodium(mixinClassName)); } @Override diff --git a/neoforge/src/main/java/net/deechael/concentration/neoforge/config/ConcentrationConfigNeoForge.java b/neoforge/src/main/java/net/deechael/concentration/neoforge/config/ConcentrationConfigNeoForge.java index ed54da0..1b64baf 100644 --- a/neoforge/src/main/java/net/deechael/concentration/neoforge/config/ConcentrationConfigNeoForge.java +++ b/neoforge/src/main/java/net/deechael/concentration/neoforge/config/ConcentrationConfigNeoForge.java @@ -1,15 +1,9 @@ package net.deechael.concentration.neoforge.config; -import com.electronwill.nightconfig.core.file.CommentedFileConfig; -import com.electronwill.nightconfig.core.io.WritingMode; -import net.deechael.concentration.ConcentrationConstants; import net.deechael.concentration.FullscreenMode; import net.deechael.concentration.config.Config; -import net.neoforged.fml.loading.FMLPaths; import net.neoforged.neoforge.common.ModConfigSpec; -import java.nio.file.Path; - public final class ConcentrationConfigNeoForge implements Config { public final static ConcentrationConfigNeoForge INSTANCE = new ConcentrationConfigNeoForge(); @@ -71,6 +65,11 @@ public final class ConcentrationConfigNeoForge implements Config { private ConcentrationConfigNeoForge() { } + @Override + public boolean customized() { + return CUSTOMIZED.get(); + } + @Override public FullscreenMode getFullscreenMode() { return FULLSCREEN.get(); diff --git a/neoforge/src/main/java/net/deechael/concentration/neoforge/mixin/WindowMixin.java b/neoforge/src/main/java/net/deechael/concentration/neoforge/mixin/WindowMixin.java index 9126427..d19ca40 100644 --- a/neoforge/src/main/java/net/deechael/concentration/neoforge/mixin/WindowMixin.java +++ b/neoforge/src/main/java/net/deechael/concentration/neoforge/mixin/WindowMixin.java @@ -6,8 +6,11 @@ import com.mojang.blaze3d.platform.VideoMode; import com.mojang.blaze3d.platform.Window; import net.deechael.concentration.ConcentrationConstants; import net.deechael.concentration.FullscreenMode; +import net.deechael.concentration.config.Config; import net.deechael.concentration.neoforge.config.ConcentrationConfigNeoForge; import org.lwjgl.glfw.GLFW; +import org.lwjgl.glfw.GLFWNativeWin32; +import org.lwjgl.system.windows.User32; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; @@ -41,6 +44,9 @@ public abstract class WindowMixin { @Shadow private int height; + @Shadow + @Final + private long window; @Unique private long concentration$lastMonitor = -1; @@ -89,15 +95,17 @@ public abstract class WindowMixin { ConcentrationConstants.LOGGER.info("================= [Concentration Start] ================="); ConcentrationConstants.LOGGER.info("Trying to modify window monitor"); - // Monitor is 0 means the game is windowed mode, so the expression means if is toggling to fullscreen + Monitor monitorInstance = this.screenManager.getMonitor(monitor); + ConcentrationConstants.LOGGER.info("Current fullscreen monitor is {}", monitor); + if (monitor != 0L) { + VideoMode currentMode = monitorInstance.getCurrentMode(); ConcentrationConstants.LOGGER.info("Modifying window size limits"); - GLFW.glfwSetWindowSizeLimits(window, 0, 0, width, height); + GLFW.glfwSetWindowSizeLimits(window, 0, 0, currentMode.getWidth(), currentMode.getHeight()); } - // Because whether in fullscreen mode or windowed mode - // The final step is same - // So I extracted the value then execute the final step + long finalMonitor; + int finalWidth; int finalHeight; @@ -105,97 +113,71 @@ public abstract class WindowMixin { int finalY; if (this.fullscreen) { + VideoMode currentMode = monitorInstance.getCurrentMode(); ConcentrationConfigNeoForge.ensureLoaded(); - // If the game started with fullscreen mode, when switching to windowed mode, it will be forced to move to the primary monitor - // Though size and position isn't be set at initialization, but I think the window should be at the initial monitor - // So save the monitor and use the monitor value when the size isn't cached this.concentration$lastMonitor = monitor; - // Lock caching, because when switching back, the window will be once resized to the maximum value and the cache value will be wrong - // Position won't be affected, so it doesn't need lock this.concentration$cacheSizeLock = true; ConcentrationConstants.LOGGER.info("Locked size caching"); if (ConcentrationConfigNeoForge.FULLSCREEN.get() == FullscreenMode.NATIVE) { ConcentrationConstants.LOGGER.info("Fullscreen mode is native, apply now!"); - GLFW.glfwSetWindowMonitor(window, monitor, xpos, ypos, width, height, -1); - ConcentrationConstants.LOGGER.info("================= [Concentration End] ================="); - return; - } - - ConcentrationConstants.LOGGER.info("Trying to switch to borderless fullscreen mode"); - - // Get the monitor the user want to use and get the relative position in the system - // The monitor is always non-null because when switching fullscreen mode, there must be a monitor to put the window - Monitor monitorInstance = this.screenManager.getMonitor(monitor); - ConcentrationConstants.LOGGER.info("Current fullscreen monitor is {}", monitor); - - // Remove the title bar to prevent that user can see the title bar if they put their monitors vertically connected - GLFW.glfwSetWindowAttrib(window, GLFW.GLFW_DECORATED, GLFW.GLFW_FALSE); - ConcentrationConstants.LOGGER.info("Trying to remove the title bar"); - - if (ConcentrationConfigNeoForge.CUSTOMIZED.get()) { - final boolean related = ConcentrationConfigNeoForge.RELATED.get(); - final int configX = ConcentrationConfigNeoForge.X.get(); - final int configY = ConcentrationConfigNeoForge.Y.get(); - final int configWidth = ConcentrationConfigNeoForge.WIDTH.get(); - final int configHeight = ConcentrationConfigNeoForge.HEIGHT.get(); - - ConcentrationConstants.LOGGER.info("Customization enabled, so replace the fullscreen size with customized size"); - - finalX = configX + (related ? monitorInstance.getX() : 0); - finalY = configY - (configHeight == height ? 1 : 0) + (related ? monitorInstance.getY() : 0); - finalWidth = configWidth; - finalHeight = configHeight + (configHeight == height ? 1 : 0); - } else { - // If we make the window not decorated and set the window size exactly the same with the screen size, it will become native fullscreen mode - // to prevent this, I enlarge the height by 1 pixel and move up the window by 1 pixel which won't affect anything (unless you have a screen - // which is added above the monitor which holds the game) and will have a good experience - // Actually this is a little bit dirty, needs to find a better way to solve it + finalMonitor = monitor; finalX = monitorInstance.getX(); - finalY = monitorInstance.getY() - 1; - finalWidth = width; - finalHeight = height + 1; - } + finalY = monitorInstance.getY(); + finalWidth = currentMode.getWidth(); + finalHeight = currentMode.getHeight(); + } else { + ConcentrationConstants.LOGGER.info("Trying to switch to borderless fullscreen mode"); - this.x = finalX; - this.y = finalY; - this.width = finalWidth; - this.height = finalHeight; + /*if (ConcentrationConfigForge.CUSTOMIZED.get()) { + final boolean related = ConcentrationConfigForge.RELATED.get(); + final int configX = ConcentrationConfigForge.X.get(); + final int configY = ConcentrationConfigForge.Y.get(); + final int configWidth = ConcentrationConfigForge.WIDTH.get(); + final int configHeight = ConcentrationConfigForge.HEIGHT.get(); + + ConcentrationConstants.LOGGER.info("Customization enabled, so replace the fullscreen size with customized size"); + + finalX = configX + (related ? monitorInstance.getX() : 0); + finalY = configY - (configHeight == height ? 1 : 0) + (related ? monitorInstance.getY() : 0); + finalWidth = configWidth; + finalHeight = configHeight + (configHeight == height ? 1 : 0); + } else */ + { + finalMonitor = monitor; + finalX = monitorInstance.getX(); + finalY = monitorInstance.getY(); + finalWidth = currentMode.getWidth(); + finalHeight = currentMode.getHeight(); + } + this.x = finalX; + this.y = finalY; + this.width = finalWidth; + this.height = finalHeight; + } } else { ConcentrationConstants.LOGGER.info("Trying to switch to windowed mode"); - - // Re-add the title bar so user can move the window and minimize, maximize and close the window - ConcentrationConstants.LOGGER.info("Trying to add title bar back"); - GLFW.glfwSetWindowAttrib(window, GLFW.GLFW_DECORATED, GLFW.GLFW_TRUE); + finalMonitor = 0L; ConcentrationConstants.LOGGER.info("Trying to use cached value to resize the window"); - // Make sure that Concentration has cached position and size, because position size won't be cached when the game starting in fullscreen mode finalWidth = concentration$cachedSize ? concentration$cachedWidth : width; finalHeight = concentration$cachedSize ? concentration$cachedHeight : height; - // To make sure that even starting with fullscreen mode can also make the window stay at the current monitor - // So I set two ways to ensure the position if (this.concentration$cachedPos) { - // If Concentration cached the pos, use the cached value finalX = concentration$cachedX; finalY = concentration$cachedY; - } else if (this.concentration$lastMonitor != -1) { - // or else maybe the game started with fullscreen mode, so I don't need to care about the size - // only need to make sure that the position is in the correct monitor - Monitor monitorInstance = this.screenManager.getMonitor(this.concentration$lastMonitor); - VideoMode videoMode = monitorInstance.getCurrentMode(); + } else if (this.concentration$lastMonitor != -1 && this.screenManager.getMonitor(this.concentration$lastMonitor) != null) { + Monitor lastMonitor = this.screenManager.getMonitor(this.concentration$lastMonitor); + VideoMode videoMode = lastMonitor.getCurrentMode(); finalX = (videoMode.getWidth() - finalWidth) / 2; finalY = (videoMode.getHeight() - finalHeight) / 2; } else { - // if both value are missed, use the default value to prevent errors finalX = xpos; finalY = ypos; } - - // Unlock caching, because user can change the window size now this.concentration$cacheSizeLock = false; ConcentrationConstants.LOGGER.info("Unlocked size caching"); } @@ -203,14 +185,32 @@ public abstract class WindowMixin { ConcentrationConstants.LOGGER.info("Window size: {}, {}, position: {}, {}", finalWidth, finalHeight, finalX, finalY); ConcentrationConstants.LOGGER.info("Trying to resize and reposition the window"); - GLFW.glfwSetWindowMonitor(window, 0L, finalX, finalY, finalWidth, finalHeight, -1); + GLFW.glfwSetWindowMonitor(window, finalMonitor, finalX, finalY, finalWidth, finalHeight, -1); + + if (this.fullscreen && !(Config.isBorderless() && Config.isCustomized())) { + GLFW.glfwSetWindowAttrib(this.window, 0x20006, 1); + + long hWnd = GLFWNativeWin32.glfwGetWin32Window(this.window); + if (hWnd != 0) { + User32.SetWindowPos(hWnd, User32.HWND_TOPMOST, this.x, this.y, this.width, this.height, 1027); + User32.SetWindowLongPtr(hWnd, -16, 0x960A0000L); + User32.SetWindowLongPtr(hWnd, -20, 0x40010L); + } + + if (Config.isBorderless()) { + GLFW.glfwSetWindowAttrib(this.window, 0x20006, 0); + + if (System.getProperty("os.name").contains("Windows")) { + if (hWnd != 0) { + User32.SetWindowPos(hWnd, User32.HWND_NOTOPMOST, this.x, this.y, this.width, this.height, 1027); + User32.SetWindowLongPtr(hWnd, -16, 369229824); + User32.SetWindowLongPtr(hWnd, -20, 34340880); + } + } + } + } ConcentrationConstants.LOGGER.info("================= [Concentration End] ================="); } - @Redirect(method = "setMode", at = @At(value = "INVOKE", remap = false, target = "Lorg/lwjgl/glfw/GLFW;glfwGetWindowMonitor(J)J")) - private long redirect$glfwGetWindowMonitor(long window) { - return 1L; - } - } \ No newline at end of file