1 /*
   2  * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 
  27 package sun.lwawt;
  28 
  29 import java.awt.*;
  30 
  31 import java.awt.dnd.DropTarget;
  32 import java.awt.dnd.peer.DropTargetPeer;
  33 import java.awt.event.*;
  34 
  35 import java.awt.image.ColorModel;
  36 import java.awt.image.ImageObserver;
  37 import java.awt.image.ImageProducer;
  38 import java.awt.image.VolatileImage;
  39 
  40 import java.awt.peer.ComponentPeer;
  41 import java.awt.peer.ContainerPeer;
  42 
  43 import java.awt.peer.KeyboardFocusManagerPeer;
  44 import java.util.concurrent.atomic.AtomicBoolean;
  45 import java.lang.reflect.Field;
  46 import java.security.AccessController;
  47 import java.security.PrivilegedAction;
  48 
  49 import sun.awt.*;
  50 
  51 import sun.awt.event.IgnorePaintEvent;
  52 
  53 import sun.awt.image.SunVolatileImage;
  54 import sun.awt.image.ToolkitImage;
  55 
  56 import sun.java2d.SunGraphics2D;
  57 import sun.java2d.opengl.OGLRenderQueue;
  58 import sun.java2d.pipe.Region;
  59 
  60 import sun.util.logging.PlatformLogger;
  61 
  62 import javax.swing.JComponent;
  63 import javax.swing.SwingUtilities;
  64 import javax.swing.RepaintManager;
  65 
  66 import com.sun.java.swing.SwingUtilities3;
  67 
  68 public abstract class LWComponentPeer<T extends Component, D extends JComponent>
  69     implements ComponentPeer, DropTargetPeer
  70 {
  71     private static final PlatformLogger focusLog = PlatformLogger.getLogger("sun.lwawt.focus.LWComponentPeer");
  72 
  73     /**
  74      * State lock is to be used for modifications to this peer's fields (e.g.
  75      * bounds, background, font, etc.) It should be the last lock in the lock
  76      * chain
  77      */
  78     private final Object stateLock = new Object();
  79 
  80     /**
  81      * The lock to operate with the peers hierarchy. AWT tree lock is not used
  82      * as there are many peers related ops to be done on the toolkit thread, and
  83      * we don't want to depend on a public lock on this thread
  84      */
  85     private static final Object peerTreeLock = new Object();
  86 
  87     /**
  88      * The associated AWT object.
  89      */
  90     private final T target;
  91 
  92     /**
  93      * Container peer. It may not be the peer of the target's direct parent, for
  94      * example, in the case of hw/lw mixing. However, let's skip this scenario
  95      * for the time being. We also assume the container peer is not null, which
  96      * might also be false if addNotify() is called for a component outside of
  97      * the hierarchy. The exception is LWWindowPeers: their containers are
  98      * always null
  99      */
 100     private final LWContainerPeer<?, ?> containerPeer;
 101 
 102     /**
 103      * Handy reference to the top-level window peer. Window peer is borrowed
 104      * from the containerPeer in constructor, and should also be updated when
 105      * the component is reparented to another container
 106      */
 107     private final LWWindowPeer windowPeer;
 108 
 109     private final AtomicBoolean disposed = new AtomicBoolean(false);
 110 
 111     // Bounds are relative to parent peer
 112     private final Rectangle bounds = new Rectangle();
 113     private Region region;
 114 
 115     // Component state. Should be accessed under the state lock
 116     private boolean visible = false;
 117     private boolean enabled = true;
 118 
 119     private Color background;
 120     private Color foreground;
 121     private Font font;
 122 
 123     /**
 124      * Paint area to coalesce all the paint events and store the target dirty
 125      * area.
 126      */
 127     private final RepaintArea targetPaintArea;
 128 
 129     //   private volatile boolean paintPending;
 130     private volatile boolean isLayouting;
 131 
 132     private final D delegate;
 133     private Container delegateContainer;
 134     private Component delegateDropTarget;
 135     private final Object dropTargetLock = new Object();
 136 
 137     private int fNumDropTargets = 0;
 138     private PlatformDropTarget fDropTarget = null;
 139 
 140     private final PlatformComponent platformComponent;
 141 
 142     /**
 143      * Character with reasonable value between the minimum width and maximum.
 144      */
 145     static final char WIDE_CHAR = '0';
 146 
 147     /**
 148      * The back buffer provide user with a BufferStrategy.
 149      */
 150     private Image backBuffer;
 151 
 152     /**
 153      * All Swing delegates use delegateContainer as a parent. This container
 154      * intentionally do not use parent of the peer.
 155      */
 156     @SuppressWarnings("serial")// Safe: outer class is non-serializable.
 157     private final class DelegateContainer extends Container {
 158         {
 159             enableEvents(0xFFFFFFFF);
 160         }
 161 
 162         // Empty non private constructor was added because access to this
 163         // class shouldn't be emulated by a synthetic accessor method.
 164         DelegateContainer() {
 165             super();
 166         }
 167 
 168         @Override
 169         public boolean isLightweight() {
 170             return false;
 171         }
 172 
 173         @Override
 174         public Point getLocation() {
 175             return getLocationOnScreen();
 176         }
 177 
 178         @Override
 179         public Point getLocationOnScreen() {
 180             return LWComponentPeer.this.getLocationOnScreen();
 181         }
 182 
 183         @Override
 184         public int getX() {
 185             return getLocation().x;
 186         }
 187 
 188         @Override
 189         public int getY() {
 190             return getLocation().y;
 191         }
 192     }
 193 
 194     LWComponentPeer(final T target, final PlatformComponent platformComponent) {
 195         targetPaintArea = new LWRepaintArea();
 196         this.target = target;
 197         this.platformComponent = platformComponent;
 198 
 199         // Container peer is always null for LWWindowPeers, so
 200         // windowPeer is always null for them as well. On the other
 201         // hand, LWWindowPeer shouldn't use windowPeer at all
 202         final Container container = SunToolkit.getNativeContainer(target);
 203         containerPeer = (LWContainerPeer) LWToolkit.targetToPeer(container);
 204         windowPeer = containerPeer != null ? containerPeer.getWindowPeerOrSelf()
 205                                            : null;
 206         // don't bother about z-order here as updateZOrder()
 207         // will be called from addNotify() later anyway
 208         if (containerPeer != null) {
 209             containerPeer.addChildPeer(this);
 210         }
 211 
 212         // the delegate must be created after the target is set
 213         AWTEventListener toolkitListener = null;
 214         synchronized (Toolkit.getDefaultToolkit()) {
 215             try {
 216                 toolkitListener = getToolkitAWTEventListener();
 217                 setToolkitAWTEventListener(null);
 218 
 219                 synchronized (getDelegateLock()) {
 220                     delegate = createDelegate();
 221                     if (delegate != null) {
 222                         delegate.setVisible(false);
 223                         delegateContainer = new DelegateContainer();
 224                         delegateContainer.add(delegate);
 225                         delegateContainer.addNotify();
 226                         delegate.addNotify();
 227                         resetColorsAndFont(delegate);
 228                         delegate.setOpaque(true);
 229                     } else {
 230                         return;
 231                     }
 232                 }
 233 
 234             } finally {
 235                 setToolkitAWTEventListener(toolkitListener);
 236             }
 237 
 238             // todo swing: later on we will probably have one global RM
 239             SwingUtilities3.setDelegateRepaintManager(delegate, new RepaintManager() {
 240                 @Override
 241                 public void addDirtyRegion(final JComponent c, final int x, final int y, final int w, final int h) {
 242                     repaintPeer(SwingUtilities.convertRectangle(
 243                             c, new Rectangle(x, y, w, h), getDelegate()));
 244                 }
 245             });
 246         }
 247     }
 248 
 249     /**
 250      * This method must be called under Toolkit.getDefaultToolkit() lock
 251      * and followed by setToolkitAWTEventListener()
 252      */
 253     protected final AWTEventListener getToolkitAWTEventListener() {
 254         return AccessController.doPrivileged(new PrivilegedAction<AWTEventListener>() {
 255             public AWTEventListener run() {
 256                 Toolkit toolkit = Toolkit.getDefaultToolkit();
 257                 try {
 258                     Field field = Toolkit.class.getDeclaredField("eventListener");
 259                     field.setAccessible(true);
 260                     return (AWTEventListener) field.get(toolkit);
 261                 } catch (Exception e) {
 262                     throw new InternalError(e.toString());
 263                 }
 264             }
 265         });
 266     }
 267 
 268     protected final void setToolkitAWTEventListener(final AWTEventListener listener) {
 269         AccessController.doPrivileged(new PrivilegedAction<Void>() {
 270             public Void run() {
 271                 Toolkit toolkit = Toolkit.getDefaultToolkit();
 272                 try {
 273                     Field field = Toolkit.class.getDeclaredField("eventListener");
 274                     field.setAccessible(true);
 275                     field.set(toolkit, listener);
 276                 } catch (Exception e) {
 277                     throw new InternalError(e.toString());
 278                 }
 279                 return null;
 280             }
 281         });
 282     }
 283 
 284     /**
 285      * This method is called under getDelegateLock().
 286      * Overridden in subclasses.
 287      */
 288     D createDelegate() {
 289         return null;
 290     }
 291 
 292     final D getDelegate() {
 293         return delegate;
 294     }
 295 
 296     /**
 297      * This method should be called under getDelegateLock().
 298      */
 299     Component getDelegateFocusOwner() {
 300         return getDelegate();
 301     }
 302 
 303     /**
 304      * Initializes this peer. The call to initialize() is not placed to
 305      * LWComponentPeer ctor to let the subclass ctor to finish completely first.
 306      * Instead, it's the LWToolkit object who is responsible for initialization.
 307      * Note that we call setVisible() at the end of initialization.
 308      */
 309     public final void initialize() {
 310         platformComponent.initialize(getPlatformWindow());
 311         initializeImpl();
 312         setVisible(target.isVisible());
 313     }
 314 
 315     /**
 316      * Fetching general properties from the target. Should be overridden in
 317      * subclasses to initialize specific peers properties.
 318      */
 319     void initializeImpl() {
 320         // note that these methods can be overridden by the user and
 321         // can return some strange values like null.
 322         setBackground(target.getBackground());
 323         setForeground(target.getForeground());
 324         setFont(target.getFont());
 325         setBounds(target.getBounds());
 326         setEnabled(target.isEnabled());
 327     }
 328 
 329     private static void resetColorsAndFont(final Container c) {
 330         c.setBackground(null);
 331         c.setForeground(null);
 332         c.setFont(null);
 333         for (int i = 0; i < c.getComponentCount(); i++) {
 334             resetColorsAndFont((Container) c.getComponent(i));
 335         }
 336     }
 337 
 338     final Object getStateLock() {
 339         return stateLock;
 340     }
 341 
 342     /**
 343      * Synchronize all operations with the Swing delegates under AWT tree lock,
 344      * using a new separate lock to synchronize access to delegates may lead
 345      * deadlocks. Think of it as a 'virtual EDT'.
 346      *
 347      * @return DelegateLock
 348      */
 349     final Object getDelegateLock() {
 350         return getTarget().getTreeLock();
 351     }
 352 
 353     protected static final Object getPeerTreeLock() {
 354         return peerTreeLock;
 355     }
 356 
 357     public final T getTarget() {
 358         return target;
 359     }
 360 
 361     // Just a helper method
 362     // Returns the window peer or null if this is a window peer
 363     protected final LWWindowPeer getWindowPeer() {
 364         return windowPeer;
 365     }
 366 
 367     // Returns the window peer or 'this' if this is a window peer
 368     protected LWWindowPeer getWindowPeerOrSelf() {
 369         return getWindowPeer();
 370     }
 371 
 372     // Just a helper method
 373     protected final LWContainerPeer<?, ?> getContainerPeer() {
 374         return containerPeer;
 375     }
 376 
 377     public PlatformWindow getPlatformWindow() {
 378         LWWindowPeer windowPeer = getWindowPeer();
 379         return windowPeer.getPlatformWindow();
 380     }
 381 
 382     // ---- PEER METHODS ---- //
 383 
 384     // Just a helper method
 385     public LWToolkit getLWToolkit() {
 386         return LWToolkit.getLWToolkit();
 387     }
 388 
 389     @Override
 390     public final void dispose() {
 391         if (disposed.compareAndSet(false, true)) {
 392             disposeImpl();
 393         }
 394     }
 395 
 396     protected void disposeImpl() {
 397         destroyBuffers();
 398         LWContainerPeer<?, ?> cp = getContainerPeer();
 399         if (cp != null) {
 400             cp.removeChildPeer(this);
 401         }
 402         platformComponent.dispose();
 403         LWToolkit.targetDisposedPeer(getTarget(), this);
 404     }
 405 
 406     public final boolean isDisposed() {
 407         return disposed.get();
 408     }
 409 
 410     /*
 411      * GraphicsConfiguration is borrowed from the parent peer. The
 412      * return value must not be null.
 413      *
 414      * Overridden in LWWindowPeer.
 415      */
 416     @Override
 417     public GraphicsConfiguration getGraphicsConfiguration() {
 418         // Don't check windowPeer for null as it can only happen
 419         // for windows, but this method is overridden in
 420         // LWWindowPeer and doesn't call super()
 421         return getWindowPeer().getGraphicsConfiguration();
 422     }
 423 
 424 
 425     // Just a helper method
 426     public final LWGraphicsConfig getLWGC() {
 427         return (LWGraphicsConfig) getGraphicsConfiguration();
 428     }
 429 
 430     /*
 431      * Overridden in LWWindowPeer to replace its surface
 432      * data and back buffer.
 433      */
 434     @Override
 435     public boolean updateGraphicsData(GraphicsConfiguration gc) {
 436         // TODO: not implemented
 437 //        throw new RuntimeException("Has not been implemented yet.");
 438         return false;
 439     }
 440 
 441     @Override
 442     public Graphics getGraphics() {
 443         final Graphics g = getOnscreenGraphics();
 444         if (g != null) {
 445             synchronized (getPeerTreeLock()){
 446                 applyConstrain(g);
 447             }
 448         }
 449         return g;
 450     }
 451 
 452     /*
 453      * Peer Graphics is borrowed from the parent peer, while
 454      * foreground and background colors and font are specific to
 455      * this peer.
 456      */
 457     public final Graphics getOnscreenGraphics() {
 458         final LWWindowPeer wp = getWindowPeerOrSelf();
 459         return wp.getOnscreenGraphics(getForeground(), getBackground(),
 460                                       getFont());
 461 
 462     }
 463 
 464     private void applyConstrain(final Graphics g) {
 465         final SunGraphics2D sg2d = (SunGraphics2D) g;
 466         final Rectangle size = localToWindow(getSize());
 467         sg2d.constrain(size.x, size.y, size.width, size.height, getVisibleRegion());
 468     }
 469 
 470     Region getVisibleRegion() {
 471         return computeVisibleRect(this, getRegion());
 472     }
 473 
 474     static final Region computeVisibleRect(final LWComponentPeer<?, ?> c,
 475                                            Region region) {
 476         final LWContainerPeer<?, ?> p = c.getContainerPeer();
 477         if (p != null) {
 478             final Rectangle r = c.getBounds();
 479             region = region.getTranslatedRegion(r.x, r.y);
 480             region = region.getIntersection(p.getRegion());
 481             region = region.getIntersection(p.getContentSize());
 482             region = p.cutChildren(region, c);
 483             region = computeVisibleRect(p, region);
 484             region = region.getTranslatedRegion(-r.x, -r.y);
 485         }
 486         return region;
 487     }
 488 
 489     @Override
 490     public ColorModel getColorModel() {
 491         // Is it a correct implementation?
 492         return getGraphicsConfiguration().getColorModel();
 493     }
 494 
 495     public boolean isTranslucent() {
 496         // Translucent windows of the top level are supported only
 497         return false;
 498     }
 499 
 500     @Override
 501     public final void createBuffers(int numBuffers, BufferCapabilities caps)
 502             throws AWTException {
 503         getLWGC().assertOperationSupported(numBuffers, caps);
 504         final Image buffer = getLWGC().createBackBuffer(this);
 505         synchronized (getStateLock()) {
 506             backBuffer = buffer;
 507         }
 508     }
 509 
 510     @Override
 511     public final Image getBackBuffer() {
 512         synchronized (getStateLock()) {
 513             if (backBuffer != null) {
 514                 return backBuffer;
 515             }
 516         }
 517         throw new IllegalStateException("Buffers have not been created");
 518     }
 519 
 520     @Override
 521     public final void flip(int x1, int y1, int x2, int y2,
 522                      BufferCapabilities.FlipContents flipAction) {
 523         getLWGC().flip(this, getBackBuffer(), x1, y1, x2, y2, flipAction);
 524     }
 525 
 526     @Override
 527     public final void destroyBuffers() {
 528         final Image oldBB;
 529         synchronized (getStateLock()) {
 530             oldBB = backBuffer;
 531             backBuffer = null;
 532         }
 533         getLWGC().destroyBackBuffer(oldBB);
 534     }
 535 
 536     // Helper method
 537     public void setBounds(Rectangle r) {
 538         setBounds(r.x, r.y, r.width, r.height, SET_BOUNDS);
 539     }
 540 
 541     /**
 542      * This method could be called on the toolkit thread.
 543      */
 544     @Override
 545     public void setBounds(int x, int y, int w, int h, int op) {
 546         setBounds(x, y, w, h, op, true, false);
 547     }
 548 
 549     protected void setBounds(int x, int y, int w, int h, int op, boolean notify,
 550                              final boolean updateTarget) {
 551         Rectangle oldBounds;
 552         synchronized (getStateLock()) {
 553             oldBounds = new Rectangle(bounds);
 554             if ((op & (SET_LOCATION | SET_BOUNDS)) != 0) {
 555                 bounds.x = x;
 556                 bounds.y = y;
 557             }
 558             if ((op & (SET_SIZE | SET_BOUNDS)) != 0) {
 559                 bounds.width = w;
 560                 bounds.height = h;
 561             }
 562         }
 563         boolean moved = (oldBounds.x != x) || (oldBounds.y != y);
 564         boolean resized = (oldBounds.width != w) || (oldBounds.height != h);
 565         if (!moved && !resized) {
 566             return;
 567         }
 568         final D delegate = getDelegate();
 569         if (delegate != null) {
 570             synchronized (getDelegateLock()) {
 571                 delegateContainer.setBounds(0, 0, w, h);
 572                 delegate.setBounds(delegateContainer.getBounds());
 573                 // TODO: the following means that the delegateContainer NEVER gets validated. That's WRONG!
 574                 delegate.validate();
 575             }
 576         }
 577 
 578         final Point locationInWindow = localToWindow(0, 0);
 579         platformComponent.setBounds(locationInWindow.x, locationInWindow.y, w,
 580                                     h);
 581         if (notify) {
 582             repaintOldNewBounds(oldBounds);
 583             if (resized) {
 584                 handleResize(w, h, updateTarget);
 585             }
 586             if (moved) {
 587                 handleMove(x, y, updateTarget);
 588             }
 589         }
 590     }
 591 
 592     public final Rectangle getBounds() {
 593         synchronized (getStateLock()) {
 594             // Return a copy to prevent subsequent modifications
 595             return bounds.getBounds();
 596         }
 597     }
 598 
 599     public final Rectangle getSize() {
 600         synchronized (getStateLock()) {
 601             // Return a copy to prevent subsequent modifications
 602             return new Rectangle(bounds.width, bounds.height);
 603         }
 604     }
 605 
 606     @Override
 607     public Point getLocationOnScreen() {
 608         Point windowLocation = getWindowPeer().getLocationOnScreen();
 609         Point locationInWindow = localToWindow(0, 0);
 610         return new Point(windowLocation.x + locationInWindow.x,
 611                 windowLocation.y + locationInWindow.y);
 612     }
 613 
 614     /**
 615      * Returns the cursor of the peer, which is cursor of the target by default,
 616      * but peer can override this behavior.
 617      *
 618      * @param p Point relative to the peer.
 619      * @return Cursor of the peer or null if default cursor should be used.
 620      */
 621     Cursor getCursor(final Point p) {
 622         return getTarget().getCursor();
 623     }
 624 
 625     @Override
 626     public void setBackground(final Color c) {
 627         final Color oldBg = getBackground();
 628         if (oldBg == c || (oldBg != null && oldBg.equals(c))) {
 629             return;
 630         }
 631         synchronized (getStateLock()) {
 632             background = c;
 633         }
 634         final D delegate = getDelegate();
 635         if (delegate != null) {
 636             synchronized (getDelegateLock()) {
 637                 // delegate will repaint the target
 638                 delegate.setBackground(c);
 639             }
 640         } else {
 641             repaintPeer();
 642         }
 643     }
 644 
 645     public final Color getBackground() {
 646         synchronized (getStateLock()) {
 647             return background;
 648         }
 649     }
 650 
 651     @Override
 652     public void setForeground(final Color c) {
 653         final Color oldFg = getForeground();
 654         if (oldFg == c || (oldFg != null && oldFg.equals(c))) {
 655             return;
 656         }
 657         synchronized (getStateLock()) {
 658             foreground = c;
 659         }
 660         final D delegate = getDelegate();
 661         if (delegate != null) {
 662             synchronized (getDelegateLock()) {
 663                 // delegate will repaint the target
 664                 delegate.setForeground(c);
 665             }
 666         } else {
 667             repaintPeer();
 668         }
 669     }
 670 
 671     protected final Color getForeground() {
 672         synchronized (getStateLock()) {
 673             return foreground;
 674         }
 675     }
 676 
 677     @Override
 678     public void setFont(final Font f) {
 679         final Font oldF = getFont();
 680         if (oldF == f || (oldF != null && oldF.equals(f))) {
 681             return;
 682         }
 683         synchronized (getStateLock()) {
 684             font = f;
 685         }
 686         final D delegate = getDelegate();
 687         if (delegate != null) {
 688             synchronized (getDelegateLock()) {
 689                 // delegate will repaint the target
 690                 delegate.setFont(f);
 691             }
 692         } else {
 693             repaintPeer();
 694         }
 695     }
 696 
 697     protected final Font getFont() {
 698         synchronized (getStateLock()) {
 699             return font;
 700         }
 701     }
 702 
 703     @Override
 704     public FontMetrics getFontMetrics(final Font f) {
 705         // Borrow the metrics from the top-level window
 706 //        return getWindowPeer().getFontMetrics(f);
 707         // Obtain the metrics from the offscreen window where this peer is
 708         // mostly drawn to.
 709         // TODO: check for "use platform metrics" settings
 710         final Graphics g = getOnscreenGraphics();
 711         if (g != null) {
 712             try {
 713                 return g.getFontMetrics(f);
 714             } finally {
 715                 g.dispose();
 716             }
 717         }
 718         synchronized (getDelegateLock()) {
 719             return delegateContainer.getFontMetrics(f);
 720         }
 721     }
 722 
 723     @Override
 724     public void setEnabled(final boolean e) {
 725         boolean status = e;
 726         final LWComponentPeer<?, ?> cp = getContainerPeer();
 727         if (cp != null) {
 728             status &= cp.isEnabled();
 729         }
 730         synchronized (getStateLock()) {
 731             if (enabled == status) {
 732                 return;
 733             }
 734             enabled = status;
 735         }
 736 
 737         final D delegate = getDelegate();
 738 
 739         if (delegate != null) {
 740             synchronized (getDelegateLock()) {
 741                 delegate.setEnabled(status);
 742             }
 743         } else {
 744             repaintPeer();
 745         }
 746     }
 747 
 748     // Helper method
 749     public final boolean isEnabled() {
 750         synchronized (getStateLock()) {
 751             return enabled;
 752         }
 753     }
 754 
 755     @Override
 756     public void setVisible(final boolean v) {
 757         synchronized (getStateLock()) {
 758             if (visible == v) {
 759                 return;
 760             }
 761             visible = v;
 762         }
 763         setVisibleImpl(v);
 764     }
 765 
 766     protected void setVisibleImpl(final boolean v) {
 767         final D delegate = getDelegate();
 768 
 769         if (delegate != null) {
 770             synchronized (getDelegateLock()) {
 771                 delegate.setVisible(v);
 772             }
 773         }
 774         if (visible) {
 775             repaintPeer();
 776         } else {
 777             repaintParent(getBounds());
 778         }
 779     }
 780 
 781     // Helper method
 782     public final boolean isVisible() {
 783         synchronized (getStateLock()) {
 784             return visible;
 785         }
 786     }
 787 
 788     @Override
 789     public void paint(final Graphics g) {
 790         getTarget().paint(g);
 791     }
 792 
 793     @Override
 794     public void print(final Graphics g) {
 795         getTarget().print(g);
 796     }
 797 
 798     @Override
 799     public void reparent(ContainerPeer newContainer) {
 800         // TODO: not implemented
 801         throw new UnsupportedOperationException("ComponentPeer.reparent()");
 802     }
 803 
 804     @Override
 805     public boolean isReparentSupported() {
 806         // TODO: not implemented
 807         return false;
 808     }
 809 
 810     @Override
 811     public void setZOrder(final ComponentPeer above) {
 812         LWContainerPeer<?, ?> cp = getContainerPeer();
 813         // Don't check containerPeer for null as it can only happen
 814         // for windows, but this method is overridden in
 815         // LWWindowPeer and doesn't call super()
 816         cp.setChildPeerZOrder(this, (LWComponentPeer<?, ?>) above);
 817     }
 818 
 819     @Override
 820     public void coalescePaintEvent(PaintEvent e) {
 821         if (!(e instanceof IgnorePaintEvent)) {
 822             Rectangle r = e.getUpdateRect();
 823             if ((r != null) && !r.isEmpty()) {
 824                 targetPaintArea.add(r, e.getID());
 825             }
 826         }
 827     }
 828 
 829     /*
 830      * Should be overridden in subclasses which use complex Swing components.
 831      */
 832     @Override
 833     public void layout() {
 834         // TODO: not implemented
 835     }
 836 
 837     @Override
 838     public boolean isObscured() {
 839         // TODO: not implemented
 840         return false;
 841     }
 842 
 843     @Override
 844     public boolean canDetermineObscurity() {
 845         // TODO: not implemented
 846         return false;
 847     }
 848 
 849     /**
 850      * Determines the preferred size of the component. By default forwards the
 851      * request to the Swing helper component. Should be overridden in subclasses
 852      * if required.
 853      */
 854     @Override
 855     public Dimension getPreferredSize() {
 856         final Dimension size;
 857         synchronized (getDelegateLock()) {
 858             size = getDelegate().getPreferredSize();
 859         }
 860         return validateSize(size);
 861     }
 862 
 863     /**
 864      * Determines the minimum size of the component. By default forwards the
 865      * request to the Swing helper component. Should be overridden in subclasses
 866      * if required.
 867      */
 868     @Override
 869     public Dimension getMinimumSize() {
 870         final Dimension size;
 871         synchronized (getDelegateLock()) {
 872             size = getDelegate().getMinimumSize();
 873         }
 874         return validateSize(size);
 875     }
 876 
 877     /**
 878      * In some situations delegates can return empty minimum/preferred size.
 879      * (For example: empty JLabel, etc), but awt components never should be
 880      * empty. In the XPeers or WPeers we use some magic constants, but here we
 881      * try to use something more useful,
 882      */
 883     private Dimension validateSize(final Dimension size) {
 884         if (size.width == 0 || size.height == 0) {
 885             final FontMetrics fm = getFontMetrics(getFont());
 886             size.width = fm.charWidth(WIDE_CHAR);
 887             size.height = fm.getHeight();
 888         }
 889         return size;
 890     }
 891 
 892     @Override
 893     public void updateCursorImmediately() {
 894         getLWToolkit().getCursorManager().updateCursor();
 895     }
 896 
 897     @Override
 898     public boolean isFocusable() {
 899         // Overridden in focusable subclasses like buttons
 900         return false;
 901     }
 902 
 903     @Override
 904     public boolean requestFocus(Component lightweightChild, boolean temporary,
 905                                 boolean focusedWindowChangeAllowed, long time,
 906                                 FocusEvent.Cause cause)
 907     {
 908         if (focusLog.isLoggable(PlatformLogger.Level.FINEST)) {
 909             focusLog.finest("lightweightChild=" + lightweightChild + ", temporary=" + temporary +
 910                             ", focusedWindowChangeAllowed=" + focusedWindowChangeAllowed +
 911                             ", time= " + time + ", cause=" + cause);
 912         }
 913         if (LWKeyboardFocusManagerPeer.processSynchronousLightweightTransfer(
 914                 getTarget(), lightweightChild, temporary,
 915                 focusedWindowChangeAllowed, time)) {
 916             return true;
 917         }
 918 
 919         int result = LWKeyboardFocusManagerPeer.shouldNativelyFocusHeavyweight(
 920                 getTarget(), lightweightChild, temporary,
 921                 focusedWindowChangeAllowed, time, cause);
 922         switch (result) {
 923             case LWKeyboardFocusManagerPeer.SNFH_FAILURE:
 924                 return false;
 925             case LWKeyboardFocusManagerPeer.SNFH_SUCCESS_PROCEED:
 926                 Window parentWindow = SunToolkit.getContainingWindow(getTarget());
 927                 if (parentWindow == null) {
 928                     focusLog.fine("request rejected, parentWindow is null");
 929                     LWKeyboardFocusManagerPeer.removeLastFocusRequest(getTarget());
 930                     return false;
 931                 }
 932                 final LWWindowPeer parentPeer =
 933                         AWTAccessor.getComponentAccessor()
 934                                    .getPeer(parentWindow);
 935                 if (parentPeer == null) {
 936                     focusLog.fine("request rejected, parentPeer is null");
 937                     LWKeyboardFocusManagerPeer.removeLastFocusRequest(getTarget());
 938                     return false;
 939                 }
 940 
 941                 // A fix for 7145768. Ensure the parent window is currently natively focused.
 942                 // The more evident place to perform this check is in KFM.shouldNativelyFocusHeavyweight,
 943                 // however that is the shared code and this particular problem's reproducibility has
 944                 // platform specifics. So, it was decided to narrow down the fix to lwawt (OSX) in
 945                 // current release. TODO: consider fixing it in the shared code.
 946                 if (!focusedWindowChangeAllowed) {
 947                     LWWindowPeer decoratedPeer = parentPeer.isSimpleWindow() ?
 948                         LWWindowPeer.getOwnerFrameDialog(parentPeer) : parentPeer;
 949 
 950                     if (decoratedPeer == null || !decoratedPeer.getPlatformWindow().isActive()) {
 951                         if (focusLog.isLoggable(PlatformLogger.Level.FINE)) {
 952                             focusLog.fine("request rejected, focusedWindowChangeAllowed==false, " +
 953                                           "decoratedPeer is inactive: " + decoratedPeer);
 954                         }
 955                         LWKeyboardFocusManagerPeer.removeLastFocusRequest(getTarget());
 956                         return false;
 957                     }
 958                 }
 959 
 960                 boolean res = parentPeer.requestWindowFocus(cause);
 961                 // If parent window can be made focused and has been made focused (synchronously)
 962                 // then we can proceed with children, otherwise we retreat
 963                 if (!res || !parentWindow.isFocused()) {
 964                     if (focusLog.isLoggable(PlatformLogger.Level.FINE)) {
 965                         focusLog.fine("request rejected, res= " + res + ", parentWindow.isFocused()=" +
 966                                       parentWindow.isFocused());
 967                     }
 968                     LWKeyboardFocusManagerPeer.removeLastFocusRequest(getTarget());
 969                     return false;
 970                 }
 971 
 972                 KeyboardFocusManagerPeer kfmPeer = LWKeyboardFocusManagerPeer.getInstance();
 973                 Component focusOwner = kfmPeer.getCurrentFocusOwner();
 974                 return LWKeyboardFocusManagerPeer.deliverFocus(lightweightChild,
 975                         getTarget(), temporary,
 976                         focusedWindowChangeAllowed,
 977                         time, cause, focusOwner);
 978 
 979             case LWKeyboardFocusManagerPeer.SNFH_SUCCESS_HANDLED:
 980                 return true;
 981         }
 982 
 983         return false;
 984     }
 985 
 986     @Override
 987     public final Image createImage(final ImageProducer producer) {
 988         return new ToolkitImage(producer);
 989     }
 990 
 991     @Override
 992     public final Image createImage(final int width, final int height) {
 993         return getLWGC().createAcceleratedImage(getTarget(), width, height);
 994     }
 995 
 996     @Override
 997     public final VolatileImage createVolatileImage(final int w, final int h) {
 998         return new SunVolatileImage(getTarget(), w, h);
 999     }
1000 
1001     @Override
1002     public boolean prepareImage(Image img, int w, int h, ImageObserver o) {
1003         // TODO: is it a right/complete implementation?
1004         return Toolkit.getDefaultToolkit().prepareImage(img, w, h, o);
1005     }
1006 
1007     @Override
1008     public int checkImage(Image img, int w, int h, ImageObserver o) {
1009         // TODO: is it a right/complete implementation?
1010         return Toolkit.getDefaultToolkit().checkImage(img, w, h, o);
1011     }
1012 
1013     @Override
1014     public boolean handlesWheelScrolling() {
1015         // TODO: not implemented
1016         return false;
1017     }
1018 
1019     @Override
1020     public final void applyShape(final Region shape) {
1021         synchronized (getStateLock()) {
1022             if (region == shape || (region != null && region.equals(shape))) {
1023                 return;
1024             }
1025         }
1026         applyShapeImpl(shape);
1027     }
1028 
1029     void applyShapeImpl(final Region shape) {
1030         synchronized (getStateLock()) {
1031             if (shape != null) {
1032                 region = Region.WHOLE_REGION.getIntersection(shape);
1033             } else {
1034                 region = null;
1035             }
1036         }
1037         repaintParent(getBounds());
1038     }
1039 
1040     protected final Region getRegion() {
1041         synchronized (getStateLock()) {
1042             return isShaped() ? region : Region.getInstance(getSize());
1043         }
1044     }
1045 
1046     public boolean isShaped() {
1047         synchronized (getStateLock()) {
1048             return region != null;
1049         }
1050     }
1051 
1052     // DropTargetPeer Method
1053     @Override
1054     public void addDropTarget(DropTarget dt) {
1055         LWWindowPeer winPeer = getWindowPeerOrSelf();
1056         if (winPeer != null && winPeer != this) {
1057             // We need to register the DropTarget in the
1058             // peer of the window ancestor of the component
1059             winPeer.addDropTarget(dt);
1060         } else {
1061             synchronized (dropTargetLock) {
1062                 // 10-14-02 VL: Windows WComponentPeer would add (or remove) the drop target only
1063                 // if it's the first (or last) one for the component. Otherwise this call is a no-op.
1064                 if (++fNumDropTargets == 1) {
1065                     // Having a non-null drop target would be an error but let's check just in case:
1066                     if (fDropTarget != null) {
1067                         throw new IllegalStateException("Current drop target is not null");
1068                     }
1069                     // Create a new drop target:
1070                     fDropTarget = LWToolkit.getLWToolkit().createDropTarget(dt, target, this);
1071                 }
1072             }
1073         }
1074     }
1075 
1076     // DropTargetPeer Method
1077     @Override
1078     public void removeDropTarget(DropTarget dt) {
1079         LWWindowPeer winPeer = getWindowPeerOrSelf();
1080         if (winPeer != null && winPeer != this) {
1081             // We need to unregister the DropTarget in the
1082             // peer of the window ancestor of the component
1083             winPeer.removeDropTarget(dt);
1084         } else {
1085             synchronized (dropTargetLock){
1086                 // 10-14-02 VL: Windows WComponentPeer would add (or remove) the drop target only
1087                 // if it's the first (or last) one for the component. Otherwise this call is a no-op.
1088                 if (--fNumDropTargets == 0) {
1089                     // Having a null drop target would be an error but let's check just in case:
1090                     if (fDropTarget != null) {
1091                         // Dispose of the drop target:
1092                         fDropTarget.dispose();
1093                         fDropTarget = null;
1094                     } else
1095                         System.err.println("CComponent.removeDropTarget(): current drop target is null.");
1096                 }
1097             }
1098         }
1099     }
1100 
1101     // ---- PEER NOTIFICATIONS ---- //
1102 
1103     /**
1104      * Called when this peer's location has been changed either as a result
1105      * of target.setLocation() or as a result of user actions (window is
1106      * dragged with mouse).
1107      *
1108      * This method could be called on the toolkit thread.
1109      */
1110     protected final void handleMove(final int x, final int y,
1111                                     final boolean updateTarget) {
1112         if (updateTarget) {
1113             AWTAccessor.getComponentAccessor().setLocation(getTarget(), x, y);
1114         }
1115         postEvent(new ComponentEvent(getTarget(),
1116                                      ComponentEvent.COMPONENT_MOVED));
1117     }
1118 
1119     /**
1120      * Called when this peer's size has been changed either as a result of
1121      * target.setSize() or as a result of user actions (window is resized).
1122      *
1123      * This method could be called on the toolkit thread.
1124      */
1125     protected final void handleResize(final int w, final int h,
1126                                       final boolean updateTarget) {
1127         Image oldBB = null;
1128         synchronized (getStateLock()) {
1129             if (backBuffer != null) {
1130                 oldBB = backBuffer;
1131                 backBuffer = getLWGC().createBackBuffer(this);
1132             }
1133         }
1134         getLWGC().destroyBackBuffer(oldBB);
1135 
1136         if (updateTarget) {
1137             AWTAccessor.getComponentAccessor().setSize(getTarget(), w, h);
1138         }
1139         postEvent(new ComponentEvent(getTarget(),
1140                                      ComponentEvent.COMPONENT_RESIZED));
1141     }
1142 
1143     protected final void repaintOldNewBounds(final Rectangle oldB) {
1144         repaintParent(oldB);
1145         repaintPeer(getSize());
1146     }
1147 
1148     protected final void repaintParent(final Rectangle oldB) {
1149         final LWContainerPeer<?, ?> cp = getContainerPeer();
1150         if (cp != null) {
1151             // Repaint unobscured part of the parent
1152             cp.repaintPeer(cp.getContentSize().intersection(oldB));
1153         }
1154     }
1155 
1156     // ---- EVENTS ---- //
1157 
1158     /**
1159      * Post an event to the proper Java EDT.
1160      */
1161     public void postEvent(final AWTEvent event) {
1162         LWToolkit.postEvent(event);
1163     }
1164 
1165     protected void postPaintEvent(int x, int y, int w, int h) {
1166         // TODO: call getIgnoreRepaint() directly with the right ACC
1167         if (AWTAccessor.getComponentAccessor().getIgnoreRepaint(target)) {
1168             return;
1169         }
1170         PaintEvent event = PaintEventDispatcher.getPaintEventDispatcher().
1171                 createPaintEvent(getTarget(), x, y, w, h);
1172         if (event != null) {
1173             postEvent(event);
1174         }
1175     }
1176 
1177     /*
1178      * Gives a chance for the peer to handle the event after it's been
1179      * processed by the target.
1180      */
1181     @Override
1182     public void handleEvent(AWTEvent e) {
1183         if ((e instanceof InputEvent) && ((InputEvent) e).isConsumed()) {
1184             return;
1185         }
1186         switch (e.getID()) {
1187             case FocusEvent.FOCUS_GAINED:
1188             case FocusEvent.FOCUS_LOST:
1189                 handleJavaFocusEvent((FocusEvent) e);
1190                 break;
1191             case PaintEvent.PAINT:
1192                 // Got a native paint event
1193 //                paintPending = false;
1194                 // fall through to the next statement
1195             case PaintEvent.UPDATE:
1196                 handleJavaPaintEvent();
1197                 break;
1198             case MouseEvent.MOUSE_PRESSED:
1199                 handleJavaMouseEvent((MouseEvent)e);
1200         }
1201 
1202         sendEventToDelegate(e);
1203     }
1204 
1205     protected void sendEventToDelegate(final AWTEvent e) {
1206         if (getDelegate() == null || !isShowing() || !isEnabled()) {
1207             return;
1208         }
1209         synchronized (getDelegateLock()) {
1210             AWTEvent delegateEvent = createDelegateEvent(e);
1211             if (delegateEvent != null) {
1212                 AWTAccessor.getComponentAccessor()
1213                         .processEvent((Component) delegateEvent.getSource(),
1214                                 delegateEvent);
1215                 if (delegateEvent instanceof KeyEvent) {
1216                     KeyEvent ke = (KeyEvent) delegateEvent;
1217                     SwingUtilities.processKeyBindings(ke);
1218                 }
1219             }
1220         }
1221     }
1222 
1223     /**
1224      * Changes the target of the AWTEvent from awt component to appropriate
1225      * swing delegate.
1226      */
1227     private AWTEvent createDelegateEvent(final AWTEvent e) {
1228         // TODO modifiers should be changed to getModifiers()|getModifiersEx()?
1229         AWTEvent delegateEvent = null;
1230         if (e instanceof MouseWheelEvent) {
1231             MouseWheelEvent me = (MouseWheelEvent) e;
1232             delegateEvent = new MouseWheelEvent(
1233                     delegate, me.getID(), me.getWhen(),
1234                     me.getModifiers(),
1235                     me.getX(), me.getY(),
1236                     me.getXOnScreen(), me.getYOnScreen(),
1237                     me.getClickCount(),
1238                     me.isPopupTrigger(),
1239                     me.getScrollType(),
1240                     me.getScrollAmount(),
1241                     me.getWheelRotation(),
1242                     me.getPreciseWheelRotation());
1243         } else if (e instanceof MouseEvent) {
1244             MouseEvent me = (MouseEvent) e;
1245 
1246             Component eventTarget = SwingUtilities.getDeepestComponentAt(delegate, me.getX(), me.getY());
1247 
1248             if (me.getID() == MouseEvent.MOUSE_DRAGGED) {
1249                 if (delegateDropTarget == null) {
1250                     delegateDropTarget = eventTarget;
1251                 } else {
1252                     eventTarget = delegateDropTarget;
1253                 }
1254             }
1255             if (me.getID() == MouseEvent.MOUSE_RELEASED && delegateDropTarget != null) {
1256                 eventTarget = delegateDropTarget;
1257                 delegateDropTarget = null;
1258             }
1259             if (eventTarget == null) {
1260                 eventTarget = delegate;
1261             }
1262             delegateEvent = SwingUtilities.convertMouseEvent(getTarget(), me, eventTarget);
1263         } else if (e instanceof KeyEvent) {
1264             KeyEvent ke = (KeyEvent) e;
1265             delegateEvent = new KeyEvent(getDelegateFocusOwner(), ke.getID(), ke.getWhen(),
1266                     ke.getModifiers(), ke.getKeyCode(), ke.getKeyChar(), ke.getKeyLocation());
1267             AWTAccessor.getKeyEventAccessor().setExtendedKeyCode((KeyEvent) delegateEvent,
1268                     ke.getExtendedKeyCode());
1269         } else if (e instanceof FocusEvent) {
1270             FocusEvent fe = (FocusEvent) e;
1271             delegateEvent = new FocusEvent(getDelegateFocusOwner(), fe.getID(), fe.isTemporary());
1272         }
1273         return delegateEvent;
1274     }
1275 
1276     protected void handleJavaMouseEvent(MouseEvent e) {
1277         Component target = getTarget();
1278         assert (e.getSource() == target);
1279 
1280         if (!target.isFocusOwner() && LWKeyboardFocusManagerPeer.shouldFocusOnClick(target)) {
1281             LWKeyboardFocusManagerPeer.requestFocusFor(target, FocusEvent.Cause.MOUSE_EVENT);
1282         }
1283     }
1284 
1285     /**
1286      * Handler for FocusEvents.
1287      */
1288     void handleJavaFocusEvent(final FocusEvent e) {
1289         // Note that the peer receives all the FocusEvents from
1290         // its lightweight children as well
1291         KeyboardFocusManagerPeer kfmPeer = LWKeyboardFocusManagerPeer.getInstance();
1292         kfmPeer.setCurrentFocusOwner(e.getID() == FocusEvent.FOCUS_GAINED ? getTarget() : null);
1293     }
1294 
1295     /**
1296      * All peers should clear background before paint.
1297      *
1298      * @return false on components that DO NOT require a clearRect() before
1299      *         painting.
1300      */
1301     protected final boolean shouldClearRectBeforePaint() {
1302         // TODO: sun.awt.noerasebackground
1303         return true;
1304     }
1305 
1306     /**
1307      * Handler for PAINT and UPDATE PaintEvents.
1308      */
1309     private void handleJavaPaintEvent() {
1310         // Skip all painting while layouting and all UPDATEs
1311         // while waiting for native paint
1312 //        if (!isLayouting && !paintPending) {
1313         if (!isLayouting()) {
1314             targetPaintArea.paint(getTarget(), shouldClearRectBeforePaint());
1315         }
1316     }
1317 
1318     // ---- UTILITY METHODS ---- //
1319 
1320     /**
1321      * Finds a top-most visible component for the given point. The location is
1322      * specified relative to the peer's parent.
1323      */
1324     LWComponentPeer<?, ?> findPeerAt(final int x, final int y) {
1325         final Rectangle r = getBounds();
1326         final Region sh = getRegion();
1327         final boolean found = isVisible() && sh.contains(x - r.x, y - r.y);
1328         return found ? this : null;
1329     }
1330 
1331     /*
1332      * Translated the given point in Window coordinates to the point in
1333      * coordinates local to this component. The given window peer must be
1334      * the window where this component is in.
1335      */
1336     public Point windowToLocal(int x, int y, LWWindowPeer wp) {
1337         return windowToLocal(new Point(x, y), wp);
1338     }
1339 
1340     public Point windowToLocal(Point p, LWWindowPeer wp) {
1341         LWComponentPeer<?, ?> cp = this;
1342         while (cp != wp) {
1343             Rectangle cpb = cp.getBounds();
1344             p.x -= cpb.x;
1345             p.y -= cpb.y;
1346             cp = cp.getContainerPeer();
1347         }
1348         // Return a copy to prevent subsequent modifications
1349         return new Point(p);
1350     }
1351 
1352     public Rectangle windowToLocal(Rectangle r, LWWindowPeer wp) {
1353         Point p = windowToLocal(r.getLocation(), wp);
1354         return new Rectangle(p, r.getSize());
1355     }
1356 
1357     public Point localToWindow(int x, int y) {
1358         return localToWindow(new Point(x, y));
1359     }
1360 
1361     public Point localToWindow(Point p) {
1362         LWComponentPeer<?, ?> cp = getContainerPeer();
1363         Rectangle r = getBounds();
1364         while (cp != null) {
1365             p.x += r.x;
1366             p.y += r.y;
1367             r = cp.getBounds();
1368             cp = cp.getContainerPeer();
1369         }
1370         // Return a copy to prevent subsequent modifications
1371         return new Point(p);
1372     }
1373 
1374     public Rectangle localToWindow(Rectangle r) {
1375         Point p = localToWindow(r.getLocation());
1376         return new Rectangle(p, r.getSize());
1377     }
1378 
1379     public final void repaintPeer() {
1380         repaintPeer(getSize());
1381     }
1382 
1383     void repaintPeer(final Rectangle r) {
1384         final Rectangle toPaint = getSize().intersection(r);
1385         if (!isShowing() || toPaint.isEmpty()) {
1386             return;
1387         }
1388 
1389         postPaintEvent(toPaint.x, toPaint.y, toPaint.width, toPaint.height);
1390     }
1391 
1392     /**
1393      * Determines whether this peer is showing on screen. This means that the
1394      * peer must be visible, and it must be in a container that is visible and
1395      * showing.
1396      *
1397      * @see #isVisible()
1398      */
1399     protected final boolean isShowing() {
1400         synchronized (getPeerTreeLock()) {
1401             if (isVisible()) {
1402                 final LWContainerPeer<?, ?> container = getContainerPeer();
1403                 return (container == null) || container.isShowing();
1404             }
1405         }
1406         return false;
1407     }
1408 
1409     /**
1410      * Paints the peer. Delegate the actual painting to Swing components.
1411      */
1412     protected final void paintPeer(final Graphics g) {
1413         final D delegate = getDelegate();
1414         if (delegate != null) {
1415             if (!SwingUtilities.isEventDispatchThread()) {
1416                 throw new InternalError("Painting must be done on EDT");
1417             }
1418             synchronized (getDelegateLock()) {
1419                 // JComponent.print() is guaranteed to not affect the double buffer
1420                 getDelegate().print(g);
1421             }
1422         }
1423     }
1424 
1425     protected static final void flushOnscreenGraphics(){
1426         final OGLRenderQueue rq = OGLRenderQueue.getInstance();
1427         rq.lock();
1428         try {
1429             rq.flushNow();
1430         } finally {
1431             rq.unlock();
1432         }
1433     }
1434 
1435     /**
1436      * Used by ContainerPeer to skip all the paint events during layout.
1437      *
1438      * @param isLayouting layouting state.
1439      */
1440     protected final void setLayouting(final boolean isLayouting) {
1441         this.isLayouting = isLayouting;
1442     }
1443 
1444     /**
1445      * Returns layouting state. Used by ComponentPeer to skip all the paint
1446      * events during layout.
1447      *
1448      * @return true during layout, false otherwise.
1449      */
1450     private final boolean isLayouting() {
1451         return isLayouting;
1452     }
1453 }