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