2 Copyright (C) 1999, 2000, 2002, 2003, 2004 Free Software Foundation
4 This file is part of GNU Classpath.
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING. If not, write to the
18 Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library. Thus, the terms and
23 conditions of the GNU General Public License cover the whole
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module. An independent module is a module which is not derived from
33 or based on this library. If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so. If you do not wish to do so, delete this
36 exception statement from your version. */
41 import java.awt.event.ComponentEvent;
42 import java.awt.event.FocusEvent;
43 import java.awt.event.WindowAdapter;
44 import java.awt.event.WindowEvent;
45 import java.awt.event.WindowFocusListener;
46 import java.awt.event.WindowListener;
47 import java.awt.event.WindowStateListener;
48 import java.awt.peer.WindowPeer;
49 import java.lang.ref.Reference;
50 import java.lang.ref.WeakReference;
51 import java.util.EventListener;
52 import java.util.Iterator;
53 import java.util.Locale;
54 import java.util.ResourceBundle;
55 import java.util.Vector;
57 import javax.accessibility.Accessible;
58 import javax.accessibility.AccessibleContext;
59 import javax.accessibility.AccessibleRole;
60 import javax.accessibility.AccessibleState;
61 import javax.accessibility.AccessibleStateSet;
64 * This class represents a top-level window with no decorations.
66 * @author Aaron M. Renn (arenn@urbanophile.com)
67 * @author Warren Levy (warrenl@cygnus.com)
69 public class Window extends Container implements Accessible
71 private static final long serialVersionUID = 4497834738069338734L;
73 // Serialized fields, from Sun's serialization spec.
74 private String warningString = null;
75 private int windowSerializedDataVersion = 0; // FIXME
77 // private FocusManager focusMgr; // FIXME: what is this?
79 private int state = 0;
81 private boolean focusableWindowState = true;
83 // A list of other top-level windows owned by this window.
84 private transient Vector ownedWindows = new Vector();
86 private transient WindowListener windowListener;
87 private transient WindowFocusListener windowFocusListener;
88 private transient WindowStateListener windowStateListener;
89 private transient GraphicsConfiguration graphicsConfiguration;
91 private transient boolean shown;
93 private transient Component windowFocusOwner;
95 protected class AccessibleAWTWindow extends AccessibleAWTContainer
97 public AccessibleRole getAccessibleRole()
99 return AccessibleRole.WINDOW;
102 public AccessibleStateSet getAccessibleStateSet()
104 AccessibleStateSet states = super.getAccessibleStateSet();
106 states.add(AccessibleState.ACTIVE);
112 * This (package access) constructor is used by subclasses that want
113 * to build windows that do not have parents. Eg. toplevel
114 * application frames. Subclasses cannot call super(null), since
115 * null is an illegal argument.
120 // Windows are the only Containers that default to being focus
122 focusCycleRoot = true;
123 setLayout(new BorderLayout());
125 addWindowFocusListener (new WindowAdapter ()
127 public void windowGainedFocus (WindowEvent event)
129 if (windowFocusOwner != null)
131 // FIXME: move this section and the other similar
132 // sections in Component into a separate method.
133 EventQueue eq = Toolkit.getDefaultToolkit ().getSystemEventQueue ();
136 KeyboardFocusManager manager = KeyboardFocusManager.getCurrentKeyboardFocusManager ();
137 Component currentFocusOwner = manager.getGlobalPermanentFocusOwner ();
138 if (currentFocusOwner != null)
140 eq.postEvent (new FocusEvent (currentFocusOwner, FocusEvent.FOCUS_LOST,
141 false, windowFocusOwner));
142 eq.postEvent (new FocusEvent (windowFocusOwner, FocusEvent.FOCUS_GAINED,
143 false, currentFocusOwner));
146 eq.postEvent (new FocusEvent (windowFocusOwner, FocusEvent.FOCUS_GAINED, false));
153 Window(GraphicsConfiguration gc)
156 graphicsConfiguration = gc;
160 * Initializes a new instance of <code>Window</code> with the specified
161 * parent. The window will initially be invisible.
163 * @param owner The owning <code>Frame</code> of this window.
165 * @exception IllegalArgumentException If the owner's GraphicsConfiguration
166 * is not from a screen device, or if owner is null; this exception is always
167 * thrown when GraphicsEnvironment.isHeadless returns true.
169 public Window(Frame owner)
171 this (owner, owner.getGraphicsConfiguration ());
175 * Initializes a new instance of <code>Window</code> with the specified
176 * parent. The window will initially be invisible.
178 * @exception IllegalArgumentException If the owner's GraphicsConfiguration
179 * is not from a screen device, or if owner is null; this exception is always
180 * thrown when GraphicsEnvironment.isHeadless returns true.
184 public Window(Window owner)
186 this (owner, owner.getGraphicsConfiguration ());
190 * Initializes a new instance of <code>Window</code> with the specified
191 * parent. The window will initially be invisible.
193 * @exception IllegalArgumentException If owner is null or if gc is not from a
194 * screen device; this exception is always thrown when
195 * GraphicsEnvironment.isHeadless returns true.
199 public Window(Window owner, GraphicsConfiguration gc)
203 synchronized (getTreeLock())
206 throw new IllegalArgumentException ("owner must not be null");
209 owner.ownedWindows.add(new WeakReference(this));
212 // FIXME: make this text visible in the window.
213 SecurityManager s = System.getSecurityManager();
214 if (s != null && ! s.checkTopLevelWindow(this))
215 warningString = System.getProperty("awt.appletWarning");
218 && gc.getDevice().getType() != GraphicsDevice.TYPE_RASTER_SCREEN)
219 throw new IllegalArgumentException ("gc must be from a screen device");
222 graphicsConfiguration = GraphicsEnvironment.getLocalGraphicsEnvironment()
223 .getDefaultScreenDevice()
224 .getDefaultConfiguration();
226 graphicsConfiguration = gc;
229 GraphicsConfiguration getGraphicsConfigurationImpl()
231 if (graphicsConfiguration != null)
232 return graphicsConfiguration;
234 return super.getGraphicsConfigurationImpl();
238 * Creates the native peer for this window.
240 public void addNotify()
243 peer = getToolkit().createWindow(this);
248 * Relays out this window's child components at their preferred size.
250 * @specnote pack() doesn't appear to be called internally by show(), so
251 * we duplicate some of the functionality.
255 if (parent != null && !parent.isDisplayable())
260 setSize(getPreferredSize());
266 * Shows on-screen this window and any of its owned windows for whom
267 * isVisible returns true.
271 if (parent != null && !parent.isDisplayable())
276 // Show visible owned windows.
277 synchronized (getTreeLock())
279 Iterator e = ownedWindows.iterator();
282 Window w = (Window)(((Reference) e.next()).get());
286 w.getPeer().setVisible(true);
289 // Remove null weak reference from ownedWindows.
290 // Unfortunately this can't be done in the Window's
291 // finalize method because there is no way to guarantee
292 // synchronous access to ownedWindows there.
300 KeyboardFocusManager manager = KeyboardFocusManager.getCurrentKeyboardFocusManager ();
301 manager.setGlobalFocusedWindow (this);
305 FocusTraversalPolicy policy = getFocusTraversalPolicy ();
306 Component initialFocusOwner = null;
309 initialFocusOwner = policy.getInitialComponent (this);
311 if (initialFocusOwner != null)
312 initialFocusOwner.requestFocusInWindow ();
320 // Hide visible owned windows.
321 synchronized (getTreeLock ())
323 Iterator e = ownedWindows.iterator();
326 Window w = (Window)(((Reference) e.next()).get());
329 if (w.isVisible() && w.getPeer() != null)
330 w.getPeer().setVisible(false);
339 public boolean isDisplayable()
341 if (super.isDisplayable())
347 * Destroys any resources associated with this window. This includes
348 * all components in the window and all owned top-level windows.
350 public void dispose()
354 synchronized (getTreeLock ())
356 Iterator e = ownedWindows.iterator();
359 Window w = (Window)(((Reference) e.next()).get());
363 // Remove null weak reference from ownedWindows.
367 for (int i = 0; i < ncomponents; ++i)
368 component[i].removeNotify();
371 // Post a WINDOW_CLOSED event.
372 WindowEvent we = new WindowEvent(this, WindowEvent.WINDOW_CLOSED);
373 getToolkit().getSystemEventQueue().postEvent(we);
378 * Sends this window to the back so that all other windows display in
385 WindowPeer wp = (WindowPeer) peer;
391 * Brings this window to the front so that it displays in front of
394 public void toFront()
398 WindowPeer wp = (WindowPeer) peer;
404 * Returns the toolkit used to create this window.
406 * @return The toolkit used to create this window.
408 * @specnote Unlike Component.getToolkit, this implementation always
409 * returns the value of Toolkit.getDefaultToolkit().
411 public Toolkit getToolkit()
413 return Toolkit.getDefaultToolkit();
417 * Returns the warning string that will be displayed if this window is
418 * popped up by an unsecure applet or application.
420 * @return The unsecure window warning message.
422 public final String getWarningString()
424 return warningString;
428 * Returns the locale that this window is configured for.
430 * @return The locale this window is configured for.
432 public Locale getLocale()
434 return locale == null ? Locale.getDefault() : locale;
439 public InputContext getInputContext()
446 * Sets the cursor for this window to the specifiec cursor.
448 * @param cursor The new cursor for this window.
450 public void setCursor(Cursor cursor)
452 super.setCursor(cursor);
455 public Window getOwner()
457 return (Window) parent;
461 public Window[] getOwnedWindows()
463 Window [] trimmedList;
464 synchronized (getTreeLock ())
466 // Windows with non-null weak references in ownedWindows.
467 Window [] validList = new Window [ownedWindows.size()];
469 Iterator e = ownedWindows.iterator();
473 Window w = (Window)(((Reference) e.next()).get());
475 validList[numValid++] = w;
477 // Remove null weak reference from ownedWindows.
481 if (numValid != validList.length)
483 trimmedList = new Window [numValid];
484 System.arraycopy (validList, 0, trimmedList, 0, numValid);
487 trimmedList = validList;
493 * Adds the specified listener to the list of <code>WindowListeners</code>
494 * that will receive events for this window.
496 * @param listener The <code>WindowListener</code> to add.
498 public synchronized void addWindowListener(WindowListener listener)
500 windowListener = AWTEventMulticaster.add(windowListener, listener);
504 * Removes the specified listener from the list of
505 * <code>WindowListeners</code> that will receive events for this window.
507 * @param listener The <code>WindowListener</code> to remove.
509 public synchronized void removeWindowListener(WindowListener listener)
511 windowListener = AWTEventMulticaster.remove(windowListener, listener);
515 * Returns an array of all the window listeners registered on this window.
519 public synchronized WindowListener[] getWindowListeners()
521 return (WindowListener[])
522 AWTEventMulticaster.getListeners(windowListener,
523 WindowListener.class);
527 * Returns an array of all the window focus listeners registered on this
532 public synchronized WindowFocusListener[] getWindowFocusListeners()
534 return (WindowFocusListener[])
535 AWTEventMulticaster.getListeners(windowFocusListener,
536 WindowFocusListener.class);
540 * Returns an array of all the window state listeners registered on this
545 public synchronized WindowStateListener[] getWindowStateListeners()
547 return (WindowStateListener[])
548 AWTEventMulticaster.getListeners(windowStateListener,
549 WindowStateListener.class);
553 * Adds the specified listener to this window.
555 public void addWindowFocusListener (WindowFocusListener wfl)
557 windowFocusListener = AWTEventMulticaster.add (windowFocusListener, wfl);
561 * Adds the specified listener to this window.
565 public void addWindowStateListener (WindowStateListener wsl)
567 windowStateListener = AWTEventMulticaster.add (windowStateListener, wsl);
571 * Removes the specified listener from this window.
573 public void removeWindowFocusListener (WindowFocusListener wfl)
575 windowFocusListener = AWTEventMulticaster.remove (windowFocusListener, wfl);
579 * Removes the specified listener from this window.
583 public void removeWindowStateListener (WindowStateListener wsl)
585 windowStateListener = AWTEventMulticaster.remove (windowStateListener, wsl);
589 * Returns an array of all the objects currently registered as FooListeners
590 * upon this Window. FooListeners are registered using the addFooListener
593 * @exception ClassCastException If listenerType doesn't specify a class or
594 * interface that implements java.util.EventListener.
598 public EventListener[] getListeners(Class listenerType)
600 if (listenerType == WindowListener.class)
601 return getWindowListeners();
602 return super.getListeners(listenerType);
605 void dispatchEventImpl(AWTEvent e)
607 // Make use of event id's in order to avoid multiple instanceof tests.
608 if (e.id <= WindowEvent.WINDOW_LAST
609 && e.id >= WindowEvent.WINDOW_FIRST
610 && (windowListener != null
611 || windowFocusListener != null
612 || windowStateListener != null
613 || (eventMask & AWTEvent.WINDOW_EVENT_MASK) != 0))
616 super.dispatchEventImpl(e);
620 * Processes the specified event for this window. If the event is an
621 * instance of <code>WindowEvent</code>, then
622 * <code>processWindowEvent()</code> is called to process the event,
623 * otherwise the superclass version of this method is invoked.
625 * @param evt The event to process.
627 protected void processEvent(AWTEvent evt)
629 if (evt instanceof WindowEvent)
630 processWindowEvent((WindowEvent) evt);
632 super.processEvent(evt);
636 * Dispatches this event to any listeners that are listening for
637 * <code>WindowEvents</code> on this window. This method only gets
638 * invoked if it is enabled via <code>enableEvents()</code> or if
639 * a listener has been added.
641 * @param evt The event to process.
643 protected void processWindowEvent(WindowEvent evt)
645 int id = evt.getID();
647 if (id == WindowEvent.WINDOW_GAINED_FOCUS
648 || id == WindowEvent.WINDOW_LOST_FOCUS)
649 processWindowFocusEvent (evt);
650 else if (id == WindowEvent.WINDOW_STATE_CHANGED)
651 processWindowStateEvent (evt);
654 if (windowListener != null)
658 case WindowEvent.WINDOW_ACTIVATED:
659 windowListener.windowActivated(evt);
662 case WindowEvent.WINDOW_CLOSED:
663 windowListener.windowClosed(evt);
666 case WindowEvent.WINDOW_CLOSING:
667 windowListener.windowClosing(evt);
670 case WindowEvent.WINDOW_DEACTIVATED:
671 windowListener.windowDeactivated(evt);
674 case WindowEvent.WINDOW_DEICONIFIED:
675 windowListener.windowDeiconified(evt);
678 case WindowEvent.WINDOW_ICONIFIED:
679 windowListener.windowIconified(evt);
682 case WindowEvent.WINDOW_OPENED:
683 windowListener.windowOpened(evt);
694 * Identifies if this window is active. The active window is a Frame or
695 * Dialog that has focus or owns the active window.
697 * @return true if active, else false.
700 public boolean isActive()
702 KeyboardFocusManager manager = KeyboardFocusManager.getCurrentKeyboardFocusManager ();
703 return manager.getActiveWindow() == this;
707 * Identifies if this window is focused. A window is focused if it is the
708 * focus owner or it contains the focus owner.
710 * @return true if focused, else false.
713 public boolean isFocused()
715 KeyboardFocusManager manager = KeyboardFocusManager.getCurrentKeyboardFocusManager ();
716 return manager.getFocusedWindow() == this;
720 * Returns the child window that has focus if this window is active.
721 * This method returns <code>null</code> if this window is not active
722 * or no children have focus.
724 * @return The component that has focus, or <code>null</code> if no
725 * component has focus.
727 public Component getFocusOwner ()
729 KeyboardFocusManager manager = KeyboardFocusManager.getCurrentKeyboardFocusManager ();
731 Window activeWindow = manager.getActiveWindow ();
733 // The currently-focused Component belongs to the active Window.
734 if (activeWindow == this)
735 return manager.getFocusOwner ();
737 return windowFocusOwner;
741 * Set the focus owner for this window. This method is used to
742 * remember which component was focused when this window lost
743 * top-level focus, so that when it regains top-level focus the same
744 * child component can be refocused.
746 * @param windowFocusOwner the component in this window that owns
749 void setFocusOwner (Component windowFocusOwner)
751 this.windowFocusOwner = windowFocusOwner;
755 * Post a Java 1.0 event to the event queue.
757 * @param e The event to post.
761 public boolean postEvent(Event e)
763 return handleEvent (e);
767 * Tests whether or not this window is visible on the screen.
769 * @return <code>true</code> if this window is visible, <code>false</code>
772 public boolean isShowing()
774 return super.isShowing();
777 public void setLocationRelativeTo (Component c)
779 if (c == null || !c.isShowing ())
784 GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment ();
785 Point center = ge.getCenterPoint ();
786 x = center.x - (width / 2);
787 y = center.y - (height / 2);
790 // FIXME: handle case where component is non-null.
798 public void applyResourceBundle(ResourceBundle rb)
800 throw new Error ("Not implemented");
808 public void applyResourceBundle(String rbName)
810 ResourceBundle rb = ResourceBundle.getBundle(rbName, Locale.getDefault(),
811 ClassLoader.getSystemClassLoader());
813 applyResourceBundle(rb);
817 * Gets the AccessibleContext associated with this <code>Window</code>.
818 * The context is created, if necessary.
820 * @return the associated context
822 public AccessibleContext getAccessibleContext()
824 /* Create the context if this is the first request */
825 if (accessibleContext == null)
826 accessibleContext = new AccessibleAWTWindow();
827 return accessibleContext;
831 * Get graphics configuration. The implementation for Window will
832 * not ask any parent containers, since Window is a toplevel
833 * window and not actually embedded in the parent component.
835 public GraphicsConfiguration getGraphicsConfiguration()
837 if (graphicsConfiguration != null) return graphicsConfiguration;
838 if (peer != null) return peer.getGraphicsConfiguration();
842 protected void processWindowFocusEvent(WindowEvent event)
844 if (windowFocusListener != null)
846 switch (event.getID ())
848 case WindowEvent.WINDOW_GAINED_FOCUS:
849 windowFocusListener.windowGainedFocus (event);
852 case WindowEvent.WINDOW_LOST_FOCUS:
853 windowFocusListener.windowLostFocus (event);
865 protected void processWindowStateEvent(WindowEvent event)
867 if (windowStateListener != null
868 && event.getID () == WindowEvent.WINDOW_STATE_CHANGED)
869 windowStateListener.windowStateChanged (event);
873 * Returns whether this <code>Window</code> can get the focus or not.
877 public final boolean isFocusableWindow ()
879 if (getFocusableWindowState () == false)
882 if (this instanceof Dialog
883 || this instanceof Frame)
886 // FIXME: Implement more possible cases for returning true.
892 * Returns the value of the focusableWindowState property.
896 public boolean getFocusableWindowState ()
898 return focusableWindowState;
902 * Sets the value of the focusableWindowState property.
906 public void setFocusableWindowState (boolean focusableWindowState)
908 this.focusableWindowState = focusableWindowState;
911 // setBoundsCallback is needed so that when a user moves a window,
912 // the Window's location can be updated without calling the peer's
913 // setBounds method. When a user moves a window the peer window's
914 // location is updated automatically and the windowing system sends
915 // a message back to the application informing it of its updated
916 // dimensions. We must update the AWT Window class with these new
917 // dimensions. But we don't want to call the peer's setBounds
918 // method, because the peer's dimensions have already been updated.
919 // (Under X, having this method prevents Configure event loops when
920 // moving windows: Component.setBounds -> peer.setBounds ->
921 // postConfigureEvent -> Component.setBounds -> ... In some cases
922 // Configure event loops cause windows to jitter back and forth
924 void setBoundsCallback (int x, int y, int w, int h)
926 if (this.x == x && this.y == y && width == w && height == h)
929 boolean resized = width != w || height != h;
930 boolean moved = this.x != x || this.y != y;
935 if (resized && isShowing ())
938 new ComponentEvent(this, ComponentEvent.COMPONENT_RESIZED);
939 getToolkit().getSystemEventQueue().postEvent(ce);
941 if (moved && isShowing ())
944 new ComponentEvent(this, ComponentEvent.COMPONENT_MOVED);
945 getToolkit().getSystemEventQueue().postEvent(ce);