refactor: replaced dirty solution with real exclusive fullscreen
This commit is contained in:
parent
4fc4ee149e
commit
87f924ce8e
@ -4,10 +4,20 @@ import net.deechael.concentration.FullscreenMode;
|
|||||||
|
|
||||||
public interface Config {
|
public interface Config {
|
||||||
|
|
||||||
|
boolean customized();
|
||||||
|
|
||||||
FullscreenMode getFullscreenMode();
|
FullscreenMode getFullscreenMode();
|
||||||
|
|
||||||
void setFullscreenMode(FullscreenMode fullscreenMode);
|
void setFullscreenMode(FullscreenMode fullscreenMode);
|
||||||
|
|
||||||
void save();
|
void save();
|
||||||
|
|
||||||
|
static boolean isBorderless() {
|
||||||
|
return ConfigProvider.INSTANCE.ensureLoaded().getFullscreenMode() == FullscreenMode.BORDERLESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static boolean isCustomized() {
|
||||||
|
return ConfigProvider.INSTANCE.ensureLoaded().customized();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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 {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -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() {
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -7,6 +7,7 @@
|
|||||||
"mixins": [],
|
"mixins": [],
|
||||||
"client": [
|
"client": [
|
||||||
"KeyboardHandlerMixin",
|
"KeyboardHandlerMixin",
|
||||||
|
"MainMixin",
|
||||||
"VideoSettingsScreenMixin",
|
"VideoSettingsScreenMixin",
|
||||||
"accessor.WindowAccessor"
|
"accessor.WindowAccessor"
|
||||||
],
|
],
|
||||||
|
@ -43,6 +43,11 @@ public class ConcentrationConfigFabric implements Config {
|
|||||||
public int height = 600;
|
public int height = 600;
|
||||||
public FullscreenMode fullscreen = FullscreenMode.BORDERLESS;
|
public FullscreenMode fullscreen = FullscreenMode.BORDERLESS;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean customized() {
|
||||||
|
return this.customized;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public FullscreenMode getFullscreenMode() {
|
public FullscreenMode getFullscreenMode() {
|
||||||
return this.fullscreen;
|
return this.fullscreen;
|
||||||
|
@ -5,12 +5,16 @@ import com.mojang.blaze3d.platform.VideoMode;
|
|||||||
import com.mojang.blaze3d.platform.Window;
|
import com.mojang.blaze3d.platform.Window;
|
||||||
import net.deechael.concentration.ConcentrationConstants;
|
import net.deechael.concentration.ConcentrationConstants;
|
||||||
import net.deechael.concentration.FullscreenMode;
|
import net.deechael.concentration.FullscreenMode;
|
||||||
|
import net.deechael.concentration.config.Config;
|
||||||
import net.deechael.concentration.fabric.ConcentrationFabricCaching;
|
import net.deechael.concentration.fabric.ConcentrationFabricCaching;
|
||||||
import net.deechael.concentration.fabric.config.ConcentrationConfigFabric;
|
import net.deechael.concentration.fabric.config.ConcentrationConfigFabric;
|
||||||
import net.deechael.concentration.mixin.accessor.WindowAccessor;
|
import net.deechael.concentration.mixin.accessor.WindowAccessor;
|
||||||
import net.minecraft.client.Minecraft;
|
import net.minecraft.client.Minecraft;
|
||||||
import org.lwjgl.glfw.GLFW;
|
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.Mixin;
|
||||||
|
import org.spongepowered.asm.mixin.Unique;
|
||||||
import org.spongepowered.asm.mixin.injection.At;
|
import org.spongepowered.asm.mixin.injection.At;
|
||||||
import org.spongepowered.asm.mixin.injection.Inject;
|
import org.spongepowered.asm.mixin.injection.Inject;
|
||||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||||
@ -27,112 +31,94 @@ public class GLFWMixin {
|
|||||||
ConcentrationConstants.LOGGER.info("================= [Concentration Start] =================");
|
ConcentrationConstants.LOGGER.info("================= [Concentration Start] =================");
|
||||||
ConcentrationConstants.LOGGER.info("Trying to modify window monitor");
|
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) {
|
if (monitor != 0L) {
|
||||||
|
VideoMode currentMode = monitorInstance.getCurrentMode();
|
||||||
ConcentrationConstants.LOGGER.info("Modifying window size limits");
|
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
|
long finalMonitor;
|
||||||
// The final step is same
|
|
||||||
// So I extracted the value then execute the final step
|
|
||||||
int finalWidth;
|
int finalWidth;
|
||||||
int finalHeight;
|
int finalHeight;
|
||||||
|
|
||||||
int finalX;
|
int finalX;
|
||||||
int finalY;
|
int finalY;
|
||||||
|
|
||||||
Window windowInstance = Minecraft.getInstance().getWindow();
|
|
||||||
WindowAccessor accessor = (WindowAccessor) (Object) windowInstance;
|
|
||||||
|
|
||||||
if (windowInstance != null && windowInstance.isFullscreen()) {
|
if (windowInstance != null && windowInstance.isFullscreen()) {
|
||||||
|
VideoMode currentMode = monitorInstance.getCurrentMode();
|
||||||
|
|
||||||
ConcentrationConfigFabric config = ConcentrationConfigFabric.getInstance();
|
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;
|
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;
|
ConcentrationFabricCaching.cacheSizeLock = true;
|
||||||
ConcentrationConstants.LOGGER.info("Locked size caching");
|
ConcentrationConstants.LOGGER.info("Locked size caching");
|
||||||
|
|
||||||
if (config.fullscreen == FullscreenMode.NATIVE) {
|
if (config.fullscreen == FullscreenMode.NATIVE) {
|
||||||
ConcentrationConstants.LOGGER.info("Fullscreen mode is native, apply now!");
|
ConcentrationConstants.LOGGER.info("Fullscreen mode is native, apply now!");
|
||||||
if (monitor == 0L)
|
finalMonitor = monitor;
|
||||||
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
|
|
||||||
finalX = monitorInstance.getX();
|
finalX = monitorInstance.getX();
|
||||||
finalY = monitorInstance.getY() - 1;
|
finalY = monitorInstance.getY();
|
||||||
finalWidth = width;
|
finalWidth = currentMode.getWidth();
|
||||||
finalHeight = height + 1;
|
finalHeight = currentMode.getHeight();
|
||||||
}
|
ConcentrationConstants.LOGGER.info("================= [Concentration End] =================");
|
||||||
|
} else {
|
||||||
|
ConcentrationConstants.LOGGER.info("Trying to switch to borderless fullscreen mode");
|
||||||
|
|
||||||
accessor.setX(finalX);
|
/*if (ConcentrationConfigFabric.getInstance().customized) {
|
||||||
accessor.setY(finalY);
|
ConcentrationConstants.LOGGER.info("Customization enabled, so replace the fullscreen size with customized size");
|
||||||
accessor.setWidth(finalWidth);
|
finalX = config.x + (config.related ? monitorInstance.getX() : 0);
|
||||||
accessor.setHeight(finalHeight);
|
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 {
|
} else {
|
||||||
ConcentrationConstants.LOGGER.info("Trying to switch to windowed mode");
|
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
|
finalMonitor = 0L;
|
||||||
ConcentrationConstants.LOGGER.info("Trying to add title bar back");
|
|
||||||
GLFW.glfwSetWindowAttrib(window, GLFW.GLFW_DECORATED, GLFW.GLFW_TRUE);
|
|
||||||
|
|
||||||
ConcentrationConstants.LOGGER.info("Trying to use cached value to resize the window");
|
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;
|
finalWidth = ConcentrationFabricCaching.cachedSize ? ConcentrationFabricCaching.cachedWidth : width;
|
||||||
finalHeight = ConcentrationFabricCaching.cachedSize ? ConcentrationFabricCaching.cachedHeight : height;
|
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 (ConcentrationFabricCaching.cachedPos) {
|
||||||
// If Concentration cached the pos, use the cached value
|
|
||||||
finalX = ConcentrationFabricCaching.cachedX;
|
finalX = ConcentrationFabricCaching.cachedX;
|
||||||
finalY = ConcentrationFabricCaching.cachedY;
|
finalY = ConcentrationFabricCaching.cachedY;
|
||||||
} else if (ConcentrationFabricCaching.lastMonitor != -1) {
|
} else if (ConcentrationFabricCaching.lastMonitor != -1) {
|
||||||
// or else maybe the game started with fullscreen mode, so I don't need to care about the size
|
Monitor lastMonitor = accessor.getScreenManager().getMonitor(ConcentrationFabricCaching.lastMonitor);
|
||||||
// only need to make sure that the position is in the correct monitor
|
VideoMode videoMode = lastMonitor.getCurrentMode();
|
||||||
Monitor monitorInstance = accessor.getScreenManager().getMonitor(ConcentrationFabricCaching.lastMonitor);
|
|
||||||
VideoMode videoMode = monitorInstance.getCurrentMode();
|
|
||||||
finalX = (videoMode.getWidth() - finalWidth) / 2;
|
finalX = (videoMode.getWidth() - finalWidth) / 2;
|
||||||
finalY = (videoMode.getHeight() - finalHeight) / 2;
|
finalY = (videoMode.getHeight() - finalHeight) / 2;
|
||||||
} else {
|
} else {
|
||||||
// if both value are missed, use the default value to prevent errors
|
|
||||||
finalX = xpos;
|
finalX = xpos;
|
||||||
finalY = ypos;
|
finalY = ypos;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unlock caching, because user can change the window size now
|
|
||||||
ConcentrationFabricCaching.cacheSizeLock = false;
|
ConcentrationFabricCaching.cacheSizeLock = false;
|
||||||
ConcentrationConstants.LOGGER.info("Unlocked size caching");
|
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("Window size: {}, {}, position: {}, {}", finalWidth, finalHeight, finalX, finalY);
|
||||||
|
|
||||||
ConcentrationConstants.LOGGER.info("Trying to resize and reposition the window");
|
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] =================");
|
ConcentrationConstants.LOGGER.info("================= [Concentration End] =================");
|
||||||
ci.cancel();
|
ci.cancel();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Unique
|
||||||
private static void finalExecute(long window, long monitor, int xpos, int ypos, int width, int height, int refreshRate) {
|
private static void finalExecute(long window, long monitor, int xpos, int ypos, int width, int height, int refreshRate) {
|
||||||
long __functionAddress = GLFW.Functions.SetWindowMonitor;
|
long __functionAddress = GLFW.Functions.SetWindowMonitor;
|
||||||
if (CHECKS) {
|
if (CHECKS) {
|
||||||
|
@ -6,9 +6,12 @@ import com.mojang.blaze3d.platform.VideoMode;
|
|||||||
import com.mojang.blaze3d.platform.Window;
|
import com.mojang.blaze3d.platform.Window;
|
||||||
import net.deechael.concentration.ConcentrationConstants;
|
import net.deechael.concentration.ConcentrationConstants;
|
||||||
import net.deechael.concentration.FullscreenMode;
|
import net.deechael.concentration.FullscreenMode;
|
||||||
|
import net.deechael.concentration.config.Config;
|
||||||
import net.deechael.concentration.fabric.ConcentrationFabricCaching;
|
import net.deechael.concentration.fabric.ConcentrationFabricCaching;
|
||||||
import net.deechael.concentration.fabric.config.ConcentrationConfigFabric;
|
import net.deechael.concentration.fabric.config.ConcentrationConfigFabric;
|
||||||
import org.lwjgl.glfw.GLFW;
|
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.Final;
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
import org.spongepowered.asm.mixin.Shadow;
|
import org.spongepowered.asm.mixin.Shadow;
|
||||||
@ -41,6 +44,10 @@ public abstract class WindowMixin {
|
|||||||
@Shadow
|
@Shadow
|
||||||
private int height;
|
private int height;
|
||||||
|
|
||||||
|
@Shadow
|
||||||
|
@Final
|
||||||
|
private long window;
|
||||||
|
|
||||||
@Inject(method = "onMove", at = @At("HEAD"))
|
@Inject(method = "onMove", at = @At("HEAD"))
|
||||||
private void inject$onMove$head(long window, int x, int y, CallbackInfo ci) {
|
private void inject$onMove$head(long window, int x, int y, CallbackInfo ci) {
|
||||||
if (!this.fullscreen) {
|
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"))
|
@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("================= [Concentration Start] =================");
|
||||||
ConcentrationConstants.LOGGER.info("Trying to modify window monitor");
|
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) {
|
if (monitor != 0L) {
|
||||||
|
VideoMode currentMode = monitorInstance.getCurrentMode();
|
||||||
ConcentrationConstants.LOGGER.info("Modifying window size limits");
|
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
|
long finalMonitor;
|
||||||
// The final step is same
|
|
||||||
// So I extracted the value then execute the final step
|
|
||||||
int finalWidth;
|
int finalWidth;
|
||||||
int finalHeight;
|
int finalHeight;
|
||||||
|
|
||||||
@ -86,90 +95,67 @@ public abstract class WindowMixin {
|
|||||||
int finalY;
|
int finalY;
|
||||||
|
|
||||||
if (this.fullscreen) {
|
if (this.fullscreen) {
|
||||||
|
VideoMode currentMode = monitorInstance.getCurrentMode();
|
||||||
|
|
||||||
ConcentrationConfigFabric config = ConcentrationConfigFabric.getInstance();
|
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;
|
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;
|
ConcentrationFabricCaching.cacheSizeLock = true;
|
||||||
ConcentrationConstants.LOGGER.info("Locked size caching");
|
ConcentrationConstants.LOGGER.info("Locked size caching");
|
||||||
|
|
||||||
if (config.fullscreen == FullscreenMode.NATIVE) {
|
if (config.fullscreen == FullscreenMode.NATIVE) {
|
||||||
ConcentrationConstants.LOGGER.info("Fullscreen mode is native, apply now!");
|
ConcentrationConstants.LOGGER.info("Fullscreen mode is native");
|
||||||
GLFW.glfwSetWindowMonitor(window, monitor, xpos, ypos, width, height, -1);
|
finalMonitor = monitor;
|
||||||
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
|
|
||||||
finalX = monitorInstance.getX();
|
finalX = monitorInstance.getX();
|
||||||
finalY = monitorInstance.getY() - 1;
|
finalY = monitorInstance.getY();
|
||||||
finalWidth = width;
|
finalWidth = currentMode.getWidth();
|
||||||
finalHeight = height + 1;
|
finalHeight = currentMode.getHeight();
|
||||||
}
|
} else {
|
||||||
|
ConcentrationConstants.LOGGER.info("Trying to switch to borderless fullscreen mode");
|
||||||
|
|
||||||
this.x = finalX;
|
/*if (ConcentrationConfigFabric.getInstance().customized) {
|
||||||
this.y = finalY;
|
GLFW.glfwSetWindowAttrib(window, GLFW.GLFW_DECORATED, GLFW.GLFW_FALSE);
|
||||||
this.width = finalWidth;
|
finalMonitor = 0L;
|
||||||
this.height = finalHeight;
|
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 {
|
} else {
|
||||||
ConcentrationConstants.LOGGER.info("Trying to switch to windowed mode");
|
ConcentrationConstants.LOGGER.info("Trying to switch to windowed mode");
|
||||||
|
finalMonitor = 0L;
|
||||||
// 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);
|
|
||||||
|
|
||||||
ConcentrationConstants.LOGGER.info("Trying to use cached value to resize the window");
|
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;
|
finalWidth = ConcentrationFabricCaching.cachedSize ? ConcentrationFabricCaching.cachedWidth : width;
|
||||||
finalHeight = ConcentrationFabricCaching.cachedSize ? ConcentrationFabricCaching.cachedHeight : height;
|
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 (ConcentrationFabricCaching.cachedPos) {
|
||||||
// If Concentration cached the pos, use the cached value
|
|
||||||
finalX = ConcentrationFabricCaching.cachedX;
|
finalX = ConcentrationFabricCaching.cachedX;
|
||||||
finalY = ConcentrationFabricCaching.cachedY;
|
finalY = ConcentrationFabricCaching.cachedY;
|
||||||
} else if (ConcentrationFabricCaching.lastMonitor != -1) {
|
} else if (ConcentrationFabricCaching.lastMonitor != -1 && this.screenManager.getMonitor(ConcentrationFabricCaching.lastMonitor) != null) {
|
||||||
// or else maybe the game started with fullscreen mode, so I don't need to care about the size
|
Monitor lastMonitor = this.screenManager.getMonitor(ConcentrationFabricCaching.lastMonitor);
|
||||||
// only need to make sure that the position is in the correct monitor
|
VideoMode videoMode = lastMonitor.getCurrentMode();
|
||||||
Monitor monitorInstance = this.screenManager.getMonitor(ConcentrationFabricCaching.lastMonitor);
|
|
||||||
VideoMode videoMode = monitorInstance.getCurrentMode();
|
|
||||||
finalX = (videoMode.getWidth() - finalWidth) / 2;
|
finalX = (videoMode.getWidth() - finalWidth) / 2;
|
||||||
finalY = (videoMode.getHeight() - finalHeight) / 2;
|
finalY = (videoMode.getHeight() - finalHeight) / 2;
|
||||||
} else {
|
} else {
|
||||||
// if both value are missed, use the default value to prevent errors
|
|
||||||
finalX = xpos;
|
finalX = xpos;
|
||||||
finalY = ypos;
|
finalY = ypos;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unlock caching, because user can change the window size now
|
|
||||||
ConcentrationFabricCaching.cacheSizeLock = false;
|
ConcentrationFabricCaching.cacheSizeLock = false;
|
||||||
ConcentrationConstants.LOGGER.info("Unlocked size caching");
|
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("Window size: {}, {}, position: {}, {}", finalWidth, finalHeight, finalX, finalY);
|
||||||
|
|
||||||
ConcentrationConstants.LOGGER.info("Trying to resize and reposition the window");
|
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] =================");
|
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
@ -71,6 +71,11 @@ public final class ConcentrationConfigForge implements Config {
|
|||||||
private ConcentrationConfigForge() {
|
private ConcentrationConfigForge() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean customized() {
|
||||||
|
return CUSTOMIZED.get();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public FullscreenMode getFullscreenMode() {
|
public FullscreenMode getFullscreenMode() {
|
||||||
return FULLSCREEN.get();
|
return FULLSCREEN.get();
|
||||||
|
@ -6,8 +6,11 @@ import com.mojang.blaze3d.platform.VideoMode;
|
|||||||
import com.mojang.blaze3d.platform.Window;
|
import com.mojang.blaze3d.platform.Window;
|
||||||
import net.deechael.concentration.ConcentrationConstants;
|
import net.deechael.concentration.ConcentrationConstants;
|
||||||
import net.deechael.concentration.FullscreenMode;
|
import net.deechael.concentration.FullscreenMode;
|
||||||
|
import net.deechael.concentration.config.Config;
|
||||||
import net.deechael.concentration.forge.config.ConcentrationConfigForge;
|
import net.deechael.concentration.forge.config.ConcentrationConfigForge;
|
||||||
import org.lwjgl.glfw.GLFW;
|
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.Final;
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
import org.spongepowered.asm.mixin.Shadow;
|
import org.spongepowered.asm.mixin.Shadow;
|
||||||
@ -41,6 +44,9 @@ public abstract class WindowMixin {
|
|||||||
@Shadow
|
@Shadow
|
||||||
private int height;
|
private int height;
|
||||||
|
|
||||||
|
@Shadow
|
||||||
|
@Final
|
||||||
|
private long window;
|
||||||
@Unique
|
@Unique
|
||||||
private long concentration$lastMonitor = -1;
|
private long concentration$lastMonitor = -1;
|
||||||
|
|
||||||
@ -89,15 +95,17 @@ public abstract class WindowMixin {
|
|||||||
ConcentrationConstants.LOGGER.info("================= [Concentration Start] =================");
|
ConcentrationConstants.LOGGER.info("================= [Concentration Start] =================");
|
||||||
ConcentrationConstants.LOGGER.info("Trying to modify window monitor");
|
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) {
|
if (monitor != 0L) {
|
||||||
|
VideoMode currentMode = monitorInstance.getCurrentMode();
|
||||||
ConcentrationConstants.LOGGER.info("Modifying window size limits");
|
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
|
long finalMonitor;
|
||||||
// The final step is same
|
|
||||||
// So I extracted the value then execute the final step
|
|
||||||
int finalWidth;
|
int finalWidth;
|
||||||
int finalHeight;
|
int finalHeight;
|
||||||
|
|
||||||
@ -105,97 +113,71 @@ public abstract class WindowMixin {
|
|||||||
int finalY;
|
int finalY;
|
||||||
|
|
||||||
if (this.fullscreen) {
|
if (this.fullscreen) {
|
||||||
|
VideoMode currentMode = monitorInstance.getCurrentMode();
|
||||||
ConcentrationConfigForge.ensureLoaded();
|
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;
|
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;
|
this.concentration$cacheSizeLock = true;
|
||||||
ConcentrationConstants.LOGGER.info("Locked size caching");
|
ConcentrationConstants.LOGGER.info("Locked size caching");
|
||||||
|
|
||||||
if (ConcentrationConfigForge.FULLSCREEN.get() == FullscreenMode.NATIVE) {
|
if (ConcentrationConfigForge.FULLSCREEN.get() == FullscreenMode.NATIVE) {
|
||||||
ConcentrationConstants.LOGGER.info("Fullscreen mode is native, apply now!");
|
ConcentrationConstants.LOGGER.info("Fullscreen mode is native, apply now!");
|
||||||
GLFW.glfwSetWindowMonitor(window, monitor, xpos, ypos, width, height, -1);
|
finalMonitor = monitor;
|
||||||
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
|
|
||||||
finalX = monitorInstance.getX();
|
finalX = monitorInstance.getX();
|
||||||
finalY = monitorInstance.getY() - 1;
|
finalY = monitorInstance.getY();
|
||||||
finalWidth = width;
|
finalWidth = currentMode.getWidth();
|
||||||
finalHeight = height + 1;
|
finalHeight = currentMode.getHeight();
|
||||||
}
|
} else {
|
||||||
|
ConcentrationConstants.LOGGER.info("Trying to switch to borderless fullscreen mode");
|
||||||
|
|
||||||
this.x = finalX;
|
/*if (ConcentrationConfigForge.CUSTOMIZED.get()) {
|
||||||
this.y = finalY;
|
final boolean related = ConcentrationConfigForge.RELATED.get();
|
||||||
this.width = finalWidth;
|
final int configX = ConcentrationConfigForge.X.get();
|
||||||
this.height = finalHeight;
|
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 {
|
} else {
|
||||||
ConcentrationConstants.LOGGER.info("Trying to switch to windowed mode");
|
ConcentrationConstants.LOGGER.info("Trying to switch to windowed mode");
|
||||||
|
finalMonitor = 0L;
|
||||||
// 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);
|
|
||||||
|
|
||||||
ConcentrationConstants.LOGGER.info("Trying to use cached value to resize the window");
|
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;
|
finalWidth = concentration$cachedSize ? concentration$cachedWidth : width;
|
||||||
finalHeight = concentration$cachedSize ? concentration$cachedHeight : height;
|
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 (this.concentration$cachedPos) {
|
||||||
// If Concentration cached the pos, use the cached value
|
|
||||||
finalX = concentration$cachedX;
|
finalX = concentration$cachedX;
|
||||||
finalY = concentration$cachedY;
|
finalY = concentration$cachedY;
|
||||||
} else if (this.concentration$lastMonitor != -1) {
|
} else if (this.concentration$lastMonitor != -1 && this.screenManager.getMonitor(this.concentration$lastMonitor) != null) {
|
||||||
// or else maybe the game started with fullscreen mode, so I don't need to care about the size
|
Monitor lastMonitor = this.screenManager.getMonitor(this.concentration$lastMonitor);
|
||||||
// only need to make sure that the position is in the correct monitor
|
VideoMode videoMode = lastMonitor.getCurrentMode();
|
||||||
Monitor monitorInstance = this.screenManager.getMonitor(this.concentration$lastMonitor);
|
|
||||||
VideoMode videoMode = monitorInstance.getCurrentMode();
|
|
||||||
finalX = (videoMode.getWidth() - finalWidth) / 2;
|
finalX = (videoMode.getWidth() - finalWidth) / 2;
|
||||||
finalY = (videoMode.getHeight() - finalHeight) / 2;
|
finalY = (videoMode.getHeight() - finalHeight) / 2;
|
||||||
} else {
|
} else {
|
||||||
// if both value are missed, use the default value to prevent errors
|
|
||||||
finalX = xpos;
|
finalX = xpos;
|
||||||
finalY = ypos;
|
finalY = ypos;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unlock caching, because user can change the window size now
|
|
||||||
this.concentration$cacheSizeLock = false;
|
this.concentration$cacheSizeLock = false;
|
||||||
ConcentrationConstants.LOGGER.info("Unlocked size caching");
|
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("Window size: {}, {}, position: {}, {}", finalWidth, finalHeight, finalX, finalY);
|
||||||
|
|
||||||
ConcentrationConstants.LOGGER.info("Trying to resize and reposition the window");
|
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] =================");
|
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
@ -1,4 +1,4 @@
|
|||||||
version=2.0.1
|
version=2.1.0
|
||||||
group=net.deechael.concentration
|
group=net.deechael.concentration
|
||||||
java_version=21
|
java_version=21
|
||||||
|
|
||||||
|
@ -5,7 +5,6 @@ import net.deechael.concentration.ConcentrationConstants;
|
|||||||
import net.deechael.concentration.config.ConcentrationConfigScreen;
|
import net.deechael.concentration.config.ConcentrationConfigScreen;
|
||||||
import net.deechael.concentration.neoforge.compat.EmbeddiumCompat;
|
import net.deechael.concentration.neoforge.compat.EmbeddiumCompat;
|
||||||
import net.deechael.concentration.neoforge.config.ConcentrationConfigNeoForge;
|
import net.deechael.concentration.neoforge.config.ConcentrationConfigNeoForge;
|
||||||
import net.minecraft.client.Minecraft;
|
|
||||||
import net.minecraft.client.OptionInstance;
|
import net.minecraft.client.OptionInstance;
|
||||||
import net.minecraft.client.gui.screens.Screen;
|
import net.minecraft.client.gui.screens.Screen;
|
||||||
import net.minecraft.network.chat.Component;
|
import net.minecraft.network.chat.Component;
|
||||||
|
@ -26,8 +26,8 @@ public class ConcentrationNeoForgeMixinPlugin implements IMixinConfigPlugin {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean shouldApplyMixin(String targetClassName, String mixinClassName) {
|
public boolean shouldApplyMixin(String targetClassName, String mixinClassName) {
|
||||||
return mixinClassName.equals("net.deechael.concentration.fabric.mixin.WindowMixin")
|
return mixinClassName.equals("net.deechael.concentration.fabric.mixin.WindowMixin")
|
||||||
|| (!ModList.get().isLoaded("embeddium") && checkSodium(mixinClassName));
|
|| (!ModList.get().isLoaded("embeddium") && checkSodium(mixinClassName));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -1,15 +1,9 @@
|
|||||||
package net.deechael.concentration.neoforge.config;
|
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.FullscreenMode;
|
||||||
import net.deechael.concentration.config.Config;
|
import net.deechael.concentration.config.Config;
|
||||||
import net.neoforged.fml.loading.FMLPaths;
|
|
||||||
import net.neoforged.neoforge.common.ModConfigSpec;
|
import net.neoforged.neoforge.common.ModConfigSpec;
|
||||||
|
|
||||||
import java.nio.file.Path;
|
|
||||||
|
|
||||||
public final class ConcentrationConfigNeoForge implements Config {
|
public final class ConcentrationConfigNeoForge implements Config {
|
||||||
|
|
||||||
public final static ConcentrationConfigNeoForge INSTANCE = new ConcentrationConfigNeoForge();
|
public final static ConcentrationConfigNeoForge INSTANCE = new ConcentrationConfigNeoForge();
|
||||||
@ -71,6 +65,11 @@ public final class ConcentrationConfigNeoForge implements Config {
|
|||||||
private ConcentrationConfigNeoForge() {
|
private ConcentrationConfigNeoForge() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean customized() {
|
||||||
|
return CUSTOMIZED.get();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public FullscreenMode getFullscreenMode() {
|
public FullscreenMode getFullscreenMode() {
|
||||||
return FULLSCREEN.get();
|
return FULLSCREEN.get();
|
||||||
|
@ -6,8 +6,11 @@ import com.mojang.blaze3d.platform.VideoMode;
|
|||||||
import com.mojang.blaze3d.platform.Window;
|
import com.mojang.blaze3d.platform.Window;
|
||||||
import net.deechael.concentration.ConcentrationConstants;
|
import net.deechael.concentration.ConcentrationConstants;
|
||||||
import net.deechael.concentration.FullscreenMode;
|
import net.deechael.concentration.FullscreenMode;
|
||||||
|
import net.deechael.concentration.config.Config;
|
||||||
import net.deechael.concentration.neoforge.config.ConcentrationConfigNeoForge;
|
import net.deechael.concentration.neoforge.config.ConcentrationConfigNeoForge;
|
||||||
import org.lwjgl.glfw.GLFW;
|
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.Final;
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
import org.spongepowered.asm.mixin.Shadow;
|
import org.spongepowered.asm.mixin.Shadow;
|
||||||
@ -41,6 +44,9 @@ public abstract class WindowMixin {
|
|||||||
@Shadow
|
@Shadow
|
||||||
private int height;
|
private int height;
|
||||||
|
|
||||||
|
@Shadow
|
||||||
|
@Final
|
||||||
|
private long window;
|
||||||
@Unique
|
@Unique
|
||||||
private long concentration$lastMonitor = -1;
|
private long concentration$lastMonitor = -1;
|
||||||
|
|
||||||
@ -89,15 +95,17 @@ public abstract class WindowMixin {
|
|||||||
ConcentrationConstants.LOGGER.info("================= [Concentration Start] =================");
|
ConcentrationConstants.LOGGER.info("================= [Concentration Start] =================");
|
||||||
ConcentrationConstants.LOGGER.info("Trying to modify window monitor");
|
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) {
|
if (monitor != 0L) {
|
||||||
|
VideoMode currentMode = monitorInstance.getCurrentMode();
|
||||||
ConcentrationConstants.LOGGER.info("Modifying window size limits");
|
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
|
long finalMonitor;
|
||||||
// The final step is same
|
|
||||||
// So I extracted the value then execute the final step
|
|
||||||
int finalWidth;
|
int finalWidth;
|
||||||
int finalHeight;
|
int finalHeight;
|
||||||
|
|
||||||
@ -105,97 +113,71 @@ public abstract class WindowMixin {
|
|||||||
int finalY;
|
int finalY;
|
||||||
|
|
||||||
if (this.fullscreen) {
|
if (this.fullscreen) {
|
||||||
|
VideoMode currentMode = monitorInstance.getCurrentMode();
|
||||||
ConcentrationConfigNeoForge.ensureLoaded();
|
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;
|
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;
|
this.concentration$cacheSizeLock = true;
|
||||||
ConcentrationConstants.LOGGER.info("Locked size caching");
|
ConcentrationConstants.LOGGER.info("Locked size caching");
|
||||||
|
|
||||||
if (ConcentrationConfigNeoForge.FULLSCREEN.get() == FullscreenMode.NATIVE) {
|
if (ConcentrationConfigNeoForge.FULLSCREEN.get() == FullscreenMode.NATIVE) {
|
||||||
ConcentrationConstants.LOGGER.info("Fullscreen mode is native, apply now!");
|
ConcentrationConstants.LOGGER.info("Fullscreen mode is native, apply now!");
|
||||||
GLFW.glfwSetWindowMonitor(window, monitor, xpos, ypos, width, height, -1);
|
finalMonitor = monitor;
|
||||||
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
|
|
||||||
finalX = monitorInstance.getX();
|
finalX = monitorInstance.getX();
|
||||||
finalY = monitorInstance.getY() - 1;
|
finalY = monitorInstance.getY();
|
||||||
finalWidth = width;
|
finalWidth = currentMode.getWidth();
|
||||||
finalHeight = height + 1;
|
finalHeight = currentMode.getHeight();
|
||||||
}
|
} else {
|
||||||
|
ConcentrationConstants.LOGGER.info("Trying to switch to borderless fullscreen mode");
|
||||||
|
|
||||||
this.x = finalX;
|
/*if (ConcentrationConfigForge.CUSTOMIZED.get()) {
|
||||||
this.y = finalY;
|
final boolean related = ConcentrationConfigForge.RELATED.get();
|
||||||
this.width = finalWidth;
|
final int configX = ConcentrationConfigForge.X.get();
|
||||||
this.height = finalHeight;
|
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 {
|
} else {
|
||||||
ConcentrationConstants.LOGGER.info("Trying to switch to windowed mode");
|
ConcentrationConstants.LOGGER.info("Trying to switch to windowed mode");
|
||||||
|
finalMonitor = 0L;
|
||||||
// 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);
|
|
||||||
|
|
||||||
ConcentrationConstants.LOGGER.info("Trying to use cached value to resize the window");
|
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;
|
finalWidth = concentration$cachedSize ? concentration$cachedWidth : width;
|
||||||
finalHeight = concentration$cachedSize ? concentration$cachedHeight : height;
|
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 (this.concentration$cachedPos) {
|
||||||
// If Concentration cached the pos, use the cached value
|
|
||||||
finalX = concentration$cachedX;
|
finalX = concentration$cachedX;
|
||||||
finalY = concentration$cachedY;
|
finalY = concentration$cachedY;
|
||||||
} else if (this.concentration$lastMonitor != -1) {
|
} else if (this.concentration$lastMonitor != -1 && this.screenManager.getMonitor(this.concentration$lastMonitor) != null) {
|
||||||
// or else maybe the game started with fullscreen mode, so I don't need to care about the size
|
Monitor lastMonitor = this.screenManager.getMonitor(this.concentration$lastMonitor);
|
||||||
// only need to make sure that the position is in the correct monitor
|
VideoMode videoMode = lastMonitor.getCurrentMode();
|
||||||
Monitor monitorInstance = this.screenManager.getMonitor(this.concentration$lastMonitor);
|
|
||||||
VideoMode videoMode = monitorInstance.getCurrentMode();
|
|
||||||
finalX = (videoMode.getWidth() - finalWidth) / 2;
|
finalX = (videoMode.getWidth() - finalWidth) / 2;
|
||||||
finalY = (videoMode.getHeight() - finalHeight) / 2;
|
finalY = (videoMode.getHeight() - finalHeight) / 2;
|
||||||
} else {
|
} else {
|
||||||
// if both value are missed, use the default value to prevent errors
|
|
||||||
finalX = xpos;
|
finalX = xpos;
|
||||||
finalY = ypos;
|
finalY = ypos;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unlock caching, because user can change the window size now
|
|
||||||
this.concentration$cacheSizeLock = false;
|
this.concentration$cacheSizeLock = false;
|
||||||
ConcentrationConstants.LOGGER.info("Unlocked size caching");
|
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("Window size: {}, {}, position: {}, {}", finalWidth, finalHeight, finalX, finalY);
|
||||||
|
|
||||||
ConcentrationConstants.LOGGER.info("Trying to resize and reposition the window");
|
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] =================");
|
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user