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.event.*; 30 import java.awt.geom.Rectangle2D; 31 import java.awt.image.VolatileImage; 32 33 import sun.awt.CGraphicsConfig; 34 import sun.awt.CGraphicsEnvironment; 35 import sun.lwawt.LWWindowPeer; 36 import sun.lwawt.macosx.event.NSEvent; 37 38 import sun.java2d.SurfaceData; 39 import sun.java2d.opengl.CGLLayer; 40 import sun.java2d.opengl.CGLSurfaceData; 41 42 public class CPlatformView extends CFRetainedResource { 43 private native long nativeCreateView(int x, int y, int width, int height, long windowLayerPtr); 44 private static native void nativeSetAutoResizable(long awtView, boolean toResize); 45 private static native int nativeGetNSViewDisplayID(long awtView); 46 private static native Rectangle2D nativeGetLocationOnScreen(long awtView); 47 private static native boolean nativeIsViewUnderMouse(long ptr); 48 49 private LWWindowPeer peer; 50 private SurfaceData surfaceData; 51 private CGLLayer windowLayer; 52 private CPlatformResponder responder; 53 54 public CPlatformView() { 55 super(0, true); 56 } 57 58 public void initialize(LWWindowPeer peer, CPlatformResponder responder) { 59 this.peer = peer; 60 this.responder = responder; 61 62 if (!LWCToolkit.getSunAwtDisableCALayers()) { 63 this.windowLayer = new CGLLayer(peer); 64 } 65 setPtr(nativeCreateView(0, 0, 0, 0, getWindowLayerPtr())); 66 } 67 68 public long getAWTView() { 69 return ptr; 70 } 71 72 public boolean isOpaque() { 73 return !peer.isTranslucent(); 74 } 75 76 /* 77 * All coordinates passed to the method should be based on the origin being in the bottom-left corner (standard 78 * Cocoa coordinates). 79 */ 80 public void setBounds(int x, int y, int width, int height) { 81 CWrapper.NSView.setFrame(ptr, x, y, width, height); 82 } 83 84 // REMIND: CGLSurfaceData expects top-level's size 85 public Rectangle getBounds() { 86 return peer.getBounds(); 87 } 88 89 public Object getDestination() { 90 return peer; 91 } 92 93 public void enterFullScreenMode(final long nsWindowPtr) { 94 CWrapper.NSView.enterFullScreenMode(ptr); 95 96 // REMIND: CGLSurfaceData expects top-level's size 97 // and therefore we need to account insets before 98 // recreating the surface data 99 Insets insets = peer.getInsets(); 100 101 Rectangle screenBounds; 102 final long screenPtr = CWrapper.NSWindow.screen(nsWindowPtr); 103 try { 104 screenBounds = CWrapper.NSScreen.frame(screenPtr).getBounds(); 105 } finally { 106 CWrapper.NSObject.release(screenPtr); 107 } 108 109 // the move/size notification from the underlying system comes 110 // but it contains a bounds smaller than the whole screen 111 // and therefore we need to create the synthetic notifications 112 peer.notifyReshape(screenBounds.x - insets.left, 113 screenBounds.y - insets.bottom, 114 screenBounds.width + insets.left + insets.right, 115 screenBounds.height + insets.top + insets.bottom); 116 } 117 118 public void exitFullScreenMode() { 119 CWrapper.NSView.exitFullScreenMode(ptr); 120 } 121 122 // ---------------------------------------------------------------------- 123 // PAINTING METHODS 124 // ---------------------------------------------------------------------- 125 126 public void drawImageOnPeer(VolatileImage xBackBuffer, int x1, int y1, int x2, int y2) { 127 Graphics g = peer.getGraphics(); 128 try { 129 g.drawImage(xBackBuffer, x1, y1, x2, y2, x1, y1, x2, y2, null); 130 } finally { 131 g.dispose(); 132 } 133 } 134 135 public Image createBackBuffer() { 136 Rectangle r = peer.getBounds(); 137 Image im = null; 138 if (!r.isEmpty()) { 139 int transparency = (isOpaque() ? Transparency.OPAQUE : Transparency.TRANSLUCENT); 140 im = peer.getGraphicsConfiguration().createCompatibleImage(r.width, r.height, transparency); 141 } 142 return im; 143 } 144 145 public SurfaceData replaceSurfaceData() { 146 if (!LWCToolkit.getSunAwtDisableCALayers()) { 147 surfaceData = windowLayer.replaceSurfaceData(); 148 } else { 149 if (surfaceData == null) { 150 CGraphicsConfig graphicsConfig = (CGraphicsConfig)peer.getGraphicsConfiguration(); 151 surfaceData = graphicsConfig.createSurfaceData(this); 152 } else { 153 validateSurface(); 154 } 155 } 156 return surfaceData; 157 } 158 159 private void validateSurface() { 160 if (surfaceData != null) { 161 ((CGLSurfaceData)surfaceData).validate(); 162 } 163 } 164 165 public GraphicsConfiguration getGraphicsConfiguration() { 166 return peer.getGraphicsConfiguration(); 167 } 168 169 public SurfaceData getSurfaceData() { 170 return surfaceData; 171 } 172 173 @Override 174 public void dispose() { 175 if (!LWCToolkit.getSunAwtDisableCALayers()) { 176 windowLayer.dispose(); 177 } 178 super.dispose(); 179 } 180 181 public long getWindowLayerPtr() { 182 if (!LWCToolkit.getSunAwtDisableCALayers()) { 183 return windowLayer.getPointer(); 184 } else { 185 return 0; 186 } 187 } 188 189 public void setAutoResizable(boolean toResize) { 190 nativeSetAutoResizable(this.getAWTView(), toResize); 191 } 192 193 public boolean isUnderMouse() { 194 return nativeIsViewUnderMouse(getAWTView()); 195 } 196 197 public GraphicsDevice getGraphicsDevice() { 198 GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); 199 CGraphicsEnvironment cge = (CGraphicsEnvironment)ge; 200 int displayID = nativeGetNSViewDisplayID(getAWTView()); 201 GraphicsDevice gd = cge.getScreenDevice(displayID); 202 if (gd == null) { 203 // this could possibly happen during device removal 204 // use the default screen device in this case 205 gd = ge.getDefaultScreenDevice(); 206 } 207 return gd; 208 } 209 210 public Point getLocationOnScreen() { 211 Rectangle r = nativeGetLocationOnScreen(this.getAWTView()).getBounds(); 212 return new Point(r.x, r.y); 213 } 214 215 // ---------------------------------------------------------------------- 216 // NATIVE CALLBACKS 217 // ---------------------------------------------------------------------- 218 219 /* 220 * The callback is called only in the embedded case when the view is 221 * automatically resized by the superview. 222 * In normal mode this method is never called. 223 */ 224 private void deliverResize(int x, int y, int w, int h) { 225 peer.notifyReshape(x, y, w, h); 226 } 227 228 229 private void deliverMouseEvent(NSEvent event) { 230 int x = event.getX(); 231 int y = getBounds().height - event.getY(); 232 233 if (event.getType() == CocoaConstants.NSScrollWheel) { 234 responder.handleScrollEvent(x, y, event.getModifierFlags(), 235 event.getScrollDeltaX(), event.getScrollDeltaY()); 236 } else { 237 responder.handleMouseEvent(event.getType(), event.getModifierFlags(), event.getButtonNumber(), 238 event.getClickCount(), x, y, event.getAbsX(), event.getAbsY()); 239 } 240 } 241 242 private void deliverKeyEvent(NSEvent event) { 243 responder.handleKeyEvent(event.getType(), event.getModifierFlags(), 244 event.getCharactersIgnoringModifiers(), event.getKeyCode(), true); 245 } 246 247 private void deliverWindowDidExposeEvent() { 248 Rectangle r = peer.getBounds(); 249 peer.notifyExpose(0, 0, r.width, r.height); 250 } 251 252 private void deliverWindowDidExposeEvent(float x, float y, float w, float h) { 253 peer.notifyExpose((int)x, (int)y, (int)w, (int)h); 254 } 255 }