Added experimental Display.setParent to allow Display to be embedded in an AWT Canvas. Added basic linux implementation and test.

This commit is contained in:
Elias Naur 2008-04-06 20:56:52 +00:00
parent 350c3c2661
commit c499f33bcf
16 changed files with 282 additions and 59 deletions

View file

@ -33,7 +33,7 @@ package org.lwjgl.opengl;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsDevice;
import java.awt.Component;
import java.awt.Canvas;
import org.lwjgl.LWJGLException;
@ -47,7 +47,7 @@ interface AWTCanvasImplementation {
/**
* Return an opaque handle to the canvas peer information required to create a context from it.
*/
PeerInfo createPeerInfo(Component component, PixelFormat pixel_format) throws LWJGLException;
PeerInfo createPeerInfo(Canvas component, PixelFormat pixel_format) throws LWJGLException;
/**
* Find a proper GraphicsConfiguration from the given GraphicsDevice and PixelFormat.

View file

@ -31,7 +31,7 @@
*/
package org.lwjgl.opengl;
import java.awt.Component;
import java.awt.Canvas;
import java.nio.ByteBuffer;
import java.security.AccessController;
import java.security.PrivilegedActionException;
@ -60,7 +60,7 @@ final class AWTSurfaceLock {
private static native ByteBuffer createHandle();
public ByteBuffer lockAndGetHandle(Component component) throws LWJGLException {
public ByteBuffer lockAndGetHandle(Canvas component) throws LWJGLException {
while (!privilegedLockAndInitHandle(component)) {
LWJGLUtil.log("Could not get drawing surface info, retrying...");
try {
@ -73,12 +73,12 @@ final class AWTSurfaceLock {
return lock_buffer;
}
private boolean privilegedLockAndInitHandle(final Component component) throws LWJGLException {
private boolean privilegedLockAndInitHandle(final Canvas component) throws LWJGLException {
// Workaround for Sun JDK bug 4796548 which still exists in java for OS X
// We need to elevate privileges because of an AWT bug. Please see
// http://192.18.37.44/forums/index.php?topic=10572 for a discussion.
// It is only needed on first call, so we avoid it on all subsequent calls
// due to performance.
// due to performance.
if (firstLockSucceeded)
return lockAndInitHandle(lock_buffer, component);
else
@ -96,7 +96,7 @@ final class AWTSurfaceLock {
}
}
private static native boolean lockAndInitHandle(ByteBuffer lock_buffer, Component component) throws LWJGLException;
private static native boolean lockAndInitHandle(ByteBuffer lock_buffer, Canvas component) throws LWJGLException;
protected void unlock() throws LWJGLException {
nUnlock(lock_buffer);

View file

@ -49,6 +49,7 @@ import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.Arrays;
import java.util.HashSet;
import java.awt.Canvas;
import org.lwjgl.BufferUtils;
import org.lwjgl.LWJGLException;
@ -71,6 +72,9 @@ public final class Display {
/** The initial display mode */
private static final DisplayMode initial_mode;
/** The parent, if any */
private static Canvas parent;
/** The current display mode, if created */
private static DisplayMode current_mode;
@ -244,7 +248,7 @@ public final class Display {
}
int window_x;
int window_y;
if (!fullscreen) {
if (!fullscreen && parent == null) {
// if no display location set, center window
if (x == -1 && y == -1) {
window_x = Math.max(0, (initial_mode.getWidth() - current_mode.getWidth()) / 2);
@ -257,7 +261,10 @@ public final class Display {
window_x = 0;
window_y = 0;
}
display_impl.createWindow(current_mode, fullscreen, window_x, window_y);
Canvas tmp_parent = fullscreen ? null : parent;
if (tmp_parent != null && !tmp_parent.isDisplayable()) // Only a best effort check, since the parent can turn undisplayable hereafter
throw new LWJGLException("Parent.isDisplayable() must be true");
display_impl.createWindow(current_mode, fullscreen, tmp_parent, window_x, window_y);
window_created = true;
setTitle(title);
@ -464,6 +471,50 @@ public final class Display {
}
}
/**
* Return the last parent set with setParent().
*/
public static Canvas getParent() {
synchronized (GlobalLock.lock) {
return parent;
}
}
/**
* Set the parent of the Display. If parent is null, the Display will appear as a top level window.
* If parent is not null, the Display is made a child of the parent. A parent's isDisplayable() must be true when
* setParent() is called and remain true until setParent() is called again with
* null or a different parent. This generally means that the parent component must remain added to it's parent container.<p>
* It is not advisable to call this method from an AWT thread, since the context will be made current on the thread
* and it is difficult to predict which AWT thread will process any given AWT event.<p>
* If the Display is in fullscreen mode, the current parent will be ignored.
*
*/
public static void setParent(Canvas parent) throws LWJGLException {
synchronized (GlobalLock.lock) {
if (Display.parent != parent) {
Display.parent = parent;
if (!isCreated())
return;
destroyWindow();
try {
if (fullscreen) {
switchDisplayMode();
} else {
display_impl.resetDisplayMode();
}
createWindow();
makeCurrentAndSetSwapInterval();
} catch (LWJGLException e) {
destroyContext();
destroyPeerInfo();
display_impl.resetDisplayMode();
throw e;
}
}
}
}
/**
* Set the fullscreen mode of the context. If no context has been created through create(),
* the mode will apply when create() is called. If fullscreen is true, the context will become
@ -914,7 +965,7 @@ public final class Display {
}
/**
* Set the window's location. This is a no-op on fullscreen windows.
* Set the window's location. This is a no-op on fullscreen windows or when getParent() != null.
* The window is clamped to remain entirely on the screen. If you attempt
* to position the window such that it would extend off the screen, the window
* is simply placed as close to the edge as possible.

View file

@ -41,12 +41,13 @@ package org.lwjgl.opengl;
import java.nio.ByteBuffer;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import java.awt.Canvas;
import org.lwjgl.LWJGLException;
interface DisplayImplementation extends InputImplementation {
void createWindow(DisplayMode mode, boolean fullscreen, int x, int y) throws LWJGLException;
void createWindow(DisplayMode mode, boolean fullscreen, Canvas parent, int x, int y) throws LWJGLException;
void destroyWindow();

View file

@ -35,7 +35,7 @@ import java.nio.ByteBuffer;
import org.lwjgl.LWJGLException;
import org.lwjgl.LWJGLUtil;
import java.awt.Component;
import java.awt.Canvas;
/**
*
@ -44,11 +44,11 @@ import java.awt.Component;
* $Id$
*/
final class LinuxAWTGLCanvasPeerInfo extends LinuxPeerInfo {
private final Component component;
private final Canvas component;
private final AWTSurfaceLock awt_surface = new AWTSurfaceLock();
private int screen = -1;
public LinuxAWTGLCanvasPeerInfo(Component component) {
public LinuxAWTGLCanvasPeerInfo(Canvas component) {
this.component = component;
}

View file

@ -33,7 +33,7 @@ package org.lwjgl.opengl;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsDevice;
import java.awt.Component;
import java.awt.Canvas;
import java.lang.reflect.Method;
import java.security.AccessController;
import java.security.PrivilegedExceptionAction;
@ -76,7 +76,7 @@ final class LinuxCanvasImplementation implements AWTCanvasImplementation {
}
}
public PeerInfo createPeerInfo(Component component, PixelFormat pixel_format) throws LWJGLException {
public PeerInfo createPeerInfo(Canvas component, PixelFormat pixel_format) throws LWJGLException {
return new LinuxAWTGLCanvasPeerInfo(component);
}

View file

@ -42,6 +42,8 @@ import java.nio.ByteBuffer;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import java.awt.Canvas;
import org.lwjgl.BufferUtils;
import org.lwjgl.LWJGLException;
import org.lwjgl.LWJGLUtil;
@ -103,6 +105,7 @@ final class LinuxDisplay implements DisplayImplementation {
private boolean focused_at_least_once;
private long current_cursor;
private long blank_cursor;
private Canvas parent;
private LinuxKeyboard keyboard;
private LinuxMouse mouse;
@ -357,7 +360,7 @@ final class LinuxDisplay implements DisplayImplementation {
ungrabKeyboard();
}
public void createWindow(DisplayMode mode, boolean fullscreen, int x, int y) throws LWJGLException {
public void createWindow(DisplayMode mode, boolean fullscreen, Canvas parent, int x, int y) throws LWJGLException {
lockAWT();
try {
incDisplay();
@ -365,7 +368,10 @@ final class LinuxDisplay implements DisplayImplementation {
ByteBuffer handle = peer_info.lockAndGetHandle();
try {
current_window_mode = getWindowMode(fullscreen);
current_window = nCreateWindow(getDisplay(), getDefaultScreen(), handle, mode, current_window_mode, x, y);
boolean undecorated = Display.getPrivilegedBoolean("org.lwjgl.opengl.Window.undecorated") || current_window_mode != WINDOWED;
this.parent = parent;
long parent_window = parent != null ? getHandle(parent) : getRootWindow(getDisplay(), getDefaultScreen());
current_window = nCreateWindow(getDisplay(), getDefaultScreen(), handle, mode, current_window_mode, x, y, undecorated, parent_window);
blank_cursor = createBlankCursor();
current_cursor = None;
focused = true;
@ -388,7 +394,19 @@ final class LinuxDisplay implements DisplayImplementation {
unlockAWT();
}
}
private static native long nCreateWindow(long display, int screen, ByteBuffer peer_info_handle, DisplayMode mode, int window_mode, int x, int y) throws LWJGLException;
private static native long nCreateWindow(long display, int screen, ByteBuffer peer_info_handle, DisplayMode mode, int window_mode, int x, int y, boolean undecorated, long parent_handle) throws LWJGLException;
private static native long getRootWindow(long display, int screen);
private static long getHandle(Canvas parent) throws LWJGLException {
AWTCanvasImplementation awt_impl = AWTGLCanvas.createImplementation();
LinuxPeerInfo parent_peer_info = (LinuxPeerInfo)awt_impl.createPeerInfo(parent, null);
ByteBuffer parent_peer_info_handle = parent_peer_info.lockAndGetHandle();
try {
return parent_peer_info.getDrawable();
} finally {
parent_peer_info.unlock();
}
}
private void updateInputGrab() {
updatePointerGrab();
@ -602,7 +620,11 @@ final class LinuxDisplay implements DisplayImplementation {
return peer_info;
}
private native static void setInputFocus(long display, long window);
private void processEvents() {
if (!focused && parent != null && parent.isFocusOwner())
setInputFocus(getDisplay(), getWindow());
while (LinuxEvent.getPending(getDisplay()) > 0) {
event_buffer.nextEvent(getDisplay());
long event_window = event_buffer.getWindow();

View file

@ -33,7 +33,7 @@ package org.lwjgl.opengl;
import org.lwjgl.LWJGLException;
import java.awt.Component;
import java.awt.Canvas;
/**
*
@ -42,9 +42,9 @@ import java.awt.Component;
* $Id$
*/
final class MacOSXAWTGLCanvasPeerInfo extends MacOSXCanvasPeerInfo {
private final Component component;
private final Canvas component;
public MacOSXAWTGLCanvasPeerInfo(Component component, PixelFormat pixel_format, boolean support_pbuffer) throws LWJGLException {
public MacOSXAWTGLCanvasPeerInfo(Canvas component, PixelFormat pixel_format, boolean support_pbuffer) throws LWJGLException {
super(pixel_format, support_pbuffer);
this.component = component;
}

View file

@ -33,7 +33,7 @@ package org.lwjgl.opengl;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsDevice;
import java.awt.Component;
import java.awt.Canvas;
import org.lwjgl.LWJGLException;
@ -44,7 +44,7 @@ import org.lwjgl.LWJGLException;
* $Id$
*/
final class MacOSXCanvasImplementation implements AWTCanvasImplementation {
public PeerInfo createPeerInfo(Component component, PixelFormat pixel_format) throws LWJGLException {
public PeerInfo createPeerInfo(Canvas component, PixelFormat pixel_format) throws LWJGLException {
try {
return new MacOSXAWTGLCanvasPeerInfo(component, pixel_format, true);
} catch (LWJGLException e) {

View file

@ -31,7 +31,7 @@
*/
package org.lwjgl.opengl;
import java.awt.Component;
import java.awt.Canvas;
import java.nio.ByteBuffer;
import org.lwjgl.LWJGLException;
@ -49,7 +49,7 @@ abstract class MacOSXCanvasPeerInfo extends MacOSXPeerInfo {
super(pixel_format, true, true, support_pbuffer, true);
}
protected void initHandle(Component component) throws LWJGLException {
protected void initHandle(Canvas component) throws LWJGLException {
nInitHandle(awt_surface.lockAndGetHandle(component), getHandle());
}
private static native void nInitHandle(ByteBuffer surface_buffer, ByteBuffer peer_info_handle) throws LWJGLException;

View file

@ -39,6 +39,7 @@ package org.lwjgl.opengl;
*/
import java.awt.Cursor;
import java.awt.Canvas;
import java.awt.Robot;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
@ -73,7 +74,7 @@ final class MacOSXDisplay implements DisplayImplementation {
new MacOSXApplicationListener();
}
public void createWindow(DisplayMode mode, boolean fullscreen, int x, int y) throws LWJGLException {
public void createWindow(DisplayMode mode, boolean fullscreen, Canvas parent, int x, int y) throws LWJGLException {
hideUI(fullscreen);
close_requested = false;
try {

View file

@ -35,7 +35,7 @@ import java.nio.ByteBuffer;
import org.lwjgl.LWJGLException;
import java.awt.Component;
import java.awt.Canvas;
/**
*
@ -44,12 +44,12 @@ import java.awt.Component;
* $Id$
*/
final class WindowsAWTGLCanvasPeerInfo extends WindowsPeerInfo {
private final Component component;
private final Canvas component;
private final AWTSurfaceLock awt_surface = new AWTSurfaceLock();
private final PixelFormat pixel_format;
private boolean has_pixel_format= false;
public WindowsAWTGLCanvasPeerInfo(Component component, PixelFormat pixel_format) {
public WindowsAWTGLCanvasPeerInfo(Canvas component, PixelFormat pixel_format) {
this.component = component;
this.pixel_format = pixel_format;
}

View file

@ -34,7 +34,7 @@ package org.lwjgl.opengl;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsDevice;
import java.awt.Toolkit;
import java.awt.Component;
import java.awt.Canvas;
import java.security.PrivilegedAction;
import java.security.AccessController;
@ -70,7 +70,7 @@ final class WindowsCanvasImplementation implements AWTCanvasImplementation {
return new WindowsAWTInput(canvas);
}
public PeerInfo createPeerInfo(Component component, PixelFormat pixel_format) throws LWJGLException {
public PeerInfo createPeerInfo(Canvas component, PixelFormat pixel_format) throws LWJGLException {
return new WindowsAWTGLCanvasPeerInfo(component, pixel_format);
}

View file

@ -41,6 +41,7 @@ package org.lwjgl.opengl;
import java.nio.ByteBuffer;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import java.awt.Canvas;
import org.lwjgl.LWJGLException;
import org.lwjgl.LWJGLUtil;
@ -139,7 +140,7 @@ final class WindowsDisplay implements DisplayImplementation {
current_display = this;
}
public void createWindow(DisplayMode mode, boolean fullscreen, int x, int y) throws LWJGLException {
public void createWindow(DisplayMode mode, boolean fullscreen, Canvas container, int x, int y) throws LWJGLException {
close_requested = false;
is_dirty = false;
isFullscreen = fullscreen;

View file

@ -0,0 +1,122 @@
/*
* Copyright (c) 2002-2005 LWJGL 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 'LWJGL' 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.awt;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.GridLayout;
import java.awt.Container;
import java.awt.Component;
import java.awt.Canvas;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import org.lwjgl.LWJGLException;
import org.lwjgl.opengl.AWTGLCanvas;
import org.lwjgl.opengl.GL11;
import org.lwjgl.input.Keyboard;
import org.lwjgl.input.Mouse;
import org.lwjgl.util.glu.GLU;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.DisplayMode;
/**
* <p>
* Tests Display.setParent()
* <p>
* @version $Revision$
* @author $Author$
* $Id$
*/
public class DisplayParentTest extends Frame {
public DisplayParentTest() throws LWJGLException {
setTitle("LWJGL Display Parent Test");
setSize(640, 320);
setLayout(new GridLayout(1, 2));
final Canvas display_parent = new Canvas();
display_parent.setFocusable(true);
add(display_parent);
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
dispose();
}
});
setResizable(true);
setVisible(true);
Display.setParent(display_parent);
Display.create();
float angle = 0f;
int current_height = 0;
int current_width = 0;
while (isVisible()) {
angle += 1.0f;
if (getWidth() != current_width || getHeight() != current_height) {
current_width = getWidth();
current_height = getHeight();
Display.setDisplayMode(new DisplayMode(getWidth(), getHeight()));
GL11.glViewport(0, 0, current_width, current_height);
}
GL11.glViewport(0, 0, getWidth(), getHeight());
GL11.glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
GL11.glClear(GL11.GL_COLOR_BUFFER_BIT);
GL11.glMatrixMode(GL11.GL_PROJECTION);
GL11.glLoadIdentity();
GLU.gluOrtho2D(0.0f, (float) getWidth(), 0.0f, (float) getHeight());
GL11.glMatrixMode(GL11.GL_MODELVIEW);
GL11.glPushMatrix();
GL11.glTranslatef(getWidth() / 2.0f, getHeight() / 2.0f, 0.0f);
GL11.glRotatef(2*angle, 0f, 0f, -1.0f);
GL11.glRectf(-50.0f, -50.0f, 50.0f, 50.0f);
GL11.glPopMatrix();
Display.update();
while(Keyboard.next()) {
// closing on ESCAPE
if(Keyboard.getEventKey() == Keyboard.KEY_ESCAPE && Keyboard.getEventKeyState()) {
dispose();
}
if(Keyboard.getEventKey() == Keyboard.KEY_SPACE && Keyboard.getEventKeyState()) {
Mouse.setGrabbed(!Mouse.isGrabbed());
}
}
/* while (Mouse.next()) {
System.out.println(" Mouse.getEventX() = " + Mouse.getEventX() + " | Mouse.getEventY() = " + Mouse.getEventY());
}*/
}
System.exit(0);
}
public static void main(String[] args) throws LWJGLException {
new DisplayParentTest();
}
}