Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/macosx/classes/sun/lwawt/LWComponentPeer.java
38827 views
/*1* Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/242526package sun.lwawt;2728import java.awt.*;2930import java.awt.dnd.DropTarget;31import java.awt.dnd.peer.DropTargetPeer;32import java.awt.event.*;3334import java.awt.image.ColorModel;35import java.awt.image.ImageObserver;36import java.awt.image.ImageProducer;37import java.awt.image.VolatileImage;3839import java.awt.peer.ComponentPeer;40import java.awt.peer.ContainerPeer;4142import java.awt.peer.KeyboardFocusManagerPeer;43import java.util.concurrent.atomic.AtomicBoolean;44import java.lang.reflect.Field;45import java.security.AccessController;46import java.security.PrivilegedAction;4748import sun.awt.*;4950import sun.awt.event.IgnorePaintEvent;5152import sun.awt.image.SunVolatileImage;53import sun.awt.image.ToolkitImage;5455import sun.java2d.SunGraphics2D;56import sun.java2d.opengl.OGLRenderQueue;57import sun.java2d.pipe.Region;5859import sun.util.logging.PlatformLogger;6061import javax.swing.JComponent;62import javax.swing.SwingUtilities;63import javax.swing.RepaintManager;6465import sun.lwawt.macosx.CDropTarget;6667import com.sun.java.swing.SwingUtilities3;6869public abstract class LWComponentPeer<T extends Component, D extends JComponent>70implements ComponentPeer, DropTargetPeer71{72private static final PlatformLogger focusLog = PlatformLogger.getLogger("sun.lwawt.focus.LWComponentPeer");7374/**75* State lock is to be used for modifications to this peer's fields (e.g.76* bounds, background, font, etc.) It should be the last lock in the lock77* chain78*/79private final Object stateLock = new Object();8081/**82* The lock to operate with the peers hierarchy. AWT tree lock is not used83* as there are many peers related ops to be done on the toolkit thread, and84* we don't want to depend on a public lock on this thread85*/86private static final Object peerTreeLock = new Object();8788/**89* The associated AWT object.90*/91private final T target;9293/**94* Container peer. It may not be the peer of the target's direct parent, for95* example, in the case of hw/lw mixing. However, let's skip this scenario96* for the time being. We also assume the container peer is not null, which97* might also be false if addNotify() is called for a component outside of98* the hierarchy. The exception is LWWindowPeers: their containers are99* always null100*/101private final LWContainerPeer<?, ?> containerPeer;102103/**104* Handy reference to the top-level window peer. Window peer is borrowed105* from the containerPeer in constructor, and should also be updated when106* the component is reparented to another container107*/108private final LWWindowPeer windowPeer;109110private final AtomicBoolean disposed = new AtomicBoolean(false);111112// Bounds are relative to parent peer113private final Rectangle bounds = new Rectangle();114private Region region;115116// Component state. Should be accessed under the state lock117private boolean visible = false;118private boolean enabled = true;119120private Color background;121private Color foreground;122private Font font;123124/**125* Paint area to coalesce all the paint events and store the target dirty126* area.127*/128private final RepaintArea targetPaintArea;129130// private volatile boolean paintPending;131private volatile boolean isLayouting;132133private final D delegate;134private Container delegateContainer;135private Component delegateDropTarget;136private final Object dropTargetLock = new Object();137138private int fNumDropTargets = 0;139private CDropTarget fDropTarget = null;140141private final PlatformComponent platformComponent;142143/**144* Character with reasonable value between the minimum width and maximum.145*/146static final char WIDE_CHAR = '0';147148/**149* The back buffer provide user with a BufferStrategy.150*/151private Image backBuffer;152153/**154* All Swing delegates use delegateContainer as a parent. This container155* intentionally do not use parent of the peer.156*/157@SuppressWarnings("serial")// Safe: outer class is non-serializable.158private final class DelegateContainer extends Container {159{160enableEvents(0xFFFFFFFF);161}162163// Empty non private constructor was added because access to this164// class shouldn't be emulated by a synthetic accessor method.165DelegateContainer() {166super();167}168169@Override170public boolean isLightweight() {171return false;172}173174@Override175public Point getLocation() {176return getLocationOnScreen();177}178179@Override180public Point getLocationOnScreen() {181return LWComponentPeer.this.getLocationOnScreen();182}183184@Override185public int getX() {186return getLocation().x;187}188189@Override190public int getY() {191return getLocation().y;192}193}194195LWComponentPeer(final T target, final PlatformComponent platformComponent) {196targetPaintArea = new LWRepaintArea();197this.target = target;198this.platformComponent = platformComponent;199200// Container peer is always null for LWWindowPeers, so201// windowPeer is always null for them as well. On the other202// hand, LWWindowPeer shouldn't use windowPeer at all203final Container container = SunToolkit.getNativeContainer(target);204containerPeer = (LWContainerPeer) LWToolkit.targetToPeer(container);205windowPeer = containerPeer != null ? containerPeer.getWindowPeerOrSelf()206: null;207// don't bother about z-order here as updateZOrder()208// will be called from addNotify() later anyway209if (containerPeer != null) {210containerPeer.addChildPeer(this);211}212213// the delegate must be created after the target is set214AWTEventListener toolkitListener = null;215synchronized (Toolkit.getDefaultToolkit()) {216try {217toolkitListener = getToolkitAWTEventListener();218setToolkitAWTEventListener(null);219220synchronized (getDelegateLock()) {221delegate = createDelegate();222if (delegate != null) {223delegate.setVisible(false);224delegateContainer = new DelegateContainer();225delegateContainer.add(delegate);226delegateContainer.addNotify();227delegate.addNotify();228resetColorsAndFont(delegate);229delegate.setOpaque(true);230} else {231return;232}233}234235} finally {236setToolkitAWTEventListener(toolkitListener);237}238239// todo swing: later on we will probably have one global RM240SwingUtilities3.setDelegateRepaintManager(delegate, new RepaintManager() {241@Override242public void addDirtyRegion(final JComponent c, final int x, final int y, final int w, final int h) {243repaintPeer(SwingUtilities.convertRectangle(244c, new Rectangle(x, y, w, h), getDelegate()));245}246});247}248}249250/**251* This method must be called under Toolkit.getDefaultToolkit() lock252* and followed by setToolkitAWTEventListener()253*/254protected final AWTEventListener getToolkitAWTEventListener() {255return AccessController.doPrivileged(new PrivilegedAction<AWTEventListener>() {256public AWTEventListener run() {257Toolkit toolkit = Toolkit.getDefaultToolkit();258try {259Field field = Toolkit.class.getDeclaredField("eventListener");260field.setAccessible(true);261return (AWTEventListener) field.get(toolkit);262} catch (Exception e) {263throw new InternalError(e.toString());264}265}266});267}268269protected final void setToolkitAWTEventListener(final AWTEventListener listener) {270AccessController.doPrivileged(new PrivilegedAction<Void>() {271public Void run() {272Toolkit toolkit = Toolkit.getDefaultToolkit();273try {274Field field = Toolkit.class.getDeclaredField("eventListener");275field.setAccessible(true);276field.set(toolkit, listener);277} catch (Exception e) {278throw new InternalError(e.toString());279}280return null;281}282});283}284285/**286* This method is called under getDelegateLock().287* Overridden in subclasses.288*/289D createDelegate() {290return null;291}292293final D getDelegate() {294return delegate;295}296297/**298* This method should be called under getDelegateLock().299*/300Component getDelegateFocusOwner() {301return getDelegate();302}303304/**305* Initializes this peer. The call to initialize() is not placed to306* LWComponentPeer ctor to let the subclass ctor to finish completely first.307* Instead, it's the LWToolkit object who is responsible for initialization.308* Note that we call setVisible() at the end of initialization.309*/310public final void initialize() {311platformComponent.initialize(getPlatformWindow());312initializeImpl();313setVisible(target.isVisible());314}315316/**317* Fetching general properties from the target. Should be overridden in318* subclasses to initialize specific peers properties.319*/320void initializeImpl() {321// note that these methods can be overridden by the user and322// can return some strange values like null.323setBackground(target.getBackground());324setForeground(target.getForeground());325setFont(target.getFont());326setBounds(target.getBounds());327setEnabled(target.isEnabled());328}329330private static void resetColorsAndFont(final Container c) {331c.setBackground(null);332c.setForeground(null);333c.setFont(null);334for (int i = 0; i < c.getComponentCount(); i++) {335resetColorsAndFont((Container) c.getComponent(i));336}337}338339final Object getStateLock() {340return stateLock;341}342343/**344* Synchronize all operations with the Swing delegates under AWT tree lock,345* using a new separate lock to synchronize access to delegates may lead346* deadlocks. Think of it as a 'virtual EDT'.347*348* @return DelegateLock349*/350final Object getDelegateLock() {351return getTarget().getTreeLock();352}353354protected static final Object getPeerTreeLock() {355return peerTreeLock;356}357358public final T getTarget() {359return target;360}361362// Just a helper method363// Returns the window peer or null if this is a window peer364protected final LWWindowPeer getWindowPeer() {365return windowPeer;366}367368// Returns the window peer or 'this' if this is a window peer369protected LWWindowPeer getWindowPeerOrSelf() {370return getWindowPeer();371}372373// Just a helper method374protected final LWContainerPeer<?, ?> getContainerPeer() {375return containerPeer;376}377378public PlatformWindow getPlatformWindow() {379LWWindowPeer windowPeer = getWindowPeer();380return windowPeer.getPlatformWindow();381}382383// ---- PEER METHODS ---- //384385// Just a helper method386public LWToolkit getLWToolkit() {387return LWToolkit.getLWToolkit();388}389390@Override391public final void dispose() {392if (disposed.compareAndSet(false, true)) {393disposeImpl();394}395}396397protected void disposeImpl() {398destroyBuffers();399LWContainerPeer<?, ?> cp = getContainerPeer();400if (cp != null) {401cp.removeChildPeer(this);402}403platformComponent.dispose();404LWToolkit.targetDisposedPeer(getTarget(), this);405}406407public final boolean isDisposed() {408return disposed.get();409}410411/*412* GraphicsConfiguration is borrowed from the parent peer. The413* return value must not be null.414*415* Overridden in LWWindowPeer.416*/417@Override418public GraphicsConfiguration getGraphicsConfiguration() {419// Don't check windowPeer for null as it can only happen420// for windows, but this method is overridden in421// LWWindowPeer and doesn't call super()422return getWindowPeer().getGraphicsConfiguration();423}424425426// Just a helper method427public final LWGraphicsConfig getLWGC() {428return (LWGraphicsConfig) getGraphicsConfiguration();429}430431/*432* Overridden in LWWindowPeer to replace its surface433* data and back buffer.434*/435@Override436public boolean updateGraphicsData(GraphicsConfiguration gc) {437// TODO: not implemented438// throw new RuntimeException("Has not been implemented yet.");439return false;440}441442@Override443public Graphics getGraphics() {444final Graphics g = getOnscreenGraphics();445if (g != null) {446synchronized (getPeerTreeLock()){447applyConstrain(g);448}449}450return g;451}452453/*454* Peer Graphics is borrowed from the parent peer, while455* foreground and background colors and font are specific to456* this peer.457*/458public final Graphics getOnscreenGraphics() {459final LWWindowPeer wp = getWindowPeerOrSelf();460return wp.getOnscreenGraphics(getForeground(), getBackground(),461getFont());462463}464465private void applyConstrain(final Graphics g) {466final SunGraphics2D sg2d = (SunGraphics2D) g;467final Rectangle size = localToWindow(getSize());468sg2d.constrain(size.x, size.y, size.width, size.height, getVisibleRegion());469}470471Region getVisibleRegion() {472return computeVisibleRect(this, getRegion());473}474475static final Region computeVisibleRect(final LWComponentPeer<?, ?> c,476Region region) {477final LWContainerPeer<?, ?> p = c.getContainerPeer();478if (p != null) {479final Rectangle r = c.getBounds();480region = region.getTranslatedRegion(r.x, r.y);481region = region.getIntersection(p.getRegion());482region = region.getIntersection(p.getContentSize());483region = p.cutChildren(region, c);484region = computeVisibleRect(p, region);485region = region.getTranslatedRegion(-r.x, -r.y);486}487return region;488}489490@Override491public ColorModel getColorModel() {492// Is it a correct implementation?493return getGraphicsConfiguration().getColorModel();494}495496public boolean isTranslucent() {497// Translucent windows of the top level are supported only498return false;499}500501@Override502public final void createBuffers(int numBuffers, BufferCapabilities caps)503throws AWTException {504getLWGC().assertOperationSupported(numBuffers, caps);505final Image buffer = getLWGC().createBackBuffer(this);506synchronized (getStateLock()) {507backBuffer = buffer;508}509}510511@Override512public final Image getBackBuffer() {513synchronized (getStateLock()) {514if (backBuffer != null) {515return backBuffer;516}517}518throw new IllegalStateException("Buffers have not been created");519}520521@Override522public final void flip(int x1, int y1, int x2, int y2,523BufferCapabilities.FlipContents flipAction) {524getLWGC().flip(this, getBackBuffer(), x1, y1, x2, y2, flipAction);525}526527@Override528public final void destroyBuffers() {529final Image oldBB;530synchronized (getStateLock()) {531oldBB = backBuffer;532backBuffer = null;533}534getLWGC().destroyBackBuffer(oldBB);535}536537// Helper method538public void setBounds(Rectangle r) {539setBounds(r.x, r.y, r.width, r.height, SET_BOUNDS);540}541542/**543* This method could be called on the toolkit thread.544*/545@Override546public void setBounds(int x, int y, int w, int h, int op) {547setBounds(x, y, w, h, op, true, false);548}549550protected void setBounds(int x, int y, int w, int h, int op, boolean notify,551final boolean updateTarget) {552Rectangle oldBounds;553synchronized (getStateLock()) {554oldBounds = new Rectangle(bounds);555if ((op & (SET_LOCATION | SET_BOUNDS)) != 0) {556bounds.x = x;557bounds.y = y;558}559if ((op & (SET_SIZE | SET_BOUNDS)) != 0) {560bounds.width = w;561bounds.height = h;562}563}564boolean moved = (oldBounds.x != x) || (oldBounds.y != y);565boolean resized = (oldBounds.width != w) || (oldBounds.height != h);566if (!moved && !resized) {567return;568}569final D delegate = getDelegate();570if (delegate != null) {571synchronized (getDelegateLock()) {572delegateContainer.setBounds(0, 0, w, h);573delegate.setBounds(delegateContainer.getBounds());574// TODO: the following means that the delegateContainer NEVER gets validated. That's WRONG!575delegate.validate();576}577}578579final Point locationInWindow = localToWindow(0, 0);580platformComponent.setBounds(locationInWindow.x, locationInWindow.y, w,581h);582if (notify) {583repaintOldNewBounds(oldBounds);584if (resized) {585handleResize(w, h, updateTarget);586}587if (moved) {588handleMove(x, y, updateTarget);589}590}591}592593public final Rectangle getBounds() {594synchronized (getStateLock()) {595// Return a copy to prevent subsequent modifications596return bounds.getBounds();597}598}599600public final Rectangle getSize() {601synchronized (getStateLock()) {602// Return a copy to prevent subsequent modifications603return new Rectangle(bounds.width, bounds.height);604}605}606607@Override608public Point getLocationOnScreen() {609Point windowLocation = getWindowPeer().getLocationOnScreen();610Point locationInWindow = localToWindow(0, 0);611return new Point(windowLocation.x + locationInWindow.x,612windowLocation.y + locationInWindow.y);613}614615/**616* Returns the cursor of the peer, which is cursor of the target by default,617* but peer can override this behavior.618*619* @param p Point relative to the peer.620* @return Cursor of the peer or null if default cursor should be used.621*/622Cursor getCursor(final Point p) {623return getTarget().getCursor();624}625626@Override627public void setBackground(final Color c) {628final Color oldBg = getBackground();629if (oldBg == c || (oldBg != null && oldBg.equals(c))) {630return;631}632synchronized (getStateLock()) {633background = c;634}635final D delegate = getDelegate();636if (delegate != null) {637synchronized (getDelegateLock()) {638// delegate will repaint the target639delegate.setBackground(c);640}641} else {642repaintPeer();643}644}645646public final Color getBackground() {647synchronized (getStateLock()) {648return background;649}650}651652@Override653public void setForeground(final Color c) {654final Color oldFg = getForeground();655if (oldFg == c || (oldFg != null && oldFg.equals(c))) {656return;657}658synchronized (getStateLock()) {659foreground = c;660}661final D delegate = getDelegate();662if (delegate != null) {663synchronized (getDelegateLock()) {664// delegate will repaint the target665delegate.setForeground(c);666}667} else {668repaintPeer();669}670}671672protected final Color getForeground() {673synchronized (getStateLock()) {674return foreground;675}676}677678@Override679public void setFont(final Font f) {680final Font oldF = getFont();681if (oldF == f || (oldF != null && oldF.equals(f))) {682return;683}684synchronized (getStateLock()) {685font = f;686}687final D delegate = getDelegate();688if (delegate != null) {689synchronized (getDelegateLock()) {690// delegate will repaint the target691delegate.setFont(f);692}693} else {694repaintPeer();695}696}697698protected final Font getFont() {699synchronized (getStateLock()) {700return font;701}702}703704@Override705public FontMetrics getFontMetrics(final Font f) {706// Borrow the metrics from the top-level window707// return getWindowPeer().getFontMetrics(f);708// Obtain the metrics from the offscreen window where this peer is709// mostly drawn to.710// TODO: check for "use platform metrics" settings711final Graphics g = getOnscreenGraphics();712if (g != null) {713try {714return g.getFontMetrics(f);715} finally {716g.dispose();717}718}719synchronized (getDelegateLock()) {720return delegateContainer.getFontMetrics(f);721}722}723724@Override725public void setEnabled(final boolean e) {726boolean status = e;727final LWComponentPeer<?, ?> cp = getContainerPeer();728if (cp != null) {729status &= cp.isEnabled();730}731synchronized (getStateLock()) {732if (enabled == status) {733return;734}735enabled = status;736}737738final D delegate = getDelegate();739740if (delegate != null) {741synchronized (getDelegateLock()) {742delegate.setEnabled(status);743}744} else {745repaintPeer();746}747}748749// Helper method750public final boolean isEnabled() {751synchronized (getStateLock()) {752return enabled;753}754}755756@Override757public void setVisible(final boolean v) {758synchronized (getStateLock()) {759if (visible == v) {760return;761}762visible = v;763}764setVisibleImpl(v);765}766767protected void setVisibleImpl(final boolean v) {768final D delegate = getDelegate();769770if (delegate != null) {771synchronized (getDelegateLock()) {772delegate.setVisible(v);773}774}775if (visible) {776repaintPeer();777} else {778repaintParent(getBounds());779}780}781782// Helper method783public final boolean isVisible() {784synchronized (getStateLock()) {785return visible;786}787}788789@Override790public void paint(final Graphics g) {791getTarget().paint(g);792}793794@Override795public void print(final Graphics g) {796getTarget().print(g);797}798799@Override800public void reparent(ContainerPeer newContainer) {801// TODO: not implemented802throw new UnsupportedOperationException("ComponentPeer.reparent()");803}804805@Override806public boolean isReparentSupported() {807// TODO: not implemented808return false;809}810811@Override812public void setZOrder(final ComponentPeer above) {813LWContainerPeer<?, ?> cp = getContainerPeer();814// Don't check containerPeer for null as it can only happen815// for windows, but this method is overridden in816// LWWindowPeer and doesn't call super()817cp.setChildPeerZOrder(this, (LWComponentPeer<?, ?>) above);818}819820@Override821public void coalescePaintEvent(PaintEvent e) {822if (!(e instanceof IgnorePaintEvent)) {823Rectangle r = e.getUpdateRect();824if ((r != null) && !r.isEmpty()) {825targetPaintArea.add(r, e.getID());826}827}828}829830/*831* Should be overridden in subclasses which use complex Swing components.832*/833@Override834public void layout() {835// TODO: not implemented836}837838@Override839public boolean isObscured() {840// TODO: not implemented841return false;842}843844@Override845public boolean canDetermineObscurity() {846// TODO: not implemented847return false;848}849850/**851* Determines the preferred size of the component. By default forwards the852* request to the Swing helper component. Should be overridden in subclasses853* if required.854*/855@Override856public Dimension getPreferredSize() {857final Dimension size;858synchronized (getDelegateLock()) {859size = getDelegate().getPreferredSize();860}861return validateSize(size);862}863864/**865* Determines the minimum size of the component. By default forwards the866* request to the Swing helper component. Should be overridden in subclasses867* if required.868*/869@Override870public Dimension getMinimumSize() {871final Dimension size;872synchronized (getDelegateLock()) {873size = getDelegate().getMinimumSize();874}875return validateSize(size);876}877878/**879* In some situations delegates can return empty minimum/preferred size.880* (For example: empty JLabel, etc), but awt components never should be881* empty. In the XPeers or WPeers we use some magic constants, but here we882* try to use something more useful,883*/884private Dimension validateSize(final Dimension size) {885if (size.width == 0 || size.height == 0) {886final FontMetrics fm = getFontMetrics(getFont());887size.width = fm.charWidth(WIDE_CHAR);888size.height = fm.getHeight();889}890return size;891}892893@Override894public void updateCursorImmediately() {895getLWToolkit().getCursorManager().updateCursor();896}897898@Override899public boolean isFocusable() {900// Overridden in focusable subclasses like buttons901return false;902}903904@Override905public boolean requestFocus(Component lightweightChild, boolean temporary,906boolean focusedWindowChangeAllowed, long time,907CausedFocusEvent.Cause cause)908{909if (focusLog.isLoggable(PlatformLogger.Level.FINEST)) {910focusLog.finest("lightweightChild=" + lightweightChild + ", temporary=" + temporary +911", focusedWindowChangeAllowed=" + focusedWindowChangeAllowed +912", time= " + time + ", cause=" + cause);913}914if (LWKeyboardFocusManagerPeer.processSynchronousLightweightTransfer(915getTarget(), lightweightChild, temporary,916focusedWindowChangeAllowed, time)) {917return true;918}919920int result = LWKeyboardFocusManagerPeer.shouldNativelyFocusHeavyweight(921getTarget(), lightweightChild, temporary,922focusedWindowChangeAllowed, time, cause);923switch (result) {924case LWKeyboardFocusManagerPeer.SNFH_FAILURE:925return false;926case LWKeyboardFocusManagerPeer.SNFH_SUCCESS_PROCEED:927Window parentWindow = SunToolkit.getContainingWindow(getTarget());928if (parentWindow == null) {929focusLog.fine("request rejected, parentWindow is null");930LWKeyboardFocusManagerPeer.removeLastFocusRequest(getTarget());931return false;932}933final LWWindowPeer parentPeer =934(LWWindowPeer) AWTAccessor.getComponentAccessor()935.getPeer(parentWindow);936if (parentPeer == null) {937focusLog.fine("request rejected, parentPeer is null");938LWKeyboardFocusManagerPeer.removeLastFocusRequest(getTarget());939return false;940}941942// A fix for 7145768. Ensure the parent window is currently natively focused.943// The more evident place to perform this check is in KFM.shouldNativelyFocusHeavyweight,944// however that is the shared code and this particular problem's reproducibility has945// platform specifics. So, it was decided to narrow down the fix to lwawt (OSX) in946// current release. TODO: consider fixing it in the shared code.947if (!focusedWindowChangeAllowed) {948LWWindowPeer decoratedPeer = parentPeer.isSimpleWindow() ?949LWWindowPeer.getOwnerFrameDialog(parentPeer) : parentPeer;950951if (decoratedPeer == null || !decoratedPeer.getPlatformWindow().isActive()) {952if (focusLog.isLoggable(PlatformLogger.Level.FINE)) {953focusLog.fine("request rejected, focusedWindowChangeAllowed==false, " +954"decoratedPeer is inactive: " + decoratedPeer);955}956LWKeyboardFocusManagerPeer.removeLastFocusRequest(getTarget());957return false;958}959}960961boolean res = parentPeer.requestWindowFocus(cause);962// If parent window can be made focused and has been made focused (synchronously)963// then we can proceed with children, otherwise we retreat964if (!res || !parentWindow.isFocused()) {965if (focusLog.isLoggable(PlatformLogger.Level.FINE)) {966focusLog.fine("request rejected, res= " + res + ", parentWindow.isFocused()=" +967parentWindow.isFocused());968}969LWKeyboardFocusManagerPeer.removeLastFocusRequest(getTarget());970return false;971}972973KeyboardFocusManagerPeer kfmPeer = LWKeyboardFocusManagerPeer.getInstance();974Component focusOwner = kfmPeer.getCurrentFocusOwner();975return LWKeyboardFocusManagerPeer.deliverFocus(lightweightChild,976getTarget(), temporary,977focusedWindowChangeAllowed,978time, cause, focusOwner);979980case LWKeyboardFocusManagerPeer.SNFH_SUCCESS_HANDLED:981return true;982}983984return false;985}986987@Override988public final Image createImage(final ImageProducer producer) {989return new ToolkitImage(producer);990}991992@Override993public final Image createImage(final int width, final int height) {994return getLWGC().createAcceleratedImage(getTarget(), width, height);995}996997@Override998public final VolatileImage createVolatileImage(final int w, final int h) {999return new SunVolatileImage(getTarget(), w, h);1000}10011002@Override1003public boolean prepareImage(Image img, int w, int h, ImageObserver o) {1004// TODO: is it a right/complete implementation?1005return Toolkit.getDefaultToolkit().prepareImage(img, w, h, o);1006}10071008@Override1009public int checkImage(Image img, int w, int h, ImageObserver o) {1010// TODO: is it a right/complete implementation?1011return Toolkit.getDefaultToolkit().checkImage(img, w, h, o);1012}10131014@Override1015public boolean handlesWheelScrolling() {1016// TODO: not implemented1017return false;1018}10191020@Override1021public final void applyShape(final Region shape) {1022synchronized (getStateLock()) {1023if (region == shape || (region != null && region.equals(shape))) {1024return;1025}1026}1027applyShapeImpl(shape);1028}10291030void applyShapeImpl(final Region shape) {1031synchronized (getStateLock()) {1032if (shape != null) {1033region = Region.WHOLE_REGION.getIntersection(shape);1034} else {1035region = null;1036}1037}1038repaintParent(getBounds());1039}10401041protected final Region getRegion() {1042synchronized (getStateLock()) {1043return isShaped() ? region : Region.getInstance(getSize());1044}1045}10461047public boolean isShaped() {1048synchronized (getStateLock()) {1049return region != null;1050}1051}10521053// DropTargetPeer Method1054@Override1055public void addDropTarget(DropTarget dt) {1056LWWindowPeer winPeer = getWindowPeerOrSelf();1057if (winPeer != null && winPeer != this) {1058// We need to register the DropTarget in the1059// peer of the window ancestor of the component1060winPeer.addDropTarget(dt);1061} else {1062synchronized (dropTargetLock) {1063// 10-14-02 VL: Windows WComponentPeer would add (or remove) the drop target only1064// if it's the first (or last) one for the component. Otherwise this call is a no-op.1065if (++fNumDropTargets == 1) {1066// Having a non-null drop target would be an error but let's check just in case:1067if (fDropTarget != null)1068System.err.println("CComponent.addDropTarget(): current drop target is non-null.");10691070// Create a new drop target:1071fDropTarget = CDropTarget.createDropTarget(dt, target, this);1072}1073}1074}1075}10761077// DropTargetPeer Method1078@Override1079public void removeDropTarget(DropTarget dt) {1080LWWindowPeer winPeer = getWindowPeerOrSelf();1081if (winPeer != null && winPeer != this) {1082// We need to unregister the DropTarget in the1083// peer of the window ancestor of the component1084winPeer.removeDropTarget(dt);1085} else {1086synchronized (dropTargetLock){1087// 10-14-02 VL: Windows WComponentPeer would add (or remove) the drop target only1088// if it's the first (or last) one for the component. Otherwise this call is a no-op.1089if (--fNumDropTargets == 0) {1090// Having a null drop target would be an error but let's check just in case:1091if (fDropTarget != null) {1092// Dispose of the drop target:1093fDropTarget.dispose();1094fDropTarget = null;1095} else1096System.err.println("CComponent.removeDropTarget(): current drop target is null.");1097}1098}1099}1100}11011102// ---- PEER NOTIFICATIONS ---- //11031104/**1105* Called when this peer's location has been changed either as a result1106* of target.setLocation() or as a result of user actions (window is1107* dragged with mouse).1108*1109* This method could be called on the toolkit thread.1110*/1111protected final void handleMove(final int x, final int y,1112final boolean updateTarget) {1113if (updateTarget) {1114AWTAccessor.getComponentAccessor().setLocation(getTarget(), x, y);1115}1116postEvent(new ComponentEvent(getTarget(),1117ComponentEvent.COMPONENT_MOVED));1118}11191120/**1121* Called when this peer's size has been changed either as a result of1122* target.setSize() or as a result of user actions (window is resized).1123*1124* This method could be called on the toolkit thread.1125*/1126protected final void handleResize(final int w, final int h,1127final boolean updateTarget) {1128Image oldBB = null;1129synchronized (getStateLock()) {1130if (backBuffer != null) {1131oldBB = backBuffer;1132backBuffer = getLWGC().createBackBuffer(this);1133}1134}1135getLWGC().destroyBackBuffer(oldBB);11361137if (updateTarget) {1138AWTAccessor.getComponentAccessor().setSize(getTarget(), w, h);1139}1140postEvent(new ComponentEvent(getTarget(),1141ComponentEvent.COMPONENT_RESIZED));1142}11431144protected final void repaintOldNewBounds(final Rectangle oldB) {1145repaintParent(oldB);1146repaintPeer(getSize());1147}11481149protected final void repaintParent(final Rectangle oldB) {1150final LWContainerPeer<?, ?> cp = getContainerPeer();1151if (cp != null) {1152// Repaint unobscured part of the parent1153cp.repaintPeer(cp.getContentSize().intersection(oldB));1154}1155}11561157// ---- EVENTS ---- //11581159/**1160* Post an event to the proper Java EDT.1161*/1162public void postEvent(final AWTEvent event) {1163LWToolkit.postEvent(event);1164}11651166protected void postPaintEvent(int x, int y, int w, int h) {1167// TODO: call getIgnoreRepaint() directly with the right ACC1168if (AWTAccessor.getComponentAccessor().getIgnoreRepaint(target)) {1169return;1170}1171PaintEvent event = PaintEventDispatcher.getPaintEventDispatcher().1172createPaintEvent(getTarget(), x, y, w, h);1173if (event != null) {1174postEvent(event);1175}1176}11771178/*1179* Gives a chance for the peer to handle the event after it's been1180* processed by the target.1181*/1182@Override1183public void handleEvent(AWTEvent e) {1184if ((e instanceof InputEvent) && ((InputEvent) e).isConsumed()) {1185return;1186}1187switch (e.getID()) {1188case FocusEvent.FOCUS_GAINED:1189case FocusEvent.FOCUS_LOST:1190handleJavaFocusEvent((FocusEvent) e);1191break;1192case PaintEvent.PAINT:1193// Got a native paint event1194// paintPending = false;1195// fall through to the next statement1196case PaintEvent.UPDATE:1197handleJavaPaintEvent();1198break;1199case MouseEvent.MOUSE_PRESSED:1200handleJavaMouseEvent((MouseEvent)e);1201}12021203sendEventToDelegate(e);1204}12051206protected void sendEventToDelegate(final AWTEvent e) {1207if (getDelegate() == null || !isShowing() || !isEnabled()) {1208return;1209}1210synchronized (getDelegateLock()) {1211AWTEvent delegateEvent = createDelegateEvent(e);1212if (delegateEvent != null) {1213AWTAccessor.getComponentAccessor()1214.processEvent((Component) delegateEvent.getSource(),1215delegateEvent);1216if (delegateEvent instanceof KeyEvent) {1217KeyEvent ke = (KeyEvent) delegateEvent;1218SwingUtilities.processKeyBindings(ke);1219}1220}1221}1222}12231224/**1225* Changes the target of the AWTEvent from awt component to appropriate1226* swing delegate.1227*/1228private AWTEvent createDelegateEvent(final AWTEvent e) {1229// TODO modifiers should be changed to getModifiers()|getModifiersEx()?1230AWTEvent delegateEvent = null;1231if (e instanceof MouseWheelEvent) {1232MouseWheelEvent me = (MouseWheelEvent) e;1233delegateEvent = new MouseWheelEvent(1234delegate, me.getID(), me.getWhen(),1235me.getModifiers(),1236me.getX(), me.getY(),1237me.getClickCount(),1238me.isPopupTrigger(),1239me.getScrollType(),1240me.getScrollAmount(),1241me.getWheelRotation());1242} else if (e instanceof MouseEvent) {1243MouseEvent me = (MouseEvent) e;12441245Component eventTarget = SwingUtilities.getDeepestComponentAt(delegate, me.getX(), me.getY());12461247if (me.getID() == MouseEvent.MOUSE_DRAGGED) {1248if (delegateDropTarget == null) {1249delegateDropTarget = eventTarget;1250} else {1251eventTarget = delegateDropTarget;1252}1253}1254if (me.getID() == MouseEvent.MOUSE_RELEASED && delegateDropTarget != null) {1255eventTarget = delegateDropTarget;1256delegateDropTarget = null;1257}1258if (eventTarget == null) {1259eventTarget = delegate;1260}1261delegateEvent = SwingUtilities.convertMouseEvent(getTarget(), me, eventTarget);1262} else if (e instanceof KeyEvent) {1263KeyEvent ke = (KeyEvent) e;1264delegateEvent = new KeyEvent(getDelegateFocusOwner(), ke.getID(), ke.getWhen(),1265ke.getModifiers(), ke.getKeyCode(), ke.getKeyChar(), ke.getKeyLocation());1266AWTAccessor.getKeyEventAccessor().setExtendedKeyCode((KeyEvent) delegateEvent,1267ke.getExtendedKeyCode());1268} else if (e instanceof FocusEvent) {1269FocusEvent fe = (FocusEvent) e;1270delegateEvent = new FocusEvent(getDelegateFocusOwner(), fe.getID(), fe.isTemporary());1271}1272return delegateEvent;1273}12741275protected void handleJavaMouseEvent(MouseEvent e) {1276Component target = getTarget();1277assert (e.getSource() == target);12781279if (!target.isFocusOwner() && LWKeyboardFocusManagerPeer.shouldFocusOnClick(target)) {1280LWKeyboardFocusManagerPeer.requestFocusFor(target, CausedFocusEvent.Cause.MOUSE_EVENT);1281}1282}12831284/**1285* Handler for FocusEvents.1286*/1287void handleJavaFocusEvent(final FocusEvent e) {1288// Note that the peer receives all the FocusEvents from1289// its lightweight children as well1290KeyboardFocusManagerPeer kfmPeer = LWKeyboardFocusManagerPeer.getInstance();1291kfmPeer.setCurrentFocusOwner(e.getID() == FocusEvent.FOCUS_GAINED ? getTarget() : null);1292}12931294/**1295* All peers should clear background before paint.1296*1297* @return false on components that DO NOT require a clearRect() before1298* painting.1299*/1300protected final boolean shouldClearRectBeforePaint() {1301// TODO: sun.awt.noerasebackground1302return true;1303}13041305/**1306* Handler for PAINT and UPDATE PaintEvents.1307*/1308private void handleJavaPaintEvent() {1309// Skip all painting while layouting and all UPDATEs1310// while waiting for native paint1311// if (!isLayouting && !paintPending) {1312if (!isLayouting()) {1313targetPaintArea.paint(getTarget(), shouldClearRectBeforePaint());1314}1315}13161317// ---- UTILITY METHODS ---- //13181319/**1320* Finds a top-most visible component for the given point. The location is1321* specified relative to the peer's parent.1322*/1323LWComponentPeer<?, ?> findPeerAt(final int x, final int y) {1324final Rectangle r = getBounds();1325final Region sh = getRegion();1326final boolean found = isVisible() && sh.contains(x - r.x, y - r.y);1327return found ? this : null;1328}13291330/*1331* Translated the given point in Window coordinates to the point in1332* coordinates local to this component. The given window peer must be1333* the window where this component is in.1334*/1335public Point windowToLocal(int x, int y, LWWindowPeer wp) {1336return windowToLocal(new Point(x, y), wp);1337}13381339public Point windowToLocal(Point p, LWWindowPeer wp) {1340LWComponentPeer<?, ?> cp = this;1341while (cp != wp) {1342Rectangle cpb = cp.getBounds();1343p.x -= cpb.x;1344p.y -= cpb.y;1345cp = cp.getContainerPeer();1346}1347// Return a copy to prevent subsequent modifications1348return new Point(p);1349}13501351public Rectangle windowToLocal(Rectangle r, LWWindowPeer wp) {1352Point p = windowToLocal(r.getLocation(), wp);1353return new Rectangle(p, r.getSize());1354}13551356public Point localToWindow(int x, int y) {1357return localToWindow(new Point(x, y));1358}13591360public Point localToWindow(Point p) {1361LWComponentPeer<?, ?> cp = getContainerPeer();1362Rectangle r = getBounds();1363while (cp != null) {1364p.x += r.x;1365p.y += r.y;1366r = cp.getBounds();1367cp = cp.getContainerPeer();1368}1369// Return a copy to prevent subsequent modifications1370return new Point(p);1371}13721373public Rectangle localToWindow(Rectangle r) {1374Point p = localToWindow(r.getLocation());1375return new Rectangle(p, r.getSize());1376}13771378public final void repaintPeer() {1379repaintPeer(getSize());1380}13811382void repaintPeer(final Rectangle r) {1383final Rectangle toPaint = getSize().intersection(r);1384if (!isShowing() || toPaint.isEmpty()) {1385return;1386}13871388postPaintEvent(toPaint.x, toPaint.y, toPaint.width, toPaint.height);1389}13901391/**1392* Determines whether this peer is showing on screen. This means that the1393* peer must be visible, and it must be in a container that is visible and1394* showing.1395*1396* @see #isVisible()1397*/1398protected final boolean isShowing() {1399synchronized (getPeerTreeLock()) {1400if (isVisible()) {1401final LWContainerPeer<?, ?> container = getContainerPeer();1402return (container == null) || container.isShowing();1403}1404}1405return false;1406}14071408/**1409* Paints the peer. Delegate the actual painting to Swing components.1410*/1411protected final void paintPeer(final Graphics g) {1412final D delegate = getDelegate();1413if (delegate != null) {1414if (!SwingUtilities.isEventDispatchThread()) {1415throw new InternalError("Painting must be done on EDT");1416}1417synchronized (getDelegateLock()) {1418// JComponent.print() is guaranteed to not affect the double buffer1419getDelegate().print(g);1420}1421}1422}14231424protected static final void flushOnscreenGraphics(){1425final OGLRenderQueue rq = OGLRenderQueue.getInstance();1426rq.lock();1427try {1428rq.flushNow();1429} finally {1430rq.unlock();1431}1432}14331434/**1435* Used by ContainerPeer to skip all the paint events during layout.1436*1437* @param isLayouting layouting state.1438*/1439protected final void setLayouting(final boolean isLayouting) {1440this.isLayouting = isLayouting;1441}14421443/**1444* Returns layouting state. Used by ComponentPeer to skip all the paint1445* events during layout.1446*1447* @return true during layout, false otherwise.1448*/1449private final boolean isLayouting() {1450return isLayouting;1451}1452}145314541455