diff --git a/src/java/org/lwjgl/opengl/Display.java b/src/java/org/lwjgl/opengl/Display.java index e875529e..121740bb 100644 --- a/src/java/org/lwjgl/opengl/Display.java +++ b/src/java/org/lwjgl/opengl/Display.java @@ -242,7 +242,7 @@ public final class Display { try { if ( was_fullscreen && !isFullscreen() ) display_impl.resetDisplayMode(); - else if ( isFullscreen() ) + else if ( isFullscreen() ) switchDisplayMode(); createWindow(); makeCurrentAndSetSwapInterval(); diff --git a/src/java/org/lwjgl/opengl/MacOSXCanvasPeerInfo.java b/src/java/org/lwjgl/opengl/MacOSXCanvasPeerInfo.java index 3ebf4502..8aeade7f 100644 --- a/src/java/org/lwjgl/opengl/MacOSXCanvasPeerInfo.java +++ b/src/java/org/lwjgl/opengl/MacOSXCanvasPeerInfo.java @@ -44,21 +44,15 @@ import org.lwjgl.LWJGLUtil; * $Id$ */ abstract class MacOSXCanvasPeerInfo extends MacOSXPeerInfo { - private final AWTSurfaceLock awt_surface = new AWTSurfaceLock(); - protected MacOSXCanvasPeerInfo(PixelFormat pixel_format, ContextAttribs attribs, boolean support_pbuffer) throws LWJGLException { super(pixel_format, attribs, true, true, support_pbuffer, true); } protected void initHandle(Canvas component) throws LWJGLException { - // Allow the use of a Core Animation Layer only when using non fullscreen Display.setParent() or AWTGLCanvas - final boolean allowCALayer = ((Display.getParent() != null && !Display.isFullscreen()) || component instanceof AWTGLCanvas) && awt_surface.isApplet(component) && LWJGLUtil.isMacOSXEqualsOrBetterThan(10, 6); - - nInitHandle(awt_surface.lockAndGetHandle(component), getHandle(), allowCALayer); + nInitHandle(getHandle()); } - private static native void nInitHandle(ByteBuffer surface_buffer, ByteBuffer peer_info_handle, boolean allowCALayer) throws LWJGLException; + private static native void nInitHandle(ByteBuffer peer_info_handle) throws LWJGLException; protected void doUnlock() throws LWJGLException { - awt_surface.unlock(); } } diff --git a/src/java/org/lwjgl/opengl/MacOSXContextImplementation.java b/src/java/org/lwjgl/opengl/MacOSXContextImplementation.java index c47d8c87..5ea1e80f 100644 --- a/src/java/org/lwjgl/opengl/MacOSXContextImplementation.java +++ b/src/java/org/lwjgl/opengl/MacOSXContextImplementation.java @@ -90,7 +90,7 @@ final class MacOSXContextImplementation implements ContextImplementation { try { synchronized ( context ) { clearDrawable(context.getHandle()); - setView(peer_handle, context.getHandle()); + setView(peer_handle); } } finally { peer_info.unlock(); @@ -100,14 +100,14 @@ final class MacOSXContextImplementation implements ContextImplementation { public void makeCurrent(PeerInfo peer_info, ByteBuffer handle) throws LWJGLException { ByteBuffer peer_handle = peer_info.lockAndGetHandle(); try { - setView(peer_handle, handle); + setView(peer_handle); nMakeCurrent(handle); } finally { peer_info.unlock(); } } - private static native void setView(ByteBuffer peer_handle, ByteBuffer context_handle) throws LWJGLException; + private static native void setView(ByteBuffer peer_handle) throws LWJGLException; private static native void nMakeCurrent(ByteBuffer context_handle) throws LWJGLException; diff --git a/src/java/org/lwjgl/opengl/MacOSXDisplay.java b/src/java/org/lwjgl/opengl/MacOSXDisplay.java index c6032c72..65b5f900 100644 --- a/src/java/org/lwjgl/opengl/MacOSXDisplay.java +++ b/src/java/org/lwjgl/opengl/MacOSXDisplay.java @@ -40,6 +40,8 @@ package org.lwjgl.opengl; import java.awt.Canvas; import java.awt.Cursor; +import java.awt.GraphicsDevice; +import java.awt.GraphicsEnvironment; import java.awt.Robot; import java.nio.ByteBuffer; import java.nio.FloatBuffer; @@ -51,6 +53,7 @@ import java.util.ArrayList; import java.util.List; import org.lwjgl.BufferUtils; +import org.lwjgl.MemoryUtil; import org.lwjgl.LWJGLException; import org.lwjgl.LWJGLUtil; @@ -65,14 +68,25 @@ final class MacOSXDisplay implements DisplayImplementation { private static final int GAMMA_LENGTH = 256; private MacOSXCanvasListener canvas_listener; - private MacOSXFrame frame; private Canvas canvas; private Robot robot; private MacOSXMouseEventQueue mouse_queue; private KeyboardEventQueue keyboard_queue; private java.awt.DisplayMode requested_mode; + + /* Members for native window use */ + private MacOSXNativeMouse mouse; + private MacOSXNativeKeyboard keyboard; + private ByteBuffer window; + private ByteBuffer context; + private int x; + private int y; + private int width; + private int height; + + /* Whether we're using a native window or an AWT canvas */ + private boolean native_mode; - /* States */ private boolean close_requested; MacOSXDisplay() { @@ -96,49 +110,65 @@ final class MacOSXDisplay implements DisplayImplementation { } } - public void createWindow(final DrawableLWJGL drawable, DisplayMode mode, Canvas parent, int x, int y) throws LWJGLException { + private native ByteBuffer nCreateWindow(int x, int y, int width, int height, boolean fullscreen, boolean undecorated, ByteBuffer peer_info_handle, ByteBuffer window_handle) throws LWJGLException; + + private native boolean nIsMiniaturized(ByteBuffer window_handle); + + private native boolean nIsFocused(ByteBuffer window_handle); + + private native void nSetResizable(ByteBuffer window_handle, boolean resizable); + + private native void nResizeWindow(ByteBuffer window_handle, int x, int y, int width, int height); + + private native boolean nWasResized(ByteBuffer window_handle); + + private static boolean isUndecorated() { + return Display.getPrivilegedBoolean("org.lwjgl.opengl.Window.undecorated"); + } + + public void createWindow(final DrawableLWJGL drawable, DisplayMode mode, Canvas parent, int x, int y) throws LWJGLException { boolean fullscreen = Display.isFullscreen(); hideUI(fullscreen); close_requested = false; + + DrawableGL gl_drawable = (DrawableGL)Display.getDrawable(); + PeerInfo peer_info = gl_drawable.peer_info; + ByteBuffer peer_handle = peer_info.lockAndGetHandle(); try { - if (parent == null) { - frame = new MacOSXFrame(mode, requested_mode, fullscreen, x, y); - canvas = frame.getCanvas(); - } else { - frame = null; - canvas = parent; - } - canvas_listener = new MacOSXCanvasListener(canvas); - robot = AWTUtil.createRobot(canvas); + window = nCreateWindow(x, y, mode.getWidth(), mode.getHeight(), + fullscreen, isUndecorated(), + peer_handle, window); + native_mode = true; + this.x = x; + this.y = y; + this.width = mode.getWidth(); + this.height = mode.getHeight(); + this.canvas = parent; } catch (LWJGLException e) { destroyWindow(); throw e; - } + } finally { + peer_info.unlock(); + } } - private void doHandleQuit() { + public void doHandleQuit() { synchronized (this) { close_requested = true; } } + public native void nDestroyWindow(ByteBuffer window_handle); + public void destroyWindow() { - if (canvas_listener != null) { - canvas_listener.disableListeners(); - canvas_listener = null; - } - if (frame != null) { - AccessController.doPrivileged(new PrivilegedAction() { - public Object run() { - if (MacOSXFrame.getDevice().getFullScreenWindow() == frame) - MacOSXFrame.getDevice().setFullScreenWindow(null); - return null; - } - }); - if (frame.isDisplayable()) - frame.dispose(); - frame = null; - } + if (native_mode) { + nDestroyWindow(window); + } else { + if (canvas_listener != null) { + canvas_listener.disableListeners(); + canvas_listener = null; + } + } hideUI(false); } @@ -162,7 +192,7 @@ final class MacOSXDisplay implements DisplayImplementation { } public void switchDisplayMode(DisplayMode mode) throws LWJGLException { - java.awt.DisplayMode[] awt_modes = MacOSXFrame.getDevice().getDisplayModes(); + java.awt.DisplayMode[] awt_modes = getDevice().getDisplayModes(); for ( java.awt.DisplayMode awt_mode : awt_modes ) { if (equals(awt_mode, mode)) { requested_mode = awt_mode; @@ -172,9 +202,17 @@ final class MacOSXDisplay implements DisplayImplementation { throw new LWJGLException(mode + " is not supported"); } + private static GraphicsDevice getDevice() { + GraphicsEnvironment g_env = GraphicsEnvironment.getLocalGraphicsEnvironment(); + GraphicsDevice device = g_env.getDefaultScreenDevice(); + return device; + } + public void resetDisplayMode() { - if (MacOSXFrame.getDevice().getFullScreenWindow() != null) - MacOSXFrame.getDevice().setFullScreenWindow(null); + if (!native_mode) { + if (getDevice().getFullScreenWindow() != null) + getDevice().setFullScreenWindow(null); + } requested_mode = null; restoreGamma(); } @@ -198,11 +236,11 @@ final class MacOSXDisplay implements DisplayImplementation { } public DisplayMode init() throws LWJGLException { - return createLWJGLDisplayMode(MacOSXFrame.getDevice().getDisplayMode()); + return createLWJGLDisplayMode(getDevice().getDisplayMode()); } public DisplayMode[] getAvailableDisplayModes() throws LWJGLException { - java.awt.DisplayMode[] awt_modes = MacOSXFrame.getDevice().getDisplayModes(); + java.awt.DisplayMode[] awt_modes = getDevice().getDisplayModes(); List modes = new ArrayList(); for ( java.awt.DisplayMode awt_mode : awt_modes ) if ( awt_mode.getBitDepth() >= 16 ) @@ -210,26 +248,33 @@ final class MacOSXDisplay implements DisplayImplementation { return modes.toArray(new DisplayMode[modes.size()]); } + private native void nSetTitle(ByteBuffer window_handle, ByteBuffer title_buffer); + public void setTitle(String title) { - if (frame != null) - frame.setTitle(title); + ByteBuffer buffer = MemoryUtil.encodeUTF8(title); + nSetTitle(window, buffer); } public boolean isCloseRequested() { boolean result; synchronized (this) { - result = close_requested || (frame != null && frame.syncIsCloseRequested()); + result = close_requested; close_requested = false; } return result; } public boolean isVisible() { - return frame == null || frame.syncIsVisible(); + return true; } public boolean isActive() { - return canvas.isFocusOwner(); + if (native_mode) { + boolean ret = nIsFocused(window); + return ret; + } else { + return canvas.isFocusOwner(); + } } public Canvas getCanvas() { @@ -237,7 +282,7 @@ final class MacOSXDisplay implements DisplayImplementation { } public boolean isDirty() { - return frame != null && frame.getCanvas().syncIsDirty(); + return false; } public PeerInfo createPeerInfo(PixelFormat pixel_format, ContextAttribs attribs) throws LWJGLException { @@ -250,7 +295,10 @@ final class MacOSXDisplay implements DisplayImplementation { private static final IntBuffer current_viewport = BufferUtils.createIntBuffer(16); public void update() { - boolean should_update = canvas_listener.syncShouldUpdateContext(); + boolean should_update = true; + if (!native_mode) { + should_update = canvas_listener.syncShouldUpdateContext(); + } /* * Workaround for the "white screen in fullscreen mode" problem * @@ -273,46 +321,38 @@ final class MacOSXDisplay implements DisplayImplementation { * - elias */ DrawableGL drawable = (DrawableGL)Display.getDrawable(); - if (Display.isFullscreen() && (frame != null && frame.getCanvas().syncCanvasPainted() || should_update)) { - try { - MacOSXContextImplementation.resetView(drawable.peer_info, drawable.context); - } catch (LWJGLException e) { - LWJGLUtil.log("Failed to reset context: " + e); - } - } if (should_update) { drawable.context.update(); /* This is necessary to make sure the context won't "forget" about the view size */ glGetInteger(GL_VIEWPORT, current_viewport); glViewport(current_viewport.get(0), current_viewport.get(1), current_viewport.get(2), current_viewport.get(3)); } + /* if (frame != null && mouse_queue != null) { if (frame.syncShouldReleaseCursor()) MacOSXMouseEventQueue.nGrabMouse(false); if (frame.syncShouldWarpCursor()) mouse_queue.warpCursor(); } + */ } /** - * This is an interface to the native Carbon call - * SetSystemUIMode. It is used to hide the dock in a way - * that will prevent AWT from shifting the fullscreen window - * - * The workaround is not necessary on 10.4, and since 10.4 shows - * instability problems calling SetSystemUIMode, we'll only call it - * when the OS version is 10.3 or lower. + * This is an interface to the native Cocoa function, + * NSWindow:setStyleMask. It is used to set the window's border to + * undecorated. */ private void hideUI(boolean hide) { - if (!LWJGLUtil.isMacOSXEqualsOrBetterThan(10, 4)) - nHideUI(hide); + //if (!LWJGLUtil.isMacOSXEqualsOrBetterThan(10, 4)) + nHideUI(window, hide); } - private native void nHideUI(boolean hide); + private native void nHideUI(ByteBuffer window_handle, boolean hide); public void reshape(int x, int y, int width, int height) { - if (frame != null) - frame.resize(x, y, width, height); + //if (native_mode) { + // nResizeWindow(window, x, y, width, height); + //} } /* Mouse */ @@ -325,28 +365,52 @@ final class MacOSXDisplay implements DisplayImplementation { } public void createMouse() throws LWJGLException { - this.mouse_queue = new MacOSXMouseEventQueue(canvas); - mouse_queue.register(); + if (native_mode) { + mouse = new MacOSXNativeMouse(this, window); + mouse.register(); + } else { + mouse_queue = new MacOSXMouseEventQueue(canvas); + mouse_queue.register(); + } } public void destroyMouse() { - if (mouse_queue != null) { - MacOSXMouseEventQueue.nGrabMouse(false); - mouse_queue.unregister(); - } - this.mouse_queue = null; + MacOSXMouseEventQueue.nGrabMouse(false); + if (native_mode) { + if (mouse != null) { + mouse.unregister(); + } + mouse = null; + } else { + if (mouse_queue != null) { + mouse_queue.unregister(); + } + mouse_queue = null; + } } public void pollMouse(IntBuffer coord_buffer, ByteBuffer buttons_buffer) { - mouse_queue.poll(coord_buffer, buttons_buffer); + if (native_mode) { + mouse.poll(coord_buffer, buttons_buffer); + } else { + mouse_queue.poll(coord_buffer, buttons_buffer); + } } public void readMouse(ByteBuffer buffer) { - mouse_queue.copyEvents(buffer); + if (native_mode) { + mouse.copyEvents(buffer); + } else { + mouse_queue.copyEvents(buffer); + } } public void grabMouse(boolean grab) { - mouse_queue.setGrabbed(grab); + if (native_mode) { + mouse.setGrabbed(grab); + } else { + mouse_queue.setGrabbed(grab); + } } public int getNativeCursorCapabilities() { @@ -354,13 +418,10 @@ final class MacOSXDisplay implements DisplayImplementation { } public void setCursorPosition(int x, int y) { - AWTUtil.setCursorPosition(canvas, robot, x, y); + MacOSXMouseEventQueue.nWarpCursor(x, y); } public void setNativeCursor(Object handle) throws LWJGLException { - Cursor awt_cursor = (Cursor)handle; - if (frame != null) - frame.setCursor(awt_cursor); } public int getMinCursorSize() { @@ -373,48 +434,43 @@ final class MacOSXDisplay implements DisplayImplementation { /* Keyboard */ public void createKeyboard() throws LWJGLException { - this.keyboard_queue = new KeyboardEventQueue(canvas); - keyboard_queue.register(); + if (native_mode) { + this.keyboard = new MacOSXNativeKeyboard(window); + keyboard.register(); + } else { + this.keyboard_queue = new KeyboardEventQueue(canvas); + keyboard_queue.register(); + } } public void destroyKeyboard() { - if (keyboard_queue != null) - keyboard_queue.unregister(); - this.keyboard_queue = null; + if (native_mode) { + if (keyboard != null) + keyboard.unregister(); + keyboard = null; + } else { + if (keyboard_queue != null) + keyboard_queue.unregister(); + keyboard_queue = null; + } } public void pollKeyboard(ByteBuffer keyDownBuffer) { - keyboard_queue.poll(keyDownBuffer); + if (native_mode) { + keyboard.poll(keyDownBuffer); + } else { + keyboard_queue.poll(keyDownBuffer); + } } public void readKeyboard(ByteBuffer buffer) { - keyboard_queue.copyEvents(buffer); + if (native_mode) { + keyboard.copyEvents(buffer); + } else { + keyboard_queue.copyEvents(buffer); + } } -/* public int isStateKeySet(int key) { - int awt_key; - switch (key) { - case Keyboard.KEY_CAPITAL: - awt_key = KeyEvent.VK_CAPS_LOCK; - break; - case Keyboard.KEY_NUMLOCK: - awt_key = KeyEvent.VK_NUM_LOCK; - break; - case Keyboard.KEY_SYSRQ: - awt_key = KeyEvent.VK_SCROLL_LOCK; - break; - default: - return Keyboard.STATE_UNKNOWN; - } - try { - boolean state = Toolkit.getDefaultToolkit().getLockingKeyState(awt_key); - return state ? Keyboard.STATE_ON : Keyboard.STATE_OFF; - } catch (Exception e) { - LWJGLUtil.log("Failed to query key state: " + e); - return Keyboard.STATE_UNKNOWN; - } - } -*/ /** Native cursor handles */ public Object createCursor(int width, int height, int xHotspot, int yHotspot, int numImages, IntBuffer images, IntBuffer delays) throws LWJGLException { return AWTUtil.createCursor(width, height, xHotspot, yHotspot, numImages, images, delays); @@ -497,19 +553,19 @@ final class MacOSXDisplay implements DisplayImplementation { } public int getX() { - return frame.getX(); + return x; } public int getY() { - return frame.getY(); + return y; } public int getWidth() { - return frame.getWidth(); + return width; } public int getHeight() { - return frame.getHeight(); + return height; } public boolean isInsideWindow() { @@ -517,11 +573,17 @@ final class MacOSXDisplay implements DisplayImplementation { } public void setResizable(boolean resizable) { - frame.setResizable(resizable); + if (native_mode) { + nSetResizable(window, resizable); + } } public boolean wasResized() { - return canvas_listener.wasResized(); + if (native_mode) { + return nWasResized(window); + } else { + return canvas_listener.wasResized(); + } } } diff --git a/src/java/org/lwjgl/opengl/MacOSXMouseEventQueue.java b/src/java/org/lwjgl/opengl/MacOSXMouseEventQueue.java index b232becd..5e4d221a 100644 --- a/src/java/org/lwjgl/opengl/MacOSXMouseEventQueue.java +++ b/src/java/org/lwjgl/opengl/MacOSXMouseEventQueue.java @@ -44,13 +44,13 @@ import java.nio.IntBuffer; import org.lwjgl.BufferUtils; final class MacOSXMouseEventQueue extends MouseEventQueue { - private final IntBuffer delta_buffer = BufferUtils.createIntBuffer(2); - - private boolean skip_event; - private static boolean is_grabbed; + private IntBuffer delta_buffer = BufferUtils.createIntBuffer(2); + + private boolean skip_event; + private static boolean is_grabbed; MacOSXMouseEventQueue(Component component) { - super(component); + super(component); } public void setGrabbed(boolean grab) { @@ -96,18 +96,11 @@ final class MacOSXMouseEventQueue extends MouseEventQueue { // If we're going to warp the cursor position, we'll skip the next event to avoid bogus delta values skip_event = isGrabbed(); } -/* if (isGrabbed()) { - Rectangle bounds = getComponent().getBounds(); - Point location_on_screen = getComponent().getLocationOnScreen(); - int x = location_on_screen.x + bounds.width/2; - int y = location_on_screen.y + bounds.height/2; - nWarpCursor(x, y); - }*/ } private static native void getMouseDeltas(IntBuffer delta_buffer); - private static native void nWarpCursor(int x, int y); + public static native void nWarpCursor(int x, int y); - static native void nGrabMouse(boolean grab); + public static native void nGrabMouse(boolean grab); } diff --git a/src/java/org/lwjgl/opengl/MacOSXNativeKeyboard.java b/src/java/org/lwjgl/opengl/MacOSXNativeKeyboard.java new file mode 100644 index 00000000..ee12eef9 --- /dev/null +++ b/src/java/org/lwjgl/opengl/MacOSXNativeKeyboard.java @@ -0,0 +1,283 @@ +/* + * Copyright (c) 2002-2008 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.opengl; + +/** + * An AWT implementation of a LWJGL compatible Keyboard event queue. + * @author elias_naur + */ + +import java.awt.event.KeyEvent; +import java.awt.event.KeyListener; +import java.util.HashMap; +import java.awt.Component; +import java.nio.ByteBuffer; + +import org.lwjgl.input.Keyboard; + +final class MacOSXNativeKeyboard extends EventQueue { + private final byte[] key_states = new byte[Keyboard.KEYBOARD_SIZE]; + + /** Event scratch array */ + private final ByteBuffer event = ByteBuffer.allocate(Keyboard.EVENT_SIZE); + + private ByteBuffer window_handle; + + private boolean has_deferred_event; + private long deferred_nanos; + private int deferred_key_code; + private byte deferred_key_state; + private int deferred_character; + + private HashMap nativeToLwjglMap; + + MacOSXNativeKeyboard(ByteBuffer window_handle) { + super(Keyboard.EVENT_SIZE); + nativeToLwjglMap = new HashMap(); + initKeyboardMappings(); + this.window_handle = window_handle; + } + + private native void nRegisterKeyListener(ByteBuffer window_handle); + + private native void nUnregisterKeyListener(ByteBuffer window_handle); + + private void initKeyboardMappings() { + nativeToLwjglMap.put((Short)(short)0x1D, Keyboard.KEY_0); + nativeToLwjglMap.put((Short)(short)0x12, Keyboard.KEY_1); + nativeToLwjglMap.put((Short)(short)0x13, Keyboard.KEY_2); + nativeToLwjglMap.put((Short)(short)0x14, Keyboard.KEY_3); + nativeToLwjglMap.put((Short)(short)0x15, Keyboard.KEY_4); + nativeToLwjglMap.put((Short)(short)0x17, Keyboard.KEY_5); + nativeToLwjglMap.put((Short)(short)0x16, Keyboard.KEY_6); + nativeToLwjglMap.put((Short)(short)0x1A, Keyboard.KEY_7); + nativeToLwjglMap.put((Short)(short)0x1C, Keyboard.KEY_8); + nativeToLwjglMap.put((Short)(short)0x19, Keyboard.KEY_9); + nativeToLwjglMap.put((Short)(short)0x00, Keyboard.KEY_A); + nativeToLwjglMap.put((Short)(short)0x0B, Keyboard.KEY_B); + nativeToLwjglMap.put((Short)(short)0x08, Keyboard.KEY_C); + nativeToLwjglMap.put((Short)(short)0x02, Keyboard.KEY_D); + nativeToLwjglMap.put((Short)(short)0x0E, Keyboard.KEY_E); + nativeToLwjglMap.put((Short)(short)0x03, Keyboard.KEY_F); + nativeToLwjglMap.put((Short)(short)0x05, Keyboard.KEY_G); + nativeToLwjglMap.put((Short)(short)0x04, Keyboard.KEY_H); + nativeToLwjglMap.put((Short)(short)0x22, Keyboard.KEY_I); + nativeToLwjglMap.put((Short)(short)0x26, Keyboard.KEY_J); + nativeToLwjglMap.put((Short)(short)0x28, Keyboard.KEY_K); + nativeToLwjglMap.put((Short)(short)0x25, Keyboard.KEY_L); + nativeToLwjglMap.put((Short)(short)0x2E, Keyboard.KEY_M); + nativeToLwjglMap.put((Short)(short)0x2D, Keyboard.KEY_N); + nativeToLwjglMap.put((Short)(short)0x1F, Keyboard.KEY_O); + nativeToLwjglMap.put((Short)(short)0x23, Keyboard.KEY_P); + nativeToLwjglMap.put((Short)(short)0x0C, Keyboard.KEY_Q); + nativeToLwjglMap.put((Short)(short)0x0F, Keyboard.KEY_R); + nativeToLwjglMap.put((Short)(short)0x01, Keyboard.KEY_S); + nativeToLwjglMap.put((Short)(short)0x11, Keyboard.KEY_T); + nativeToLwjglMap.put((Short)(short)0x20, Keyboard.KEY_U); + nativeToLwjglMap.put((Short)(short)0x09, Keyboard.KEY_V); + nativeToLwjglMap.put((Short)(short)0x0D, Keyboard.KEY_W); + nativeToLwjglMap.put((Short)(short)0x07, Keyboard.KEY_X); + nativeToLwjglMap.put((Short)(short)0x10, Keyboard.KEY_Y); + nativeToLwjglMap.put((Short)(short)0x06, Keyboard.KEY_Z); + nativeToLwjglMap.put((Short)(short)0x2B, Keyboard.KEY_COMMA); + nativeToLwjglMap.put((Short)(short)0x2C, Keyboard.KEY_SLASH); + nativeToLwjglMap.put((Short)(short)0x2F, Keyboard.KEY_PERIOD); + nativeToLwjglMap.put((Short)(short)0x32, Keyboard.KEY_CIRCUMFLEX); + nativeToLwjglMap.put((Short)(short)0x29, Keyboard.KEY_SEMICOLON); + nativeToLwjglMap.put((Short)(short)0x129, Keyboard.KEY_COLON); + nativeToLwjglMap.put((Short)(short)0x2A, Keyboard.KEY_BACKSLASH); + nativeToLwjglMap.put((Short)(short)0x52, Keyboard.KEY_NUMPAD0); + nativeToLwjglMap.put((Short)(short)0x53, Keyboard.KEY_NUMPAD1); + nativeToLwjglMap.put((Short)(short)0x54, Keyboard.KEY_NUMPAD2); + nativeToLwjglMap.put((Short)(short)0x55, Keyboard.KEY_NUMPAD3); + nativeToLwjglMap.put((Short)(short)0x56, Keyboard.KEY_NUMPAD4); + nativeToLwjglMap.put((Short)(short)0x57, Keyboard.KEY_NUMPAD5); + nativeToLwjglMap.put((Short)(short)0x58, Keyboard.KEY_NUMPAD6); + nativeToLwjglMap.put((Short)(short)0x59, Keyboard.KEY_NUMPAD7); + nativeToLwjglMap.put((Short)(short)0x5B, Keyboard.KEY_NUMPAD8); + nativeToLwjglMap.put((Short)(short)0x5C, Keyboard.KEY_NUMPAD9); + nativeToLwjglMap.put((Short)(short)0x7A, Keyboard.KEY_F1); + nativeToLwjglMap.put((Short)(short)0x78, Keyboard.KEY_F2); + nativeToLwjglMap.put((Short)(short)0x63, Keyboard.KEY_F3); + nativeToLwjglMap.put((Short)(short)0x76, Keyboard.KEY_F4); + nativeToLwjglMap.put((Short)(short)0x60, Keyboard.KEY_F5); + nativeToLwjglMap.put((Short)(short)0x61, Keyboard.KEY_F6); + nativeToLwjglMap.put((Short)(short)0x62, Keyboard.KEY_F7); + nativeToLwjglMap.put((Short)(short)0x64, Keyboard.KEY_F8); + nativeToLwjglMap.put((Short)(short)0x65, Keyboard.KEY_F9); + nativeToLwjglMap.put((Short)(short)0x6D, Keyboard.KEY_F10); + nativeToLwjglMap.put((Short)(short)0x67, Keyboard.KEY_F11); + nativeToLwjglMap.put((Short)(short)0x6F, Keyboard.KEY_F12); + nativeToLwjglMap.put((Short)(short)0x69, Keyboard.KEY_F13); + nativeToLwjglMap.put((Short)(short)0x6B, Keyboard.KEY_F14); + nativeToLwjglMap.put((Short)(short)0x71, Keyboard.KEY_F15); + nativeToLwjglMap.put((Short)(short)0x72, Keyboard.KEY_HOME); + nativeToLwjglMap.put((Short)(short)0x18, Keyboard.KEY_EQUALS); + nativeToLwjglMap.put((Short)(short)0x7B, Keyboard.KEY_LEFT); + nativeToLwjglMap.put((Short)(short)0x7C, Keyboard.KEY_RIGHT); + nativeToLwjglMap.put((Short)(short)0x7E, Keyboard.KEY_UP); + nativeToLwjglMap.put((Short)(short)0x7D, Keyboard.KEY_DOWN); + nativeToLwjglMap.put((Short)(short)0x31, Keyboard.KEY_SPACE); + nativeToLwjglMap.put((Short)(short)0x30, Keyboard.KEY_TAB); + nativeToLwjglMap.put((Short)(short)0x35, Keyboard.KEY_ESCAPE); + nativeToLwjglMap.put((Short)(short)0x74, Keyboard.KEY_PRIOR); + nativeToLwjglMap.put((Short)(short)0x79, Keyboard.KEY_NEXT); + nativeToLwjglMap.put((Short)(short)0x41, Keyboard.KEY_DECIMAL); + nativeToLwjglMap.put((Short)(short)0x43, Keyboard.KEY_MULTIPLY); + nativeToLwjglMap.put((Short)(short)0x45, Keyboard.KEY_ADD); + nativeToLwjglMap.put((Short)(short)0x4B, Keyboard.KEY_DIVIDE); + nativeToLwjglMap.put((Short)(short)0x1B, Keyboard.KEY_MINUS); + nativeToLwjglMap.put((Short)(short)0x4E, Keyboard.KEY_SUBTRACT); + nativeToLwjglMap.put((Short)(short)0x1E, Keyboard.KEY_RBRACKET); + nativeToLwjglMap.put((Short)(short)0x21, Keyboard.KEY_LBRACKET); + nativeToLwjglMap.put((Short)(short)0x33, Keyboard.KEY_BACK); + nativeToLwjglMap.put((Short)(short)0x24, Keyboard.KEY_RETURN); + nativeToLwjglMap.put((Short)(short)0xF0, Keyboard.KEY_CAPITAL); + nativeToLwjglMap.put((Short)(short)0x39, Keyboard.KEY_CAPITAL); + nativeToLwjglMap.put((Short)(short)0xF1, Keyboard.KEY_LSHIFT); + nativeToLwjglMap.put((Short)(short)0x38, Keyboard.KEY_LSHIFT); + nativeToLwjglMap.put((Short)(short)0x3C, Keyboard.KEY_RSHIFT); + nativeToLwjglMap.put((Short)(short)0xF2, Keyboard.KEY_LCONTROL); + nativeToLwjglMap.put((Short)(short)0xF3, Keyboard.KEY_LMENU); + nativeToLwjglMap.put((Short)(short)0x3A, Keyboard.KEY_LMENU); + nativeToLwjglMap.put((Short)(short)0x3D, Keyboard.KEY_RMENU); + nativeToLwjglMap.put((Short)(short)0xF4, Keyboard.KEY_RETURN); + nativeToLwjglMap.put((Short)(short)0xF5, Keyboard.KEY_NUMLOCK); + nativeToLwjglMap.put((Short)(short)0x27, Keyboard.KEY_APOSTROPHE); + + /*KEY_MAP[KeyEvent.VK_ALT_GRAPH] = Keyboard.KEY_RMENU; + KEY_MAP[KeyEvent.VK_AT] = Keyboard.KEY_AT; + KEY_MAP[KeyEvent.VK_BACK_SPACE] = Keyboard.KEY_BACK; + KEY_MAP[KeyEvent.VK_CAPS_LOCK] = Keyboard.KEY_CAPITAL; + KEY_MAP[KeyEvent.VK_COLON] = Keyboard.KEY_COLON; + KEY_MAP[KeyEvent.VK_CONVERT] = Keyboard.KEY_CONVERT; + KEY_MAP[KeyEvent.VK_END] = Keyboard.KEY_END; + KEY_MAP[KeyEvent.VK_INSERT] = Keyboard.KEY_INSERT; + KEY_MAP[KeyEvent.VK_KANA] = Keyboard.KEY_KANA; + KEY_MAP[KeyEvent.VK_KANJI] = Keyboard.KEY_KANJI; + KEY_MAP[KeyEvent.VK_NUM_LOCK] = Keyboard.KEY_NUMLOCK; + KEY_MAP[KeyEvent.VK_PAUSE] = Keyboard.KEY_PAUSE; + KEY_MAP[KeyEvent.VK_SCROLL_LOCK] = Keyboard.KEY_SCROLL; + KEY_MAP[KeyEvent.VK_SEPARATOR] = Keyboard.KEY_DECIMAL; + KEY_MAP[KeyEvent.VK_STOP] = Keyboard.KEY_STOP;*/ + } + + public void register() { + nRegisterKeyListener(window_handle); + } + + public void unregister() { + nUnregisterKeyListener(window_handle); + } + + public void putKeyboardEvent(int key_code, byte state, int character, long nanos, boolean repeat) { + event.clear(); + event.putInt(key_code).put(state).putInt(character).putLong(nanos).put(repeat ? (byte)1 : (byte)0); + event.flip(); + putEvent(event); + } + + public synchronized void poll(ByteBuffer key_down_buffer) { + flushDeferredEvent(); + int old_position = key_down_buffer.position(); + key_down_buffer.put(key_states); + key_down_buffer.position(old_position); + } + + public synchronized void copyEvents(ByteBuffer dest) { + flushDeferredEvent(); + super.copyEvents(dest); + } + + private synchronized void handleKey(int key_code, byte state, int character, long nanos) { + if (character == KeyEvent.CHAR_UNDEFINED) + character = Keyboard.CHAR_NONE; + if (state == 1) { + boolean repeat = false; + if (has_deferred_event) { + if ((nanos == deferred_nanos && deferred_key_code == key_code)) { + has_deferred_event = false; + repeat = true; // Repeat event + } else + flushDeferredEvent(); + } + putKeyEvent(key_code, state, character, nanos, repeat); + } else { + flushDeferredEvent(); + has_deferred_event = true; + deferred_nanos = nanos; + deferred_key_code = key_code; + deferred_key_state = state; + deferred_character = character; + } + } + + private void flushDeferredEvent() { + if (has_deferred_event) { + putKeyEvent(deferred_key_code, deferred_key_state, deferred_character, deferred_nanos, false); + has_deferred_event = false; + } + } + + public void putKeyEvent(int key_code, byte state, int character, long nanos, boolean repeat) { + /* Ignore repeating presses */ + int mapped_code = getMappedKeyCode((short)key_code); + if (mapped_code < 0) { + System.out.println("Unrecognized keycode: " + key_code); + /* Unrecognized / unmapped code, do nothing */ + return; + } + if ( key_states[mapped_code] == state ) + repeat = true; + key_states[mapped_code] = state; + int key_int_char = character & 0xffff; + putKeyboardEvent(mapped_code, state, key_int_char, nanos, repeat); + } + + private int getMappedKeyCode(short key_code) { + if (nativeToLwjglMap.containsKey(key_code)) { + return nativeToLwjglMap.get(key_code); + } + return -1; + } + + public void keyPressed(int key_code, int character, long nanos) { + handleKey(key_code, (byte)1, character, nanos); + } + + public void keyReleased(int key_code, int character, long nanos) { + handleKey(key_code, (byte)0, character, nanos); + } + + public void keyTyped(KeyEvent e) { + } +} diff --git a/src/java/org/lwjgl/opengl/MacOSXNativeMouse.java b/src/java/org/lwjgl/opengl/MacOSXNativeMouse.java new file mode 100644 index 00000000..599b6441 --- /dev/null +++ b/src/java/org/lwjgl/opengl/MacOSXNativeMouse.java @@ -0,0 +1,192 @@ +/* + * Copyright (c) 2002-2008 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.opengl; + +/** + * A Cocoa implementation of a LWJGL compatible Mouse. + * @author mojang + */ + +import java.nio.ByteBuffer; +import java.nio.IntBuffer; + +import org.lwjgl.input.Mouse; + +import java.lang.reflect.*; +import java.lang.Integer; +import java.lang.Long; + +import org.lwjgl.BufferUtils; + +final class MacOSXNativeMouse extends EventQueue { + private static final int WHEEL_SCALE = 120; + private static final int NUM_BUTTONS = 3; + + private ByteBuffer window_handle; + private MacOSXDisplay display; + + private boolean grabbed; + + /** The accumulated mouse deltas returned by poll() */ + private float accum_dx; + private float accum_dy; + private int accum_dz; + + /** The last mouse position */ + private float last_x; + private float last_y; + + /** Saved control key state for ctrl-click right button emulation */ + private boolean saved_control_state; + + private final ByteBuffer event = ByteBuffer.allocate(Mouse.EVENT_SIZE); + private IntBuffer delta_buffer = BufferUtils.createIntBuffer(2); + private int skip_event; + + private final byte[] buttons = new byte[NUM_BUTTONS]; + + MacOSXNativeMouse(MacOSXDisplay display, ByteBuffer window_handle) { + super(Mouse.EVENT_SIZE); + this.display = display; + this.window_handle = window_handle; + } + + private native void nWarpCursor(ByteBuffer window_handle, int x, int y); + + public static native void nGrabMouse(boolean grab); + + private native void nRegisterMouseListener(ByteBuffer window_handle); + + private native void nUnregisterMouseListener(ByteBuffer window_handle); + + public synchronized void register() { + nRegisterMouseListener(window_handle); + } + + public synchronized void unregister() { + nUnregisterMouseListener(window_handle); + } + + public synchronized void setGrabbed(boolean grabbed) { + this.grabbed = grabbed; + nGrabMouse(grabbed); + skip_event = 1; + accum_dx = accum_dy = 0; + } + + public synchronized boolean isGrabbed() { + return grabbed; + } + + protected void resetCursorToCenter() { + clearEvents(); + accum_dx = accum_dy = 0; + if (display != null) { + last_x = display.getWidth() / 2; + last_y = display.getHeight() / 2; + } + } + + private void putMouseEvent(byte button, byte state, int dz, long nanos) { + if (grabbed) + putMouseEventWithCoords(button, state, 0, 0, dz, nanos); + else + putMouseEventWithCoords(button, state, (int)last_x, (int)last_y, dz, nanos); + } + + protected void putMouseEventWithCoords(byte button, byte state, int coord1, int coord2, int dz, long nanos) { + event.clear(); + event.put(button).put(state).putInt(coord1).putInt(coord2).putInt(dz).putLong(nanos); + event.flip(); + putEvent(event); + } + + public synchronized void poll(IntBuffer coord_buffer, ByteBuffer buttons_buffer) { + if (grabbed) { + coord_buffer.put(0, (int)accum_dx); + coord_buffer.put(1, (int)accum_dy); + } else { + coord_buffer.put(0, (int)last_x); + coord_buffer.put(1, (int)last_y); + } + coord_buffer.put(2, accum_dz); + accum_dx = accum_dy = accum_dz = 0; + int old_position = buttons_buffer.position(); + buttons_buffer.put(buttons, 0, buttons.length); + buttons_buffer.position(old_position); + } + + private void setCursorPos(float x, float y, long nanos) { + if ( grabbed ) + return; + float dx = x - last_x; + float dy = y - last_y; + addDelta(dx, dy); + last_x = x; + last_y = y; + putMouseEventWithCoords((byte)-1, (byte)0, (int)x, (int)y, 0, nanos); + } + + protected void addDelta(float dx, float dy) { + accum_dx += dx; + accum_dy += -dy; + } + + public synchronized void setButton(int button, int state, long nanos) { + buttons[button] = (byte)state; + putMouseEvent((byte)button, (byte)state, 0, nanos); + } + + public synchronized void mouseMoved(float x, float y, float dx, float dy, float dz, long nanos) { + if (skip_event > 0) { + skip_event--; + if (skip_event == 0) { + last_x = x; + last_y = y; + } + return; + } + if (grabbed) { + if ( dx != 0 || dy != 0 ) { + putMouseEventWithCoords((byte)-1, (byte)0, (int)dx, (int)-dy, 0, nanos); + addDelta(dx, dy); + } + } else { + setCursorPos(x, y, nanos); + } + if ( dz != 0 ) { + int wheel_amount = (int)(-dz * WHEEL_SCALE); + accum_dz += wheel_amount; + putMouseEvent((byte)-1, (byte)0, wheel_amount, nanos); + } + } +} diff --git a/src/java/org/lwjgl/opengl/MouseEventQueue.java b/src/java/org/lwjgl/opengl/MouseEventQueue.java index fa537cd6..356b471f 100644 --- a/src/java/org/lwjgl/opengl/MouseEventQueue.java +++ b/src/java/org/lwjgl/opengl/MouseEventQueue.java @@ -81,15 +81,19 @@ class MouseEventQueue extends EventQueue implements MouseListener, MouseMotionLi public synchronized void register() { resetCursorToCenter(); - component.addMouseListener(this); - component.addMouseMotionListener(this); - component.addMouseWheelListener(this); + if (component != null) { + component.addMouseListener(this); + component.addMouseMotionListener(this); + component.addMouseWheelListener(this); + } } public synchronized void unregister() { - component.removeMouseListener(this); - component.removeMouseMotionListener(this); - component.removeMouseWheelListener(this); + if (component != null) { + component.removeMouseListener(this); + component.removeMouseMotionListener(this); + component.removeMouseWheelListener(this); + } } protected Component getComponent() { @@ -105,18 +109,23 @@ class MouseEventQueue extends EventQueue implements MouseListener, MouseMotionLi return grabbed; } - private int transformY(int y) { - return component.getHeight() - 1 - y; + protected int transformY(int y) { + if (component != null) { + return component.getHeight() - 1 - y; + } + return y; } protected void resetCursorToCenter() { clearEvents(); accum_dx = accum_dy = 0; - Point cursor_location = AWTUtil.getCursorPosition(component); - if (cursor_location != null) { - last_x = cursor_location.x; - last_y = cursor_location.y; - } + if (component != null) { + Point cursor_location = AWTUtil.getCursorPosition(component); + if (cursor_location != null) { + last_x = cursor_location.x; + last_y = cursor_location.y; + } + } } private void putMouseEvent(byte button, byte state, int dz, long nanos) { diff --git a/src/native/macosx/context.h b/src/native/macosx/context.h index 188a0b32..3a6af76d 100644 --- a/src/native/macosx/context.h +++ b/src/native/macosx/context.h @@ -47,15 +47,65 @@ #include #include "common_tools.h" +@class NSOpenGLContext, NSOpenGLPixelFormat, MacOSXOpenGLView, MacOSXKeyableWindow; + typedef struct { - NSOpenGLPixelFormat *pixel_format; - bool window; + MacOSXKeyableWindow *window; + + NSRect display_rect; + + MacOSXOpenGLView *view; + NSOpenGLContext *context; + + // Native objects for Java callbacks + jobject jdisplay; + jobject jmouse; + jobject jkeyboard; + jboolean resized; + + // Cached for window creation + NSApplicationPresentationOptions window_options; +} MacOSXWindowInfo; + +@interface MacOSXKeyableWindow : NSWindow + +- (BOOL)canBecomeKeyWindow; +@end + +@interface MacOSXOpenGLView : NSView +{ + @public + MacOSXWindowInfo* _parent; + + @private + NSOpenGLContext* _openGLContext; + NSOpenGLPixelFormat* _pixelFormat; + NSUInteger _lastModifierFlags; + NSUInteger _modifierFlags; +} + ++ (NSOpenGLPixelFormat*)defaultPixelFormat; +- (id)initWithFrame:(NSRect)frameRect pixelFormat:(NSOpenGLPixelFormat*)format; +- (void)setOpenGLContext:(NSOpenGLContext*)context; +- (NSOpenGLContext*)openGLContext; +- (void)clearGLContext; +- (void)prepareOpenGL; +- (void)update; +- (void)lockFocus; +- (void)setPixelFormat:(NSOpenGLPixelFormat*)pixelFormat; +- (NSOpenGLPixelFormat*)pixelFormat; +- (void)setParent:(MacOSXWindowInfo*)parent; +- (BOOL)acceptsFirstResponder; +@end + +typedef struct { + bool isWindowed; bool canDrawGL; - union { - NSView *nsview; - NSOpenGLPixelBuffer *pbuffer; - }; + MacOSXWindowInfo *window_info; + NSOpenGLPixelFormat *pixel_format; + NSOpenGLPixelBuffer *pbuffer; } MacOSXPeerInfo; + NSOpenGLPixelFormat *choosePixelFormat(JNIEnv *env, jobject pixel_format, bool gl32, bool use_display_bpp, bool support_window, bool support_pbuffer, bool double_buffered); #endif diff --git a/src/native/macosx/context.m b/src/native/macosx/context.m index 510eb2d4..0240b2f7 100644 --- a/src/native/macosx/context.m +++ b/src/native/macosx/context.m @@ -91,7 +91,16 @@ NSOpenGLPixelFormat *choosePixelFormat(JNIEnv *env, jobject pixel_format, bool g int bpp; jclass cls_pixel_format = (*env)->GetObjectClass(env, pixel_format); if (use_display_bpp) - bpp = CGDisplayBitsPerPixel(kCGDirectMainDisplay); + { + CGDisplayModeRef mode = CGDisplayCopyDisplayMode(kCGDirectMainDisplay); + CFStringRef pixEnc = CGDisplayModeCopyPixelEncoding(mode); + if (CFStringCompare(pixEnc, CFSTR(IO32BitDirectPixels), kCFCompareCaseInsensitive) == kCFCompareEqualTo) + bpp = 32; + else if(CFStringCompare(pixEnc, CFSTR(IO16BitDirectPixels), kCFCompareCaseInsensitive) == kCFCompareEqualTo) + bpp = 16; + else if(CFStringCompare(pixEnc, CFSTR(IO8BitIndexedPixels), kCFCompareCaseInsensitive) == kCFCompareEqualTo) + bpp = 8; + } else bpp = (int)(*env)->GetIntField(env, pixel_format, (*env)->GetFieldID(env, cls_pixel_format, "bpp", "I")); diff --git a/src/native/macosx/org_lwjgl_opengl_Display.m b/src/native/macosx/org_lwjgl_opengl_Display.m index 96002d83..13955657 100644 --- a/src/native/macosx/org_lwjgl_opengl_Display.m +++ b/src/native/macosx/org_lwjgl_opengl_Display.m @@ -39,18 +39,433 @@ * @version $Revision$ */ +#import #import #import -#import #import #import -//#import "display.h" #import "common_tools.h" #import "org_lwjgl_opengl_MacOSXDisplay.h" #import "org_lwjgl_MacOSXSysImplementation.h" +#import "context.h" #define WAIT_DELAY 100 +static NSOpenGLPixelFormat *default_format = nil; + +@implementation MacOSXKeyableWindow +- (BOOL)canBecomeKeyWindow; +{ + return YES; +} +@end + +@implementation MacOSXOpenGLView + ++ (NSOpenGLPixelFormat*)defaultPixelFormat +{ + NSOpenGLPixelFormatAttribute defaultAttribs[] = { + NSOpenGLPFADoubleBuffer, + NSOpenGLPFADepthSize, 16, + NSOpenGLPFAColorSize, 32, + 0 + }; + if (default_format == nil) { + default_format = [[NSOpenGLPixelFormat alloc] initWithAttributes:defaultAttribs]; + } + return default_format; +} + +- (void) windowWillClose:(NSNotification *)notification +{ + MacOSXKeyableWindow *closingWindow = [notification object]; + + if (_parent != nil && closingWindow == _parent->window) { + JNIEnv *env = attachCurrentThread(); + jclass display_class = (*env)->GetObjectClass(env, _parent->jdisplay); + jmethodID close_callback = (*env)->GetMethodID(env, display_class, "doHandleQuit", "()V"); + (*env)->CallVoidMethod(env, _parent->jdisplay, close_callback); + } +} + +- (id)initWithFrame:(NSRect)frameRect pixelFormat:(NSOpenGLPixelFormat*)format +{ + self = [super initWithFrame:frameRect]; + _lastModifierFlags = 0; + _modifierFlags = 0; + if (self != nil) { + _pixelFormat = [format retain]; + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(_surfaceNeedsUpdate:) + name:NSViewGlobalFrameDidChangeNotification + object:self]; + } + return self; +} + +- (void) _surfaceNeedsUpdate:(NSNotification*)notification +{ + [self update]; +} + +- (void)setOpenGLContext:(NSOpenGLContext*)context +{ + _openGLContext = context; +} + +- (NSOpenGLContext*)openGLContext +{ + return _openGLContext; +} + +- (void)clearGLContext +{ + [_openGLContext release]; + _openGLContext = nil; +} + +- (void)prepareOpenGL +{ + +} + +- (void)update +{ + [_openGLContext update]; +} + +- (void)lockFocus +{ + NSOpenGLContext* context = [self openGLContext]; + + [super lockFocus]; + if ([context view] != self) { + [context setView:self]; + } + + [context makeCurrentContext]; +} + +- (void)setPixelFormat:(NSOpenGLPixelFormat*)pixelFormat +{ + _pixelFormat = [pixelFormat retain]; +} + +- (NSOpenGLPixelFormat*)pixelFormat +{ + return _pixelFormat; +} + +- (BOOL)acceptsFirstResponder { + return YES; +} + +- (void)setParent:(MacOSXWindowInfo*)parent { + // Un-register for native window close events if we have a parent window already + if (_parent != nil) { + [[NSNotificationCenter defaultCenter] removeObserver:self + name:NSWindowWillCloseNotification + object:_parent->window]; + } + _parent = parent; + // Register for native window close events if we now have a parent window + if (_parent != nil) { + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(windowWillClose:) name:NSWindowWillCloseNotification + object:_parent->window]; + } +} + +- (void)keyDown:(NSEvent *)event { + JNIEnv *env = attachCurrentThread(); + if (env == nil || event == nil || _parent == nil || _parent->jkeyboard == nil) { + return; + } + long time = [event timestamp] * 1000000000; + jclass keyboard_class = (*env)->GetObjectClass(env, _parent->jkeyboard); + jmethodID keydown = (*env)->GetMethodID(env, keyboard_class, "keyPressed", "(IIJ)V"); + const char* charbuf = [[event characters] cStringUsingEncoding:NSASCIIStringEncoding]; + int charcode = (charbuf == nil) ? 0 : charbuf[0]; + (*env)->CallVoidMethod(env, _parent->jkeyboard, keydown, [event keyCode], charcode, time); +} + +- (void)keyUp:(NSEvent *)event { + JNIEnv *env = attachCurrentThread(); + if (env == nil || event == nil || _parent == nil || _parent->jkeyboard == nil) { + return; + } + long time = [event timestamp] * 1000000000; + jclass keyboard_class = (*env)->GetObjectClass(env, _parent->jkeyboard); + jmethodID keyup = (*env)->GetMethodID(env, keyboard_class, "keyReleased", "(IIJ)V"); + const char* charbuf = [[event characters] cStringUsingEncoding:NSASCIIStringEncoding]; + int charcode = (charbuf == nil) ? 0 : charbuf[0]; + (*env)->CallVoidMethod(env, _parent->jkeyboard, keyup, [event keyCode], charcode, time); +} + +- (void)flagsChanged:(NSEvent *)event { + JNIEnv *env = attachCurrentThread(); + if (env == nil || event == nil || _parent == nil || _parent->jkeyboard == nil) { + return; + } + long time = [event timestamp] * 1000000000; + jclass keyboard_class = (*env)->GetObjectClass(env, _parent->jkeyboard); + jmethodID keydown = (*env)->GetMethodID(env, keyboard_class, "keyPressed", "(IIJ)V"); + jmethodID keyup = (*env)->GetMethodID(env, keyboard_class, "keyReleased", "(IIJ)V"); + _lastModifierFlags = _modifierFlags; + _modifierFlags = [event modifierFlags]; + NSUInteger flagDown = ~_lastModifierFlags & _modifierFlags; + NSUInteger flagUp = _lastModifierFlags & ~_modifierFlags; + if (flagDown & NSAlphaShiftKeyMask) { + (*env)->CallVoidMethod(env, _parent->jkeyboard, keydown, 0xf0, 0, time); + } + if (flagUp & NSAlphaShiftKeyMask) { + (*env)->CallVoidMethod(env, _parent->jkeyboard, keyup, 0xf0, 0, time); + } + if (flagDown & NSShiftKeyMask) { + (*env)->CallVoidMethod(env, _parent->jkeyboard, keydown, 0xf1, 0, time); + } + if (flagUp & NSShiftKeyMask) { + (*env)->CallVoidMethod(env, _parent->jkeyboard, keyup, 0xf1, 0, time); + } + if (flagDown & NSControlKeyMask) { + (*env)->CallVoidMethod(env, _parent->jkeyboard, keydown, 0xf2, 0, time); + } + if (flagUp & NSControlKeyMask) { + (*env)->CallVoidMethod(env, _parent->jkeyboard, keyup, 0xf2, 0, time); + } + if (flagDown & NSAlternateKeyMask) { + (*env)->CallVoidMethod(env, _parent->jkeyboard, keydown, 0xf3, 0, time); + } + if (flagUp & NSAlternateKeyMask) { + (*env)->CallVoidMethod(env, _parent->jkeyboard, keyup, 0xf3, 0, time); + } + if (flagDown & NSCommandKeyMask) { + (*env)->CallVoidMethod(env, _parent->jkeyboard, keydown, 0xf4, 0, time); + } + if (flagUp & NSCommandKeyMask) { + (*env)->CallVoidMethod(env, _parent->jkeyboard, keyup, 0xf4, 0, time); + } + if (flagDown & NSNumericPadKeyMask) { + (*env)->CallVoidMethod(env, _parent->jkeyboard, keydown, 0xf5, 0, time); + } + if (flagUp & NSNumericPadKeyMask) { + (*env)->CallVoidMethod(env, _parent->jkeyboard, keyup, 0xf5, 0, time); + } + //const char* charbuf = [[event characters] cStringUsingEncoding:NSASCIIStringEncoding]; + //(*env)->CallVoidMethod(env, _parent->jkeyboard, keymod, (jint)[event keyCode], (jint)charbuf[0], time); +} + +- (void)mouseButtonState:(NSEvent *)event :(int)button :(int)state { + JNIEnv *env = attachCurrentThread(); + if (env == nil || event == nil || _parent == nil || _parent->jkeyboard == nil) { + return; + } + long time = [event timestamp] * 1000000000; + jclass mouse_class = (*env)->GetObjectClass(env, _parent->jmouse); + jmethodID mousebutton = (*env)->GetMethodID(env, mouse_class, "setButton", "(IIJ)V"); + (*env)->CallVoidMethod(env, _parent->jmouse, mousebutton, button, state, time); +} + +- (void)mouseDown:(NSEvent *)event { + [self mouseButtonState:event :0 :1]; +} + +- (void)rightMouseDown:(NSEvent *)event { + [self mouseButtonState:event :1 :1]; +} + +- (void)otherMouseDown:(NSEvent *)event { + [self mouseButtonState:event :2 :1]; +} + +- (void)mouseUp:(NSEvent *)event { + [self mouseButtonState:event :0 :0]; +} + +- (void)rightMouseUp:(NSEvent *)event { + [self mouseButtonState:event :1 :0]; +} + +- (void)otherMouseUp:(NSEvent *)event { + [self mouseButtonState:event :2 :0]; +} + +- (void)mouseDragged:(NSEvent *)event { + JNIEnv *env = attachCurrentThread(); + if (env == nil || event == nil || _parent == nil) { + return; + } + long time = [event timestamp] * 1000000000; + jclass mouse_class = (*env)->GetObjectClass(env, _parent->jmouse); + jmethodID mousemove = (*env)->GetMethodID(env, mouse_class, "mouseMoved", "(FFFFFJ)V"); + NSPoint loc = [self convertPoint:[event locationInWindow] toView:self]; + (*env)->CallVoidMethod(env, _parent->jmouse, mousemove, loc.x, loc.y, [event deltaX], [event deltaY], 0.0f, time); +} + +- (void)mouseMoved:(NSEvent *)event { + JNIEnv *env = attachCurrentThread(); + if (env == nil || event == nil || _parent == nil || _parent->jmouse == nil) { + return; + } + long time = [event timestamp] * 1000000000; + jclass mouse_class = (*env)->GetObjectClass(env, _parent->jmouse); + jmethodID mousemove = (*env)->GetMethodID(env, mouse_class, "mouseMoved", "(FFFFFJ)V"); + NSPoint loc = [self convertPoint:[event locationInWindow] toView:self]; + (*env)->CallVoidMethod(env, _parent->jmouse, mousemove, loc.x, loc.y, [event deltaX], [event deltaY], 0.0f, time); +} + +- (void)scrollWheel:(NSEvent *)event { + JNIEnv *env = attachCurrentThread(); + if (env == nil || event == nil || _parent == nil) { + return; + } + long time = [event timestamp] * 1000000000; + float dz = [event scrollingDeltaY]; + if (![event hasPreciseScrollingDeltas]) { + dz *= 12; // or so + } + jclass mouse_class = (*env)->GetObjectClass(env, _parent->jmouse); + jmethodID mousemove = (*env)->GetMethodID(env, mouse_class, "mouseMoved", "(FFFFFJ)V"); + NSPoint loc = [self convertPoint:[event locationInWindow] toView:self]; + (*env)->CallVoidMethod(env, _parent->jmouse, mousemove, loc.x, loc.y, [event deltaX], [event deltaY], dz, time); +} + +- (void)viewDidMoveToWindow +{ + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(windowResized:) + name:NSWindowDidResizeNotification + object:[self window]]; +} + +- (void)dealloc +{ + [[NSNotificationCenter defaultCenter] removeObserver:self]; + [super dealloc]; +} + +- (void)windowResized:(NSNotification *)notification; +{ + if (_parent != nil) { + _parent->display_rect = [[self window] frame]; + _parent->resized = JNI_TRUE; + } +} +@end + +JNIEXPORT jboolean JNICALL Java_org_lwjgl_opengl_MacOSXDisplay_nIsMiniaturized(JNIEnv *env, jobject this, jobject window_handle) { + MacOSXWindowInfo *window_info = (MacOSXWindowInfo *)(*env)->GetDirectBufferAddress(env, window_handle); + return (jboolean)[window_info->window isMiniaturized]; +} + +JNIEXPORT jboolean JNICALL Java_org_lwjgl_opengl_MacOSXDisplay_nIsFocused(JNIEnv *env, jobject this, jobject window_handle) { + return JNI_TRUE; + //MacOSXWindowInfo *window_info = (MacOSXWindowInfo *)(*env)->GetDirectBufferAddress(env, window_handle); + //return (jboolean)([window_info->window isKeyWindow] || [window_info->window isMainWindow]); +} + +JNIEXPORT void JNICALL Java_org_lwjgl_opengl_MacOSXDisplay_nResizeWindow(JNIEnv *env, jobject this, jobject window_handle, jint x, jint y, jint width, jint height) { + MacOSXWindowInfo *window_info = (MacOSXWindowInfo *)(*env)->GetDirectBufferAddress(env, window_handle); + window_info->display_rect = NSMakeRect(x, y, width, height); + [window_info->window setFrame:window_info->display_rect display:false]; + [window_info->view update]; +} + +JNIEXPORT jboolean JNICALL Java_org_lwjgl_opengl_MacOSXDisplay_nWasResized(JNIEnv *env, jobject this, jobject window_handle) { + MacOSXWindowInfo *window_info = (MacOSXWindowInfo *)(*env)->GetDirectBufferAddress(env, window_handle); + jboolean was_resized = window_info->resized; + window_info->resized = JNI_FALSE; + return was_resized; +} + +JNIEXPORT void JNICALL Java_org_lwjgl_opengl_MacOSXDisplay_nSetResizable(JNIEnv *env, jobject this, jobject window_handle, jboolean resizable) { + MacOSXWindowInfo *window_info = (MacOSXWindowInfo *)(*env)->GetDirectBufferAddress(env, window_handle); + NSUInteger style_mask = [window_info->window styleMask]; + if (resizable == true) { + style_mask |= NSResizableWindowMask; + } else { + style_mask &= ~NSResizableWindowMask; + } + [window_info->window setStyleMask:style_mask]; +} + +JNIEXPORT void JNICALL Java_org_lwjgl_opengl_MacOSXDisplay_nDestroyWindow(JNIEnv *env, jobject this, jobject window_handle) { + MacOSXWindowInfo *window_info = (MacOSXWindowInfo *)(*env)->GetDirectBufferAddress(env, window_handle); + + if (window_info->window != nil) { + [window_info->window close]; + } + window_info->window = nil; + + if (window_info->view != nil) { + [window_info->view release]; + } + window_info->view = nil; + //[window_info->window release]; +} + +JNIEXPORT void JNICALL Java_org_lwjgl_opengl_MacOSXDisplay_nSetTitle(JNIEnv *env, jobject this, jobject window_handle, jobject title_buffer) { + MacOSXWindowInfo *window_info = (MacOSXWindowInfo *)(*env)->GetDirectBufferAddress(env, window_handle); + const char *title_cstr = (const char *)(*env)->GetDirectBufferAddress(env, title_buffer); + NSString *title = [[NSString alloc] initWithUTF8String:title_cstr]; + [window_info->window setTitle:title]; +} + +JNIEXPORT jobject JNICALL Java_org_lwjgl_opengl_MacOSXDisplay_nCreateWindow(JNIEnv *env, jobject this, jint x, jint y, jint width, jint height, jboolean fullscreen, jboolean undecorated, jobject peer_info_handle, jobject window_handle) { + + if (window_handle == NULL) { + window_handle = newJavaManagedByteBuffer(env, sizeof(MacOSXWindowInfo)); + if (window_handle == NULL) { + throwException(env, "Could not create handle buffer"); + return NULL; + } + } + + MacOSXWindowInfo *window_info = (MacOSXWindowInfo *)(*env)->GetDirectBufferAddress(env, window_handle); + MacOSXPeerInfo *peer_info = (MacOSXPeerInfo *)(*env)->GetDirectBufferAddress(env, peer_info_handle); + + // Cache the necessary info for window-close callbacks into the JVM + if (window_info->jdisplay == NULL) { + window_info->jdisplay = (*env)->NewGlobalRef(env, this); + } + + window_info->display_rect = NSMakeRect(x, y, width, height); + int default_window_mask = NSBorderlessWindowMask; + if (!undecorated && !fullscreen) { + printf("Resizeable\n"); fflush(stdout); + default_window_mask = NSTitledWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask | NSResizableWindowMask; + } + window_info->window = (MacOSXKeyableWindow*)[[NSApplication sharedApplication] mainWindow]; + if (window_info->window == nil) { + window_info->window = [[MacOSXKeyableWindow alloc] initWithContentRect:window_info->display_rect styleMask:default_window_mask backing:NSBackingStoreBuffered defer:YES]; + } + + NSRect view_rect = NSMakeRect(0.0, 0.0, width, height); + window_info->view = [[MacOSXOpenGLView alloc] initWithFrame:view_rect pixelFormat:peer_info->pixel_format]; + if (window_info->context != nil) { + printf("Setting context\n"); fflush(stdout); + [window_info->view setOpenGLContext:window_info->context]; + } + + // Inform the view of its parent window info; used to register for window-close callbacks + [window_info->view setParent:window_info]; + + [window_info->window setContentView:window_info->view]; + [window_info->window makeKeyAndOrderFront:[NSApplication sharedApplication]]; + [window_info->window makeFirstResponder:window_info->view]; + [window_info->window setReleasedWhenClosed:YES]; + [window_info->window setInitialFirstResponder:window_info->view]; + + if (window_info->window_options != NSApplicationPresentationDefault) { + printf("Non-default\n"); fflush(stdout); + [[NSApplication sharedApplication] setPresentationOptions:window_info->window_options]; + } + + peer_info->window_info = window_info; + + return window_handle; +} + JNIEXPORT jint JNICALL Java_org_lwjgl_DefaultSysImplementation_getJNIVersion (JNIEnv *env, jobject ignored) { return org_lwjgl_MacOSXSysImplementation_JNI_VERSION; @@ -69,10 +484,30 @@ JNIEXPORT void JNICALL Java_org_lwjgl_opengl_MacOSXDisplay_setGammaRamp(JNIEnv * } } -JNIEXPORT void JNICALL Java_org_lwjgl_opengl_MacOSXDisplay_nHideUI(JNIEnv *env, jobject this, jboolean hide) { - if (hide == JNI_TRUE) { - SetSystemUIMode(kUIModeContentSuppressed, 0); - } else { - SetSystemUIMode(kUIModeNormal, 0); - } +JNIEXPORT void JNICALL Java_org_lwjgl_opengl_MacOSXDisplay_nHideUI(JNIEnv *env, jobject this, jobject window_handle, jboolean hide) { + if (window_handle == NULL) { + printf("Window handle is null\n"); + return; + } + + MacOSXWindowInfo *window_info = (MacOSXWindowInfo *)(*env)->GetDirectBufferAddress(env, window_handle); + if(floor(NSAppKitVersionNumber) > NSAppKitVersionNumber10_5) { + NSApplicationPresentationOptions options = NSApplicationPresentationDefault; + if (hide == JNI_TRUE) { + options = NSApplicationPresentationFullScreen; + options |= NSApplicationPresentationHideDock; + options |= NSApplicationPresentationHideMenuBar; + } + printf("Setting options\n"); + window_info->window_options = options; + if (window_info->window != nil) { + [[NSApplication sharedApplication] setPresentationOptions:options]; + } + } else { + if (hide == JNI_TRUE) { + SetSystemUIMode(kUIModeContentSuppressed, 0); + } else { + SetSystemUIMode(kUIModeNormal, 0); + } + } } diff --git a/src/native/macosx/org_lwjgl_opengl_MacOSXCanvasPeerInfo.m b/src/native/macosx/org_lwjgl_opengl_MacOSXCanvasPeerInfo.m index 1593fb0d..3c982b8d 100644 --- a/src/native/macosx/org_lwjgl_opengl_MacOSXCanvasPeerInfo.m +++ b/src/native/macosx/org_lwjgl_opengl_MacOSXCanvasPeerInfo.m @@ -42,217 +42,17 @@ #import #include -#include -#include "awt_tools.h" #include "org_lwjgl_opengl_MacOSXCanvasPeerInfo.h" #include "context.h" #include "common_tools.h" -@interface AttachLayerOnMainThread : NSObject { - MacOSXPeerInfo *peer_info; - JAWT_MacOSXDrawingSurfaceInfo *macosx_dsi; -} - -- (void) attachLayer; - -- (MacOSXPeerInfo*) peer_info; -- (JAWT_MacOSXDrawingSurfaceInfo) macosx_dsi; - -- (void) setPeer_info: (MacOSXPeerInfo*)input; -- (void) setMacosx_dsi: (JAWT_MacOSXDrawingSurfaceInfo*)input; - -@end - JNIEXPORT void JNICALL Java_org_lwjgl_opengl_MacOSXCanvasPeerInfo_nInitHandle -(JNIEnv *env, jclass clazz, jobject lock_buffer_handle, jobject peer_info_handle, jboolean allowCALayer) { +(JNIEnv *env, jclass clazz, jobject peer_info_handle) { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; MacOSXPeerInfo *peer_info = (MacOSXPeerInfo *)(*env)->GetDirectBufferAddress(env, peer_info_handle); - AWTSurfaceLock *surface = (AWTSurfaceLock *)(*env)->GetDirectBufferAddress(env, lock_buffer_handle); - JAWT_MacOSXDrawingSurfaceInfo *macosx_dsi = (JAWT_MacOSXDrawingSurfaceInfo *)surface->dsi->platformInfo; - - if (allowCALayer) { - // check for CALayer support - if(surface->awt.version & 0x80000000) { //JAWT_MACOSX_USE_CALAYER) { - jint width = surface->dsi->bounds.width; - jint height = surface->dsi->bounds.height; - - if(peer_info->pbuffer == NULL || peer_info->window || width != [peer_info->pbuffer pixelsWide] || height != [peer_info->pbuffer pixelsHigh]) { - if(peer_info->pbuffer != NULL) { - [peer_info->pbuffer release]; - } - - // make pbuffer - NSOpenGLPixelBuffer *pbuffer = nil; - NSLog(@"Make pbuffer: %d x %d", width, height); - pbuffer = [[NSOpenGLPixelBuffer alloc] initWithTextureTarget:GL_TEXTURE_RECTANGLE_EXT - textureInternalFormat:GL_RGBA - textureMaxMipMapLevel:0 - pixelsWide:width - pixelsHigh:height]; - - peer_info->pbuffer = pbuffer; - peer_info->window = false; - peer_info->canDrawGL = true; - } - - if (macosx_dsi != NULL) { - - AttachLayerOnMainThread *attachLayerOnMainThread = [[AttachLayerOnMainThread new] autorelease]; - attachLayerOnMainThread.peer_info = peer_info; - attachLayerOnMainThread.macosx_dsi = macosx_dsi; - - [JNFRunLoop performOnMainThread:@selector(attachLayer) - on:attachLayerOnMainThread - withObject:nil - waitUntilDone:YES]; - } - - [pool release]; - return; - } - } - - peer_info->nsview = macosx_dsi->cocoaViewRef; - peer_info->window = true; + + peer_info->isWindowed = true; [pool release]; } - -@interface PBufferGLLayer : NSOpenGLLayer { - MacOSXPeerInfo *peer_info; - GLuint textureID; -} - -- (MacOSXPeerInfo*) peer_info; -- (GLuint) textureID; - -- (void) setPeer_info: (MacOSXPeerInfo*)input; -- (void) setTextureID: (GLuint)input; - -@end - -// Object class to CALayer on AppKit Thread -@implementation AttachLayerOnMainThread - -- (void) attachLayer { - // attach the "root layer" to the AWT Canvas surface layers - id surfaceLayers = (id )macosx_dsi;//dsi->platformInfo; - if(surfaceLayers.layer == NULL) { - PBufferGLLayer *caGLLayer = [[PBufferGLLayer new] autorelease]; - caGLLayer.peer_info = peer_info; - caGLLayer.asynchronous = YES; - caGLLayer.needsDisplayOnBoundsChange = YES; - caGLLayer.opaque = YES; - surfaceLayers.layer = caGLLayer; - } -} - -- (MacOSXPeerInfo*) peer_info { - return peer_info; -} - -- (JAWT_MacOSXDrawingSurfaceInfo*) macosx_dsi { - return macosx_dsi; -} - -- (void) setPeer_info: (MacOSXPeerInfo*)input { - peer_info = input; -} - -- (void) setMacosx_dsi: (JAWT_MacOSXDrawingSurfaceInfo*)input { - macosx_dsi = input; -} - -@end - -// rotates a red square when asked to draw -@implementation PBufferGLLayer - -// override to draw custom GL content --(void)drawInCGLContext:(CGLContextObj)glContext - pixelFormat:(CGLPixelFormatObj)pixelFormat - forLayerTime:(CFTimeInterval)timeInterval - displayTime:(const CVTimeStamp *)timeStamp { - - if(!peer_info || !peer_info->pbuffer) { - return; - } - - peer_info->canDrawGL = false; - - NSOpenGLPixelBuffer *pbuffer = self.peer_info->pbuffer; - - // set the current context - CGLSetCurrentContext(glContext); - - GLsizei width = [pbuffer pixelsWide]; - GLsizei height = [pbuffer pixelsHigh]; - - if(textureID == 0) { - glGenTextures(1, &textureID); - } - glBindTexture(GL_TEXTURE_RECTANGLE_EXT, self.textureID); - CGLTexImagePBuffer(glContext,[pbuffer CGLPBufferObj], GL_FRONT); - - glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - - glEnable(GL_TEXTURE_RECTANGLE_EXT); - - static GLfloat verts[] = { - -1.0, -1.0, - -1.0, 1.0, - 1.0, 1.0, - 1.0, -1.0 - }; - - GLfloat tex[] = { - 0.0, 0.0, - 0.0, height, - width, height, - width, 0.0 - }; - - glEnableClientState(GL_VERTEX_ARRAY); - glEnableClientState(GL_TEXTURE_COORD_ARRAY); - glVertexPointer(2, GL_FLOAT, 0, verts); - glTexCoordPointer(2, GL_FLOAT, 0, tex); - - glDrawArrays(GL_QUADS, 0, 4); - - glDisableClientState(GL_VERTEX_ARRAY); - glDisableClientState(GL_TEXTURE_COORD_ARRAY); - - glDisable(GL_TEXTURE_RECTANGLE_EXT); - - // call super to finalize the drawing - by default all it does is call glFlush() - [super drawInCGLContext:glContext pixelFormat:pixelFormat forLayerTime:timeInterval displayTime:timeStamp]; -} - --(BOOL)canDrawInCGLContext:(CGLContextObj)glContext - pixelFormat:(CGLPixelFormatObj)pixelFormat - forLayerTime:(CFTimeInterval)timeInterval - displayTime:(const CVTimeStamp *)timeStamp { - return (peer_info->canDrawGL && !peer_info->window) ? YES : NO; -} - -- (MacOSXPeerInfo*) peer_info { - return peer_info; -} - -- (GLuint) textureID { - return textureID; -} - -- (void) setPeer_info: (MacOSXPeerInfo*)input { - peer_info = input; -} - -- (void) setTextureID: (GLuint)input { - textureID = input; -} - -@end \ No newline at end of file diff --git a/src/native/macosx/org_lwjgl_opengl_MacOSXContextImplementation.m b/src/native/macosx/org_lwjgl_opengl_MacOSXContextImplementation.m index aecebe1c..36d40565 100644 --- a/src/native/macosx/org_lwjgl_opengl_MacOSXContextImplementation.m +++ b/src/native/macosx/org_lwjgl_opengl_MacOSXContextImplementation.m @@ -47,7 +47,7 @@ #import "common_tools.h" typedef struct { - NSOpenGLContext *context; + NSOpenGLContext *context; MacOSXPeerInfo *peer_info; } MacOSXContext; @@ -57,8 +57,9 @@ JNIEXPORT jobject JNICALL Java_org_lwjgl_opengl_MacOSXContextImplementation_nCre MacOSXPeerInfo *peer_info; MacOSXContext *shared_context_info; MacOSXContext *context_info; - NSOpenGLContext *context; - NSOpenGLContext *shared_context = NULL; + NSOpenGLContext *context; + NSOpenGLContext *shared_context; + printf("nCreate\n"); jobject context_handle = newJavaManagedByteBuffer(env, sizeof(MacOSXContext)); if (context_handle == NULL) { throwException(env, "Could not create handle buffer"); @@ -67,16 +68,19 @@ JNIEXPORT jobject JNICALL Java_org_lwjgl_opengl_MacOSXContextImplementation_nCre peer_info = (MacOSXPeerInfo *)(*env)->GetDirectBufferAddress(env, peer_info_handle); if (shared_context_handle != NULL) { shared_context_info = (MacOSXContext *)(*env)->GetDirectBufferAddress(env, shared_context_handle); - shared_context = shared_context_info->context; - } - context = [[NSOpenGLContext alloc] initWithFormat:peer_info->pixel_format shareContext:shared_context]; - if (context == NULL) { - throwException(env, "Could not create context"); - return NULL; + shared_context = shared_context_info->context; } + context = [[NSOpenGLContext alloc] initWithFormat:peer_info->pixel_format shareContext:shared_context]; + if (context == NULL) { + throwException(env, "Could not create context"); + return NULL; + } + [peer_info->window_info->view setOpenGLContext:context]; + peer_info->window_info->context = context; context_info = (MacOSXContext *)(*env)->GetDirectBufferAddress(env, context_handle); - context_info->context = context; + context_info->context = context; context_info->peer_info = peer_info; + [pool release]; return context_handle; } @@ -84,19 +88,19 @@ JNIEXPORT jobject JNICALL Java_org_lwjgl_opengl_MacOSXContextImplementation_nCre JNIEXPORT jlong JNICALL Java_org_lwjgl_opengl_MacOSXContextImplementation_getCGLShareGroup (JNIEnv *env, jclass clazz, jobject context_handle) { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - MacOSXContext *context_info = (MacOSXContext *)(*env)->GetDirectBufferAddress(env, context_handle); - CGLContextObj cgl_context = [context_info->context CGLContextObj]; + MacOSXPeerInfo *peer_info = ((MacOSXContext *)(*env)->GetDirectBufferAddress(env, context_handle))->peer_info; + CGLContextObj cgl_context = [[peer_info->window_info->view openGLContext] CGLContextObj]; CGLShareGroupObj share_group = CGLGetShareGroup(cgl_context); [pool release]; - return share_group; + return (jlong)share_group; } JNIEXPORT void JNICALL Java_org_lwjgl_opengl_MacOSXContextImplementation_nSwapBuffers (JNIEnv *env, jclass clazz, jobject context_handle) { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - MacOSXContext *context_info = (MacOSXContext *)(*env)->GetDirectBufferAddress(env, context_handle); - [context_info->context flushBuffer]; - context_info->peer_info->canDrawGL = true; + MacOSXPeerInfo *peer_info = ((MacOSXContext *)(*env)->GetDirectBufferAddress(env, context_handle))->peer_info; + [[peer_info->window_info->view openGLContext] flushBuffer]; + peer_info->canDrawGL = true; [pool release]; } @@ -104,37 +108,35 @@ JNIEXPORT void JNICALL Java_org_lwjgl_opengl_MacOSXContextImplementation_nSwapBu JNIEXPORT void JNICALL Java_org_lwjgl_opengl_MacOSXContextImplementation_nUpdate (JNIEnv *env, jclass clazz, jobject context_handle) { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - MacOSXContext *context_info = (MacOSXContext *)(*env)->GetDirectBufferAddress(env, context_handle); - [context_info->context update]; - context_info->peer_info->canDrawGL = true; + MacOSXPeerInfo *peer_info = ((MacOSXContext *)(*env)->GetDirectBufferAddress(env, context_handle))->peer_info; + [[peer_info->window_info->view openGLContext] update]; + peer_info->canDrawGL = true; [pool release]; } JNIEXPORT void JNICALL Java_org_lwjgl_opengl_MacOSXContextImplementation_clearDrawable (JNIEnv *env, jclass clazz, jobject context_handle) { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - MacOSXContext *context_info = (MacOSXContext *)(*env)->GetDirectBufferAddress(env, context_handle); - [context_info->context clearDrawable]; + MacOSXPeerInfo *peer_info = ((MacOSXContext *)(*env)->GetDirectBufferAddress(env, context_handle))->peer_info; + printf("clearDrawable\n"); + [[peer_info->window_info->view openGLContext] clearDrawable]; [pool release]; } JNIEXPORT void JNICALL Java_org_lwjgl_opengl_MacOSXContextImplementation_nReleaseCurrentContext (JNIEnv *env, jclass clazz) { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + printf("nReleaseCurrentContexta\n"); [NSOpenGLContext clearCurrentContext]; [pool release]; } JNIEXPORT void JNICALL Java_org_lwjgl_opengl_MacOSXContextImplementation_setView - (JNIEnv *env, jclass clazz, jobject peer_info_handle, jobject context_handle) { + (JNIEnv *env, jclass clazz, jobject peer_info_handle) { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - MacOSXContext *context_info = (MacOSXContext *)(*env)->GetDirectBufferAddress(env, context_handle); - MacOSXPeerInfo *peer_info = (MacOSXPeerInfo *)(*env)->GetDirectBufferAddress(env, peer_info_handle); - if (peer_info->window) { - [context_info->context setView: peer_info->nsview]; - } else { - [context_info->context setPixelBuffer:peer_info->pbuffer cubeMapFace:0 mipMapLevel:0 currentVirtualScreen:0]; - } + MacOSXPeerInfo *peer_info = (MacOSXPeerInfo *)(*env)->GetDirectBufferAddress(env, peer_info_handle); + printf("setView\n"); + [[peer_info->window_info->view openGLContext] setView: peer_info->window_info->view]; peer_info->canDrawGL = true; [pool release]; } @@ -142,16 +144,17 @@ JNIEXPORT void JNICALL Java_org_lwjgl_opengl_MacOSXContextImplementation_setView JNIEXPORT void JNICALL Java_org_lwjgl_opengl_MacOSXContextImplementation_nMakeCurrent (JNIEnv *env, jclass clazz, jobject context_handle) { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - MacOSXContext *context_info = (MacOSXContext *)(*env)->GetDirectBufferAddress(env, context_handle); - [context_info->context makeCurrentContext]; + MacOSXPeerInfo *peer_info = ((MacOSXContext *)(*env)->GetDirectBufferAddress(env, context_handle))->peer_info; + printf("nMakeCurrent\n"); + [[peer_info->window_info->view openGLContext] makeCurrentContext]; [pool release]; } JNIEXPORT jboolean JNICALL Java_org_lwjgl_opengl_MacOSXContextImplementation_nIsCurrent (JNIEnv *env, jclass clazz, jobject context_handle) { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - MacOSXContext *context_info = (MacOSXContext *)(*env)->GetDirectBufferAddress(env, context_handle); - bool result = context_info->context == [NSOpenGLContext currentContext]; + MacOSXPeerInfo *peer_info = ((MacOSXContext *)(*env)->GetDirectBufferAddress(env, context_handle))->peer_info; + bool result = [peer_info->window_info->view openGLContext] == [NSOpenGLContext currentContext]; [pool release]; return result ? JNI_TRUE : JNI_FALSE; } @@ -159,17 +162,18 @@ JNIEXPORT jboolean JNICALL Java_org_lwjgl_opengl_MacOSXContextImplementation_nIs JNIEXPORT void JNICALL Java_org_lwjgl_opengl_MacOSXContextImplementation_nSetSwapInterval (JNIEnv *env, jclass clazz, jobject context_handle, jint int_value) { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - MacOSXContext *context_info = (MacOSXContext *)(*env)->GetDirectBufferAddress(env, context_handle); + MacOSXPeerInfo *peer_info = ((MacOSXContext *)(*env)->GetDirectBufferAddress(env, context_handle))->peer_info; GLint value = int_value; - [context_info->context setValues:&value forParameter:NSOpenGLCPSwapInterval]; + [[peer_info->window_info->view openGLContext] setValues:&value forParameter:NSOpenGLCPSwapInterval]; [pool release]; } JNIEXPORT void JNICALL Java_org_lwjgl_opengl_MacOSXContextImplementation_nDestroy (JNIEnv *env, jclass clazz, jobject context_handle) { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - MacOSXContext *context_info = (MacOSXContext *)(*env)->GetDirectBufferAddress(env, context_handle); - [context_info->context clearDrawable]; - [context_info->context release]; + MacOSXPeerInfo *peer_info = ((MacOSXContext *)(*env)->GetDirectBufferAddress(env, context_handle))->peer_info; + printf("nDestroy\n"); + [[peer_info->window_info->view openGLContext] clearDrawable]; + [[peer_info->window_info->view openGLContext] release]; [pool release]; } diff --git a/src/native/macosx/org_lwjgl_opengl_MacOSXNativeKeyboard.m b/src/native/macosx/org_lwjgl_opengl_MacOSXNativeKeyboard.m new file mode 100644 index 00000000..aec26e84 --- /dev/null +++ b/src/native/macosx/org_lwjgl_opengl_MacOSXNativeKeyboard.m @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2002-2012 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. + */ + +/** + * $Id: org_lwjgl_opengl_MacOSXNativeKeyboard.m 3055 2012-08-29 0:46:00Z mojang $ + * + * Mac OS X native keyboard functions. + * + * @author mojang + * @version $Revision: 3055 $ + */ + +#import +#import +#import +#import +#import "common_tools.h" +#import "org_lwjgl_opengl_MacOSXNativeKeyboard.h" +#import "context.h" + +JNIEXPORT void JNICALL Java_org_lwjgl_opengl_MacOSXNativeKeyboard_nRegisterKeyListener(JNIEnv *env, jobject this, jobject window_handle) { + MacOSXWindowInfo *window_info = (MacOSXWindowInfo *)(*env)->GetDirectBufferAddress(env, window_handle); + window_info->jkeyboard = (*env)->NewGlobalRef(env, this); +} + +JNIEXPORT void JNICALL Java_org_lwjgl_opengl_MacOSXNativeKeyboard_nUnregisterKeyListener(JNIEnv *env, jobject this, jobject window_handle) { + MacOSXWindowInfo *window_info = (MacOSXWindowInfo *)(*env)->GetDirectBufferAddress(env, window_handle); + window_info->jkeyboard = NULL; +} diff --git a/src/native/macosx/org_lwjgl_opengl_MacOSXNativeMouse.m b/src/native/macosx/org_lwjgl_opengl_MacOSXNativeMouse.m new file mode 100644 index 00000000..db774a89 --- /dev/null +++ b/src/native/macosx/org_lwjgl_opengl_MacOSXNativeMouse.m @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2002-2012 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. + */ + +/** + * $Id: org_lwjgl_opengl_MacOSXNativeKeyboard.m 3055 2012-08-29 0:46:00Z mojang $ + * + * Mac OS X native keyboard functions. + * + * @author mojang + * @version $Revision: 3055 $ + */ + +#import +#import +#import +#import +#import "common_tools.h" +#import "org_lwjgl_opengl_MacOSXNativeMouse.h" +#import "context.h" + +JNIEXPORT void JNICALL Java_org_lwjgl_opengl_MacOSXNativeMouse_nGrabMouse(JNIEnv *env, jclass this, jboolean grab) { + CGAssociateMouseAndMouseCursorPosition(grab == JNI_TRUE ? FALSE : TRUE); + if (grab) + CGDisplayHideCursor(kCGDirectMainDisplay); + else + CGDisplayShowCursor(kCGDirectMainDisplay); +} + +JNIEXPORT void JNICALL Java_org_lwjgl_opengl_MacOSXNativeMouse_nWarpCursor(JNIEnv *env, jclass this, jobject window_handle, jint x, jint y) { + MacOSXWindowInfo *window_info = (MacOSXWindowInfo *)(*env)->GetDirectBufferAddress(env, window_handle); + NSPoint point = NSMakePoint(x, y); + point = [window_info->view convertPoint:point fromView:window_info->view]; + CGPoint p; + p.x = point.x; + p.y = point.y; + CGWarpMouseCursorPosition(p); +} + +JNIEXPORT void JNICALL Java_org_lwjgl_opengl_MacOSXNativeMouse_nRegisterMouseListener(JNIEnv *env, jobject _this, jobject window_handle) { + MacOSXWindowInfo *window_info = (MacOSXWindowInfo *)(*env)->GetDirectBufferAddress(env, window_handle); + [window_info->window setAcceptsMouseMovedEvents:YES]; + window_info->jmouse = (*env)->NewGlobalRef(env, _this); +} + +JNIEXPORT void JNICALL Java_org_lwjgl_opengl_MacOSXNativeMouse_nUnregisterMouseListener(JNIEnv *env, jobject this, jobject window_handle) { + MacOSXWindowInfo *window_info = (MacOSXWindowInfo *)(*env)->GetDirectBufferAddress(env, window_handle); + [window_info->window setAcceptsMouseMovedEvents:NO]; + window_info->jmouse = nil; +} diff --git a/src/native/macosx/org_lwjgl_opengl_MacOSXPbufferPeerInfo.m b/src/native/macosx/org_lwjgl_opengl_MacOSXPbufferPeerInfo.m index 46fa5655..e1e41dff 100644 --- a/src/native/macosx/org_lwjgl_opengl_MacOSXPbufferPeerInfo.m +++ b/src/native/macosx/org_lwjgl_opengl_MacOSXPbufferPeerInfo.m @@ -65,7 +65,7 @@ JNIEXPORT void JNICALL Java_org_lwjgl_opengl_MacOSXPbufferPeerInfo_nCreate(JNIEn } MacOSXPeerInfo *peer_info = (MacOSXPeerInfo *)(*env)->GetDirectBufferAddress(env, peer_info_handle); peer_info->pbuffer = pbuffer; - peer_info->window = false; + peer_info->isWindowed = false; [pool release]; }