| /* |
| * Copyright (c) 1996, 2015, 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.awt; |
| |
| import java.awt.*; |
| import java.awt.event.*; |
| import java.awt.peer.*; |
| import java.beans.PropertyChangeListener; |
| import java.beans.PropertyChangeEvent; |
| import java.util.Set; |
| import java.awt.AWTKeyStroke; |
| import java.applet.Applet; |
| |
| /** |
| * A generic container used for embedding Java components, usually applets. |
| * An EmbeddedFrame has two related uses: |
| * |
| * . Within a Java-based application, an EmbeddedFrame serves as a sort of |
| * firewall, preventing the contained components or applets from using |
| * getParent() to find parent components, such as menubars. |
| * |
| * . Within a C-based application, an EmbeddedFrame contains a window handle |
| * which was created by the application, which serves as the top-level |
| * Java window. EmbeddedFrames created for this purpose are passed-in a |
| * handle of an existing window created by the application. The window |
| * handle should be of the appropriate native type for a specific |
| * platform, as stored in the pData field of the ComponentPeer. |
| * |
| * @author Thomas Ball |
| */ |
| public abstract class EmbeddedFrame extends Frame |
| implements KeyEventDispatcher, PropertyChangeListener { |
| |
| private boolean isCursorAllowed = true; |
| private boolean supportsXEmbed = false; |
| private KeyboardFocusManager appletKFM; |
| // JDK 1.1 compatibility |
| private static final long serialVersionUID = 2967042741780317130L; |
| |
| /* |
| * The constants define focus traversal directions. |
| * Use them in {@code traverseIn}, {@code traverseOut} methods. |
| */ |
| protected static final boolean FORWARD = true; |
| protected static final boolean BACKWARD = false; |
| |
| public boolean supportsXEmbed() { |
| return supportsXEmbed && SunToolkit.needsXEmbed(); |
| } |
| |
| protected EmbeddedFrame(boolean supportsXEmbed) { |
| this((long)0, supportsXEmbed); |
| } |
| |
| |
| protected EmbeddedFrame() { |
| this((long)0); |
| } |
| |
| /** |
| * @deprecated This constructor will be removed in 1.5 |
| */ |
| @Deprecated |
| protected EmbeddedFrame(int handle) { |
| this((long)handle); |
| } |
| |
| protected EmbeddedFrame(long handle) { |
| this(handle, false); |
| } |
| |
| protected EmbeddedFrame(long handle, boolean supportsXEmbed) { |
| this.supportsXEmbed = supportsXEmbed; |
| registerListeners(); |
| } |
| |
| /** |
| * Block introspection of a parent window by this child. |
| */ |
| public Container getParent() { |
| return null; |
| } |
| |
| /** |
| * Needed to track which KeyboardFocusManager is current. We want to avoid memory |
| * leaks, so when KFM stops being current, we remove ourselves as listeners. |
| */ |
| public void propertyChange(PropertyChangeEvent evt) { |
| // We don't handle any other properties. Skip it. |
| if (!evt.getPropertyName().equals("managingFocus")) { |
| return; |
| } |
| |
| // We only do it if it stops being current. Technically, we should |
| // never get an event about KFM starting being current. |
| if (evt.getNewValue() == Boolean.TRUE) { |
| return; |
| } |
| |
| // should be the same as appletKFM |
| removeTraversingOutListeners((KeyboardFocusManager)evt.getSource()); |
| |
| appletKFM = KeyboardFocusManager.getCurrentKeyboardFocusManager(); |
| if (isVisible()) { |
| addTraversingOutListeners(appletKFM); |
| } |
| } |
| |
| /** |
| * Register us as KeyEventDispatcher and property "managingFocus" listeners. |
| */ |
| private void addTraversingOutListeners(KeyboardFocusManager kfm) { |
| kfm.addKeyEventDispatcher(this); |
| kfm.addPropertyChangeListener("managingFocus", this); |
| } |
| |
| /** |
| * Deregister us as KeyEventDispatcher and property "managingFocus" listeners. |
| */ |
| private void removeTraversingOutListeners(KeyboardFocusManager kfm) { |
| kfm.removeKeyEventDispatcher(this); |
| kfm.removePropertyChangeListener("managingFocus", this); |
| } |
| |
| /** |
| * Because there may be many AppContexts, and we can't be sure where this |
| * EmbeddedFrame is first created or shown, we can't automatically determine |
| * the correct KeyboardFocusManager to attach to as KeyEventDispatcher. |
| * Those who want to use the functionality of traversing out of the EmbeddedFrame |
| * must call this method on the Applet's AppContext. After that, all the changes |
| * can be handled automatically, including possible replacement of |
| * KeyboardFocusManager. |
| */ |
| public void registerListeners() { |
| if (appletKFM != null) { |
| removeTraversingOutListeners(appletKFM); |
| } |
| appletKFM = KeyboardFocusManager.getCurrentKeyboardFocusManager(); |
| if (isVisible()) { |
| addTraversingOutListeners(appletKFM); |
| } |
| } |
| |
| /** |
| * Needed to avoid memory leak: we register this EmbeddedFrame as a listener with |
| * KeyboardFocusManager of applet's AppContext. We don't want the KFM to keep |
| * reference to our EmbeddedFrame forever if the Frame is no longer in use, so we |
| * add listeners in show() and remove them in hide(). |
| */ |
| @SuppressWarnings("deprecation") |
| public void show() { |
| if (appletKFM != null) { |
| addTraversingOutListeners(appletKFM); |
| } |
| super.show(); |
| } |
| |
| /** |
| * Needed to avoid memory leak: we register this EmbeddedFrame as a listener with |
| * KeyboardFocusManager of applet's AppContext. We don't want the KFM to keep |
| * reference to our EmbeddedFrame forever if the Frame is no longer in use, so we |
| * add listeners in show() and remove them in hide(). |
| */ |
| @SuppressWarnings("deprecation") |
| public void hide() { |
| if (appletKFM != null) { |
| removeTraversingOutListeners(appletKFM); |
| } |
| super.hide(); |
| } |
| |
| /** |
| * Need this method to detect when the focus may have chance to leave the |
| * focus cycle root which is EmbeddedFrame. Mostly, the code here is copied |
| * from DefaultKeyboardFocusManager.processKeyEvent with some minor |
| * modifications. |
| */ |
| public boolean dispatchKeyEvent(KeyEvent e) { |
| |
| Container currentRoot = AWTAccessor.getKeyboardFocusManagerAccessor() |
| .getCurrentFocusCycleRoot(); |
| |
| // if we are not in EmbeddedFrame's cycle, we should not try to leave. |
| if (this != currentRoot) { |
| return false; |
| } |
| |
| // KEY_TYPED events cannot be focus traversal keys |
| if (e.getID() == KeyEvent.KEY_TYPED) { |
| return false; |
| } |
| |
| if (!getFocusTraversalKeysEnabled() || e.isConsumed()) { |
| return false; |
| } |
| |
| AWTKeyStroke stroke = AWTKeyStroke.getAWTKeyStrokeForEvent(e); |
| Set<AWTKeyStroke> toTest; |
| Component currentFocused = e.getComponent(); |
| |
| toTest = getFocusTraversalKeys(KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS); |
| if (toTest.contains(stroke)) { |
| // 6581899: performance improvement for SortingFocusTraversalPolicy |
| Component last = getFocusTraversalPolicy().getLastComponent(this); |
| if (currentFocused == last || last == null) { |
| if (traverseOut(FORWARD)) { |
| e.consume(); |
| return true; |
| } |
| } |
| } |
| |
| toTest = getFocusTraversalKeys(KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS); |
| if (toTest.contains(stroke)) { |
| // 6581899: performance improvement for SortingFocusTraversalPolicy |
| Component first = getFocusTraversalPolicy().getFirstComponent(this); |
| if (currentFocused == first || first == null) { |
| if (traverseOut(BACKWARD)) { |
| e.consume(); |
| return true; |
| } |
| } |
| } |
| return false; |
| } |
| |
| /** |
| * This method is called by the embedder when we should receive focus as element |
| * of the traversal chain. The method requests focus on: |
| * 1. the first Component of this EmbeddedFrame if user moves focus forward |
| * in the focus traversal cycle. |
| * 2. the last Component of this EmbeddedFrame if user moves focus backward |
| * in the focus traversal cycle. |
| * |
| * The direction parameter specifies which of the two mentioned cases is |
| * happening. Use FORWARD and BACKWARD constants defined in the EmbeddedFrame class |
| * to avoid confusing boolean values. |
| * |
| * A concrete implementation of this method is defined in the platform-dependent |
| * subclasses. |
| * |
| * @param direction FORWARD or BACKWARD |
| * @return true, if the EmbeddedFrame wants to get focus, false otherwise. |
| */ |
| public boolean traverseIn(boolean direction) { |
| Component comp = null; |
| |
| if (direction == FORWARD) { |
| comp = getFocusTraversalPolicy().getFirstComponent(this); |
| } else { |
| comp = getFocusTraversalPolicy().getLastComponent(this); |
| } |
| if (comp != null) { |
| // comp.requestFocus(); - Leads to a hung. |
| |
| AWTAccessor.getKeyboardFocusManagerAccessor().setMostRecentFocusOwner(this, comp); |
| synthesizeWindowActivation(true); |
| } |
| return (null != comp); |
| } |
| |
| /** |
| * This method is called from dispatchKeyEvent in the following two cases: |
| * 1. The focus is on the first Component of this EmbeddedFrame and we are |
| * about to transfer the focus backward. |
| * 2. The focus in on the last Component of this EmbeddedFrame and we are |
| * about to transfer the focus forward. |
| * This is needed to give the opportuity for keyboard focus to leave the |
| * EmbeddedFrame. Override this method, initiate focus transfer in it and |
| * return true if you want the focus to leave EmbeddedFrame's cycle. |
| * The direction parameter specifies which of the two mentioned cases is |
| * happening. Use FORWARD and BACKWARD constants defined in EmbeddedFrame |
| * to avoid confusing boolean values. |
| * |
| * @param direction FORWARD or BACKWARD |
| * @return true, if EmbeddedFrame wants the focus to leave it, |
| * false otherwise. |
| */ |
| protected boolean traverseOut(boolean direction) { |
| return false; |
| } |
| |
| /** |
| * Block modifying any frame attributes, since they aren't applicable |
| * for EmbeddedFrames. |
| */ |
| public void setTitle(String title) {} |
| public void setIconImage(Image image) {} |
| public void setIconImages(java.util.List<? extends Image> icons) {} |
| public void setMenuBar(MenuBar mb) {} |
| public void setResizable(boolean resizable) {} |
| public void remove(MenuComponent m) {} |
| |
| public boolean isResizable() { |
| return true; |
| } |
| |
| public void addNotify() { |
| synchronized (getTreeLock()) { |
| if (!isDisplayable()) { |
| setPeer(new NullEmbeddedFramePeer()); |
| } |
| super.addNotify(); |
| } |
| } |
| |
| // These three functions consitute RFE 4100710. Do not remove. |
| public void setCursorAllowed(boolean isCursorAllowed) { |
| this.isCursorAllowed = isCursorAllowed; |
| final FramePeer peer = AWTAccessor.getComponentAccessor().getPeer(this); |
| peer.updateCursorImmediately(); |
| } |
| public boolean isCursorAllowed() { |
| return isCursorAllowed; |
| } |
| public Cursor getCursor() { |
| return (isCursorAllowed) |
| ? super.getCursor() |
| : Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR); |
| } |
| |
| protected void setPeer(final ComponentPeer p){ |
| AWTAccessor.getComponentAccessor().setPeer(EmbeddedFrame.this, p); |
| }; |
| |
| /** |
| * Synthesize native message to activate or deactivate EmbeddedFrame window |
| * depending on the value of parameter {@code b}. |
| * Peers should override this method if they are to implement |
| * this functionality. |
| * @param doActivate if {@code true}, activates the window; |
| * otherwise, deactivates the window |
| */ |
| public void synthesizeWindowActivation(boolean doActivate) {} |
| |
| /** |
| * Moves this embedded frame to a new location. The top-left corner of |
| * the new location is specified by the {@code x} and {@code y} |
| * parameters relative to the native parent component. |
| * <p> |
| * setLocation() and setBounds() for EmbeddedFrame really don't move it |
| * within the native parent. These methods always put embedded frame to |
| * (0, 0) for backward compatibility. To allow moving embedded frame |
| * setLocationPrivate() and setBoundsPrivate() were introduced, and they |
| * work just the same way as setLocation() and setBounds() for usual, |
| * non-embedded components. |
| * </p> |
| * <p> |
| * Using usual get/setLocation() and get/setBounds() together with new |
| * get/setLocationPrivate() and get/setBoundsPrivate() is not recommended. |
| * For example, calling getBoundsPrivate() after setLocation() works fine, |
| * but getBounds() after setBoundsPrivate() may return unpredictable value. |
| * </p> |
| * @param x the new <i>x</i>-coordinate relative to the parent component |
| * @param y the new <i>y</i>-coordinate relative to the parent component |
| * @see java.awt.Component#setLocation |
| * @see #getLocationPrivate |
| * @see #setBoundsPrivate |
| * @see #getBoundsPrivate |
| * @since 1.5 |
| */ |
| protected void setLocationPrivate(int x, int y) { |
| Dimension size = getSize(); |
| setBoundsPrivate(x, y, size.width, size.height); |
| } |
| |
| /** |
| * Gets the location of this embedded frame as a point specifying the |
| * top-left corner relative to parent component. |
| * <p> |
| * setLocation() and setBounds() for EmbeddedFrame really don't move it |
| * within the native parent. These methods always put embedded frame to |
| * (0, 0) for backward compatibility. To allow getting location and size |
| * of embedded frame getLocationPrivate() and getBoundsPrivate() were |
| * introduced, and they work just the same way as getLocation() and getBounds() |
| * for ususal, non-embedded components. |
| * </p> |
| * <p> |
| * Using usual get/setLocation() and get/setBounds() together with new |
| * get/setLocationPrivate() and get/setBoundsPrivate() is not recommended. |
| * For example, calling getBoundsPrivate() after setLocation() works fine, |
| * but getBounds() after setBoundsPrivate() may return unpredictable value. |
| * </p> |
| * @return a point indicating this embedded frame's top-left corner |
| * @see java.awt.Component#getLocation |
| * @see #setLocationPrivate |
| * @see #setBoundsPrivate |
| * @see #getBoundsPrivate |
| * @since 1.6 |
| */ |
| protected Point getLocationPrivate() { |
| Rectangle bounds = getBoundsPrivate(); |
| return new Point(bounds.x, bounds.y); |
| } |
| |
| /** |
| * Moves and resizes this embedded frame. The new location of the top-left |
| * corner is specified by {@code x} and {@code y} parameters |
| * relative to the native parent component. The new size is specified by |
| * {@code width} and {@code height}. |
| * <p> |
| * setLocation() and setBounds() for EmbeddedFrame really don't move it |
| * within the native parent. These methods always put embedded frame to |
| * (0, 0) for backward compatibility. To allow moving embedded frames |
| * setLocationPrivate() and setBoundsPrivate() were introduced, and they |
| * work just the same way as setLocation() and setBounds() for usual, |
| * non-embedded components. |
| * </p> |
| * <p> |
| * Using usual get/setLocation() and get/setBounds() together with new |
| * get/setLocationPrivate() and get/setBoundsPrivate() is not recommended. |
| * For example, calling getBoundsPrivate() after setLocation() works fine, |
| * but getBounds() after setBoundsPrivate() may return unpredictable value. |
| * </p> |
| * @param x the new <i>x</i>-coordinate relative to the parent component |
| * @param y the new <i>y</i>-coordinate relative to the parent component |
| * @param width the new {@code width} of this embedded frame |
| * @param height the new {@code height} of this embedded frame |
| * @see java.awt.Component#setBounds |
| * @see #setLocationPrivate |
| * @see #getLocationPrivate |
| * @see #getBoundsPrivate |
| * @since 1.5 |
| */ |
| protected void setBoundsPrivate(int x, int y, int width, int height) { |
| final FramePeer peer = AWTAccessor.getComponentAccessor().getPeer(this); |
| if (peer != null) { |
| peer.setBoundsPrivate(x, y, width, height); |
| } |
| } |
| |
| /** |
| * Gets the bounds of this embedded frame as a rectangle specifying the |
| * width, height and location relative to the native parent component. |
| * <p> |
| * setLocation() and setBounds() for EmbeddedFrame really don't move it |
| * within the native parent. These methods always put embedded frame to |
| * (0, 0) for backward compatibility. To allow getting location and size |
| * of embedded frames getLocationPrivate() and getBoundsPrivate() were |
| * introduced, and they work just the same way as getLocation() and getBounds() |
| * for ususal, non-embedded components. |
| * </p> |
| * <p> |
| * Using usual get/setLocation() and get/setBounds() together with new |
| * get/setLocationPrivate() and get/setBoundsPrivate() is not recommended. |
| * For example, calling getBoundsPrivate() after setLocation() works fine, |
| * but getBounds() after setBoundsPrivate() may return unpredictable value. |
| * </p> |
| * @return a rectangle indicating this embedded frame's bounds |
| * @see java.awt.Component#getBounds |
| * @see #setLocationPrivate |
| * @see #getLocationPrivate |
| * @see #setBoundsPrivate |
| * @since 1.6 |
| */ |
| protected Rectangle getBoundsPrivate() { |
| final FramePeer peer = AWTAccessor.getComponentAccessor().getPeer(this); |
| if (peer != null) { |
| return peer.getBoundsPrivate(); |
| } |
| else { |
| return getBounds(); |
| } |
| } |
| |
| public void toFront() {} |
| public void toBack() {} |
| |
| public abstract void registerAccelerator(AWTKeyStroke stroke); |
| public abstract void unregisterAccelerator(AWTKeyStroke stroke); |
| |
| /** |
| * Checks if the component is in an EmbeddedFrame. If so, |
| * returns the applet found in the hierarchy or null if |
| * not found. |
| * @return the parent applet or {@code null} |
| * @since 1.6 |
| * |
| * @deprecated The Applet API is deprecated. See the |
| * <a href="../../java/applet/package-summary.html"> java.applet package |
| * documentation</a> for further information. |
| */ |
| @Deprecated(since = "9") |
| public static Applet getAppletIfAncestorOf(Component comp) { |
| Container parent = comp.getParent(); |
| Applet applet = null; |
| while (parent != null && !(parent instanceof EmbeddedFrame)) { |
| if (parent instanceof Applet) { |
| applet = (Applet)parent; |
| } |
| parent = parent.getParent(); |
| } |
| return parent == null ? null : applet; |
| } |
| |
| /** |
| * This method should be overriden in subclasses. It is |
| * called when window this frame is within should be blocked |
| * by some modal dialog. |
| */ |
| public void notifyModalBlocked(Dialog blocker, boolean blocked) { |
| } |
| |
| private static class NullEmbeddedFramePeer |
| extends NullComponentPeer implements FramePeer { |
| public void setTitle(String title) {} |
| public void setIconImage(Image im) {} |
| public void updateIconImages() {} |
| public void setMenuBar(MenuBar mb) {} |
| public void setResizable(boolean resizeable) {} |
| public void setState(int state) {} |
| public int getState() { return Frame.NORMAL; } |
| public void setMaximizedBounds(Rectangle b) {} |
| public void toFront() {} |
| public void toBack() {} |
| public void updateFocusableWindowState() {} |
| public void updateAlwaysOnTop() {} |
| public void updateAlwaysOnTopState() {} |
| public Component getGlobalHeavyweightFocusOwner() { return null; } |
| public void setBoundsPrivate(int x, int y, int width, int height) { |
| setBounds(x, y, width, height, SET_BOUNDS); |
| } |
| public Rectangle getBoundsPrivate() { |
| return getBounds(); |
| } |
| public void setModalBlocked(Dialog blocker, boolean blocked) {} |
| |
| public void restack() { |
| throw new UnsupportedOperationException(); |
| } |
| |
| public boolean isRestackSupported() { |
| return false; |
| } |
| public boolean requestWindowFocus() { |
| return false; |
| } |
| public void updateMinimumSize() { |
| } |
| |
| public void setOpacity(float opacity) { |
| } |
| |
| public void setOpaque(boolean isOpaque) { |
| } |
| |
| public void updateWindow() { |
| } |
| |
| public void repositionSecurityWarning() { |
| } |
| |
| public void emulateActivation(boolean activate) { |
| } |
| } |
| } // class EmbeddedFrame |