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