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.peer.*;
  29 import java.awt.image.VolatileImage;
  30 import sun.awt.RepaintArea;
  31 import sun.awt.CausedFocusEvent;
  32 import sun.awt.image.SunVolatileImage;
  33 import sun.awt.image.ToolkitImage;
  34 import java.awt.image.BufferedImage;
  35 import java.awt.image.ImageProducer;
  36 import java.awt.image.ImageObserver;
  37 import java.awt.image.ColorModel;
  38 import java.awt.event.PaintEvent;
  39 import java.awt.event.InvocationEvent;
  40 import java.awt.event.KeyEvent;
  41 import java.awt.event.FocusEvent;
  42 import java.awt.event.MouseEvent;
  43 import java.awt.event.MouseWheelEvent;
  44 import java.awt.event.InputEvent;
  45 import sun.awt.Win32GraphicsConfig;
  46 import sun.awt.Win32GraphicsEnvironment;
  47 import sun.java2d.InvalidPipeException;
  48 import sun.java2d.SurfaceData;
  49 import sun.java2d.ScreenUpdateManager;
  50 import sun.java2d.d3d.D3DSurfaceData;
  51 import sun.java2d.opengl.OGLSurfaceData;
  52 import sun.java2d.pipe.Region;
  53 import sun.awt.DisplayChangedListener;
  54 import sun.awt.PaintEventDispatcher;
  55 import sun.awt.SunToolkit;
  56 import sun.awt.event.IgnorePaintEvent;
  57 
  58 import java.awt.dnd.DropTarget;
  59 import java.awt.dnd.peer.DropTargetPeer;
  60 import sun.awt.AWTAccessor;
  61 
  62 import sun.util.logging.PlatformLogger;
  63 
  64 public abstract class WComponentPeer extends WObjectPeer
  65     implements ComponentPeer, DropTargetPeer
  66 {
  67     /**
  68      * Handle to native window
  69      */
  70     protected volatile long hwnd;
  71 
  72     private static final PlatformLogger log = PlatformLogger.getLogger("sun.awt.windows.WComponentPeer");
  73     private static final PlatformLogger shapeLog = PlatformLogger.getLogger("sun.awt.windows.shape.WComponentPeer");
  74     private static final PlatformLogger focusLog = PlatformLogger.getLogger("sun.awt.windows.focus.WComponentPeer");
  75 
  76     // ComponentPeer implementation
  77     SurfaceData surfaceData;
  78 
  79     private RepaintArea paintArea;
  80 
  81     protected Win32GraphicsConfig winGraphicsConfig;
  82 
  83     boolean isLayouting = false;
  84     boolean paintPending = false;
  85     int     oldWidth = -1;
  86     int     oldHeight = -1;
  87     private int numBackBuffers = 0;
  88     private VolatileImage backBuffer = null;
  89     private BufferCapabilities backBufferCaps = null;
  90 
  91     // foreground, background and color are cached to avoid calling back
  92     // into the Component.
  93     private Color foreground;
  94     private Color background;
  95     private Font font;
  96 
  97     public native boolean isObscured();
  98     public boolean canDetermineObscurity() { return true; }
  99 
 100     // DropTarget support
 101 
 102     int nDropTargets;
 103     long nativeDropTargetContext; // native pointer
 104 
 105     public synchronized native void pShow();
 106     public synchronized native void hide();
 107     public synchronized native void enable();
 108     public synchronized native void disable();
 109 
 110     public long getHWnd() {
 111         return hwnd;
 112     }
 113 
 114     /* New 1.1 API */
 115     public native Point getLocationOnScreen();
 116 
 117     /* New 1.1 API */
 118     public void setVisible(boolean b) {
 119         if (b) {
 120             show();
 121         } else {
 122             hide();
 123         }
 124     }
 125 
 126     public void show() {
 127         Dimension s = ((Component)target).getSize();
 128         oldHeight = s.height;
 129         oldWidth = s.width;
 130         pShow();
 131     }
 132 
 133     /* New 1.1 API */
 134     public void setEnabled(boolean b) {
 135         if (b) {
 136             enable();
 137         } else {
 138             disable();
 139         }
 140     }
 141 
 142     public int serialNum = 0;
 143 
 144     private native void reshapeNoCheck(int x, int y, int width, int height);
 145 
 146     /* New 1.1 API */
 147     public void setBounds(int x, int y, int width, int height, int op) {
 148         // Should set paintPending before reahape to prevent
 149         // thread race between paint events
 150         // Native components do redraw after resize
 151         paintPending = (width != oldWidth) || (height != oldHeight);
 152 
 153         if ( (op & NO_EMBEDDED_CHECK) != 0 ) {
 154             reshapeNoCheck(x, y, width, height);
 155         } else {
 156             reshape(x, y, width, height);
 157         }
 158         if ((width != oldWidth) || (height != oldHeight)) {
 159             // Only recreate surfaceData if this setBounds is called
 160             // for a resize; a simple move should not trigger a recreation
 161             try {
 162                 replaceSurfaceData();
 163             } catch (InvalidPipeException e) {
 164                 // REMIND : what do we do if our surface creation failed?
 165             }
 166             oldWidth = width;
 167             oldHeight = height;
 168         }
 169 
 170         serialNum++;
 171     }
 172 
 173     /*
 174      * Called from native code (on Toolkit thread) in order to
 175      * dynamically layout the Container during resizing
 176      */
 177     void dynamicallyLayoutContainer() {
 178         // If we got the WM_SIZING, this must be a Container, right?
 179         // In fact, it must be the top-level Container.
 180         if (log.isLoggable(PlatformLogger.Level.FINE)) {
 181             Container parent = WToolkit.getNativeContainer((Component)target);
 182             if (parent != null) {
 183                 log.fine("Assertion (parent == null) failed");
 184             }
 185         }
 186         final Container cont = (Container)target;
 187 
 188         WToolkit.executeOnEventHandlerThread(cont, new Runnable() {
 189             public void run() {
 190                 // Discarding old paint events doesn't seem to be necessary.
 191                 cont.invalidate();
 192                 cont.validate();
 193 
 194                 if (surfaceData instanceof D3DSurfaceData.D3DWindowSurfaceData ||
 195                     surfaceData instanceof OGLSurfaceData)
 196                 {
 197                     // When OGL or D3D is enabled, it is necessary to
 198                     // replace the SurfaceData for each dynamic layout
 199                     // request so that the viewport stays in sync
 200                     // with the window bounds.
 201                     try {
 202                         replaceSurfaceData();
 203                     } catch (InvalidPipeException e) {
 204                         // REMIND: this is unlikely to occur for OGL, but
 205                         // what do we do if surface creation fails?
 206                     }
 207                 }
 208 
 209                 // Forcing a paint here doesn't seem to be necessary.
 210                 // paintDamagedAreaImmediately();
 211             }
 212         });
 213     }
 214 
 215     /*
 216      * Paints any portion of the component that needs updating
 217      * before the call returns (similar to the Win32 API UpdateWindow)
 218      */
 219     void paintDamagedAreaImmediately() {
 220         // force Windows to send any pending WM_PAINT events so
 221         // the damage area is updated on the Java side
 222         updateWindow();
 223         // make sure paint events are transferred to main event queue
 224         // for coalescing
 225         SunToolkit.flushPendingEvents();
 226         // paint the damaged area
 227         paintArea.paint(target, shouldClearRectBeforePaint());
 228     }
 229 
 230     native synchronized void updateWindow();
 231 
 232     public void paint(Graphics g) {
 233         ((Component)target).paint(g);
 234     }
 235 
 236     public void repaint(long tm, int x, int y, int width, int height) {
 237     }
 238 
 239     private static final double BANDING_DIVISOR = 4.0;
 240     private native int[] createPrintedPixels(int srcX, int srcY,
 241                                              int srcW, int srcH,
 242                                              int alpha);
 243     public void print(Graphics g) {
 244 
 245         Component comp = (Component)target;
 246 
 247         // To conserve memory usage, we will band the image.
 248 
 249         int totalW = comp.getWidth();
 250         int totalH = comp.getHeight();
 251 
 252         int hInc = (int)(totalH / BANDING_DIVISOR);
 253         if (hInc == 0) {
 254             hInc = totalH;
 255         }
 256 
 257         for (int startY = 0; startY < totalH; startY += hInc) {
 258             int endY = startY + hInc - 1;
 259             if (endY >= totalH) {
 260                 endY = totalH - 1;
 261             }
 262             int h = endY - startY + 1;
 263 
 264             Color bgColor = comp.getBackground();
 265             int[] pix = createPrintedPixels(0, startY, totalW, h,
 266                                             bgColor == null ? 255 : bgColor.getAlpha());
 267             if (pix != null) {
 268                 BufferedImage bim = new BufferedImage(totalW, h,
 269                                               BufferedImage.TYPE_INT_ARGB);
 270                 bim.setRGB(0, 0, totalW, h, pix, 0, totalW);
 271                 g.drawImage(bim, 0, startY, null);
 272                 bim.flush();
 273             }
 274         }
 275 
 276         comp.print(g);
 277     }
 278 
 279     public void coalescePaintEvent(PaintEvent e) {
 280         Rectangle r = e.getUpdateRect();
 281         if (!(e instanceof IgnorePaintEvent)) {
 282             paintArea.add(r, e.getID());
 283         }
 284 
 285         if (log.isLoggable(PlatformLogger.Level.FINEST)) {
 286             switch(e.getID()) {
 287             case PaintEvent.UPDATE:
 288                 log.finest("coalescePaintEvent: UPDATE: add: x = " +
 289                     r.x + ", y = " + r.y + ", width = " + r.width + ", height = " + r.height);
 290                 return;
 291             case PaintEvent.PAINT:
 292                 log.finest("coalescePaintEvent: PAINT: add: x = " +
 293                     r.x + ", y = " + r.y + ", width = " + r.width + ", height = " + r.height);
 294                 return;
 295             }
 296         }
 297     }
 298 
 299     public synchronized native void reshape(int x, int y, int width, int height);
 300 
 301     // returns true if the event has been handled and shouldn't be propagated
 302     // though handleEvent method chain - e.g. WTextFieldPeer returns true
 303     // on handling '\n' to prevent it from being passed to native code
 304     public boolean handleJavaKeyEvent(KeyEvent e) { return false; }
 305 
 306     public void handleJavaMouseEvent(MouseEvent e) {
 307         switch (e.getID()) {
 308           case MouseEvent.MOUSE_PRESSED:
 309               // Note that Swing requests focus in its own mouse event handler.
 310               if (target == e.getSource() &&
 311                   !((Component)target).isFocusOwner() &&
 312                   WKeyboardFocusManagerPeer.shouldFocusOnClick((Component)target))
 313               {
 314                   WKeyboardFocusManagerPeer.requestFocusFor((Component)target,
 315                                                             CausedFocusEvent.Cause.MOUSE_EVENT);
 316               }
 317               break;
 318         }
 319     }
 320 
 321     native void nativeHandleEvent(AWTEvent e);
 322 
 323     @SuppressWarnings("fallthrough")
 324     public void handleEvent(AWTEvent e) {
 325         int id = e.getID();
 326 
 327         if ((e instanceof InputEvent) && !((InputEvent)e).isConsumed() &&
 328             ((Component)target).isEnabled())
 329         {
 330             if (e instanceof MouseEvent && !(e instanceof MouseWheelEvent)) {
 331                 handleJavaMouseEvent((MouseEvent) e);
 332             } else if (e instanceof KeyEvent) {
 333                 if (handleJavaKeyEvent((KeyEvent)e)) {
 334                     return;
 335                 }
 336             }
 337         }
 338 
 339         switch(id) {
 340             case PaintEvent.PAINT:
 341                 // Got native painting
 342                 paintPending = false;
 343                 // Fallthrough to next statement
 344             case PaintEvent.UPDATE:
 345                 // Skip all painting while layouting and all UPDATEs
 346                 // while waiting for native paint
 347                 if (!isLayouting && ! paintPending) {
 348                     paintArea.paint(target,shouldClearRectBeforePaint());
 349                 }
 350                 return;
 351             case FocusEvent.FOCUS_LOST:
 352             case FocusEvent.FOCUS_GAINED:
 353                 handleJavaFocusEvent((FocusEvent)e);
 354             default:
 355             break;
 356         }
 357 
 358         // Call the native code
 359         nativeHandleEvent(e);
 360     }
 361 
 362     void handleJavaFocusEvent(FocusEvent fe) {
 363         if (focusLog.isLoggable(PlatformLogger.Level.FINER)) {
 364             focusLog.finer(fe.toString());
 365         }
 366         setFocus(fe.getID() == FocusEvent.FOCUS_GAINED);
 367     }
 368 
 369     native void setFocus(boolean doSetFocus);
 370 
 371     public Dimension getMinimumSize() {
 372         return ((Component)target).getSize();
 373     }
 374 
 375     public Dimension getPreferredSize() {
 376         return getMinimumSize();
 377     }
 378 
 379     // Do nothing for heavyweight implementation
 380     public void layout() {}
 381 
 382     public Rectangle getBounds() {
 383         return ((Component)target).getBounds();
 384     }
 385 
 386     public boolean isFocusable() {
 387         return false;
 388     }
 389 
 390     /*
 391      * Return the GraphicsConfiguration associated with this peer, either
 392      * the locally stored winGraphicsConfig, or that of the target Component.
 393      */
 394     public GraphicsConfiguration getGraphicsConfiguration() {
 395         if (winGraphicsConfig != null) {
 396             return winGraphicsConfig;
 397         }
 398         else {
 399             // we don't need a treelock here, since
 400             // Component.getGraphicsConfiguration() gets it itself.
 401             return ((Component)target).getGraphicsConfiguration();
 402         }
 403     }
 404 
 405     public SurfaceData getSurfaceData() {
 406         return surfaceData;
 407     }
 408 
 409     /**
 410      * Creates new surfaceData object and invalidates the previous
 411      * surfaceData object.
 412      * Replacing the surface data should never lock on any resources which are
 413      * required by other threads which may have them and may require
 414      * the tree-lock.
 415      * This is a degenerate version of replaceSurfaceData(numBackBuffers), so
 416      * just call that version with our current numBackBuffers.
 417      */
 418     public void replaceSurfaceData() {
 419         replaceSurfaceData(this.numBackBuffers, this.backBufferCaps);
 420     }
 421 
 422     public void createScreenSurface(boolean isResize)
 423     {
 424         Win32GraphicsConfig gc = (Win32GraphicsConfig)getGraphicsConfiguration();
 425         ScreenUpdateManager mgr = ScreenUpdateManager.getInstance();
 426 
 427         surfaceData = mgr.createScreenSurface(gc, this, numBackBuffers, isResize);
 428     }
 429 
 430 
 431     /**
 432      * Multi-buffer version of replaceSurfaceData.  This version is called
 433      * by createBuffers(), which needs to acquire the same locks in the same
 434      * order, but also needs to perform additional functions inside the
 435      * locks.
 436      */
 437     public void replaceSurfaceData(int newNumBackBuffers,
 438                                    BufferCapabilities caps)
 439     {
 440         SurfaceData oldData = null;
 441         VolatileImage oldBB = null;
 442         synchronized(((Component)target).getTreeLock()) {
 443             synchronized(this) {
 444                 if (pData == 0) {
 445                     return;
 446                 }
 447                 numBackBuffers = newNumBackBuffers;
 448                 ScreenUpdateManager mgr = ScreenUpdateManager.getInstance();
 449                 oldData = surfaceData;
 450                 mgr.dropScreenSurface(oldData);
 451                 createScreenSurface(true);
 452                 if (oldData != null) {
 453                     oldData.invalidate();
 454                 }
 455 
 456                 oldBB = backBuffer;
 457                 if (numBackBuffers > 0) {
 458                     // set the caps first, they're used when creating the bb
 459                     backBufferCaps = caps;
 460                     Win32GraphicsConfig gc =
 461                         (Win32GraphicsConfig)getGraphicsConfiguration();
 462                     backBuffer = gc.createBackBuffer(this);
 463                 } else if (backBuffer != null) {
 464                     backBufferCaps = null;
 465                     backBuffer = null;
 466                 }
 467             }
 468         }
 469         // it would be better to do this before we create new ones,
 470         // but then we'd run into deadlock issues
 471         if (oldData != null) {
 472             oldData.flush();
 473             // null out the old data to make it collected faster
 474             oldData = null;
 475         }
 476         if (oldBB != null) {
 477             oldBB.flush();
 478             // null out the old data to make it collected faster
 479             oldData = null;
 480         }
 481     }
 482 
 483     public void replaceSurfaceDataLater() {
 484         Runnable r = new Runnable() {
 485             public void run() {
 486                 // Shouldn't do anything if object is disposed in meanwhile
 487                 // No need for sync as disposeAction in Window is performed
 488                 // on EDT
 489                 if (!isDisposed()) {
 490                     try {
 491                         replaceSurfaceData();
 492                     } catch (InvalidPipeException e) {
 493                         // REMIND : what do we do if our surface creation failed?
 494                     }
 495                 }
 496             }
 497         };
 498         Component c = (Component)target;
 499         // Fix 6255371.
 500         if (!PaintEventDispatcher.getPaintEventDispatcher().queueSurfaceDataReplacing(c, r)) {
 501             postEvent(new InvocationEvent(c, r));
 502         }
 503     }
 504 
 505     public boolean updateGraphicsData(GraphicsConfiguration gc) {
 506         winGraphicsConfig = (Win32GraphicsConfig)gc;
 507         try {
 508             replaceSurfaceData();
 509         } catch (InvalidPipeException e) {
 510             // REMIND : what do we do if our surface creation failed?
 511         }
 512         return false;
 513     }
 514 
 515     //This will return null for Components not yet added to a Container
 516     public ColorModel getColorModel() {
 517         GraphicsConfiguration gc = getGraphicsConfiguration();
 518         if (gc != null) {
 519             return gc.getColorModel();
 520         }
 521         else {
 522             return null;
 523         }
 524     }
 525 
 526     //This will return null for Components not yet added to a Container
 527     public ColorModel getDeviceColorModel() {
 528         Win32GraphicsConfig gc =
 529             (Win32GraphicsConfig)getGraphicsConfiguration();
 530         if (gc != null) {
 531             return gc.getDeviceColorModel();
 532         }
 533         else {
 534             return null;
 535         }
 536     }
 537 
 538     //Returns null for Components not yet added to a Container
 539     public ColorModel getColorModel(int transparency) {
 540 //      return WToolkit.config.getColorModel(transparency);
 541         GraphicsConfiguration gc = getGraphicsConfiguration();
 542         if (gc != null) {
 543             return gc.getColorModel(transparency);
 544         }
 545         else {
 546             return null;
 547         }
 548     }
 549     public java.awt.Toolkit getToolkit() {
 550         return Toolkit.getDefaultToolkit();
 551     }
 552 
 553     // fallback default font object
 554     final static Font defaultFont = new Font(Font.DIALOG, Font.PLAIN, 12);
 555 
 556     @SuppressWarnings("deprecation")
 557     public Graphics getGraphics() {
 558         if (isDisposed()) {
 559             return null;
 560         }
 561 
 562         Component target = (Component)getTarget();
 563         Window window = SunToolkit.getContainingWindow(target);
 564         if (window != null) {
 565             Graphics g =
 566                 ((WWindowPeer)window.getPeer()).getTranslucentGraphics();
 567             // getTranslucentGraphics() returns non-null value for non-opaque windows only
 568             if (g != null) {
 569                 // Non-opaque windows do not support heavyweight children.
 570                 // Redirect all painting to the Window's Graphics instead.
 571                 // The caller is responsible for calling the
 572                 // WindowPeer.updateWindow() after painting has finished.
 573                 int x = 0, y = 0;
 574                 for (Component c = target; c != window; c = c.getParent()) {
 575                     x += c.getX();
 576                     y += c.getY();
 577                 }
 578 
 579                 g.translate(x, y);
 580                 g.clipRect(0, 0, target.getWidth(), target.getHeight());
 581 
 582                 return g;
 583             }
 584         }
 585 
 586         SurfaceData surfaceData = this.surfaceData;
 587         if (surfaceData != null) {
 588             /* Fix for bug 4746122. Color and Font shouldn't be null */
 589             Color bgColor = background;
 590             if (bgColor == null) {
 591                 bgColor = SystemColor.window;
 592             }
 593             Color fgColor = foreground;
 594             if (fgColor == null) {
 595                 fgColor = SystemColor.windowText;
 596             }
 597             Font font = this.font;
 598             if (font == null) {
 599                 font = defaultFont;
 600             }
 601             ScreenUpdateManager mgr =
 602                 ScreenUpdateManager.getInstance();
 603             return mgr.createGraphics(surfaceData, this, fgColor,
 604                                       bgColor, font);
 605         }
 606         return null;
 607     }
 608     public FontMetrics getFontMetrics(Font font) {
 609         return WFontMetrics.getFontMetrics(font);
 610     }
 611 
 612     private synchronized native void _dispose();
 613     protected void disposeImpl() {
 614         SurfaceData oldData = surfaceData;
 615         surfaceData = null;
 616         ScreenUpdateManager.getInstance().dropScreenSurface(oldData);
 617         oldData.invalidate();
 618         // remove from updater before calling targetDisposedPeer
 619         WToolkit.targetDisposedPeer(target, this);
 620         _dispose();
 621     }
 622 
 623     public void disposeLater() {
 624         postEvent(new InvocationEvent(target, new Runnable() {
 625             public void run() {
 626                 dispose();
 627             }
 628         }));
 629     }
 630 
 631     public synchronized void setForeground(Color c) {
 632         foreground = c;
 633         _setForeground(c.getRGB());
 634     }
 635 
 636     public synchronized void setBackground(Color c) {
 637         background = c;
 638         _setBackground(c.getRGB());
 639     }
 640 
 641     /**
 642      * This method is intentionally not synchronized as it is called while
 643      * holding other locks.
 644      *
 645      * @see sun.java2d.d3d.D3DScreenUpdateManager#validate(D3DWindowSurfaceData)
 646      */
 647     public Color getBackgroundNoSync() {
 648         return background;
 649     }
 650 
 651     public native void _setForeground(int rgb);
 652     public native void _setBackground(int rgb);
 653 
 654     public synchronized void setFont(Font f) {
 655         font = f;
 656         _setFont(f);
 657     }
 658     public synchronized native void _setFont(Font f);
 659     public final void updateCursorImmediately() {
 660         WGlobalCursorManager.getCursorManager().updateCursorImmediately();
 661     }
 662 
 663     // TODO: consider moving it to KeyboardFocusManagerPeerImpl
 664     @SuppressWarnings("deprecation")
 665     public boolean requestFocus(Component lightweightChild, boolean temporary,
 666                                 boolean focusedWindowChangeAllowed, long time,
 667                                 CausedFocusEvent.Cause cause)
 668     {
 669         if (WKeyboardFocusManagerPeer.
 670             processSynchronousLightweightTransfer((Component)target, lightweightChild, temporary,
 671                                                   focusedWindowChangeAllowed, time))
 672         {
 673             return true;
 674         }
 675 
 676         int result = WKeyboardFocusManagerPeer
 677             .shouldNativelyFocusHeavyweight((Component)target, lightweightChild,
 678                                             temporary, focusedWindowChangeAllowed,
 679                                             time, cause);
 680 
 681         switch (result) {
 682           case WKeyboardFocusManagerPeer.SNFH_FAILURE:
 683               return false;
 684           case WKeyboardFocusManagerPeer.SNFH_SUCCESS_PROCEED:
 685               if (focusLog.isLoggable(PlatformLogger.Level.FINER)) {
 686                   focusLog.finer("Proceeding with request to " + lightweightChild + " in " + target);
 687               }
 688               Window parentWindow = SunToolkit.getContainingWindow((Component)target);
 689               if (parentWindow == null) {
 690                   return rejectFocusRequestHelper("WARNING: Parent window is null");
 691               }
 692               WWindowPeer wpeer = (WWindowPeer)parentWindow.getPeer();
 693               if (wpeer == null) {
 694                   return rejectFocusRequestHelper("WARNING: Parent window's peer is null");
 695               }
 696               boolean res = wpeer.requestWindowFocus(cause);
 697 
 698               if (focusLog.isLoggable(PlatformLogger.Level.FINER)) {
 699                   focusLog.finer("Requested window focus: " + res);
 700               }
 701               // If parent window can be made focused and has been made focused(synchronously)
 702               // then we can proceed with children, otherwise we retreat.
 703               if (!(res && parentWindow.isFocused())) {
 704                   return rejectFocusRequestHelper("Waiting for asynchronous processing of the request");
 705               }
 706               return WKeyboardFocusManagerPeer.deliverFocus(lightweightChild,
 707                                                             (Component)target,
 708                                                             temporary,
 709                                                             focusedWindowChangeAllowed,
 710                                                             time, cause);
 711 
 712           case WKeyboardFocusManagerPeer.SNFH_SUCCESS_HANDLED:
 713               // Either lightweight or excessive request - all events are generated.
 714               return true;
 715         }
 716         return false;
 717     }
 718 
 719     private boolean rejectFocusRequestHelper(String logMsg) {
 720         if (focusLog.isLoggable(PlatformLogger.Level.FINER)) {
 721             focusLog.finer(logMsg);
 722         }
 723         WKeyboardFocusManagerPeer.removeLastFocusRequest((Component)target);
 724         return false;
 725     }
 726 
 727     public Image createImage(ImageProducer producer) {
 728         return new ToolkitImage(producer);
 729     }
 730 
 731     public Image createImage(int width, int height) {
 732         Win32GraphicsConfig gc =
 733             (Win32GraphicsConfig)getGraphicsConfiguration();
 734         return gc.createAcceleratedImage((Component)target, width, height);
 735     }
 736 
 737     public VolatileImage createVolatileImage(int width, int height) {
 738         return new SunVolatileImage((Component)target, width, height);
 739     }
 740 
 741     public boolean prepareImage(Image img, int w, int h, ImageObserver o) {
 742         return getToolkit().prepareImage(img, w, h, o);
 743     }
 744 
 745     public int checkImage(Image img, int w, int h, ImageObserver o) {
 746         return getToolkit().checkImage(img, w, h, o);
 747     }
 748 
 749     // Object overrides
 750 
 751     public String toString() {
 752         return getClass().getName() + "[" + target + "]";
 753     }
 754 
 755     // Toolkit & peer internals
 756 
 757     private int updateX1, updateY1, updateX2, updateY2;
 758 
 759     WComponentPeer(Component target) {
 760         this.target = target;
 761         this.paintArea = new RepaintArea();
 762         create(getNativeParent());
 763         // fix for 5088782: check if window object is created successfully
 764         checkCreation();
 765 
 766         createScreenSurface(false);
 767         initialize();
 768         start();  // Initialize enable/disable state, turn on callbacks
 769     }
 770     abstract void create(WComponentPeer parent);
 771 
 772     /**
 773      * Gets the native parent of this peer. We use the term "parent" explicitly,
 774      * because we override the method in top-level window peer implementations.
 775      *
 776      * @return the parent container/owner of this peer.
 777      */
 778     WComponentPeer getNativeParent() {
 779         Container parent = SunToolkit.getNativeContainer((Component) target);
 780         return (WComponentPeer) WToolkit.targetToPeer(parent);
 781     }
 782 
 783     protected void checkCreation()
 784     {
 785         if ((hwnd == 0) || (pData == 0))
 786         {
 787             if (createError != null)
 788             {
 789                 throw createError;
 790             }
 791             else
 792             {
 793                 throw new InternalError("couldn't create component peer");
 794             }
 795         }
 796     }
 797 
 798     synchronized native void start();
 799 
 800     void initialize() {
 801         if (((Component)target).isVisible()) {
 802             show();  // the wnd starts hidden
 803         }
 804         Color fg = ((Component)target).getForeground();
 805         if (fg != null) {
 806             setForeground(fg);
 807         }
 808         // Set background color in C++, to avoid inheriting a parent's color.
 809         Font  f = ((Component)target).getFont();
 810         if (f != null) {
 811             setFont(f);
 812         }
 813         if (! ((Component)target).isEnabled()) {
 814             disable();
 815         }
 816         Rectangle r = ((Component)target).getBounds();
 817         setBounds(r.x, r.y, r.width, r.height, SET_BOUNDS);
 818     }
 819 
 820     // Callbacks for window-system events to the frame
 821 
 822     // Invoke a update() method call on the target
 823     void handleRepaint(int x, int y, int w, int h) {
 824         // Repaints are posted from updateClient now...
 825     }
 826 
 827     // Invoke a paint() method call on the target, after clearing the
 828     // damaged area.
 829     void handleExpose(int x, int y, int w, int h) {
 830         // Bug ID 4081126 & 4129709 - can't do the clearRect() here,
 831         // since it interferes with the java thread working in the
 832         // same window on multi-processor NT machines.
 833 
 834         postPaintIfNecessary(x, y, w, h);
 835     }
 836 
 837     /* Invoke a paint() method call on the target, without clearing the
 838      * damaged area.  This is normally called by a native control after
 839      * it has painted itself.
 840      *
 841      * NOTE: This is called on the privileged toolkit thread. Do not
 842      *       call directly into user code using this thread!
 843      */
 844     public void handlePaint(int x, int y, int w, int h) {
 845         postPaintIfNecessary(x, y, w, h);
 846     }
 847 
 848     private void postPaintIfNecessary(int x, int y, int w, int h) {
 849         if ( !AWTAccessor.getComponentAccessor().getIgnoreRepaint( (Component) target) ) {
 850             PaintEvent event = PaintEventDispatcher.getPaintEventDispatcher().
 851                 createPaintEvent((Component)target, x, y, w, h);
 852             if (event != null) {
 853                 postEvent(event);
 854             }
 855         }
 856     }
 857 
 858     /*
 859      * Post an event. Queue it for execution by the callback thread.
 860      */
 861     void postEvent(AWTEvent event) {
 862         preprocessPostEvent(event);
 863         WToolkit.postEvent(WToolkit.targetToAppContext(target), event);
 864     }
 865 
 866     void preprocessPostEvent(AWTEvent event) {}
 867 
 868     // Routines to support deferred window positioning.
 869     public void beginLayout() {
 870         // Skip all painting till endLayout
 871         isLayouting = true;
 872     }
 873 
 874     public void endLayout() {
 875         if(!paintArea.isEmpty() && !paintPending &&
 876             !((Component)target).getIgnoreRepaint()) {
 877             // if not waiting for native painting repaint damaged area
 878             postEvent(new PaintEvent((Component)target, PaintEvent.PAINT,
 879                           new Rectangle()));
 880         }
 881         isLayouting = false;
 882     }
 883 
 884     public native void beginValidate();
 885     public native void endValidate();
 886 
 887     /**
 888      * DEPRECATED
 889      */
 890     public Dimension minimumSize() {
 891         return getMinimumSize();
 892     }
 893 
 894     /**
 895      * DEPRECATED
 896      */
 897     public Dimension preferredSize() {
 898         return getPreferredSize();
 899     }
 900 
 901     /**
 902      * register a DropTarget with this native peer
 903      */
 904 
 905     public synchronized void addDropTarget(DropTarget dt) {
 906         if (nDropTargets == 0) {
 907             nativeDropTargetContext = addNativeDropTarget();
 908         }
 909         nDropTargets++;
 910     }
 911 
 912     /**
 913      * unregister a DropTarget with this native peer
 914      */
 915 
 916     public synchronized void removeDropTarget(DropTarget dt) {
 917         nDropTargets--;
 918         if (nDropTargets == 0) {
 919             removeNativeDropTarget();
 920             nativeDropTargetContext = 0;
 921         }
 922     }
 923 
 924     /**
 925      * add the native peer's AwtDropTarget COM object
 926      * @return reference to AwtDropTarget object
 927      */
 928 
 929     native long addNativeDropTarget();
 930 
 931     /**
 932      * remove the native peer's AwtDropTarget COM object
 933      */
 934 
 935     native void removeNativeDropTarget();
 936     native boolean nativeHandlesWheelScrolling();
 937 
 938     public boolean handlesWheelScrolling() {
 939         // should this be cached?
 940         return nativeHandlesWheelScrolling();
 941     }
 942 
 943     // Returns true if we are inside begin/endLayout and
 944     // are waiting for native painting
 945     public boolean isPaintPending() {
 946         return paintPending && isLayouting;
 947     }
 948 
 949     /**
 950      * The following multibuffering-related methods delegate to our
 951      * associated GraphicsConfig (Win or WGL) to handle the appropriate
 952      * native windowing system specific actions.
 953      */
 954 
 955     @Override
 956     public void createBuffers(int numBuffers, BufferCapabilities caps)
 957         throws AWTException
 958     {
 959         Win32GraphicsConfig gc =
 960             (Win32GraphicsConfig)getGraphicsConfiguration();
 961         gc.assertOperationSupported((Component)target, numBuffers, caps);
 962 
 963         // Re-create the primary surface with the new number of back buffers
 964         try {
 965             replaceSurfaceData(numBuffers - 1, caps);
 966         } catch (InvalidPipeException e) {
 967             throw new AWTException(e.getMessage());
 968         }
 969     }
 970 
 971     @Override
 972     public void destroyBuffers() {
 973         replaceSurfaceData(0, null);
 974     }
 975 
 976     @Override
 977     public void flip(int x1, int y1, int x2, int y2,
 978                                   BufferCapabilities.FlipContents flipAction)
 979     {
 980         VolatileImage backBuffer = this.backBuffer;
 981         if (backBuffer == null) {
 982             throw new IllegalStateException("Buffers have not been created");
 983         }
 984         Win32GraphicsConfig gc =
 985             (Win32GraphicsConfig)getGraphicsConfiguration();
 986         gc.flip(this, (Component)target, backBuffer, x1, y1, x2, y2, flipAction);
 987     }
 988 
 989     @Override
 990     public synchronized Image getBackBuffer() {
 991         Image backBuffer = this.backBuffer;
 992         if (backBuffer == null) {
 993             throw new IllegalStateException("Buffers have not been created");
 994         }
 995         return backBuffer;
 996     }
 997     public BufferCapabilities getBackBufferCaps() {
 998         return backBufferCaps;
 999     }
1000     public int getBackBuffersNum() {
1001         return numBackBuffers;
1002     }
1003 
1004     /* override and return false on components that DO NOT require
1005        a clearRect() before painting (i.e. native components) */
1006     public boolean shouldClearRectBeforePaint() {
1007         return true;
1008     }
1009 
1010     native void pSetParent(ComponentPeer newNativeParent);
1011 
1012     /**
1013      * @see java.awt.peer.ComponentPeer#reparent
1014      */
1015     public void reparent(ContainerPeer newNativeParent) {
1016         pSetParent(newNativeParent);
1017     }
1018 
1019     /**
1020      * @see java.awt.peer.ComponentPeer#isReparentSupported
1021      */
1022     public boolean isReparentSupported() {
1023         return true;
1024     }
1025 
1026     public void setBoundsOperation(int operation) {
1027     }
1028 
1029     private volatile boolean isAccelCapable = true;
1030 
1031     /**
1032      * Returns whether this component is capable of being hw accelerated.
1033      * More specifically, whether rendering to this component or a
1034      * BufferStrategy's back-buffer for this component can be hw accelerated.
1035      *
1036      * Conditions which could prevent hw acceleration include the toplevel
1037      * window containing this component being
1038      * {@link GraphicsDevice.WindowTranslucency#PERPIXEL_TRANSLUCENT
1039      * PERPIXEL_TRANSLUCENT}.
1040      *
1041      * Another condition is if Xor paint mode was detected when rendering
1042      * to an on-screen accelerated surface associated with this peer.
1043      * in this case both on- and off-screen acceleration for this peer is
1044      * disabled.
1045      *
1046      * @return {@code true} if this component is capable of being hw
1047      * accelerated, {@code false} otherwise
1048      * @see GraphicsDevice.WindowTranslucency#PERPIXEL_TRANSLUCENT
1049      */
1050     public boolean isAccelCapable() {
1051         if (!isAccelCapable ||
1052             !isContainingTopLevelAccelCapable((Component)target))
1053         {
1054             return false;
1055         }
1056 
1057         boolean isTranslucent =
1058             SunToolkit.isContainingTopLevelTranslucent((Component)target);
1059         // D3D/OGL and translucent windows interacted poorly in Windows XP;
1060         // these problems are no longer present in Vista
1061         return !isTranslucent || Win32GraphicsEnvironment.isVistaOS();
1062     }
1063 
1064     /**
1065      * Disables acceleration for this peer.
1066      */
1067     public void disableAcceleration() {
1068         isAccelCapable = false;
1069     }
1070 
1071 
1072     native void setRectangularShape(int lox, int loy, int hix, int hiy,
1073                      Region region);
1074 
1075 
1076     // REMIND: Temp workaround for issues with using HW acceleration
1077     // in the browser on Vista when DWM is enabled.
1078     // @return true if the toplevel container is not an EmbeddedFrame or
1079     // if this EmbeddedFrame is acceleration capable, false otherwise
1080     @SuppressWarnings("deprecation")
1081     private static final boolean isContainingTopLevelAccelCapable(Component c) {
1082         while (c != null && !(c instanceof WEmbeddedFrame)) {
1083             c = c.getParent();
1084         }
1085         if (c == null) {
1086             return true;
1087         }
1088         return ((WEmbeddedFramePeer)c.getPeer()).isAccelCapable();
1089     }
1090 
1091     /**
1092      * Applies the shape to the native component window.
1093      * @since 1.7
1094      */
1095     @SuppressWarnings("deprecation")
1096     public void applyShape(Region shape) {
1097         if (shapeLog.isLoggable(PlatformLogger.Level.FINER)) {
1098             shapeLog.finer("*** INFO: Setting shape: PEER: " + this
1099                             + "; TARGET: " + target
1100                             + "; SHAPE: " + shape);
1101         }
1102 
1103         if (shape != null) {
1104             setRectangularShape(shape.getLoX(), shape.getLoY(), shape.getHiX(), shape.getHiY(),
1105                     (shape.isRectangular() ? null : shape));
1106         } else {
1107             setRectangularShape(0, 0, 0, 0, null);
1108         }
1109     }
1110 
1111     /**
1112      * Lowers this component at the bottom of the above component. If the above parameter
1113      * is null then the method places this component at the top of the Z-order.
1114      */
1115     public void setZOrder(ComponentPeer above) {
1116         long aboveHWND = (above != null) ? ((WComponentPeer)above).getHWnd() : 0;
1117 
1118         setZOrder(aboveHWND);
1119     }
1120 
1121     private native void setZOrder(long above);
1122 }