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