1 /* 2 * Copyright (c) 2011, 2014, 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; 27 28 import java.awt.*; 29 import java.awt.event.*; 30 import java.awt.peer.*; 31 import java.util.List; 32 33 import javax.swing.*; 34 35 import sun.awt.*; 36 import sun.java2d.*; 37 import sun.java2d.loops.Blit; 38 import sun.java2d.loops.CompositeType; 39 import sun.java2d.pipe.Region; 40 import sun.util.logging.PlatformLogger; 41 42 public class LWWindowPeer 43 extends LWContainerPeer<Window, JComponent> 44 implements FramePeer, DialogPeer, FullScreenCapable, DisplayChangedListener, PlatformEventNotifier 45 { 46 public enum PeerType { 47 SIMPLEWINDOW, 48 FRAME, 49 DIALOG, 50 EMBEDDED_FRAME, 51 VIEW_EMBEDDED_FRAME, 52 LW_FRAME 53 } 54 55 private static final PlatformLogger focusLog = PlatformLogger.getLogger("sun.lwawt.focus.LWWindowPeer"); 56 57 private final PlatformWindow platformWindow; 58 59 private static final int MINIMUM_WIDTH = 1; 60 private static final int MINIMUM_HEIGHT = 1; 61 62 private Insets insets = new Insets(0, 0, 0, 0); 63 64 private GraphicsDevice graphicsDevice; 65 private GraphicsConfiguration graphicsConfig; 66 67 private SurfaceData surfaceData; 68 private final Object surfaceDataLock = new Object(); 69 70 private volatile int windowState = Frame.NORMAL; 71 72 // check that the mouse is over the window 73 private volatile boolean isMouseOver = false; 74 75 // A peer where the last mouse event came to. Used by cursor manager to 76 // find the component under cursor 77 private static volatile LWComponentPeer<?, ?> lastCommonMouseEventPeer; 78 79 // A peer where the last mouse event came to. Used to generate 80 // MOUSE_ENTERED/EXITED notifications 81 private volatile LWComponentPeer<?, ?> lastMouseEventPeer; 82 83 // Peers where all dragged/released events should come to, 84 // depending on what mouse button is being dragged according to Cocoa 85 private static final LWComponentPeer<?, ?>[] mouseDownTarget = new LWComponentPeer<?, ?>[3]; 86 87 // A bitmask that indicates what mouse buttons produce MOUSE_CLICKED events 88 // on MOUSE_RELEASE. Click events are only generated if there were no drag 89 // events between MOUSE_PRESSED and MOUSE_RELEASED for particular button 90 private static int mouseClickButtons = 0; 91 92 private volatile boolean isOpaque = true; 93 94 private static final Font DEFAULT_FONT = new Font("Lucida Grande", Font.PLAIN, 13); 95 96 private static LWWindowPeer grabbingWindow; 97 98 private volatile boolean skipNextFocusChange; 99 100 private static final Color nonOpaqueBackground = new Color(0, 0, 0, 0); 101 102 private volatile boolean textured; 103 104 private final PeerType peerType; 105 106 private final SecurityWarningWindow warningWindow; 107 108 private volatile boolean targetFocusable; 109 110 /** 111 * Current modal blocker or null. 112 * 113 * Synchronization: peerTreeLock. 114 */ 115 private LWWindowPeer blocker; 116 117 public LWWindowPeer(Window target, PlatformComponent platformComponent, 118 PlatformWindow platformWindow, PeerType peerType) 119 { 120 super(target, platformComponent); 121 this.platformWindow = platformWindow; 122 this.peerType = peerType; 123 124 Window owner = target.getOwner(); 125 LWWindowPeer ownerPeer = owner == null ? null : 126 (LWWindowPeer) AWTAccessor.getComponentAccessor().getPeer(owner); 127 PlatformWindow ownerDelegate = (ownerPeer != null) ? ownerPeer.getPlatformWindow() : null; 128 129 // The delegate.initialize() needs a non-null GC on X11. 130 GraphicsConfiguration gc = getTarget().getGraphicsConfiguration(); 131 synchronized (getStateLock()) { 132 // graphicsConfig should be updated according to the real window 133 // bounds when the window is shown, see 4868278 134 this.graphicsConfig = gc; 135 } 136 137 if (!target.isFontSet()) { 138 target.setFont(DEFAULT_FONT); 139 } 140 141 if (!target.isBackgroundSet()) { 142 target.setBackground(SystemColor.window); 143 } else { 144 // first we check if user provided alpha for background. This is 145 // similar to what Apple's Java do. 146 // Since JDK7 we should rely on setOpacity() only. 147 // this.opacity = c.getAlpha(); 148 } 149 150 if (!target.isForegroundSet()) { 151 target.setForeground(SystemColor.windowText); 152 // we should not call setForeground because it will call a repaint 153 // which the peer may not be ready to do yet. 154 } 155 156 platformWindow.initialize(target, this, ownerDelegate); 157 158 // Init warning window(for applets) 159 SecurityWarningWindow warn = null; 160 if (target.getWarningString() != null) { 161 // accessSystemTray permission allows to display TrayIcon, TrayIcon tooltip 162 // and TrayIcon balloon windows without a warning window. 163 if (!AWTAccessor.getWindowAccessor().isTrayIconWindow(target)) { 164 LWToolkit toolkit = (LWToolkit)Toolkit.getDefaultToolkit(); 165 warn = toolkit.createSecurityWarning(target, this); 166 } 167 } 168 169 warningWindow = warn; 170 } 171 172 @Override 173 void initializeImpl() { 174 super.initializeImpl(); 175 176 177 if (getTarget() instanceof Frame) { 178 setTitle(((Frame) getTarget()).getTitle()); 179 setState(((Frame) getTarget()).getExtendedState()); 180 } else if (getTarget() instanceof Dialog) { 181 setTitle(((Dialog) getTarget()).getTitle()); 182 } 183 184 updateAlwaysOnTopState(); 185 updateMinimumSize(); 186 187 targetFocusable = getTarget().isFocusableWindow(); 188 189 final Shape shape = getTarget().getShape(); 190 if (shape != null) { 191 applyShape(Region.getInstance(shape, null)); 192 } 193 194 final float opacity = getTarget().getOpacity(); 195 if (opacity < 1.0f) { 196 setOpacity(opacity); 197 } 198 199 setOpaque(getTarget().isOpaque()); 200 201 updateInsets(platformWindow.getInsets()); 202 if (getSurfaceData() == null) { 203 replaceSurfaceData(false); 204 } 205 activateDisplayListener(); 206 } 207 208 // Just a helper method 209 @Override 210 public PlatformWindow getPlatformWindow() { 211 return platformWindow; 212 } 213 214 @Override 215 protected LWWindowPeer getWindowPeerOrSelf() { 216 return this; 217 } 218 219 // ---- PEER METHODS ---- // 220 221 @Override 222 protected void disposeImpl() { 223 deactivateDisplayListener(); 224 SurfaceData oldData = getSurfaceData(); 225 synchronized (surfaceDataLock){ 226 surfaceData = null; 227 } 228 if (oldData != null) { 229 oldData.invalidate(); 230 } 231 if (isGrabbing()) { 232 ungrab(); 233 } 234 if (warningWindow != null) { 235 warningWindow.dispose(); 236 } 237 238 platformWindow.dispose(); 239 super.disposeImpl(); 240 } 241 242 @Override 243 protected void setVisibleImpl(final boolean visible) { 244 if (!visible && warningWindow != null) { 245 warningWindow.setVisible(false, false); 246 } 247 updateFocusableWindowState(); 248 super.setVisibleImpl(visible); 249 // TODO: update graphicsConfig, see 4868278 250 platformWindow.setVisible(visible); 251 if (isSimpleWindow()) { 252 KeyboardFocusManagerPeer kfmPeer = LWKeyboardFocusManagerPeer.getInstance(); 253 if (visible) { 254 if (!getTarget().isAutoRequestFocus()) { 255 return; 256 } else { 257 requestWindowFocus(CausedFocusEvent.Cause.ACTIVATION); 258 } 259 // Focus the owner in case this window is focused. 260 } else if (kfmPeer.getCurrentFocusedWindow() == getTarget()) { 261 // Transfer focus to the owner. 262 LWWindowPeer owner = getOwnerFrameDialog(LWWindowPeer.this); 263 if (owner != null) { 264 owner.requestWindowFocus(CausedFocusEvent.Cause.ACTIVATION); 265 } 266 } 267 } 268 269 } 270 271 @Override 272 public final GraphicsConfiguration getGraphicsConfiguration() { 273 synchronized (getStateLock()) { 274 return graphicsConfig; 275 } 276 } 277 278 @Override 279 public boolean updateGraphicsData(GraphicsConfiguration gc) { 280 setGraphicsConfig(gc); 281 return false; 282 } 283 284 protected final Graphics getOnscreenGraphics(Color fg, Color bg, Font f) { 285 if (getSurfaceData() == null) { 286 return null; 287 } 288 if (fg == null) { 289 fg = SystemColor.windowText; 290 } 291 if (bg == null) { 292 bg = SystemColor.window; 293 } 294 if (f == null) { 295 f = DEFAULT_FONT; 296 } 297 return platformWindow.transformGraphics(new SunGraphics2D(getSurfaceData(), fg, bg, f)); 298 } 299 300 @Override 301 public void setBounds(int x, int y, int w, int h, int op) { 302 303 if((op & NO_EMBEDDED_CHECK) == 0 && getPeerType() == PeerType.VIEW_EMBEDDED_FRAME) { 304 return; 305 } 306 307 if ((op & SET_CLIENT_SIZE) != 0) { 308 // SET_CLIENT_SIZE is only applicable to window peers, so handle it here 309 // instead of pulling 'insets' field up to LWComponentPeer 310 // no need to add insets since Window's notion of width and height includes insets. 311 op &= ~SET_CLIENT_SIZE; 312 op |= SET_SIZE; 313 } 314 315 // Don't post ComponentMoved/Resized and Paint events 316 // until we've got a notification from the delegate 317 Rectangle cb = constrainBounds(x, y, w, h); 318 319 Rectangle newBounds = new Rectangle(getBounds()); 320 if ((op & (SET_LOCATION | SET_BOUNDS)) != 0) { 321 newBounds.x = cb.x; 322 newBounds.y = cb.y; 323 } 324 if ((op & (SET_SIZE | SET_BOUNDS)) != 0) { 325 newBounds.width = cb.width; 326 newBounds.height = cb.height; 327 } 328 // Native system could constraint bounds, so the peer wold be updated in the callback 329 platformWindow.setBounds(newBounds.x, newBounds.y, newBounds.width, newBounds.height); 330 } 331 332 public Rectangle constrainBounds(Rectangle bounds) { 333 return constrainBounds(bounds.x, bounds.y, bounds.width, bounds.height); 334 } 335 336 public Rectangle constrainBounds(int x, int y, int w, int h) { 337 338 if (w < MINIMUM_WIDTH) { 339 w = MINIMUM_WIDTH; 340 } 341 342 if (h < MINIMUM_HEIGHT) { 343 h = MINIMUM_HEIGHT; 344 } 345 346 final int maxW = getLWGC().getMaxTextureWidth(); 347 final int maxH = getLWGC().getMaxTextureHeight(); 348 349 if (w > maxW) { 350 w = maxW; 351 } 352 if (h > maxH) { 353 h = maxH; 354 } 355 356 return new Rectangle(x, y, w, h); 357 } 358 359 @Override 360 public Point getLocationOnScreen() { 361 return platformWindow.getLocationOnScreen(); 362 } 363 364 /** 365 * Overridden from LWContainerPeer to return the correct insets. 366 * Insets are queried from the delegate and are kept up to date by 367 * requiering when needed (i.e. when the window geometry is changed). 368 */ 369 @Override 370 public Insets getInsets() { 371 synchronized (getStateLock()) { 372 return insets; 373 } 374 } 375 376 @Override 377 public FontMetrics getFontMetrics(Font f) { 378 // TODO: check for "use platform metrics" settings 379 return platformWindow.getFontMetrics(f); 380 } 381 382 @Override 383 public void toFront() { 384 platformWindow.toFront(); 385 } 386 387 @Override 388 public void toBack() { 389 platformWindow.toBack(); 390 } 391 392 @Override 393 public void setZOrder(ComponentPeer above) { 394 throw new RuntimeException("not implemented"); 395 } 396 397 @Override 398 public void updateAlwaysOnTopState() { 399 platformWindow.setAlwaysOnTop(getTarget().isAlwaysOnTop()); 400 } 401 402 @Override 403 public void updateFocusableWindowState() { 404 targetFocusable = getTarget().isFocusableWindow(); 405 platformWindow.updateFocusableWindowState(); 406 } 407 408 @Override 409 public void setModalBlocked(Dialog blocker, boolean blocked) { 410 synchronized (getPeerTreeLock()) { 411 ComponentPeer peer = AWTAccessor.getComponentAccessor().getPeer(blocker); 412 if (blocked && (peer instanceof LWWindowPeer)) { 413 this.blocker = (LWWindowPeer) peer; 414 } else { 415 this.blocker = null; 416 } 417 } 418 419 platformWindow.setModalBlocked(blocked); 420 } 421 422 @Override 423 public void updateMinimumSize() { 424 final Dimension min; 425 if (getTarget().isMinimumSizeSet()) { 426 min = getTarget().getMinimumSize(); 427 min.width = Math.max(min.width, MINIMUM_WIDTH); 428 min.height = Math.max(min.height, MINIMUM_HEIGHT); 429 } else { 430 min = new Dimension(MINIMUM_WIDTH, MINIMUM_HEIGHT); 431 } 432 433 final Dimension max; 434 if (getTarget().isMaximumSizeSet()) { 435 max = getTarget().getMaximumSize(); 436 max.width = Math.min(max.width, getLWGC().getMaxTextureWidth()); 437 max.height = Math.min(max.height, getLWGC().getMaxTextureHeight()); 438 } else { 439 max = new Dimension(getLWGC().getMaxTextureWidth(), 440 getLWGC().getMaxTextureHeight()); 441 } 442 443 platformWindow.setSizeConstraints(min.width, min.height, max.width, max.height); 444 } 445 446 @Override 447 public void updateIconImages() { 448 getPlatformWindow().updateIconImages(); 449 } 450 451 @Override 452 public void setBackground(final Color c) { 453 super.setBackground(c); 454 updateOpaque(); 455 } 456 457 @Override 458 public void setOpacity(float opacity) { 459 getPlatformWindow().setOpacity(opacity); 460 repaintPeer(); 461 } 462 463 @Override 464 public final void setOpaque(final boolean isOpaque) { 465 if (this.isOpaque != isOpaque) { 466 this.isOpaque = isOpaque; 467 updateOpaque(); 468 } 469 } 470 471 private void updateOpaque() { 472 getPlatformWindow().setOpaque(!isTranslucent()); 473 replaceSurfaceData(false); 474 repaintPeer(); 475 } 476 477 @Override 478 public void updateWindow() { 479 } 480 481 public final boolean isTextured() { 482 return textured; 483 } 484 485 public final void setTextured(final boolean isTextured) { 486 textured = isTextured; 487 } 488 489 @Override 490 public final boolean isTranslucent() { 491 synchronized (getStateLock()) { 492 /* 493 * Textured window is a special case of translucent window. 494 * The difference is only in nswindow background. So when we set 495 * texture property our peer became fully translucent. It doesn't 496 * fill background, create non opaque backbuffers and layer etc. 497 */ 498 return !isOpaque || isShaped() || isTextured(); 499 } 500 } 501 502 @Override 503 final void applyShapeImpl(final Region shape) { 504 super.applyShapeImpl(shape); 505 updateOpaque(); 506 } 507 508 @Override 509 public void repositionSecurityWarning() { 510 if (warningWindow != null) { 511 AWTAccessor.ComponentAccessor compAccessor = AWTAccessor.getComponentAccessor(); 512 Window target = getTarget(); 513 int x = compAccessor.getX(target); 514 int y = compAccessor.getY(target); 515 int width = compAccessor.getWidth(target); 516 int height = compAccessor.getHeight(target); 517 warningWindow.reposition(x, y, width, height); 518 } 519 } 520 521 // ---- FRAME PEER METHODS ---- // 522 523 @Override // FramePeer and DialogPeer 524 public void setTitle(String title) { 525 platformWindow.setTitle(title == null ? "" : title); 526 } 527 528 @Override 529 public void setMenuBar(MenuBar mb) { 530 platformWindow.setMenuBar(mb); 531 } 532 533 @Override // FramePeer and DialogPeer 534 public void setResizable(boolean resizable) { 535 platformWindow.setResizable(resizable); 536 } 537 538 @Override 539 public void setState(int state) { 540 platformWindow.setWindowState(state); 541 } 542 543 @Override 544 public int getState() { 545 return windowState; 546 } 547 548 @Override 549 public void setMaximizedBounds(Rectangle bounds) { 550 // TODO: not implemented 551 } 552 553 @Override 554 public void setBoundsPrivate(int x, int y, int width, int height) { 555 setBounds(x, y, width, height, SET_BOUNDS | NO_EMBEDDED_CHECK); 556 } 557 558 @Override 559 public Rectangle getBoundsPrivate() { 560 throw new RuntimeException("not implemented"); 561 } 562 563 // ---- DIALOG PEER METHODS ---- // 564 565 @Override 566 public void blockWindows(List<Window> windows) { 567 //TODO: LWX will probably need some collectJavaToplevels to speed this up 568 for (Window w : windows) { 569 WindowPeer wp = 570 (WindowPeer) AWTAccessor.getComponentAccessor().getPeer(w); 571 if (wp != null) { 572 wp.setModalBlocked((Dialog)getTarget(), true); 573 } 574 } 575 } 576 577 // ---- PEER NOTIFICATIONS ---- // 578 579 @Override 580 public void notifyIconify(boolean iconify) { 581 //The toplevel target is Frame and states are applicable to it. 582 //Otherwise, the target is Window and it don't have state property. 583 //Hopefully, no such events are posted in the queue so consider the 584 //target as Frame in all cases. 585 586 // REMIND: should we send it anyway if the state not changed since last 587 // time? 588 WindowEvent iconifyEvent = new WindowEvent(getTarget(), 589 iconify ? WindowEvent.WINDOW_ICONIFIED 590 : WindowEvent.WINDOW_DEICONIFIED); 591 postEvent(iconifyEvent); 592 593 int newWindowState = iconify ? Frame.ICONIFIED : Frame.NORMAL; 594 postWindowStateChangedEvent(newWindowState); 595 596 // REMIND: RepaintManager doesn't repaint iconified windows and 597 // hence ignores any repaint request during deiconification. 598 // So, we need to repaint window explicitly when it becomes normal. 599 if (!iconify) { 600 repaintPeer(); 601 } 602 } 603 604 @Override 605 public void notifyZoom(boolean isZoomed) { 606 int newWindowState = isZoomed ? Frame.MAXIMIZED_BOTH : Frame.NORMAL; 607 postWindowStateChangedEvent(newWindowState); 608 } 609 610 /** 611 * Called by the {@code PlatformWindow} when any part of the window should 612 * be repainted. 613 */ 614 @Override 615 public void notifyExpose(final Rectangle r) { 616 repaintPeer(r); 617 } 618 619 /** 620 * Called by the {@code PlatformWindow} when this window is moved/resized by 621 * user or window insets are changed. There's no notifyReshape() in 622 * LWComponentPeer as the only components which could be resized by user are 623 * top-level windows. 624 */ 625 @Override 626 public void notifyReshape(int x, int y, int w, int h) { 627 Rectangle oldBounds = getBounds(); 628 final boolean invalid = updateInsets(platformWindow.getInsets()); 629 final boolean moved = (x != oldBounds.x) || (y != oldBounds.y); 630 final boolean resized = (w != oldBounds.width) || (h != oldBounds.height); 631 632 // Check if anything changed 633 if (!moved && !resized && !invalid) { 634 return; 635 } 636 // First, update peer's bounds 637 setBounds(x, y, w, h, SET_BOUNDS, false, false); 638 639 // Second, update the graphics config and surface data 640 final boolean isNewDevice = updateGraphicsDevice(); 641 if (resized || isNewDevice) { 642 replaceSurfaceData(); 643 updateMinimumSize(); 644 } 645 646 // Third, COMPONENT_MOVED/COMPONENT_RESIZED/PAINT events 647 if (moved || invalid) { 648 handleMove(x, y, true); 649 } 650 if (resized || invalid || isNewDevice) { 651 handleResize(w, h, true); 652 repaintPeer(); 653 } 654 655 repositionSecurityWarning(); 656 } 657 658 private void clearBackground(final int w, final int h) { 659 final Graphics g = getOnscreenGraphics(getForeground(), getBackground(), 660 getFont()); 661 if (g != null) { 662 try { 663 if (g instanceof Graphics2D) { 664 ((Graphics2D) g).setComposite(AlphaComposite.Src); 665 } 666 if (isTranslucent()) { 667 g.setColor(nonOpaqueBackground); 668 g.fillRect(0, 0, w, h); 669 } 670 if (!isTextured()) { 671 if (g instanceof SunGraphics2D) { 672 ((SunGraphics2D) g).constrain(0, 0, w, h, getRegion()); 673 } 674 g.setColor(getBackground()); 675 g.fillRect(0, 0, w, h); 676 } 677 } finally { 678 g.dispose(); 679 } 680 } 681 } 682 683 @Override 684 public void notifyUpdateCursor() { 685 getLWToolkit().getCursorManager().updateCursorLater(this); 686 } 687 688 @Override 689 public void notifyActivation(boolean activation, LWWindowPeer opposite) { 690 Window oppositeWindow = (opposite == null)? null : opposite.getTarget(); 691 changeFocusedWindow(activation, oppositeWindow); 692 } 693 694 // MouseDown in non-client area 695 @Override 696 public void notifyNCMouseDown() { 697 // Ungrab except for a click on a Dialog with the grabbing owner 698 if (grabbingWindow != null && 699 !grabbingWindow.isOneOfOwnersOf(this)) 700 { 701 grabbingWindow.ungrab(); 702 } 703 } 704 705 // ---- EVENTS ---- // 706 707 /* 708 * Called by the delegate to dispatch the event to Java. Event 709 * coordinates are relative to non-client window are, i.e. the top-left 710 * point of the client area is (insets.top, insets.left). 711 */ 712 @Override 713 public void notifyMouseEvent(int id, long when, int button, 714 int x, int y, int screenX, int screenY, 715 int modifiers, int clickCount, boolean popupTrigger, 716 byte[] bdata) 717 { 718 // TODO: fill "bdata" member of AWTEvent 719 Rectangle r = getBounds(); 720 // findPeerAt() expects parent coordinates 721 LWComponentPeer<?, ?> targetPeer = findPeerAt(r.x + x, r.y + y); 722 723 if (id == MouseEvent.MOUSE_EXITED) { 724 isMouseOver = false; 725 if (lastMouseEventPeer != null) { 726 if (lastMouseEventPeer.isEnabled()) { 727 Point lp = lastMouseEventPeer.windowToLocal(x, y, 728 this); 729 Component target = lastMouseEventPeer.getTarget(); 730 postMouseExitedEvent(target, when, modifiers, lp, 731 screenX, screenY, clickCount, popupTrigger, button); 732 } 733 734 // Sometimes we may get MOUSE_EXITED after lastCommonMouseEventPeer is switched 735 // to a peer from another window. So we must first check if this peer is 736 // the same as lastWindowPeer 737 if (lastCommonMouseEventPeer != null && lastCommonMouseEventPeer.getWindowPeerOrSelf() == this) { 738 lastCommonMouseEventPeer = null; 739 } 740 lastMouseEventPeer = null; 741 } 742 } else if(id == MouseEvent.MOUSE_ENTERED) { 743 isMouseOver = true; 744 if (targetPeer != null) { 745 if (targetPeer.isEnabled()) { 746 Point lp = targetPeer.windowToLocal(x, y, this); 747 Component target = targetPeer.getTarget(); 748 postMouseEnteredEvent(target, when, modifiers, lp, 749 screenX, screenY, clickCount, popupTrigger, button); 750 } 751 lastCommonMouseEventPeer = targetPeer; 752 lastMouseEventPeer = targetPeer; 753 } 754 } else { 755 PlatformWindow topmostPlatforWindow = 756 platformWindow.getTopmostPlatformWindowUnderMouse(); 757 758 LWWindowPeer topmostWindowPeer = 759 topmostPlatforWindow != null ? topmostPlatforWindow.getPeer() : null; 760 761 // topmostWindowPeer == null condition is added for the backward 762 // compatibility with applets. It can be removed when the 763 // getTopmostPlatformWindowUnderMouse() method will be properly 764 // implemented in CPlatformEmbeddedFrame class 765 if (topmostWindowPeer == this || topmostWindowPeer == null) { 766 generateMouseEnterExitEventsForComponents(when, button, x, y, 767 screenX, screenY, modifiers, clickCount, popupTrigger, 768 targetPeer); 769 } else { 770 LWComponentPeer<?, ?> topmostTargetPeer = 771 topmostWindowPeer != null ? topmostWindowPeer.findPeerAt(r.x + x, r.y + y) : null; 772 topmostWindowPeer.generateMouseEnterExitEventsForComponents(when, button, x, y, 773 screenX, screenY, modifiers, clickCount, popupTrigger, 774 topmostTargetPeer); 775 } 776 777 // TODO: fill "bdata" member of AWTEvent 778 779 int eventButtonMask = (button > 0)? MouseEvent.getMaskForButton(button) : 0; 780 int otherButtonsPressed = modifiers & ~eventButtonMask; 781 782 // For pressed/dragged/released events OS X treats other 783 // mouse buttons as if they were BUTTON2, so we do the same 784 int targetIdx = (button > 3) ? MouseEvent.BUTTON2 - 1 : button - 1; 785 786 // MOUSE_ENTERED/EXITED are generated for the components strictly under 787 // mouse even when dragging. That's why we first update lastMouseEventPeer 788 // based on initial targetPeer value and only then recalculate targetPeer 789 // for MOUSE_DRAGGED/RELEASED events 790 if (id == MouseEvent.MOUSE_PRESSED) { 791 792 // Ungrab only if this window is not an owned window of the grabbing one. 793 if (!isGrabbing() && grabbingWindow != null && 794 !grabbingWindow.isOneOfOwnersOf(this)) 795 { 796 grabbingWindow.ungrab(); 797 } 798 if (otherButtonsPressed == 0) { 799 mouseClickButtons = eventButtonMask; 800 } else { 801 mouseClickButtons |= eventButtonMask; 802 } 803 804 // The window should be focused on mouse click. If it gets activated by the native platform, 805 // this request will be no op. It will take effect when: 806 // 1. A simple not focused window is clicked. 807 // 2. An active but not focused owner frame/dialog is clicked. 808 // The mouse event then will trigger a focus request "in window" to the component, so the window 809 // should gain focus before. 810 requestWindowFocus(CausedFocusEvent.Cause.MOUSE_EVENT); 811 812 mouseDownTarget[targetIdx] = targetPeer; 813 } else if (id == MouseEvent.MOUSE_DRAGGED) { 814 // Cocoa dragged event has the information about which mouse 815 // button is being dragged. Use it to determine the peer that 816 // should receive the dragged event. 817 targetPeer = mouseDownTarget[targetIdx]; 818 mouseClickButtons &= ~modifiers; 819 } else if (id == MouseEvent.MOUSE_RELEASED) { 820 // TODO: currently, mouse released event goes to the same component 821 // that received corresponding mouse pressed event. For most cases, 822 // it's OK, however, we need to make sure that our behavior is consistent 823 // with 1.6 for cases where component in question have been 824 // hidden/removed in between of mouse pressed/released events. 825 targetPeer = mouseDownTarget[targetIdx]; 826 827 if ((modifiers & eventButtonMask) == 0) { 828 mouseDownTarget[targetIdx] = null; 829 } 830 831 // mouseClickButtons is updated below, after MOUSE_CLICK is sent 832 } 833 834 if (targetPeer == null) { 835 //TODO This can happen if this window is invisible. this is correct behavior in this case? 836 targetPeer = this; 837 } 838 839 840 Point lp = targetPeer.windowToLocal(x, y, this); 841 if (targetPeer.isEnabled()) { 842 MouseEvent event = new MouseEvent(targetPeer.getTarget(), id, 843 when, modifiers, lp.x, lp.y, 844 screenX, screenY, clickCount, 845 popupTrigger, button); 846 postEvent(event); 847 } 848 849 if (id == MouseEvent.MOUSE_RELEASED) { 850 if ((mouseClickButtons & eventButtonMask) != 0 851 && targetPeer.isEnabled()) { 852 postEvent(new MouseEvent(targetPeer.getTarget(), 853 MouseEvent.MOUSE_CLICKED, 854 when, modifiers, 855 lp.x, lp.y, screenX, screenY, 856 clickCount, popupTrigger, button)); 857 } 858 mouseClickButtons &= ~eventButtonMask; 859 } 860 } 861 notifyUpdateCursor(); 862 } 863 864 private void generateMouseEnterExitEventsForComponents(long when, 865 int button, int x, int y, int screenX, int screenY, 866 int modifiers, int clickCount, boolean popupTrigger, 867 final LWComponentPeer<?, ?> targetPeer) { 868 869 if (!isMouseOver || targetPeer == lastMouseEventPeer) { 870 return; 871 } 872 873 // Generate Mouse Exit for components 874 if (lastMouseEventPeer != null && lastMouseEventPeer.isEnabled()) { 875 Point oldp = lastMouseEventPeer.windowToLocal(x, y, this); 876 Component target = lastMouseEventPeer.getTarget(); 877 postMouseExitedEvent(target, when, modifiers, oldp, screenX, screenY, 878 clickCount, popupTrigger, button); 879 } 880 lastCommonMouseEventPeer = targetPeer; 881 lastMouseEventPeer = targetPeer; 882 883 // Generate Mouse Enter for components 884 if (targetPeer != null && targetPeer.isEnabled()) { 885 Point newp = targetPeer.windowToLocal(x, y, this); 886 Component target = targetPeer.getTarget(); 887 postMouseEnteredEvent(target, when, modifiers, newp, screenX, screenY, clickCount, popupTrigger, button); 888 } 889 } 890 891 private void postMouseEnteredEvent(Component target, long when, int modifiers, 892 Point loc, int xAbs, int yAbs, 893 int clickCount, boolean popupTrigger, int button) { 894 895 updateSecurityWarningVisibility(); 896 897 postEvent(new MouseEvent(target, 898 MouseEvent.MOUSE_ENTERED, 899 when, modifiers, 900 loc.x, loc.y, xAbs, yAbs, 901 clickCount, popupTrigger, button)); 902 } 903 904 private void postMouseExitedEvent(Component target, long when, int modifiers, 905 Point loc, int xAbs, int yAbs, 906 int clickCount, boolean popupTrigger, int button) { 907 908 updateSecurityWarningVisibility(); 909 910 postEvent(new MouseEvent(target, 911 MouseEvent.MOUSE_EXITED, 912 when, modifiers, 913 loc.x, loc.y, xAbs, yAbs, 914 clickCount, popupTrigger, button)); 915 } 916 917 @Override 918 public void notifyMouseWheelEvent(long when, int x, int y, int modifiers, 919 int scrollType, int scrollAmount, 920 int wheelRotation, double preciseWheelRotation, 921 byte[] bdata) 922 { 923 // TODO: could we just use the last mouse event target here? 924 Rectangle r = getBounds(); 925 // findPeerAt() expects parent coordinates 926 final LWComponentPeer<?, ?> targetPeer = findPeerAt(r.x + x, r.y + y); 927 if (targetPeer == null || !targetPeer.isEnabled()) { 928 return; 929 } 930 931 Point lp = targetPeer.windowToLocal(x, y, this); 932 // TODO: fill "bdata" member of AWTEvent 933 // TODO: screenX/screenY 934 postEvent(new MouseWheelEvent(targetPeer.getTarget(), 935 MouseEvent.MOUSE_WHEEL, 936 when, modifiers, 937 lp.x, lp.y, 938 0, 0, /* screenX, Y */ 939 0 /* clickCount */, false /* popupTrigger */, 940 scrollType, scrollAmount, 941 wheelRotation, preciseWheelRotation)); 942 } 943 944 /* 945 * Called by the delegate when a key is pressed. 946 */ 947 @Override 948 public void notifyKeyEvent(int id, long when, int modifiers, 949 int keyCode, char keyChar, int keyLocation) 950 { 951 LWKeyboardFocusManagerPeer kfmPeer = LWKeyboardFocusManagerPeer.getInstance(); 952 Component focusOwner = kfmPeer.getCurrentFocusOwner(); 953 954 if (focusOwner == null) { 955 focusOwner = kfmPeer.getCurrentFocusedWindow(); 956 if (focusOwner == null) { 957 focusOwner = this.getTarget(); 958 } 959 } 960 961 KeyEvent keyEvent = new KeyEvent(focusOwner, id, when, modifiers, 962 keyCode, keyChar, keyLocation); 963 AWTAccessor.getKeyEventAccessor().setExtendedKeyCode(keyEvent, 964 (keyChar == KeyEvent.CHAR_UNDEFINED) ? keyCode 965 : ExtendedKeyCodes.getExtendedKeyCodeForChar(keyChar)); 966 postEvent(keyEvent); 967 } 968 969 // ---- UTILITY METHODS ---- // 970 971 private void activateDisplayListener() { 972 final GraphicsEnvironment ge = 973 GraphicsEnvironment.getLocalGraphicsEnvironment(); 974 ((SunGraphicsEnvironment) ge).addDisplayChangedListener(this); 975 } 976 977 private void deactivateDisplayListener() { 978 final GraphicsEnvironment ge = 979 GraphicsEnvironment.getLocalGraphicsEnvironment(); 980 ((SunGraphicsEnvironment) ge).removeDisplayChangedListener(this); 981 } 982 983 private void postWindowStateChangedEvent(int newWindowState) { 984 if (getTarget() instanceof Frame) { 985 AWTAccessor.getFrameAccessor().setExtendedState( 986 (Frame)getTarget(), newWindowState); 987 } 988 989 WindowEvent stateChangedEvent = new WindowEvent(getTarget(), 990 WindowEvent.WINDOW_STATE_CHANGED, 991 windowState, newWindowState); 992 postEvent(stateChangedEvent); 993 windowState = newWindowState; 994 995 updateSecurityWarningVisibility(); 996 } 997 998 private static int getGraphicsConfigScreen(GraphicsConfiguration gc) { 999 // TODO: this method can be implemented in a more 1000 // efficient way by forwarding to the delegate 1001 GraphicsDevice gd = gc.getDevice(); 1002 GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); 1003 GraphicsDevice[] gds = ge.getScreenDevices(); 1004 for (int i = 0; i < gds.length; i++) { 1005 if (gds[i] == gd) { 1006 return i; 1007 } 1008 } 1009 // Should never happen if gc is a screen device config 1010 return 0; 1011 } 1012 1013 /* 1014 * This method is called when window's graphics config is changed from 1015 * the app code (e.g. when the window is made non-opaque) or when 1016 * the window is moved to another screen by user. 1017 * 1018 * Returns true if the graphics config has been changed, false otherwise. 1019 */ 1020 private boolean setGraphicsConfig(GraphicsConfiguration gc) { 1021 synchronized (getStateLock()) { 1022 if (graphicsConfig == gc) { 1023 return false; 1024 } 1025 // If window's graphics config is changed from the app code, the 1026 // config correspond to the same device as before; when the window 1027 // is moved by user, graphicsDevice is updated in notifyReshape(). 1028 // In either case, there's nothing to do with screenOn here 1029 graphicsConfig = gc; 1030 } 1031 // SurfaceData is replaced later in updateGraphicsData() 1032 return true; 1033 } 1034 1035 /** 1036 * Returns true if the GraphicsDevice has been changed, false otherwise. 1037 */ 1038 public boolean updateGraphicsDevice() { 1039 GraphicsDevice newGraphicsDevice = platformWindow.getGraphicsDevice(); 1040 synchronized (getStateLock()) { 1041 if (graphicsDevice == newGraphicsDevice) { 1042 return false; 1043 } 1044 graphicsDevice = newGraphicsDevice; 1045 } 1046 1047 final GraphicsConfiguration newGC = newGraphicsDevice.getDefaultConfiguration(); 1048 1049 if (!setGraphicsConfig(newGC)) return false; 1050 1051 SunToolkit.executeOnEventHandlerThread(getTarget(), new Runnable() { 1052 public void run() { 1053 AWTAccessor.getComponentAccessor().setGraphicsConfiguration(getTarget(), newGC); 1054 } 1055 }); 1056 return true; 1057 } 1058 1059 @Override 1060 public final void displayChanged() { 1061 if (updateGraphicsDevice()) { 1062 updateMinimumSize(); 1063 } 1064 // Replace surface unconditionally, because internal state of the 1065 // GraphicsDevice could be changed. 1066 replaceSurfaceData(); 1067 repaintPeer(); 1068 } 1069 1070 @Override 1071 public final void paletteChanged() { 1072 // components do not need to react to this event. 1073 } 1074 1075 /* 1076 * May be called by delegate to provide SD to Java2D code. 1077 */ 1078 public SurfaceData getSurfaceData() { 1079 synchronized (surfaceDataLock) { 1080 return surfaceData; 1081 } 1082 } 1083 1084 private void replaceSurfaceData() { 1085 replaceSurfaceData(true); 1086 } 1087 1088 private void replaceSurfaceData(final boolean blit) { 1089 synchronized (surfaceDataLock) { 1090 final SurfaceData oldData = getSurfaceData(); 1091 surfaceData = platformWindow.replaceSurfaceData(); 1092 final Rectangle size = getSize(); 1093 if (getSurfaceData() != null && oldData != getSurfaceData()) { 1094 clearBackground(size.width, size.height); 1095 } 1096 1097 if (blit) { 1098 blitSurfaceData(oldData, getSurfaceData()); 1099 } 1100 1101 if (oldData != null && oldData != getSurfaceData()) { 1102 // TODO: drop oldData for D3D/WGL pipelines 1103 // This can only happen when this peer is being created 1104 oldData.flush(); 1105 } 1106 } 1107 flushOnscreenGraphics(); 1108 } 1109 1110 private void blitSurfaceData(final SurfaceData src, final SurfaceData dst) { 1111 //TODO blit. proof-of-concept 1112 if (src != dst && src != null && dst != null 1113 && !(dst instanceof NullSurfaceData) 1114 && !(src instanceof NullSurfaceData) 1115 && src.getSurfaceType().equals(dst.getSurfaceType()) 1116 && src.getDefaultScale() == dst.getDefaultScale()) { 1117 final Rectangle size = src.getBounds(); 1118 final Blit blit = Blit.locate(src.getSurfaceType(), 1119 CompositeType.Src, 1120 dst.getSurfaceType()); 1121 if (blit != null) { 1122 blit.Blit(src, dst, AlphaComposite.Src, null, 0, 0, 0, 0, 1123 size.width, size.height); 1124 } 1125 } 1126 } 1127 1128 /** 1129 * Request the window insets from the delegate and compares it with the 1130 * current one. This method is mostly called by the delegate, e.g. when the 1131 * window state is changed and insets should be recalculated. 1132 * <p/> 1133 * This method may be called on the toolkit thread. 1134 */ 1135 public final boolean updateInsets(final Insets newInsets) { 1136 synchronized (getStateLock()) { 1137 if (insets.equals(newInsets)) { 1138 return false; 1139 } 1140 insets = newInsets; 1141 } 1142 return true; 1143 } 1144 1145 public static LWWindowPeer getWindowUnderCursor() { 1146 return lastCommonMouseEventPeer != null ? lastCommonMouseEventPeer.getWindowPeerOrSelf() : null; 1147 } 1148 1149 public static LWComponentPeer<?, ?> getPeerUnderCursor() { 1150 return lastCommonMouseEventPeer; 1151 } 1152 1153 /* 1154 * Requests platform to set native focus on a frame/dialog. 1155 * In case of a simple window, triggers appropriate java focus change. 1156 */ 1157 public boolean requestWindowFocus(CausedFocusEvent.Cause cause) { 1158 if (focusLog.isLoggable(PlatformLogger.Level.FINE)) { 1159 focusLog.fine("requesting native focus to " + this); 1160 } 1161 1162 if (!focusAllowedFor()) { 1163 focusLog.fine("focus is not allowed"); 1164 return false; 1165 } 1166 1167 if (platformWindow.rejectFocusRequest(cause)) { 1168 return false; 1169 } 1170 1171 AppContext targetAppContext = AWTAccessor.getComponentAccessor().getAppContext(getTarget()); 1172 KeyboardFocusManager kfm = AWTAccessor.getKeyboardFocusManagerAccessor() 1173 .getCurrentKeyboardFocusManager(targetAppContext); 1174 Window currentActive = kfm.getActiveWindow(); 1175 1176 1177 Window opposite = LWKeyboardFocusManagerPeer.getInstance(). 1178 getCurrentFocusedWindow(); 1179 1180 // Make the owner active window. 1181 if (isSimpleWindow()) { 1182 LWWindowPeer owner = getOwnerFrameDialog(this); 1183 1184 // If owner is not natively active, request native 1185 // activation on it w/o sending events up to java. 1186 if (owner != null && !owner.platformWindow.isActive()) { 1187 if (focusLog.isLoggable(PlatformLogger.Level.FINE)) { 1188 focusLog.fine("requesting native focus to the owner " + owner); 1189 } 1190 LWWindowPeer currentActivePeer = currentActive == null ? null : 1191 (LWWindowPeer) AWTAccessor.getComponentAccessor().getPeer( 1192 currentActive); 1193 1194 // Ensure the opposite is natively active and suppress sending events. 1195 if (currentActivePeer != null && currentActivePeer.platformWindow.isActive()) { 1196 if (focusLog.isLoggable(PlatformLogger.Level.FINE)) { 1197 focusLog.fine("the opposite is " + currentActivePeer); 1198 } 1199 currentActivePeer.skipNextFocusChange = true; 1200 } 1201 owner.skipNextFocusChange = true; 1202 1203 owner.platformWindow.requestWindowFocus(); 1204 } 1205 1206 // DKFM will synthesize all the focus/activation events correctly. 1207 changeFocusedWindow(true, opposite); 1208 return true; 1209 1210 // In case the toplevel is active but not focused, change focus directly, 1211 // as requesting native focus on it will not have effect. 1212 } else if (getTarget() == currentActive && !getTarget().hasFocus()) { 1213 1214 changeFocusedWindow(true, opposite); 1215 return true; 1216 } 1217 1218 return platformWindow.requestWindowFocus(); 1219 } 1220 1221 protected boolean focusAllowedFor() { 1222 Window window = getTarget(); 1223 // TODO: check if modal blocked 1224 return window.isVisible() && window.isEnabled() && isFocusableWindow(); 1225 } 1226 1227 protected boolean isTargetFocusable() { 1228 return targetFocusable; 1229 } 1230 1231 private boolean isFocusableWindow() { 1232 boolean focusable = isTargetFocusable(); 1233 if (isSimpleWindow()) { 1234 LWWindowPeer ownerPeer = getOwnerFrameDialog(this); 1235 if (ownerPeer == null) { 1236 return false; 1237 } 1238 return focusable && ownerPeer.isTargetFocusable(); 1239 } 1240 return focusable; 1241 } 1242 1243 public boolean isSimpleWindow() { 1244 Window window = getTarget(); 1245 return !(window instanceof Dialog || window instanceof Frame); 1246 } 1247 1248 @Override 1249 public void emulateActivation(boolean activate) { 1250 changeFocusedWindow(activate, null); 1251 } 1252 1253 private boolean isOneOfOwnersOf(LWWindowPeer peer) { 1254 Window owner = (peer != null ? peer.getTarget().getOwner() : null); 1255 while (owner != null) { 1256 if ((LWWindowPeer)owner.getPeer() == this) { 1257 return true; 1258 } 1259 owner = owner.getOwner(); 1260 } 1261 return false; 1262 } 1263 1264 /* 1265 * Changes focused window on java level. 1266 */ 1267 protected void changeFocusedWindow(boolean becomesFocused, Window opposite) { 1268 if (focusLog.isLoggable(PlatformLogger.Level.FINE)) { 1269 focusLog.fine((becomesFocused?"gaining":"loosing") + " focus window: " + this); 1270 } 1271 if (skipNextFocusChange) { 1272 focusLog.fine("skipping focus change"); 1273 skipNextFocusChange = false; 1274 return; 1275 } 1276 if (!isFocusableWindow() && becomesFocused) { 1277 focusLog.fine("the window is not focusable"); 1278 return; 1279 } 1280 if (becomesFocused) { 1281 synchronized (getPeerTreeLock()) { 1282 if (blocker != null) { 1283 if (focusLog.isLoggable(PlatformLogger.Level.FINEST)) { 1284 focusLog.finest("the window is blocked by " + blocker); 1285 } 1286 return; 1287 } 1288 } 1289 } 1290 1291 // Note, the method is not called: 1292 // - when the opposite (gaining focus) window is an owned/owner window. 1293 // - for a simple window in any case. 1294 if (!becomesFocused && 1295 (isGrabbing() || this.isOneOfOwnersOf(grabbingWindow))) 1296 { 1297 if (focusLog.isLoggable(PlatformLogger.Level.FINE)) { 1298 focusLog.fine("ungrabbing on " + grabbingWindow); 1299 } 1300 // ungrab a simple window if its owner looses activation. 1301 grabbingWindow.ungrab(); 1302 } 1303 1304 KeyboardFocusManagerPeer kfmPeer = LWKeyboardFocusManagerPeer.getInstance(); 1305 kfmPeer.setCurrentFocusedWindow(becomesFocused ? getTarget() : null); 1306 1307 int eventID = becomesFocused ? WindowEvent.WINDOW_GAINED_FOCUS : WindowEvent.WINDOW_LOST_FOCUS; 1308 WindowEvent windowEvent = new TimedWindowEvent(getTarget(), eventID, opposite, System.currentTimeMillis()); 1309 1310 // TODO: wrap in SequencedEvent 1311 postEvent(windowEvent); 1312 } 1313 1314 /* 1315 * Retrieves the owner of the peer. 1316 * Note: this method returns the owner which can be activated, (i.e. the instance 1317 * of Frame or Dialog may be returned). 1318 */ 1319 static LWWindowPeer getOwnerFrameDialog(LWWindowPeer peer) { 1320 Window owner = (peer != null ? peer.getTarget().getOwner() : null); 1321 while (owner != null && !(owner instanceof Frame || owner instanceof Dialog)) { 1322 owner = owner.getOwner(); 1323 } 1324 return owner == null ? null : 1325 (LWWindowPeer) AWTAccessor.getComponentAccessor().getPeer(owner); 1326 } 1327 1328 /** 1329 * Returns the foremost modal blocker of this window, or null. 1330 */ 1331 public LWWindowPeer getBlocker() { 1332 synchronized (getPeerTreeLock()) { 1333 LWWindowPeer blocker = this.blocker; 1334 if (blocker == null) { 1335 return null; 1336 } 1337 while (blocker.blocker != null) { 1338 blocker = blocker.blocker; 1339 } 1340 return blocker; 1341 } 1342 } 1343 1344 @Override 1345 public void enterFullScreenMode() { 1346 platformWindow.enterFullScreenMode(); 1347 updateSecurityWarningVisibility(); 1348 } 1349 1350 @Override 1351 public void exitFullScreenMode() { 1352 platformWindow.exitFullScreenMode(); 1353 updateSecurityWarningVisibility(); 1354 } 1355 1356 public long getLayerPtr() { 1357 return getPlatformWindow().getLayerPtr(); 1358 } 1359 1360 void grab() { 1361 if (grabbingWindow != null && !isGrabbing()) { 1362 grabbingWindow.ungrab(); 1363 } 1364 grabbingWindow = this; 1365 } 1366 1367 final void ungrab(boolean doPost) { 1368 if (isGrabbing()) { 1369 grabbingWindow = null; 1370 if (doPost) { 1371 postEvent(new UngrabEvent(getTarget())); 1372 } 1373 } 1374 } 1375 1376 void ungrab() { 1377 ungrab(true); 1378 } 1379 1380 private boolean isGrabbing() { 1381 return this == grabbingWindow; 1382 } 1383 1384 public PeerType getPeerType() { 1385 return peerType; 1386 } 1387 1388 public void updateSecurityWarningVisibility() { 1389 if (warningWindow == null) { 1390 return; 1391 } 1392 1393 if (!isVisible()) { 1394 return; // The warning window should already be hidden. 1395 } 1396 1397 boolean show = false; 1398 1399 if (!platformWindow.isFullScreenMode()) { 1400 if (isVisible()) { 1401 if (LWKeyboardFocusManagerPeer.getInstance().getCurrentFocusedWindow() == 1402 getTarget()) { 1403 show = true; 1404 } 1405 1406 if (platformWindow.isUnderMouse() || warningWindow.isUnderMouse()) { 1407 show = true; 1408 } 1409 } 1410 } 1411 1412 warningWindow.setVisible(show, true); 1413 } 1414 1415 @Override 1416 public String toString() { 1417 return super.toString() + " [target is " + getTarget() + "]"; 1418 } 1419 }