/*
* The MIT License (MIT)
*
* Copyright (c) 2014-2017 Sri Harsha Chilakapati
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.shc.silenceengine.backend.lwjgl.glfw;
import com.shc.silenceengine.backend.lwjgl.glfw.callbacks.*;
import com.shc.silenceengine.core.SilenceEngine;
import com.shc.silenceengine.graphics.Color;
import com.shc.silenceengine.graphics.Image;
import com.shc.silenceengine.io.FilePath;
import com.shc.silenceengine.math.Vector2;
import com.shc.silenceengine.math.Vector4;
import com.shc.silenceengine.utils.functional.SimpleCallback;
import com.shc.silenceengine.utils.functional.UniCallback;
import org.lwjgl.BufferUtils;
import org.lwjgl.glfw.*;
import org.lwjgl.opengl.GL;
import org.lwjgl.opengl.GLCapabilities;
import java.nio.ByteBuffer;
import java.nio.DoubleBuffer;
import java.nio.IntBuffer;
import java.util.HashMap;
import java.util.Map;
import static org.lwjgl.glfw.GLFW.*;
import static org.lwjgl.system.MemoryUtil.*;
/**
* <p> This class is an object oriented wrapper for GLFWwindow structure, which encapsulates both the window and the
* context. For example, this creates a 640 by 480 windowed mode window.</p>
*
* <pre>
* Window window = new Window(640, 480, "My Title");
* </pre>
*
* <p> There are several other overloads of the constructors allowing you to specify the size, title, monitor, a parent
* window and the video mode. The window object is provided along with the input events, so the event handlers can tell
* which window recieved the input.</p>
*
* <h2>Full screen windows</h2>
*
* <p> To create a full screen window, you need to specify which monitor the window should use. In most cases, the
* user's primary monitor is a good choice. For more information about retrieving monitors, see {@link
* Monitor#getMonitors()}.</p>
*
* <pre>
* Window window = new Window(640, 480, Monitor.getPrimaryMonitor());
* </pre>
*
* <p> Full screen windows cover the entire display area of a monitor, have no border or decorations. You can also pass
* a {@link VideoMode} to the constructor along with the monitor to change the resolution of the monitor.</p>
*
* <h2>Window hints</h2>
*
* <p> There are a number of hints that can be set before the creation of a window and context. Some affect the window
* itself, others affect the framebuffer or context. These hints are set to their default values each time the library
* is initialized with {@link GLFW3#init()}, can be set individually with {@link Window#setHint(int, boolean)} or {@link
* Window#setHint(int, int)}, and reset all at once to their defaults with {@link Window#setDefaultHints()}.</p>
*
* <pre>
* Window.setHint(GLFW.GLFW_CONTEXT_VERSION_MAJOR, 3);
* Window.setHint(GLFW.GLFW_CONTEXT_VERSION_MINOR, 2);
* Window.setHint(GLFW.GLFW_OPENGL_FORWARD_COMPAT, true);
* Window.setHint(GLFW.GLFW_OPENGL_PROFILE, GLFW.GLFW_OPENGL_CORE_PROFILE);
*
* Window coreProfileWindow = new Window(640, 480);
* </pre>
*
* <p> Note that hints need to be set before the creation of the window and context you wish to have the specified
* attributes.</p>
*
* <h2>Context object sharing</h2>
*
* <p> When creating a window and its OpenGL context, you can specify another window whose context the new one should
* share its objects (textures, vertex and element buffers, etc.) with.</p>
*
* <pre>
* Window secondWindow = new Window(640, 480, "Second Window", firstWindow);
* </pre>
*
* <p> Object sharing is implemented by the operating system and graphics driver. On platforms where it is possible to
* choose which types of objects are shared, GLFW requests that all types are shared. A common exception to this is VAO
* objects, they have to be recreated for every context.</p>
*
* @author Sri Harsha Chilakapati
* @author lclc98
* @see Monitor
* @see VideoMode
* @see Cursor
*/
public class Window
{
// A HashMap to store the Window objects based on the handle of the window.
// This is used to send the Window object to the input events because, say
// long pointers are ugly in Java.
private static Map<Long, Window> registeredWindows = new HashMap<>();
private long handle;
private Vector2 position;
private Vector2 size;
private Vector2 framebufferSize;
private String title;
private Monitor monitor;
/* Native GLFW Callbacks */
private GLFWCharCallback glfwCharCallback;
private GLFWCharModsCallback glfwCharModsCallback;
private GLFWCursorEnterCallback glfwCursorEnterCallback;
private GLFWCursorPosCallback glfwCursorPosCallback;
private GLFWDropCallback glfwDropCallback;
private GLFWFramebufferSizeCallback glfwFramebufferSizeCallback;
private GLFWKeyCallback glfwKeyCallback;
private GLFWMouseButtonCallback glfwMouseButtonCallback;
private GLFWScrollCallback glfwScrollCallback;
private GLFWWindowCloseCallback glfwWindowCloseCallback;
private GLFWWindowFocusCallback glfwWindowFocusCallback;
private GLFWWindowIconifyCallback glfwWindowIconifyCallback;
private GLFWWindowPosCallback glfwWindowPosCallback;
private GLFWWindowRefreshCallback glfwWindowRefreshCallback;
private GLFWWindowSizeCallback glfwWindowSizeCallback;
/* Overridden custom Callbacks for better interfacing with C++ code */
private ICharacterCallback characterCallback;
private ICharacterModsCallback characterModsCallback;
private ICursorEnterCallback cursorEnterCallback;
private ICursorPositionCallback cursorPositionCallback;
private IDropCallback dropCallback;
private IFramebufferSizeCallback framebufferSizeCallback;
private IKeyCallback keyCallback;
private IMouseButtonCallback mouseButtonCallback;
private IScrollCallback scrollCallback;
private IWindowCloseCallback windowCloseCallback;
private IWindowFocusCallback windowFocusCallback;
private IWindowIconifyCallback windowIconifyCallback;
private IWindowPositionCallback windowPositionCallback;
private IWindowRefreshCallback windowRefreshCallback;
private IWindowSizeCallback windowSizeCallback;
private GLCapabilities windowCapabilities;
/**
* Creates a window which is 800 by 600 in dimensions with the title "SilenceEngine Window".
*/
public Window()
{
this(800, 600);
}
/**
* Creates a windowed mode window with a specified width and height, in screen coordinates. The title will be the
* default title which is "SilenceEngine Window".
*
* @param width The desired width, in screen coordinates, of the window. This must be greater than zero.
* @param height The desired height, in screen coordinates, of the window. This must be greater than zero.
*/
public Window(int width, int height)
{
this(width, height, (Monitor) null, null);
}
/**
* Crates a window and its associated OpenGL context, by taking into account the resolution of the screen and the
* monitor that the window should be made full screen on, and another window if you want to share the context of the
* other window.
*
* @param width The desired width, in screen coordinates, of the window. This must be greater than zero.
* @param height The desired height, in screen coordinates, of the window. This must be greater than zero.
* @param monitor The monitor to use for full screen mode, or {@code null} to use windowed mode.
* @param share The window whose context to share resources with, or {@code null} to not share resources.
*/
public Window(int width, int height, Monitor monitor, Window share)
{
this(width, height, "SilenceEngine Window | SilenceEngine " + SilenceEngine.getVersionString(), monitor, share);
}
/**
* <p> Creates a window and its associated OpenGL context. Most of the options controlling how the window and its
* context should be created are specified with window hints.</p>
*
* <p> Successful creation does not change which context is current. Before you can use the newly created context,
* you need to make it current.</p>
*
* <p> The created window, framebuffer and context may differ from what you requested, as not all parameters and
* hints are hard constraints. This includes the size of the window, especially for full screen windows. You could
* query them manually after the window is created.</p>
*
* <p> To create a full screen window, you need to specify the monitor the window will cover. If no monitor is
* specified, windowed mode will be used. Unless you have a way for the user to choose a specific monitor, it is
* recommended that you pick the primary monitor.</p>
*
* <p> For full screen windows, the specified size becomes the resolution of the window's desired video mode. As
* long as a full screen window has input focus, the supported video mode most closely matching the desired video
* mode is set for the specified monitor.</p>
*
* <p> By default, newly created windows use the placement recommended by the window system. To create the window at
* a specific position, make it initially invisible using the {@code GLFW_VISIBLE} window hint, set its
* position and then show it.</p>
*
* <p> If a full screen window has input focus, the screensaver is prohibited from starting.</p>
*
* <p> The swap interval is not set during window creation and the initial value may vary depending on driver
* settings and defaults.</p>
*
* @param width The desired width, in screen coordinates, of the window. This must be greater than zero.
* @param height The desired height, in screen coordinates, of the window. This must be greater than zero.
* @param title The desired title string of the Window. This can also contain UTF-8 characters.
* @param monitor The monitor to use for full screen mode, or {@code null} to use windowed mode.
* @param share The window whose context to share resources with, or {@code null} to not share resources.
*/
public Window(int width, int height, String title, Monitor monitor, Window share)
{
this(width, height, title, monitor, (monitor == null ? Monitor.getPrimaryMonitor() : monitor).getVideoMode().getRefreshRate(), share);
}
/**
* <p> Creates a window and its associated OpenGL context. Most of the options controlling how the window and its
* context should be created are specified with window hints.</p>
*
* <p> Successful creation does not change which context is current. Before you can use the newly created context,
* you need to make it current.</p>
*
* <p> The created window, framebuffer and context may differ from what you requested, as not all parameters and
* hints are hard constraints. This includes the size of the window, especially for full screen windows. You could
* query them manually after the window is created.</p>
*
* <p> To create a full screen window, you need to specify the monitor the window will cover. If no monitor is
* specified, windowed mode will be used. Unless you have a way for the user to choose a specific monitor, it is
* recommended that you pick the primary monitor.</p>
*
* <p> For full screen windows, the specified size becomes the resolution of the window's desired video mode. As
* long as a full screen window has input focus, the supported video mode most closely matching the desired video
* mode is set for the specified monitor.</p>
*
* <p> By default, newly created windows use the placement recommended by the window system. To create the window at
* a specific position, make it initially invisible using the {@code GLFW_VISIBLE} window hint, set its
* position and then show it.</p>
*
* <p> If a full screen window has input focus, the screensaver is prohibited from starting.</p>
*
* <p> The swap interval is not set during window creation and the initial value may vary depending on driver
* settings and defaults.</p>
*
* @param width The desired width, in screen coordinates, of the window. This must be greater than zero.
* @param height The desired height, in screen coordinates, of the window. This must be greater than zero.
* @param title The desired title string of the Window. This can also contain UTF-8 characters.
* @param monitor The monitor to use for full screen mode, or {@code null} to use windowed mode.
* @param refreshRate The refresh rate to be used for the window. This is ignored for windowed mode windows.
* @param share The window whose context to share resources with, or {@code null} to not share
* resources.
*/
public Window(int width, int height, String title, Monitor monitor, int refreshRate, Window share)
{
size = new Vector2(width, height);
framebufferSize = new Vector2();
position = new Vector2();
this.title = title;
this.monitor = monitor;
setHint(GLFW_REFRESH_RATE, refreshRate);
handle = glfwCreateWindow(width, height, title, monitor == null ? NULL : monitor.getHandle(), share == null ? NULL : share.getHandle());
if (handle == NULL)
throw new RuntimeException("Cannot create window");
registeredWindows.put(handle, this);
// Initialize the native callbacks
initNativeCallbacks();
}
/**
* This constructor creates a fullscreen mode window that fills the monitor. The resolution will be set to the
* default resolution of the monitor supplied. If the monitor is supplied as {@code null}, then a windowed mode
* window is created instead which is 800 by 600 in size.
*
* @param monitor The monitor to use for full screen mode, or {@code null} to use windowed mode.
*/
public Window(Monitor monitor)
{
this(monitor != null ? monitor.getVideoMode().getWidth() : 800,
monitor != null ? monitor.getVideoMode().getHeight() : 600, monitor);
}
/**
* Creates a full screen window over a specified monitor. The width and height are the resolution of the monitor.
*
* @param width The desired width, in screen coordinates, of the window. This must be greater than zero.
* @param height The desired height, in screen coordinates, of the window. This must be greater than zero.
* @param monitor The monitor to use for full screen mode, or {@code null} to use windowed mode.
*/
public Window(int width, int height, Monitor monitor)
{
this(width, height, "SilenceEngine Window", monitor);
}
/**
* Creates a full screen window over a specified monitor with a title. The width and height are the resolution of
* the monitor. The title is used on the taskbar entry if the user minimised to the desktop.
*
* @param width The desired width, in screen coordinates, of the window. This must be greater than zero.
* @param height The desired height, in screen coordinates, of the window. This must be greater than zero.
* @param title The desired title string of the Window. This can also contain UTF-8 characters.
* @param monitor The monitor to use for full screen mode, or {@code null} to use windowed mode.
*/
public Window(int width, int height, String title, Monitor monitor)
{
this(width, height, title, monitor, null);
}
/**
* Creates a windowed mode window that is 800 by 600 in size and shares it's context with another window. Everything
* except the VAOs (Vertex Array Objects) are shared across the contexts.
*
* @param share The window who's context should be shared by the new window.
*/
public Window(Window share)
{
this(800, 600, share);
}
/**
* Creates a windowed mode window that has a given dimensions, and shares it's context with another window. The
* title is the default title, "SilenceEngine window". Everything except the VAOs (Vertex Array Objects) are shared
* across the context.
*
* @param width The desired width, in screen coordinates, of the window. This must be greater than zero.
* @param height The desired height, in screen coordinates, of the window. This must be greater than zero.
* @param share The window who's context should be shared by the new window.
*/
public Window(int width, int height, Window share)
{
this(width, height, "SilenceEngine window", share);
}
/**
* Creates a windowed mode window that has a given dimensions, a title, and shares it's context with another window.
* Everything except the VAOs (Vertex Array Objects) are shared across the context.
*
* @param width The desired width, in screen coordinates, of the window. This must be greater than zero.
* @param height The desired height, in screen coordinates, of the window. This must be greater than zero.
* @param title The desired title string of the Window. This can also contain UTF-8 characters.
* @param share The window who's context should be shared by the new window.
*/
public Window(int width, int height, String title, Window share)
{
this(width, height, title, null, share);
}
/**
* Creates a windowed mode window that has a specified title. The dimensions are the default dimensions, 800 by
* 600.
*
* @param title The desired title string of the Window. This can also contain UTF-8 characters.
*/
public Window(String title)
{
this(800, 600, title);
}
/**
* Creates a windowed mode window with the given dimensions and the title.
*
* @param width The desired width, in screen coordinates, of the window. This must be greater than zero.
* @param height The desired height, in screen coordinates, of the window. This must be greater than zero.
* @param title The desired title string of the Window. This can also contain UTF-8 characters.
*/
public Window(int width, int height, String title)
{
this(width, height, title, (Monitor) null);
}
/**
* Creates a fullscreen window on a monitor with a specific {@link VideoMode}.
*
* @param videoMode The VideoMode to use for the monitor.
* @param monitor The monitor that should be used for fullscreen.
*/
public Window(VideoMode videoMode, Monitor monitor)
{
this(videoMode, "SilenceEngine Window", monitor);
}
/**
* Creates a fullscreen window on a monitor with a specific {@link VideoMode} and a title.
*
* @param videoMode The VideoMode to use for the monitor.
* @param title The desired title string of the Window. This can also contain UTF-8 characters.
* @param monitor The monitor that should be used for fullscreen.
*/
public Window(VideoMode videoMode, String title, Monitor monitor)
{
this(videoMode, title, monitor, null);
}
/**
* Creates a fullscreen window on a monitor with a specific {@link VideoMode}, a title, and also shares it's context
* with an existing window. Everything except VAOs (Vertex Array Objects) are shared across contexts.
*
* @param videoMode The VideoMode to use for the monitor.
* @param title The desired title string of the Window. This can also contain UTF-8 characters.
* @param monitor The monitor that should be used for fullscreen.
* @param share The window who's context should be shared with the new window.
*/
public Window(VideoMode videoMode, String title, Monitor monitor, Window share)
{
this(videoMode.getWidth(), videoMode.getHeight(), title, monitor, videoMode.getRefreshRate(), share);
}
/**
* This method sets the window hints that would affect the next newly created window. The hints, once set, retain
* their values until changed by a call to {@link Window#setHint(int, int)} or {@link Window#setDefaultHints()} or
* this method. These are also cleared by terminating the GLFW library with {@link GLFW3#terminate()}.
*
* @param hint The window hint to be set. These hints are integer constants provided in the {@link GLFW} class.
* @param value The new value of the window hint.
*/
public static void setHint(int hint, boolean value)
{
setHint(hint, value ? 1 : 0);
}
/**
* This method sets the window hints that would affect the next newly created window. The hints, once set, retain
* their values until changed by a call to {@link Window#setHint(int, boolean)} or {@link Window#setDefaultHints()}
* or this method. These are also cleared by terminating the GLFW library with {@link GLFW3#terminate()}.
*
* @param hint The window hint to be set. These hints are integer constants provided in the {@link GLFW} class.
* @param value The new value of the window hint.
*/
public static void setHint(int hint, int value)
{
glfwWindowHint(hint, value);
}
/**
* This method resets all the window hints to their default values.
*/
public static void setDefaultHints()
{
glfwDefaultWindowHints();
}
/**
* This method returns the Window whose context is current on the thread that called this method.
*
* @return The window whose context is current in the current thread.
*/
public static Window getCurrentContext()
{
return registeredWindows.get(glfwGetCurrentContext());
}
/**
* Returns the native pointer of the window. This value can be casted to a {@code GLFWwindow*} in the native
* code. This is useful if you want to use the native glfw functions from the {@link GLFW} class.
*
* @return The native handle that corresponds to this window.
*/
public long getHandle()
{
return handle;
}
/**
* This method initialises the native callbacks, which just translate the events into the custom written callback
* interfaces. This is done to allow ease of development and more object oriented classes instead of long pointers.
*/
private void initNativeCallbacks()
{
// Initialize overriden callbacks
initCustomCallbacks();
// Create the callback functions that re-post the events
glfwCharCallback = GLFWCharCallback.create((window, codePoint) ->
characterCallback.invoke(registeredWindows.get(window), codePoint));
glfwCharModsCallback = GLFWCharModsCallback.create((window, codePoint, mods) ->
{
characterModsCallback.invoke(registeredWindows.get(window), codePoint, mods);
});
glfwCursorEnterCallback = GLFWCursorEnterCallback.create((window, entered) ->
cursorEnterCallback.invoke(registeredWindows.get(window), entered));
glfwCursorPosCallback = GLFWCursorPosCallback.create((win, xPos, yPos) ->
{
Window window = registeredWindows.get(win);
cursorPositionCallback.invoke(window, xPos, yPos);
});
glfwDropCallback = GLFWDropCallback.create((window, count, names) ->
{
String[] strings = new String[count];
for (int i = 0; i < count; i++)
strings[i] = GLFWDropCallback.getName(names, i);
dropCallback.invoke(registeredWindows.get(window), strings);
});
glfwFramebufferSizeCallback = GLFWFramebufferSizeCallback.create((window, width, height) ->
framebufferSizeCallback.invoke(registeredWindows.get(window), width, height));
glfwKeyCallback = GLFWKeyCallback.create((win, key, scanCode, action, mods) ->
{
Window window = registeredWindows.get(win);
keyCallback.invoke(window, key, scanCode, action, mods);
});
glfwMouseButtonCallback = GLFWMouseButtonCallback.create((win, button, action, mods) ->
{
Window window = registeredWindows.get(win);
mouseButtonCallback.invoke(window, button, action, mods);
});
glfwScrollCallback = GLFWScrollCallback.create((win, xOffset, yOffset) ->
{
Window window = registeredWindows.get(win);
scrollCallback.invoke(window, xOffset, yOffset);
});
glfwWindowCloseCallback = GLFWWindowCloseCallback.create((window) ->
windowCloseCallback.invoke(registeredWindows.get(window))
);
glfwWindowFocusCallback = GLFWWindowFocusCallback.create((window, focus) ->
windowFocusCallback.invoke(registeredWindows.get(window), focus)
);
glfwWindowIconifyCallback = GLFWWindowIconifyCallback.create((window, iconify) ->
windowIconifyCallback.invoke(registeredWindows.get(window), iconify)
);
glfwWindowPosCallback = GLFWWindowPosCallback.create((window, xPos, yPos) ->
windowPositionCallback.invoke(registeredWindows.get(window), xPos, yPos)
);
glfwWindowRefreshCallback = GLFWWindowRefreshCallback.create((window) ->
windowRefreshCallback.invoke(registeredWindows.get(window))
);
glfwWindowSizeCallback = GLFWWindowSizeCallback.create((window, width, height) ->
windowSizeCallback.invoke(registeredWindows.get(window), width, height)
);
// Register native callbacks
glfwSetCharCallback(handle, glfwCharCallback);
glfwSetCharModsCallback(handle, glfwCharModsCallback);
glfwSetCursorEnterCallback(handle, glfwCursorEnterCallback);
glfwSetCursorPosCallback(handle, glfwCursorPosCallback);
glfwSetDropCallback(handle, glfwDropCallback);
glfwSetFramebufferSizeCallback(handle, glfwFramebufferSizeCallback);
glfwSetKeyCallback(handle, glfwKeyCallback);
glfwSetMouseButtonCallback(handle, glfwMouseButtonCallback);
glfwSetScrollCallback(handle, glfwScrollCallback);
glfwSetWindowCloseCallback(handle, glfwWindowCloseCallback);
glfwSetWindowFocusCallback(handle, glfwWindowFocusCallback);
glfwSetWindowIconifyCallback(handle, glfwWindowIconifyCallback);
glfwSetWindowPosCallback(handle, glfwWindowPosCallback);
glfwSetWindowRefreshCallback(handle, glfwWindowRefreshCallback);
glfwSetWindowSizeCallback(handle, glfwWindowSizeCallback);
}
/**
* This method initialises the custom callbacks, which just sit here and doesn't do anything. This is nothing but
* simply setting them to null.
*/
private void initCustomCallbacks()
{
// The default callbacks does nothing
setCharacterCallback(null);
setCharacterModsCallback(null);
setCursorEnterCallback(null);
setCursorPositionCallback(null);
setDropCallback(null);
setFramebufferSizeCallback(null);
setKeyCallback(null);
setMouseButtonCallback(null);
setScrollCallback(null);
setCloseCallback(null);
setFocusCallback(null);
setIconifyCallback(null);
setPositionCallback(null);
setRefreshCallback(null);
setSizeCallback(null);
}
/**
* <p> This method returns the last state reported for the specified key to the specified window. The returned state
* is one of {@code GLFW_PRESS} or {@code GLFW_RELEASE}. The higher-level action {@code GLFW_REPEAT}
* is only reported to the key callback.</p>
*
* <p> If the {@code GLFW_STICKY_KEYS} input mode is enabled, this function returns {@code GLFW_PRESS} the
* first time you call it for a key that was pressed, even if that key has already been released.</p>
*
* <p> The key methods deal with physical keys, with key tokens named after their use on the standard US keyboard
* layout. If you want to input text, use the Unicode character callback instead.</p>
*
* <p> The modifier key bit masks are not key tokens and cannot be used with this method.</p>
*
* @param key The desired keyboard key. {@code GLFW_KEY_UNKNOWN} is not a valid key for this method.
*
* @return One of {@code GLFW_PRESS} or {@code GLFW_RELEASE}.
*/
public int getKey(int key)
{
return glfwGetKey(handle, key);
}
/**
* <p> This method returns the last state reported for the specified mouse button to the specified window. The
* returned state is one of {@code GLFW_PRESS} or {@code GLFW_RELEASE}.</p>
*
* <p> If the {@code GLFW_STICKY_MOUSE_BUTTONS} input mode is enabled, this method {@code GLFW_PRESS} the
* first time you call it for a mouse button that was pressed, even if that mouse button has already been released.
* </p>
*
* @param button The desired mouse button.
*
* @return One of {@code GLFW_PRESS} or {@code GLFW_RELEASE}.
*
* @see Window#setInputMode(int, int)
*/
public int getMouseButton(int button)
{
return glfwGetMouseButton(handle, button);
}
/**
* <p> This method returns the position of the cursor, in screen coordinates, relative to the upper-left corner of
* the client area of the specified window.</p>
*
* <p> If the cursor is disabled (with {@code GLFW_CURSOR_DISABLED}) then the cursor position is unbounded and
* limited only by the minimum and maximum values of a double.</p>
*
* @return The current position of the mouse cursor in screen coordinates, as a {@link Vector2} object.
*/
public Vector2 getCursorPos()
{
DoubleBuffer pos = BufferUtils.createDoubleBuffer(2);
nglfwGetCursorPos(handle, memAddress(pos), memAddress(pos) + Double.BYTES);
return new Vector2((float) pos.get(0), (float) pos.get(1));
}
/**
* <p> This method sets the position, in screen coordinates, of the cursor relative to the upper-left corner of the
* client area of the window. The window must have input focus. If the window does not have input focus when this
* method is called, it fails silently.</p>
*
* <p> <b>Do not use this method</b> to implement things like camera controls. GLFW already provides the
* {@code GLFW_CURSOR_DISABLED} cursor mode that hides the cursor, transparently re-centers it and provides
* unconstrained cursor motion. See {@link Window#setInputMode(int, int)} for more information.</p>
*
* <p> If the cursor mode is {@code GLFW_CURSOR_DISABLED} then the cursor position is unconstrained and limited
* only by the minimum and maximum values of a double.</p>
*
* @param pos The desired position of the cursor as a Vector2 object.
*/
public void setCursorPos(Vector2 pos)
{
setCursorPos(pos.x, pos.y);
}
/**
* <p> This method sets the position, in screen coordinates, of the cursor relative to the upper-left corner of the
* client area of the window. The window must have input focus. If the window does not have input focus when this
* method is called, it fails silently.</p>
*
* <p> <b>Do not use this method</b> to implement things like camera controls. GLFW already provides the
* {@code GLFW_CURSOR_DISABLED} cursor mode that hides the cursor, transparently re-centers it and provides
* unconstrained cursor motion. See {@link Window#setInputMode(int, int)} for more information.</p>
*
* <p> If the cursor mode is {@code GLFW_CURSOR_DISABLED} then the cursor position is unconstrained and limited
* only by the minimum and maximum values of a double.</p>
*
* @param xPos The desired x-coordinate, relative to the left edge of the client area.
* @param yPos The desired y-coordinate, relative to the top edge of the client area.
*/
public void setCursorPos(double xPos, double yPos)
{
glfwSetCursorPos(handle, xPos, yPos);
}
/**
* <p> This method sets an input mode option for this window. The mode must be one of {@code GLFW_CURSOR},
* {@code GLFW_STICKY_KEYS} or {@code GLFW_STICKY_MOUSE_BUTTONS}.</p>
*
* <p> If the mode is GLFW_CURSOR, the value must be one of the following cursor modes:</p>
*
* <ul> <li>{@code GLFW_CURSOR_NORMAL} makes the cursor visible and behaving normally.</li>
* <li>{@code GLFW_CURSOR_HIDDEN} makes the cursor invisible when it is over the client area of the window but
* does not restrict the cursor from leaving.</li> <li>{@code GLFW_CURSOR_DISABLED} hides and grabs the cursor,
* providing virtual and unlimited cursor movement. This is useful for implementing for example 3D camera
* controls.</li> </ul>
*
* <p> If the mode is {@code GLFW_STICKY_KEYS}, the value must be either {@code GL_TRUE} to enable sticky
* keys, or {@code GL_FALSE} to disable it. If sticky keys are enabled, a key press will ensure that {@link
* Window#getKey(int)} returns {@code GLFW_PRESS} the next time it is called even if the key had been released
* before the call. This is useful when you are only interested in whether keys have been pressed but not when or in
* which order.</p>
*
* <p> If the mode is {@code GLFW_STICKY_MOUSE_BUTTONS}, the value must be either {@code GL_TRUE} to
* enable sticky mouse buttons, or {@code GL_FALSE} to disable it. If sticky mouse buttons are enabled, a mouse
* button press will ensure that {@link Window#getMouseButton(int)} returns {@code GLFW_PRESS} the next time it
* is called even if the mouse button had been released before the call. This is useful when you are only interested
* in whether mouse buttons have been pressed but not when or in which order.</p>
*
* @param mode One of {@code GLFW_CURSOR}, {@code GLFW_STICKY_KEYS} or {@code GLFW_STICKY_MOUSE_BUTTONS}.
* @param value The new value of the specified input mode.
*/
public void setInputMode(int mode, int value)
{
glfwSetInputMode(handle, mode, value);
}
/**
* <p> This method sets the cursor image to be used when the cursor is over the client area of the specified window.
* The set cursor will only be visible when the cursor mode of the window is {@code GLFW_CURSOR_NORMAL}.</p>
*
* <p> On some platforms, the set cursor may not be visible unless the window also has input focus.</p>
*
* @param cursor The cursor to set, or {@code null} to switch back to the default arrow cursor.
*/
public void setCursor(Cursor cursor)
{
glfwSetCursor(handle, cursor == null ? NULL : cursor.getHandle());
}
/**
* <p> This method makes the OpenGL context of this window current on the calling thread. A context can only be made
* current on a single thread at a time and each thread can have only a single current context at a time.</p>
*
* <p> By default, making a context non-current implicitly forces a pipeline flush. On machines that support
* {@code GL_KHR_context_flush_control}, you can control whether a context performs this flush by setting the
* {@code GLFW_CONTEXT_RELEASE_BEHAVIOR} window hint.</p>
*/
public void makeCurrent()
{
glfwMakeContextCurrent(handle);
if (windowCapabilities == null)
windowCapabilities = GL.createCapabilities();
else
GL.setCapabilities(windowCapabilities);
}
public void setMonitor(Monitor monitor, VideoMode videoMode)
{
this.monitor = monitor;
if (videoMode == null)
{
Vector2 size = getSize();
videoMode = new VideoMode((int) size.x, (int) size.y, 32, 32, 32, 32);
}
glfwSetWindowMonitor(handle, monitor == null ? NULL : monitor.getHandle(), 0, 0, videoMode.getWidth(), videoMode.getHeight(), videoMode.getRefreshRate());
}
/**
* This method swaps the front and back buffers of the specified window. If the swap interval is greater than zero,
* the GPU driver waits the specified number of screen updates before swapping the buffers.
*/
public void swapBuffers()
{
glfwSwapBuffers(handle);
}
/**
* This method returns the value of the close flag of this window.
*
* @return The close flag of this window.
*/
public boolean shouldClose()
{
return glfwWindowShouldClose(handle);
}
public void maximize()
{
glfwMaximizeWindow(handle);
}
/**
* Sets the icon for the window.
*
* @param image The image to be used as an icon.
*/
public void setIcon(Image image)
{
int width = image.getWidth();
int height = image.getHeight();
GLFWImage.Buffer glfwImages = GLFWImage.calloc(1);
GLFWImage glfwImage = glfwImages.get(0);
glfwImage.width(width);
glfwImage.height(height);
ByteBuffer data = BufferUtils.createByteBuffer(width * height * 4);
Color color = Color.REUSABLE_STACK.pop();
for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x++)
{
image.getPixel(x, y, color);
float r = (color.r * 255f);
float g = (color.g * 255f);
float b = (color.b * 255f);
float a = (color.a * 255f);
data.put((byte) r)
.put((byte) g)
.put((byte) b)
.put((byte) a);
}
}
Color.REUSABLE_STACK.push(color);
data.flip();
glfwImage.pixels(data);
glfwSetWindowIcon(handle, glfwImages);
glfwImages.free();
}
/**
* Sets the icon for the window.
*
* @param imagePath The image to be used as an icon.
* @param success The callback to be called upon successful icon set.
*/
public void setIcon(FilePath imagePath, SimpleCallback success)
{
SilenceEngine.io.getImageReader().readImage(imagePath, image ->
{
setIcon(image);
success.invoke();
});
}
/**
* Sets the icon for the window.
*
* @param imagePath The image to be used as an icon.
* @param success The callback to be called upon successful icon set.
* @param error The callback to be called upon an error.
*/
public void setIcon(FilePath imagePath, SimpleCallback success, UniCallback<Throwable> error)
{
SilenceEngine.io.getImageReader().readImage(imagePath, image ->
{
setIcon(image);
success.invoke();
}, error);
}
/**
* This method sets the value of the close flag of this window. This can be used to override the user's attempt to
* close the window, or to signal that it should be closed.
*
* @param value The new value.
*/
public void setShouldClose(boolean value)
{
glfwSetWindowShouldClose(handle, value);
}
/**
* <p> This method iconifies (minimizes) this window if it was previously restored. If the window is already
* iconified, this method does nothing.</p>
*
* <p> If this window is a full screen window, the original monitor resolution is restored until the window is
* restored again.</p>
*/
public void iconify()
{
glfwIconifyWindow(handle);
}
/**
* <p> This method restores this window if it was previously iconified (minimized). If the window is already
* restored, this method does nothing.</p>
*
* <p> If this window is a full screen window, the resolution chosen for the window is restored on the selected
* monitor.</p>
*/
public void restore()
{
glfwRestoreWindow(handle);
}
/**
* This method hides this window if it was previously visible. If the window is already hidden or is in full screen
* mode, this method does nothing.
*/
public void hide()
{
glfwHideWindow(handle);
}
/**
* This method makes this window visible if it was previously hidden. If the window is already visible or is in full
* screen mode, this method does nothing.
*/
public void show()
{
glfwShowWindow(handle);
}
/**
* This method destroys this window and its context. On calling this method, no further callbacks will be called for
* this window. If the context of this window is current on the main thread, it is detached before being destroyed.
* The context of this window must not be current on any other thread when this function is called.
*/
public void destroy()
{
releaseNativeCallbacks();
glfwDestroyWindow(handle);
}
/**
* This method releases the native callbacks, preventing the occurrence of segmentation fault errors from the JNI
* code, which usually occurs due to the function address not being cleared from the native code. Releasing these
* callbacks erases the function address, so it can't be called again.
*/
private void releaseNativeCallbacks()
{
glfwCharCallback.free();
glfwCharModsCallback.free();
glfwCursorEnterCallback.free();
glfwCursorPosCallback.free();
glfwDropCallback.free();
glfwFramebufferSizeCallback.free();
glfwKeyCallback.free();
glfwMouseButtonCallback.free();
glfwScrollCallback.free();
glfwWindowCloseCallback.free();
glfwWindowFocusCallback.free();
glfwWindowIconifyCallback.free();
glfwWindowPosCallback.free();
glfwWindowRefreshCallback.free();
glfwWindowSizeCallback.free();
}
/**
* This method retrieves the position, in screen coordinates, of the upper-left corner of the client area of this
* window. If any error occurs, the position is set to zero.
*
* @return The position of the upper-left corner of the client area of this window, as a Vector2.
*/
public Vector2 getPosition()
{
IntBuffer pos = BufferUtils.createIntBuffer(2);
nglfwGetWindowPos(handle, memAddress(pos), memAddress(pos) + Integer.BYTES);
return position.set(pos.get(0), pos.get(1));
}
/**
* <p> This method sets the position, in screen coordinates, of the upper-left corner of the client area of this
* windowed mode window. If the window is a full screen window, this function does nothing.</p>
*
* <p> <b>Do not use this method</b> to move an already visible window unless you have very good reasons for doing
* so, as it will confuse and annoy the user.</p>
*
* <p> The window manager may put limits on what positions are allowed. GLFW cannot and should not override these
* limits.</p>
*
* @param position The new position of this window.
*/
public void setPosition(Vector2 position)
{
this.position.set(position);
glfwSetWindowPos(handle, (int) position.x, (int) position.y);
}
/**
* <p> This method sets the position, in screen coordinates, of the upper-left corner of the client area of this
* windowed mode window. If the window is a full screen window, this function does nothing.</p>
*
* <p> <b>Do not use this method</b> to move an already visible window unless you have very good reasons for doing
* so, as it will confuse and annoy the user.</p>
*
* <p> The window manager may put limits on what positions are allowed. GLFW cannot and should not override these
* limits.</p>
*
* @param x The x-coordinate of the upper-left corner of the client area.
* @param y The y-coordinate of the upper-left corner of the client area.
*/
public void setPosition(float x, float y)
{
setPosition(position.set(x, y));
}
/**
* This method retrieves the size, in screen coordinates, of the client area of this window. If you wish to retrieve
* the size of the framebuffer of the window in pixels, see {@link Window#getFramebufferSize()}.
*
* @return The size of the client area of this window, in screen coordinates, as a Vector2.
*/
public Vector2 getSize()
{
IntBuffer size = BufferUtils.createIntBuffer(2);
nglfwGetWindowSize(handle, memAddress(size), memAddress(size) + Integer.BYTES);
return this.size.set(size.get(0), size.get(1));
}
/**
* <p> This method sets the size, in screen coordinates, of the client area of this window.</p>
*
* <p> For full screen windows, this method selects and switches to the resolution closest to the specified size,
* without affecting the window's context. As the context is unaffected, the bit depths of the framebuffer remain
* unchanged.</p>
*
* <p> The window manager may put limits on what sizes are allowed. GLFW cannot and should not override these
* limits.</p>
*
* @param size The new size of the client area of this window, in screen coordinates, as a Vector2.
*/
public void setSize(Vector2 size)
{
this.size.set(size);
glfwSetWindowSize(handle, (int) size.x, (int) size.y);
}
/**
* <p> This method sets the size, in screen coordinates, of the client area of this window.</p>
*
* <p> For full screen windows, this method selects and switches to the resolution closest to the specified size,
* without affecting the window's context. As the context is unaffected, the bit depths of the framebuffer remain
* unchanged.</p>
*
* <p> The window manager may put limits on what sizes are allowed. GLFW cannot and should not override these
* limits.</p>
*
* @param width The desired width of the specified window.
* @param height The desired height of the specified window.
*/
public void setSize(float width, float height)
{
setSize(size.set(width, height));
}
/**
* This method retrieves the size, in pixels, of the framebuffer of this window. If you wish to retrieve the size of
* the window in screen coordinates, see {@link Window#getSize()}.
*
* @return The size of the window framebuffer, in pixels, as a Vector2.
*/
public Vector2 getFramebufferSize()
{
IntBuffer size = BufferUtils.createIntBuffer(2);
nglfwGetFramebufferSize(handle, memAddress(size), memAddress(size) + Integer.BYTES);
return framebufferSize.set(size.get(0), size.get(1));
}
/**
* This method resizes the window such that the framebuffer is fixed to the size specified. The difference to the
* {@code setSize()} methods is that this method accepts the input in pixels, while those methods accept the
* input in screen coordinates.
*
* @param fbSize The size of the framebuffer in pixels.
*/
public void setFramebufferSize(Vector2 fbSize)
{
Vector2 temp = Vector2.REUSABLE_STACK.pop();
Vector2 framebufferSize = getFramebufferSize();
Vector2 size = getSize();
temp.set(size).scale(1 / framebufferSize.x, 1 / framebufferSize.y);
this.framebufferSize.set(fbSize);
size.set(fbSize).scale(temp.x, temp.y);
setSize(size);
Vector2.REUSABLE_STACK.push(temp);
}
/**
* This method resizes the window such that the framebuffer is fixed to the size specified. The difference to the
* {@code setSize()} methods is that this method accepts the input in pixels, while those methods accept the
* input in screen coordinates.
*
* @param width The width of the window framebuffer, in pixels.
* @param height The height of the window framebuffer, in pixels.
*/
public void setFramebufferSize(float width, float height)
{
Vector2 temp = Vector2.REUSABLE_STACK.pop();
setFramebufferSize(temp.set(width, height));
Vector2.REUSABLE_STACK.push(temp);
}
public String getClipboardString()
{
return glfwGetClipboardString(handle);
}
public void setClipboardString(String string)
{
glfwSetClipboardString(handle, string);
}
/**
* <p> This method retrieves the size, in screen coordinates, of each edge of the frame of this window. This size
* includes the title bar, if the window has one. The size of the frame may vary depending on the window-related
* hints used to create it.</p>
*
* <p> Because this method retrieves the size of each window frame edge and not the offset along a particular
* coordinate axis, the retrieved values will always be zero or positive.</p>
*
* @return The size of the frame as a Vector4. The x-component is the size of the left edge, y-component is the top
* edge, z-component is the right edge and the last w-component is the size of the bottom edge.
*/
public Vector4 getFrameSize()
{
IntBuffer size = BufferUtils.createIntBuffer(4);
long left = memAddress(size);
long top = left + Integer.BYTES;
long right = top + Integer.BYTES;
long bottom = right + Integer.BYTES;
nglfwGetWindowFrameSize(handle, left, top, right, bottom);
return new Vector4(size.get(0), size.get(1), size.get(2), size.get(3));
}
/**
* This methods returns the monitor that this window is fullscreen upon. If this window is in windowed mode, then
* the monitor will be {@code null}.
*
* @return The monitor used by this window.
*/
public Monitor getMonitor()
{
return monitor;
}
public void setMonitor(Monitor monitor)
{
setMonitor(monitor, monitor == null ? null : monitor.getVideoMode());
}
/**
* This method returns the title of this window.
*
* @return The title of this window, encoded as UTF-8 string.
*/
public String getTitle()
{
return title;
}
/**
* This method sets the title of the window, which is a string encoding in UTF-8.
*
* @param title The new title of this window.
*/
public void setTitle(String title)
{
this.title = title;
glfwSetWindowTitle(handle, title);
}
/**
* This method returns the value of an attribute of the specified window or its OpenGL context.
*
* @param attribute The window attribute whose value to return.
*
* @return The value of the attribute, or zero if an error occurred.
*/
public int getAttribute(int attribute)
{
return glfwGetWindowAttrib(handle, attribute);
}
/**
* Returns the currently set {@link ICharacterCallback} of this window object.
*
* @return The currently set character callback, or {@code null} if there is none.
*/
public ICharacterCallback getCharacterCallback()
{
return characterCallback;
}
/**
* This method sets a {@link ICharacterCallback} with this window, allowing you to listen to character input events
* that happened on this window.
*
* @param callback The callback instance which will be invoked when a character input event occurs.
*
* @return The previously set callback, or {@code null} if there is no previously set callback.
*/
public ICharacterCallback setCharacterCallback(ICharacterCallback callback)
{
ICharacterCallback previousCallback = characterCallback;
if (callback == null)
callback = (window, codePoint) ->
{
};
this.characterCallback = callback;
return previousCallback;
}
/**
* This method returns the currently set {@link ICharacterModsCallback} for this window. If there is no callback
* registered, this method returns {@code null}.
*
* @return The currently set character mods callback on this window.
*/
public ICharacterModsCallback getCharacterModsCallback()
{
return characterModsCallback;
}
/**
* This method sets the {@link ICharacterModsCallback} used by this window to notify input events. This method also
* returns the previously set callback for you.
*
* @param callback The new {@link ICharacterModsCallback} to be used.
*
* @return The previously used callback, or {@code null} if there is none.
*/
public ICharacterModsCallback setCharacterModsCallback(ICharacterModsCallback callback)
{
ICharacterModsCallback previousCallback = characterModsCallback;
if (callback == null)
callback = (window, cp, mods) ->
{
};
this.characterModsCallback = callback;
return previousCallback;
}
/**
* This method returns the currently set {@link ICursorEnterCallback} on this window. If there is no callback, then
* this method returns {@code null}.
*
* @return The currently set {@link ICursorEnterCallback}, or {@code null} if there is none.
*/
public ICursorEnterCallback getCursorEnterCallback()
{
return cursorEnterCallback;
}
/**
* This method sets the {@link ICursorEnterCallback} on this window. Also, it returns the previously set callback.
*
* @param callback The new {@link ICursorEnterCallback} to be used, or {@code null} to clear it.
*
* @return The previously used callback, or {@code null} if there is none.
*/
public ICursorEnterCallback setCursorEnterCallback(ICursorEnterCallback callback)
{
ICursorEnterCallback previousCallback = cursorEnterCallback;
if (callback == null)
callback = (window, entered) ->
{
};
this.cursorEnterCallback = callback;
return previousCallback;
}
/**
* This method returns the currently set {@link ICursorPositionCallback} on this window.
*
* @return The currently set callback, or {@code null} if there is none set.
*/
public ICursorPositionCallback getCursorPositionCallback()
{
return cursorPositionCallback;
}
/**
* This method sets the {@link ICursorPositionCallback} to be used by this window. If you want to clear the existing
* callback, pass {@code null} as the argument.
*
* @param callback The new {@link ICursorPositionCallback} to be used.
*
* @return The previously set callback, or {@code null} if there is none set.
*/
public ICursorPositionCallback setCursorPositionCallback(ICursorPositionCallback callback)
{
ICursorPositionCallback previousCallback = cursorPositionCallback;
if (callback == null)
callback = (window, x, y) ->
{
};
this.cursorPositionCallback = callback;
return previousCallback;
}
/**
* This method returns the currently set {@link IDropCallback} on this window. If there is no callback set, then
* {@code null} is returned to you.
*
* @return The currently set callback, or {@code null} if there is none set.
*/
public IDropCallback getDropCallback()
{
return dropCallback;
}
/**
* This method sets a {@link IDropCallback} to be used by this Window. To clear the current callback, just pass
* {@code null} to the argument.
*
* @param callback The new callback to be used by this window, or {@code null} to clear the existing one.
*
* @return The previously used callback, or {@code null} if there is none set.
*/
public IDropCallback setDropCallback(IDropCallback callback)
{
IDropCallback previousCallback = dropCallback;
if (callback == null)
callback = (window, paths) ->
{
};
this.dropCallback = callback;
return previousCallback;
}
/**
* This method returns the currently used {@link IFramebufferSizeCallback} by this window. If there is no existing
* callback, then this method returns {@code null} to you.
*
* @return The current callback, or {@code null} if none is set previously.
*/
public IFramebufferSizeCallback getFramebufferSizeCallback()
{
return framebufferSizeCallback;
}
/**
* This method sets the {@link IFramebufferSizeCallback} used by this window. If you want to clear the existing
* callback, simply pass {@code null} as the value for the argument.
*
* @param callback The new callback to be used, or {@code null} to clear the existing one.
*
* @return The previously used callback, or {@code null} if none exists before.
*/
public IFramebufferSizeCallback setFramebufferSizeCallback(IFramebufferSizeCallback callback)
{
IFramebufferSizeCallback previousCallback = framebufferSizeCallback;
if (callback == null)
callback = (window, w, h) ->
{
};
this.framebufferSizeCallback = callback;
return previousCallback;
}
/**
* This method returns the currently used {@link IKeyCallback} of this window. If there is no callback set before,
* this method returns {@code null} to you.
*
* @return The currently used key callback of this window.
*/
public IKeyCallback getKeyCallback()
{
return keyCallback;
}
/**
* This method sets the {@link IKeyCallback} used by this window object. If you want to clear the existing one, just
* pass {@code null} as the value of the argument.
*
* @param callback The new callback to be used, or {@code null} to clear the existing one.
*
* @return The previously used key callback, or {@code null} if there is nothing previously set.
*/
public IKeyCallback setKeyCallback(IKeyCallback callback)
{
IKeyCallback previousCallback = keyCallback;
if (callback == null)
callback = (win, key, sc, act, mods) ->
{
};
this.keyCallback = callback;
return previousCallback;
}
/**
* This method returns the currently set {@link IMouseButtonCallback} of this Window object. If there is nothing set
* before, then this method returns {@code null} to you.
*
* @return The currently set mouse button callback, or {@code null} if there is nothing set previously.
*/
public IMouseButtonCallback getMouseButtonCallback()
{
return mouseButtonCallback;
}
/**
* This method sets the {@link IMouseButtonCallback} used by this window object. If you want to clear the existing
* callback, simply pass {@code null} as the value of the argument.
*
* @param callback The new callback to be used, or {@code null} if you want to clear it.
*
* @return The previously set mouse button callback, or {@code null} if there is nothing set previously.
*/
public IMouseButtonCallback setMouseButtonCallback(IMouseButtonCallback callback)
{
IMouseButtonCallback previousCallback = mouseButtonCallback;
if (callback == null)
callback = (win, b, act, mods) ->
{
};
this.mouseButtonCallback = callback;
return previousCallback;
}
/**
* This method returns the {@link IScrollCallback} used by this window object. If there is no callback registered,
* then this method returns {@code null}.
*
* @return The current scroll callback, or {@code null} if there is nothing set previously.
*/
public IScrollCallback getScrollCallback()
{
return scrollCallback;
}
/**
* This method sets the {@link IScrollCallback} used by this window object. If you want to clear the existing
* callback, simply pass {@code null} to the argument.
*
* @param callback The new callback to be used, or {@code null} if you want to clear existing callback.
*
* @return The previously used scroll callback, or {@code null} if there isn't any.
*/
public IScrollCallback setScrollCallback(IScrollCallback callback)
{
IScrollCallback previousCallback = scrollCallback;
if (callback == null)
callback = (win, x, y) ->
{
};
this.scrollCallback = callback;
return previousCallback;
}
/**
* This method returns the current {@link IWindowCloseCallback} of this window object. If there is no existing
* callback, this method returns {@code null} as the return value.
*
* @return The current window close callback, or {@code null} if there is nothing previously.
*/
public IWindowCloseCallback getCloseCallback()
{
return windowCloseCallback;
}
/**
* This method sets the {@link IWindowCloseCallback} used by this window object. If you want to clear the existing
* callback, then simply pass {@code null} to the value of the argument.
*
* @param callback The new callback to be used, or {@code null} if you want to clear the existing one.
*
* @return The previously set close callback, or {@code null} if nothing is set previously.
*/
public IWindowCloseCallback setCloseCallback(IWindowCloseCallback callback)
{
IWindowCloseCallback previousCallback = windowCloseCallback;
if (callback == null)
callback = (win) ->
{
};
this.windowCloseCallback = callback;
return previousCallback;
}
/**
* This method returns the currently set {@link IWindowFocusCallback} of this window object. If there is no existing
* callback, then {@code null} is returned to you.
*
* @return The currently set focus callback, or {@code null} if there is nothing set previously.
*/
public IWindowFocusCallback getFocusCallback()
{
return windowFocusCallback;
}
/**
* This method sets the {@link IWindowFocusCallback} used by this window object. If you want to clear out the
* existing callback, then simply pass {@code null} as the value of the argument.
*
* @param callback The new callback to be used, or {@code null} to clear the existing one.
*
* @return The previously used focus callback, or {@code null} if there is nothing set previously.
*/
public IWindowFocusCallback setFocusCallback(IWindowFocusCallback callback)
{
IWindowFocusCallback previousCallback = windowFocusCallback;
if (callback == null)
callback = (win, focused) ->
{
};
this.windowFocusCallback = callback;
return previousCallback;
}
/**
* This method returns the {@link IWindowIconifyCallback} used by this window object. If there is no existing
* callback, then {@code null} is returned.
*
* @return The currently used iconify callback, or {@code null} if there is none set previously.
*/
public IWindowIconifyCallback getIconifyCallback()
{
return windowIconifyCallback;
}
/**
* This method sets the {@link IWindowIconifyCallback} used by this window object. If you want to clear the existing
* callback, simply pass {@code null} as the value of the argument.
*
* @param callback The new callback to be used, or {@code null} to clear the existing callback.
*
* @return The previously used iconify callback, or {@code null} if there is none set previously.
*/
public IWindowIconifyCallback setIconifyCallback(IWindowIconifyCallback callback)
{
IWindowIconifyCallback previousCallback = windowIconifyCallback;
if (callback == null)
callback = (win, ic) ->
{
};
this.windowIconifyCallback = callback;
return previousCallback;
}
/**
* This method returns the currently set {@link IWindowPositionCallback} of this window object. If there is nothing
* set previously, then this method returns {@code null}.
*
* @return The current window position callback, or {@code null} if there is nothing previously set.
*/
public IWindowPositionCallback getPositionCallback()
{
return windowPositionCallback;
}
/**
* This method sets the {@link IWindowPositionCallback} of this window object. If you want to clear the existing
* callback, then simply pass {@code null} to the value of the argument.
*
* @param callback The new callback to be used, or {@code null} to clear the existing one.
*
* @return The previously used callback, or {@code null} if there is nothing previously set.
*/
public IWindowPositionCallback setPositionCallback(IWindowPositionCallback callback)
{
IWindowPositionCallback previousCallback = windowPositionCallback;
if (callback == null)
callback = (win, x, y) ->
{
};
this.windowPositionCallback = callback;
return previousCallback;
}
/**
* This method returns the currently set {@link IWindowRefreshCallback} on this window object. If there is no
* callback previously set, this method will return {@code null} to you.
*
* @return The currently set window refresh callback, or {@code null} if there is nothing set previously.
*/
public IWindowRefreshCallback getRefreshCallback()
{
return windowRefreshCallback;
}
/**
* This method sets the {@link IWindowRefreshCallback} on this window object. If you want to clear out the existing
* callback, then simply pass {@code null} as the value to the argument.
*
* @param callback The new callback to be used, or {@code null} to clear the existing callback.
*
* @return The previously used callback, or {@code null} if there is nothing set previously.
*/
public IWindowRefreshCallback setRefreshCallback(IWindowRefreshCallback callback)
{
IWindowRefreshCallback previousCallback = windowRefreshCallback;
if (callback == null)
callback = (win) ->
{
};
this.windowRefreshCallback = callback;
return previousCallback;
}
/**
* This method returns the currently used {@link IWindowSizeCallback} of this window object. If there is no existing
* callback, this method returns {@code null}.
*
* @return The currently set window size callback, or {@code null} if there is nothing set previously.
*/
public IWindowSizeCallback getSizeCallback()
{
return windowSizeCallback;
}
/**
* This method sets the {@link IWindowSizeCallback} used by this window object. If you want to clear the existing
* callback, simply pass {@code null} as the argument.
*
* @param callback The new callback to be used, or {@code null} to clear the existing one.
*
* @return The previously used callback, or {@code null} if there is nothing set previously.
*/
public IWindowSizeCallback setSizeCallback(IWindowSizeCallback callback)
{
IWindowSizeCallback previousCallback = windowSizeCallback;
if (callback == null)
callback = (win, w, h) ->
{
};
this.windowSizeCallback = callback;
return previousCallback;
}
/**
* This methods returns the current monitor that this window is on. If the window is over multiple screen it will
* pick the one that has more of the window on the monitor. In the case of being equal it will pick the monitor that
* is called first.
*
* @return The monitor that the window is on.
*/
public Monitor getCurrentMonitor()
{
int bestoverlap = 0;
Monitor currentMonitor = null;
int wx = (int) getPosition().x;
int wy = (int) getPosition().y;
int ww = (int) getSize().x;
int wh = (int) getSize().y;
for (Monitor monitor : Monitor.getMonitors())
{
Vector2 vPos = monitor.getVirtualPosition();
VideoMode vMode = monitor.getVideoMode();
int mx = (int) vPos.x;
int my = (int) vPos.y;
int mw = vMode.getWidth();
int mh = vMode.getHeight();
int overlap = Math.max(0, Math.min(wx + ww, mx + mw) - Math.max(wx, mx)) * Math.max(0, Math.min(wy + wh, my + mh) - Math.max(wy, my));
if (bestoverlap < overlap)
{
bestoverlap = overlap;
currentMonitor = monitor;
}
}
return currentMonitor;
}
/**
* Returns the GL capabilities instance of this window. If the window haven't been made current even once, then this
* method returns {@code null} to the caller.
*
* @return The GLCapabilities instance.
*/
public GLCapabilities getCapabilities()
{
return windowCapabilities;
}
}