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