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