1 /* 2 * Copyright (c) 2011, 2016, 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.macos.MacOSFlags; 37 import sun.java2d.metal.MTLLayer; 38 import sun.java2d.metal.MTLSurfaceData; 39 import sun.lwawt.LWWindowPeer; 40 41 import sun.java2d.SurfaceData; 42 import sun.java2d.opengl.CGLLayer; 43 import sun.java2d.opengl.CGLSurfaceData; 44 45 public class CPlatformView extends CFRetainedResource { 46 private native long nativeCreateView(int x, int y, int width, int height, long windowLayerPtr); 47 private static native void nativeSetAutoResizable(long awtView, boolean toResize); 48 private static native int nativeGetNSViewDisplayID(long awtView); 49 private static native Rectangle2D nativeGetLocationOnScreen(long awtView); 50 private static native boolean nativeIsViewUnderMouse(long ptr); 51 52 private LWWindowPeer peer; 53 private SurfaceData surfaceData; 54 private CFRetainedResource windowLayer; 55 private CPlatformResponder responder; 56 57 public CPlatformView() { 58 super(0, true); 59 } 60 61 public void initialize(LWWindowPeer peer, CPlatformResponder responder) { 62 initializeBase(peer, responder); 63 64 if (!LWCToolkit.getSunAwtDisableCALayers()) { 65 this.windowLayer = MacOSFlags.isMetalEnabled()? createMTLLayer() : createCGLayer(); 66 } 67 setPtr(nativeCreateView(0, 0, 0, 0, getWindowLayerPtr())); 68 } 69 70 public CGLLayer createCGLayer() { 71 return new CGLLayer(peer); 72 } 73 74 public MTLLayer createMTLLayer() { 75 return new MTLLayer(peer); 76 } 77 78 79 protected void initializeBase(LWWindowPeer peer, CPlatformResponder responder) { 80 this.peer = peer; 81 this.responder = responder; 82 } 83 84 public long getAWTView() { 85 return ptr; 86 } 87 88 public boolean isOpaque() { 89 return !peer.isTranslucent(); 90 } 91 92 /* 93 * All coordinates passed to the method should be based on the origin being in the bottom-left corner (standard 94 * Cocoa coordinates). 95 */ 96 public void setBounds(int x, int y, int width, int height) { 97 execute(ptr->CWrapper.NSView.setFrame(ptr, x, y, width, height)); 98 } 99 100 // REMIND: CGLSurfaceData expects top-level's size 101 public Rectangle getBounds() { 102 return peer.getBounds(); 103 } 104 105 public Object getDestination() { 106 return peer; 107 } 108 109 public void setToolTip(String msg) { 110 execute(ptr -> CWrapper.NSView.setToolTip(ptr, msg)); 111 } 112 113 // ---------------------------------------------------------------------- 114 // PAINTING METHODS 115 // ---------------------------------------------------------------------- 116 public SurfaceData replaceSurfaceData() { 117 if (!LWCToolkit.getSunAwtDisableCALayers()) { 118 surfaceData = (MacOSFlags.isMetalEnabled()) ? 119 ((MTLLayer)windowLayer).replaceSurfaceData() : 120 ((CGLLayer)windowLayer).replaceSurfaceData() 121 ; 122 } else { 123 if (surfaceData == null) { 124 CGraphicsConfig graphicsConfig = (CGraphicsConfig)getGraphicsConfiguration(); 125 surfaceData = graphicsConfig.createSurfaceData(this); 126 } else { 127 validateSurface(); 128 } 129 } 130 return surfaceData; 131 } 132 133 private void validateSurface() { 134 if (surfaceData != null) { 135 if (MacOSFlags.isMetalEnabled()) { 136 ((MTLSurfaceData) surfaceData).validate(); 137 } else { 138 ((CGLSurfaceData) surfaceData).validate(); 139 } 140 } 141 } 142 143 public GraphicsConfiguration getGraphicsConfiguration() { 144 return peer.getGraphicsConfiguration(); 145 } 146 147 public SurfaceData getSurfaceData() { 148 return surfaceData; 149 } 150 151 @Override 152 public void dispose() { 153 if (!LWCToolkit.getSunAwtDisableCALayers()) { 154 windowLayer.dispose(); 155 } 156 super.dispose(); 157 } 158 159 public long getWindowLayerPtr() { 160 if (!LWCToolkit.getSunAwtDisableCALayers()) { 161 return MacOSFlags.isMetalEnabled() ? 162 ((MTLLayer)windowLayer).getPointer() : 163 ((CGLLayer)windowLayer).getPointer(); 164 } else { 165 return 0; 166 } 167 } 168 169 public void setAutoResizable(boolean toResize) { 170 execute(ptr -> nativeSetAutoResizable(ptr, toResize)); 171 } 172 173 public boolean isUnderMouse() { 174 AtomicBoolean ref = new AtomicBoolean(); 175 execute(ptr -> { 176 ref.set(nativeIsViewUnderMouse(ptr)); 177 }); 178 return ref.get(); 179 } 180 181 public GraphicsDevice getGraphicsDevice() { 182 GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); 183 CGraphicsEnvironment cge = (CGraphicsEnvironment)ge; 184 AtomicInteger ref = new AtomicInteger(); 185 execute(ptr -> { 186 ref.set(nativeGetNSViewDisplayID(ptr)); 187 }); 188 GraphicsDevice gd = cge.getScreenDevice(ref.get()); 189 if (gd == null) { 190 // this could possibly happen during device removal 191 // use the default screen device in this case 192 gd = ge.getDefaultScreenDevice(); 193 } 194 return gd; 195 } 196 197 public Point getLocationOnScreen() { 198 AtomicReference<Rectangle> ref = new AtomicReference<>(); 199 execute(ptr -> { 200 ref.set(nativeGetLocationOnScreen(ptr).getBounds()); 201 }); 202 Rectangle r = ref.get(); 203 if (r != null) { 204 return new Point(r.x, r.y); 205 } 206 return new Point(0, 0); 207 } 208 209 // ---------------------------------------------------------------------- 210 // NATIVE CALLBACKS 211 // ---------------------------------------------------------------------- 212 213 /* 214 * The callback is called only in the embedded case when the view is 215 * automatically resized by the superview. 216 * In normal mode this method is never called. 217 */ 218 private void deliverResize(int x, int y, int w, int h) { 219 peer.notifyReshape(x, y, w, h); 220 } 221 222 223 private void deliverMouseEvent(final NSEvent event) { 224 int x = event.getX(); 225 int y = getBounds().height - event.getY(); 226 int absX = event.getAbsX(); 227 int absY = event.getAbsY(); 228 229 if (event.getType() == CocoaConstants.NSScrollWheel) { 230 responder.handleScrollEvent(x, y, absX, absY, event.getModifierFlags(), 231 event.getScrollDeltaX(), event.getScrollDeltaY(), 232 event.getScrollPhase()); 233 } else { 234 responder.handleMouseEvent(event.getType(), event.getModifierFlags(), event.getButtonNumber(), 235 event.getClickCount(), x, y, 236 absX, absY); 237 } 238 } 239 240 private void deliverKeyEvent(NSEvent event) { 241 responder.handleKeyEvent(event.getType(), event.getModifierFlags(), event.getCharacters(), 242 event.getCharactersIgnoringModifiers(), event.getKeyCode(), true, false); 243 } 244 245 /** 246 * Called by the native delegate in layer backed view mode or in the simple 247 * NSView mode. See NSView.drawRect(). 248 */ 249 private void deliverWindowDidExposeEvent() { 250 peer.notifyExpose(peer.getSize()); 251 } 252 }