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 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 
  39 import javax.swing.*;
  40 
  41 import sun.awt.*;
  42 import sun.awt.AWTAccessor.ComponentAccessor;
  43 import sun.java2d.SurfaceData;
  44 import sun.java2d.opengl.CGLSurfaceData;
  45 import sun.lwawt.*;
  46 import sun.util.logging.PlatformLogger;
  47 
  48 import com.apple.laf.*;
  49 import com.apple.laf.ClientPropertyApplicator.Property;
  50 import com.sun.awt.AWTUtilities;
  51 import sun.lwawt.LWWindowPeer.PeerType;
  52 
  53 public class CPlatformWindow extends CFRetainedResource implements PlatformWindow {
  54     private native long nativeCreateNSWindow(long nsViewPtr,long ownerPtr, long styleBits, double x, double y, double w, double h);
  55     private static native void nativeSetNSWindowStyleBits(long nsWindowPtr, int mask, int data);
  56     private static native void nativeSetNSWindowMenuBar(long nsWindowPtr, long menuBarPtr);
  57     private static native Insets nativeGetNSWindowInsets(long nsWindowPtr);
  58     private static native void nativeSetNSWindowBounds(long nsWindowPtr, double x, double y, double w, double h);
  59     private static native void nativeSetNSWindowLocationByPlatform(long nsWindowPtr);
  60     private static native void nativeSetNSWindowStandardFrame(long nsWindowPtr,
  61             double x, double y, double w, double h);
  62     private static native void nativeSetNSWindowMinMax(long nsWindowPtr, double minW, double minH, double maxW, double maxH);
  63     private static native void nativePushNSWindowToBack(long nsWindowPtr);
  64     private static native void nativePushNSWindowToFront(long nsWindowPtr);
  65     private static native void nativeSetNSWindowTitle(long nsWindowPtr, String title);
  66     private static native void nativeRevalidateNSWindowShadow(long nsWindowPtr);
  67     private static native void nativeSetNSWindowMinimizedIcon(long nsWindowPtr, long nsImage);
  68     private static native void nativeSetNSWindowRepresentedFilename(long nsWindowPtr, String representedFilename);
  69     private static native void nativeSetEnabled(long nsWindowPtr, boolean isEnabled);
  70     private static native void nativeSynthesizeMouseEnteredExitedEvents();
  71     private static native void nativeSynthesizeMouseEnteredExitedEvents(long nsWindowPtr, int eventType);
  72     private static native void nativeDispose(long nsWindowPtr);
  73     private static native void nativeEnterFullScreenMode(long nsWindowPtr);
  74     private static native void nativeExitFullScreenMode(long nsWindowPtr);
  75     static native CPlatformWindow nativeGetTopmostPlatformWindowUnderMouse();
  76 
  77     // Loger to report issues happened during execution but that do not affect functionality
  78     private static final PlatformLogger logger = PlatformLogger.getLogger("sun.lwawt.macosx.CPlatformWindow");
  79     private static final PlatformLogger focusLogger = PlatformLogger.getLogger("sun.lwawt.macosx.focus.CPlatformWindow");
  80 
  81     // for client properties
  82     public static final String WINDOW_BRUSH_METAL_LOOK = "apple.awt.brushMetalLook";
  83     public static final String WINDOW_DRAGGABLE_BACKGROUND = "apple.awt.draggableWindowBackground";
  84 
  85     public static final String WINDOW_ALPHA = "Window.alpha";
  86     public static final String WINDOW_SHADOW = "Window.shadow";
  87 
  88     public static final String WINDOW_STYLE = "Window.style";
  89     public static final String WINDOW_SHADOW_REVALIDATE_NOW = "apple.awt.windowShadow.revalidateNow";
  90 
  91     public static final String WINDOW_DOCUMENT_MODIFIED = "Window.documentModified";
  92     public static final String WINDOW_DOCUMENT_FILE = "Window.documentFile";
  93 
  94     public static final String WINDOW_CLOSEABLE = "Window.closeable";
  95     public static final String WINDOW_MINIMIZABLE = "Window.minimizable";
  96     public static final String WINDOW_ZOOMABLE = "Window.zoomable";
  97     public static final String WINDOW_HIDES_ON_DEACTIVATE="Window.hidesOnDeactivate";
  98 
  99     public static final String WINDOW_DOC_MODAL_SHEET = "apple.awt.documentModalSheet";
 100     public static final String WINDOW_FADE_DELEGATE = "apple.awt._windowFadeDelegate";
 101     public static final String WINDOW_FADE_IN = "apple.awt._windowFadeIn";
 102     public static final String WINDOW_FADE_OUT = "apple.awt._windowFadeOut";
 103     public static final String WINDOW_FULLSCREENABLE = "apple.awt.fullscreenable";
 104 
 105 
 106     // Yeah, I know. But it's easier to deal with ints from JNI
 107     static final int MODELESS = 0;
 108     static final int DOCUMENT_MODAL = 1;
 109     static final int APPLICATION_MODAL = 2;
 110     static final int TOOLKIT_MODAL = 3;
 111 
 112     // window style bits
 113     static final int _RESERVED_FOR_DATA = 1 << 0;
 114 
 115     // corresponds to native style mask bits
 116     static final int DECORATED = 1 << 1;
 117     static final int TEXTURED = 1 << 2;
 118     static final int UNIFIED = 1 << 3;
 119     static final int UTILITY = 1 << 4;
 120     static final int HUD = 1 << 5;
 121     static final int SHEET = 1 << 6;
 122 
 123     static final int CLOSEABLE = 1 << 7;
 124     static final int MINIMIZABLE = 1 << 8;
 125 
 126     static final int RESIZABLE = 1 << 9; // both a style bit and prop bit
 127     static final int NONACTIVATING = 1 << 24;
 128     static final int IS_DIALOG = 1 << 25;
 129     static final int IS_MODAL = 1 << 26;
 130     static final int IS_POPUP = 1 << 27;
 131 
 132     static final int _STYLE_PROP_BITMASK = DECORATED | TEXTURED | UNIFIED | UTILITY | HUD | SHEET | CLOSEABLE | MINIMIZABLE | RESIZABLE;
 133 
 134     // corresponds to method-based properties
 135     static final int HAS_SHADOW = 1 << 10;
 136     static final int ZOOMABLE = 1 << 11;
 137 
 138     static final int ALWAYS_ON_TOP = 1 << 15;
 139     static final int HIDES_ON_DEACTIVATE = 1 << 17;
 140     static final int DRAGGABLE_BACKGROUND = 1 << 19;
 141     static final int DOCUMENT_MODIFIED = 1 << 21;
 142     static final int FULLSCREENABLE = 1 << 23;
 143 
 144     static final int _METHOD_PROP_BITMASK = RESIZABLE | HAS_SHADOW | ZOOMABLE | ALWAYS_ON_TOP | HIDES_ON_DEACTIVATE | DRAGGABLE_BACKGROUND | DOCUMENT_MODIFIED | FULLSCREENABLE;
 145 
 146     // corresponds to callback-based properties
 147     static final int SHOULD_BECOME_KEY = 1 << 12;
 148     static final int SHOULD_BECOME_MAIN = 1 << 13;
 149     static final int MODAL_EXCLUDED = 1 << 16;
 150 
 151     static final int _CALLBACK_PROP_BITMASK = SHOULD_BECOME_KEY | SHOULD_BECOME_MAIN | MODAL_EXCLUDED;
 152 
 153     static int SET(final int bits, final int mask, final boolean value) {
 154         if (value) return (bits | mask);
 155         return bits & ~mask;
 156     }
 157 
 158     static boolean IS(final int bits, final int mask) {
 159         return (bits & mask) != 0;
 160     }
 161 
 162     @SuppressWarnings({"unchecked", "rawtypes"})
 163     static ClientPropertyApplicator<JRootPane, CPlatformWindow> CLIENT_PROPERTY_APPLICATOR = new ClientPropertyApplicator<JRootPane, CPlatformWindow>(new Property[] {
 164         new Property<CPlatformWindow>(WINDOW_DOCUMENT_MODIFIED) { public void applyProperty(final CPlatformWindow c, final Object value) {
 165             c.setStyleBits(DOCUMENT_MODIFIED, value == null ? false : Boolean.parseBoolean(value.toString()));
 166         }},
 167         new Property<CPlatformWindow>(WINDOW_BRUSH_METAL_LOOK) { public void applyProperty(final CPlatformWindow c, final Object value) {
 168             c.setStyleBits(TEXTURED, Boolean.parseBoolean(value.toString()));
 169         }},
 170         new Property<CPlatformWindow>(WINDOW_ALPHA) { public void applyProperty(final CPlatformWindow c, final Object value) {
 171             AWTUtilities.setWindowOpacity(c.target, value == null ? 1.0f : Float.parseFloat(value.toString()));
 172         }},
 173         new Property<CPlatformWindow>(WINDOW_SHADOW) { public void applyProperty(final CPlatformWindow c, final Object value) {
 174             c.setStyleBits(HAS_SHADOW, value == null ? true : Boolean.parseBoolean(value.toString()));
 175         }},
 176         new Property<CPlatformWindow>(WINDOW_MINIMIZABLE) { public void applyProperty(final CPlatformWindow c, final Object value) {
 177             c.setStyleBits(MINIMIZABLE, Boolean.parseBoolean(value.toString()));
 178         }},
 179         new Property<CPlatformWindow>(WINDOW_CLOSEABLE) { public void applyProperty(final CPlatformWindow c, final Object value) {
 180             c.setStyleBits(CLOSEABLE, Boolean.parseBoolean(value.toString()));
 181         }},
 182         new Property<CPlatformWindow>(WINDOW_ZOOMABLE) { public void applyProperty(final CPlatformWindow c, final Object value) {
 183             boolean zoomable = Boolean.parseBoolean(value.toString());
 184             if (c.target instanceof RootPaneContainer
 185                     && c.getPeer().getPeerType() == PeerType.FRAME) {
 186                 if (c.isInFullScreen && !zoomable) {
 187                     c.toggleFullScreen();
 188                 }
 189             }
 190             c.setStyleBits(ZOOMABLE, zoomable);
 191         }},
 192         new Property<CPlatformWindow>(WINDOW_FULLSCREENABLE) { public void applyProperty(final CPlatformWindow c, final Object value) {
 193             boolean fullscrenable = Boolean.parseBoolean(value.toString());
 194             if (c.target instanceof RootPaneContainer
 195                     && c.getPeer().getPeerType() == PeerType.FRAME) {
 196                 if (c.isInFullScreen && !fullscrenable) {
 197                     c.toggleFullScreen();
 198                 }
 199             }
 200             c.setStyleBits(FULLSCREENABLE, fullscrenable);
 201         }},
 202         new Property<CPlatformWindow>(WINDOW_SHADOW_REVALIDATE_NOW) { public void applyProperty(final CPlatformWindow c, final Object value) {
 203             nativeRevalidateNSWindowShadow(c.getNSWindowPtr());
 204         }},
 205         new Property<CPlatformWindow>(WINDOW_DOCUMENT_FILE) { public void applyProperty(final CPlatformWindow c, final Object value) {
 206             if (value == null || !(value instanceof java.io.File)) {
 207                 nativeSetNSWindowRepresentedFilename(c.getNSWindowPtr(), null);
 208                 return;
 209             }
 210 
 211             final String filename = ((java.io.File)value).getAbsolutePath();
 212             nativeSetNSWindowRepresentedFilename(c.getNSWindowPtr(), filename);
 213         }}
 214     }) {
 215         @SuppressWarnings("deprecation")
 216         public CPlatformWindow convertJComponentToTarget(final JRootPane p) {
 217             Component root = SwingUtilities.getRoot(p);
 218             final ComponentAccessor acc = AWTAccessor.getComponentAccessor();
 219             if (root == null || acc.getPeer(root) == null) return null;
 220             return (CPlatformWindow)((LWWindowPeer)acc.getPeer(root)).getPlatformWindow();
 221         }
 222     };
 223 
 224     // Bounds of the native widget but in the Java coordinate system.
 225     // In order to keep it up-to-date we will update them on
 226     // 1) setting native bounds via nativeSetBounds() call
 227     // 2) getting notification from the native level via deliverMoveResizeEvent()
 228     private Rectangle nativeBounds = new Rectangle(0, 0, 0, 0);
 229     private volatile boolean isFullScreenMode;
 230     private boolean isFullScreenAnimationOn;
 231 
 232     private volatile boolean isInFullScreen;
 233 
 234     private Window target;
 235     private LWWindowPeer peer;
 236     protected CPlatformView contentView;
 237     protected CPlatformWindow owner;
 238     protected boolean visible = false; // visibility status from native perspective
 239     private boolean undecorated; // initialized in getInitialStyleBits()
 240     private Rectangle normalBounds = null; // not-null only for undecorated maximized windows
 241     private CPlatformResponder responder;
 242 
 243     public CPlatformWindow() {
 244         super(0, true);
 245     }
 246 
 247     /*
 248      * Delegate initialization (create native window and all the
 249      * related resources).
 250      */
 251     @Override // PlatformWindow
 252     public void initialize(Window _target, LWWindowPeer _peer, PlatformWindow _owner) {
 253         initializeBase(_target, _peer, _owner, new CPlatformView());
 254 
 255         final int styleBits = getInitialStyleBits();
 256 
 257         responder = createPlatformResponder();
 258         contentView = createContentView();
 259         contentView.initialize(peer, responder);
 260 
 261         final long ownerPtr = owner != null ? owner.getNSWindowPtr() : 0L;
 262         Rectangle bounds;
 263         if (!IS(DECORATED, styleBits)) {
 264             // For undecorated frames the move/resize event does not come if the frame is centered on the screen
 265             // so we need to set a stub location to force an initial move/resize. Real bounds would be set later.
 266             bounds = new Rectangle(0, 0, 1, 1);
 267         } else {
 268             bounds = _peer.constrainBounds(_target.getBounds());
 269         }
 270         final long nativeWindowPtr = nativeCreateNSWindow(contentView.getAWTView(),
 271                 ownerPtr, styleBits, bounds.x, bounds.y, bounds.width, bounds.height);
 272         setPtr(nativeWindowPtr);
 273 
 274         if (target instanceof javax.swing.RootPaneContainer) {
 275             final javax.swing.JRootPane rootpane = ((javax.swing.RootPaneContainer)target).getRootPane();
 276             if (rootpane != null) rootpane.addPropertyChangeListener("ancestor", new PropertyChangeListener() {
 277                 public void propertyChange(final PropertyChangeEvent evt) {
 278                     CLIENT_PROPERTY_APPLICATOR.attachAndApplyClientProperties(rootpane);
 279                     rootpane.removePropertyChangeListener("ancestor", this);
 280                 }
 281             });
 282         }
 283 
 284         validateSurface();
 285     }
 286 
 287     protected void initializeBase(Window target, LWWindowPeer peer, PlatformWindow owner, CPlatformView view) {
 288         this.peer = peer;
 289         this.target = target;
 290         if (owner instanceof CPlatformWindow) {
 291             this.owner = (CPlatformWindow)owner;
 292         }
 293         this.contentView = view;
 294     }
 295 
 296     protected CPlatformResponder createPlatformResponder() {
 297         return new CPlatformResponder(peer, false);
 298     }
 299 
 300     protected CPlatformView createContentView() {
 301         return new CPlatformView();
 302     }
 303 
 304     protected int getInitialStyleBits() {
 305         // defaults style bits
 306         int styleBits = DECORATED | HAS_SHADOW | CLOSEABLE | MINIMIZABLE | ZOOMABLE | RESIZABLE;
 307 
 308         if (isNativelyFocusableWindow()) {
 309             styleBits = SET(styleBits, SHOULD_BECOME_KEY, true);
 310             styleBits = SET(styleBits, SHOULD_BECOME_MAIN, true);
 311         }
 312 
 313         final boolean isFrame = (target instanceof Frame);
 314         final boolean isDialog = (target instanceof Dialog);
 315         final boolean isPopup = (target.getType() == Window.Type.POPUP);
 316         if (isDialog) {
 317             styleBits = SET(styleBits, MINIMIZABLE, false);
 318         }
 319 
 320         // Either java.awt.Frame or java.awt.Dialog can be undecorated, however java.awt.Window always is undecorated.
 321         {
 322             this.undecorated = isFrame ? ((Frame)target).isUndecorated() : (isDialog ? ((Dialog)target).isUndecorated() : true);
 323             if (this.undecorated) styleBits = SET(styleBits, DECORATED, false);
 324         }
 325 
 326         // Either java.awt.Frame or java.awt.Dialog can be resizable, however java.awt.Window is never resizable
 327         {
 328             final boolean resizable = isFrame ? ((Frame)target).isResizable() : (isDialog ? ((Dialog)target).isResizable() : false);
 329             styleBits = SET(styleBits, RESIZABLE, resizable);
 330             if (!resizable) {
 331                 styleBits = SET(styleBits, ZOOMABLE, false);
 332             } else {
 333                 setCanFullscreen(true);
 334             }
 335         }
 336 
 337         if (target.isAlwaysOnTop()) {
 338             styleBits = SET(styleBits, ALWAYS_ON_TOP, true);
 339         }
 340 
 341         if (target.getModalExclusionType() == Dialog.ModalExclusionType.APPLICATION_EXCLUDE) {
 342             styleBits = SET(styleBits, MODAL_EXCLUDED, true);
 343         }
 344 
 345         // If the target is a dialog, popup or tooltip we want it to ignore the brushed metal look.
 346         if (isPopup) {
 347             styleBits = SET(styleBits, TEXTURED, false);
 348             // Popups in applets don't activate applet's process
 349             styleBits = SET(styleBits, NONACTIVATING, true);
 350             styleBits = SET(styleBits, IS_POPUP, true);
 351         }
 352 
 353         if (Window.Type.UTILITY.equals(target.getType())) {
 354             styleBits = SET(styleBits, UTILITY, true);
 355         }
 356 
 357         if (target instanceof javax.swing.RootPaneContainer) {
 358             javax.swing.JRootPane rootpane = ((javax.swing.RootPaneContainer)target).getRootPane();
 359             Object prop = null;
 360 
 361             prop = rootpane.getClientProperty(WINDOW_BRUSH_METAL_LOOK);
 362             if (prop != null) {
 363                 styleBits = SET(styleBits, TEXTURED, Boolean.parseBoolean(prop.toString()));
 364             }
 365 
 366             if (isDialog && ((Dialog)target).getModalityType() == ModalityType.DOCUMENT_MODAL) {
 367                 prop = rootpane.getClientProperty(WINDOW_DOC_MODAL_SHEET);
 368                 if (prop != null) {
 369                     styleBits = SET(styleBits, SHEET, Boolean.parseBoolean(prop.toString()));
 370                 }
 371             }
 372 
 373             prop = rootpane.getClientProperty(WINDOW_STYLE);
 374             if (prop != null) {
 375                 if ("small".equals(prop))  {
 376                     styleBits = SET(styleBits, UTILITY, true);
 377                     if (target.isAlwaysOnTop() && rootpane.getClientProperty(WINDOW_HIDES_ON_DEACTIVATE) == null) {
 378                         styleBits = SET(styleBits, HIDES_ON_DEACTIVATE, true);
 379                     }
 380                 }
 381                 if ("textured".equals(prop)) styleBits = SET(styleBits, TEXTURED, true);
 382                 if ("unified".equals(prop)) styleBits = SET(styleBits, UNIFIED, true);
 383                 if ("hud".equals(prop)) styleBits = SET(styleBits, HUD, true);
 384             }
 385 
 386             prop = rootpane.getClientProperty(WINDOW_HIDES_ON_DEACTIVATE);
 387             if (prop != null) {
 388                 styleBits = SET(styleBits, HIDES_ON_DEACTIVATE, Boolean.parseBoolean(prop.toString()));
 389             }
 390 
 391             prop = rootpane.getClientProperty(WINDOW_CLOSEABLE);
 392             if (prop != null) {
 393                 styleBits = SET(styleBits, CLOSEABLE, Boolean.parseBoolean(prop.toString()));
 394             }
 395 
 396             prop = rootpane.getClientProperty(WINDOW_MINIMIZABLE);
 397             if (prop != null) {
 398                 styleBits = SET(styleBits, MINIMIZABLE, Boolean.parseBoolean(prop.toString()));
 399             }
 400 
 401             prop = rootpane.getClientProperty(WINDOW_ZOOMABLE);
 402             if (prop != null) {
 403                 styleBits = SET(styleBits, ZOOMABLE, Boolean.parseBoolean(prop.toString()));
 404             }
 405 
 406             prop = rootpane.getClientProperty(WINDOW_FULLSCREENABLE);
 407             if (prop != null) {
 408                 styleBits = SET(styleBits, FULLSCREENABLE, Boolean.parseBoolean(prop.toString()));
 409             }
 410 
 411             prop = rootpane.getClientProperty(WINDOW_SHADOW);
 412             if (prop != null) {
 413                 styleBits = SET(styleBits, HAS_SHADOW, Boolean.parseBoolean(prop.toString()));
 414             }
 415 
 416             prop = rootpane.getClientProperty(WINDOW_DRAGGABLE_BACKGROUND);
 417             if (prop != null) {
 418                 styleBits = SET(styleBits, DRAGGABLE_BACKGROUND, Boolean.parseBoolean(prop.toString()));
 419             }
 420         }
 421 
 422         if (isDialog) {
 423             styleBits = SET(styleBits, IS_DIALOG, true);
 424             if (((Dialog) target).isModal()) {
 425                 styleBits = SET(styleBits, IS_MODAL, true);
 426             }
 427         }
 428 
 429         peer.setTextured(IS(TEXTURED, styleBits));
 430 
 431         return styleBits;
 432     }
 433 
 434     // this is the counter-point to -[CWindow _nativeSetStyleBit:]
 435     private void setStyleBits(final int mask, final boolean value) {
 436         nativeSetNSWindowStyleBits(getNSWindowPtr(), mask, value ? mask : 0);
 437     }
 438 
 439     private native void _toggleFullScreenMode(final long model);
 440 
 441     public void toggleFullScreen() {
 442         _toggleFullScreenMode(getNSWindowPtr());
 443     }
 444 
 445     @Override // PlatformWindow
 446     public void setMenuBar(MenuBar mb) {
 447         final long nsWindowPtr = getNSWindowPtr();
 448         CMenuBar mbPeer = (CMenuBar)LWToolkit.targetToPeer(mb);
 449         if (mbPeer != null) {
 450             nativeSetNSWindowMenuBar(nsWindowPtr, mbPeer.getModel());
 451         } else {
 452             nativeSetNSWindowMenuBar(nsWindowPtr, 0);
 453         }
 454     }
 455 
 456     @Override // PlatformWindow
 457     public void dispose() {
 458         contentView.dispose();
 459         nativeDispose(getNSWindowPtr());
 460         CPlatformWindow.super.dispose();
 461     }
 462 
 463     @Override // PlatformWindow
 464     public FontMetrics getFontMetrics(Font f) {
 465         // TODO: not implemented
 466         (new RuntimeException("unimplemented")).printStackTrace();
 467         return null;
 468     }
 469 
 470     @Override // PlatformWindow
 471     public Insets getInsets() {
 472         return nativeGetNSWindowInsets(getNSWindowPtr());
 473     }
 474 
 475     @Override // PlatformWindow
 476     public Point getLocationOnScreen() {
 477         return new Point(nativeBounds.x, nativeBounds.y);
 478     }
 479 
 480     @Override
 481     public GraphicsDevice getGraphicsDevice() {
 482         return contentView.getGraphicsDevice();
 483     }
 484 
 485     @Override // PlatformWindow
 486     public SurfaceData getScreenSurface() {
 487         // TODO: not implemented
 488         return null;
 489     }
 490 
 491     @Override // PlatformWindow
 492     public SurfaceData replaceSurfaceData() {
 493         return contentView.replaceSurfaceData();
 494     }
 495 
 496     @Override // PlatformWindow
 497     public void setBounds(int x, int y, int w, int h) {
 498         nativeSetNSWindowBounds(getNSWindowPtr(), x, y, w, h);
 499     }
 500 
 501     public void setMaximizedBounds(int x, int y, int w, int h) {
 502         nativeSetNSWindowStandardFrame(getNSWindowPtr(), x, y, w, h);
 503     }
 504 
 505     private boolean isMaximized() {
 506         return undecorated ? this.normalBounds != null
 507                 : CWrapper.NSWindow.isZoomed(getNSWindowPtr());
 508     }
 509 
 510     private void maximize() {
 511         if (peer == null || isMaximized()) {
 512             return;
 513         }
 514         if (!undecorated) {
 515             CWrapper.NSWindow.zoom(getNSWindowPtr());
 516         } else {
 517             deliverZoom(true);
 518 
 519             // We need an up to date size of the peer, so we flush the native events
 520             // to be sure that there are no setBounds requests in the queue.
 521             LWCToolkit.flushNativeSelectors();
 522             this.normalBounds = peer.getBounds();
 523             Rectangle maximizedBounds = peer.getMaximizedBounds();
 524             setBounds(maximizedBounds.x, maximizedBounds.y,
 525                     maximizedBounds.width, maximizedBounds.height);
 526         }
 527     }
 528 
 529     private void unmaximize() {
 530         if (!isMaximized()) {
 531             return;
 532         }
 533         if (!undecorated) {
 534             CWrapper.NSWindow.zoom(getNSWindowPtr());
 535         } else {
 536             deliverZoom(false);
 537 
 538             Rectangle toBounds = this.normalBounds;
 539             this.normalBounds = null;
 540             setBounds(toBounds.x, toBounds.y, toBounds.width, toBounds.height);
 541         }
 542     }
 543 
 544     public boolean isVisible() {
 545         return this.visible;
 546     }
 547 
 548     @Override // PlatformWindow
 549     public void setVisible(boolean visible) {
 550         final long nsWindowPtr = getNSWindowPtr();
 551 
 552         // Configure stuff
 553         updateIconImages();
 554         updateFocusabilityForAutoRequestFocus(false);
 555 
 556         boolean wasMaximized = isMaximized();
 557 
 558         if (visible && target.isLocationByPlatform()) {
 559             nativeSetNSWindowLocationByPlatform(getNSWindowPtr());
 560         }
 561 
 562         // Actually show or hide the window
 563         LWWindowPeer blocker = (peer == null)? null : peer.getBlocker();
 564         if (blocker == null || !visible) {
 565             // If it ain't blocked, or is being hidden, go regular way
 566             if (visible) {
 567                 CWrapper.NSWindow.makeFirstResponder(nsWindowPtr, contentView.getAWTView());
 568 
 569                 boolean isPopup = (target.getType() == Window.Type.POPUP);
 570                 if (isPopup) {
 571                     // Popups in applets don't activate applet's process
 572                     CWrapper.NSWindow.orderFrontRegardless(nsWindowPtr);
 573                 } else {
 574                     CWrapper.NSWindow.orderFront(nsWindowPtr);
 575                 }
 576 
 577                 boolean isKeyWindow = CWrapper.NSWindow.isKeyWindow(nsWindowPtr);
 578                 if (!isKeyWindow) {
 579                     CWrapper.NSWindow.makeKeyWindow(nsWindowPtr);
 580                 }
 581             } else {
 582                 // immediately hide the window
 583                 CWrapper.NSWindow.orderOut(nsWindowPtr);
 584                 // process the close
 585                 CWrapper.NSWindow.close(nsWindowPtr);
 586             }
 587         } else {
 588             // otherwise, put it in a proper z-order
 589             CWrapper.NSWindow.orderWindow(nsWindowPtr, CWrapper.NSWindow.NSWindowBelow,
 590                     ((CPlatformWindow)blocker.getPlatformWindow()).getNSWindowPtr());
 591         }
 592         this.visible = visible;
 593 
 594         // Manage the extended state when showing
 595         if (visible) {
 596             // Apply the extended state as expected in shared code
 597             if (target instanceof Frame) {
 598                 if (!wasMaximized && isMaximized()) {
 599                     // setVisible could have changed the native maximized state
 600                     deliverZoom(true);
 601                 } else {
 602                     int frameState = ((Frame)target).getExtendedState();
 603                     if ((frameState & Frame.ICONIFIED) != 0) {
 604                         // Treat all state bit masks with ICONIFIED bit as ICONIFIED state.
 605                         frameState = Frame.ICONIFIED;
 606                     }
 607                     switch (frameState) {
 608                         case Frame.ICONIFIED:
 609                             CWrapper.NSWindow.miniaturize(nsWindowPtr);
 610                             break;
 611                         case Frame.MAXIMIZED_BOTH:
 612                             maximize();
 613                             break;
 614                         default: // NORMAL
 615                             unmaximize(); // in case it was maximized, otherwise this is a no-op
 616                             break;
 617                     }
 618                 }
 619             }
 620         }
 621 
 622         nativeSynthesizeMouseEnteredExitedEvents();
 623 
 624         // Configure stuff #2
 625         updateFocusabilityForAutoRequestFocus(true);
 626 
 627         // Manage parent-child relationship when showing
 628         final ComponentAccessor acc = AWTAccessor.getComponentAccessor();
 629 
 630         if (visible) {
 631             // Order myself above my parent
 632             if (owner != null && owner.isVisible()) {
 633                 CWrapper.NSWindow.orderWindow(nsWindowPtr, CWrapper.NSWindow.NSWindowAbove, owner.getNSWindowPtr());
 634                 applyWindowLevel(target);
 635             }
 636 
 637             // Order my own children above myself
 638             for (Window w : target.getOwnedWindows()) {
 639                 final Object p = acc.getPeer(w);
 640                 if (p instanceof LWWindowPeer) {
 641                     CPlatformWindow pw = (CPlatformWindow)((LWWindowPeer)p).getPlatformWindow();
 642                     if (pw != null && pw.isVisible()) {
 643                         CWrapper.NSWindow.orderWindow(pw.getNSWindowPtr(), CWrapper.NSWindow.NSWindowAbove, nsWindowPtr);
 644                         pw.applyWindowLevel(w);
 645                     }
 646                 }
 647             }
 648         }
 649 
 650         // Deal with the blocker of the window being shown
 651         if (blocker != null && visible) {
 652             // Make sure the blocker is above its siblings
 653             ((CPlatformWindow)blocker.getPlatformWindow()).orderAboveSiblings();
 654         }
 655     }
 656 
 657     @Override // PlatformWindow
 658     public void setTitle(String title) {
 659         nativeSetNSWindowTitle(getNSWindowPtr(), title);
 660     }
 661 
 662     // Should be called on every window key property change.
 663     @Override // PlatformWindow
 664     public void updateIconImages() {
 665         final long nsWindowPtr = getNSWindowPtr();
 666         final CImage cImage = getImageForTarget();
 667         nativeSetNSWindowMinimizedIcon(nsWindowPtr, cImage == null ? 0L : cImage.ptr);
 668     }
 669 
 670     public long getNSWindowPtr() {
 671         final long nsWindowPtr = ptr;
 672         if (nsWindowPtr == 0L) {
 673             if(logger.isLoggable(PlatformLogger.Level.FINE)) {
 674                 logger.fine("NSWindow already disposed?", new Exception("Pointer to native NSWindow is invalid."));
 675             }
 676         }
 677         return nsWindowPtr;
 678     }
 679 
 680     public SurfaceData getSurfaceData() {
 681         return contentView.getSurfaceData();
 682     }
 683 
 684     @Override  // PlatformWindow
 685     public void toBack() {
 686         final long nsWindowPtr = getNSWindowPtr();
 687         nativePushNSWindowToBack(nsWindowPtr);
 688     }
 689 
 690     @Override  // PlatformWindow
 691     public void toFront() {
 692         final long nsWindowPtr = getNSWindowPtr();
 693         LWCToolkit lwcToolkit = (LWCToolkit) Toolkit.getDefaultToolkit();
 694         Window w = DefaultKeyboardFocusManager.getCurrentKeyboardFocusManager().getActiveWindow();
 695         final ComponentAccessor acc = AWTAccessor.getComponentAccessor();
 696         if( w != null && acc.getPeer(w) != null
 697                 && ((LWWindowPeer)acc.getPeer(w)).getPeerType() == LWWindowPeer.PeerType.EMBEDDED_FRAME
 698                 && !lwcToolkit.isApplicationActive()) {
 699             lwcToolkit.activateApplicationIgnoringOtherApps();
 700         }
 701         updateFocusabilityForAutoRequestFocus(false);
 702         nativePushNSWindowToFront(nsWindowPtr);
 703         updateFocusabilityForAutoRequestFocus(true);
 704     }
 705 
 706     private void setCanFullscreen(final boolean canFullScreen) {
 707         if (target instanceof RootPaneContainer
 708                 && getPeer().getPeerType() == PeerType.FRAME) {
 709 
 710             if (isInFullScreen && !canFullScreen) {
 711                 toggleFullScreen();
 712             }
 713 
 714             final RootPaneContainer rpc = (RootPaneContainer) target;
 715             rpc.getRootPane().putClientProperty(
 716                     CPlatformWindow.WINDOW_FULLSCREENABLE, canFullScreen);
 717         }
 718     }
 719 
 720     @Override
 721     public void setResizable(final boolean resizable) {
 722         setCanFullscreen(resizable);
 723         setStyleBits(RESIZABLE, resizable);
 724         setStyleBits(ZOOMABLE, resizable);
 725     }
 726 
 727     @Override
 728     public void setSizeConstraints(int minW, int minH, int maxW, int maxH) {
 729         nativeSetNSWindowMinMax(getNSWindowPtr(), minW, minH, maxW, maxH);
 730     }
 731 
 732     @Override
 733     public boolean rejectFocusRequest(FocusEvent.Cause cause) {
 734         // Cross-app activation requests are not allowed.
 735         if (cause != FocusEvent.Cause.MOUSE_EVENT &&
 736             !((LWCToolkit)Toolkit.getDefaultToolkit()).isApplicationActive())
 737         {
 738             focusLogger.fine("the app is inactive, so the request is rejected");
 739             return true;
 740         }
 741         return false;
 742     }
 743 
 744     @Override
 745     public boolean requestWindowFocus() {
 746 
 747         long ptr = getNSWindowPtr();
 748         if (CWrapper.NSWindow.canBecomeMainWindow(ptr)) {
 749             CWrapper.NSWindow.makeMainWindow(ptr);
 750         }
 751         CWrapper.NSWindow.makeKeyAndOrderFront(ptr);
 752         return true;
 753     }
 754 
 755     @Override
 756     public boolean isActive() {
 757         long ptr = getNSWindowPtr();
 758         return CWrapper.NSWindow.isKeyWindow(ptr);
 759     }
 760 
 761     @Override
 762     public void updateFocusableWindowState() {
 763         final boolean isFocusable = isNativelyFocusableWindow();
 764         setStyleBits(SHOULD_BECOME_KEY | SHOULD_BECOME_MAIN, isFocusable); // set both bits at once
 765     }
 766 
 767     @Override
 768     public void setAlwaysOnTop(boolean isAlwaysOnTop) {
 769         setStyleBits(ALWAYS_ON_TOP, isAlwaysOnTop);
 770     }
 771 
 772     @Override
 773     public void setOpacity(float opacity) {
 774         CWrapper.NSWindow.setAlphaValue(getNSWindowPtr(), opacity);
 775     }
 776 
 777     @Override
 778     public void setOpaque(boolean isOpaque) {
 779         CWrapper.NSWindow.setOpaque(getNSWindowPtr(), isOpaque);
 780         boolean isTextured = (peer == null) ? false : peer.isTextured();
 781         if (!isTextured) {
 782             if (!isOpaque) {
 783                 CWrapper.NSWindow.setBackgroundColor(getNSWindowPtr(), 0);
 784             } else if (peer != null) {
 785                 Color color = peer.getBackground();
 786                 if (color != null) {
 787                     int rgb = color.getRGB();
 788                     CWrapper.NSWindow.setBackgroundColor(getNSWindowPtr(), rgb);
 789                 }
 790             }
 791         }
 792 
 793         //This is a temporary workaround. Looks like after 7124236 will be fixed
 794         //the correct place for invalidateShadow() is CGLayer.drawInCGLContext.
 795         SwingUtilities.invokeLater(this::invalidateShadow);
 796     }
 797 
 798     @Override
 799     public void enterFullScreenMode() {
 800         isFullScreenMode = true;
 801         nativeEnterFullScreenMode(getNSWindowPtr());
 802     }
 803 
 804     @Override
 805     public void exitFullScreenMode() {
 806         nativeExitFullScreenMode(getNSWindowPtr());
 807         isFullScreenMode = false;
 808     }
 809 
 810     @Override
 811     public boolean isFullScreenMode() {
 812         return isFullScreenMode;
 813     }
 814 
 815     @Override
 816     public void setWindowState(int windowState) {
 817         if (peer == null || !peer.isVisible()) {
 818             // setVisible() applies the state
 819             return;
 820         }
 821 
 822         int prevWindowState = peer.getState();
 823         if (prevWindowState == windowState) return;
 824 
 825         final long nsWindowPtr = getNSWindowPtr();
 826         if ((windowState & Frame.ICONIFIED) != 0) {
 827             // Treat all state bit masks with ICONIFIED bit as ICONIFIED state.
 828             windowState = Frame.ICONIFIED;
 829         }
 830         switch (windowState) {
 831             case Frame.ICONIFIED:
 832                 if (prevWindowState == Frame.MAXIMIZED_BOTH) {
 833                     // let's return into the normal states first
 834                     // the zoom call toggles between the normal and the max states
 835                     unmaximize();
 836                 }
 837                 CWrapper.NSWindow.miniaturize(nsWindowPtr);
 838                 break;
 839             case Frame.MAXIMIZED_BOTH:
 840                 if (prevWindowState == Frame.ICONIFIED) {
 841                     // let's return into the normal states first
 842                     CWrapper.NSWindow.deminiaturize(nsWindowPtr);
 843                 }
 844                 maximize();
 845                 break;
 846             case Frame.NORMAL:
 847                 if (prevWindowState == Frame.ICONIFIED) {
 848                     CWrapper.NSWindow.deminiaturize(nsWindowPtr);
 849                 } else if (prevWindowState == Frame.MAXIMIZED_BOTH) {
 850                     // the zoom call toggles between the normal and the max states
 851                     unmaximize();
 852                 }
 853                 break;
 854             default:
 855                 throw new RuntimeException("Unknown window state: " + windowState);
 856         }
 857 
 858         // NOTE: the SWP.windowState field gets updated to the newWindowState
 859         //       value when the native notification comes to us
 860     }
 861 
 862     @Override
 863     public void setModalBlocked(boolean blocked) {
 864         if (target.getModalExclusionType() == Dialog.ModalExclusionType.APPLICATION_EXCLUDE) {
 865             return;
 866         }
 867 
 868         if (blocked) {
 869             // We are going to show a modal window. Previously displayed window will be
 870             // blocked/disabled. So we have to send mouse exited event to it now, since
 871             // all mouse events are discarded for blocked/disabled windows.
 872             nativeSynthesizeMouseEnteredExitedEvents(getNSWindowPtr(), CocoaConstants.NSMouseExited);
 873         }
 874 
 875         nativeSetEnabled(getNSWindowPtr(), !blocked);
 876         checkBlockingAndOrder();
 877     }
 878 
 879     public final void invalidateShadow(){
 880         nativeRevalidateNSWindowShadow(getNSWindowPtr());
 881     }
 882 
 883     // ----------------------------------------------------------------------
 884     //                          UTILITY METHODS
 885     // ----------------------------------------------------------------------
 886 
 887     /**
 888      * Find image to install into Title or into Application icon. First try
 889      * icons installed for toplevel. Null is returned, if there is no icon and
 890      * default Duke image should be used.
 891      */
 892     private CImage getImageForTarget() {
 893         CImage icon = null;
 894         try {
 895             icon = CImage.getCreator().createFromImages(target.getIconImages());
 896         } catch (Exception ignored) {
 897             // Perhaps the icon passed into Java is broken. Skipping this icon.
 898         }
 899         return icon;
 900     }
 901 
 902     /*
 903      * Returns LWWindowPeer associated with this delegate.
 904      */
 905     @Override
 906     public LWWindowPeer getPeer() {
 907         return peer;
 908     }
 909 
 910     @Override
 911     public boolean isUnderMouse() {
 912         return contentView.isUnderMouse();
 913     }
 914 
 915     public CPlatformView getContentView() {
 916         return contentView;
 917     }
 918 
 919     @Override
 920     public long getLayerPtr() {
 921         return contentView.getWindowLayerPtr();
 922     }
 923 
 924     private void validateSurface() {
 925         SurfaceData surfaceData = getSurfaceData();
 926         if (surfaceData instanceof CGLSurfaceData) {
 927             ((CGLSurfaceData)surfaceData).validate();
 928         }
 929     }
 930 
 931     void flushBuffers() {
 932         if (isVisible() && !nativeBounds.isEmpty() && !isFullScreenMode) {
 933             try {
 934                 LWCToolkit.invokeAndWait(new Runnable() {
 935                     @Override
 936                     public void run() {
 937                         //Posting an empty to flush the EventQueue without blocking the main thread
 938                     }
 939                 }, target);
 940             } catch (InvocationTargetException e) {
 941                 e.printStackTrace();
 942             }
 943         }
 944     }
 945 
 946     /**
 947      * Helper method to get a pointer to the native view from the PlatformWindow.
 948      */
 949     static long getNativeViewPtr(PlatformWindow platformWindow) {
 950         long nativePeer = 0L;
 951         if (platformWindow instanceof CPlatformWindow) {
 952             nativePeer = ((CPlatformWindow) platformWindow).getContentView().getAWTView();
 953         } else if (platformWindow instanceof CViewPlatformEmbeddedFrame){
 954             nativePeer = ((CViewPlatformEmbeddedFrame) platformWindow).getNSViewPtr();
 955         }
 956         return nativePeer;
 957     }
 958 
 959     /*************************************************************
 960      * Callbacks from the AWTWindow and AWTView objc classes.
 961      *************************************************************/
 962     private void deliverWindowFocusEvent(boolean gained, CPlatformWindow opposite){
 963         // Fix for 7150349: ingore "gained" notifications when the app is inactive.
 964         if (gained && !((LWCToolkit)Toolkit.getDefaultToolkit()).isApplicationActive()) {
 965             focusLogger.fine("the app is inactive, so the notification is ignored");
 966             return;
 967         }
 968 
 969         LWWindowPeer oppositePeer = (opposite == null)? null : opposite.getPeer();
 970         responder.handleWindowFocusEvent(gained, oppositePeer);
 971     }
 972 
 973     protected void deliverMoveResizeEvent(int x, int y, int width, int height,
 974                                         boolean byUser) {
 975         checkZoom();
 976 
 977         final Rectangle oldB = nativeBounds;
 978         nativeBounds = new Rectangle(x, y, width, height);
 979         if (peer != null) {
 980             peer.notifyReshape(x, y, width, height);
 981             // System-dependent appearance optimization.
 982             if ((byUser && !oldB.getSize().equals(nativeBounds.getSize()))
 983                     || isFullScreenAnimationOn) {
 984                 flushBuffers();
 985             }
 986         }
 987     }
 988 
 989     private void deliverWindowClosingEvent() {
 990         if (peer != null && peer.getBlocker() == null) {
 991             peer.postEvent(new WindowEvent(target, WindowEvent.WINDOW_CLOSING));
 992         }
 993     }
 994 
 995     private void deliverIconify(final boolean iconify) {
 996         if (peer != null) {
 997             peer.notifyIconify(iconify);
 998         }
 999     }
1000 
1001     private void deliverZoom(final boolean isZoomed) {
1002         if (peer != null) {
1003             peer.notifyZoom(isZoomed);
1004         }
1005     }
1006 
1007     private void checkZoom() {
1008         if (peer != null) {
1009             int state = peer.getState();
1010             if (state != Frame.MAXIMIZED_BOTH && isMaximized()) {
1011                 deliverZoom(true);
1012             } else if (state == Frame.MAXIMIZED_BOTH && !isMaximized()) {
1013                 deliverZoom(false);
1014             }
1015         }
1016     }
1017 
1018     private void deliverNCMouseDown() {
1019         if (peer != null) {
1020             peer.notifyNCMouseDown();
1021         }
1022     }
1023 
1024     /*
1025      * Our focus model is synthetic and only non-simple window
1026      * may become natively focusable window.
1027      */
1028     private boolean isNativelyFocusableWindow() {
1029         if (peer == null) {
1030             return false;
1031         }
1032 
1033         return !peer.isSimpleWindow() && target.getFocusableWindowState();
1034     }
1035 
1036     /*
1037      * An utility method for the support of the auto request focus.
1038      * Updates the focusable state of the window under certain
1039      * circumstances.
1040      */
1041     private void updateFocusabilityForAutoRequestFocus(boolean isFocusable) {
1042         if (target.isAutoRequestFocus() || !isNativelyFocusableWindow()) return;
1043         setStyleBits(SHOULD_BECOME_KEY | SHOULD_BECOME_MAIN, isFocusable); // set both bits at once
1044     }
1045 
1046     private boolean checkBlockingAndOrder() {
1047         LWWindowPeer blocker = (peer == null)? null : peer.getBlocker();
1048         if (blocker == null) {
1049             return false;
1050         }
1051 
1052         if (blocker instanceof CPrinterDialogPeer) {
1053             return true;
1054         }
1055 
1056         CPlatformWindow pWindow = (CPlatformWindow)blocker.getPlatformWindow();
1057 
1058         pWindow.orderAboveSiblings();
1059 
1060         final long nsWindowPtr = pWindow.getNSWindowPtr();
1061         CWrapper.NSWindow.orderFrontRegardless(nsWindowPtr);
1062         CWrapper.NSWindow.makeKeyAndOrderFront(nsWindowPtr);
1063         CWrapper.NSWindow.makeMainWindow(nsWindowPtr);
1064 
1065         return true;
1066     }
1067 
1068     private boolean isOneOfOwnersOrSelf(CPlatformWindow window) {
1069         while (window != null) {
1070             if (this == window) {
1071                 return true;
1072             }
1073             window = window.owner;
1074         }
1075         return false;
1076     }
1077 
1078     private CPlatformWindow getRootOwner() {
1079         CPlatformWindow rootOwner = this;
1080         while (rootOwner.owner != null) {
1081             rootOwner = rootOwner.owner;
1082         }
1083         return rootOwner;
1084     }
1085 
1086     private void orderAboveSiblings() {
1087         // Recursively pop up the windows from the very bottom, (i.e. root owner) so that
1088         // the windows are ordered above their nearest owner; ancestors of the window,
1089         // which is going to become 'main window', are placed above their siblings.
1090         CPlatformWindow rootOwner = getRootOwner();
1091         if (rootOwner.isVisible()) {
1092             CWrapper.NSWindow.orderFront(rootOwner.getNSWindowPtr());
1093         }
1094         orderAboveSiblingsImpl(rootOwner.target.getOwnedWindows());
1095     }
1096 
1097     private void orderAboveSiblingsImpl(Window[] windows) {
1098         ArrayList<Window> childWindows = new ArrayList<Window>();
1099 
1100         final ComponentAccessor acc = AWTAccessor.getComponentAccessor();
1101 
1102         // Go through the list of windows and perform ordering.
1103         for (Window w : windows) {
1104             final Object p = acc.getPeer(w);
1105             if (p instanceof LWWindowPeer) {
1106                 CPlatformWindow pw = (CPlatformWindow)((LWWindowPeer)p).getPlatformWindow();
1107                 if (pw != null && pw.isVisible()) {
1108                     // If the window is one of ancestors of 'main window' or is going to become main by itself,
1109                     // the window should be ordered above its siblings; otherwise the window is just ordered
1110                     // above its nearest parent.
1111                     if (pw.isOneOfOwnersOrSelf(this)) {
1112                         CWrapper.NSWindow.orderFront(pw.getNSWindowPtr());
1113                     } else {
1114                         CWrapper.NSWindow.orderWindow(pw.getNSWindowPtr(), CWrapper.NSWindow.NSWindowAbove,
1115                                 pw.owner.getNSWindowPtr());
1116                     }
1117                     pw.applyWindowLevel(w);
1118                 }
1119             }
1120             // Retrieve the child windows for each window from the list and store them for future use.
1121             // Note: we collect data about child windows even for invisible owners, since they may have
1122             // visible children.
1123             java.util.List<Window> pwChildWindows = new ArrayList<Window>(Arrays.asList(w.getOwnedWindows()));
1124             childWindows.addAll(pwChildWindows);
1125         }
1126         // If some windows, which have just been ordered, have any child windows, let's start new iteration
1127         // and order these child windows.
1128         if (!childWindows.isEmpty()) {
1129             orderAboveSiblingsImpl(childWindows.toArray(new Window[childWindows.size()]));
1130         }
1131     }
1132 
1133     protected void applyWindowLevel(Window target) {
1134         if (target.isAlwaysOnTop() && target.getType() != Window.Type.POPUP) {
1135             CWrapper.NSWindow.setLevel(getNSWindowPtr(), CWrapper.NSWindow.NSFloatingWindowLevel);
1136         } else if (target.getType() == Window.Type.POPUP) {
1137             CWrapper.NSWindow.setLevel(getNSWindowPtr(), CWrapper.NSWindow.NSPopUpMenuWindowLevel);
1138         }
1139     }
1140 
1141     // ----------------------------------------------------------------------
1142     //                          NATIVE CALLBACKS
1143     // ----------------------------------------------------------------------
1144 
1145     private void windowDidBecomeMain() {
1146         if (checkBlockingAndOrder()) return;
1147         // If it's not blocked, make sure it's above its siblings
1148         orderAboveSiblings();
1149     }
1150 
1151     private void windowWillEnterFullScreen() {
1152         isFullScreenAnimationOn = true;
1153     }
1154 
1155     private void windowDidEnterFullScreen() {
1156         isInFullScreen = true;
1157         isFullScreenAnimationOn = false;
1158     }
1159 
1160     private void windowWillExitFullScreen() {
1161         isFullScreenAnimationOn = true;
1162     }
1163 
1164     private void windowDidExitFullScreen() {
1165         isInFullScreen = false;
1166         isFullScreenAnimationOn = false;
1167     }
1168 }