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