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