diff --git a/graphics/glfw/src/main/java/de/staropensource/sosengine/graphics/glfw/classes/GlfwInternalClass.java b/graphics/glfw/src/main/java/de/staropensource/sosengine/graphics/glfw/classes/GlfwInternalClass.java
new file mode 100644
index 0000000..1d3ffd8
--- /dev/null
+++ b/graphics/glfw/src/main/java/de/staropensource/sosengine/graphics/glfw/classes/GlfwInternalClass.java
@@ -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 .
+ */
+
+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;
+ }
+}
diff --git a/graphics/glfw/src/main/java/de/staropensource/sosengine/graphics/glfw/classes/GlfwManagementClass.java b/graphics/glfw/src/main/java/de/staropensource/sosengine/graphics/glfw/classes/GlfwManagementClass.java
index 995b377..548907d 100644
--- a/graphics/glfw/src/main/java/de/staropensource/sosengine/graphics/glfw/classes/GlfwManagementClass.java
+++ b/graphics/glfw/src/main/java/de/staropensource/sosengine/graphics/glfw/classes/GlfwManagementClass.java
@@ -58,6 +58,7 @@ public abstract class GlfwManagementClass extends ApiManagementClass {
LinkedHashMap<@NotNull Window, @NotNull Throwable> throwables = new LinkedHashMap<>();
+ // Update and render all windows
for (Window window : Window.getWindows()) {
try {
window.updateState();
@@ -67,6 +68,8 @@ public abstract class GlfwManagementClass extends ApiManagementClass {
throwables.put(window, throwable);
}
}
+
+ // Poll for events
glfwPollEvents();
return throwables;
diff --git a/graphics/glfw/src/main/java/de/staropensource/sosengine/graphics/glfw/classes/GlfwMonitor.java b/graphics/glfw/src/main/java/de/staropensource/sosengine/graphics/glfw/classes/GlfwMonitor.java
new file mode 100644
index 0000000..2072fbb
--- /dev/null
+++ b/graphics/glfw/src/main/java/de/staropensource/sosengine/graphics/glfw/classes/GlfwMonitor.java
@@ -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 .
+ */
+
+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();
+ }
+}
diff --git a/graphics/glfw/src/main/java/de/staropensource/sosengine/graphics/glfw/classes/GlfwWindow.java b/graphics/glfw/src/main/java/de/staropensource/sosengine/graphics/glfw/classes/GlfwWindow.java
index eea8c51..aaafa2a 100644
--- a/graphics/glfw/src/main/java/de/staropensource/sosengine/graphics/glfw/classes/GlfwWindow.java
+++ b/graphics/glfw/src/main/java/de/staropensource/sosengine/graphics/glfw/classes/GlfwWindow.java
@@ -24,6 +24,7 @@ import de.staropensource.sosengine.base.types.Tristate;
import de.staropensource.sosengine.base.types.vectors.Vec2i;
import de.staropensource.sosengine.base.utility.Miscellaneous;
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.events.GraphicsApiErrorEvent;
import de.staropensource.sosengine.graphics.events.InputEvent;
@@ -41,6 +42,7 @@ import org.lwjgl.system.MemoryStack;
import org.lwjgl.system.MemoryUtil;
import java.nio.IntBuffer;
+import java.util.Objects;
import static org.lwjgl.glfw.GLFW.*;
@@ -90,6 +92,7 @@ public abstract class GlfwWindow extends Window {
* @param maximumSize maximum size
* @param position position
* @param windowMode window mode
+ * @param monitor monitor
* @param resizable resizable flag
* @param borderless borderless 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
* @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 {
- super(name, title, size, minimumSize, maximumSize, position, windowMode, resizable, borderless, focusable, onTop, transparent, rendering);
+ 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, monitor, resizable, borderless, focusable, onTop, transparent, rendering);
}
/** {@inheritDoc} */
@@ -226,6 +229,31 @@ public abstract class GlfwWindow extends Window {
if (!Miscellaneous.onMainThread())
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()) {
IntBuffer width = 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()));
}
- // 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
super.setResizable(Miscellaneous.getBooleanizedInteger(glfwGetWindowAttrib(identifierLong, GLFW_RESIZABLE)));
super.setOnTop(Miscellaneous.getBooleanizedInteger(glfwGetWindowAttrib(identifierLong, GLFW_FLOATING)));
diff --git a/graphics/opengl/src/main/java/de/staropensource/sosengine/graphics/opengl/OpenGlInternalApi.java b/graphics/opengl/src/main/java/de/staropensource/sosengine/graphics/opengl/OpenGlInternalApi.java
index 720ad0c..fbb1bb8 100644
--- a/graphics/opengl/src/main/java/de/staropensource/sosengine/graphics/opengl/OpenGlInternalApi.java
+++ b/graphics/opengl/src/main/java/de/staropensource/sosengine/graphics/opengl/OpenGlInternalApi.java
@@ -19,16 +19,27 @@
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.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 org.jetbrains.annotations.NotNull;
-public final class OpenGlInternalApi implements ApiInternalClass {
+import java.util.Set;
+
+public final class OpenGlInternalApi extends GlfwInternalClass {
/** {@inheritDoc} */
@Override
@NotNull
public Class extends Window> getWindowClass() {
return OpenGlWindow.class;
}
+
+ /** {@inheritDoc} */
+ @Override
+ public @NotNull Class extends Monitor> getMonitorClass() {
+ return OpenGlMonitor.class;
+ }
}
diff --git a/graphics/opengl/src/main/java/de/staropensource/sosengine/graphics/opengl/classes/OpenGlMonitor.java b/graphics/opengl/src/main/java/de/staropensource/sosengine/graphics/opengl/classes/OpenGlMonitor.java
new file mode 100644
index 0000000..3e18666
--- /dev/null
+++ b/graphics/opengl/src/main/java/de/staropensource/sosengine/graphics/opengl/classes/OpenGlMonitor.java
@@ -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 .
+ */
+
+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);
+ }
+}
diff --git a/graphics/opengl/src/main/java/de/staropensource/sosengine/graphics/opengl/classes/OpenGlWindow.java b/graphics/opengl/src/main/java/de/staropensource/sosengine/graphics/opengl/classes/OpenGlWindow.java
index c809eb6..9e7727c 100644
--- a/graphics/opengl/src/main/java/de/staropensource/sosengine/graphics/opengl/classes/OpenGlWindow.java
+++ b/graphics/opengl/src/main/java/de/staropensource/sosengine/graphics/opengl/classes/OpenGlWindow.java
@@ -21,6 +21,7 @@ package de.staropensource.sosengine.graphics.opengl.classes;
import de.staropensource.sosengine.base.exceptions.UnexpectedThrowableException;
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.exceptions.NotOnMainThreadException;
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
* @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 {
- super(name, title, size, minimumSize, maximumSize, position, windowMode, resizable, borderless, focusable, onTop, transparent, rendering);
+ 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, monitor, resizable, borderless, focusable, onTop, transparent, rendering);
}
/** {@inheritDoc} */
diff --git a/graphics/src/main/java/de/staropensource/sosengine/graphics/classes/Monitor.java b/graphics/src/main/java/de/staropensource/sosengine/graphics/classes/Monitor.java
new file mode 100644
index 0000000..b68811a
--- /dev/null
+++ b/graphics/src/main/java/de/staropensource/sosengine/graphics/classes/Monitor.java
@@ -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 .
+ */
+
+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.
+ *
+ * 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.
+ *
+ * This identifier is unique to every monitor and does not change during runtime.
+ *
+ * @since v1-alpha2
+ *
+ * -- GETTER --
+ * Returns the unique monitor identifier.
+ *
+ * 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.
+ *
+ * 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.
+ *
+ * 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.
+ *
+ * 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;
+}
diff --git a/graphics/src/main/java/de/staropensource/sosengine/graphics/classes/Window.java b/graphics/src/main/java/de/staropensource/sosengine/graphics/classes/Window.java
index d89d280..c5fd967 100644
--- a/graphics/src/main/java/de/staropensource/sosengine/graphics/classes/Window.java
+++ b/graphics/src/main/java/de/staropensource/sosengine/graphics/classes/Window.java
@@ -35,6 +35,7 @@ import org.jetbrains.annotations.Nullable;
import java.util.HashSet;
import java.util.Set;
+import java.util.UUID;
/**
* Abstract class for implementing windows in a Graphics API.
@@ -94,13 +95,34 @@ public abstract class Window implements AutoCloseable {
@Setter(AccessLevel.PROTECTED)
private boolean terminated;
+ /**
+ * Contains the unique window identifier.
+ *
+ * This identifier is unique to every window and does not change during runtime.
+ *
+ * @since v1-alpha2
+ *
+ * -- GETTER --
+ * Returns the unique window identifier.
+ *
+ * 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.
+ *
+ * This identifier is used by the Graphics API to refer to a window and may change during runtime.
*
* @since v1-alpha1
*
* -- GETTER --
* Returns the window identifier.
+ *
+ * This identifier is used by the Graphics API to refer to a window and may change during runtime.
*
* @return window identifier
* @since v1-alpha2
@@ -108,7 +130,7 @@ public abstract class Window implements AutoCloseable {
* -- SETTER --
* Sets the window identifier.
*
- * 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
* @since v1-alpha2
@@ -317,6 +339,27 @@ public abstract class Window implements AutoCloseable {
@Setter
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.
*
@@ -485,6 +528,7 @@ public abstract class Window implements AutoCloseable {
* @param maximumSize maximum size
* @param position position
* @param windowMode window mode
+ * @param monitor monitor
* @param resizable resizable flag
* @param borderless borderless 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
* @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 {
- 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);
-
+ 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 {
// Initialize variables
+ this.uniqueIdentifier = UUID.randomUUID();
this.name = name;
this.title = title;
this.size = size;
@@ -505,6 +548,7 @@ public abstract class Window implements AutoCloseable {
this.maximumSize = maximumSize;
this.position = position;
this.windowMode = windowMode;
+ this.monitor = monitor;
this.resizable = resizable;
this.borderless = borderless;
this.focusable = focusable;
@@ -512,6 +556,9 @@ public abstract class Window implements AutoCloseable {
this.transparent = transparent;
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 {
// Allow Graphics API to initialize window
initializeWindow();
@@ -752,6 +799,22 @@ public abstract class Window implements AutoCloseable {
@Nullable
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.
*
@@ -888,6 +951,8 @@ public abstract class Window implements AutoCloseable {
maximumSize = new Vec2i(-1, -1);
if (windowMode == null)
windowMode = WindowMode.WINDOWED;
+ if (monitor == null)
+ monitor = Monitor.getMonitors().getFirst();
// Override booleanized tristate defaults
if (resizable == Tristate.FALSE)
@@ -906,8 +971,8 @@ public abstract class Window implements AutoCloseable {
// Create new Window instance
try {
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)
- .newInstance(name, title, size, minimumSize, maximumSize, position, windowMode, resizableBoolean, borderlessBoolean, focusableBoolean, onTopBoolean, transparentBoolean, renderingBoolean);
+ .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, monitor, resizableBoolean, borderlessBoolean, focusableBoolean, onTopBoolean, transparentBoolean, renderingBoolean);
} catch (Throwable throwable) {
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;
}
+ /**
+ * 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.
*
diff --git a/graphics/src/main/java/de/staropensource/sosengine/graphics/classes/api/ApiInternalClass.java b/graphics/src/main/java/de/staropensource/sosengine/graphics/classes/api/ApiInternalClass.java
index c62c5ad..cfc10e5 100644
--- a/graphics/src/main/java/de/staropensource/sosengine/graphics/classes/api/ApiInternalClass.java
+++ b/graphics/src/main/java/de/staropensource/sosengine/graphics/classes/api/ApiInternalClass.java
@@ -19,9 +19,13 @@
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.exceptions.NoMonitorsFoundException;
import org.jetbrains.annotations.NotNull;
+import java.util.LinkedHashSet;
+
/**
* The interface for internal API access, used by the graphics subsystem.
*
@@ -33,7 +37,17 @@ public interface ApiInternalClass {
* Returns the {@link Window} class.
*
* @return {@link Window} class
+ * @since v1-alpha2
*/
@NotNull
Class extends Window> getWindowClass();
+
+ /**
+ * Returns all connected monitors.
+ *
+ * @return connected monitors
+ * @since v1-alpha2
+ */
+ @NotNull
+ LinkedHashSet<@NotNull Monitor> getMonitors() throws NoMonitorsFoundException;
}
diff --git a/graphics/src/main/java/de/staropensource/sosengine/graphics/events/InputEvent.java b/graphics/src/main/java/de/staropensource/sosengine/graphics/events/InputEvent.java
index ad9dae0..42eb976 100644
--- a/graphics/src/main/java/de/staropensource/sosengine/graphics/events/InputEvent.java
+++ b/graphics/src/main/java/de/staropensource/sosengine/graphics/events/InputEvent.java
@@ -64,7 +64,8 @@ public class InputEvent implements Event {
*/
public void callEvent(@Nullable Window window, @NotNull Key key, @NotNull KeyState state) {
if (GraphicsSubsystemConfiguration.getInstance().isDebugInput())
- logger.diag("Got input event: window=" + (window == null ? "" : window.getName() + (window.getName() == null ? "" : "(" + window.getName() + ")") + "[" + window.hashCode() + "]") + " key=" + key.name() + " state=" + state.name());
+ logger.diag("Got input event: window=" + (window == null ? "\\" : window.getUniqueIdentifier()) + " key=" + key.name() + " state=" + state.name());
+
EventHelper.invokeAnnotatedMethods(getClass(), window, key, state);
}
}
diff --git a/graphics/src/main/java/de/staropensource/sosengine/graphics/exceptions/InvalidMonitorException.java b/graphics/src/main/java/de/staropensource/sosengine/graphics/exceptions/InvalidMonitorException.java
new file mode 100644
index 0000000..bdcfc15
--- /dev/null
+++ b/graphics/src/main/java/de/staropensource/sosengine/graphics/exceptions/InvalidMonitorException.java
@@ -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 .
+ */
+
+package de.staropensource.sosengine.graphics.exceptions;
+
+/**
+ * Thrown when the specified monitor could not be found.
+ *
+ * @since v1-alpha2
+ */
+public class InvalidMonitorException extends RuntimeException {}
diff --git a/graphics/src/main/java/de/staropensource/sosengine/graphics/exceptions/NoMonitorsFoundException.java b/graphics/src/main/java/de/staropensource/sosengine/graphics/exceptions/NoMonitorsFoundException.java
index 4259358..8e2ed28 100644
--- a/graphics/src/main/java/de/staropensource/sosengine/graphics/exceptions/NoMonitorsFoundException.java
+++ b/graphics/src/main/java/de/staropensource/sosengine/graphics/exceptions/NoMonitorsFoundException.java
@@ -25,4 +25,4 @@ package de.staropensource.sosengine.graphics.exceptions;
* @since v1-alpha2
*/
@SuppressWarnings({ "unused" })
-public final class NoMonitorsFoundException extends Exception {}
+public final class NoMonitorsFoundException extends RuntimeException {}