1 /* 2 * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package sun.lwawt.macosx; 27 28 import java.awt.*; 29 import java.awt.geom.Rectangle2D; 30 import java.awt.image.VolatileImage; 31 32 import sun.awt.CGraphicsConfig; 33 import sun.awt.CGraphicsEnvironment; 34 import sun.lwawt.LWWindowPeer; 35 import sun.lwawt.macosx.event.NSEvent; 36 37 import sun.java2d.SurfaceData; 38 import sun.java2d.opengl.CGLLayer; 39 import sun.java2d.opengl.CGLSurfaceData; 40 41 public class CPlatformView extends CFRetainedResource { 42 private native long nativeCreateView(int x, int y, int width, int height, long windowLayerPtr); 43 private static native void nativeSetAutoResizable(long awtView, boolean toResize); 44 private static native int nativeGetNSViewDisplayID(long awtView); 45 private static native Rectangle2D nativeGetLocationOnScreen(long awtView); 46 private static native boolean nativeIsViewUnderMouse(long ptr); 47 48 private LWWindowPeer peer; 49 private SurfaceData surfaceData; 50 private CGLLayer windowLayer; 51 private CPlatformResponder responder; 52 53 public CPlatformView() { 54 super(0, true); 55 } 56 57 public void initialize(LWWindowPeer peer, CPlatformResponder responder) { 58 this.peer = peer; 59 this.responder = responder; 60 61 if (!LWCToolkit.getSunAwtDisableCALayers()) { 62 this.windowLayer = new CGLLayer(peer); 63 } 64 setPtr(nativeCreateView(0, 0, 0, 0, getWindowLayerPtr())); 65 } 66 67 public long getAWTView() { 68 return ptr; 69 } 70 71 public boolean isOpaque() { 72 return !peer.isTranslucent(); 73 } 74 75 /* 76 * All coordinates passed to the method should be based on the origin being in the bottom-left corner (standard 77 * Cocoa coordinates). 78 */ 79 public void setBounds(int x, int y, int width, int height) { 80 CWrapper.NSView.setFrame(ptr, x, y, width, height); 81 } 82 83 // REMIND: CGLSurfaceData expects top-level's size 84 public Rectangle getBounds() { 85 return peer.getBounds(); 86 } 87 88 public Object getDestination() { 89 return peer; 90 } 91 92 public void enterFullScreenMode(final long nsWindowPtr) { 93 CWrapper.NSView.enterFullScreenMode(ptr); 94 95 // REMIND: CGLSurfaceData expects top-level's size 96 // and therefore we need to account insets before 97 // recreating the surface data 98 Insets insets = peer.getInsets(); 99 100 Rectangle screenBounds; 101 final long screenPtr = CWrapper.NSWindow.screen(nsWindowPtr); 102 try { 103 screenBounds = CWrapper.NSScreen.frame(screenPtr).getBounds(); 104 } finally { 105 CWrapper.NSObject.release(screenPtr); 106 } 107 108 // the move/size notification from the underlying system comes 109 // but it contains a bounds smaller than the whole screen 110 // and therefore we need to create the synthetic notifications 111 peer.notifyReshape(screenBounds.x - insets.left, 112 screenBounds.y - insets.bottom, 113 screenBounds.width + insets.left + insets.right, 114 screenBounds.height + insets.top + insets.bottom); 115 } 116 117 public void exitFullScreenMode() { 118 CWrapper.NSView.exitFullScreenMode(ptr); 119 } 120 121 // ---------------------------------------------------------------------- 122 // PAINTING METHODS 123 // ---------------------------------------------------------------------- 124 public SurfaceData replaceSurfaceData() { 125 if (!LWCToolkit.getSunAwtDisableCALayers()) { 126 surfaceData = windowLayer.replaceSurfaceData(); 127 } else { 128 if (surfaceData == null) { 129 CGraphicsConfig graphicsConfig = (CGraphicsConfig)peer.getGraphicsConfiguration(); 130 surfaceData = graphicsConfig.createSurfaceData(this); 131 } else { 132 validateSurface(); 133 } 134 } 135 return surfaceData; 136 } 137 138 private void validateSurface() { 139 if (surfaceData != null) { 140 ((CGLSurfaceData)surfaceData).validate(); 141 } 142 } 143 144 public GraphicsConfiguration getGraphicsConfiguration() { 145 return peer.getGraphicsConfiguration(); 146 } 147 148 public SurfaceData getSurfaceData() { 149 return surfaceData; 150 } 151 152 @Override 153 public void dispose() { 154 if (!LWCToolkit.getSunAwtDisableCALayers()) { 155 windowLayer.dispose(); 156 } 157 super.dispose(); 158 } 159 160 public long getWindowLayerPtr() { 161 if (!LWCToolkit.getSunAwtDisableCALayers()) { 162 return windowLayer.getPointer(); 163 } else { 164 return 0; 165 } 166 } 167 168 public void setAutoResizable(boolean toResize) { 169 nativeSetAutoResizable(this.getAWTView(), toResize); 170 } 171 172 public boolean isUnderMouse() { 173 return nativeIsViewUnderMouse(getAWTView()); 174 } 175 176 public GraphicsDevice getGraphicsDevice() { 177 GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); 178 CGraphicsEnvironment cge = (CGraphicsEnvironment)ge; 179 int displayID = nativeGetNSViewDisplayID(getAWTView()); 180 GraphicsDevice gd = cge.getScreenDevice(displayID); 181 if (gd == null) { 182 // this could possibly happen during device removal 183 // use the default screen device in this case 184 gd = ge.getDefaultScreenDevice(); 185 } 186 return gd; 187 } 188 189 public Point getLocationOnScreen() { 190 Rectangle r = nativeGetLocationOnScreen(this.getAWTView()).getBounds(); 191 return new Point(r.x, r.y); 192 } 193 194 // ---------------------------------------------------------------------- 195 // NATIVE CALLBACKS 196 // ---------------------------------------------------------------------- 197 198 /* 199 * The callback is called only in the embedded case when the view is 200 * automatically resized by the superview. 201 * In normal mode this method is never called. 202 */ 203 private void deliverResize(int x, int y, int w, int h) { 204 peer.notifyReshape(x, y, w, h); 205 } 206 207 208 private void deliverMouseEvent(NSEvent event) { 209 int x = event.getX(); 210 int y = getBounds().height - event.getY(); 211 212 if (event.getType() == CocoaConstants.NSScrollWheel) { 213 responder.handleScrollEvent(x, y, event.getModifierFlags(), 214 event.getScrollDeltaX(), event.getScrollDeltaY()); 215 } else { 216 responder.handleMouseEvent(event.getType(), event.getModifierFlags(), event.getButtonNumber(), 217 event.getClickCount(), x, y, event.getAbsX(), event.getAbsY()); 218 } 219 } 220 221 private void deliverKeyEvent(NSEvent event) { 222 responder.handleKeyEvent(event.getType(), event.getModifierFlags(), 223 event.getCharactersIgnoringModifiers(), event.getKeyCode(), true); 224 } 225 226 /** 227 * Called by the native delegate in layer backed view mode or in the simple 228 * NSView mode. See NSView.drawRect(). 229 */ 230 private void deliverWindowDidExposeEvent() { 231 peer.notifyExpose(peer.getSize()); 232 } 233 }