2020-07-22 06:23:34 +01:00
package com.mojang.blaze3d.platform ;
2020-07-22 06:25:47 +01:00
import net.minecraft.client.main.SilentInitException ;
2020-07-22 06:23:34 +01:00
import org.apache.logging.log4j.LogManager ;
import org.lwjgl.glfw.Callbacks ;
import org.lwjgl.glfw.GLFWErrorCallbackI ;
2020-07-22 06:25:47 +01:00
import org.lwjgl.util.tinyfd.TinyFileDialogs ;
2020-07-22 06:23:34 +01:00
import java.nio.Buffer ;
import java.nio.ByteBuffer ;
import java.nio.IntBuffer ;
import java.io.IOException ;
import org.lwjgl.stb.STBImage ;
import org.lwjgl.glfw.GLFWImage ;
import java.io.FileNotFoundException ;
import java.io.InputStream ;
import org.lwjgl.PointerBuffer ;
import org.lwjgl.system.MemoryUtil ;
import org.lwjgl.system.MemoryStack ;
import java.util.function.BiConsumer ;
import org.lwjgl.opengl.GL ;
import org.lwjgl.glfw.GLFW ;
2020-07-22 06:25:47 +01:00
import com.mojang.blaze3d.systems.RenderSystem ;
import javax.annotation.Nullable ;
2020-07-22 06:23:34 +01:00
import java.util.Optional ;
import org.lwjgl.glfw.GLFWErrorCallback ;
import org.apache.logging.log4j.Logger ;
public final class Window implements AutoCloseable {
private static final Logger LOGGER ;
private final GLFWErrorCallback defaultErrorCallback ;
2020-07-22 06:25:47 +01:00
private final WindowEventHandler eventHandler ;
2020-07-22 06:23:34 +01:00
private final ScreenManager screenManager ;
private final long window ;
private int windowedX ;
private int windowedY ;
private int windowedWidth ;
private int windowedHeight ;
private Optional < VideoMode > preferredFullscreenVideoMode ;
private boolean fullscreen ;
private boolean actuallyFullscreen ;
private int x ;
private int y ;
private int width ;
private int height ;
private int framebufferWidth ;
private int framebufferHeight ;
private int guiScaledWidth ;
private int guiScaledHeight ;
private double guiScale ;
private String errorSection ;
private boolean dirty ;
private int framerateLimit ;
private boolean vsync ;
2020-07-22 06:32:50 +01:00
public Window ( final WindowEventHandler dgz , final ScreenManager dgu , final DisplayData dgi , @Nullable final String string4 , final String string5 ) {
2020-07-22 06:23:34 +01:00
this . defaultErrorCallback = GLFWErrorCallback . create ( this : : defaultErrorCallback ) ;
this . errorSection = " " ;
2020-07-22 06:25:47 +01:00
RenderSystem . assertThread ( RenderSystem : : isInInitPhase ) ;
2020-07-22 06:32:50 +01:00
this . screenManager = dgu ;
2020-07-22 06:25:47 +01:00
this . setBootErrorCallback ( ) ;
this . setErrorSection ( " Pre startup " ) ;
2020-07-22 06:32:50 +01:00
this . eventHandler = dgz ;
2020-07-22 06:23:34 +01:00
final Optional < VideoMode > optional7 = VideoMode . read ( string4 ) ;
if ( optional7 . isPresent ( ) ) {
this . preferredFullscreenVideoMode = optional7 ;
}
2020-07-22 06:32:50 +01:00
else if ( dgi . fullscreenWidth . isPresent ( ) & & dgi . fullscreenHeight . isPresent ( ) ) {
this . preferredFullscreenVideoMode = Optional . < VideoMode > of ( new VideoMode ( dgi . fullscreenWidth . getAsInt ( ) , dgi . fullscreenHeight . getAsInt ( ) , 8 , 8 , 8 , 60 ) ) ;
2020-07-22 06:23:34 +01:00
}
else {
this . preferredFullscreenVideoMode = Optional . < VideoMode > empty ( ) ;
}
2020-07-22 06:32:50 +01:00
final boolean isFullscreen = dgi . isFullscreen ;
2020-07-22 06:23:34 +01:00
this . fullscreen = isFullscreen ;
this . actuallyFullscreen = isFullscreen ;
2020-07-22 06:32:50 +01:00
final Monitor dgq8 = dgu . getMonitor ( GLFW . glfwGetPrimaryMonitor ( ) ) ;
final int n = ( dgi . width > 0 ) ? dgi . width : 1 ;
2020-07-22 06:23:34 +01:00
this . width = n ;
this . windowedWidth = n ;
2020-07-22 06:32:50 +01:00
final int n2 = ( dgi . height > 0 ) ? dgi . height : 1 ;
2020-07-22 06:23:34 +01:00
this . height = n2 ;
this . windowedHeight = n2 ;
GLFW . glfwDefaultWindowHints ( ) ;
2020-07-22 06:25:47 +01:00
GLFW . glfwWindowHint ( 139265 , 196609 ) ;
GLFW . glfwWindowHint ( 139275 , 221185 ) ;
GLFW . glfwWindowHint ( 139266 , 2 ) ;
GLFW . glfwWindowHint ( 139267 , 0 ) ;
GLFW . glfwWindowHint ( 139272 , 0 ) ;
2020-07-22 06:32:50 +01:00
this . window = GLFW . glfwCreateWindow ( this . width , this . height , ( CharSequence ) string5 , ( this . fullscreen & & dgq8 ! = null ) ? dgq8 . getMonitor ( ) : 0L , 0L ) ;
if ( dgq8 ! = null ) {
final VideoMode dgx9 = dgq8 . getPreferredVidMode ( this . fullscreen ? this . preferredFullscreenVideoMode : Optional . < VideoMode > empty ( ) ) ;
final int n3 = dgq8 . getX ( ) + dgx9 . getWidth ( ) / 2 - this . width / 2 ;
2020-07-22 06:23:34 +01:00
this . x = n3 ;
this . windowedX = n3 ;
2020-07-22 06:32:50 +01:00
final int n4 = dgq8 . getY ( ) + dgx9 . getHeight ( ) / 2 - this . height / 2 ;
2020-07-22 06:23:34 +01:00
this . y = n4 ;
this . windowedY = n4 ;
}
else {
final int [ ] arr9 = { 0 } ;
final int [ ] arr10 = { 0 } ;
GLFW . glfwGetWindowPos ( this . window , arr9 , arr10 ) ;
final int n5 = arr9 [ 0 ] ;
this . x = n5 ;
this . windowedX = n5 ;
final int n6 = arr10 [ 0 ] ;
this . y = n6 ;
this . windowedY = n6 ;
}
GLFW . glfwMakeContextCurrent ( this . window ) ;
GL . createCapabilities ( ) ;
this . setMode ( ) ;
this . refreshFramebufferSize ( ) ;
GLFW . glfwSetFramebufferSizeCallback ( this . window , this : : onFramebufferResize ) ;
GLFW . glfwSetWindowPosCallback ( this . window , this : : onMove ) ;
GLFW . glfwSetWindowSizeCallback ( this . window , this : : onResize ) ;
GLFW . glfwSetWindowFocusCallback ( this . window , this : : onFocus ) ;
2020-07-22 06:32:50 +01:00
GLFW . glfwSetCursorEnterCallback ( this . window , this : : onEnter ) ;
2020-07-22 06:23:34 +01:00
}
2020-07-22 06:25:47 +01:00
public int getRefreshRate ( ) {
RenderSystem . assertThread ( RenderSystem : : isOnRenderThread ) ;
return GLX . _getRefreshRate ( this ) ;
}
public boolean shouldClose ( ) {
return GLX . _shouldClose ( this ) ;
}
2020-07-22 06:23:34 +01:00
public static void checkGlfwError ( final BiConsumer < Integer , String > biConsumer ) {
2020-07-22 06:25:47 +01:00
RenderSystem . assertThread ( RenderSystem : : isInInitPhase ) ;
2020-07-22 06:23:34 +01:00
try ( final MemoryStack memoryStack2 = MemoryStack . stackPush ( ) ) {
final PointerBuffer pointerBuffer4 = memoryStack2 . mallocPointer ( 1 ) ;
final int integer5 = GLFW . glfwGetError ( pointerBuffer4 ) ;
if ( integer5 ! = 0 ) {
final long long6 = pointerBuffer4 . get ( ) ;
final String string8 = ( long6 = = 0L ) ? " " : MemoryUtil . memUTF8 ( long6 ) ;
biConsumer . accept ( integer5 , string8 ) ;
}
}
}
public void setIcon ( final InputStream inputStream1 , final InputStream inputStream2 ) {
2020-07-22 06:25:47 +01:00
RenderSystem . assertThread ( RenderSystem : : isInInitPhase ) ;
2020-07-22 06:23:34 +01:00
try ( final MemoryStack memoryStack4 = MemoryStack . stackPush ( ) ) {
if ( inputStream1 = = null ) {
throw new FileNotFoundException ( " icons/icon_16x16.png " ) ;
}
if ( inputStream2 = = null ) {
throw new FileNotFoundException ( " icons/icon_32x32.png " ) ;
}
final IntBuffer intBuffer6 = memoryStack4 . mallocInt ( 1 ) ;
final IntBuffer intBuffer7 = memoryStack4 . mallocInt ( 1 ) ;
final IntBuffer intBuffer8 = memoryStack4 . mallocInt ( 1 ) ;
final GLFWImage . Buffer buffer9 = GLFWImage . mallocStack ( 2 , memoryStack4 ) ;
final ByteBuffer byteBuffer10 = this . readIconPixels ( inputStream1 , intBuffer6 , intBuffer7 , intBuffer8 ) ;
if ( byteBuffer10 = = null ) {
throw new IllegalStateException ( " Could not load icon: " + STBImage . stbi_failure_reason ( ) ) ;
}
buffer9 . position ( 0 ) ;
buffer9 . width ( intBuffer6 . get ( 0 ) ) ;
buffer9 . height ( intBuffer7 . get ( 0 ) ) ;
buffer9 . pixels ( byteBuffer10 ) ;
final ByteBuffer byteBuffer11 = this . readIconPixels ( inputStream2 , intBuffer6 , intBuffer7 , intBuffer8 ) ;
if ( byteBuffer11 = = null ) {
throw new IllegalStateException ( " Could not load icon: " + STBImage . stbi_failure_reason ( ) ) ;
}
buffer9 . position ( 1 ) ;
buffer9 . width ( intBuffer6 . get ( 0 ) ) ;
buffer9 . height ( intBuffer7 . get ( 0 ) ) ;
buffer9 . pixels ( byteBuffer11 ) ;
buffer9 . position ( 0 ) ;
GLFW . glfwSetWindowIcon ( this . window , buffer9 ) ;
STBImage . stbi_image_free ( byteBuffer10 ) ;
STBImage . stbi_image_free ( byteBuffer11 ) ;
}
catch ( IOException iOException4 ) {
Window . LOGGER . error ( " Couldn't set icon " , ( Throwable ) iOException4 ) ;
}
}
@Nullable
private ByteBuffer readIconPixels ( final InputStream inputStream , final IntBuffer intBuffer2 , final IntBuffer intBuffer3 , final IntBuffer intBuffer4 ) throws IOException {
2020-07-22 06:25:47 +01:00
RenderSystem . assertThread ( RenderSystem : : isInInitPhase ) ;
2020-07-22 06:23:34 +01:00
ByteBuffer byteBuffer6 = null ;
try {
byteBuffer6 = TextureUtil . readResource ( inputStream ) ;
byteBuffer6 . rewind ( ) ;
return STBImage . stbi_load_from_memory ( byteBuffer6 , intBuffer2 , intBuffer3 , intBuffer4 , 0 ) ;
}
finally {
if ( byteBuffer6 ! = null ) {
MemoryUtil . memFree ( ( Buffer ) byteBuffer6 ) ;
}
}
}
2020-07-22 06:25:47 +01:00
public void setErrorSection ( final String string ) {
2020-07-22 06:23:34 +01:00
this . errorSection = string ;
}
2020-07-22 06:25:47 +01:00
private void setBootErrorCallback ( ) {
RenderSystem . assertThread ( RenderSystem : : isInInitPhase ) ;
2020-07-22 06:23:34 +01:00
GLFW . glfwSetErrorCallback ( Window : : bootCrash ) ;
}
private static void bootCrash ( final int integer , final long long2 ) {
2020-07-22 06:25:47 +01:00
RenderSystem . assertThread ( RenderSystem : : isInInitPhase ) ;
final String string4 = " GLFW error " + integer + " : " + MemoryUtil . memUTF8 ( long2 ) ;
TinyFileDialogs . tinyfd_messageBox ( ( CharSequence ) " Minecraft " , ( CharSequence ) ( string4 + " . \ n \ nPlease make sure you have up-to-date drivers (see aka.ms/mcdriver for instructions). " ) , ( CharSequence ) " ok " , ( CharSequence ) " error " , false ) ;
throw new WindowInitFailed ( string4 ) ;
2020-07-22 06:23:34 +01:00
}
public void defaultErrorCallback ( final int integer , final long long2 ) {
2020-07-22 06:25:47 +01:00
RenderSystem . assertThread ( RenderSystem : : isOnRenderThread ) ;
2020-07-22 06:23:34 +01:00
final String string5 = MemoryUtil . memUTF8 ( long2 ) ;
Window . LOGGER . error ( " ########## GL ERROR ########## " ) ;
Window . LOGGER . error ( " @ {} " , this . errorSection ) ;
Window . LOGGER . error ( " {}: {} " , integer , string5 ) ;
}
2020-07-22 06:25:47 +01:00
public void setDefaultErrorCallback ( ) {
final GLFWErrorCallback gLFWErrorCallback2 = GLFW . glfwSetErrorCallback ( ( GLFWErrorCallbackI ) this . defaultErrorCallback ) ;
if ( gLFWErrorCallback2 ! = null ) {
gLFWErrorCallback2 . free ( ) ;
}
2020-07-22 06:23:34 +01:00
}
public void updateVsync ( final boolean boolean1 ) {
2020-07-22 06:25:47 +01:00
RenderSystem . assertThread ( RenderSystem : : isOnRenderThreadOrInit ) ;
2020-07-22 06:23:34 +01:00
GLFW . glfwSwapInterval ( ( int ) ( ( this . vsync = boolean1 ) ? 1 : 0 ) ) ;
}
@Override
public void close ( ) {
2020-07-22 06:25:47 +01:00
RenderSystem . assertThread ( RenderSystem : : isOnRenderThread ) ;
2020-07-22 06:23:34 +01:00
Callbacks . glfwFreeCallbacks ( this . window ) ;
this . defaultErrorCallback . close ( ) ;
GLFW . glfwDestroyWindow ( this . window ) ;
GLFW . glfwTerminate ( ) ;
}
private void onMove ( final long long1 , final int integer2 , final int integer3 ) {
this . x = integer2 ;
this . y = integer3 ;
}
private void onFramebufferResize ( final long long1 , final int integer2 , final int integer3 ) {
if ( long1 ! = this . window ) {
return ;
}
final int integer4 = this . getWidth ( ) ;
final int integer5 = this . getHeight ( ) ;
if ( integer2 = = 0 | | integer3 = = 0 ) {
return ;
}
this . framebufferWidth = integer2 ;
this . framebufferHeight = integer3 ;
if ( this . getWidth ( ) ! = integer4 | | this . getHeight ( ) ! = integer5 ) {
2020-07-22 06:25:47 +01:00
this . eventHandler . resizeDisplay ( ) ;
2020-07-22 06:23:34 +01:00
}
}
private void refreshFramebufferSize ( ) {
2020-07-22 06:25:47 +01:00
RenderSystem . assertThread ( RenderSystem : : isInInitPhase ) ;
2020-07-22 06:23:34 +01:00
final int [ ] arr2 = { 0 } ;
final int [ ] arr3 = { 0 } ;
GLFW . glfwGetFramebufferSize ( this . window , arr2 , arr3 ) ;
this . framebufferWidth = arr2 [ 0 ] ;
this . framebufferHeight = arr3 [ 0 ] ;
}
private void onResize ( final long long1 , final int integer2 , final int integer3 ) {
this . width = integer2 ;
this . height = integer3 ;
}
private void onFocus ( final long long1 , final boolean boolean2 ) {
if ( long1 = = this . window ) {
2020-07-22 06:25:47 +01:00
this . eventHandler . setWindowActive ( boolean2 ) ;
2020-07-22 06:23:34 +01:00
}
}
2020-07-22 06:32:50 +01:00
private void onEnter ( final long long1 , final boolean boolean2 ) {
if ( boolean2 ) {
this . eventHandler . cursorEntered ( ) ;
}
}
2020-07-22 06:23:34 +01:00
public void setFramerateLimit ( final int integer ) {
this . framerateLimit = integer ;
}
public int getFramerateLimit ( ) {
return this . framerateLimit ;
}
2020-07-22 06:25:47 +01:00
public void updateDisplay ( ) {
RenderSystem . flipFrame ( this . window ) ;
2020-07-22 06:23:34 +01:00
if ( this . fullscreen ! = this . actuallyFullscreen ) {
this . actuallyFullscreen = this . fullscreen ;
this . updateFullscreen ( this . vsync ) ;
}
}
public Optional < VideoMode > getPreferredFullscreenVideoMode ( ) {
return this . preferredFullscreenVideoMode ;
}
public void setPreferredFullscreenVideoMode ( final Optional < VideoMode > optional ) {
final boolean boolean3 = ! optional . equals ( this . preferredFullscreenVideoMode ) ;
this . preferredFullscreenVideoMode = optional ;
if ( boolean3 ) {
this . dirty = true ;
}
}
public void changeFullscreenVideoMode ( ) {
if ( this . fullscreen & & this . dirty ) {
this . dirty = false ;
this . setMode ( ) ;
2020-07-22 06:25:47 +01:00
this . eventHandler . resizeDisplay ( ) ;
2020-07-22 06:23:34 +01:00
}
}
private void setMode ( ) {
2020-07-22 06:25:47 +01:00
RenderSystem . assertThread ( RenderSystem : : isInInitPhase ) ;
2020-07-22 06:23:34 +01:00
final boolean boolean2 = GLFW . glfwGetWindowMonitor ( this . window ) ! = 0L ;
if ( this . fullscreen ) {
2020-07-22 06:32:50 +01:00
final Monitor dgq3 = this . screenManager . findBestMonitor ( this ) ;
if ( dgq3 = = null ) {
2020-07-22 06:23:34 +01:00
Window . LOGGER . warn ( " Failed to find suitable monitor for fullscreen mode " ) ;
this . fullscreen = false ;
}
else {
2020-07-22 06:32:50 +01:00
final VideoMode dgx4 = dgq3 . getPreferredVidMode ( this . preferredFullscreenVideoMode ) ;
2020-07-22 06:23:34 +01:00
if ( ! boolean2 ) {
this . windowedX = this . x ;
this . windowedY = this . y ;
this . windowedWidth = this . width ;
this . windowedHeight = this . height ;
}
this . x = 0 ;
this . y = 0 ;
2020-07-22 06:32:50 +01:00
this . width = dgx4 . getWidth ( ) ;
this . height = dgx4 . getHeight ( ) ;
GLFW . glfwSetWindowMonitor ( this . window , dgq3 . getMonitor ( ) , this . x , this . y , this . width , this . height , dgx4 . getRefreshRate ( ) ) ;
2020-07-22 06:23:34 +01:00
}
}
else {
this . x = this . windowedX ;
this . y = this . windowedY ;
this . width = this . windowedWidth ;
this . height = this . windowedHeight ;
GLFW . glfwSetWindowMonitor ( this . window , 0L , this . x , this . y , this . width , this . height , - 1 ) ;
}
}
public void toggleFullScreen ( ) {
this . fullscreen = ! this . fullscreen ;
}
private void updateFullscreen ( final boolean boolean1 ) {
2020-07-22 06:25:47 +01:00
RenderSystem . assertThread ( RenderSystem : : isOnRenderThread ) ;
2020-07-22 06:23:34 +01:00
try {
this . setMode ( ) ;
2020-07-22 06:25:47 +01:00
this . eventHandler . resizeDisplay ( ) ;
2020-07-22 06:23:34 +01:00
this . updateVsync ( boolean1 ) ;
2020-07-22 06:25:47 +01:00
this . updateDisplay ( ) ;
2020-07-22 06:23:34 +01:00
}
catch ( Exception exception3 ) {
Window . LOGGER . error ( " Couldn't toggle fullscreen " , ( Throwable ) exception3 ) ;
}
}
public int calculateScale ( final int integer , final boolean boolean2 ) {
int integer2 ;
for ( integer2 = 1 ; integer2 ! = integer & & integer2 < this . framebufferWidth & & integer2 < this . framebufferHeight & & this . framebufferWidth / ( integer2 + 1 ) > = 320 & & this . framebufferHeight / ( integer2 + 1 ) > = 240 ; + + integer2 ) { }
if ( boolean2 & & integer2 % 2 ! = 0 ) {
+ + integer2 ;
}
return integer2 ;
}
public void setGuiScale ( final double double1 ) {
this . guiScale = double1 ;
final int integer4 = ( int ) ( this . framebufferWidth / double1 ) ;
this . guiScaledWidth = ( ( this . framebufferWidth / double1 > integer4 ) ? ( integer4 + 1 ) : integer4 ) ;
final int integer5 = ( int ) ( this . framebufferHeight / double1 ) ;
this . guiScaledHeight = ( ( this . framebufferHeight / double1 > integer5 ) ? ( integer5 + 1 ) : integer5 ) ;
}
2020-07-22 06:30:03 +01:00
public void setTitle ( final String string ) {
GLFW . glfwSetWindowTitle ( this . window , ( CharSequence ) string ) ;
}
2020-07-22 06:23:34 +01:00
public long getWindow ( ) {
return this . window ;
}
public boolean isFullscreen ( ) {
return this . fullscreen ;
}
public int getWidth ( ) {
return this . framebufferWidth ;
}
public int getHeight ( ) {
return this . framebufferHeight ;
}
public int getScreenWidth ( ) {
return this . width ;
}
public int getScreenHeight ( ) {
return this . height ;
}
public int getGuiScaledWidth ( ) {
return this . guiScaledWidth ;
}
public int getGuiScaledHeight ( ) {
return this . guiScaledHeight ;
}
public int getX ( ) {
return this . x ;
}
public int getY ( ) {
return this . y ;
}
public double getGuiScale ( ) {
return this . guiScale ;
}
@Nullable
public Monitor findBestMonitor ( ) {
return this . screenManager . findBestMonitor ( this ) ;
}
public void updateRawMouseInput ( final boolean boolean1 ) {
InputConstants . updateRawMouseInput ( this . window , boolean1 ) ;
}
static {
LOGGER = LogManager . getLogger ( ) ;
}
2020-07-22 06:25:47 +01:00
public static class WindowInitFailed extends SilentInitException {
private WindowInitFailed ( final String string ) {
super ( string ) ;
}
}
2020-07-22 06:23:34 +01:00
}