2 Copyright (C) 1999, 2000, 2002, 2003 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
.WindowEvent
;
43 import java
.awt
.event
.WindowFocusListener
;
44 import java
.awt
.event
.WindowListener
;
45 import java
.awt
.event
.WindowStateListener
;
46 import java
.awt
.peer
.WindowPeer
;
47 import java
.lang
.ref
.Reference
;
48 import java
.lang
.ref
.WeakReference
;
49 import java
.util
.Iterator
;
50 import java
.util
.EventListener
;
51 import java
.util
.Locale
;
52 import java
.util
.ResourceBundle
;
53 import java
.util
.Vector
;
54 import javax
.accessibility
.Accessible
;
55 import javax
.accessibility
.AccessibleContext
;
58 * This class represents a top-level window with no decorations.
60 * @author Aaron M. Renn <arenn@urbanophile.com>
61 * @author Warren Levy <warrenl@cygnus.com>
63 public class Window
extends Container
implements Accessible
65 private static final long serialVersionUID
= 4497834738069338734L;
67 // Serialized fields, from Sun's serialization spec.
68 private String warningString
= null;
69 private int windowSerializedDataVersion
= 0; // FIXME
71 // private FocusManager focusMgr; // FIXME: what is this?
73 private int state
= 0;
75 private boolean focusableWindowState
= true;
77 // A list of other top-level windows owned by this window.
78 private transient Vector ownedWindows
= new Vector();
80 private transient WindowListener windowListener
;
81 private transient WindowFocusListener windowFocusListener
;
82 private transient WindowStateListener windowStateListener
;
83 private transient GraphicsConfiguration graphicsConfiguration
;
84 private transient AccessibleContext accessibleContext
;
86 private transient boolean shown
;
89 * This (package access) constructor is used by subclasses that want
90 * to build windows that do not have parents. Eg. toplevel
91 * application frames. Subclasses cannot call super(null), since
92 * null is an illegal argument.
97 // Windows are the only Containers that default to being focus
99 focusCycleRoot
= true;
100 setLayout(new BorderLayout());
103 Window(GraphicsConfiguration gc
)
106 graphicsConfiguration
= gc
;
110 * Initializes a new instance of <code>Window</code> with the specified
111 * parent. The window will initially be invisible.
113 * @param parent The owning <code>Frame</code> of this window.
115 * @exception IllegalArgumentException If the owner's GraphicsConfiguration
116 * is not from a screen device, or if owner is null; this exception is always
117 * thrown when GraphicsEnvironment.isHeadless returns true.
119 public Window(Frame owner
)
121 this (owner
, owner
.getGraphicsConfiguration ());
125 * Initializes a new instance of <code>Window</code> with the specified
126 * parent. The window will initially be invisible.
128 * @exception IllegalArgumentException If the owner's GraphicsConfiguration
129 * is not from a screen device, or if owner is null; this exception is always
130 * thrown when GraphicsEnvironment.isHeadless returns true.
134 public Window(Window owner
)
136 this (owner
, owner
.getGraphicsConfiguration ());
140 * Initializes a new instance of <code>Window</code> with the specified
141 * parent. The window will initially be invisible.
143 * @exception IllegalArgumentException If owner is null or if gc is not from a
144 * screen device; this exception is always thrown when
145 * GraphicsEnvironment.isHeadless returns true.
149 public Window(Window owner
, GraphicsConfiguration gc
)
153 synchronized (getTreeLock())
156 throw new IllegalArgumentException ("owner must not be null");
159 owner
.ownedWindows
.add(new WeakReference(this));
162 // FIXME: make this text visible in the window.
163 SecurityManager s
= System
.getSecurityManager();
164 if (s
!= null && ! s
.checkTopLevelWindow(this))
165 warningString
= System
.getProperty("awt.appletWarning");
168 && gc
.getDevice().getType() != GraphicsDevice
.TYPE_RASTER_SCREEN
)
169 throw new IllegalArgumentException ("gc must be from a screen device");
171 // FIXME: until we implement this, it just causes AWT to crash.
173 // graphicsConfiguration = GraphicsEnvironment.getLocalGraphicsEnvironment()
174 // .getDefaultScreenDevice()
175 // .getDefaultConfiguration();
177 graphicsConfiguration
= gc
;
180 GraphicsConfiguration
getGraphicsConfigurationImpl()
182 if (graphicsConfiguration
!= null)
183 return graphicsConfiguration
;
185 return super.getGraphicsConfigurationImpl();
189 * Creates the native peer for this window.
191 public void addNotify()
194 peer
= getToolkit().createWindow(this);
199 * Relays out this window's child components at their preferred size.
201 * @specnote pack() doesn't appear to be called internally by show(), so
202 * we duplicate some of the functionality.
206 if (parent
!= null && !parent
.isDisplayable())
211 setSize(getPreferredSize());
217 * Shows on-screen this window and any of its owned windows for whom
218 * isVisible returns true.
222 if (parent
!= null && !parent
.isDisplayable())
227 // Show visible owned windows.
228 synchronized (getTreeLock())
230 Iterator e
= ownedWindows
.iterator();
233 Window w
= (Window
)(((Reference
) e
.next()).get());
237 w
.getPeer().setVisible(true);
240 // Remove null weak reference from ownedWindows.
241 // Unfortunately this can't be done in the Window's
242 // finalize method because there is no way to guarantee
243 // synchronous access to ownedWindows there.
251 KeyboardFocusManager manager
= KeyboardFocusManager
.getCurrentKeyboardFocusManager ();
252 manager
.setGlobalFocusedWindow (this);
256 FocusTraversalPolicy policy
= getFocusTraversalPolicy ();
257 Component initialFocusOwner
= null;
260 initialFocusOwner
= policy
.getInitialComponent (this);
262 if (initialFocusOwner
!= null)
263 initialFocusOwner
.requestFocusInWindow (false);
271 // Hide visible owned windows.
272 synchronized (getTreeLock ())
274 Iterator e
= ownedWindows
.iterator();
277 Window w
= (Window
)(((Reference
) e
.next()).get());
280 if (w
.isVisible() && w
.getPeer() != null)
281 w
.getPeer().setVisible(false);
290 public boolean isDisplayable()
292 if (super.isDisplayable())
298 * Destroys any resources associated with this window. This includes
299 * all components in the window and all owned top-level windows.
301 public void dispose()
305 synchronized (getTreeLock ())
307 Iterator e
= ownedWindows
.iterator();
310 Window w
= (Window
)(((Reference
) e
.next()).get());
314 // Remove null weak reference from ownedWindows.
318 for (int i
= 0; i
< ncomponents
; ++i
)
319 component
[i
].removeNotify();
322 // Post a WINDOW_CLOSED event.
323 WindowEvent we
= new WindowEvent(this, WindowEvent
.WINDOW_CLOSED
);
324 getToolkit().getSystemEventQueue().postEvent(we
);
329 * Sends this window to the back so that all other windows display in
336 WindowPeer wp
= (WindowPeer
) peer
;
342 * Brings this window to the front so that it displays in front of
345 public void toFront()
349 WindowPeer wp
= (WindowPeer
) peer
;
355 * Returns the toolkit used to create this window.
357 * @return The toolkit used to create this window.
359 * @specnote Unlike Component.getToolkit, this implementation always
360 * returns the value of Toolkit.getDefaultToolkit().
362 public Toolkit
getToolkit()
364 return Toolkit
.getDefaultToolkit();
368 * Returns the warning string that will be displayed if this window is
369 * popped up by an unsecure applet or application.
371 * @return The unsecure window warning message.
373 public final String
getWarningString()
375 return warningString
;
379 * Returns the locale that this window is configured for.
381 * @return The locale this window is configured for.
383 public Locale
getLocale()
385 return locale
== null ? Locale
.getDefault() : locale
;
390 public InputContext getInputContext()
397 * Sets the cursor for this window to the specifiec cursor.
399 * @param cursor The new cursor for this window.
401 public void setCursor(Cursor cursor
)
403 super.setCursor(cursor
);
406 public Window
getOwner()
408 return (Window
) parent
;
412 public Window
[] getOwnedWindows()
414 Window
[] trimmedList
;
415 synchronized (getTreeLock ())
417 // Windows with non-null weak references in ownedWindows.
418 Window
[] validList
= new Window
[ownedWindows
.size()];
420 Iterator e
= ownedWindows
.iterator();
424 Window w
= (Window
)(((Reference
) e
.next()).get());
426 validList
[numValid
++] = w
;
428 // Remove null weak reference from ownedWindows.
432 if (numValid
!= validList
.length
)
434 trimmedList
= new Window
[numValid
];
435 System
.arraycopy (validList
, 0, trimmedList
, 0, numValid
);
438 trimmedList
= validList
;
444 * Adds the specified listener to the list of <code>WindowListeners</code>
445 * that will receive events for this window.
447 * @param listener The <code>WindowListener</code> to add.
449 public synchronized void addWindowListener(WindowListener listener
)
451 windowListener
= AWTEventMulticaster
.add(windowListener
, listener
);
455 * Removes the specified listener from the list of
456 * <code>WindowListeners</code> that will receive events for this window.
458 * @param listener The <code>WindowListener</code> to remove.
460 public synchronized void removeWindowListener(WindowListener listener
)
462 windowListener
= AWTEventMulticaster
.remove(windowListener
, listener
);
466 * Returns an array of all the window listeners registered on this window.
470 public synchronized WindowListener
[] getWindowListeners()
472 return (WindowListener
[])
473 AWTEventMulticaster
.getListeners(windowListener
,
474 WindowListener
.class);
478 * Returns an array of all the window focus listeners registered on this
483 public synchronized WindowFocusListener
[] getWindowFocusListeners()
485 return (WindowFocusListener
[])
486 AWTEventMulticaster
.getListeners(windowFocusListener
,
487 WindowFocusListener
.class);
491 * Returns an array of all the window state listeners registered on this
496 public synchronized WindowStateListener
[] getWindowStateListeners()
498 return (WindowStateListener
[])
499 AWTEventMulticaster
.getListeners(windowStateListener
,
500 WindowStateListener
.class);
504 * Adds the specified listener to this window.
506 public void addWindowFocusListener (WindowFocusListener wfl
)
508 windowFocusListener
= AWTEventMulticaster
.add (windowFocusListener
, wfl
);
512 * Adds the specified listener to this window.
516 public void addWindowStateListener (WindowStateListener wsl
)
518 windowStateListener
= AWTEventMulticaster
.add (windowStateListener
, wsl
);
522 * Removes the specified listener from this window.
524 public void removeWindowFocusListener (WindowFocusListener wfl
)
526 windowFocusListener
= AWTEventMulticaster
.remove (windowFocusListener
, wfl
);
530 * Removes the specified listener from this window.
534 public void removeWindowStateListener (WindowStateListener wsl
)
536 windowStateListener
= AWTEventMulticaster
.remove (windowStateListener
, wsl
);
540 * Returns an array of all the objects currently registered as FooListeners
541 * upon this Window. FooListeners are registered using the addFooListener
544 * @exception ClassCastException If listenerType doesn't specify a class or
545 * interface that implements java.util.EventListener.
549 public EventListener
[] getListeners(Class listenerType
)
551 if (listenerType
== WindowListener
.class)
552 return getWindowListeners();
553 return super.getListeners(listenerType
);
556 void dispatchEventImpl(AWTEvent e
)
558 // Make use of event id's in order to avoid multiple instanceof tests.
559 if (e
.id
<= WindowEvent
.WINDOW_LAST
560 && e
.id
>= WindowEvent
.WINDOW_FIRST
561 && (windowListener
!= null
562 || windowFocusListener
!= null
563 || windowStateListener
!= null
564 || (eventMask
& AWTEvent
.WINDOW_EVENT_MASK
) != 0))
567 super.dispatchEventImpl(e
);
571 * Processes the specified event for this window. If the event is an
572 * instance of <code>WindowEvent</code>, then
573 * <code>processWindowEvent()</code> is called to process the event,
574 * otherwise the superclass version of this method is invoked.
576 * @param event The event to process.
578 protected void processEvent(AWTEvent evt
)
580 if (evt
instanceof WindowEvent
)
581 processWindowEvent((WindowEvent
) evt
);
583 super.processEvent(evt
);
587 * Dispatches this event to any listeners that are listening for
588 * <code>WindowEvents</code> on this window. This method only gets
589 * invoked if it is enabled via <code>enableEvents()</code> or if
590 * a listener has been added.
592 * @param event The event to process.
594 protected void processWindowEvent(WindowEvent evt
)
596 int id
= evt
.getID();
598 if (id
== WindowEvent
.WINDOW_GAINED_FOCUS
599 || id
== WindowEvent
.WINDOW_LOST_FOCUS
)
600 processWindowFocusEvent (evt
);
601 else if (id
== WindowEvent
.WINDOW_STATE_CHANGED
)
602 processWindowStateEvent (evt
);
605 if (windowListener
!= null)
609 case WindowEvent
.WINDOW_ACTIVATED
:
610 windowListener
.windowActivated(evt
);
613 case WindowEvent
.WINDOW_CLOSED
:
614 windowListener
.windowClosed(evt
);
617 case WindowEvent
.WINDOW_CLOSING
:
618 windowListener
.windowClosing(evt
);
621 case WindowEvent
.WINDOW_DEACTIVATED
:
622 windowListener
.windowDeactivated(evt
);
625 case WindowEvent
.WINDOW_DEICONIFIED
:
626 windowListener
.windowDeiconified(evt
);
629 case WindowEvent
.WINDOW_ICONIFIED
:
630 windowListener
.windowIconified(evt
);
633 case WindowEvent
.WINDOW_OPENED
:
634 windowListener
.windowOpened(evt
);
645 * Returns the child window that has focus if this window is active.
646 * This method returns <code>null</code> if this window is not active
647 * or no children have focus.
649 * @return The component that has focus, or <code>null</code> if no
650 * component has focus.
652 public Component
getFocusOwner ()
654 KeyboardFocusManager manager
= KeyboardFocusManager
.getCurrentKeyboardFocusManager ();
656 Window activeWindow
= manager
.getActiveWindow ();
658 // The currently-focused Component belongs to the active Window.
659 if (activeWindow
== this)
660 return manager
.getFocusOwner ();
666 * Post a Java 1.0 event to the event queue.
668 * @param event The event to post.
672 public boolean postEvent(Event e
)
679 * Tests whether or not this window is visible on the screen.
681 * @return <code>true</code> if this window is visible, <code>false</code>
684 public boolean isShowing()
686 return super.isShowing();
694 public void applyResourceBundle(ResourceBundle rb
)
696 throw new Error ("Not implemented");
704 public void applyResourceBundle(String rbName
)
706 ResourceBundle rb
= ResourceBundle
.getBundle(rbName
);
708 applyResourceBundle(rb
);
711 public AccessibleContext
getAccessibleContext()
715 throw new Error ("Not implemented");
719 * Get graphics configuration. The implementation for Window will
720 * not ask any parent containers, since Window is a toplevel
721 * window and not actually embedded in the parent component.
723 public GraphicsConfiguration
getGraphicsConfiguration()
725 if (graphicsConfiguration
!= null) return graphicsConfiguration
;
726 if (peer
!= null) return peer
.getGraphicsConfiguration();
730 protected void processWindowFocusEvent(WindowEvent event
)
732 if (windowFocusListener
!= null)
734 switch (event
.getID ())
736 case WindowEvent
.WINDOW_GAINED_FOCUS
:
737 windowFocusListener
.windowGainedFocus (event
);
740 case WindowEvent
.WINDOW_LOST_FOCUS
:
741 windowFocusListener
.windowLostFocus (event
);
753 protected void processWindowStateEvent(WindowEvent event
)
755 if (windowStateListener
!= null
756 && event
.getID () == WindowEvent
.WINDOW_STATE_CHANGED
)
757 windowStateListener
.windowStateChanged (event
);
761 * Returns whether this <code>Window</code> can get the focus or not.
765 public final boolean isFocusableWindow ()
767 if (getFocusableWindowState () == false)
770 if (this instanceof Dialog
771 || this instanceof Frame
)
774 // FIXME: Implement more possible cases for returning true.
780 * Returns the value of the focusableWindowState property.
784 public boolean getFocusableWindowState ()
786 return focusableWindowState
;
790 * Sets the value of the focusableWindowState property.
794 public void setFocusableWindowState (boolean focusableWindowState
)
796 this.focusableWindowState
= focusableWindowState
;
799 // setBoundsCallback is needed so that when a user moves a window,
800 // the Window's location can be updated without calling the peer's
801 // setBounds method. When a user moves a window the peer window's
802 // location is updated automatically and the windowing system sends
803 // a message back to the application informing it of its updated
804 // dimensions. We must update the AWT Window class with these new
805 // dimensions. But we don't want to call the peer's setBounds
806 // method, because the peer's dimensions have already been updated.
807 // (Under X, having this method prevents Configure event loops when
808 // moving windows: Component.setBounds -> peer.setBounds ->
809 // postConfigureEvent -> Component.setBounds -> ... In some cases
810 // Configure event loops cause windows to jitter back and forth
812 void setBoundsCallback (int x
, int y
, int w
, int h
)
814 if (this.x
== x
&& this.y
== y
&& width
== w
&& height
== h
)
817 boolean resized
= width
!= w
|| height
!= h
;
818 boolean moved
= this.x
!= x
|| this.y
!= y
;
826 new ComponentEvent(this, ComponentEvent
.COMPONENT_RESIZED
);
827 getToolkit().getSystemEventQueue().postEvent(ce
);
832 new ComponentEvent(this, ComponentEvent
.COMPONENT_MOVED
);
833 getToolkit().getSystemEventQueue().postEvent(ce
);