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