From 37262e6727ae64066e90d6c4f88d71968d91ee61 Mon Sep 17 00:00:00 2001 From: Caspian Rychlik-Prince Date: Sat, 3 Apr 2004 23:01:39 +0000 Subject: [PATCH] New window sizing & undecorated code --- src/java/org/lwjgl/opengl/Window.java | 132 +++++++++++++++++- .../lwjgl/test/opengl/BouncingWindowTest.java | 109 +++++++++++++++ src/native/common/org_lwjgl_opengl_Window.h | 12 +- src/native/linux/org_lwjgl_opengl_Window.cpp | 26 ++-- src/native/win32/org_lwjgl_opengl_Window.cpp | 60 ++++++-- 5 files changed, 312 insertions(+), 27 deletions(-) create mode 100644 src/java/org/lwjgl/test/opengl/BouncingWindowTest.java diff --git a/src/java/org/lwjgl/opengl/Window.java b/src/java/org/lwjgl/opengl/Window.java index 80593c8f..97d0bec8 100644 --- a/src/java/org/lwjgl/opengl/Window.java +++ b/src/java/org/lwjgl/opengl/Window.java @@ -80,6 +80,9 @@ public final class Window { /** Fullscreen */ private static boolean fullscreen; + + /** Undecorated */ + private static boolean undecorated; /** Tracks VBO state for the window context */ private static VBOTracker vbo_tracker; @@ -102,6 +105,24 @@ public final class Window { private Window() { } + /** + * @return the X coordinate of the window (always 0 for fullscreen) + */ + public static int getX() { + if (!isCreated()) + throw new IllegalStateException("Cannot get X on uncreated window"); + return x; + } + + /** + * @return the Y coordinate of the window (always 0 for fullscreen) + */ + public static int getY() { + if (!isCreated()) + throw new IllegalStateException("Cannot get Y on uncreated window"); + return y; + } + /** * @return the width of the window */ @@ -326,6 +347,7 @@ public final class Window { if (isCreated()) throw new IllegalStateException("Only one LWJGL window may be instantiated at any one time."); Window.fullscreen = true; + Window.undecorated = true; Window.x = 0; Window.y = 0; Window.width = Display.getWidth(); @@ -352,7 +374,29 @@ public final class Window { * the minimum requirements could not be met satisfactorily */ public static void create(String title, int x, int y, int width, int height, int bpp, int alpha, int depth, int stencil) throws LWJGLException { - create(title, x, y, width, height, bpp, alpha, depth, stencil, 0); + create(title, x, y, width, height, false, bpp, alpha, depth, stencil); + } + + /** + * Create a window. If the underlying OS does not have "floating" windows, then a fullscreen + * display will be created instead. If this fails too then an LWJGLException will be thrown. + * If the window is created fullscreen, then its size may not match the specified size + * here. + *

The window created will be set up in orthographic 2D projection, with 1:1 pixel ratio with GL coordinates. + * @param title The title of the window + * @param x The position of the window on the x axis. May be ignored. + * @param y The position of the window on the y axis. May be ignored. + * @param width The width of the window's client area + * @param height The height of the window's client area + * @param undecorated A hint to specify that the window should not have OS decorations such as drag bar and close box + * @param bpp Minimum bits per pixel + * @param alpha Minimum bits per pixel in alpha buffer + * @param depth Minimum bits per pixel in depth buffer + * @throws LWJGLException if the window could not be created for any reason; typically because + * the minimum requirements could not be met satisfactorily + */ + public static void create(String title, int x, int y, int width, int height, boolean undecorated, int bpp, int alpha, int depth, int stencil) throws LWJGLException { + create(title, x, y, width, height, undecorated, bpp, alpha, depth, stencil, 0); } /** @@ -377,9 +421,37 @@ public final class Window { */ public static void create(String title, int x, int y, int width, int height, int bpp, int alpha, int depth, int stencil, int samples) throws LWJGLException { + + create(title, x, y, width, height, false, bpp, alpha, depth, stencil, samples); + } + + /** + * Create a window. If the underlying OS does not have "floating" windows, then a fullscreen + * display will be created instead. If this fails too then an LWJGLException will be thrown. + * If the window is created fullscreen, then its size may not match the specified size + * here. + *

The window created will be set up in orthographic 2D projection, with 1:1 pixel ratio with GL coordinates. + * @param title The title of the window + * @param x The position of the window on the x axis. May be ignored. + * @param y The position of the window on the y axis. May be ignored. + * @param width The width of the window's client area + * @param height The height of the window's client area + * @param undecorated A hint to specify that the window should not have OS decorations such as drag bar and close box + * @param bpp Minimum bits per pixel + * @param alpha Minimum bits per pixel in alpha buffer + * @param depth Minimum bits per pixel in depth buffer + * @param stencil Minimum bits per pixel in stencil buffer + * @param samples Minimum samples in multisample buffer (corresponds to GL_SAMPLES_ARB in GL_ARB_multisample spec). + Pass 0 to disable multisampling. This parameter is ignored if GL_ARB_multisample is not supported. + * @throws LWJGLException if the window could not be created for any reason; typically because + * the minimum requirements could not be met satisfactorily + */ + public static void create(String title, int x, int y, int width, int height, boolean undecorated, int bpp, int alpha, int depth, int stencil, int samples) + throws LWJGLException { if (isCreated()) throw new IllegalStateException("Only one LWJGL window may be instantiated at any one time."); Window.fullscreen = false; + Window.undecorated = undecorated; Window.x = x; Window.y = y; Window.width = width; @@ -399,6 +471,7 @@ public final class Window { int width, int height, boolean fullscreen, + boolean undecordated, int bpp, int alpha, int depth, @@ -407,7 +480,7 @@ public final class Window { throws LWJGLException; private static void createWindow(int bpp, int alpha, int depth, int stencil, int samples) throws LWJGLException { - nCreate(title, x, y, width, height, fullscreen, bpp, alpha, depth, stencil, samples); + nCreate(title, x, y, width, height, fullscreen, undecorated, bpp, alpha, depth, stencil, samples); context = new Window(); makeCurrent(); @@ -548,5 +621,60 @@ public final class Window { private static native void nSetVSyncEnabled(boolean sync); + /** + * Set the window's location. This is a no-op on fullscreen windows. + * @param x, y The new window location + */ + public static void setLocation(int x, int y) { + if (!isCreated()) + throw new IllegalStateException("Cannot move uncreated window"); + if (fullscreen) { + return; + } + Window.x = x; + Window.y = y; + nReshape(Window.x, Window.y, Window.width, Window.height); + } + + /** + * Set the window's size. This is a no-op on fullscreen windows. + * The window's size is clipped to the screen bounds. + * @param width, height The new window dimensions + */ + public static void setSize(int width, int height) { + if (!isCreated()) + throw new IllegalStateException("Cannot resize uncreated window"); + if (fullscreen) { + return; + } + Window.width = width; + Window.height = height; + nReshape(Window.x, Window.y, Window.width, Window.height); + } + + /** + * Set the window's wounds. This is a no-op on fullscreen windows. + * @param x, y The new window location + * @param width, height The new window dimensions + */ + public static void setBounds(int x, int y, int width, int height) { + if (!isCreated()) + throw new IllegalStateException("Cannot reshape uncreated window"); + if (fullscreen) { + return; + } + Window.x = x; + Window.y = y; + Window.width = width; + Window.height = height; + nReshape(Window.x, Window.y, Window.width, Window.height); + } + + /** + * Native method to reshape the window + * @param x, y The new window location + * @param width, height The new window dimensions + */ + private static native void nReshape(int x, int y, int width, int height); } diff --git a/src/java/org/lwjgl/test/opengl/BouncingWindowTest.java b/src/java/org/lwjgl/test/opengl/BouncingWindowTest.java new file mode 100644 index 00000000..c2381448 --- /dev/null +++ b/src/java/org/lwjgl/test/opengl/BouncingWindowTest.java @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2002 Lightweight Java Game Library Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of 'Light Weight Java Game Library' nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package org.lwjgl.test.opengl; + +import org.lwjgl.Display; +import org.lwjgl.LWJGLException; +import org.lwjgl.input.Keyboard; +import org.lwjgl.opengl.GL11; +import org.lwjgl.opengl.Window; + +/** + * $Id$ + * + * Tests the windowing functions. ESCAPE quits. + * + * @author $author$ + * @version $revision$ + */ +public class BouncingWindowTest { + public static void main(String[] args) { + + int x = 0, y = 0, dx = 1, dy = 1; + try { + Window.create("Bouncing Window Test", 0, 0, 64, 64, true, 16, 0, 16, 8, 0); + } catch (LWJGLException e) { + e.printStackTrace(System.err); + System.exit(-1); + } + + Window.setVSyncEnabled(true); + + float angle = 0.0f; + float color = 0.0f; + while (!Keyboard.isKeyDown(Keyboard.KEY_ESCAPE) && !Window.isCloseRequested()) { + Window.update(); + x += dx; + y += dy; + if (x < 0) { + x = 1; + dx = 1; + } else if (x >= Display.getWidth() - Window.getWidth()) { + x = Display.getWidth() - Window.getWidth() - 1; + dx = -1; + } + if (y < 0) { + y = 1; + dy = 1; + } else if (y >= Display.getHeight() - Window.getHeight()) { + y = Display.getHeight() - Window.getHeight() - 1; + dy = -1; + } + + Window.setLocation(x, y); + angle += 1.0f; + if (angle >= 360.0f) { + angle = 0.0f; + } + color += 0.01f; + GL11.glClear(GL11.GL_COLOR_BUFFER_BIT); + GL11.glPushMatrix(); + GL11.glTranslatef(Window.getWidth() / 2.0f, Window.getHeight() / 2.0f, 0.0f); + GL11.glRotatef(angle, 0.0f, 0.0f, 1.0f); + GL11.glColor3f( + (float)Math.abs(Math.sin(color)), + (float)Math.abs(Math.cos(color)), + (float)Math.abs(Math.sin(color) * Math.cos(color)) + ); + GL11.glBegin(GL11.GL_QUADS); + { + GL11.glVertex2f(-20.0f, -20.0f); + GL11.glVertex2f(20.0f, -20.0f); + GL11.glVertex2f(20.0f, 20.0f); + GL11.glVertex2f(-20.0f, 20.0f); + } + GL11.glEnd(); + GL11.glPopMatrix(); + } + + } +} diff --git a/src/native/common/org_lwjgl_opengl_Window.h b/src/native/common/org_lwjgl_opengl_Window.h index 553a67a1..5ed54491 100644 --- a/src/native/common/org_lwjgl_opengl_Window.h +++ b/src/native/common/org_lwjgl_opengl_Window.h @@ -93,10 +93,10 @@ JNIEXPORT void JNICALL Java_org_lwjgl_opengl_Window_nMakeCurrent /* * Class: org_lwjgl_opengl_Window * Method: nCreate - * Signature: (Ljava/lang/String;IIIIZIIIII)V + * Signature: (Ljava/lang/String;IIIIZZIIIII)V */ JNIEXPORT void JNICALL Java_org_lwjgl_opengl_Window_nCreate - (JNIEnv *, jclass, jstring, jint, jint, jint, jint, jboolean, jint, jint, jint, jint, jint); + (JNIEnv *, jclass, jstring, jint, jint, jint, jint, jboolean, jboolean, jint, jint, jint, jint, jint); /* * Class: org_lwjgl_opengl_Window @@ -130,6 +130,14 @@ JNIEXPORT jboolean JNICALL Java_org_lwjgl_opengl_Window_nIsVSyncEnabled JNIEXPORT void JNICALL Java_org_lwjgl_opengl_Window_nSetVSyncEnabled (JNIEnv *, jclass, jboolean); +/* + * Class: org_lwjgl_opengl_Window + * Method: nReshape + * Signature: (IIII)V + */ +JNIEXPORT void JNICALL Java_org_lwjgl_opengl_Window_nReshape + (JNIEnv *, jclass, jint, jint, jint, jint); + #ifdef __cplusplus } #endif diff --git a/src/native/linux/org_lwjgl_opengl_Window.cpp b/src/native/linux/org_lwjgl_opengl_Window.cpp index 0f704ae3..2fb46858 100644 --- a/src/native/linux/org_lwjgl_opengl_Window.cpp +++ b/src/native/linux/org_lwjgl_opengl_Window.cpp @@ -68,7 +68,8 @@ static int current_width; static bool input_released; -static bool dirty; +static bool isUndecorated; +static bool focused; static bool vsync_enabled; static bool minimized; static bool focused; @@ -179,7 +180,7 @@ JNIEXPORT void JNICALL Java_org_lwjgl_opengl_Window_nSetTitle env->ReleaseStringUTFChars(title_obj, title); } -static void createWindow(JNIEnv* env, Display *disp, int screen, XVisualInfo *vis_info, jstring title, int x, int y, int width, int height, bool fullscreen) { +static void createWindow(JNIEnv* env, Display *disp, int screen, XVisualInfo *vis_info, jstring title, int x, int y, int width, int height, bool fullscreen, bool undecorated) { dirty = true; focused = true; minimized = false; @@ -391,7 +392,7 @@ static void destroy(void) { extgl_Close(); } -static bool initWindowGLX13(JNIEnv *env, Display *disp, int screen, jstring title, int x, int y, int width, int height, int bpp, int depth, int alpha, int stencil, int samples, bool fscreen) { +static bool initWindowGLX13(JNIEnv *env, Display *disp, int screen, jstring title, int x, int y, int width, int height, int bpp, int depth, int alpha, int stencil, int samples, bool fscreen, bool undecorated) { GLXFBConfig *configs = chooseVisualGLX13(disp, screen, bpp, depth, alpha, stencil, samples); if (configs == NULL) { throwException(env, "Could not find a matching pixel format"); @@ -417,7 +418,7 @@ static bool initWindowGLX13(JNIEnv *env, Display *disp, int screen, jstring titl throwException(env, "Could not create visual info from FB config"); return false; } - createWindow(env, disp, screen, vis_info, title, x, y, width, height, fscreen); + createWindow(env, disp, screen, vis_info, title, x, y, width, height, fscreen, undecorated); glx_window = glXCreateWindow(disp, configs[0], getCurrentWindow(), NULL); makeCurrent(); if (isDebugEnabled()) @@ -427,7 +428,7 @@ static bool initWindowGLX13(JNIEnv *env, Display *disp, int screen, jstring titl return true; } -static bool initWindowGLX(JNIEnv *env, Display *disp, int screen, jstring title, int x, int y, int width, int height, int bpp, int depth, int alpha, int stencil, int samples, bool fscreen) { +static bool initWindowGLX(JNIEnv *env, Display *disp, int screen, jstring title, int x, int y, int width, int height, int bpp, int depth, int alpha, int stencil, int samples, bool fscreen, bool undecorated) { XVisualInfo *vis_info = chooseVisual(disp, screen, bpp, depth, alpha, stencil, samples); if (vis_info == NULL) { throwException(env, "Could not find a matching pixel format"); @@ -448,20 +449,22 @@ static bool initWindowGLX(JNIEnv *env, Display *disp, int screen, jstring title, throwException(env, "Could not create a direct GLX context"); return false; } - createWindow(env, disp, screen, vis_info, title, x, y, width, height, fscreen); + createWindow(env, disp, screen, vis_info, title, x, y, width, height, fscreen, undecorated); makeCurrent(); XFree(vis_info); return true; } JNIEXPORT void JNICALL Java_org_lwjgl_opengl_Window_nCreate - (JNIEnv * env, jclass clazz, jstring title, jint x, jint y, jint width, jint height, jboolean fullscreen, jint bpp, jint alpha, jint depth, jint stencil, jint samples) + (JNIEnv * env, jclass clazz, jstring title, jint x, jint y, jint width, jint height, jboolean fullscreen, jboolean undecorated, jint bpp, jint alpha, jint depth, jint stencil, jint samples) { int screen; Display *disp; bool fscreen = false; if (fullscreen == JNI_TRUE) fscreen = true; + if (undecorated == JNI_TRUE) + isUndecorated = true; if (!extgl_Open()) { throwException(env, "Could not load gl libs"); @@ -481,9 +484,9 @@ JNIEXPORT void JNICALL Java_org_lwjgl_opengl_Window_nCreate } bool create_success; if (USEGLX13) { - create_success = initWindowGLX13(env, disp, screen, title, x, y, width, height, bpp, depth, alpha, stencil, samples, fscreen); + create_success = initWindowGLX13(env, disp, screen, title, x, y, width, height, bpp, depth, alpha, stencil, samples, fscreen, isUndecorated); } else { - create_success = initWindowGLX(env, disp, screen, title, x, y, width, height, bpp, depth, alpha, stencil, samples, fscreen); + create_success = initWindowGLX(env, disp, screen, title, x, y, width, height, bpp, depth, alpha, stencil, samples, fscreen, isUndecorated); } if (!create_success) { XCloseDisplay(disp); @@ -597,3 +600,8 @@ JNIEXPORT void JNICALL Java_org_lwjgl_opengl_Window_nSetVSyncEnabled } } } + +JNIEXPORT void JNICALL Java_org_lwjgl_opengl_Window_nReshape + (JNIEnv *env, jclass clazz, jint x, jint y, jint width, jint height) +{ +} diff --git a/src/native/win32/org_lwjgl_opengl_Window.cpp b/src/native/win32/org_lwjgl_opengl_Window.cpp index 2f32dcc6..847cb32e 100755 --- a/src/native/win32/org_lwjgl_opengl_Window.cpp +++ b/src/native/win32/org_lwjgl_opengl_Window.cpp @@ -54,6 +54,7 @@ static bool isFullScreen = false; // Whether we're fullscreen or not static bool isMinimized = false; // Whether we're minimized or not static bool isFocused = false; // whether we're focused or not static bool isDirty = false; // Whether we're dirty or not +static bool isUndecorated = false; // Whether we're undecorated or not extern HINSTANCE dll_handle; // Handle to the LWJGL dll RECT clientSize; @@ -382,21 +383,23 @@ static void handleMessages(JNIEnv * env, jclass clazz) * * Returns true for success, or false for failure */ -static bool createWindow(JNIEnv *env, jstring title_obj, int x, int y, int width, int height, bool fullscreen) +static bool createWindow(JNIEnv *env, jstring title_obj, int x, int y, int width, int height, bool fullscreen, bool undecorated) { - // 2. Create the window int exstyle, windowflags; if (fullscreen) { exstyle = WS_EX_APPWINDOW | WS_EX_TOPMOST; windowflags = WS_POPUP; + } else if (undecorated) { + exstyle = WS_EX_APPWINDOW; + windowflags = WS_POPUP; } else { exstyle = WS_EX_APPWINDOW; windowflags = WS_OVERLAPPED | WS_BORDER | WS_CAPTION | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_MINIMIZEBOX | WS_SYSMENU; } // If we're not a fullscreen window, adjust the height to account for the - // height of the title bar: + // height of the title bar (unless undecorated) clientSize.bottom = height; clientSize.left = 0; clientSize.right = width; @@ -523,13 +526,14 @@ JNIEXPORT void JNICALL Java_org_lwjgl_opengl_Window_swapBuffers * Signature: (Ljava/lang/String;IIIIZIIII)V */ JNIEXPORT void JNICALL Java_org_lwjgl_opengl_Window_nCreate - (JNIEnv * env, jclass clazz, jstring title, jint x, jint y, jint width, jint height, jboolean fullscreen, jint bpp, jint alpha, jint depth, jint stencil, jint samples) + (JNIEnv * env, jclass clazz, jstring title, jint x, jint y, jint width, jint height, jboolean fullscreen, jboolean undecorated, jint bpp, jint alpha, jint depth, jint stencil, jint samples) { closerequested = false; isMinimized = false; isFocused = true; isDirty = true; isFullScreen = fullscreen == JNI_TRUE; + isUndecorated = undecorated == JNI_TRUE; vsync = JNI_FALSE; // Speacial option for allowing software opengl @@ -546,7 +550,7 @@ JNIEXPORT void JNICALL Java_org_lwjgl_opengl_Window_nCreate return; } - if (!createWindow(env, title, x, y, width, height, isFullScreen)) { + if (!createWindow(env, title, x, y, width, height, isFullScreen, isUndecorated)) { extgl_Close(); return; } @@ -564,7 +568,7 @@ JNIEXPORT void JNICALL Java_org_lwjgl_opengl_Window_nCreate wglMakeCurrent(NULL, NULL); wglDeleteContext(hglrc); closeWindow(); - if (!createWindow(env, title, x, y, width, height, isFullScreen)) { + if (!createWindow(env, title, x, y, width, height, isFullScreen, isUndecorated)) { extgl_Close(); return; } @@ -574,14 +578,7 @@ JNIEXPORT void JNICALL Java_org_lwjgl_opengl_Window_nCreate return; } } - /* - if (!extgl_Initialize(env, ext_set)) { - closeWindow(); - extgl_Close(); - throwException(env, "Failed to initialize GL extensions"); - return; - } - */ + if (!createDirectInput()) { // Close the window closeWindow(); @@ -693,3 +690,38 @@ JNIEXPORT void JNICALL Java_org_lwjgl_opengl_Window_nMakeCurrent { wglMakeCurrent(hdc, hglrc); } + +JNIEXPORT void JNICALL Java_org_lwjgl_opengl_Window_nReshape + (JNIEnv *env, jclass clazz, jint x, jint y, jint width, jint height) +{ + if (isFullScreen) { + return; + } + + int exstyle, windowflags; + + if (isUndecorated) { + exstyle = WS_EX_APPWINDOW; + windowflags = WS_OVERLAPPED; + } else { + exstyle = WS_EX_APPWINDOW; + windowflags = WS_OVERLAPPED | WS_BORDER | WS_CAPTION | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_MINIMIZEBOX | WS_SYSMENU; + } + + // If we're not a fullscreen window, adjust the height to account for the + // height of the title bar: + clientSize.bottom = height; + clientSize.left = 0; + clientSize.right = width; + clientSize.top = 0; + + AdjustWindowRectEx( + &clientSize, // client-rectangle structure + windowflags, // window styles + FALSE, // menu-present option + exstyle // extended window style + ); + + SetWindowPos(hwnd, HWND_TOP, x, y, clientSize.right - clientSize.left, + clientSize.bottom - clientSize.top, SWP_NOZORDER); +}