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