/*
 * Copyright (c) 2011, 2024, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package sun.lwawt;

import java.awt.AWTEvent;
import java.awt.AWTException;
import java.awt.BufferCapabilities;
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.GraphicsConfiguration;
import java.awt.Image;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Toolkit;
import java.awt.Window;
import java.awt.dnd.DropTarget;
import java.awt.dnd.peer.DropTargetPeer;
import java.awt.event.AWTEventListener;
import java.awt.event.ComponentEvent;
import java.awt.event.FocusEvent;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import java.awt.event.MouseWheelEvent;
import java.awt.event.PaintEvent;
import java.awt.image.ColorModel;
import java.awt.image.VolatileImage;
import java.awt.peer.ComponentPeer;
import java.awt.peer.ContainerPeer;
import java.awt.peer.KeyboardFocusManagerPeer;
import java.lang.reflect.Field;
import java.util.concurrent.atomic.AtomicBoolean;

import javax.swing.JComponent;
import javax.swing.RepaintManager;
import javax.swing.SwingUtilities;

import com.sun.java.swing.SwingUtilities3;
import sun.awt.AWTAccessor;
import sun.awt.CGraphicsDevice;
import sun.awt.PaintEventDispatcher;
import sun.awt.RepaintArea;
import sun.awt.SunToolkit;
import sun.awt.event.IgnorePaintEvent;
import sun.awt.image.SunVolatileImage;
import sun.java2d.SunGraphics2D;
import sun.java2d.metal.MTLRenderQueue;
import sun.java2d.opengl.OGLRenderQueue;
import sun.java2d.pipe.Region;
import sun.java2d.pipe.RenderQueue;
import sun.util.logging.PlatformLogger;

public abstract class LWComponentPeer<T extends Component, D extends JComponent>
    implements ComponentPeer, DropTargetPeer
{
    private static final PlatformLogger focusLog = PlatformLogger.getLogger("sun.lwawt.focus.LWComponentPeer");

    /**
     * State lock is to be used for modifications to this peer's fields (e.g.
     * bounds, background, font, etc.) It should be the last lock in the lock
     * chain
     */
    private final Object stateLock = new Object();

    /**
     * The lock to operate with the peers hierarchy. AWT tree lock is not used
     * as there are many peers related ops to be done on the toolkit thread, and
     * we don't want to depend on a public lock on this thread
     */
    private static final Object peerTreeLock = new Object();

    /**
     * The associated AWT object.
     */
    private final T target;

    /**
     * Container peer. It may not be the peer of the target's direct parent, for
     * example, in the case of hw/lw mixing. However, let's skip this scenario
     * for the time being. We also assume the container peer is not null, which
     * might also be false if addNotify() is called for a component outside of
     * the hierarchy. The exception is LWWindowPeers: their containers are
     * always null
     */
    private final LWContainerPeer<?, ?> containerPeer;

    /**
     * Handy reference to the top-level window peer. Window peer is borrowed
     * from the containerPeer in constructor, and should also be updated when
     * the component is reparented to another container
     */
    private final LWWindowPeer windowPeer;

    private final AtomicBoolean disposed = new AtomicBoolean(false);

    // Bounds are relative to parent peer
    private final Rectangle bounds = new Rectangle();
    private Region region;

    // Component state. Should be accessed under the state lock
    private boolean visible = false;
    private boolean enabled = true;

    private Color background;
    private Color foreground;
    private Font font;

    /**
     * Paint area to coalesce all the paint events and store the target dirty
     * area.
     */
    private final RepaintArea targetPaintArea;

    //   private volatile boolean paintPending;
    private volatile boolean isLayouting;

    private final D delegate;
    private Container delegateContainer;
    private Component delegateDropTarget;
    private final Object dropTargetLock = new Object();

    private int fNumDropTargets = 0;
    private PlatformDropTarget fDropTarget = null;

    private final PlatformComponent platformComponent;

    /**
     * Character with reasonable value between the minimum width and maximum.
     */
    static final char WIDE_CHAR = '0';

    /**
     * The back buffer provide user with a BufferStrategy.
     */
    private Image backBuffer;

    /**
     * All Swing delegates use delegateContainer as a parent. This container
     * intentionally do not use parent of the peer.
     */
    @SuppressWarnings("serial")// Safe: outer class is non-serializable.
    private final class DelegateContainer extends Container {
        {
            enableEvents(0xFFFFFFFF);
        }

        @Override
        public boolean isLightweight() {
            return false;
        }

        @Override
        public Point getLocation() {
            return getLocationOnScreen();
        }

        @Override
        public Point getLocationOnScreen() {
            return LWComponentPeer.this.getLocationOnScreen();
        }

        @Override
        public int getX() {
            return getLocation().x;
        }

        @Override
        public int getY() {
            return getLocation().y;
        }
    }

    LWComponentPeer(final T target, final PlatformComponent platformComponent) {
        targetPaintArea = new LWRepaintArea();
        this.target = target;
        this.platformComponent = platformComponent;

        // Container peer is always null for LWWindowPeers, so
        // windowPeer is always null for them as well. On the other
        // hand, LWWindowPeer shouldn't use windowPeer at all
        final Container container = SunToolkit.getNativeContainer(target);
        containerPeer = (LWContainerPeer) LWToolkit.targetToPeer(container);
        windowPeer = containerPeer != null ? containerPeer.getWindowPeerOrSelf()
                                           : null;
        // don't bother about z-order here as updateZOrder()
        // will be called from addNotify() later anyway
        if (containerPeer != null) {
            containerPeer.addChildPeer(this);
        }

        // the delegate must be created after the target is set
        AWTEventListener toolkitListener = null;
        synchronized (Toolkit.getDefaultToolkit()) {
            try {
                toolkitListener = getToolkitAWTEventListener();
                setToolkitAWTEventListener(null);

                synchronized (getDelegateLock()) {
                    delegate = createDelegate();
                    if (delegate != null) {
                        delegate.setVisible(false);
                        delegateContainer = new DelegateContainer();
                        delegateContainer.add(delegate);
                        delegateContainer.addNotify();
                        delegate.addNotify();
                        resetColorsAndFont(delegate);
                        delegate.setOpaque(true);
                    } else {
                        return;
                    }
                }

            } finally {
                setToolkitAWTEventListener(toolkitListener);
            }

            // todo swing: later on we will probably have one global RM
            SwingUtilities3.setDelegateRepaintManager(delegate, new RepaintManager() {
                @Override
                public void addDirtyRegion(final JComponent c, final int x, final int y, final int w, final int h) {
                    repaintPeer(SwingUtilities.convertRectangle(
                            c, new Rectangle(x, y, w, h), getDelegate()));
                }
            });
        }
    }

    /**
     * This method must be called under Toolkit.getDefaultToolkit() lock
     * and followed by setToolkitAWTEventListener()
     */
    protected final AWTEventListener getToolkitAWTEventListener() {
        Toolkit toolkit = Toolkit.getDefaultToolkit();
        try {
            Field field = Toolkit.class.getDeclaredField("eventListener");
            field.setAccessible(true);
            return (AWTEventListener) field.get(toolkit);
        } catch (Exception e) {
            throw new InternalError(e.toString());
        }
    }

    protected final void setToolkitAWTEventListener(final AWTEventListener listener) {
        Toolkit toolkit = Toolkit.getDefaultToolkit();
        try {
            Field field = Toolkit.class.getDeclaredField("eventListener");
            field.setAccessible(true);
            field.set(toolkit, listener);
        } catch (Exception e) {
            throw new InternalError(e.toString());
        }
    }

    /**
     * This method is called under getDelegateLock().
     * Overridden in subclasses.
     */
    D createDelegate() {
        return null;
    }

    final D getDelegate() {
        return delegate;
    }

    /**
     * This method should be called under getDelegateLock().
     */
    Component getDelegateFocusOwner() {
        return getDelegate();
    }

    /**
     * Initializes this peer. The call to initialize() is not placed to
     * LWComponentPeer ctor to let the subclass ctor to finish completely first.
     * Instead, it's the LWToolkit object who is responsible for initialization.
     * Note that we call setVisible() at the end of initialization.
     */
    public final void initialize() {
        platformComponent.initialize(getPlatformWindow());
        initializeImpl();
        setVisible(target.isVisible());
    }

    /**
     * Fetching general properties from the target. Should be overridden in
     * subclasses to initialize specific peers properties.
     */
    void initializeImpl() {
        // note that these methods can be overridden by the user and
        // can return some strange values like null.
        setBackground(target.getBackground());
        setForeground(target.getForeground());
        setFont(target.getFont());
        setBounds(target.getBounds());
        setEnabled(target.isEnabled());
    }

    private static void resetColorsAndFont(final Container c) {
        c.setBackground(null);
        c.setForeground(null);
        c.setFont(null);
        for (int i = 0; i < c.getComponentCount(); i++) {
            resetColorsAndFont((Container) c.getComponent(i));
        }
    }

    final Object getStateLock() {
        return stateLock;
    }

    /**
     * Synchronize all operations with the Swing delegates under AWT tree lock,
     * using a new separate lock to synchronize access to delegates may lead
     * deadlocks. Think of it as a 'virtual EDT'.
     *
     * @return DelegateLock
     */
    final Object getDelegateLock() {
        return getTarget().getTreeLock();
    }

    protected static final Object getPeerTreeLock() {
        return peerTreeLock;
    }

    public final T getTarget() {
        return target;
    }

    // Just a helper method
    // Returns the window peer or null if this is a window peer
    protected final LWWindowPeer getWindowPeer() {
        return windowPeer;
    }

    // Returns the window peer or 'this' if this is a window peer
    protected LWWindowPeer getWindowPeerOrSelf() {
        return getWindowPeer();
    }

    // Just a helper method
    protected final LWContainerPeer<?, ?> getContainerPeer() {
        return containerPeer;
    }

    public PlatformWindow getPlatformWindow() {
        LWWindowPeer windowPeer = getWindowPeer();
        return windowPeer.getPlatformWindow();
    }

    // ---- PEER METHODS ---- //

    // Just a helper method
    public LWToolkit getLWToolkit() {
        return LWToolkit.getLWToolkit();
    }

    @Override
    public final void dispose() {
        if (disposed.compareAndSet(false, true)) {
            disposeImpl();
        }
    }

    protected void disposeImpl() {
        destroyBuffers();
        LWContainerPeer<?, ?> cp = getContainerPeer();
        if (cp != null) {
            cp.removeChildPeer(this);
        }
        platformComponent.dispose();
        LWToolkit.targetDisposedPeer(getTarget(), this);
    }

    public final boolean isDisposed() {
        return disposed.get();
    }

    /*
     * GraphicsConfiguration is borrowed from the parent peer. The
     * return value must not be null.
     *
     * Overridden in LWWindowPeer.
     */
    @Override
    public GraphicsConfiguration getGraphicsConfiguration() {
        // Don't check windowPeer for null as it can only happen
        // for windows, but this method is overridden in
        // LWWindowPeer and doesn't call super()
        return getWindowPeer().getGraphicsConfiguration();
    }


    // Just a helper method
    public final LWGraphicsConfig getLWGC() {
        return (LWGraphicsConfig) getGraphicsConfiguration();
    }

    /*
     * Overridden in LWWindowPeer to replace its surface
     * data and back buffer.
     */
    @Override
    public boolean updateGraphicsData(GraphicsConfiguration gc) {
        // TODO: not implemented
//        throw new RuntimeException("Has not been implemented yet.");
        return false;
    }

    @Override
    public Graphics getGraphics() {
        final Graphics g = getOnscreenGraphics();
        if (g != null) {
            synchronized (getPeerTreeLock()){
                applyConstrain(g);
            }
        }
        return g;
    }

    /*
     * Peer Graphics is borrowed from the parent peer, while
     * foreground and background colors and font are specific to
     * this peer.
     */
    public final Graphics getOnscreenGraphics() {
        final LWWindowPeer wp = getWindowPeerOrSelf();
        return wp.getOnscreenGraphics(getForeground(), getBackground(),
                                      getFont());

    }

    private void applyConstrain(final Graphics g) {
        final SunGraphics2D sg2d = (SunGraphics2D) g;
        final Rectangle size = localToWindow(getSize());
        sg2d.constrain(size.x, size.y, size.width, size.height, getVisibleRegion());
    }

    Region getVisibleRegion() {
        return computeVisibleRect(this, getRegion());
    }

    static final Region computeVisibleRect(final LWComponentPeer<?, ?> c,
                                           Region region) {
        final LWContainerPeer<?, ?> p = c.getContainerPeer();
        if (p != null) {
            final Rectangle r = c.getBounds();
            region = region.getTranslatedRegion(r.x, r.y);
            region = region.getIntersection(p.getRegion());
            region = region.getIntersection(p.getContentSize());
            region = p.cutChildren(region, c);
            region = computeVisibleRect(p, region);
            region = region.getTranslatedRegion(-r.x, -r.y);
        }
        return region;
    }

    @Override
    public ColorModel getColorModel() {
        // Is it a correct implementation?
        return getGraphicsConfiguration().getColorModel();
    }

    public boolean isTranslucent() {
        // Translucent windows of the top level are supported only
        return false;
    }

    @Override
    public final void createBuffers(int numBuffers, BufferCapabilities caps)
            throws AWTException {
        getLWGC().assertOperationSupported(numBuffers, caps);
        final Image buffer = getLWGC().createBackBuffer(this);
        synchronized (getStateLock()) {
            backBuffer = buffer;
        }
    }

    @Override
    public final Image getBackBuffer() {
        synchronized (getStateLock()) {
            if (backBuffer != null) {
                return backBuffer;
            }
        }
        throw new IllegalStateException("Buffers have not been created");
    }

    @Override
    public final void flip(int x1, int y1, int x2, int y2,
                     BufferCapabilities.FlipContents flipAction) {
        getLWGC().flip(this, getBackBuffer(), x1, y1, x2, y2, flipAction);
    }

    @Override
    public final void destroyBuffers() {
        final Image oldBB;
        synchronized (getStateLock()) {
            oldBB = backBuffer;
            backBuffer = null;
        }
        getLWGC().destroyBackBuffer(oldBB);
    }

    // Helper method
    public void setBounds(Rectangle r) {
        setBounds(r.x, r.y, r.width, r.height, SET_BOUNDS);
    }

    /**
     * This method could be called on the toolkit thread.
     */
    @Override
    public void setBounds(int x, int y, int w, int h, int op) {
        setBounds(x, y, w, h, op, true, false);
    }

    protected void setBounds(int x, int y, int w, int h, int op, boolean notify,
                             final boolean updateTarget) {
        Rectangle oldBounds;
        synchronized (getStateLock()) {
            oldBounds = new Rectangle(bounds);
            if ((op & (SET_LOCATION | SET_BOUNDS)) != 0) {
                bounds.x = x;
                bounds.y = y;
            }
            if ((op & (SET_SIZE | SET_BOUNDS)) != 0) {
                bounds.width = w;
                bounds.height = h;
            }
        }
        boolean moved = (oldBounds.x != x) || (oldBounds.y != y);
        boolean resized = (oldBounds.width != w) || (oldBounds.height != h);
        if (!moved && !resized) {
            return;
        }
        final D delegate = getDelegate();
        if (delegate != null) {
            synchronized (getDelegateLock()) {
                delegateContainer.setBounds(0, 0, w, h);
                delegate.setBounds(delegateContainer.getBounds());
                // TODO: the following means that the delegateContainer NEVER gets validated. That's WRONG!
                delegate.validate();
            }
        }

        final Point locationInWindow = localToWindow(0, 0);
        platformComponent.setBounds(locationInWindow.x, locationInWindow.y, w,
                                    h);
        if (notify) {
            repaintOldNewBounds(oldBounds);
            if (resized) {
                handleResize(w, h, updateTarget);
            }
            if (moved) {
                handleMove(x, y, updateTarget);
            }
        }
    }

    public final Rectangle getBounds() {
        synchronized (getStateLock()) {
            // Return a copy to prevent subsequent modifications
            return bounds.getBounds();
        }
    }

    public final Rectangle getSize() {
        synchronized (getStateLock()) {
            // Return a copy to prevent subsequent modifications
            return new Rectangle(bounds.width, bounds.height);
        }
    }

    @Override
    public Point getLocationOnScreen() {
        Point windowLocation = getWindowPeer().getLocationOnScreen();
        Point locationInWindow = localToWindow(0, 0);
        return new Point(windowLocation.x + locationInWindow.x,
                windowLocation.y + locationInWindow.y);
    }

    /**
     * Returns the cursor of the peer, which is cursor of the target by default,
     * but peer can override this behavior.
     *
     * @param p Point relative to the peer.
     * @return Cursor of the peer or null if default cursor should be used.
     */
    Cursor getCursor(final Point p) {
        return getTarget().getCursor();
    }

    @Override
    public void setBackground(final Color c) {
        final Color oldBg = getBackground();
        if (oldBg == c || (oldBg != null && oldBg.equals(c))) {
            return;
        }
        synchronized (getStateLock()) {
            background = c;
        }
        final D delegate = getDelegate();
        if (delegate != null) {
            synchronized (getDelegateLock()) {
                // delegate will repaint the target
                delegate.setBackground(c);
            }
        } else {
            repaintPeer();
        }
    }

    public final Color getBackground() {
        synchronized (getStateLock()) {
            return background;
        }
    }

    @Override
    public void setForeground(final Color c) {
        final Color oldFg = getForeground();
        if (oldFg == c || (oldFg != null && oldFg.equals(c))) {
            return;
        }
        synchronized (getStateLock()) {
            foreground = c;
        }
        final D delegate = getDelegate();
        if (delegate != null) {
            synchronized (getDelegateLock()) {
                // delegate will repaint the target
                delegate.setForeground(c);
            }
        } else {
            repaintPeer();
        }
    }

    protected final Color getForeground() {
        synchronized (getStateLock()) {
            return foreground;
        }
    }

    @Override
    public void setFont(final Font f) {
        final Font oldF = getFont();
        if (oldF == f || (oldF != null && oldF.equals(f))) {
            return;
        }
        synchronized (getStateLock()) {
            font = f;
        }
        final D delegate = getDelegate();
        if (delegate != null) {
            synchronized (getDelegateLock()) {
                // delegate will repaint the target
                delegate.setFont(f);
            }
        } else {
            repaintPeer();
        }
    }

    protected final Font getFont() {
        synchronized (getStateLock()) {
            return font;
        }
    }

    @Override
    public FontMetrics getFontMetrics(final Font f) {
        // Borrow the metrics from the top-level window
//        return getWindowPeer().getFontMetrics(f);
        // Obtain the metrics from the offscreen window where this peer is
        // mostly drawn to.
        // TODO: check for "use platform metrics" settings
        final Graphics g = getOnscreenGraphics();
        if (g != null) {
            try {
                return g.getFontMetrics(f);
            } finally {
                g.dispose();
            }
        }
        synchronized (getDelegateLock()) {
            return delegateContainer.getFontMetrics(f);
        }
    }

    @Override
    public void setEnabled(final boolean e) {
        boolean status = e;
        final LWComponentPeer<?, ?> cp = getContainerPeer();
        if (cp != null) {
            status &= cp.isEnabled();
        }
        synchronized (getStateLock()) {
            if (enabled == status) {
                return;
            }
            enabled = status;
        }

        final D delegate = getDelegate();

        if (delegate != null) {
            synchronized (getDelegateLock()) {
                delegate.setEnabled(status);
            }
        } else {
            repaintPeer();
        }
    }

    // Helper method
    public final boolean isEnabled() {
        synchronized (getStateLock()) {
            return enabled;
        }
    }

    @Override
    public void setVisible(final boolean v) {
        synchronized (getStateLock()) {
            if (visible == v) {
                return;
            }
            visible = v;
        }
        setVisibleImpl(v);
    }

    protected void setVisibleImpl(final boolean v) {
        final D delegate = getDelegate();

        if (delegate != null) {
            synchronized (getDelegateLock()) {
                delegate.setVisible(v);
            }
        }
        if (visible) {
            repaintPeer();
        } else {
            repaintParent(getBounds());
        }
    }

    // Helper method
    public final boolean isVisible() {
        synchronized (getStateLock()) {
            return visible;
        }
    }

    @Override
    public void paint(final Graphics g) {
        getTarget().paint(g);
    }

    @Override
    public void print(final Graphics g) {
        getTarget().print(g);
    }

    @Override
    public void reparent(ContainerPeer newContainer) {
        // TODO: not implemented
        throw new UnsupportedOperationException("ComponentPeer.reparent()");
    }

    @Override
    public boolean isReparentSupported() {
        // TODO: not implemented
        return false;
    }

    @Override
    public void setZOrder(final ComponentPeer above) {
        LWContainerPeer<?, ?> cp = getContainerPeer();
        // Don't check containerPeer for null as it can only happen
        // for windows, but this method is overridden in
        // LWWindowPeer and doesn't call super()
        cp.setChildPeerZOrder(this, (LWComponentPeer<?, ?>) above);
    }

    @Override
    public void coalescePaintEvent(PaintEvent e) {
        if (!(e instanceof IgnorePaintEvent)) {
            Rectangle r = e.getUpdateRect();
            if ((r != null) && !r.isEmpty()) {
                targetPaintArea.add(r, e.getID());
            }
        }
    }

    /*
     * Should be overridden in subclasses which use complex Swing components.
     */
    @Override
    public void layout() {
        // TODO: not implemented
    }

    @Override
    public boolean isObscured() {
        // TODO: not implemented
        return false;
    }

    @Override
    public boolean canDetermineObscurity() {
        // TODO: not implemented
        return false;
    }

    /**
     * Determines the preferred size of the component. By default forwards the
     * request to the Swing helper component. Should be overridden in subclasses
     * if required.
     */
    @Override
    public Dimension getPreferredSize() {
        final Dimension size;
        synchronized (getDelegateLock()) {
            size = getDelegate().getPreferredSize();
        }
        return validateSize(size);
    }

    /**
     * Determines the minimum size of the component. By default forwards the
     * request to the Swing helper component. Should be overridden in subclasses
     * if required.
     */
    @Override
    public Dimension getMinimumSize() {
        final Dimension size;
        synchronized (getDelegateLock()) {
            size = getDelegate().getMinimumSize();
        }
        return validateSize(size);
    }

    /**
     * In some situations delegates can return empty minimum/preferred size.
     * (For example: empty JLabel, etc), but awt components never should be
     * empty. In the XPeers or WPeers we use some magic constants, but here we
     * try to use something more useful,
     */
    private Dimension validateSize(final Dimension size) {
        if (size.width == 0 || size.height == 0) {
            final FontMetrics fm = getFontMetrics(getFont());
            size.width = fm.charWidth(WIDE_CHAR);
            size.height = fm.getHeight();
        }
        return size;
    }

    @Override
    public void updateCursorImmediately() {
        getLWToolkit().getCursorManager().updateCursor();
    }

    @Override
    public boolean isFocusable() {
        // Overridden in focusable subclasses like buttons
        return false;
    }

    @Override
    public boolean requestFocus(Component lightweightChild, boolean temporary,
                                boolean focusedWindowChangeAllowed, long time,
                                FocusEvent.Cause cause)
    {
        if (focusLog.isLoggable(PlatformLogger.Level.FINEST)) {
            focusLog.finest("lightweightChild=" + lightweightChild + ", temporary=" + temporary +
                            ", focusedWindowChangeAllowed=" + focusedWindowChangeAllowed +
                            ", time= " + time + ", cause=" + cause);
        }
        if (LWKeyboardFocusManagerPeer.processSynchronousLightweightTransfer(
                getTarget(), lightweightChild, temporary,
                focusedWindowChangeAllowed, time)) {
            return true;
        }

        int result = LWKeyboardFocusManagerPeer.shouldNativelyFocusHeavyweight(
                getTarget(), lightweightChild, temporary,
                focusedWindowChangeAllowed, time, cause);
        switch (result) {
            case LWKeyboardFocusManagerPeer.SNFH_FAILURE:
                return false;
            case LWKeyboardFocusManagerPeer.SNFH_SUCCESS_PROCEED:
                Window parentWindow = SunToolkit.getContainingWindow(getTarget());
                if (parentWindow == null) {
                    focusLog.fine("request rejected, parentWindow is null");
                    LWKeyboardFocusManagerPeer.removeLastFocusRequest(getTarget());
                    return false;
                }
                final LWWindowPeer parentPeer =
                        AWTAccessor.getComponentAccessor()
                                   .getPeer(parentWindow);
                if (parentPeer == null) {
                    focusLog.fine("request rejected, parentPeer is null");
                    LWKeyboardFocusManagerPeer.removeLastFocusRequest(getTarget());
                    return false;
                }

                // A fix for 7145768. Ensure the parent window is currently natively focused.
                // The more evident place to perform this check is in KFM.shouldNativelyFocusHeavyweight,
                // however that is the shared code and this particular problem's reproducibility has
                // platform specifics. So, it was decided to narrow down the fix to lwawt (OSX) in
                // current release. TODO: consider fixing it in the shared code.
                if (!focusedWindowChangeAllowed) {
                    LWWindowPeer decoratedPeer = parentPeer.isSimpleWindow() ?
                        LWWindowPeer.getOwnerFrameDialog(parentPeer) : parentPeer;

                    if (decoratedPeer == null || !decoratedPeer.getPlatformWindow().isActive()) {
                        if (focusLog.isLoggable(PlatformLogger.Level.FINE)) {
                            focusLog.fine("request rejected, focusedWindowChangeAllowed==false, " +
                                          "decoratedPeer is inactive: " + decoratedPeer);
                        }
                        LWKeyboardFocusManagerPeer.removeLastFocusRequest(getTarget());
                        return false;
                    }
                }

                boolean res = parentPeer.requestWindowFocus(cause);
                // If parent window can be made focused and has been made focused (synchronously)
                // then we can proceed with children, otherwise we retreat
                if (!res || !parentWindow.isFocused()) {
                    if (focusLog.isLoggable(PlatformLogger.Level.FINE)) {
                        focusLog.fine("request rejected, res= " + res + ", parentWindow.isFocused()=" +
                                      parentWindow.isFocused());
                    }
                    LWKeyboardFocusManagerPeer.removeLastFocusRequest(getTarget());
                    return false;
                }

                KeyboardFocusManagerPeer kfmPeer = LWKeyboardFocusManagerPeer.getInstance();
                Component focusOwner = kfmPeer.getCurrentFocusOwner();
                return LWKeyboardFocusManagerPeer.deliverFocus(lightweightChild,
                        getTarget(), temporary,
                        focusedWindowChangeAllowed,
                        time, cause, focusOwner);

            case LWKeyboardFocusManagerPeer.SNFH_SUCCESS_HANDLED:
                return true;
        }

        return false;
    }

    @Override
    public final Image createImage(final int width, final int height) {
        return getLWGC().createAcceleratedImage(getTarget(), width, height);
    }

    @Override
    public final VolatileImage createVolatileImage(final int w, final int h) {
        return new SunVolatileImage(getTarget(), w, h);
    }

    @Override
    public boolean handlesWheelScrolling() {
        // TODO: not implemented
        return false;
    }

    @Override
    public final void applyShape(final Region shape) {
        synchronized (getStateLock()) {
            if (region == shape || (region != null && region.equals(shape))) {
                return;
            }
        }
        applyShapeImpl(shape);
    }

    void applyShapeImpl(final Region shape) {
        synchronized (getStateLock()) {
            if (shape != null) {
                region = Region.WHOLE_REGION.getIntersection(shape);
            } else {
                region = null;
            }
        }
        repaintParent(getBounds());
    }

    protected final Region getRegion() {
        synchronized (getStateLock()) {
            return isShaped() ? region : Region.getInstance(getSize());
        }
    }

    public boolean isShaped() {
        synchronized (getStateLock()) {
            return region != null;
        }
    }

    // DropTargetPeer Method
    @Override
    public void addDropTarget(DropTarget dt) {
        LWWindowPeer winPeer = getWindowPeerOrSelf();
        if (winPeer != null && winPeer != this) {
            // We need to register the DropTarget in the
            // peer of the window ancestor of the component
            winPeer.addDropTarget(dt);
        } else {
            synchronized (dropTargetLock) {
                // 10-14-02 VL: Windows WComponentPeer would add (or remove) the drop target only
                // if it's the first (or last) one for the component. Otherwise this call is a no-op.
                if (++fNumDropTargets == 1) {
                    // Having a non-null drop target would be an error but let's check just in case:
                    if (fDropTarget != null) {
                        throw new IllegalStateException("Current drop target is not null");
                    }
                    // Create a new drop target:
                    fDropTarget = LWToolkit.getLWToolkit().createDropTarget(dt, target, this);
                }
            }
        }
    }

    // DropTargetPeer Method
    @Override
    public void removeDropTarget(DropTarget dt) {
        LWWindowPeer winPeer = getWindowPeerOrSelf();
        if (winPeer != null && winPeer != this) {
            // We need to unregister the DropTarget in the
            // peer of the window ancestor of the component
            winPeer.removeDropTarget(dt);
        } else {
            synchronized (dropTargetLock){
                // 10-14-02 VL: Windows WComponentPeer would add (or remove) the drop target only
                // if it's the first (or last) one for the component. Otherwise this call is a no-op.
                if (--fNumDropTargets == 0) {
                    // Having a null drop target would be an error but let's check just in case:
                    if (fDropTarget != null) {
                        // Dispose of the drop target:
                        fDropTarget.dispose();
                        fDropTarget = null;
                    } else
                        System.err.println("CComponent.removeDropTarget(): current drop target is null.");
                }
            }
        }
    }

    // ---- PEER NOTIFICATIONS ---- //

    /**
     * Called when this peer's location has been changed either as a result
     * of target.setLocation() or as a result of user actions (window is
     * dragged with mouse).
     *
     * This method could be called on the toolkit thread.
     */
    protected final void handleMove(final int x, final int y,
                                    final boolean updateTarget) {
        if (updateTarget) {
            AWTAccessor.getComponentAccessor().setLocation(getTarget(), x, y);
            postEvent(new ComponentEvent(getTarget(),
                                         ComponentEvent.COMPONENT_MOVED));
        }
    }

    /**
     * Called when this peer's size has been changed either as a result of
     * target.setSize() or as a result of user actions (window is resized).
     *
     * This method could be called on the toolkit thread.
     */
    protected final void handleResize(final int w, final int h,
                                      final boolean updateTarget) {
        Image oldBB = null;
        synchronized (getStateLock()) {
            if (backBuffer != null) {
                oldBB = backBuffer;
                backBuffer = getLWGC().createBackBuffer(this);
            }
        }
        getLWGC().destroyBackBuffer(oldBB);

        if (updateTarget) {
            AWTAccessor.getComponentAccessor().setSize(getTarget(), w, h);
            postEvent(new ComponentEvent(getTarget(),
                                         ComponentEvent.COMPONENT_RESIZED));
        }
    }

    protected final void repaintOldNewBounds(final Rectangle oldB) {
        repaintParent(oldB);
        repaintPeer(getSize());
    }

    protected final void repaintParent(final Rectangle oldB) {
        final LWContainerPeer<?, ?> cp = getContainerPeer();
        if (cp != null) {
            // Repaint unobscured part of the parent
            cp.repaintPeer(cp.getContentSize().intersection(oldB));
        }
    }

    // ---- EVENTS ---- //

    /**
     * Post an event to the proper Java EDT.
     */
    public void postEvent(final AWTEvent event) {
        LWToolkit.postEvent(event);
    }

    protected void postPaintEvent(int x, int y, int w, int h) {
        // TODO: call getIgnoreRepaint() directly with the right ACC
        if (AWTAccessor.getComponentAccessor().getIgnoreRepaint(target)) {
            return;
        }
        PaintEvent event = PaintEventDispatcher.getPaintEventDispatcher().
                createPaintEvent(getTarget(), x, y, w, h);
        if (event != null) {
            postEvent(event);
        }
    }

    /*
     * Gives a chance for the peer to handle the event after it's been
     * processed by the target.
     */
    @Override
    public void handleEvent(AWTEvent e) {
        if ((e instanceof InputEvent) && ((InputEvent) e).isConsumed()) {
            return;
        }
        switch (e.getID()) {
            case FocusEvent.FOCUS_GAINED:
            case FocusEvent.FOCUS_LOST:
                handleJavaFocusEvent((FocusEvent) e);
                break;
            case PaintEvent.PAINT:
                // Got a native paint event
//                paintPending = false;
                // fall through to the next statement
            case PaintEvent.UPDATE:
                handleJavaPaintEvent();
                break;
            case MouseEvent.MOUSE_PRESSED:
                handleJavaMouseEvent((MouseEvent)e);
        }

        sendEventToDelegate(e);
    }

    protected void sendEventToDelegate(final AWTEvent e) {
        if (getDelegate() == null || !isShowing() || !isEnabled()) {
            return;
        }
        synchronized (getDelegateLock()) {
            AWTEvent delegateEvent = createDelegateEvent(e);
            if (delegateEvent != null) {
                AWTAccessor.getComponentAccessor()
                        .processEvent((Component) delegateEvent.getSource(),
                                delegateEvent);
                if (delegateEvent instanceof KeyEvent) {
                    KeyEvent ke = (KeyEvent) delegateEvent;
                    SwingUtilities.processKeyBindings(ke);
                }
            }
        }
    }

    /**
     * Changes the target of the AWTEvent from awt component to appropriate
     * swing delegate.
     */
    @SuppressWarnings("deprecation")
    private AWTEvent createDelegateEvent(final AWTEvent e) {
        // TODO modifiers should be changed to getModifiers()|getModifiersEx()?
        AWTEvent delegateEvent = null;
        if (e instanceof MouseWheelEvent) {
            MouseWheelEvent me = (MouseWheelEvent) e;
            delegateEvent = new MouseWheelEvent(
                    delegate, me.getID(), me.getWhen(),
                    me.getModifiers(),
                    me.getX(), me.getY(),
                    me.getXOnScreen(), me.getYOnScreen(),
                    me.getClickCount(),
                    me.isPopupTrigger(),
                    me.getScrollType(),
                    me.getScrollAmount(),
                    me.getWheelRotation(),
                    me.getPreciseWheelRotation());
        } else if (e instanceof MouseEvent) {
            MouseEvent me = (MouseEvent) e;

            Component eventTarget = SwingUtilities.getDeepestComponentAt(delegate, me.getX(), me.getY());

            if (me.getID() == MouseEvent.MOUSE_DRAGGED) {
                if (delegateDropTarget == null) {
                    delegateDropTarget = eventTarget;
                } else {
                    eventTarget = delegateDropTarget;
                }
            }
            if (me.getID() == MouseEvent.MOUSE_RELEASED && delegateDropTarget != null) {
                eventTarget = delegateDropTarget;
                delegateDropTarget = null;
            }
            if (eventTarget == null) {
                eventTarget = delegate;
            }
            delegateEvent = SwingUtilities.convertMouseEvent(getTarget(), me, eventTarget);
        } else if (e instanceof KeyEvent) {
            KeyEvent ke = (KeyEvent) e;
            delegateEvent = new KeyEvent(getDelegateFocusOwner(), ke.getID(), ke.getWhen(),
                    ke.getModifiers(), ke.getKeyCode(), ke.getKeyChar(), ke.getKeyLocation());
            AWTAccessor.getKeyEventAccessor().setExtendedKeyCode((KeyEvent) delegateEvent,
                    ke.getExtendedKeyCode());
        } else if (e instanceof FocusEvent) {
            FocusEvent fe = (FocusEvent) e;
            delegateEvent = new FocusEvent(getDelegateFocusOwner(), fe.getID(), fe.isTemporary());
        }
        return delegateEvent;
    }

    protected void handleJavaMouseEvent(MouseEvent e) {
        Component target = getTarget();
        assert (e.getSource() == target);

        if (!target.isFocusOwner() && LWKeyboardFocusManagerPeer.shouldFocusOnClick(target)) {
            LWKeyboardFocusManagerPeer.requestFocusFor(target, FocusEvent.Cause.MOUSE_EVENT);
        }
    }

    /**
     * Handler for FocusEvents.
     */
    void handleJavaFocusEvent(final FocusEvent e) {
        // Note that the peer receives all the FocusEvents from
        // its lightweight children as well
        KeyboardFocusManagerPeer kfmPeer = LWKeyboardFocusManagerPeer.getInstance();
        kfmPeer.setCurrentFocusOwner(e.getID() == FocusEvent.FOCUS_GAINED ? getTarget() : null);
    }

    /**
     * All peers should clear background before paint.
     *
     * @return false on components that DO NOT require a clearRect() before
     *         painting.
     */
    protected final boolean shouldClearRectBeforePaint() {
        // TODO: sun.awt.noerasebackground
        return true;
    }

    /**
     * Handler for PAINT and UPDATE PaintEvents.
     */
    private void handleJavaPaintEvent() {
        // Skip all painting while layouting and all UPDATEs
        // while waiting for native paint
//        if (!isLayouting && !paintPending) {
        if (!isLayouting()) {
            targetPaintArea.paint(getTarget(), shouldClearRectBeforePaint());
        }
    }

    // ---- UTILITY METHODS ---- //

    /**
     * Finds a top-most visible component for the given point. The location is
     * specified relative to the peer's parent.
     */
    LWComponentPeer<?, ?> findPeerAt(final int x, final int y) {
        final Rectangle r = getBounds();
        final Region sh = getRegion();
        final boolean found = isVisible() && sh.contains(x - r.x, y - r.y);
        return found ? this : null;
    }

    /*
     * Translated the given point in Window coordinates to the point in
     * coordinates local to this component. The given window peer must be
     * the window where this component is in.
     */
    public Point windowToLocal(int x, int y, LWWindowPeer wp) {
        return windowToLocal(new Point(x, y), wp);
    }

    public Point windowToLocal(Point p, LWWindowPeer wp) {
        LWComponentPeer<?, ?> cp = this;
        while (cp != wp) {
            Rectangle cpb = cp.getBounds();
            p.x -= cpb.x;
            p.y -= cpb.y;
            cp = cp.getContainerPeer();
        }
        // Return a copy to prevent subsequent modifications
        return new Point(p);
    }

    public Rectangle windowToLocal(Rectangle r, LWWindowPeer wp) {
        Point p = windowToLocal(r.getLocation(), wp);
        return new Rectangle(p, r.getSize());
    }

    public Point localToWindow(int x, int y) {
        return localToWindow(new Point(x, y));
    }

    public Point localToWindow(Point p) {
        LWComponentPeer<?, ?> cp = getContainerPeer();
        Rectangle r = getBounds();
        while (cp != null) {
            p.x += r.x;
            p.y += r.y;
            r = cp.getBounds();
            cp = cp.getContainerPeer();
        }
        // Return a copy to prevent subsequent modifications
        return new Point(p);
    }

    public Rectangle localToWindow(Rectangle r) {
        Point p = localToWindow(r.getLocation());
        return new Rectangle(p, r.getSize());
    }

    public final void repaintPeer() {
        repaintPeer(getSize());
    }

    void repaintPeer(final Rectangle r) {
        final Rectangle toPaint = getSize().intersection(r);
        if (!isShowing() || toPaint.isEmpty()) {
            return;
        }

        postPaintEvent(toPaint.x, toPaint.y, toPaint.width, toPaint.height);
    }

    /**
     * Determines whether this peer is showing on screen. This means that the
     * peer must be visible, and it must be in a container that is visible and
     * showing.
     *
     * @see #isVisible()
     */
    protected final boolean isShowing() {
        synchronized (getPeerTreeLock()) {
            if (isVisible()) {
                final LWContainerPeer<?, ?> container = getContainerPeer();
                return (container == null) || container.isShowing();
            }
        }
        return false;
    }

    /**
     * Paints the peer. Delegate the actual painting to Swing components.
     */
    protected final void paintPeer(final Graphics g) {
        final D delegate = getDelegate();
        if (delegate != null) {
            if (!SwingUtilities.isEventDispatchThread()) {
                throw new InternalError("Painting must be done on EDT");
            }
            synchronized (getDelegateLock()) {
                // JComponent.print() is guaranteed to not affect the double buffer
                getDelegate().print(g);
            }
        }
    }

    protected static final void flushOnscreenGraphics(){
        RenderQueue rq =  CGraphicsDevice.usingMetalPipeline() ?
                MTLRenderQueue.getInstance() : OGLRenderQueue.getInstance();
        rq.lock();
        try {
            rq.flushNow();
        } finally {
            rq.unlock();
        }
    }

    /**
     * Used by ContainerPeer to skip all the paint events during layout.
     *
     * @param isLayouting layouting state.
     */
    protected final void setLayouting(final boolean isLayouting) {
        this.isLayouting = isLayouting;
    }

    /**
     * Returns layouting state. Used by ComponentPeer to skip all the paint
     * events during layout.
     *
     * @return true during layout, false otherwise.
     */
    private boolean isLayouting() {
        return isLayouting;
    }
}
