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