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