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