1 /* 2 * Copyright (c) 2011, 2019, 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.util.concurrent.atomic.AtomicBoolean; 31 import java.util.concurrent.atomic.AtomicInteger; 32 import java.util.concurrent.atomic.AtomicReference; 33 34 import sun.awt.CGraphicsConfig; 35 import sun.awt.CGraphicsEnvironment; 36 import sun.java2d.metal.MetalLayer; 37 import sun.java2d.metal.MetalSurfaceData; 38 import sun.lwawt.LWWindowPeer; 39 40 import sun.java2d.SurfaceData; 41 import sun.java2d.opengl.CGLLayer; 42 import sun.java2d.opengl.CGLSurfaceData; 43 import sun.java2d.NullSurfaceData; 44 45 46 public class CPlatformView extends CFRetainedResource { 47 private native long nativeCreateView(int x, int y, int width, int height, long windowLayerPtr); 48 private static native void nativeSetAutoResizable(long awtView, boolean toResize); 49 private static native int nativeGetNSViewDisplayID(long awtView); 50 private static native Rectangle2D nativeGetLocationOnScreen(long awtView); 51 private static native boolean nativeIsViewUnderMouse(long ptr); 52 53 private LWWindowPeer peer; 54 private SurfaceData surfaceData; 55 private CGLLayer windowLayer; 56 private MetalLayer windowMetalLayer; //hack : will be null if opengl is used 57 //private CFRetainedResource windowLayer; 58 //Todo: Have to verify how we can replace CGL layer with more common CFRetaindedResource 59 private CPlatformResponder responder; 60 61 public CPlatformView() { 62 super(0, true); 63 } 64 65 66 public void initialize(LWWindowPeer peer, CPlatformResponder responder) { 67 initializeBase(peer, responder); 68 69 if (!LWCToolkit.getSunAwtDisableCALayers()) { 70 71 if (isMetalSystemProperty()) { 72 this.windowMetalLayer = createMetalLayer(); 73 } else { 74 this.windowLayer = createCGLayer(); 75 } 76 } 77 setPtr(nativeCreateView(0, 0, 0, 0, getWindowLayerPtr())); 78 79 // TODO : We should not simply validate view directly here. 80 //if (isMetalSystemProperty()) { 81 //windowMetalLayer.validate(getAWTView()); 82 //} 83 } 84 85 private boolean isMetalSystemProperty() { 86 String str = System.getProperty("sun.java2d.metal"); 87 88 if (str != null) { 89 System.out.println("Property : sun.java2d.metal=" + str); 90 if (str.equals("true")) { 91 return true; 92 } 93 } 94 return false; 95 } 96 97 public CGLLayer createCGLayer() { 98 return new CGLLayer(peer); 99 } 100 101 public MetalLayer createMetalLayer() { 102 return new MetalLayer(peer); 103 } 104 protected void initializeBase(LWWindowPeer peer, CPlatformResponder responder) { 105 this.peer = peer; 106 this.responder = responder; 107 } 108 109 public long getAWTView() { 110 return ptr; 111 } 112 113 public boolean isOpaque() { 114 return !peer.isTranslucent(); 115 } 116 117 /* 118 * All coordinates passed to the method should be based on the origin being in the bottom-left corner (standard 119 * Cocoa coordinates). 120 */ 121 public void setBounds(int x, int y, int width, int height) { 122 execute(ptr->CWrapper.NSView.setFrame(ptr, x, y, width, height)); 123 124 // TODO : Check the use case that why below code is added. 125 //if (windowMetalLayer != null) { 126 //windowMetalLayer.validate(getAWTView()); 127 //} 128 } 129 130 // REMIND: CGLSurfaceData expects top-level's size 131 public Rectangle getBounds() { 132 return peer.getBounds(); 133 } 134 135 public Object getDestination() { 136 return peer; 137 } 138 139 public void setToolTip(String msg) { 140 execute(ptr -> CWrapper.NSView.setToolTip(ptr, msg)); 141 } 142 143 // ---------------------------------------------------------------------- 144 // PAINTING METHODS 145 // ---------------------------------------------------------------------- 146 public SurfaceData replaceSurfaceData() { 147 if (!LWCToolkit.getSunAwtDisableCALayers()) { 148 149 if (isMetalSystemProperty()) { 150 surfaceData = windowMetalLayer.replaceSurfaceData(); 151 152 // TODO : Why we are checking about NullSurfaceData here 153 //if (surfaceData != NullSurfaceData.theInstance) { 154 //validateSurface(); 155 //windowMetalLayer.drawInMetalContext(getAWTView()); 156 //} 157 158 } else { 159 surfaceData = windowLayer.replaceSurfaceData(); 160 } 161 162 } else { 163 if (surfaceData == null) { 164 CGraphicsConfig graphicsConfig = (CGraphicsConfig)getGraphicsConfiguration(); 165 surfaceData = graphicsConfig.createSurfaceData(this); 166 } else { 167 validateSurface(); 168 } 169 } 170 return surfaceData; 171 } 172 173 private void validateSurface() { 174 175 if (surfaceData != null) { 176 // TODO : Why we are validating with View here 177 if (isMetalSystemProperty()) { 178 //((MetalSurfaceData)surfaceData).validate(); 179 //windowMetalLayer.validate(getAWTView()); 180 ((MetalSurfaceData)surfaceData).validate(); 181 } else { 182 ((CGLSurfaceData)surfaceData).validate(); 183 } 184 } 185 } 186 187 public GraphicsConfiguration getGraphicsConfiguration() { 188 return peer.getGraphicsConfiguration(); 189 } 190 191 public SurfaceData getSurfaceData() { 192 return surfaceData; 193 } 194 195 @Override 196 public void dispose() { 197 if (!LWCToolkit.getSunAwtDisableCALayers()) { 198 if (isMetalSystemProperty()) { 199 windowMetalLayer.dispose(); 200 } else { 201 windowLayer.dispose(); 202 } 203 } 204 super.dispose(); 205 } 206 207 public long getWindowLayerPtr() { 208 if (!LWCToolkit.getSunAwtDisableCALayers()) { 209 if (isMetalSystemProperty()) { 210 return windowMetalLayer.getPointer(); 211 } else { 212 return windowLayer.getPointer(); 213 } 214 } else { 215 return 0; 216 } 217 } 218 219 public void setAutoResizable(boolean toResize) { 220 execute(ptr -> nativeSetAutoResizable(ptr, toResize)); 221 } 222 223 public boolean isUnderMouse() { 224 AtomicBoolean ref = new AtomicBoolean(); 225 execute(ptr -> { 226 ref.set(nativeIsViewUnderMouse(ptr)); 227 }); 228 return ref.get(); 229 } 230 231 public GraphicsDevice getGraphicsDevice() { 232 GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); 233 CGraphicsEnvironment cge = (CGraphicsEnvironment)ge; 234 AtomicInteger ref = new AtomicInteger(); 235 execute(ptr -> { 236 ref.set(nativeGetNSViewDisplayID(ptr)); 237 }); 238 GraphicsDevice gd = cge.getScreenDevice(ref.get()); 239 if (gd == null) { 240 // this could possibly happen during device removal 241 // use the default screen device in this case 242 gd = ge.getDefaultScreenDevice(); 243 } 244 return gd; 245 } 246 247 public Point getLocationOnScreen() { 248 AtomicReference<Rectangle> ref = new AtomicReference<>(); 249 execute(ptr -> { 250 ref.set(nativeGetLocationOnScreen(ptr).getBounds()); 251 }); 252 Rectangle r = ref.get(); 253 if (r != null) { 254 return new Point(r.x, r.y); 255 } 256 return new Point(0, 0); 257 } 258 259 // ---------------------------------------------------------------------- 260 // NATIVE CALLBACKS 261 // ---------------------------------------------------------------------- 262 263 /* 264 * The callback is called only in the embedded case when the view is 265 * automatically resized by the superview. 266 * In normal mode this method is never called. 267 */ 268 private void deliverResize(int x, int y, int w, int h) { 269 peer.notifyReshape(x, y, w, h); 270 } 271 272 273 private void deliverMouseEvent(final NSEvent event) { 274 int x = event.getX(); 275 int y = getBounds().height - event.getY(); 276 int absX = event.getAbsX(); 277 int absY = event.getAbsY(); 278 279 if (event.getType() == CocoaConstants.NSScrollWheel) { 280 responder.handleScrollEvent(x, y, absX, absY, event.getModifierFlags(), 281 event.getScrollDeltaX(), event.getScrollDeltaY(), 282 event.getScrollPhase()); 283 } else { 284 responder.handleMouseEvent(event.getType(), event.getModifierFlags(), event.getButtonNumber(), 285 event.getClickCount(), x, y, 286 absX, absY); 287 } 288 } 289 290 private void deliverKeyEvent(NSEvent event) { 291 responder.handleKeyEvent(event.getType(), event.getModifierFlags(), event.getCharacters(), 292 event.getCharactersIgnoringModifiers(), event.getKeyCode(), true, false); 293 } 294 295 /** 296 * Called by the native delegate in layer backed view mode or in the simple 297 * NSView mode. See NSView.drawRect(). 298 */ 299 private void deliverWindowDidExposeEvent() { 300 peer.notifyExpose(peer.getSize()); 301 } 302 }