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