Add monitor API and add UUIDs

This commit is contained in:
JeremyStar™ 2024-07-27 02:25:10 +02:00
parent 45307ab842
commit 935bbaf7ce
Signed by: JeremyStarTM
GPG key ID: E366BAEF67E4704D
13 changed files with 565 additions and 23 deletions

View file

@ -0,0 +1,69 @@
/*
* STAROPENSOURCE ENGINE SOURCE FILE
* Copyright (c) 2024 The StarOpenSource Engine Contributors
* Licensed under the GNU Affero General Public License v3
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.staropensource.sosengine.graphics.glfw.classes;
import de.staropensource.sosengine.base.logging.Logger;
import de.staropensource.sosengine.base.types.CodePart;
import de.staropensource.sosengine.base.types.logging.LogIssuer;
import de.staropensource.sosengine.graphics.classes.Monitor;
import de.staropensource.sosengine.graphics.classes.api.ApiInternalClass;
import de.staropensource.sosengine.graphics.exceptions.NoMonitorsFoundException;
import org.jetbrains.annotations.NotNull;
import org.lwjgl.PointerBuffer;
import java.lang.reflect.InvocationTargetException;
import java.util.LinkedHashSet;
import static org.lwjgl.glfw.GLFW.*;
@SuppressWarnings({ "unused" })
public abstract class GlfwInternalClass implements ApiInternalClass {
/**
* Returns the {@link Monitor} class.
*
* @return {@link Monitor} class
* @since v1-alpha2
*/
@NotNull
public abstract Class<? extends Monitor> getMonitorClass();
/**
* Returns all connected monitors.
*
* @return connected monitors
* @since v1-alpha2
*/
@Override
public @NotNull LinkedHashSet<@NotNull Monitor> getMonitors() throws NoMonitorsFoundException {
PointerBuffer monitors = glfwGetMonitors();
LinkedHashSet<@NotNull Monitor> output = new LinkedHashSet<>();
if (monitors == null)
throw new NoMonitorsFoundException();
while (monitors.hasRemaining())
try {
output.add(getMonitorClass().getDeclaredConstructor(Long.TYPE).newInstance(monitors.get()));
} catch (NoSuchMethodException | InstantiationException | IllegalAccessException | InvocationTargetException exception) {
Logger.crash(new LogIssuer(getClass(), CodePart.ENGINE), "Unable to create new Monitor instance: Threw an exception", exception);
}
return output;
}
}

View file

@ -58,6 +58,7 @@ public abstract class GlfwManagementClass extends ApiManagementClass {
LinkedHashMap<@NotNull Window, @NotNull Throwable> throwables = new LinkedHashMap<>(); LinkedHashMap<@NotNull Window, @NotNull Throwable> throwables = new LinkedHashMap<>();
// Update and render all windows
for (Window window : Window.getWindows()) { for (Window window : Window.getWindows()) {
try { try {
window.updateState(); window.updateState();
@ -67,6 +68,8 @@ public abstract class GlfwManagementClass extends ApiManagementClass {
throwables.put(window, throwable); throwables.put(window, throwable);
} }
} }
// Poll for events
glfwPollEvents(); glfwPollEvents();
return throwables; return throwables;

View file

@ -0,0 +1,114 @@
/*
* STAROPENSOURCE ENGINE SOURCE FILE
* Copyright (c) 2024 The StarOpenSource Engine Contributors
* Licensed under the GNU Affero General Public License v3
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.staropensource.sosengine.graphics.glfw.classes;
import de.staropensource.sosengine.base.types.vectors.Vec2i;
import de.staropensource.sosengine.graphics.classes.Monitor;
import de.staropensource.sosengine.graphics.exceptions.InvalidMonitorException;
import lombok.SneakyThrows;
import org.jetbrains.annotations.NotNull;
import org.lwjgl.glfw.GLFWVidMode;
import java.util.Objects;
import static org.lwjgl.glfw.GLFW.*;
@SuppressWarnings({ "unused", "JavadocDeclaration", "JavadocBlankLines" })
public class GlfwMonitor extends Monitor {
/**
* Contains the {@link #identifier} as a long.
*
* @since v1-alpha2
*
* -- GETTER --
* Returns the monitor identifier as a long.
*
* @return monitor identifier as a long
* @since v1-alpha2
*/
private final long identifierLong;
/**
* Constructs this class.
*
* @param identifier glfw monitor pointer
* @since v1-alpha2
*/
@SneakyThrows
public GlfwMonitor(long identifier) throws InvalidMonitorException {
// Set identifier
setIdentifier(String.valueOf(identifier));
identifierLong = identifier;
// Check if connected
checkConnected();
}
/** {@inheritDoc} */
@SneakyThrows
public void checkConnected() throws InvalidMonitorException {
super.checkConnected();
}
/** {@inheritDoc} */
@Override
public boolean isConnected() {
return glfwGetMonitorName(identifierLong) != null;
}
/**
* Returns the monitor name.
*
* @return monitor name
* @since v1-alpha2
*/
@Override
public @NotNull String getName() throws InvalidMonitorException {
checkConnected();
return Objects.requireNonNull(glfwGetMonitorName(identifierLong));
}
/**
* Returns the monitor size.
*
* @return monitor size
* @since v1-alpha2
*/
@Override
public @NotNull Vec2i getSize() throws InvalidMonitorException {
checkConnected();
GLFWVidMode videoMode = Objects.requireNonNull(glfwGetVideoMode(identifierLong));
return new Vec2i(videoMode.width(), videoMode.height());
}
/**
* Returns the monitor refresh rate.
*
* @return monitor refresh rate
* @since v1-alpha2
*/
@Override
public short getRefreshRate() throws InvalidMonitorException {
checkConnected();
return (short) Objects.requireNonNull(glfwGetVideoMode(identifierLong)).refreshRate();
}
}

View file

@ -24,6 +24,7 @@ import de.staropensource.sosengine.base.types.Tristate;
import de.staropensource.sosengine.base.types.vectors.Vec2i; import de.staropensource.sosengine.base.types.vectors.Vec2i;
import de.staropensource.sosengine.base.utility.Miscellaneous; import de.staropensource.sosengine.base.utility.Miscellaneous;
import de.staropensource.sosengine.graphics.GraphicsSubsystemConfiguration; import de.staropensource.sosengine.graphics.GraphicsSubsystemConfiguration;
import de.staropensource.sosengine.graphics.classes.Monitor;
import de.staropensource.sosengine.graphics.classes.Window; import de.staropensource.sosengine.graphics.classes.Window;
import de.staropensource.sosengine.graphics.events.GraphicsApiErrorEvent; import de.staropensource.sosengine.graphics.events.GraphicsApiErrorEvent;
import de.staropensource.sosengine.graphics.events.InputEvent; import de.staropensource.sosengine.graphics.events.InputEvent;
@ -41,6 +42,7 @@ import org.lwjgl.system.MemoryStack;
import org.lwjgl.system.MemoryUtil; import org.lwjgl.system.MemoryUtil;
import java.nio.IntBuffer; import java.nio.IntBuffer;
import java.util.Objects;
import static org.lwjgl.glfw.GLFW.*; import static org.lwjgl.glfw.GLFW.*;
@ -90,6 +92,7 @@ public abstract class GlfwWindow extends Window {
* @param maximumSize maximum size * @param maximumSize maximum size
* @param position position * @param position position
* @param windowMode window mode * @param windowMode window mode
* @param monitor monitor
* @param resizable resizable flag * @param resizable resizable flag
* @param borderless borderless flag * @param borderless borderless flag
* @param focusable focusable flag * @param focusable focusable flag
@ -99,8 +102,8 @@ public abstract class GlfwWindow extends Window {
* @throws UnexpectedThrowableException stuff thrown by the {@link #initializeWindow()} and {@link #render()} methods of the implementing Graphics API * @throws UnexpectedThrowableException stuff thrown by the {@link #initializeWindow()} and {@link #render()} methods of the implementing Graphics API
* @since v1-alpha2 * @since v1-alpha2
*/ */
public GlfwWindow(@NotNull String name, @NotNull String title, @NotNull Vec2i size, @NotNull Vec2i minimumSize, @NotNull Vec2i maximumSize, @NotNull Vec2i position, @NotNull WindowMode windowMode, boolean resizable, boolean borderless, boolean focusable, boolean onTop, boolean transparent, boolean rendering) throws UnexpectedThrowableException { public GlfwWindow(@NotNull String name, @NotNull String title, @NotNull Vec2i size, @NotNull Vec2i minimumSize, @NotNull Vec2i maximumSize, @NotNull Vec2i position, @NotNull WindowMode windowMode, @NotNull Monitor monitor, boolean resizable, boolean borderless, boolean focusable, boolean onTop, boolean transparent, boolean rendering) throws UnexpectedThrowableException {
super(name, title, size, minimumSize, maximumSize, position, windowMode, resizable, borderless, focusable, onTop, transparent, rendering); super(name, title, size, minimumSize, maximumSize, position, windowMode, monitor, resizable, borderless, focusable, onTop, transparent, rendering);
} }
/** {@inheritDoc} */ /** {@inheritDoc} */
@ -226,6 +229,31 @@ public abstract class GlfwWindow extends Window {
if (!Miscellaneous.onMainThread()) if (!Miscellaneous.onMainThread())
throw new NotOnMainThreadException(); throw new NotOnMainThreadException();
// Update window mode
if (Miscellaneous.getBooleanizedInteger(glfwGetWindowAttrib(identifierLong, GLFW_ICONIFIED)))
super.setWindowMode(WindowMode.MINIMIZED);
else if (Miscellaneous.getBooleanizedInteger(glfwGetWindowAttrib(identifierLong, GLFW_MAXIMIZED)))
super.setWindowMode(WindowMode.MAXIMIZED);
else if (Miscellaneous.getBooleanizedInteger(glfwGetWindowAttrib(identifierLong, GLFW_VISIBLE)))
super.setWindowMode(WindowMode.WINDOWED);
else if (Miscellaneous.getBooleanizedInteger(glfwGetWindowAttrib(identifierLong, GLFW_VISIBLE)))
super.setWindowMode(WindowMode.HIDDEN);
// Update monitor
if (!getMonitor().isConnected()) {
Monitor newMonitor = null;
for (Monitor monitor : Monitor.getMonitors())
if (monitor.isConnected())
newMonitor = monitor;
if (newMonitor == null)
getLogger().crash("Unable to set a new target monitor for window " + getUniqueIdentifier() + " as no monitors are connected to the system");
setMonitor(Objects.requireNonNull(newMonitor));
}
// Update vectors
try (MemoryStack stack = MemoryStack.stackPush()) { try (MemoryStack stack = MemoryStack.stackPush()) {
IntBuffer width = stack.mallocInt(2); IntBuffer width = stack.mallocInt(2);
IntBuffer height = stack.mallocInt(2); IntBuffer height = stack.mallocInt(2);
@ -237,16 +265,6 @@ public abstract class GlfwWindow extends Window {
super.setPosition(new Vec2i(width.get(), height.get())); super.setPosition(new Vec2i(width.get(), height.get()));
} }
// Update window mode
if (Miscellaneous.getBooleanizedInteger(glfwGetWindowAttrib(identifierLong, GLFW_ICONIFIED)))
super.setWindowMode(WindowMode.MINIMIZED);
else if (Miscellaneous.getBooleanizedInteger(glfwGetWindowAttrib(identifierLong, GLFW_MAXIMIZED)))
super.setWindowMode(WindowMode.MAXIMIZED);
else if (Miscellaneous.getBooleanizedInteger(glfwGetWindowAttrib(identifierLong, GLFW_VISIBLE)))
super.setWindowMode(WindowMode.WINDOWED);
else if (Miscellaneous.getBooleanizedInteger(glfwGetWindowAttrib(identifierLong, GLFW_VISIBLE)))
super.setWindowMode(WindowMode.HIDDEN);
// Update booleans // Update booleans
super.setResizable(Miscellaneous.getBooleanizedInteger(glfwGetWindowAttrib(identifierLong, GLFW_RESIZABLE))); super.setResizable(Miscellaneous.getBooleanizedInteger(glfwGetWindowAttrib(identifierLong, GLFW_RESIZABLE)));
super.setOnTop(Miscellaneous.getBooleanizedInteger(glfwGetWindowAttrib(identifierLong, GLFW_FLOATING))); super.setOnTop(Miscellaneous.getBooleanizedInteger(glfwGetWindowAttrib(identifierLong, GLFW_FLOATING)));

View file

@ -19,16 +19,27 @@
package de.staropensource.sosengine.graphics.opengl; package de.staropensource.sosengine.graphics.opengl;
import de.staropensource.sosengine.graphics.classes.Monitor;
import de.staropensource.sosengine.graphics.classes.api.ApiInternalClass; import de.staropensource.sosengine.graphics.classes.api.ApiInternalClass;
import de.staropensource.sosengine.graphics.classes.Window; import de.staropensource.sosengine.graphics.classes.Window;
import de.staropensource.sosengine.graphics.glfw.classes.GlfwInternalClass;
import de.staropensource.sosengine.graphics.opengl.classes.OpenGlMonitor;
import de.staropensource.sosengine.graphics.opengl.classes.OpenGlWindow; import de.staropensource.sosengine.graphics.opengl.classes.OpenGlWindow;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
public final class OpenGlInternalApi implements ApiInternalClass { import java.util.Set;
public final class OpenGlInternalApi extends GlfwInternalClass {
/** {@inheritDoc} */ /** {@inheritDoc} */
@Override @Override
@NotNull @NotNull
public Class<? extends Window> getWindowClass() { public Class<? extends Window> getWindowClass() {
return OpenGlWindow.class; return OpenGlWindow.class;
} }
/** {@inheritDoc} */
@Override
public @NotNull Class<? extends Monitor> getMonitorClass() {
return OpenGlMonitor.class;
}
} }

View file

@ -0,0 +1,35 @@
/*
* STAROPENSOURCE ENGINE SOURCE FILE
* Copyright (c) 2024 The StarOpenSource Engine Contributors
* Licensed under the GNU Affero General Public License v3
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.staropensource.sosengine.graphics.opengl.classes;
import de.staropensource.sosengine.graphics.exceptions.InvalidMonitorException;
import de.staropensource.sosengine.graphics.glfw.classes.GlfwMonitor;
public class OpenGlMonitor extends GlfwMonitor {
/**
* Constructs this class.
*
* @param identifier glfw monitor pointer
* @since v1-alpha2
*/
public OpenGlMonitor(long identifier) throws InvalidMonitorException {
super(identifier);
}
}

View file

@ -21,6 +21,7 @@ package de.staropensource.sosengine.graphics.opengl.classes;
import de.staropensource.sosengine.base.exceptions.UnexpectedThrowableException; import de.staropensource.sosengine.base.exceptions.UnexpectedThrowableException;
import de.staropensource.sosengine.base.types.vectors.Vec2i; import de.staropensource.sosengine.base.types.vectors.Vec2i;
import de.staropensource.sosengine.graphics.classes.Monitor;
import de.staropensource.sosengine.graphics.glfw.classes.GlfwWindow; import de.staropensource.sosengine.graphics.glfw.classes.GlfwWindow;
import de.staropensource.sosengine.graphics.exceptions.NotOnMainThreadException; import de.staropensource.sosengine.graphics.exceptions.NotOnMainThreadException;
import de.staropensource.sosengine.graphics.exceptions.WindowCreationFailureException; import de.staropensource.sosengine.graphics.exceptions.WindowCreationFailureException;
@ -57,8 +58,8 @@ public final class OpenGlWindow extends GlfwWindow {
* @throws UnexpectedThrowableException stuff thrown by the {@link #initializeWindow()} and {@link #render()} methods of the implementing Graphics API * @throws UnexpectedThrowableException stuff thrown by the {@link #initializeWindow()} and {@link #render()} methods of the implementing Graphics API
* @since v1-alpha2 * @since v1-alpha2
*/ */
public OpenGlWindow(@NotNull String name, @NotNull String title, @NotNull Vec2i size, @NotNull Vec2i minimumSize, @NotNull Vec2i maximumSize, @NotNull Vec2i position, @NotNull WindowMode windowMode, boolean resizable, boolean borderless, boolean focusable, boolean onTop, boolean transparent, boolean rendering) throws UnexpectedThrowableException { public OpenGlWindow(@NotNull String name, @NotNull String title, @NotNull Vec2i size, @NotNull Vec2i minimumSize, @NotNull Vec2i maximumSize, @NotNull Vec2i position, @NotNull WindowMode windowMode, @NotNull Monitor monitor, boolean resizable, boolean borderless, boolean focusable, boolean onTop, boolean transparent, boolean rendering) throws UnexpectedThrowableException {
super(name, title, size, minimumSize, maximumSize, position, windowMode, resizable, borderless, focusable, onTop, transparent, rendering); super(name, title, size, minimumSize, maximumSize, position, windowMode, monitor, resizable, borderless, focusable, onTop, transparent, rendering);
} }
/** {@inheritDoc} */ /** {@inheritDoc} */

View file

@ -0,0 +1,171 @@
/*
* STAROPENSOURCE ENGINE SOURCE FILE
* Copyright (c) 2024 The StarOpenSource Engine Contributors
* Licensed under the GNU Affero General Public License v3
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.staropensource.sosengine.graphics.classes;
import de.staropensource.sosengine.base.logging.LoggerInstance;
import de.staropensource.sosengine.base.types.CodePart;
import de.staropensource.sosengine.base.types.logging.LogIssuer;
import de.staropensource.sosengine.base.types.vectors.Vec2i;
import de.staropensource.sosengine.graphics.GraphicsSubsystem;
import de.staropensource.sosengine.graphics.exceptions.InvalidMonitorException;
import de.staropensource.sosengine.graphics.exceptions.NoMonitorsFoundException;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.Setter;
import org.jetbrains.annotations.NotNull;
import java.util.LinkedHashSet;
import java.util.UUID;
/**
* Abstract class for implementing monitors in a Graphics API.
* <p>
* Note that monitors stop working unannounced when disconnected,
* call {@link #isConnected()} before using to avoid unexpected behaviour.
*
* @since v1-alpha2
*/
@SuppressWarnings({ "unused", "JavadocDeclaration", "JavadocBlankLines" })
public abstract class Monitor {
/**
* The logger instance for this class.
*
* @see LoggerInstance
* @since v1-alpha2
*
* -- GETTER --
* Returns the logger instance for this class.
*
* @return logger instance
* @see LoggerInstance
* @since v1-alpha2
*/
@Getter(value = AccessLevel.PROTECTED)
private final LoggerInstance logger = new LoggerInstance(new LogIssuer(getClass(), CodePart.ENGINE));
/**
* Contains the unique monitor identifier.
* <p>
* This identifier is unique to every monitor and does not change during runtime.
*
* @since v1-alpha2
*
* -- GETTER --
* Returns the unique monitor identifier.
* <p>
* This identifier is unique to every monitor and does not change during runtime.
*
* @return unique identifier
* @since v1-alpha2
*/
@Getter
private final UUID uniqueIdentifier;
/**
* Contains the monitor identifier.
* <p>
* This identifier is used by the Graphics API to refer to a monitor and may change during runtime.
*
* @since v1-alpha1
*
* -- GETTER --
* Returns the monitor identifier.
* <p>
* This identifier is used by the Graphics API to refer to a monitor and may change during runtime.
*
* @return monitor identifier
* @since v1-alpha2
*
* -- SETTER --
* Sets the monitor identifier.
* <p>
* This identifier is used by the Graphics API to refer to a monitor and may change during runtime.
*
* @param identifier new monitor identifier
* @since v1-alpha2
*/
@Setter(AccessLevel.PROTECTED)
private String identifier = null;
/**
* Constructs this class.
*
* @since v1-alpha2
*/
public Monitor() {
this.uniqueIdentifier = UUID.randomUUID();
}
/**
* Returns all connected monitors.
*
* @return connected monitors
* @since v1-alpha2
*/
@NotNull
public static LinkedHashSet<@NotNull Monitor> getMonitors() throws NoMonitorsFoundException {
return GraphicsSubsystem.getInstance().getApi().getInternalApi().getMonitors();
}
/**
* Checks if the monitor is actually connected.
* If not, throws an {@link InvalidMonitorException}.
*
* @since v1-alpha2
*/
public void checkConnected() throws InvalidMonitorException, NoMonitorsFoundException {
if (!isConnected())
throw new InvalidMonitorException();
}
/**
* Checks if the monitor is connected or not.
*
* @return connection status
* @since v1-alpha2
*/
public abstract boolean isConnected() throws NoMonitorsFoundException;
/**
* Returns the monitor name.
*
* @return monitor name
* @since v1-alpha2
*/
@NotNull
public abstract String getName() throws InvalidMonitorException, NoMonitorsFoundException;
/**
* Returns the monitor size.
*
* @return monitor size
* @since v1-alpha2
*/
@NotNull
public abstract Vec2i getSize() throws InvalidMonitorException, NoMonitorsFoundException;
/**
* Returns the monitor refresh rate.
*
* @return monitor refresh rate
* @since v1-alpha2
*/
public abstract short getRefreshRate() throws InvalidMonitorException, NoMonitorsFoundException;
}

View file

@ -35,6 +35,7 @@ import org.jetbrains.annotations.Nullable;
import java.util.HashSet; import java.util.HashSet;
import java.util.Set; import java.util.Set;
import java.util.UUID;
/** /**
* Abstract class for implementing windows in a Graphics API. * Abstract class for implementing windows in a Graphics API.
@ -94,13 +95,34 @@ public abstract class Window implements AutoCloseable {
@Setter(AccessLevel.PROTECTED) @Setter(AccessLevel.PROTECTED)
private boolean terminated; private boolean terminated;
/**
* Contains the unique window identifier.
* <p>
* This identifier is unique to every window and does not change during runtime.
*
* @since v1-alpha2
*
* -- GETTER --
* Returns the unique window identifier.
* <p>
* This identifier is unique to every window and does not change during runtime.
*
* @return unique identifier
* @since v1-alpha2
*/
private final UUID uniqueIdentifier;
/** /**
* Contains the window identifier. * Contains the window identifier.
* <p>
* This identifier is used by the Graphics API to refer to a window and may change during runtime.
* *
* @since v1-alpha1 * @since v1-alpha1
* *
* -- GETTER -- * -- GETTER --
* Returns the window identifier. * Returns the window identifier.
* <p>
* This identifier is used by the Graphics API to refer to a window and may change during runtime.
* *
* @return window identifier * @return window identifier
* @since v1-alpha2 * @since v1-alpha2
@ -108,7 +130,7 @@ public abstract class Window implements AutoCloseable {
* -- SETTER -- * -- SETTER --
* Sets the window identifier. * Sets the window identifier.
* <p> * <p>
* Recommended to be called only once. * This identifier is used by the Graphics API to refer to a window and may change during runtime.
* *
* @param identifier new window identifier * @param identifier new window identifier
* @since v1-alpha2 * @since v1-alpha2
@ -317,6 +339,27 @@ public abstract class Window implements AutoCloseable {
@Setter @Setter
private WindowMode windowMode; private WindowMode windowMode;
/**
* Determines on which {@link Monitor} the window is displayed on.
*
* @since v1-alpha2
*
* -- GETTER --
* Returns the {@link Monitor} the window is displayed on.
*
* @return target monitor
* @since v1-alpha2
*
* -- SETTER --
* Sets the {@link Monitor} the window is displayed on.
*
* @param monitor new target monitor
* @since v1-alpha2
*/
@NotNull
@Setter
private Monitor monitor;
/** /**
* Determines how fast the window may update it's contents. * Determines how fast the window may update it's contents.
* *
@ -485,6 +528,7 @@ public abstract class Window implements AutoCloseable {
* @param maximumSize maximum size * @param maximumSize maximum size
* @param position position * @param position position
* @param windowMode window mode * @param windowMode window mode
* @param monitor monitor
* @param resizable resizable flag * @param resizable resizable flag
* @param borderless borderless flag * @param borderless borderless flag
* @param focusable focusable flag * @param focusable focusable flag
@ -494,10 +538,9 @@ public abstract class Window implements AutoCloseable {
* @throws UnexpectedThrowableException stuff thrown by the {@link #initializeWindow()} and {@link #render()} methods of the implementing Graphics API * @throws UnexpectedThrowableException stuff thrown by the {@link #initializeWindow()} and {@link #render()} methods of the implementing Graphics API
* @since v1-alpha2 * @since v1-alpha2
*/ */
public Window(@NotNull String name, @NotNull String title, @NotNull Vec2i size, @NotNull Vec2i minimumSize, @NotNull Vec2i maximumSize, @NotNull Vec2i position, @NotNull WindowMode windowMode, boolean resizable, boolean borderless, boolean focusable, boolean onTop, boolean transparent, boolean rendering) throws UnexpectedThrowableException { public Window(@NotNull String name, @NotNull String title, @NotNull Vec2i size, @NotNull Vec2i minimumSize, @NotNull Vec2i maximumSize, @NotNull Vec2i position, @NotNull WindowMode windowMode, @NotNull Monitor monitor, boolean resizable, boolean borderless, boolean focusable, boolean onTop, boolean transparent, boolean rendering) throws UnexpectedThrowableException {
logger.diag("Creating new window with properties: name=\"" + name + "\" title=\"" + title + "\" size=" + size + " minimumSize=" + minimumSize + " maximumSize=" + maximumSize + " position=" + position + " windowMode=" + windowMode + " resizable=" + resizable + " borderless=" + borderless + " focusable=" + focusable + " onTop=" + onTop + " transparent=" + transparent + " rendering=" + rendering);
// Initialize variables // Initialize variables
this.uniqueIdentifier = UUID.randomUUID();
this.name = name; this.name = name;
this.title = title; this.title = title;
this.size = size; this.size = size;
@ -505,6 +548,7 @@ public abstract class Window implements AutoCloseable {
this.maximumSize = maximumSize; this.maximumSize = maximumSize;
this.position = position; this.position = position;
this.windowMode = windowMode; this.windowMode = windowMode;
this.monitor = monitor;
this.resizable = resizable; this.resizable = resizable;
this.borderless = borderless; this.borderless = borderless;
this.focusable = focusable; this.focusable = focusable;
@ -512,6 +556,9 @@ public abstract class Window implements AutoCloseable {
this.transparent = transparent; this.transparent = transparent;
this.rendering = rendering; this.rendering = rendering;
// Log about window creation
logger.diag("Creating new window with properties: uniqueIdentifier=" + uniqueIdentifier + " name=\"" + name + "\" title=\"" + title + "\" size=" + size + " minimumSize=" + minimumSize + " maximumSize=" + maximumSize + " position=" + position + " windowMode=" + windowMode + " monitor=" + monitor.getUniqueIdentifier() + " (" + monitor.getName() + ") resizable=" + resizable + " borderless=" + borderless + " focusable=" + focusable + " onTop=" + onTop + " transparent=" + transparent + " rendering=" + rendering);
try { try {
// Allow Graphics API to initialize window // Allow Graphics API to initialize window
initializeWindow(); initializeWindow();
@ -752,6 +799,22 @@ public abstract class Window implements AutoCloseable {
@Nullable @Nullable
private WindowMode windowMode = null; private WindowMode windowMode = null;
/**
* Contains the target monitor.
*
* @see Window#monitor
* @since v1-alpha2
*
* -- GETTER --
* Returns the target monitor.
*
* @return target monitor
* @see Window#monitor
* @since v1-alpha2
*/
@Nullable
private Monitor monitor = null;
/** /**
* Contains the resizable flag. * Contains the resizable flag.
* *
@ -888,6 +951,8 @@ public abstract class Window implements AutoCloseable {
maximumSize = new Vec2i(-1, -1); maximumSize = new Vec2i(-1, -1);
if (windowMode == null) if (windowMode == null)
windowMode = WindowMode.WINDOWED; windowMode = WindowMode.WINDOWED;
if (monitor == null)
monitor = Monitor.getMonitors().getFirst();
// Override booleanized tristate defaults // Override booleanized tristate defaults
if (resizable == Tristate.FALSE) if (resizable == Tristate.FALSE)
@ -906,8 +971,8 @@ public abstract class Window implements AutoCloseable {
// Create new Window instance // Create new Window instance
try { try {
return GraphicsSubsystem.getInstance().getApi().getInternalApi().getWindowClass() return GraphicsSubsystem.getInstance().getApi().getInternalApi().getWindowClass()
.getDeclaredConstructor(String.class, String.class, Vec2i.class, Vec2i.class, Vec2i.class, Vec2i.class, WindowMode.class, Boolean.TYPE, Boolean.TYPE, Boolean.TYPE, Boolean.TYPE, Boolean.TYPE, Boolean.TYPE) .getDeclaredConstructor(String.class, String.class, Vec2i.class, Vec2i.class, Vec2i.class, Vec2i.class, WindowMode.class, Monitor.class, Boolean.TYPE, Boolean.TYPE, Boolean.TYPE, Boolean.TYPE, Boolean.TYPE, Boolean.TYPE)
.newInstance(name, title, size, minimumSize, maximumSize, position, windowMode, resizableBoolean, borderlessBoolean, focusableBoolean, onTopBoolean, transparentBoolean, renderingBoolean); .newInstance(name, title, size, minimumSize, maximumSize, position, windowMode, monitor, resizableBoolean, borderlessBoolean, focusableBoolean, onTopBoolean, transparentBoolean, renderingBoolean);
} catch (Throwable throwable) { } catch (Throwable throwable) {
throw new UnexpectedThrowableException(throwable, "Window.Builder was unable to create new Window instance"); throw new UnexpectedThrowableException(throwable, "Window.Builder was unable to create new Window instance");
} }
@ -1004,6 +1069,19 @@ public abstract class Window implements AutoCloseable {
return this; return this;
} }
/**
* Sets the target monitor.
*
* @param monitor new target monitor
* @return builder instance
* @since v1-alpha2
*/
@NotNull
private synchronized Builder setMonitor(@Nullable Monitor monitor) {
this.monitor = monitor;
return this;
}
/** /**
* Sets the resizable flag. * Sets the resizable flag.
* *

View file

@ -19,9 +19,13 @@
package de.staropensource.sosengine.graphics.classes.api; package de.staropensource.sosengine.graphics.classes.api;
import de.staropensource.sosengine.graphics.classes.Monitor;
import de.staropensource.sosengine.graphics.classes.Window; import de.staropensource.sosengine.graphics.classes.Window;
import de.staropensource.sosengine.graphics.exceptions.NoMonitorsFoundException;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import java.util.LinkedHashSet;
/** /**
* The interface for internal API access, used by the graphics subsystem. * The interface for internal API access, used by the graphics subsystem.
* *
@ -33,7 +37,17 @@ public interface ApiInternalClass {
* Returns the {@link Window} class. * Returns the {@link Window} class.
* *
* @return {@link Window} class * @return {@link Window} class
* @since v1-alpha2
*/ */
@NotNull @NotNull
Class<? extends Window> getWindowClass(); Class<? extends Window> getWindowClass();
/**
* Returns all connected monitors.
*
* @return connected monitors
* @since v1-alpha2
*/
@NotNull
LinkedHashSet<@NotNull Monitor> getMonitors() throws NoMonitorsFoundException;
} }

View file

@ -64,7 +64,8 @@ public class InputEvent implements Event {
*/ */
public void callEvent(@Nullable Window window, @NotNull Key key, @NotNull KeyState state) { public void callEvent(@Nullable Window window, @NotNull Key key, @NotNull KeyState state) {
if (GraphicsSubsystemConfiguration.getInstance().isDebugInput()) if (GraphicsSubsystemConfiguration.getInstance().isDebugInput())
logger.diag("Got input event: window=" + (window == null ? "<null>" : window.getName() + (window.getName() == null ? "" : "(" + window.getName() + ")") + "[" + window.hashCode() + "]") + " key=" + key.name() + " state=" + state.name()); logger.diag("Got input event: window=" + (window == null ? "\\<null>" : window.getUniqueIdentifier()) + " key=" + key.name() + " state=" + state.name());
EventHelper.invokeAnnotatedMethods(getClass(), window, key, state); EventHelper.invokeAnnotatedMethods(getClass(), window, key, state);
} }
} }

View file

@ -0,0 +1,27 @@
/*
* STAROPENSOURCE ENGINE SOURCE FILE
* Copyright (c) 2024 The StarOpenSource Engine Contributors
* Licensed under the GNU Affero General Public License v3
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.staropensource.sosengine.graphics.exceptions;
/**
* Thrown when the specified monitor could not be found.
*
* @since v1-alpha2
*/
public class InvalidMonitorException extends RuntimeException {}

View file

@ -25,4 +25,4 @@ package de.staropensource.sosengine.graphics.exceptions;
* @since v1-alpha2 * @since v1-alpha2
*/ */
@SuppressWarnings({ "unused" }) @SuppressWarnings({ "unused" })
public final class NoMonitorsFoundException extends Exception {} public final class NoMonitorsFoundException extends RuntimeException {}