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