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