Path: blob/master/src/java.desktop/share/classes/sun/awt/EmbeddedFrame.java
41152 views
/*1* Copyright (c) 1996, 2021, 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*/2425package sun.awt;2627import java.applet.Applet;28import java.awt.AWTKeyStroke;29import java.awt.Component;30import java.awt.Container;31import java.awt.Cursor;32import java.awt.Dialog;33import java.awt.Dimension;34import java.awt.Frame;35import java.awt.Image;36import java.awt.KeyEventDispatcher;37import java.awt.KeyboardFocusManager;38import java.awt.MenuBar;39import java.awt.MenuComponent;40import java.awt.Point;41import java.awt.Rectangle;42import java.awt.event.KeyEvent;43import java.awt.peer.ComponentPeer;44import java.awt.peer.FramePeer;45import java.beans.PropertyChangeEvent;46import java.beans.PropertyChangeListener;47import java.io.Serial;48import java.util.Set;4950/**51* A generic container used for embedding Java components, usually applets.52* An EmbeddedFrame has two related uses:53*54* . Within a Java-based application, an EmbeddedFrame serves as a sort of55* firewall, preventing the contained components or applets from using56* getParent() to find parent components, such as menubars.57*58* . Within a C-based application, an EmbeddedFrame contains a window handle59* which was created by the application, which serves as the top-level60* Java window. EmbeddedFrames created for this purpose are passed-in a61* handle of an existing window created by the application. The window62* handle should be of the appropriate native type for a specific63* platform, as stored in the pData field of the ComponentPeer.64*65* @author Thomas Ball66*/67public abstract class EmbeddedFrame extends Frame68implements KeyEventDispatcher, PropertyChangeListener {6970private boolean isCursorAllowed = true;71private boolean supportsXEmbed = false;72@SuppressWarnings("serial") // Not statically typed as Serializable73private KeyboardFocusManager appletKFM;7475/**76* Use serialVersionUID from JDK 1.1 for interoperability.77*/78@Serial79private static final long serialVersionUID = 2967042741780317130L;8081/*82* The constants define focus traversal directions.83* Use them in {@code traverseIn}, {@code traverseOut} methods.84*/85protected static final boolean FORWARD = true;86protected static final boolean BACKWARD = false;8788public boolean supportsXEmbed() {89return supportsXEmbed && SunToolkit.needsXEmbed();90}9192protected EmbeddedFrame(boolean supportsXEmbed) {93this((long)0, supportsXEmbed);94}959697protected EmbeddedFrame() {98this((long)0);99}100101/**102* @deprecated This constructor will be removed in 1.5103*/104@Deprecated105protected EmbeddedFrame(int handle) {106this((long)handle);107}108109protected EmbeddedFrame(long handle) {110this(handle, false);111}112113protected EmbeddedFrame(long handle, boolean supportsXEmbed) {114this.supportsXEmbed = supportsXEmbed;115registerListeners();116}117118/**119* Block introspection of a parent window by this child.120*/121public Container getParent() {122return null;123}124125/**126* Needed to track which KeyboardFocusManager is current. We want to avoid memory127* leaks, so when KFM stops being current, we remove ourselves as listeners.128*/129public void propertyChange(PropertyChangeEvent evt) {130// We don't handle any other properties. Skip it.131if (!evt.getPropertyName().equals("managingFocus")) {132return;133}134135// We only do it if it stops being current. Technically, we should136// never get an event about KFM starting being current.137if (evt.getNewValue() == Boolean.TRUE) {138return;139}140141// should be the same as appletKFM142removeTraversingOutListeners((KeyboardFocusManager)evt.getSource());143144appletKFM = KeyboardFocusManager.getCurrentKeyboardFocusManager();145if (isVisible()) {146addTraversingOutListeners(appletKFM);147}148}149150/**151* Register us as KeyEventDispatcher and property "managingFocus" listeners.152*/153private void addTraversingOutListeners(KeyboardFocusManager kfm) {154kfm.addKeyEventDispatcher(this);155kfm.addPropertyChangeListener("managingFocus", this);156}157158/**159* Deregister us as KeyEventDispatcher and property "managingFocus" listeners.160*/161private void removeTraversingOutListeners(KeyboardFocusManager kfm) {162kfm.removeKeyEventDispatcher(this);163kfm.removePropertyChangeListener("managingFocus", this);164}165166/**167* Because there may be many AppContexts, and we can't be sure where this168* EmbeddedFrame is first created or shown, we can't automatically determine169* the correct KeyboardFocusManager to attach to as KeyEventDispatcher.170* Those who want to use the functionality of traversing out of the EmbeddedFrame171* must call this method on the Applet's AppContext. After that, all the changes172* can be handled automatically, including possible replacement of173* KeyboardFocusManager.174*/175public void registerListeners() {176if (appletKFM != null) {177removeTraversingOutListeners(appletKFM);178}179appletKFM = KeyboardFocusManager.getCurrentKeyboardFocusManager();180if (isVisible()) {181addTraversingOutListeners(appletKFM);182}183}184185/**186* Needed to avoid memory leak: we register this EmbeddedFrame as a listener with187* KeyboardFocusManager of applet's AppContext. We don't want the KFM to keep188* reference to our EmbeddedFrame forever if the Frame is no longer in use, so we189* add listeners in show() and remove them in hide().190*/191@SuppressWarnings("deprecation")192public void show() {193if (appletKFM != null) {194addTraversingOutListeners(appletKFM);195}196super.show();197}198199/**200* Needed to avoid memory leak: we register this EmbeddedFrame as a listener with201* KeyboardFocusManager of applet's AppContext. We don't want the KFM to keep202* reference to our EmbeddedFrame forever if the Frame is no longer in use, so we203* add listeners in show() and remove them in hide().204*/205@SuppressWarnings("deprecation")206public void hide() {207if (appletKFM != null) {208removeTraversingOutListeners(appletKFM);209}210super.hide();211}212213/**214* Need this method to detect when the focus may have chance to leave the215* focus cycle root which is EmbeddedFrame. Mostly, the code here is copied216* from DefaultKeyboardFocusManager.processKeyEvent with some minor217* modifications.218*/219public boolean dispatchKeyEvent(KeyEvent e) {220221Container currentRoot = AWTAccessor.getKeyboardFocusManagerAccessor()222.getCurrentFocusCycleRoot();223224// if we are not in EmbeddedFrame's cycle, we should not try to leave.225if (this != currentRoot) {226return false;227}228229// KEY_TYPED events cannot be focus traversal keys230if (e.getID() == KeyEvent.KEY_TYPED) {231return false;232}233234if (!getFocusTraversalKeysEnabled() || e.isConsumed()) {235return false;236}237238AWTKeyStroke stroke = AWTKeyStroke.getAWTKeyStrokeForEvent(e);239Set<AWTKeyStroke> toTest;240Component currentFocused = e.getComponent();241242toTest = getFocusTraversalKeys(KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS);243if (toTest.contains(stroke)) {244// 6581899: performance improvement for SortingFocusTraversalPolicy245Component last = getFocusTraversalPolicy().getLastComponent(this);246if (currentFocused == last || last == null) {247if (traverseOut(FORWARD)) {248e.consume();249return true;250}251}252}253254toTest = getFocusTraversalKeys(KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS);255if (toTest.contains(stroke)) {256// 6581899: performance improvement for SortingFocusTraversalPolicy257Component first = getFocusTraversalPolicy().getFirstComponent(this);258if (currentFocused == first || first == null) {259if (traverseOut(BACKWARD)) {260e.consume();261return true;262}263}264}265return false;266}267268/**269* This method is called by the embedder when we should receive focus as element270* of the traversal chain. The method requests focus on:271* 1. the first Component of this EmbeddedFrame if user moves focus forward272* in the focus traversal cycle.273* 2. the last Component of this EmbeddedFrame if user moves focus backward274* in the focus traversal cycle.275*276* The direction parameter specifies which of the two mentioned cases is277* happening. Use FORWARD and BACKWARD constants defined in the EmbeddedFrame class278* to avoid confusing boolean values.279*280* A concrete implementation of this method is defined in the platform-dependent281* subclasses.282*283* @param direction FORWARD or BACKWARD284* @return true, if the EmbeddedFrame wants to get focus, false otherwise.285*/286public boolean traverseIn(boolean direction) {287Component comp = null;288289if (direction == FORWARD) {290comp = getFocusTraversalPolicy().getFirstComponent(this);291} else {292comp = getFocusTraversalPolicy().getLastComponent(this);293}294if (comp != null) {295// comp.requestFocus(); - Leads to a hung.296297AWTAccessor.getKeyboardFocusManagerAccessor().setMostRecentFocusOwner(this, comp);298synthesizeWindowActivation(true);299}300return (null != comp);301}302303/**304* This method is called from dispatchKeyEvent in the following two cases:305* 1. The focus is on the first Component of this EmbeddedFrame and we are306* about to transfer the focus backward.307* 2. The focus in on the last Component of this EmbeddedFrame and we are308* about to transfer the focus forward.309* This is needed to give the opportuity for keyboard focus to leave the310* EmbeddedFrame. Override this method, initiate focus transfer in it and311* return true if you want the focus to leave EmbeddedFrame's cycle.312* The direction parameter specifies which of the two mentioned cases is313* happening. Use FORWARD and BACKWARD constants defined in EmbeddedFrame314* to avoid confusing boolean values.315*316* @param direction FORWARD or BACKWARD317* @return true, if EmbeddedFrame wants the focus to leave it,318* false otherwise.319*/320protected boolean traverseOut(boolean direction) {321return false;322}323324/**325* Block modifying any frame attributes, since they aren't applicable326* for EmbeddedFrames.327*/328public void setTitle(String title) {}329public void setIconImage(Image image) {}330public void setIconImages(java.util.List<? extends Image> icons) {}331public void setMenuBar(MenuBar mb) {}332public void setResizable(boolean resizable) {}333public void remove(MenuComponent m) {}334335public boolean isResizable() {336return true;337}338339public void addNotify() {340synchronized (getTreeLock()) {341if (!isDisplayable()) {342setPeer(new NullEmbeddedFramePeer());343}344super.addNotify();345}346}347348// These three functions consitute RFE 4100710. Do not remove.349public void setCursorAllowed(boolean isCursorAllowed) {350this.isCursorAllowed = isCursorAllowed;351final FramePeer peer = AWTAccessor.getComponentAccessor().getPeer(this);352peer.updateCursorImmediately();353}354public boolean isCursorAllowed() {355return isCursorAllowed;356}357public Cursor getCursor() {358return (isCursorAllowed)359? super.getCursor()360: Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR);361}362363protected void setPeer(final ComponentPeer p){364AWTAccessor.getComponentAccessor().setPeer(EmbeddedFrame.this, p);365};366367/**368* Synthesize native message to activate or deactivate EmbeddedFrame window369* depending on the value of parameter {@code b}.370* Peers should override this method if they are to implement371* this functionality.372* @param doActivate if {@code true}, activates the window;373* otherwise, deactivates the window374*/375public void synthesizeWindowActivation(boolean doActivate) {}376377/**378* Moves this embedded frame to a new location. The top-left corner of379* the new location is specified by the {@code x} and {@code y}380* parameters relative to the native parent component.381* <p>382* setLocation() and setBounds() for EmbeddedFrame really don't move it383* within the native parent. These methods always put embedded frame to384* (0, 0) for backward compatibility. To allow moving embedded frame385* setLocationPrivate() and setBoundsPrivate() were introduced, and they386* work just the same way as setLocation() and setBounds() for usual,387* non-embedded components.388* </p>389* <p>390* Using usual get/setLocation() and get/setBounds() together with new391* get/setLocationPrivate() and get/setBoundsPrivate() is not recommended.392* For example, calling getBoundsPrivate() after setLocation() works fine,393* but getBounds() after setBoundsPrivate() may return unpredictable value.394* </p>395* @param x the new <i>x</i>-coordinate relative to the parent component396* @param y the new <i>y</i>-coordinate relative to the parent component397* @see java.awt.Component#setLocation398* @see #getLocationPrivate399* @see #setBoundsPrivate400* @see #getBoundsPrivate401* @since 1.5402*/403protected void setLocationPrivate(int x, int y) {404Dimension size = getSize();405setBoundsPrivate(x, y, size.width, size.height);406}407408/**409* Gets the location of this embedded frame as a point specifying the410* top-left corner relative to parent component.411* <p>412* setLocation() and setBounds() for EmbeddedFrame really don't move it413* within the native parent. These methods always put embedded frame to414* (0, 0) for backward compatibility. To allow getting location and size415* of embedded frame getLocationPrivate() and getBoundsPrivate() were416* introduced, and they work just the same way as getLocation() and getBounds()417* for ususal, non-embedded components.418* </p>419* <p>420* Using usual get/setLocation() and get/setBounds() together with new421* get/setLocationPrivate() and get/setBoundsPrivate() is not recommended.422* For example, calling getBoundsPrivate() after setLocation() works fine,423* but getBounds() after setBoundsPrivate() may return unpredictable value.424* </p>425* @return a point indicating this embedded frame's top-left corner426* @see java.awt.Component#getLocation427* @see #setLocationPrivate428* @see #setBoundsPrivate429* @see #getBoundsPrivate430* @since 1.6431*/432protected Point getLocationPrivate() {433Rectangle bounds = getBoundsPrivate();434return new Point(bounds.x, bounds.y);435}436437/**438* Moves and resizes this embedded frame. The new location of the top-left439* corner is specified by {@code x} and {@code y} parameters440* relative to the native parent component. The new size is specified by441* {@code width} and {@code height}.442* <p>443* setLocation() and setBounds() for EmbeddedFrame really don't move it444* within the native parent. These methods always put embedded frame to445* (0, 0) for backward compatibility. To allow moving embedded frames446* setLocationPrivate() and setBoundsPrivate() were introduced, and they447* work just the same way as setLocation() and setBounds() for usual,448* non-embedded components.449* </p>450* <p>451* Using usual get/setLocation() and get/setBounds() together with new452* get/setLocationPrivate() and get/setBoundsPrivate() is not recommended.453* For example, calling getBoundsPrivate() after setLocation() works fine,454* but getBounds() after setBoundsPrivate() may return unpredictable value.455* </p>456* @param x the new <i>x</i>-coordinate relative to the parent component457* @param y the new <i>y</i>-coordinate relative to the parent component458* @param width the new {@code width} of this embedded frame459* @param height the new {@code height} of this embedded frame460* @see java.awt.Component#setBounds461* @see #setLocationPrivate462* @see #getLocationPrivate463* @see #getBoundsPrivate464* @since 1.5465*/466protected void setBoundsPrivate(int x, int y, int width, int height) {467final FramePeer peer = AWTAccessor.getComponentAccessor().getPeer(this);468if (peer != null) {469peer.setBoundsPrivate(x, y, width, height);470}471}472473/**474* Gets the bounds of this embedded frame as a rectangle specifying the475* width, height and location relative to the native parent component.476* <p>477* setLocation() and setBounds() for EmbeddedFrame really don't move it478* within the native parent. These methods always put embedded frame to479* (0, 0) for backward compatibility. To allow getting location and size480* of embedded frames getLocationPrivate() and getBoundsPrivate() were481* introduced, and they work just the same way as getLocation() and getBounds()482* for ususal, non-embedded components.483* </p>484* <p>485* Using usual get/setLocation() and get/setBounds() together with new486* get/setLocationPrivate() and get/setBoundsPrivate() is not recommended.487* For example, calling getBoundsPrivate() after setLocation() works fine,488* but getBounds() after setBoundsPrivate() may return unpredictable value.489* </p>490* @return a rectangle indicating this embedded frame's bounds491* @see java.awt.Component#getBounds492* @see #setLocationPrivate493* @see #getLocationPrivate494* @see #setBoundsPrivate495* @since 1.6496*/497protected Rectangle getBoundsPrivate() {498final FramePeer peer = AWTAccessor.getComponentAccessor().getPeer(this);499if (peer != null) {500return peer.getBoundsPrivate();501}502else {503return getBounds();504}505}506507public void toFront() {}508public void toBack() {}509510public abstract void registerAccelerator(AWTKeyStroke stroke);511public abstract void unregisterAccelerator(AWTKeyStroke stroke);512513/**514* Checks if the component is in an EmbeddedFrame. If so,515* returns the applet found in the hierarchy or null if516* not found.517* @return the parent applet or {@code null}518* @since 1.6519*520* @deprecated The Applet API is deprecated. See the521* <a href="../../java/applet/package-summary.html"> java.applet package522* documentation</a> for further information.523*/524@Deprecated(since = "9", forRemoval = true)525@SuppressWarnings("removal")526public static Applet getAppletIfAncestorOf(Component comp) {527Container parent = comp.getParent();528Applet applet = null;529while (parent != null && !(parent instanceof EmbeddedFrame)) {530if (parent instanceof Applet) {531applet = (Applet)parent;532}533parent = parent.getParent();534}535return parent == null ? null : applet;536}537538/**539* This method should be overriden in subclasses. It is540* called when window this frame is within should be blocked541* by some modal dialog.542*/543public void notifyModalBlocked(Dialog blocker, boolean blocked) {544}545546private static class NullEmbeddedFramePeer547extends NullComponentPeer implements FramePeer {548public void setTitle(String title) {}549public void setIconImage(Image im) {}550public void updateIconImages() {}551public void setMenuBar(MenuBar mb) {}552public void setResizable(boolean resizeable) {}553public void setState(int state) {}554public int getState() { return Frame.NORMAL; }555public void setMaximizedBounds(Rectangle b) {}556public void toFront() {}557public void toBack() {}558public void updateFocusableWindowState() {}559public void updateAlwaysOnTop() {}560public void updateAlwaysOnTopState() {}561public Component getGlobalHeavyweightFocusOwner() { return null; }562public void setBoundsPrivate(int x, int y, int width, int height) {563setBounds(x, y, width, height, SET_BOUNDS);564}565public Rectangle getBoundsPrivate() {566return getBounds();567}568public void setModalBlocked(Dialog blocker, boolean blocked) {}569570public void restack() {571throw new UnsupportedOperationException();572}573574public boolean isRestackSupported() {575return false;576}577public boolean requestWindowFocus() {578return false;579}580public void updateMinimumSize() {581}582583public void setOpacity(float opacity) {584}585586public void setOpaque(boolean isOpaque) {587}588589public void updateWindow() {590}591592public void repositionSecurityWarning() {593}594595public void emulateActivation(boolean activate) {596}597}598} // class EmbeddedFrame599600601