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