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