1 /* 2 * Copyright (c) 1996, 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 package sun.awt.windows; 26 27 import java.awt.*; 28 import java.awt.event.*; 29 import java.awt.image.*; 30 import java.awt.peer.*; 31 32 import java.beans.*; 33 34 import java.util.*; 35 import java.util.List; 36 import sun.util.logging.PlatformLogger; 37 import java.awt.geom.AffineTransform; 38 import sun.awt.*; 39 40 import sun.java2d.pipe.Region; 41 42 public class WWindowPeer extends WPanelPeer implements WindowPeer, 43 DisplayChangedListener 44 { 45 46 private static final PlatformLogger log = PlatformLogger.getLogger("sun.awt.windows.WWindowPeer"); 47 private static final PlatformLogger screenLog = PlatformLogger.getLogger("sun.awt.windows.screen.WWindowPeer"); 48 49 // we can't use WDialogPeer as blocker may be an instance of WPrintDialogPeer that 50 // extends WWindowPeer, not WDialogPeer 51 private WWindowPeer modalBlocker = null; 52 53 private boolean isOpaque; 54 55 private TranslucentWindowPainter painter; 56 57 /* 58 * A key used for storing a list of active windows in AppContext. The value 59 * is a list of windows, sorted by the time of activation: later a window is 60 * activated, greater its index is in the list. 61 */ 62 private static final StringBuffer ACTIVE_WINDOWS_KEY = 63 new StringBuffer("active_windows_list"); 64 65 /* 66 * Listener for 'activeWindow' KFM property changes. It is added to each 67 * AppContext KFM. See ActiveWindowListener inner class below. 68 */ 69 private static PropertyChangeListener activeWindowListener = 70 new ActiveWindowListener(); 71 72 /* 73 * The object is a listener for the AppContext.GUI_DISPOSED property. 74 */ 75 private static final PropertyChangeListener guiDisposedListener = 76 new GuiDisposedListener(); 77 78 /* 79 * Called (on the Toolkit thread) before the appropriate 80 * WindowStateEvent is posted to the EventQueue. 81 */ 82 private WindowListener windowListener; 83 84 /** 85 * Initialize JNI field IDs 86 */ 87 private static native void initIDs(); 88 static { 89 initIDs(); 90 } 91 92 // WComponentPeer overrides 93 @Override 94 @SuppressWarnings("unchecked") 95 protected void disposeImpl() { 96 AppContext appContext = SunToolkit.targetToAppContext(target); 97 synchronized (appContext) { 98 List<WWindowPeer> l = (List<WWindowPeer>)appContext.get(ACTIVE_WINDOWS_KEY); 99 if (l != null) { 100 l.remove(this); 101 } 102 } 103 104 // Remove ourself from the Map of DisplayChangeListeners 105 GraphicsConfiguration gc = getGraphicsConfiguration(); 106 ((Win32GraphicsDevice)gc.getDevice()).removeDisplayChangedListener(this); 107 108 synchronized (getStateLock()) { 109 TranslucentWindowPainter currentPainter = painter; 110 if (currentPainter != null) { 111 currentPainter.flush(); 112 // don't set the current one to null here; reduces the chances of 113 // MT issues (like NPEs) 114 } 115 } 116 117 super.disposeImpl(); 118 } 119 120 // WindowPeer implementation 121 122 @Override 123 public void toFront() { 124 updateFocusableWindowState(); 125 _toFront(); 126 } 127 private native void _toFront(); 128 129 @Override 130 public native void toBack(); 131 132 private native void setAlwaysOnTopNative(boolean value); 133 134 public void setAlwaysOnTop(boolean value) { 135 if ((value && ((Window)target).isVisible()) || !value) { 136 setAlwaysOnTopNative(value); 137 } 138 } 139 140 @Override 141 public void updateAlwaysOnTopState() { 142 setAlwaysOnTop(((Window)target).isAlwaysOnTop()); 143 } 144 145 @Override 146 public void updateFocusableWindowState() { 147 setFocusableWindow(((Window)target).isFocusableWindow()); 148 } 149 native void setFocusableWindow(boolean value); 150 151 // FramePeer & DialogPeer partial shared implementation 152 153 public void setTitle(String title) { 154 // allow a null title to pass as an empty string. 155 if (title == null) { 156 title = ""; 157 } 158 _setTitle(title); 159 } 160 private native void _setTitle(String title); 161 162 public void setResizable(boolean resizable) { 163 _setResizable(resizable); 164 } 165 166 private native void _setResizable(boolean resizable); 167 168 // Toolkit & peer internals 169 170 WWindowPeer(Window target) { 171 super(target); 172 } 173 174 @Override 175 void initialize() { 176 super.initialize(); 177 178 updateInsets(insets_); 179 180 if (!((Window) target).isFontSet()) { 181 ((Window) target).setFont(defaultFont); 182 setFont(defaultFont); 183 } 184 if (!((Window) target).isForegroundSet()) { 185 ((Window) target).setForeground(SystemColor.windowText); 186 } 187 if (!((Window) target).isBackgroundSet()) { 188 ((Window) target).setBackground(SystemColor.window); 189 } 190 191 // Express our interest in display changes 192 GraphicsConfiguration gc = getGraphicsConfiguration(); 193 ((Win32GraphicsDevice)gc.getDevice()).addDisplayChangedListener(this); 194 195 initActiveWindowsTracking((Window)target); 196 197 updateIconImages(); 198 199 Shape shape = ((Window)target).getShape(); 200 if (shape != null) { 201 applyShape(Region.getInstance(shape, null)); 202 } 203 204 float opacity = ((Window)target).getOpacity(); 205 if (opacity < 1.0f) { 206 setOpacity(opacity); 207 } 208 209 synchronized (getStateLock()) { 210 // default value of a boolean field is 'false', so set isOpaque to 211 // true here explicitly 212 this.isOpaque = true; 213 setOpaque(((Window)target).isOpaque()); 214 } 215 } 216 217 native void createAwtWindow(WComponentPeer parent); 218 219 private volatile Window.Type windowType = Window.Type.NORMAL; 220 221 // This method must be called for Window, Dialog, and Frame before creating 222 // the hwnd 223 void preCreate(WComponentPeer parent) { 224 windowType = ((Window)target).getType(); 225 } 226 227 @Override 228 void create(WComponentPeer parent) { 229 preCreate(parent); 230 createAwtWindow(parent); 231 } 232 233 @Override 234 final WComponentPeer getNativeParent() { 235 final Container owner = ((Window) target).getOwner(); 236 return (WComponentPeer) WToolkit.targetToPeer(owner); 237 } 238 239 // should be overriden in WDialogPeer 240 protected void realShow() { 241 super.show(); 242 } 243 244 @Override 245 public void show() { 246 updateFocusableWindowState(); 247 248 boolean alwaysOnTop = ((Window)target).isAlwaysOnTop(); 249 250 // Fix for 4868278. 251 // If we create a window with a specific GraphicsConfig, and then move it with 252 // setLocation() or setBounds() to another one before its peer has been created, 253 // then calling Window.getGraphicsConfig() returns wrong config. That may lead 254 // to some problems like wrong-placed tooltips. It is caused by calling 255 // super.displayChanged() in WWindowPeer.displayChanged() regardless of whether 256 // GraphicsDevice was really changed, or not. So we need to track it here. 257 updateGC(); 258 259 realShow(); 260 updateMinimumSize(); 261 262 if (((Window)target).isAlwaysOnTopSupported() && alwaysOnTop) { 263 setAlwaysOnTop(alwaysOnTop); 264 } 265 266 synchronized (getStateLock()) { 267 if (!isOpaque) { 268 updateWindow(true); 269 } 270 } 271 272 // See https://javafx-jira.kenai.com/browse/RT-32570 273 WComponentPeer owner = getNativeParent(); 274 if (owner != null && owner.isLightweightFramePeer()) { 275 Rectangle b = getBounds(); 276 handleExpose(0, 0, b.width, b.height); 277 } 278 } 279 280 // Synchronize the insets members (here & in helper) with actual window 281 // state. 282 native void updateInsets(Insets i); 283 284 static native int getSysMinWidth(); 285 static native int getSysMinHeight(); 286 static native int getSysIconWidth(); 287 static native int getSysIconHeight(); 288 static native int getSysSmIconWidth(); 289 static native int getSysSmIconHeight(); 290 /**windows/classes/sun/awt/windows/ 291 * Creates native icon from specified raster data and updates 292 * icon for window and all descendant windows that inherit icon. 293 * Raster data should be passed in the ARGB form. 294 * Note that raster data format was changed to provide support 295 * for XP icons with alpha-channel 296 */ 297 native void setIconImagesData(int[] iconRaster, int w, int h, 298 int[] smallIconRaster, int smw, int smh); 299 300 synchronized native void reshapeFrame(int x, int y, int width, int height); 301 302 native Dimension getNativeWindowSize(); 303 304 public Dimension getScaledWindowSize() { 305 return getNativeWindowSize(); 306 } 307 308 public boolean requestWindowFocus(FocusEvent.Cause cause) { 309 if (!focusAllowedFor()) { 310 return false; 311 } 312 return requestWindowFocus(cause == FocusEvent.Cause.MOUSE_EVENT); 313 } 314 private native boolean requestWindowFocus(boolean isMouseEventCause); 315 316 public boolean focusAllowedFor() { 317 Window window = (Window)this.target; 318 if (!window.isVisible() || 319 !window.isEnabled() || 320 !window.isFocusableWindow()) 321 { 322 return false; 323 } 324 if (isModalBlocked()) { 325 return false; 326 } 327 return true; 328 } 329 330 @Override 331 void hide() { 332 WindowListener listener = windowListener; 333 if (listener != null) { 334 // We're not getting WINDOW_CLOSING from the native code when hiding 335 // the window programmatically. So, create it and notify the listener. 336 listener.windowClosing(new WindowEvent((Window)target, WindowEvent.WINDOW_CLOSING)); 337 } 338 super.hide(); 339 } 340 341 // WARNING: it's called on the Toolkit thread! 342 @Override 343 void preprocessPostEvent(AWTEvent event) { 344 if (event instanceof WindowEvent) { 345 WindowListener listener = windowListener; 346 if (listener != null) { 347 switch(event.getID()) { 348 case WindowEvent.WINDOW_CLOSING: 349 listener.windowClosing((WindowEvent)event); 350 break; 351 case WindowEvent.WINDOW_ICONIFIED: 352 listener.windowIconified((WindowEvent)event); 353 break; 354 } 355 } 356 } 357 } 358 359 synchronized void addWindowListener(WindowListener l) { 360 windowListener = AWTEventMulticaster.add(windowListener, l); 361 } 362 363 synchronized void removeWindowListener(WindowListener l) { 364 windowListener = AWTEventMulticaster.remove(windowListener, l); 365 } 366 367 @Override 368 public void updateMinimumSize() { 369 Dimension minimumSize = null; 370 if (((Component)target).isMinimumSizeSet()) { 371 minimumSize = ((Component)target).getMinimumSize(); 372 } 373 if (minimumSize != null) { 374 int msw = getSysMinWidth(); 375 int msh = getSysMinHeight(); 376 int w = (minimumSize.width >= msw) ? minimumSize.width : msw; 377 int h = (minimumSize.height >= msh) ? minimumSize.height : msh; 378 setMinSize(w, h); 379 } else { 380 setMinSize(0, 0); 381 } 382 } 383 384 @Override 385 public void updateIconImages() { 386 java.util.List<Image> imageList = ((Window)target).getIconImages(); 387 if (imageList == null || imageList.size() == 0) { 388 setIconImagesData(null, 0, 0, null, 0, 0); 389 } else { 390 int w = getSysIconWidth(); 391 int h = getSysIconHeight(); 392 int smw = getSysSmIconWidth(); 393 int smh = getSysSmIconHeight(); 394 AffineTransform tx = getGraphicsConfiguration().getDefaultTransform(); 395 w = Region.clipScale(w, tx.getScaleX()); 396 h = Region.clipScale(h, tx.getScaleY()); 397 smw = Region.clipScale(smw, tx.getScaleX()); 398 smh = Region.clipScale(smh, tx.getScaleY()); 399 DataBufferInt iconData = SunToolkit.getScaledIconData(imageList, 400 w, h); 401 DataBufferInt iconSmData = SunToolkit.getScaledIconData(imageList, 402 smw, smh); 403 if (iconData != null && iconSmData != null) { 404 setIconImagesData(iconData.getData(), w, h, 405 iconSmData.getData(), smw, smh); 406 } else { 407 setIconImagesData(null, 0, 0, null, 0, 0); 408 } 409 } 410 } 411 412 native void setMinSize(int width, int height); 413 414 /* 415 * ---- MODALITY SUPPORT ---- 416 */ 417 418 /** 419 * Some modality-related code here because WFileDialogPeer, WPrintDialogPeer and 420 * WPageDialogPeer are descendants of WWindowPeer, not WDialogPeer 421 */ 422 423 public boolean isModalBlocked() { 424 return modalBlocker != null; 425 } 426 427 @Override 428 public void setModalBlocked(Dialog dialog, boolean blocked) { 429 synchronized (((Component)getTarget()).getTreeLock()) // State lock should always be after awtLock 430 { 431 // use WWindowPeer instead of WDialogPeer because of FileDialogs and PrintDialogs 432 WWindowPeer blockerPeer = AWTAccessor.getComponentAccessor() 433 .getPeer(dialog); 434 if (blocked) 435 { 436 modalBlocker = blockerPeer; 437 // handle native dialogs separately, as they may have not 438 // got HWND yet; modalEnable/modalDisable is called from 439 // their setHWnd() methods 440 if (blockerPeer instanceof WFileDialogPeer) { 441 ((WFileDialogPeer)blockerPeer).blockWindow(this); 442 } else if (blockerPeer instanceof WPrintDialogPeer) { 443 ((WPrintDialogPeer)blockerPeer).blockWindow(this); 444 } else { 445 modalDisable(dialog, blockerPeer.getHWnd()); 446 } 447 } else { 448 modalBlocker = null; 449 if (blockerPeer instanceof WFileDialogPeer) { 450 ((WFileDialogPeer)blockerPeer).unblockWindow(this); 451 } else if (blockerPeer instanceof WPrintDialogPeer) { 452 ((WPrintDialogPeer)blockerPeer).unblockWindow(this); 453 } else { 454 modalEnable(dialog); 455 } 456 } 457 } 458 } 459 460 native void modalDisable(Dialog blocker, long blockerHWnd); 461 native void modalEnable(Dialog blocker); 462 463 /* 464 * Returns all the ever active windows from the current AppContext. 465 * The list is sorted by the time of activation, so the latest 466 * active window is always at the end. 467 */ 468 @SuppressWarnings("unchecked") 469 public static long[] getActiveWindowHandles(Component target) { 470 AppContext appContext = SunToolkit.targetToAppContext(target); 471 if (appContext == null) return null; 472 synchronized (appContext) { 473 List<WWindowPeer> l = (List<WWindowPeer>)appContext.get(ACTIVE_WINDOWS_KEY); 474 if (l == null) { 475 return null; 476 } 477 long[] result = new long[l.size()]; 478 for (int j = 0; j < l.size(); j++) { 479 result[j] = l.get(j).getHWnd(); 480 } 481 return result; 482 } 483 } 484 485 /* 486 * ----DISPLAY CHANGE SUPPORT---- 487 */ 488 489 /* 490 * Called from native code when we have been dragged onto another screen. 491 */ 492 void draggedToNewScreen() { 493 SunToolkit.executeOnEventHandlerThread((Component)target,new Runnable() 494 { 495 @Override 496 public void run() { 497 displayChanged(); 498 } 499 }); 500 } 501 502 public void updateGC() { 503 int scrn = getScreenImOn(); 504 if (screenLog.isLoggable(PlatformLogger.Level.FINER)) { 505 log.finer("Screen number: " + scrn); 506 } 507 508 // get current GD 509 Win32GraphicsDevice oldDev = winGraphicsConfig.getDevice(); 510 511 Win32GraphicsDevice newDev; 512 GraphicsDevice devs[] = GraphicsEnvironment 513 .getLocalGraphicsEnvironment() 514 .getScreenDevices(); 515 // Occasionally during device addition/removal getScreenImOn can return 516 // a non-existing screen number. Use the default device in this case. 517 if (scrn >= devs.length) { 518 newDev = (Win32GraphicsDevice)GraphicsEnvironment 519 .getLocalGraphicsEnvironment().getDefaultScreenDevice(); 520 } else { 521 newDev = (Win32GraphicsDevice)devs[scrn]; 522 } 523 524 // Set winGraphicsConfig to the default GC for the monitor this Window 525 // is now mostly on. 526 winGraphicsConfig = (Win32GraphicsConfig)newDev 527 .getDefaultConfiguration(); 528 if (screenLog.isLoggable(PlatformLogger.Level.FINE)) { 529 if (winGraphicsConfig == null) { 530 screenLog.fine("Assertion (winGraphicsConfig != null) failed"); 531 } 532 } 533 534 // if on a different display, take off old GD and put on new GD 535 if (oldDev != newDev) { 536 oldDev.removeDisplayChangedListener(this); 537 newDev.addDisplayChangedListener(this); 538 } 539 540 AWTAccessor.getComponentAccessor(). 541 setGraphicsConfiguration((Component)target, winGraphicsConfig); 542 } 543 544 /** 545 * From the DisplayChangedListener interface. 546 * 547 * This method handles a display change - either when the display settings 548 * are changed, or when the window has been dragged onto a different 549 * display. 550 * Called after a change in the display mode. This event 551 * triggers replacing the surfaceData object (since that object 552 * reflects the current display depth information, which has 553 * just changed). 554 */ 555 @Override 556 public void displayChanged() { 557 updateGC(); 558 } 559 560 /** 561 * Part of the DisplayChangedListener interface: components 562 * do not need to react to this event 563 */ 564 @Override 565 public void paletteChanged() { 566 } 567 568 private native int getScreenImOn(); 569 570 // Used in Win32GraphicsDevice. 571 public final native void setFullScreenExclusiveModeState(boolean state); 572 573 /* 574 * ----END DISPLAY CHANGE SUPPORT---- 575 */ 576 577 public void grab() { 578 nativeGrab(); 579 } 580 581 public void ungrab() { 582 nativeUngrab(); 583 } 584 private native void nativeGrab(); 585 private native void nativeUngrab(); 586 587 private final boolean hasWarningWindow() { 588 return ((Window)target).getWarningString() != null; 589 } 590 591 boolean isTargetUndecorated() { 592 return true; 593 } 594 595 // These are the peer bounds. They get updated at: 596 // 1. the WWindowPeer.setBounds() method. 597 // 2. the native code (on WM_SIZE/WM_MOVE) 598 private volatile int sysX = 0; 599 private volatile int sysY = 0; 600 private volatile int sysW = 0; 601 private volatile int sysH = 0; 602 603 @Override 604 public native void repositionSecurityWarning(); 605 606 @Override 607 public void setBounds(int x, int y, int width, int height, int op) { 608 sysX = x; 609 sysY = y; 610 sysW = width; 611 sysH = height; 612 613 super.setBounds(x, y, width, height, op); 614 } 615 616 @Override 617 public void print(Graphics g) { 618 // We assume we print the whole frame, 619 // so we expect no clip was set previously 620 Shape shape = AWTAccessor.getWindowAccessor().getShape((Window)target); 621 if (shape != null) { 622 g.setClip(shape); 623 } 624 super.print(g); 625 } 626 627 private void replaceSurfaceDataRecursively(Component c) { 628 if (c instanceof Container) { 629 for (Component child : ((Container)c).getComponents()) { 630 replaceSurfaceDataRecursively(child); 631 } 632 } 633 final Object cp = AWTAccessor.getComponentAccessor().getPeer(c); 634 if (cp instanceof WComponentPeer) { 635 ((WComponentPeer)cp).replaceSurfaceDataLater(); 636 } 637 } 638 639 public final Graphics getTranslucentGraphics() { 640 synchronized (getStateLock()) { 641 return isOpaque ? null : painter.getBackBuffer(false).getGraphics(); 642 } 643 } 644 645 @Override 646 public void setBackground(Color c) { 647 super.setBackground(c); 648 synchronized (getStateLock()) { 649 if (!isOpaque && ((Window)target).isVisible()) { 650 updateWindow(true); 651 } 652 } 653 } 654 655 private native void setOpacity(int iOpacity); 656 private float opacity = 1.0f; 657 658 @Override 659 public void setOpacity(float opacity) { 660 if (!((SunToolkit)((Window)target).getToolkit()). 661 isWindowOpacitySupported()) 662 { 663 return; 664 } 665 666 if (opacity < 0.0f || opacity > 1.0f) { 667 throw new IllegalArgumentException( 668 "The value of opacity should be in the range [0.0f .. 1.0f]."); 669 } 670 671 if (((this.opacity == 1.0f && opacity < 1.0f) || 672 (this.opacity < 1.0f && opacity == 1.0f)) && 673 !Win32GraphicsEnvironment.isVistaOS()) 674 { 675 // non-Vista OS: only replace the surface data if opacity status 676 // changed (see WComponentPeer.isAccelCapable() for more) 677 replaceSurfaceDataRecursively((Component)getTarget()); 678 } 679 680 this.opacity = opacity; 681 682 final int maxOpacity = 0xff; 683 int iOpacity = (int)(opacity * maxOpacity); 684 if (iOpacity < 0) { 685 iOpacity = 0; 686 } 687 if (iOpacity > maxOpacity) { 688 iOpacity = maxOpacity; 689 } 690 691 setOpacity(iOpacity); 692 693 synchronized (getStateLock()) { 694 if (!isOpaque && ((Window)target).isVisible()) { 695 updateWindow(true); 696 } 697 } 698 } 699 700 private native void setOpaqueImpl(boolean isOpaque); 701 702 @Override 703 public void setOpaque(boolean isOpaque) { 704 synchronized (getStateLock()) { 705 if (this.isOpaque == isOpaque) { 706 return; 707 } 708 } 709 710 Window target = (Window)getTarget(); 711 712 if (!isOpaque) { 713 SunToolkit sunToolkit = (SunToolkit)target.getToolkit(); 714 if (!sunToolkit.isWindowTranslucencySupported() || 715 !sunToolkit.isTranslucencyCapable(target.getGraphicsConfiguration())) 716 { 717 return; 718 } 719 } 720 721 boolean isVistaOS = Win32GraphicsEnvironment.isVistaOS(); 722 723 if (this.isOpaque != isOpaque && !isVistaOS) { 724 // non-Vista OS: only replace the surface data if the opacity 725 // status changed (see WComponentPeer.isAccelCapable() for more) 726 replaceSurfaceDataRecursively(target); 727 } 728 729 synchronized (getStateLock()) { 730 this.isOpaque = isOpaque; 731 setOpaqueImpl(isOpaque); 732 if (isOpaque) { 733 TranslucentWindowPainter currentPainter = painter; 734 if (currentPainter != null) { 735 currentPainter.flush(); 736 painter = null; 737 } 738 } else { 739 painter = TranslucentWindowPainter.createInstance(this); 740 } 741 } 742 743 if (isVistaOS) { 744 // On Vista: setting the window non-opaque makes the window look 745 // rectangular, though still catching the mouse clicks within 746 // its shape only. To restore the correct visual appearance 747 // of the window (i.e. w/ the correct shape) we have to reset 748 // the shape. 749 Shape shape = target.getShape(); 750 if (shape != null) { 751 target.setShape(shape); 752 } 753 } 754 755 if (target.isVisible()) { 756 updateWindow(true); 757 } 758 } 759 760 native void updateWindowImpl(int[] data, int width, int height); 761 762 @Override 763 public void updateWindow() { 764 updateWindow(false); 765 } 766 767 private void updateWindow(boolean repaint) { 768 Window w = (Window)target; 769 synchronized (getStateLock()) { 770 if (isOpaque || !w.isVisible() || 771 (w.getWidth() <= 0) || (w.getHeight() <= 0)) 772 { 773 return; 774 } 775 TranslucentWindowPainter currentPainter = painter; 776 if (currentPainter != null) { 777 currentPainter.updateWindow(repaint); 778 } else if (log.isLoggable(PlatformLogger.Level.FINER)) { 779 log.finer("Translucent window painter is null in updateWindow"); 780 } 781 } 782 } 783 784 /* 785 * The method maps the list of the active windows to the window's AppContext, 786 * then the method registers ActiveWindowListener, GuiDisposedListener listeners; 787 * it executes the initilialization only once per AppContext. 788 */ 789 @SuppressWarnings("unchecked") 790 private static void initActiveWindowsTracking(Window w) { 791 AppContext appContext = AppContext.getAppContext(); 792 synchronized (appContext) { 793 List<WWindowPeer> l = (List<WWindowPeer>)appContext.get(ACTIVE_WINDOWS_KEY); 794 if (l == null) { 795 l = new LinkedList<WWindowPeer>(); 796 appContext.put(ACTIVE_WINDOWS_KEY, l); 797 appContext.addPropertyChangeListener(AppContext.GUI_DISPOSED, guiDisposedListener); 798 799 KeyboardFocusManager kfm = KeyboardFocusManager.getCurrentKeyboardFocusManager(); 800 kfm.addPropertyChangeListener("activeWindow", activeWindowListener); 801 } 802 } 803 } 804 805 /* 806 * The GuiDisposedListener class listens for the AppContext.GUI_DISPOSED property, 807 * it removes the list of the active windows from the disposed AppContext and 808 * unregisters ActiveWindowListener listener. 809 */ 810 private static class GuiDisposedListener implements PropertyChangeListener { 811 @Override 812 public void propertyChange(PropertyChangeEvent e) { 813 boolean isDisposed = (Boolean)e.getNewValue(); 814 if (isDisposed != true) { 815 if (log.isLoggable(PlatformLogger.Level.FINE)) { 816 log.fine(" Assertion (newValue != true) failed for AppContext.GUI_DISPOSED "); 817 } 818 } 819 AppContext appContext = AppContext.getAppContext(); 820 synchronized (appContext) { 821 appContext.remove(ACTIVE_WINDOWS_KEY); 822 appContext.removePropertyChangeListener(AppContext.GUI_DISPOSED, this); 823 824 KeyboardFocusManager kfm = KeyboardFocusManager.getCurrentKeyboardFocusManager(); 825 kfm.removePropertyChangeListener("activeWindow", activeWindowListener); 826 } 827 } 828 } 829 830 /* 831 * Static inner class, listens for 'activeWindow' KFM property changes and 832 * updates the list of active windows per AppContext, so the latest active 833 * window is always at the end of the list. The list is stored in AppContext. 834 */ 835 @SuppressWarnings("unchecked") 836 private static class ActiveWindowListener implements PropertyChangeListener { 837 @Override 838 public void propertyChange(PropertyChangeEvent e) { 839 Window w = (Window)e.getNewValue(); 840 if (w == null) { 841 return; 842 } 843 AppContext appContext = SunToolkit.targetToAppContext(w); 844 synchronized (appContext) { 845 WWindowPeer wp = AWTAccessor.getComponentAccessor().getPeer(w); 846 // add/move wp to the end of the list 847 List<WWindowPeer> l = (List<WWindowPeer>)appContext.get(ACTIVE_WINDOWS_KEY); 848 if (l != null) { 849 l.remove(wp); 850 l.add(wp); 851 } 852 } 853 } 854 } 855 }