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     private boolean maximizedBothState = false;
 299     private boolean frameResizibilityChanged = false;
 300 
 301     public CPlatformWindow() {
 302         super(0, true);
 303     }
 304 
 305     /*
 306      * Delegate initialization (create native window and all the
 307      * related resources).
 308      */
 309     @Override // PlatformWindow
 310     public void initialize(Window _target, LWWindowPeer _peer, PlatformWindow _owner) {
 311         initializeBase(_target, _peer, _owner, new CPlatformView());
 312 
 313         final int styleBits = getInitialStyleBits();
 314 
 315         responder = createPlatformResponder();
 316         contentView = createContentView();
 317         contentView.initialize(peer, responder);
 318 
 319         Rectangle bounds;
 320         if (!IS(DECORATED, styleBits)) {
 321             // For undecorated frames the move/resize event does not come if the frame is centered on the screen
 322             // so we need to set a stub location to force an initial move/resize. Real bounds would be set later.
 323             bounds = new Rectangle(0, 0, 1, 1);
 324         } else {
 325             bounds = _peer.constrainBounds(_target.getBounds());
 326         }
 327         AtomicLong ref = new AtomicLong();
 328         contentView.execute(viewPtr -> {
 329             boolean hasOwnerPtr = false;
 330 
 331             if (owner != null) {
 332                 hasOwnerPtr = 0L != owner.executeGet(ownerPtr -> {
 333                     ref.set(nativeCreateNSWindow(viewPtr, ownerPtr, styleBits,
 334                                                     bounds.x, bounds.y,
 335                                                     bounds.width, bounds.height));
 336                     return 1;
 337                 });
 338             }
 339 
 340             if (!hasOwnerPtr) {
 341                 ref.set(nativeCreateNSWindow(viewPtr, 0,
 342                                              styleBits, bounds.x, bounds.y,
 343                                              bounds.width, bounds.height));
 344             }
 345         });
 346         setPtr(ref.get());
 347 
 348         if (target instanceof javax.swing.RootPaneContainer) {
 349             final javax.swing.JRootPane rootpane = ((javax.swing.RootPaneContainer)target).getRootPane();
 350             if (rootpane != null) rootpane.addPropertyChangeListener("ancestor", new PropertyChangeListener() {
 351                 public void propertyChange(final PropertyChangeEvent evt) {
 352                     CLIENT_PROPERTY_APPLICATOR.attachAndApplyClientProperties(rootpane);
 353                     rootpane.removePropertyChangeListener("ancestor", this);
 354                 }
 355             });
 356         }
 357 
 358         validateSurface();
 359     }
 360 
 361     protected void initializeBase(Window target, LWWindowPeer peer, PlatformWindow owner, CPlatformView view) {
 362         this.peer = peer;
 363         this.target = target;
 364         if (owner instanceof CPlatformWindow) {
 365             this.owner = (CPlatformWindow)owner;
 366         }
 367         this.contentView = view;
 368     }
 369 
 370     protected CPlatformResponder createPlatformResponder() {
 371         return new CPlatformResponder(peer, false);
 372     }
 373 
 374     protected CPlatformView createContentView() {
 375         return new CPlatformView();
 376     }
 377 
 378     protected int getInitialStyleBits() {
 379         // defaults style bits
 380         int styleBits = DECORATED | HAS_SHADOW | CLOSEABLE | MINIMIZABLE | ZOOMABLE | RESIZABLE;
 381 
 382         if (isNativelyFocusableWindow()) {
 383             styleBits = SET(styleBits, SHOULD_BECOME_KEY, true);
 384             styleBits = SET(styleBits, SHOULD_BECOME_MAIN, true);
 385         }
 386 
 387         final boolean isFrame = (target instanceof Frame);
 388         final boolean isDialog = (target instanceof Dialog);
 389         final boolean isPopup = (target.getType() == Window.Type.POPUP);
 390         if (isDialog) {
 391             styleBits = SET(styleBits, MINIMIZABLE, false);
 392         }
 393 
 394         // Either java.awt.Frame or java.awt.Dialog can be undecorated, however java.awt.Window always is undecorated.
 395         {
 396             this.undecorated = isFrame ? ((Frame)target).isUndecorated() : (isDialog ? ((Dialog)target).isUndecorated() : true);
 397             if (this.undecorated) styleBits = SET(styleBits, DECORATED, false);
 398         }
 399 
 400         // Either java.awt.Frame or java.awt.Dialog can be resizable, however java.awt.Window is never resizable
 401         {
 402             final boolean resizable = isTargetResizable();
 403             styleBits = SET(styleBits, RESIZABLE, resizable);
 404             if (!resizable) {
 405                 styleBits = SET(styleBits, ZOOMABLE, false);
 406             }
 407         }
 408 
 409         if (target.isAlwaysOnTop()) {
 410             styleBits = SET(styleBits, ALWAYS_ON_TOP, true);
 411         }
 412 
 413         if (target.getModalExclusionType() == Dialog.ModalExclusionType.APPLICATION_EXCLUDE) {
 414             styleBits = SET(styleBits, MODAL_EXCLUDED, true);
 415         }
 416 
 417         // If the target is a dialog, popup or tooltip we want it to ignore the brushed metal look.
 418         if (isPopup) {
 419             styleBits = SET(styleBits, TEXTURED, false);
 420             // Popups in applets don't activate applet's process
 421             styleBits = SET(styleBits, NONACTIVATING, true);
 422             styleBits = SET(styleBits, IS_POPUP, true);
 423         }
 424 
 425         if (Window.Type.UTILITY.equals(target.getType())) {
 426             styleBits = SET(styleBits, UTILITY, true);
 427         }
 428 
 429         if (target instanceof javax.swing.RootPaneContainer) {
 430             javax.swing.JRootPane rootpane = ((javax.swing.RootPaneContainer)target).getRootPane();
 431             Object prop = null;
 432 
 433             prop = rootpane.getClientProperty(WINDOW_BRUSH_METAL_LOOK);
 434             if (prop != null) {
 435                 styleBits = SET(styleBits, TEXTURED, Boolean.parseBoolean(prop.toString()));
 436             }
 437 
 438             if (isDialog && ((Dialog)target).getModalityType() == ModalityType.DOCUMENT_MODAL) {
 439                 prop = rootpane.getClientProperty(WINDOW_DOC_MODAL_SHEET);
 440                 if (prop != null) {
 441                     styleBits = SET(styleBits, SHEET, Boolean.parseBoolean(prop.toString()));
 442                 }
 443             }
 444 
 445             prop = rootpane.getClientProperty(WINDOW_STYLE);
 446             if (prop != null) {
 447                 if ("small".equals(prop))  {
 448                     styleBits = SET(styleBits, UTILITY, true);
 449                     if (target.isAlwaysOnTop() && rootpane.getClientProperty(WINDOW_HIDES_ON_DEACTIVATE) == null) {
 450                         styleBits = SET(styleBits, HIDES_ON_DEACTIVATE, true);
 451                     }
 452                 }
 453                 if ("textured".equals(prop)) styleBits = SET(styleBits, TEXTURED, true);
 454                 if ("unified".equals(prop)) styleBits = SET(styleBits, UNIFIED, true);
 455                 if ("hud".equals(prop)) styleBits = SET(styleBits, HUD, true);
 456             }
 457 
 458             prop = rootpane.getClientProperty(WINDOW_HIDES_ON_DEACTIVATE);
 459             if (prop != null) {
 460                 styleBits = SET(styleBits, HIDES_ON_DEACTIVATE, Boolean.parseBoolean(prop.toString()));
 461             }
 462 
 463             prop = rootpane.getClientProperty(WINDOW_CLOSEABLE);
 464             if (prop != null) {
 465                 styleBits = SET(styleBits, CLOSEABLE, Boolean.parseBoolean(prop.toString()));
 466             }
 467 
 468             prop = rootpane.getClientProperty(WINDOW_MINIMIZABLE);
 469             if (prop != null) {
 470                 styleBits = SET(styleBits, MINIMIZABLE, Boolean.parseBoolean(prop.toString()));
 471             }
 472 
 473             prop = rootpane.getClientProperty(WINDOW_ZOOMABLE);
 474             if (prop != null) {
 475                 styleBits = SET(styleBits, ZOOMABLE, Boolean.parseBoolean(prop.toString()));
 476             }
 477 
 478             prop = rootpane.getClientProperty(WINDOW_FULLSCREENABLE);
 479             if (prop != null) {
 480                 styleBits = SET(styleBits, FULLSCREENABLE, Boolean.parseBoolean(prop.toString()));
 481             }
 482 
 483             prop = rootpane.getClientProperty(WINDOW_SHADOW);
 484             if (prop != null) {
 485                 styleBits = SET(styleBits, HAS_SHADOW, Boolean.parseBoolean(prop.toString()));
 486             }
 487 
 488             prop = rootpane.getClientProperty(WINDOW_DRAGGABLE_BACKGROUND);
 489             if (prop != null) {
 490                 styleBits = SET(styleBits, DRAGGABLE_BACKGROUND, Boolean.parseBoolean(prop.toString()));
 491             }
 492 
 493             prop = rootpane.getClientProperty(WINDOW_FULL_CONTENT);
 494             if (prop != null) {
 495                 styleBits = SET(styleBits, FULL_WINDOW_CONTENT, Boolean.parseBoolean(prop.toString()));
 496             }
 497 
 498             prop = rootpane.getClientProperty(WINDOW_TRANSPARENT_TITLE_BAR);
 499             if (prop != null) {
 500                 styleBits = SET(styleBits, TRANSPARENT_TITLE_BAR, Boolean.parseBoolean(prop.toString()));
 501             }
 502         }
 503 
 504         if (isDialog) {
 505             styleBits = SET(styleBits, IS_DIALOG, true);
 506             if (((Dialog) target).isModal()) {
 507                 styleBits = SET(styleBits, IS_MODAL, true);
 508             }
 509         }
 510 
 511         peer.setTextured(IS(TEXTURED, styleBits));
 512 
 513         return styleBits;
 514     }
 515 
 516     // this is the counter-point to -[CWindow _nativeSetStyleBit:]
 517     private void setStyleBits(final int mask, final boolean value) {
 518         execute(ptr -> nativeSetNSWindowStyleBits(ptr, mask, value ? mask : 0));
 519     }
 520 
 521     private native void _toggleFullScreenMode(final long model);
 522 
 523     public void toggleFullScreen() {
 524         execute(this::_toggleFullScreenMode);
 525     }
 526 
 527     @Override // PlatformWindow
 528     public void setMenuBar(MenuBar mb) {
 529         CMenuBar mbPeer = (CMenuBar)LWToolkit.targetToPeer(mb);
 530         execute(nsWindowPtr->{
 531             if (mbPeer != null) {
 532                 mbPeer.execute(ptr -> nativeSetNSWindowMenuBar(nsWindowPtr, ptr));
 533             } else {
 534                 nativeSetNSWindowMenuBar(nsWindowPtr, 0);
 535             }
 536         });
 537     }
 538 
 539     @Override // PlatformWindow
 540     public void dispose() {
 541         contentView.dispose();
 542         execute(CPlatformWindow::nativeDispose);
 543         CPlatformWindow.super.dispose();
 544     }
 545 
 546     @Override // PlatformWindow
 547     public FontMetrics getFontMetrics(Font f) {
 548         // TODO: not implemented
 549         (new RuntimeException("unimplemented")).printStackTrace();
 550         return null;
 551     }
 552 
 553     @Override // PlatformWindow
 554     public Insets getInsets() {
 555         AtomicReference<Insets> ref = new AtomicReference<>();
 556         execute(ptr -> {
 557             ref.set(nativeGetNSWindowInsets(ptr));
 558         });
 559         return ref.get() != null ? ref.get() : new Insets(0, 0, 0, 0);
 560     }
 561 
 562     @Override // PlatformWindow
 563     public Point getLocationOnScreen() {
 564         return new Point(nativeBounds.x, nativeBounds.y);
 565     }
 566 
 567     @Override
 568     public GraphicsDevice getGraphicsDevice() {
 569         return contentView.getGraphicsDevice();
 570     }
 571 
 572     @Override // PlatformWindow
 573     public SurfaceData getScreenSurface() {
 574         // TODO: not implemented
 575         return null;
 576     }
 577 
 578     @Override // PlatformWindow
 579     public SurfaceData replaceSurfaceData() {
 580         return contentView.replaceSurfaceData();
 581     }
 582 
 583     @Override // PlatformWindow
 584     public void setBounds(int x, int y, int w, int h) {
 585         execute(ptr -> nativeSetNSWindowBounds(ptr, x, y, w, h));
 586     }
 587 
 588     public void setMaximizedBounds(int x, int y, int w, int h) {
 589         execute(ptr -> nativeSetNSWindowStandardFrame(ptr, x, y, w, h));
 590     }
 591 
 592     private boolean isMaximized() {
 593         return undecorated ? this.normalBounds != null
 594                 : isZoomed;
 595     }
 596 
 597     private void maximize() {
 598         if (peer == null || isMaximized()) {
 599             return;
 600         }
 601         if (!undecorated) {
 602             execute(CWrapper.NSWindow::zoom);
 603         } else {
 604             deliverZoom(true);
 605 
 606             // We need an up to date size of the peer, so we flush the native events
 607             // to be sure that there are no setBounds requests in the queue.
 608             LWCToolkit.flushNativeSelectors();
 609             this.normalBounds = peer.getBounds();
 610             Rectangle maximizedBounds = peer.getMaximizedBounds();
 611             setBounds(maximizedBounds.x, maximizedBounds.y,
 612                     maximizedBounds.width, maximizedBounds.height);
 613         }
 614         setFrameResizibilityChanged(true);
 615         updateResizableAndMaximizeState(true);
 616     }
 617 
 618     private void unmaximize() {
 619         if (!isMaximized()) {
 620             return;
 621         }
 622         if (!undecorated) {
 623             execute(CWrapper.NSWindow::zoom);
 624         } else {
 625             deliverZoom(false);
 626 
 627             Rectangle toBounds = this.normalBounds;
 628             this.normalBounds = null;
 629             setBounds(toBounds.x, toBounds.y, toBounds.width, toBounds.height);
 630         }
 631     }
 632 
 633     public boolean isVisible() {
 634         return this.visible;
 635     }
 636 
 637     @Override // PlatformWindow
 638     public void setVisible(boolean visible) {
 639         // Configure stuff
 640         updateIconImages();
 641         updateFocusabilityForAutoRequestFocus(false);
 642 
 643         boolean wasMaximized = isMaximized();
 644 
 645         if (visible && target.isLocationByPlatform()) {
 646             execute(CPlatformWindow::nativeSetNSWindowLocationByPlatform);
 647         }
 648 
 649         // Actually show or hide the window
 650         LWWindowPeer blocker = (peer == null)? null : peer.getBlocker();
 651         if (blocker == null || !visible) {
 652             // If it ain't blocked, or is being hidden, go regular way
 653             if (visible) {
 654                 contentView.execute(viewPtr -> {
 655                     execute(ptr -> CWrapper.NSWindow.makeFirstResponder(ptr,
 656                                                                         viewPtr));
 657                 });
 658 
 659                 boolean isPopup = (target.getType() == Window.Type.POPUP);
 660                 execute(ptr -> {
 661                     if (isPopup) {
 662                         // Popups in applets don't activate applet's process
 663                         CWrapper.NSWindow.orderFrontRegardless(ptr);
 664                     } else {
 665                         CWrapper.NSWindow.orderFront(ptr);
 666                     }
 667 
 668                     boolean isKeyWindow = CWrapper.NSWindow.isKeyWindow(ptr);
 669                     if (!isKeyWindow) {
 670                         CWrapper.NSWindow.makeKeyWindow(ptr);
 671                     }
 672 
 673                     if (owner != null
 674                             && owner.getPeer() instanceof LWLightweightFramePeer) {
 675                         LWLightweightFramePeer peer =
 676                                 (LWLightweightFramePeer) owner.getPeer();
 677 
 678                         long ownerWindowPtr = peer.getOverriddenWindowHandle();
 679                         if (ownerWindowPtr != 0) {
 680                             //Place window above JavaFX stage
 681                             CWrapper.NSWindow.addChildWindow(
 682                                     ownerWindowPtr, ptr,
 683                                     CWrapper.NSWindow.NSWindowAbove);
 684                         }
 685                     }
 686                 });
 687             } else {
 688                 execute(ptr->{
 689                     // immediately hide the window
 690                     CWrapper.NSWindow.orderOut(ptr);
 691                     // process the close
 692                     CWrapper.NSWindow.close(ptr);
 693                 });
 694             }
 695         } else {
 696             // otherwise, put it in a proper z-order
 697             CPlatformWindow bw
 698                     = (CPlatformWindow) blocker.getPlatformWindow();
 699             bw.execute(blockerPtr -> {
 700                 execute(ptr -> {
 701                     CWrapper.NSWindow.orderWindow(ptr,
 702                                                   CWrapper.NSWindow.NSWindowBelow,
 703                                                   blockerPtr);
 704                 });
 705             });
 706         }
 707         this.visible = visible;
 708 
 709         // Manage the extended state when showing
 710         if (visible) {
 711             /* Frame or Dialog should be set property WINDOW_FULLSCREENABLE to true if the
 712             Frame resizable and Frame state is not MAXIMIZED_BOTH or Dialog is resizable.
 713             **/
 714             if (isTargetResizable()) {
 715                 setCanFullscreen(true);
 716             }
 717 
 718             // Apply the extended state as expected in shared code
 719             if (target instanceof Frame) {
 720                 if (!wasMaximized && isMaximized()) {
 721                     // setVisible could have changed the native maximized state
 722                     deliverZoom(true);
 723                 } else {
 724                     int frameState = ((Frame)target).getExtendedState();
 725                     if ((frameState & Frame.ICONIFIED) != 0) {
 726                         // Treat all state bit masks with ICONIFIED bit as ICONIFIED state.
 727                         frameState = Frame.ICONIFIED;
 728                     }
 729 
 730                     if (isFrameResizibilityChanged()) {
 731                         updateResizableAndMaximizeState(false);
 732                         setFrameResizibilityChanged(false);
 733                     }
 734 
 735                     switch (frameState) {
 736                         case Frame.ICONIFIED:
 737                             execute(CWrapper.NSWindow::miniaturize);
 738                             break;
 739                         case Frame.MAXIMIZED_BOTH:
 740                             maximize();
 741                             break;
 742                         default: // NORMAL
 743                             unmaximize(); // in case it was maximized, otherwise this is a no-op
 744                             break;
 745                     }
 746                 }
 747             }
 748         }
 749 
 750         nativeSynthesizeMouseEnteredExitedEvents();
 751 
 752         // Configure stuff #2
 753         updateFocusabilityForAutoRequestFocus(true);
 754 
 755         // Manage parent-child relationship when showing
 756         final ComponentAccessor acc = AWTAccessor.getComponentAccessor();
 757 
 758         if (visible) {
 759             // Order myself above my parent
 760             if (owner != null && owner.isVisible()) {
 761                 owner.execute(ownerPtr -> {
 762                     execute(ptr -> {
 763                         CWrapper.NSWindow.orderWindow(ptr, CWrapper.NSWindow.NSWindowAbove, ownerPtr);
 764                     });
 765                 });
 766                 execute(CWrapper.NSWindow::orderFront);
 767                 applyWindowLevel(target);
 768             }
 769 
 770             // Order my own children above myself
 771             for (Window w : target.getOwnedWindows()) {
 772                 final Object p = acc.getPeer(w);
 773                 if (p instanceof LWWindowPeer) {
 774                     CPlatformWindow pw = (CPlatformWindow)((LWWindowPeer)p).getPlatformWindow();
 775                     if (pw != null && pw.isVisible()) {
 776                         pw.execute(childPtr -> {
 777                             execute(ptr -> {
 778                                 CWrapper.NSWindow.orderWindow(childPtr, CWrapper.NSWindow.NSWindowAbove, ptr);
 779                             });
 780                         });
 781                         pw.applyWindowLevel(w);
 782                     }
 783                 }
 784             }
 785         }
 786 
 787         // Deal with the blocker of the window being shown
 788         if (blocker != null && visible) {
 789             // Make sure the blocker is above its siblings
 790             ((CPlatformWindow)blocker.getPlatformWindow()).orderAboveSiblings();
 791         }
 792     }
 793 
 794     @Override // PlatformWindow
 795     public void setTitle(String title) {
 796         execute(ptr -> nativeSetNSWindowTitle(ptr, title));
 797     }
 798 
 799     // Should be called on every window key property change.
 800     @Override // PlatformWindow
 801     public void updateIconImages() {
 802         final CImage cImage = getImageForTarget();
 803         execute(ptr -> {
 804             if (cImage == null) {
 805                 nativeSetNSWindowMinimizedIcon(ptr, 0L);
 806             } else {
 807                 cImage.execute(imagePtr -> {
 808                     nativeSetNSWindowMinimizedIcon(ptr, imagePtr);
 809                 });
 810             }
 811         });
 812     }
 813 
 814     public SurfaceData getSurfaceData() {
 815         return contentView.getSurfaceData();
 816     }
 817 
 818     @Override  // PlatformWindow
 819     public void toBack() {
 820         execute(CPlatformWindow::nativePushNSWindowToBack);
 821     }
 822 
 823     @Override  // PlatformWindow
 824     public void toFront() {
 825         LWCToolkit lwcToolkit = (LWCToolkit) Toolkit.getDefaultToolkit();
 826         Window w = DefaultKeyboardFocusManager.getCurrentKeyboardFocusManager().getActiveWindow();
 827         final ComponentAccessor acc = AWTAccessor.getComponentAccessor();
 828         if( w != null && acc.getPeer(w) != null
 829                 && ((LWWindowPeer)acc.getPeer(w)).getPeerType() == LWWindowPeer.PeerType.EMBEDDED_FRAME
 830                 && !lwcToolkit.isApplicationActive()) {
 831             lwcToolkit.activateApplicationIgnoringOtherApps();
 832         }
 833         updateFocusabilityForAutoRequestFocus(false);
 834         execute(CPlatformWindow::nativePushNSWindowToFront);
 835         updateFocusabilityForAutoRequestFocus(true);
 836     }
 837 
 838     private void setCanFullscreen(final boolean canFullScreen) {
 839         if (target instanceof RootPaneContainer
 840                 && getPeer().getPeerType() == PeerType.FRAME) {
 841 
 842             if (isInFullScreen && !canFullScreen) {
 843                 toggleFullScreen();
 844             }
 845 
 846             final RootPaneContainer rpc = (RootPaneContainer) target;
 847             rpc.getRootPane().putClientProperty(
 848                     CPlatformWindow.WINDOW_FULLSCREENABLE, canFullScreen);
 849         }
 850     }
 851 
 852     @Override
 853     public void setResizable(final boolean resizable) {
 854         boolean windowResizable = resizable && !isMaximizedBoth();
 855         setCanFullscreen(windowResizable);
 856         setStyleBits(RESIZABLE, windowResizable);
 857         setStyleBits(ZOOMABLE, windowResizable);
 858     }
 859 
 860     @Override
 861     public void setSizeConstraints(int minW, int minH, int maxW, int maxH) {
 862         execute(ptr -> nativeSetNSWindowMinMax(ptr, minW, minH, maxW, maxH));
 863     }
 864 
 865     @Override
 866     public boolean rejectFocusRequest(FocusEvent.Cause cause) {
 867         // Cross-app activation requests are not allowed.
 868         if (cause != FocusEvent.Cause.MOUSE_EVENT &&
 869             !((LWCToolkit)Toolkit.getDefaultToolkit()).isApplicationActive())
 870         {
 871             focusLogger.fine("the app is inactive, so the request is rejected");
 872             return true;
 873         }
 874         return false;
 875     }
 876 
 877     @Override
 878     public boolean requestWindowFocus() {
 879         execute(ptr -> {
 880             if (CWrapper.NSWindow.canBecomeMainWindow(ptr)) {
 881                 CWrapper.NSWindow.makeMainWindow(ptr);
 882             }
 883             CWrapper.NSWindow.makeKeyAndOrderFront(ptr);
 884         });
 885         return true;
 886     }
 887 
 888     @Override
 889     public boolean isActive() {
 890         AtomicBoolean ref = new AtomicBoolean();
 891         execute(ptr -> {
 892             ref.set(CWrapper.NSWindow.isKeyWindow(ptr));
 893         });
 894         return ref.get();
 895     }
 896 
 897     @Override
 898     public void updateFocusableWindowState() {
 899         final boolean isFocusable = isNativelyFocusableWindow();
 900         setStyleBits(SHOULD_BECOME_KEY | SHOULD_BECOME_MAIN, isFocusable); // set both bits at once
 901     }
 902 
 903     @Override
 904     public void setAlwaysOnTop(boolean isAlwaysOnTop) {
 905         setStyleBits(ALWAYS_ON_TOP, isAlwaysOnTop);
 906     }
 907 
 908     @Override
 909     public void setOpacity(float opacity) {
 910         execute(ptr -> CWrapper.NSWindow.setAlphaValue(ptr, opacity));
 911     }
 912 
 913     @Override
 914     public void setOpaque(boolean isOpaque) {
 915         execute(ptr -> CWrapper.NSWindow.setOpaque(ptr, isOpaque));
 916         boolean isTextured = (peer == null) ? false : peer.isTextured();
 917         if (!isTextured) {
 918             if (!isOpaque) {
 919                 execute(ptr -> CWrapper.NSWindow.setBackgroundColor(ptr, 0));
 920             } else if (peer != null) {
 921                 Color color = peer.getBackground();
 922                 if (color != null) {
 923                     int rgb = color.getRGB();
 924                     execute(ptr->CWrapper.NSWindow.setBackgroundColor(ptr, rgb));
 925                 }
 926             }
 927         }
 928 
 929         //This is a temporary workaround. Looks like after 7124236 will be fixed
 930         //the correct place for invalidateShadow() is CGLayer.drawInCGLContext.
 931         SwingUtilities.invokeLater(this::invalidateShadow);
 932     }
 933 
 934     @Override
 935     public void enterFullScreenMode() {
 936         isFullScreenMode = true;
 937         execute(CPlatformWindow::nativeEnterFullScreenMode);
 938     }
 939 
 940     @Override
 941     public void exitFullScreenMode() {
 942         execute(CPlatformWindow::nativeExitFullScreenMode);
 943         isFullScreenMode = false;
 944     }
 945 
 946     @Override
 947     public boolean isFullScreenMode() {
 948         return isFullScreenMode;
 949     }
 950 
 951     @Override
 952     public void setWindowState(int windowState) {
 953         if (peer == null || !peer.isVisible()) {
 954             // setVisible() applies the state
 955             return;
 956         }
 957 
 958         int prevWindowState = peer.getState();
 959         if (prevWindowState == windowState) return;
 960 
 961         if ((windowState & Frame.ICONIFIED) != 0) {
 962             // Treat all state bit masks with ICONIFIED bit as ICONIFIED state.
 963             windowState = Frame.ICONIFIED;
 964         }
 965 
 966         if (isFrameResizibilityChanged()) {
 967             updateResizableAndMaximizeState(false);
 968             setFrameResizibilityChanged(false);
 969         }
 970 
 971         switch (windowState) {
 972             case Frame.ICONIFIED:
 973                 if (prevWindowState == Frame.MAXIMIZED_BOTH) {
 974                     // let's return into the normal states first
 975                     // the zoom call toggles between the normal and the max states
 976                     unmaximize();
 977                 }
 978                 execute(CWrapper.NSWindow::miniaturize);
 979                 break;
 980             case Frame.MAXIMIZED_BOTH:
 981                 if (prevWindowState == Frame.ICONIFIED) {
 982                     // let's return into the normal states first
 983                     execute(CWrapper.NSWindow::deminiaturize);
 984                 }
 985                 maximize();
 986                 break;
 987             case Frame.NORMAL:
 988                 if (prevWindowState == Frame.ICONIFIED) {
 989                     execute(CWrapper.NSWindow::deminiaturize);
 990                 } else if (prevWindowState == Frame.MAXIMIZED_BOTH) {
 991                     // the zoom call toggles between the normal and the max states
 992                     unmaximize();
 993                 }
 994                 break;
 995             default:
 996                 throw new RuntimeException("Unknown window state: " + windowState);
 997         }
 998 
 999         // NOTE: the SWP.windowState field gets updated to the newWindowState
1000         //       value when the native notification comes to us
1001     }
1002 
1003     @Override
1004     public void setModalBlocked(boolean blocked) {
1005         if (target.getModalExclusionType() == Dialog.ModalExclusionType.APPLICATION_EXCLUDE) {
1006             return;
1007         }
1008 
1009         if (blocked) {
1010             // We are going to show a modal window. Previously displayed window will be
1011             // blocked/disabled. So we have to send mouse exited event to it now, since
1012             // all mouse events are discarded for blocked/disabled windows.
1013             execute(ptr -> nativeSynthesizeMouseEnteredExitedEvents(ptr, CocoaConstants.NSMouseExited));
1014         }
1015 
1016         execute(ptr -> nativeSetEnabled(ptr, !blocked));
1017         checkBlockingAndOrder();
1018     }
1019 
1020     public final void invalidateShadow() {
1021         execute(ptr -> nativeRevalidateNSWindowShadow(ptr));
1022     }
1023 
1024     // ----------------------------------------------------------------------
1025     //                          UTILITY METHODS
1026     // ----------------------------------------------------------------------
1027 
1028     /**
1029      * Find image to install into Title or into Application icon. First try
1030      * icons installed for toplevel. Null is returned, if there is no icon and
1031      * default Duke image should be used.
1032      */
1033     private CImage getImageForTarget() {
1034         CImage icon = null;
1035         try {
1036             icon = CImage.getCreator().createFromImages(target.getIconImages());
1037         } catch (Exception ignored) {
1038             // Perhaps the icon passed into Java is broken. Skipping this icon.
1039         }
1040         return icon;
1041     }
1042 
1043     /*
1044      * Returns LWWindowPeer associated with this delegate.
1045      */
1046     @Override
1047     public LWWindowPeer getPeer() {
1048         return peer;
1049     }
1050 
1051     @Override
1052     public boolean isUnderMouse() {
1053         return contentView.isUnderMouse();
1054     }
1055 
1056     public CPlatformView getContentView() {
1057         return contentView;
1058     }
1059 
1060     @Override
1061     public long getLayerPtr() {
1062         return contentView.getWindowLayerPtr();
1063     }
1064 
1065     private void validateSurface() {
1066         SurfaceData surfaceData = getSurfaceData();
1067         if (surfaceData instanceof CGLSurfaceData) {
1068             ((CGLSurfaceData)surfaceData).validate();
1069         }
1070     }
1071 
1072     void flushBuffers() {
1073         if (isVisible() && !nativeBounds.isEmpty() && !isFullScreenMode) {
1074             try {
1075                 LWCToolkit.invokeAndWait(new Runnable() {
1076                     @Override
1077                     public void run() {
1078                         //Posting an empty to flush the EventQueue without blocking the main thread
1079                     }
1080                 }, target);
1081             } catch (InvocationTargetException e) {
1082                 e.printStackTrace();
1083             }
1084         }
1085     }
1086 
1087     /**
1088      * Helper method to get a pointer to the native view from the PlatformWindow.
1089      */
1090     static long getNativeViewPtr(PlatformWindow platformWindow) {
1091         long nativePeer = 0L;
1092         if (platformWindow instanceof CPlatformWindow) {
1093             nativePeer = ((CPlatformWindow) platformWindow).getContentView().getAWTView();
1094         } else if (platformWindow instanceof CViewPlatformEmbeddedFrame){
1095             nativePeer = ((CViewPlatformEmbeddedFrame) platformWindow).getNSViewPtr();
1096         }
1097         return nativePeer;
1098     }
1099 
1100     /*************************************************************
1101      * Callbacks from the AWTWindow and AWTView objc classes.
1102      *************************************************************/
1103     private void deliverWindowFocusEvent(boolean gained, CPlatformWindow opposite){
1104         // Fix for 7150349: ingore "gained" notifications when the app is inactive.
1105         if (gained && !((LWCToolkit)Toolkit.getDefaultToolkit()).isApplicationActive()) {
1106             focusLogger.fine("the app is inactive, so the notification is ignored");
1107             return;
1108         }
1109 
1110         LWWindowPeer oppositePeer = (opposite == null)? null : opposite.getPeer();
1111         responder.handleWindowFocusEvent(gained, oppositePeer);
1112     }
1113 
1114     protected void deliverMoveResizeEvent(int x, int y, int width, int height,
1115                                         boolean byUser) {
1116         AtomicBoolean ref = new AtomicBoolean();
1117         execute(ptr -> {
1118             ref.set(CWrapper.NSWindow.isZoomed(ptr));
1119         });
1120         isZoomed = ref.get();
1121         checkZoom();
1122 
1123         final Rectangle oldB = nativeBounds;
1124         nativeBounds = new Rectangle(x, y, width, height);
1125         if (peer != null) {
1126             peer.notifyReshape(x, y, width, height);
1127             // System-dependent appearance optimization.
1128             if ((byUser && !oldB.getSize().equals(nativeBounds.getSize()))
1129                     || isFullScreenAnimationOn) {
1130                 flushBuffers();
1131             }
1132         }
1133     }
1134 
1135     private void deliverWindowClosingEvent() {
1136         if (peer != null && peer.getBlocker() == null) {
1137             peer.postEvent(new WindowEvent(target, WindowEvent.WINDOW_CLOSING));
1138         }
1139     }
1140 
1141     private void deliverIconify(final boolean iconify) {
1142         if (peer != null) {
1143             peer.notifyIconify(iconify);
1144         }
1145         if (iconify) {
1146             isIconifyAnimationActive = false;
1147         }
1148     }
1149 
1150     private void deliverZoom(final boolean isZoomed) {
1151         if (peer != null) {
1152             peer.notifyZoom(isZoomed);
1153         }
1154     }
1155 
1156     private void checkZoom() {
1157         if (peer != null) {
1158             int state = peer.getState();
1159             if (state != Frame.MAXIMIZED_BOTH && isMaximized()) {
1160                 deliverZoom(true);
1161             } else if (state == Frame.MAXIMIZED_BOTH && !isMaximized()) {
1162                 deliverZoom(false);
1163             }
1164         }
1165     }
1166 
1167     private void deliverNCMouseDown() {
1168         if (peer != null) {
1169             peer.notifyNCMouseDown();
1170         }
1171     }
1172 
1173     /*
1174      * Resizibility of frame with state MAXIMIZED_BOTH is set to true to zoom
1175      * the frame on double click on title bar and set to false later. This is
1176      * required as frame won't zoom if resizibility of frame is false.
1177      */
1178     private void deliverDoubleClickOnTitlebar() {
1179         if ((peer != null) && (target instanceof Frame)) {
1180             if (isMaximizedBoth()) {
1181                 updateResizableAndMaximizeState(false);
1182                 execute(CWrapper.NSWindow::zoom);
1183                 updateResizableAndMaximizeState(true);
1184             }
1185         }
1186     }
1187 
1188     /*
1189      * Our focus model is synthetic and only non-simple window
1190      * may become natively focusable window.
1191      */
1192     private boolean isNativelyFocusableWindow() {
1193         if (peer == null) {
1194             return false;
1195         }
1196 
1197         return !peer.isSimpleWindow() && target.getFocusableWindowState();
1198     }
1199 
1200     private boolean isBlocked() {
1201         LWWindowPeer blocker = (peer != null) ? peer.getBlocker() : null;
1202         return (blocker != null);
1203     }
1204 
1205     /*
1206      * An utility method for the support of the auto request focus.
1207      * Updates the focusable state of the window under certain
1208      * circumstances.
1209      */
1210     private void updateFocusabilityForAutoRequestFocus(boolean isFocusable) {
1211         if (target.isAutoRequestFocus() || !isNativelyFocusableWindow()) return;
1212         setStyleBits(SHOULD_BECOME_KEY | SHOULD_BECOME_MAIN, isFocusable); // set both bits at once
1213     }
1214 
1215     private boolean checkBlockingAndOrder() {
1216         LWWindowPeer blocker = (peer == null)? null : peer.getBlocker();
1217         if (blocker == null) {
1218             return false;
1219         }
1220 
1221         if (blocker instanceof CPrinterDialogPeer) {
1222             return true;
1223         }
1224 
1225         CPlatformWindow pWindow = (CPlatformWindow)blocker.getPlatformWindow();
1226 
1227         pWindow.orderAboveSiblings();
1228 
1229         pWindow.execute(ptr -> {
1230             CWrapper.NSWindow.orderFrontRegardless(ptr);
1231             CWrapper.NSWindow.makeKeyAndOrderFront(ptr);
1232             CWrapper.NSWindow.makeMainWindow(ptr);
1233         });
1234         return true;
1235     }
1236 
1237     private boolean isIconified() {
1238         boolean isIconified = false;
1239         if (target instanceof Frame) {
1240             int state = ((Frame)target).getExtendedState();
1241             if ((state & Frame.ICONIFIED) != 0) {
1242                 isIconified = true;
1243             }
1244         }
1245         return isIconifyAnimationActive || isIconified;
1246     }
1247 
1248     private boolean isOneOfOwnersOrSelf(CPlatformWindow window) {
1249         while (window != null) {
1250             if (this == window) {
1251                 return true;
1252             }
1253             window = window.owner;
1254         }
1255         return false;
1256     }
1257 
1258     private CPlatformWindow getRootOwner() {
1259         CPlatformWindow rootOwner = this;
1260         while (rootOwner.owner != null) {
1261             rootOwner = rootOwner.owner;
1262         }
1263         return rootOwner;
1264     }
1265 
1266     private void orderAboveSiblings() {
1267         CPlatformWindow rootOwner = getRootOwner();
1268 
1269         // Do not order child windows of iconified owner.
1270         if (!rootOwner.isIconified()) {
1271             final WindowAccessor windowAccessor = AWTAccessor.getWindowAccessor();
1272             Window[] windows = windowAccessor.getOwnedWindows(rootOwner.target);
1273 
1274             // No need to order windows if it doesn't own other windows and hence return
1275             if (windows.length == 0) {
1276                 return;
1277             }
1278 
1279             // Recursively pop up the windows from the very bottom, (i.e. root owner) so that
1280             // the windows are ordered above their nearest owner; ancestors of the window,
1281             // which is going to become 'main window', are placed above their siblings.
1282             if (rootOwner.isVisible()) {
1283                 rootOwner.execute(CWrapper.NSWindow::orderFront);
1284             }
1285 
1286             // Order child windows.
1287             orderAboveSiblingsImpl(windows);
1288         }
1289     }
1290 
1291     private void orderAboveSiblingsImpl(Window[] windows) {
1292         ArrayList<Window> childWindows = new ArrayList<Window>();
1293 
1294         final ComponentAccessor componentAccessor = AWTAccessor.getComponentAccessor();
1295         final WindowAccessor windowAccessor = AWTAccessor.getWindowAccessor();
1296         Arrays.sort(windows, siblingsComparator);
1297         // Go through the list of windows and perform ordering.
1298         CPlatformWindow pwUnder = null;
1299         for (Window w : windows) {
1300             boolean iconified = false;
1301             final Object p = componentAccessor.getPeer(w);
1302             if (p instanceof LWWindowPeer) {
1303                 CPlatformWindow pw = (CPlatformWindow)((LWWindowPeer)p).getPlatformWindow();
1304                 iconified = isIconified();
1305                 if (pw != null && pw.isVisible() && !iconified) {
1306                     // If the window is one of ancestors of 'main window' or is going to become main by itself,
1307                     // the window should be ordered above its siblings; otherwise the window is just ordered
1308                     // above its nearest parent.
1309                     if (pw.isOneOfOwnersOrSelf(this)) {
1310                         pw.execute(CWrapper.NSWindow::orderFront);
1311                     } else {
1312                         if (pwUnder == null) {
1313                             pwUnder = pw.owner;
1314                         }
1315                         pwUnder.execute(underPtr -> {
1316                             pw.execute(ptr -> {
1317                                 CWrapper.NSWindow.orderWindow(ptr, CWrapper.NSWindow.NSWindowAbove, underPtr);
1318                             });
1319                         });
1320                         pwUnder = pw;
1321                     }
1322                     pw.applyWindowLevel(w);
1323                 }
1324             }
1325             // Retrieve the child windows for each window from the list except iconified ones
1326             // and store them for future use.
1327             // Note: we collect data about child windows even for invisible owners, since they may have
1328             // visible children.
1329             if (!iconified) {
1330                 childWindows.addAll(Arrays.asList(windowAccessor.getOwnedWindows(w)));
1331             }
1332         }
1333         // If some windows, which have just been ordered, have any child windows, let's start new iteration
1334         // and order these child windows.
1335         if (!childWindows.isEmpty()) {
1336             orderAboveSiblingsImpl(childWindows.toArray(new Window[0]));
1337         }
1338     }
1339 
1340     protected void applyWindowLevel(Window target) {
1341         if (target.isAlwaysOnTop() && target.getType() != Window.Type.POPUP) {
1342             execute(ptr->CWrapper.NSWindow.setLevel(ptr, CWrapper.NSWindow.NSFloatingWindowLevel));
1343         } else if (target.getType() == Window.Type.POPUP) {
1344             execute(ptr->CWrapper.NSWindow.setLevel(ptr, CWrapper.NSWindow.NSPopUpMenuWindowLevel));
1345         }
1346     }
1347 
1348     private Window getOwnerFrameOrDialog(Window window) {
1349         Window owner = window.getOwner();
1350         while (owner != null && !(owner instanceof Frame || owner instanceof Dialog)) {
1351             owner = owner.getOwner();
1352         }
1353         return owner;
1354     }
1355 
1356     private boolean isSimpleWindowOwnedByEmbeddedFrame() {
1357         if (peer != null && peer.isSimpleWindow()) {
1358             return (getOwnerFrameOrDialog(target) instanceof CEmbeddedFrame);
1359         }
1360         return false;
1361     }
1362 
1363     private boolean isTargetResizable() {
1364         if (target instanceof Frame) {
1365             return ((Frame)target).isResizable() && !isMaximizedBoth();
1366         } else if (target instanceof Dialog) {
1367             return ((Dialog)target).isResizable();
1368         }
1369         return false;
1370     }
1371 
1372     private void updateResizableAndMaximizeState(boolean maximizeState) {
1373         maximizedBothState = maximizeState;
1374         setResizable(!maximizeState);
1375     }
1376 
1377     private boolean isMaximizedBoth() {
1378         return maximizedBothState;
1379     }
1380 
1381     private void setFrameResizibilityChanged(boolean resize) {
1382         frameResizibilityChanged = resize;
1383     }
1384 
1385     private boolean isFrameResizibilityChanged() {
1386         return frameResizibilityChanged;
1387     }
1388 
1389     // ----------------------------------------------------------------------
1390     //                          NATIVE CALLBACKS
1391     // ----------------------------------------------------------------------
1392 
1393     private void windowWillMiniaturize() {
1394         isIconifyAnimationActive = true;
1395     }
1396 
1397     private void windowDidBecomeMain() {
1398         lastBecomeMainTime = System.currentTimeMillis();
1399         if (checkBlockingAndOrder()) return;
1400         // If it's not blocked, make sure it's above its siblings
1401         orderAboveSiblings();
1402     }
1403 
1404     private void windowWillEnterFullScreen() {
1405         isFullScreenAnimationOn = true;
1406     }
1407 
1408     private void windowDidEnterFullScreen() {
1409         isInFullScreen = true;
1410         isFullScreenAnimationOn = false;
1411     }
1412 
1413     private void windowWillExitFullScreen() {
1414         isFullScreenAnimationOn = true;
1415     }
1416 
1417     private void windowDidExitFullScreen() {
1418         isInFullScreen = false;
1419         isFullScreenAnimationOn = false;
1420     }
1421 }