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