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 com.apple.eawt.FullScreenAdapter; 29 import com.apple.eawt.FullScreenUtilities; 30 import com.apple.eawt.event.FullScreenEvent; 31 import java.awt.*; 32 import java.awt.Dialog.ModalityType; 33 import java.awt.event.*; 34 import java.beans.*; 35 import java.lang.reflect.InvocationTargetException; 36 import java.util.ArrayList; 37 import java.util.Arrays; 38 import java.util.concurrent.atomic.AtomicBoolean; 39 import java.util.concurrent.atomic.AtomicLong; 40 import java.util.concurrent.atomic.AtomicReference; 41 42 import javax.swing.*; 43 44 import sun.awt.*; 45 import sun.awt.AWTAccessor.ComponentAccessor; 46 import sun.awt.AWTAccessor.WindowAccessor; 47 import sun.java2d.SurfaceData; 48 import sun.java2d.opengl.CGLSurfaceData; 49 import sun.lwawt.*; 50 import sun.util.logging.PlatformLogger; 51 52 import com.apple.laf.*; 53 import com.apple.laf.ClientPropertyApplicator.Property; 54 import com.sun.awt.AWTUtilities; 55 import sun.lwawt.LWWindowPeer.PeerType; 56 57 public class CPlatformWindow extends CFRetainedResource implements PlatformWindow { 58 private native long nativeCreateNSWindow(long nsViewPtr,long ownerPtr, long styleBits, double x, double y, double w, double h); 59 private static native void nativeSetNSWindowStyleBits(long nsWindowPtr, int mask, int data); 60 private static native void nativeSetNSWindowMenuBar(long nsWindowPtr, long menuBarPtr); 61 private static native Insets nativeGetNSWindowInsets(long nsWindowPtr); 62 private static native void nativeSetNSWindowBounds(long nsWindowPtr, double x, double y, double w, double h); 63 private static native void nativeSetNSWindowLocationByPlatform(long nsWindowPtr); 64 private static native void nativeSetNSWindowStandardFrame(long nsWindowPtr, 65 double x, double y, double w, double h); 66 private static native void nativeSetNSWindowMinMax(long nsWindowPtr, double minW, double minH, double maxW, double maxH); 67 private static native void nativePushNSWindowToBack(long nsWindowPtr); 68 private static native void nativePushNSWindowToFront(long nsWindowPtr); 69 private static native void nativeSetNSWindowTitle(long nsWindowPtr, String title); 70 private static native void nativeRevalidateNSWindowShadow(long nsWindowPtr); 71 private static native void nativeSetNSWindowMinimizedIcon(long nsWindowPtr, long nsImage); 72 private static native void nativeSetNSWindowRepresentedFilename(long nsWindowPtr, String representedFilename); 207 c.execute(ptr -> nativeRevalidateNSWindowShadow(ptr)); 208 }}, 209 new Property<CPlatformWindow>(WINDOW_DOCUMENT_FILE) { public void applyProperty(final CPlatformWindow c, final Object value) { 210 if (value == null || !(value instanceof java.io.File)) { 211 c.execute(ptr->nativeSetNSWindowRepresentedFilename(ptr, null)); 212 return; 213 } 214 215 final String filename = ((java.io.File)value).getAbsolutePath(); 216 c.execute(ptr->nativeSetNSWindowRepresentedFilename(ptr, filename)); 217 }} 218 }) { 219 @SuppressWarnings("deprecation") 220 public CPlatformWindow convertJComponentToTarget(final JRootPane p) { 221 Component root = SwingUtilities.getRoot(p); 222 final ComponentAccessor acc = AWTAccessor.getComponentAccessor(); 223 if (root == null || acc.getPeer(root) == null) return null; 224 return (CPlatformWindow)((LWWindowPeer)acc.getPeer(root)).getPlatformWindow(); 225 } 226 }; 227 228 // Bounds of the native widget but in the Java coordinate system. 229 // In order to keep it up-to-date we will update them on 230 // 1) setting native bounds via nativeSetBounds() call 231 // 2) getting notification from the native level via deliverMoveResizeEvent() 232 private Rectangle nativeBounds = new Rectangle(0, 0, 0, 0); 233 private volatile boolean isFullScreenMode; 234 private boolean isFullScreenAnimationOn; 235 236 private volatile boolean isInFullScreen; 237 private volatile boolean isIconifyAnimationActive; 238 private volatile boolean isZoomed; 239 240 private Window target; 241 private LWWindowPeer peer; 242 protected CPlatformView contentView; 243 protected CPlatformWindow owner; 244 protected boolean visible = false; // visibility status from native perspective 245 private boolean undecorated; // initialized in getInitialStyleBits() 246 private Rectangle normalBounds = null; // not-null only for undecorated maximized windows 247 private CPlatformResponder responder; 248 249 public CPlatformWindow() { 250 super(0, true); 251 } 252 253 /* 254 * Delegate initialization (create native window and all the 255 * related resources). 256 */ 257 @Override // PlatformWindow 258 public void initialize(Window _target, LWWindowPeer _peer, PlatformWindow _owner) { 259 initializeBase(_target, _peer, _owner, new CPlatformView()); 260 261 final int styleBits = getInitialStyleBits(); 262 263 responder = createPlatformResponder(); 264 contentView = createContentView(); 265 contentView.initialize(peer, responder); 266 267 Rectangle bounds; 1155 private void orderAboveSiblings() { 1156 // Recursively pop up the windows from the very bottom, (i.e. root owner) so that 1157 // the windows are ordered above their nearest owner; ancestors of the window, 1158 // which is going to become 'main window', are placed above their siblings. 1159 CPlatformWindow rootOwner = getRootOwner(); 1160 if (rootOwner.isVisible() && !rootOwner.isIconified()) { 1161 rootOwner.execute(CWrapper.NSWindow::orderFront); 1162 } 1163 // Do not order child windows of iconified owner. 1164 if (!rootOwner.isIconified()) { 1165 final WindowAccessor windowAccessor = AWTAccessor.getWindowAccessor(); 1166 orderAboveSiblingsImpl(windowAccessor.getOwnedWindows(rootOwner.target)); 1167 } 1168 } 1169 1170 private void orderAboveSiblingsImpl(Window[] windows) { 1171 ArrayList<Window> childWindows = new ArrayList<Window>(); 1172 1173 final ComponentAccessor componentAccessor = AWTAccessor.getComponentAccessor(); 1174 final WindowAccessor windowAccessor = AWTAccessor.getWindowAccessor(); 1175 1176 // Go through the list of windows and perform ordering. 1177 for (Window w : windows) { 1178 boolean iconified = false; 1179 final Object p = componentAccessor.getPeer(w); 1180 if (p instanceof LWWindowPeer) { 1181 CPlatformWindow pw = (CPlatformWindow)((LWWindowPeer)p).getPlatformWindow(); 1182 iconified = isIconified(); 1183 if (pw != null && pw.isVisible() && !iconified) { 1184 // If the window is one of ancestors of 'main window' or is going to become main by itself, 1185 // the window should be ordered above its siblings; otherwise the window is just ordered 1186 // above its nearest parent. 1187 if (pw.isOneOfOwnersOrSelf(this)) { 1188 pw.execute(CWrapper.NSWindow::orderFront); 1189 } else { 1190 pw.owner.execute(ownerPtr -> { 1191 pw.execute(ptr -> { 1192 CWrapper.NSWindow.orderWindow(ptr, CWrapper.NSWindow.NSWindowAbove, ownerPtr); 1193 }); 1194 }); 1195 } 1196 pw.applyWindowLevel(w); 1197 } 1198 } 1199 // Retrieve the child windows for each window from the list except iconified ones 1200 // and store them for future use. 1201 // Note: we collect data about child windows even for invisible owners, since they may have 1202 // visible children. 1203 if (!iconified) { 1204 childWindows.addAll(Arrays.asList(windowAccessor.getOwnedWindows(w))); 1205 } 1206 } 1207 // If some windows, which have just been ordered, have any child windows, let's start new iteration 1208 // and order these child windows. 1209 if (!childWindows.isEmpty()) { 1210 orderAboveSiblingsImpl(childWindows.toArray(new Window[0])); 1211 } 1212 } 1213 1214 protected void applyWindowLevel(Window target) { 1215 if (target.isAlwaysOnTop() && target.getType() != Window.Type.POPUP) { 1216 execute(ptr->CWrapper.NSWindow.setLevel(ptr, CWrapper.NSWindow.NSFloatingWindowLevel)); 1217 } else if (target.getType() == Window.Type.POPUP) { 1218 execute(ptr->CWrapper.NSWindow.setLevel(ptr, CWrapper.NSWindow.NSPopUpMenuWindowLevel)); 1219 } 1220 } 1221 1222 // ---------------------------------------------------------------------- 1223 // NATIVE CALLBACKS 1224 // ---------------------------------------------------------------------- 1225 1226 private void windowWillMiniaturize() { 1227 isIconifyAnimationActive = true; 1228 } 1229 1230 private void windowDidBecomeMain() { 1231 if (checkBlockingAndOrder()) return; 1232 // If it's not blocked, make sure it's above its siblings 1233 orderAboveSiblings(); 1234 } 1235 1236 private void windowWillEnterFullScreen() { 1237 isFullScreenAnimationOn = true; 1238 } 1239 1240 private void windowDidEnterFullScreen() { 1241 isInFullScreen = true; 1242 isFullScreenAnimationOn = false; 1243 } 1244 1245 private void windowWillExitFullScreen() { 1246 isFullScreenAnimationOn = true; 1247 } 1248 1249 private void windowDidExitFullScreen() { 1250 isInFullScreen = false; | 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.Color; 29 import java.awt.Component; 30 import java.awt.DefaultKeyboardFocusManager; 31 import java.awt.Dialog; 32 import java.awt.Dialog.ModalityType; 33 import java.awt.Font; 34 import java.awt.FontMetrics; 35 import java.awt.Frame; 36 import java.awt.GraphicsDevice; 37 import java.awt.Insets; 38 import java.awt.MenuBar; 39 import java.awt.Point; 40 import java.awt.Rectangle; 41 import java.awt.Toolkit; 42 import java.awt.Window; 43 import java.awt.event.FocusEvent; 44 import java.awt.event.WindowEvent; 45 import java.beans.PropertyChangeEvent; 46 import java.beans.PropertyChangeListener; 47 import java.lang.reflect.InvocationTargetException; 48 import java.util.ArrayList; 49 import java.util.Arrays; 50 import java.util.Comparator; 51 import java.util.concurrent.atomic.AtomicBoolean; 52 import java.util.concurrent.atomic.AtomicLong; 53 import java.util.concurrent.atomic.AtomicReference; 54 55 import javax.swing.JRootPane; 56 import javax.swing.RootPaneContainer; 57 import javax.swing.SwingUtilities; 58 59 import com.apple.laf.ClientPropertyApplicator; 60 import sun.awt.AWTAccessor; 61 import sun.awt.AWTAccessor.ComponentAccessor; 62 import sun.awt.AWTAccessor.WindowAccessor; 63 import sun.java2d.SurfaceData; 64 import sun.java2d.opengl.CGLSurfaceData; 65 import sun.lwawt.LWToolkit; 66 import sun.lwawt.LWWindowPeer; 67 import sun.lwawt.PlatformWindow; 68 import sun.util.logging.PlatformLogger; 69 70 import com.apple.laf.ClientPropertyApplicator.Property; 71 import com.sun.awt.AWTUtilities; 72 import sun.lwawt.LWWindowPeer.PeerType; 73 74 public class CPlatformWindow extends CFRetainedResource implements PlatformWindow { 75 private native long nativeCreateNSWindow(long nsViewPtr,long ownerPtr, long styleBits, double x, double y, double w, double h); 76 private static native void nativeSetNSWindowStyleBits(long nsWindowPtr, int mask, int data); 77 private static native void nativeSetNSWindowMenuBar(long nsWindowPtr, long menuBarPtr); 78 private static native Insets nativeGetNSWindowInsets(long nsWindowPtr); 79 private static native void nativeSetNSWindowBounds(long nsWindowPtr, double x, double y, double w, double h); 80 private static native void nativeSetNSWindowLocationByPlatform(long nsWindowPtr); 81 private static native void nativeSetNSWindowStandardFrame(long nsWindowPtr, 82 double x, double y, double w, double h); 83 private static native void nativeSetNSWindowMinMax(long nsWindowPtr, double minW, double minH, double maxW, double maxH); 84 private static native void nativePushNSWindowToBack(long nsWindowPtr); 85 private static native void nativePushNSWindowToFront(long nsWindowPtr); 86 private static native void nativeSetNSWindowTitle(long nsWindowPtr, String title); 87 private static native void nativeRevalidateNSWindowShadow(long nsWindowPtr); 88 private static native void nativeSetNSWindowMinimizedIcon(long nsWindowPtr, long nsImage); 89 private static native void nativeSetNSWindowRepresentedFilename(long nsWindowPtr, String representedFilename); 224 c.execute(ptr -> nativeRevalidateNSWindowShadow(ptr)); 225 }}, 226 new Property<CPlatformWindow>(WINDOW_DOCUMENT_FILE) { public void applyProperty(final CPlatformWindow c, final Object value) { 227 if (value == null || !(value instanceof java.io.File)) { 228 c.execute(ptr->nativeSetNSWindowRepresentedFilename(ptr, null)); 229 return; 230 } 231 232 final String filename = ((java.io.File)value).getAbsolutePath(); 233 c.execute(ptr->nativeSetNSWindowRepresentedFilename(ptr, filename)); 234 }} 235 }) { 236 @SuppressWarnings("deprecation") 237 public CPlatformWindow convertJComponentToTarget(final JRootPane p) { 238 Component root = SwingUtilities.getRoot(p); 239 final ComponentAccessor acc = AWTAccessor.getComponentAccessor(); 240 if (root == null || acc.getPeer(root) == null) return null; 241 return (CPlatformWindow)((LWWindowPeer)acc.getPeer(root)).getPlatformWindow(); 242 } 243 }; 244 private final Comparator<Window> siblingsComparator = (w1, w2) -> { 245 if (w1 == w2) { 246 return 0; 247 } 248 ComponentAccessor componentAccessor = AWTAccessor.getComponentAccessor(); 249 Object p1 = componentAccessor.getPeer(w1); 250 Object p2 = componentAccessor.getPeer(w2); 251 if (p1 instanceof LWWindowPeer && p2 instanceof LWWindowPeer) { 252 return Long.compare( 253 ((CPlatformWindow) (((LWWindowPeer) p1).getPlatformWindow())).lastBecomeMainTime, 254 ((CPlatformWindow) (((LWWindowPeer) p2).getPlatformWindow())).lastBecomeMainTime); 255 } 256 return 0; 257 }; 258 259 // Bounds of the native widget but in the Java coordinate system. 260 // In order to keep it up-to-date we will update them on 261 // 1) setting native bounds via nativeSetBounds() call 262 // 2) getting notification from the native level via deliverMoveResizeEvent() 263 private Rectangle nativeBounds = new Rectangle(0, 0, 0, 0); 264 private volatile boolean isFullScreenMode; 265 private boolean isFullScreenAnimationOn; 266 267 private volatile boolean isInFullScreen; 268 private volatile boolean isIconifyAnimationActive; 269 private volatile boolean isZoomed; 270 271 private Window target; 272 private LWWindowPeer peer; 273 protected CPlatformView contentView; 274 protected CPlatformWindow owner; 275 protected boolean visible = false; // visibility status from native perspective 276 private boolean undecorated; // initialized in getInitialStyleBits() 277 private Rectangle normalBounds = null; // not-null only for undecorated maximized windows 278 private CPlatformResponder responder; 279 private long lastBecomeMainTime; // this is necessary to preserve right siblings order 280 281 public CPlatformWindow() { 282 super(0, true); 283 } 284 285 /* 286 * Delegate initialization (create native window and all the 287 * related resources). 288 */ 289 @Override // PlatformWindow 290 public void initialize(Window _target, LWWindowPeer _peer, PlatformWindow _owner) { 291 initializeBase(_target, _peer, _owner, new CPlatformView()); 292 293 final int styleBits = getInitialStyleBits(); 294 295 responder = createPlatformResponder(); 296 contentView = createContentView(); 297 contentView.initialize(peer, responder); 298 299 Rectangle bounds; 1187 private void orderAboveSiblings() { 1188 // Recursively pop up the windows from the very bottom, (i.e. root owner) so that 1189 // the windows are ordered above their nearest owner; ancestors of the window, 1190 // which is going to become 'main window', are placed above their siblings. 1191 CPlatformWindow rootOwner = getRootOwner(); 1192 if (rootOwner.isVisible() && !rootOwner.isIconified()) { 1193 rootOwner.execute(CWrapper.NSWindow::orderFront); 1194 } 1195 // Do not order child windows of iconified owner. 1196 if (!rootOwner.isIconified()) { 1197 final WindowAccessor windowAccessor = AWTAccessor.getWindowAccessor(); 1198 orderAboveSiblingsImpl(windowAccessor.getOwnedWindows(rootOwner.target)); 1199 } 1200 } 1201 1202 private void orderAboveSiblingsImpl(Window[] windows) { 1203 ArrayList<Window> childWindows = new ArrayList<Window>(); 1204 1205 final ComponentAccessor componentAccessor = AWTAccessor.getComponentAccessor(); 1206 final WindowAccessor windowAccessor = AWTAccessor.getWindowAccessor(); 1207 Arrays.sort(windows, siblingsComparator); 1208 // Go through the list of windows and perform ordering. 1209 CPlatformWindow pwUnder = null; 1210 for (Window w : windows) { 1211 boolean iconified = false; 1212 final Object p = componentAccessor.getPeer(w); 1213 if (p instanceof LWWindowPeer) { 1214 CPlatformWindow pw = (CPlatformWindow)((LWWindowPeer)p).getPlatformWindow(); 1215 iconified = isIconified(); 1216 if (pw != null && pw.isVisible() && !iconified) { 1217 // If the window is one of ancestors of 'main window' or is going to become main by itself, 1218 // the window should be ordered above its siblings; otherwise the window is just ordered 1219 // above its nearest parent. 1220 if (pw.isOneOfOwnersOrSelf(this)) { 1221 pw.execute(CWrapper.NSWindow::orderFront); 1222 } else { 1223 if (pwUnder == null) { 1224 pwUnder = pw.owner; 1225 } 1226 pwUnder.execute(underPtr -> { 1227 pw.execute(ptr -> { 1228 CWrapper.NSWindow.orderWindow(ptr, CWrapper.NSWindow.NSWindowAbove, underPtr); 1229 }); 1230 }); 1231 pwUnder = pw; 1232 } 1233 pw.applyWindowLevel(w); 1234 } 1235 } 1236 // Retrieve the child windows for each window from the list except iconified ones 1237 // and store them for future use. 1238 // Note: we collect data about child windows even for invisible owners, since they may have 1239 // visible children. 1240 if (!iconified) { 1241 childWindows.addAll(Arrays.asList(windowAccessor.getOwnedWindows(w))); 1242 } 1243 } 1244 // If some windows, which have just been ordered, have any child windows, let's start new iteration 1245 // and order these child windows. 1246 if (!childWindows.isEmpty()) { 1247 orderAboveSiblingsImpl(childWindows.toArray(new Window[0])); 1248 } 1249 } 1250 1251 protected void applyWindowLevel(Window target) { 1252 if (target.isAlwaysOnTop() && target.getType() != Window.Type.POPUP) { 1253 execute(ptr->CWrapper.NSWindow.setLevel(ptr, CWrapper.NSWindow.NSFloatingWindowLevel)); 1254 } else if (target.getType() == Window.Type.POPUP) { 1255 execute(ptr->CWrapper.NSWindow.setLevel(ptr, CWrapper.NSWindow.NSPopUpMenuWindowLevel)); 1256 } 1257 } 1258 1259 // ---------------------------------------------------------------------- 1260 // NATIVE CALLBACKS 1261 // ---------------------------------------------------------------------- 1262 1263 private void windowWillMiniaturize() { 1264 isIconifyAnimationActive = true; 1265 } 1266 1267 private void windowDidBecomeMain() { 1268 lastBecomeMainTime = System.currentTimeMillis(); 1269 if (checkBlockingAndOrder()) return; 1270 // If it's not blocked, make sure it's above its siblings 1271 orderAboveSiblings(); 1272 } 1273 1274 private void windowWillEnterFullScreen() { 1275 isFullScreenAnimationOn = true; 1276 } 1277 1278 private void windowDidEnterFullScreen() { 1279 isInFullScreen = true; 1280 isFullScreenAnimationOn = false; 1281 } 1282 1283 private void windowWillExitFullScreen() { 1284 isFullScreenAnimationOn = true; 1285 } 1286 1287 private void windowDidExitFullScreen() { 1288 isInFullScreen = false; |