OSDN Git Service

2005-05-06 Thomas Fitzsimmons <fitzsim@redhat.com>
[pf3gnuchains/gcc-fork.git] / libjava / java / awt / Window.java
1 /* Window.java --
2    Copyright (C) 1999, 2000, 2002, 2003, 2004  Free Software Foundation
3
4 This file is part of GNU Classpath.
5
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)
9 any later version.
10
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.
15
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
19 02111-1307 USA.
20
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
24 combination.
25
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. */
37
38
39 package java.awt;
40
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.image.BufferStrategy;
49 import java.awt.peer.WindowPeer;
50 import java.lang.ref.Reference;
51 import java.lang.ref.WeakReference;
52 import java.util.EventListener;
53 import java.util.Iterator;
54 import java.util.Locale;
55 import java.util.ResourceBundle;
56 import java.util.Vector;
57
58 import javax.accessibility.Accessible;
59 import javax.accessibility.AccessibleContext;
60 import javax.accessibility.AccessibleRole;
61 import javax.accessibility.AccessibleState;
62 import javax.accessibility.AccessibleStateSet;
63
64 /**
65  * This class represents a top-level window with no decorations.
66  *
67  * @author Aaron M. Renn (arenn@urbanophile.com)
68  * @author Warren Levy  (warrenl@cygnus.com)
69  */
70 public class Window extends Container implements Accessible
71 {
72   private static final long serialVersionUID = 4497834738069338734L;
73
74   // Serialized fields, from Sun's serialization spec.
75   private String warningString = null;
76   private int windowSerializedDataVersion = 0; // FIXME
77   /** @since 1.2 */
78   // private FocusManager focusMgr;  // FIXME: what is this?  
79   /** @since 1.2 */
80   private int state = 0;
81   /** @since 1.4 */
82   private boolean focusableWindowState = true;
83
84   // A list of other top-level windows owned by this window.
85   private transient Vector ownedWindows = new Vector();
86
87   private transient WindowListener windowListener;
88   private transient WindowFocusListener windowFocusListener;
89   private transient WindowStateListener windowStateListener;
90   private transient GraphicsConfiguration graphicsConfiguration;
91
92   private transient boolean shown;
93
94   // This is package-private to avoid an accessor method.
95   transient Component windowFocusOwner;
96   
97   /*
98    * The number used to generate the name returned by getName.
99    */
100   private static transient long next_window_number;
101
102   protected class AccessibleAWTWindow extends AccessibleAWTContainer
103   {
104     public AccessibleRole getAccessibleRole()
105     {
106       return AccessibleRole.WINDOW;
107     }
108     
109     public AccessibleStateSet getAccessibleStateSet()
110     {
111       AccessibleStateSet states = super.getAccessibleStateSet();
112       if (isActive())
113         states.add(AccessibleState.ACTIVE);
114       return states;
115     }
116   }
117
118   /** 
119    * This (package access) constructor is used by subclasses that want
120    * to build windows that do not have parents.  Eg. toplevel
121    * application frames.  Subclasses cannot call super(null), since
122    * null is an illegal argument.
123    */
124   Window()
125   {
126     visible = false;
127     // Windows are the only Containers that default to being focus
128     // cycle roots.
129     focusCycleRoot = true;
130     setLayout(new BorderLayout());
131
132     addWindowFocusListener (new WindowAdapter ()
133       {
134         public void windowGainedFocus (WindowEvent event)
135         {
136           if (windowFocusOwner != null)
137             {
138               // FIXME: move this section and the other similar
139               // sections in Component into a separate method.
140               EventQueue eq = Toolkit.getDefaultToolkit ().getSystemEventQueue ();
141               synchronized (eq)
142                 {
143                   KeyboardFocusManager manager = KeyboardFocusManager.getCurrentKeyboardFocusManager ();
144                   Component currentFocusOwner = manager.getGlobalPermanentFocusOwner ();
145                   if (currentFocusOwner != null)
146                     {
147                       eq.postEvent (new FocusEvent (currentFocusOwner, FocusEvent.FOCUS_LOST,
148                                                     false, windowFocusOwner));
149                       eq.postEvent (new FocusEvent (windowFocusOwner, FocusEvent.FOCUS_GAINED,
150                                                     false, currentFocusOwner));
151                     }
152                   else
153                     eq.postEvent (new FocusEvent (windowFocusOwner, FocusEvent.FOCUS_GAINED, false));
154                 }
155             }
156         }
157       });
158   }
159
160   Window(GraphicsConfiguration gc)
161   {
162     this();
163     graphicsConfiguration = gc;
164   }
165
166   /**
167    * Initializes a new instance of <code>Window</code> with the specified
168    * parent.  The window will initially be invisible.
169    *
170    * @param owner The owning <code>Frame</code> of this window.
171    *
172    * @exception IllegalArgumentException If the owner's GraphicsConfiguration
173    * is not from a screen device, or if owner is null; this exception is always
174    * thrown when GraphicsEnvironment.isHeadless returns true.
175    */
176   public Window(Frame owner)
177   {
178     this (owner, owner.getGraphicsConfiguration ());
179   }
180
181   /**
182    * Initializes a new instance of <code>Window</code> with the specified
183    * parent.  The window will initially be invisible.   
184    *
185    * @exception IllegalArgumentException If the owner's GraphicsConfiguration
186    * is not from a screen device, or if owner is null; this exception is always
187    * thrown when GraphicsEnvironment.isHeadless returns true.
188    *
189    * @since 1.2
190    */
191   public Window(Window owner)
192   {
193     this (owner, owner.getGraphicsConfiguration ());
194   }
195   
196   /**
197    * Initializes a new instance of <code>Window</code> with the specified
198    * parent.  The window will initially be invisible.   
199    *
200    * @exception IllegalArgumentException If owner is null or if gc is not from a
201    * screen device; this exception is always thrown when
202    * GraphicsEnvironment.isHeadless returns true.
203    *
204    * @since 1.3
205    */
206   public Window(Window owner, GraphicsConfiguration gc)
207   {
208     this ();
209
210     synchronized (getTreeLock())
211       {
212         if (owner == null)
213           throw new IllegalArgumentException ("owner must not be null");
214
215         parent = owner;
216         owner.ownedWindows.add(new WeakReference(this));
217       }
218
219     // FIXME: make this text visible in the window.
220     SecurityManager s = System.getSecurityManager();
221     if (s != null && ! s.checkTopLevelWindow(this))
222       warningString = System.getProperty("awt.appletWarning");
223
224     if (gc != null
225         && gc.getDevice().getType() != GraphicsDevice.TYPE_RASTER_SCREEN)
226       throw new IllegalArgumentException ("gc must be from a screen device");
227
228     if (gc == null)
229       graphicsConfiguration = GraphicsEnvironment.getLocalGraphicsEnvironment()
230                                                  .getDefaultScreenDevice()
231                                                  .getDefaultConfiguration();
232     else
233       graphicsConfiguration = gc;
234   }
235
236   GraphicsConfiguration getGraphicsConfigurationImpl()
237   {
238     if (graphicsConfiguration != null)
239         return graphicsConfiguration;
240
241     return super.getGraphicsConfigurationImpl();
242   }
243
244   /**
245    * Creates the native peer for this window.
246    */
247   public void addNotify()
248   {
249     if (peer == null)
250       peer = getToolkit().createWindow(this);
251     super.addNotify();
252   }
253
254   /**
255    * Relays out this window's child components at their preferred size.
256    *
257    * @specnote pack() doesn't appear to be called internally by show(), so
258    *             we duplicate some of the functionality.
259    */
260   public void pack()
261   {
262     if (parent != null && !parent.isDisplayable())
263       parent.addNotify();
264     if (peer == null)
265       addNotify();
266
267     setSize(getPreferredSize());
268
269     validate();
270   }
271
272   /**
273    * Shows on-screen this window and any of its owned windows for whom
274    * isVisible returns true.
275    */
276   public void show()
277   {
278     if (parent != null && !parent.isDisplayable())
279       parent.addNotify();
280     if (peer == null)
281       addNotify();
282
283     // Show visible owned windows.
284     synchronized (getTreeLock())
285       {
286         Iterator e = ownedWindows.iterator();
287         while(e.hasNext())
288           {
289             Window w = (Window)(((Reference) e.next()).get());
290             if (w != null)
291               {
292                 if (w.isVisible())
293                   w.getPeer().setVisible(true);
294               }
295             else
296               // Remove null weak reference from ownedWindows.
297               // Unfortunately this can't be done in the Window's
298               // finalize method because there is no way to guarantee
299               // synchronous access to ownedWindows there.
300               e.remove();
301           }
302       }
303     validate();
304     super.show();
305     toFront();
306
307     KeyboardFocusManager manager = KeyboardFocusManager.getCurrentKeyboardFocusManager ();
308     manager.setGlobalFocusedWindow (this);
309
310     if (!shown)
311       {
312         FocusTraversalPolicy policy = getFocusTraversalPolicy ();
313         Component initialFocusOwner = null;
314
315         if (policy != null)
316           initialFocusOwner = policy.getInitialComponent (this);
317
318         if (initialFocusOwner != null)
319           initialFocusOwner.requestFocusInWindow ();
320
321         shown = true;
322       }
323   }
324
325   public void hide()
326   {
327     // Hide visible owned windows.
328     synchronized (getTreeLock ())
329       {
330         Iterator e = ownedWindows.iterator();
331         while(e.hasNext())
332           {
333             Window w = (Window)(((Reference) e.next()).get());
334             if (w != null)
335               {
336                 if (w.isVisible() && w.getPeer() != null)
337                   w.getPeer().setVisible(false);
338               }
339             else
340               e.remove();
341           }
342       }
343     super.hide();
344   }
345
346   public boolean isDisplayable()
347   {
348     if (super.isDisplayable())
349       return true;
350     return peer != null;
351   }
352
353   /**
354    * Destroys any resources associated with this window.  This includes
355    * all components in the window and all owned top-level windows.
356    */
357   public void dispose()
358   {
359     hide();
360
361     synchronized (getTreeLock ())
362       {
363         Iterator e = ownedWindows.iterator();
364         while(e.hasNext())
365           {
366             Window w = (Window)(((Reference) e.next()).get());
367             if (w != null)
368               w.dispose();
369             else
370               // Remove null weak reference from ownedWindows.
371               e.remove();
372           }
373
374         for (int i = 0; i < ncomponents; ++i)
375           component[i].removeNotify();
376         this.removeNotify();
377
378         // Post a WINDOW_CLOSED event.
379         WindowEvent we = new WindowEvent(this, WindowEvent.WINDOW_CLOSED);
380         getToolkit().getSystemEventQueue().postEvent(we);
381       }
382   }
383
384   /**
385    * Sends this window to the back so that all other windows display in
386    * front of it.
387    */
388   public void toBack()
389   {
390     if (peer != null)
391       {
392         WindowPeer wp = (WindowPeer) peer;
393         wp.toBack();
394       }
395   }
396
397   /**
398    * Brings this window to the front so that it displays in front of
399    * any other windows.
400    */
401   public void toFront()
402   {
403     if (peer != null)
404       {
405         WindowPeer wp = (WindowPeer) peer;
406         wp.toFront();
407       }
408   }
409
410   /**
411    * Returns the toolkit used to create this window.
412    *
413    * @return The toolkit used to create this window.
414    *
415    * @specnote Unlike Component.getToolkit, this implementation always 
416    *           returns the value of Toolkit.getDefaultToolkit().
417    */
418   public Toolkit getToolkit()
419   {
420     return Toolkit.getDefaultToolkit();    
421   }
422
423   /**
424    * Returns the warning string that will be displayed if this window is
425    * popped up by an unsecure applet or application.
426    *
427    * @return The unsecure window warning message.
428    */
429   public final String getWarningString()
430   {
431     return warningString;
432   }
433
434   /**
435    * Returns the locale that this window is configured for.
436    *
437    * @return The locale this window is configured for.
438    */
439   public Locale getLocale()
440   {
441     return locale == null ? Locale.getDefault() : locale;
442   }
443
444   /*
445   /** @since 1.2
446   public InputContext getInputContext()
447   {
448     // FIXME
449   }
450   */
451
452   /**
453    * Sets the cursor for this window to the specifiec cursor.
454    *
455    * @param cursor The new cursor for this window.
456    */
457   public void setCursor(Cursor cursor)
458   {
459     super.setCursor(cursor);
460   }
461
462   public Window getOwner()
463   {
464     return (Window) parent;
465   }
466
467   /** @since 1.2 */
468   public Window[] getOwnedWindows()
469   {
470     Window [] trimmedList;
471     synchronized (getTreeLock ())
472       {
473         // Windows with non-null weak references in ownedWindows.
474         Window [] validList = new Window [ownedWindows.size()];
475
476         Iterator e = ownedWindows.iterator();
477         int numValid = 0;
478         while (e.hasNext())
479           {
480             Window w = (Window)(((Reference) e.next()).get());
481             if (w != null)
482               validList[numValid++] = w;
483             else
484               // Remove null weak reference from ownedWindows.
485               e.remove();
486           }
487
488         if (numValid != validList.length)
489           {
490             trimmedList = new Window [numValid];
491             System.arraycopy (validList, 0, trimmedList, 0, numValid);
492           }
493         else
494           trimmedList = validList;
495       }
496     return trimmedList;
497   }
498
499   /**
500    * Adds the specified listener to the list of <code>WindowListeners</code>
501    * that will receive events for this window.
502    *
503    * @param listener The <code>WindowListener</code> to add.
504    */
505   public synchronized void addWindowListener(WindowListener listener)
506   {
507     windowListener = AWTEventMulticaster.add(windowListener, listener);
508   }
509
510   /**
511    * Removes the specified listener from the list of
512    * <code>WindowListeners</code> that will receive events for this window.
513    *
514    * @param listener The <code>WindowListener</code> to remove.
515    */
516   public synchronized void removeWindowListener(WindowListener listener)
517   {
518     windowListener = AWTEventMulticaster.remove(windowListener, listener);
519   }
520
521   /**
522    * Returns an array of all the window listeners registered on this window.
523    *
524    * @since 1.4
525    */
526   public synchronized WindowListener[] getWindowListeners()
527   {
528     return (WindowListener[])
529       AWTEventMulticaster.getListeners(windowListener,
530                                        WindowListener.class);
531   }
532
533   /**
534    * Returns an array of all the window focus listeners registered on this
535    * window.
536    *
537    * @since 1.4
538    */
539   public synchronized WindowFocusListener[] getWindowFocusListeners()
540   {
541     return (WindowFocusListener[])
542       AWTEventMulticaster.getListeners(windowFocusListener,
543                                        WindowFocusListener.class);
544   }
545   
546   /**
547    * Returns an array of all the window state listeners registered on this
548    * window.
549    *
550    * @since 1.4
551    */
552   public synchronized WindowStateListener[] getWindowStateListeners()
553   {
554     return (WindowStateListener[])
555       AWTEventMulticaster.getListeners(windowStateListener,
556                                        WindowStateListener.class);
557   }
558
559   /**
560    * Adds the specified listener to this window.
561    */
562   public void addWindowFocusListener (WindowFocusListener wfl)
563   {
564     windowFocusListener = AWTEventMulticaster.add (windowFocusListener, wfl);
565   }
566   
567   /**
568    * Adds the specified listener to this window.
569    *
570    * @since 1.4
571    */
572   public void addWindowStateListener (WindowStateListener wsl)
573   {
574     windowStateListener = AWTEventMulticaster.add (windowStateListener, wsl);  
575   }
576   
577   /**
578    * Removes the specified listener from this window.
579    */
580   public void removeWindowFocusListener (WindowFocusListener wfl)
581   {
582     windowFocusListener = AWTEventMulticaster.remove (windowFocusListener, wfl);
583   }
584   
585   /**
586    * Removes the specified listener from this window.
587    *
588    * @since 1.4
589    */
590   public void removeWindowStateListener (WindowStateListener wsl)
591   {
592     windowStateListener = AWTEventMulticaster.remove (windowStateListener, wsl);
593   }
594
595   /**
596    * Returns an array of all the objects currently registered as FooListeners
597    * upon this Window. FooListeners are registered using the addFooListener
598    * method.
599    *
600    * @exception ClassCastException If listenerType doesn't specify a class or
601    * interface that implements java.util.EventListener.
602    *
603    * @since 1.3
604    */
605   public EventListener[] getListeners(Class listenerType)
606   {
607     if (listenerType == WindowListener.class)
608       return getWindowListeners();
609     return super.getListeners(listenerType);
610   }
611
612   void dispatchEventImpl(AWTEvent e)
613   {
614     // Make use of event id's in order to avoid multiple instanceof tests.
615     if (e.id <= WindowEvent.WINDOW_LAST 
616         && e.id >= WindowEvent.WINDOW_FIRST
617         && (windowListener != null
618             || windowFocusListener != null
619             || windowStateListener != null
620             || (eventMask & AWTEvent.WINDOW_EVENT_MASK) != 0))
621       processEvent(e);
622     else
623       super.dispatchEventImpl(e);
624   }
625
626   /**
627    * Processes the specified event for this window.  If the event is an
628    * instance of <code>WindowEvent</code>, then
629    * <code>processWindowEvent()</code> is called to process the event,
630    * otherwise the superclass version of this method is invoked.
631    *
632    * @param evt The event to process.
633    */
634   protected void processEvent(AWTEvent evt)
635   {
636     if (evt instanceof WindowEvent)
637       processWindowEvent((WindowEvent) evt);
638     else
639       super.processEvent(evt);
640   }
641
642   /**
643    * Dispatches this event to any listeners that are listening for
644    * <code>WindowEvents</code> on this window.  This method only gets
645    * invoked if it is enabled via <code>enableEvents()</code> or if
646    * a listener has been added.
647    *
648    * @param evt The event to process.
649    */
650   protected void processWindowEvent(WindowEvent evt)
651   {
652     int id = evt.getID();
653
654     if (id == WindowEvent.WINDOW_GAINED_FOCUS
655         || id == WindowEvent.WINDOW_LOST_FOCUS)
656       processWindowFocusEvent (evt);
657     else if (id == WindowEvent.WINDOW_STATE_CHANGED)
658       processWindowStateEvent (evt);
659     else
660       {
661         if (windowListener != null)
662           {
663             switch (evt.getID())
664               {
665               case WindowEvent.WINDOW_ACTIVATED:
666                 windowListener.windowActivated(evt);
667                 break;
668
669               case WindowEvent.WINDOW_CLOSED:
670                 windowListener.windowClosed(evt);
671                 break;
672
673               case WindowEvent.WINDOW_CLOSING:
674                 windowListener.windowClosing(evt);
675                 break;
676
677               case WindowEvent.WINDOW_DEACTIVATED:
678                 windowListener.windowDeactivated(evt);
679                 break;
680
681               case WindowEvent.WINDOW_DEICONIFIED:
682                 windowListener.windowDeiconified(evt);
683                 break;
684
685               case WindowEvent.WINDOW_ICONIFIED:
686                 windowListener.windowIconified(evt);
687                 break;
688
689               case WindowEvent.WINDOW_OPENED:
690                 windowListener.windowOpened(evt);
691                 break;
692
693               default:
694                 break;
695               }
696           }
697       }
698   }
699   
700   /**
701    * Identifies if this window is active.  The active window is a Frame or
702    * Dialog that has focus or owns the active window.
703    *  
704    * @return true if active, else false.
705    * @since 1.4
706    */
707   public boolean isActive()
708   {
709     KeyboardFocusManager manager = KeyboardFocusManager.getCurrentKeyboardFocusManager ();
710     return manager.getActiveWindow() == this;
711   }
712
713   /**
714    * Identifies if this window is focused.  A window is focused if it is the
715    * focus owner or it contains the focus owner.
716    * 
717    * @return true if focused, else false.
718    * @since 1.4
719    */
720   public boolean isFocused()
721   {
722     KeyboardFocusManager manager = KeyboardFocusManager.getCurrentKeyboardFocusManager ();
723     return manager.getFocusedWindow() == this;
724   }
725   
726   /**
727    * Returns the child window that has focus if this window is active.
728    * This method returns <code>null</code> if this window is not active
729    * or no children have focus.
730    *
731    * @return The component that has focus, or <code>null</code> if no
732    * component has focus.
733    */
734   public Component getFocusOwner ()
735   {
736     KeyboardFocusManager manager = KeyboardFocusManager.getCurrentKeyboardFocusManager ();
737
738     Window activeWindow = manager.getActiveWindow ();
739
740     // The currently-focused Component belongs to the active Window.
741     if (activeWindow == this)
742       return manager.getFocusOwner ();
743     else
744       return windowFocusOwner;
745   }
746
747   /**
748    * Set the focus owner for this window.  This method is used to
749    * remember which component was focused when this window lost
750    * top-level focus, so that when it regains top-level focus the same
751    * child component can be refocused.
752    *
753    * @param windowFocusOwner the component in this window that owns
754    * the focus.
755    */
756   void setFocusOwner (Component windowFocusOwner)
757   {
758     this.windowFocusOwner = windowFocusOwner;
759   }
760
761   /**
762    * Post a Java 1.0 event to the event queue.
763    *
764    * @param e The event to post.
765    *
766    * @deprecated
767    */
768   public boolean postEvent(Event e)
769   {
770     return handleEvent (e);
771   }
772
773   /**
774    * Tests whether or not this window is visible on the screen.
775    *
776    * @return <code>true</code> if this window is visible, <code>false</code>
777    * otherwise.
778    */
779   public boolean isShowing()
780   {
781     return super.isShowing();
782   }
783
784   public void setLocationRelativeTo (Component c)
785   {
786     if (c == null || !c.isShowing ())
787       {
788         int x = 0;
789         int y = 0;
790
791         GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment ();
792         Point center = ge.getCenterPoint ();
793         x = center.x - (width / 2);
794         y = center.y - (height / 2);
795         setLocation (x, y);
796       }
797     // FIXME: handle case where component is non-null.
798   }
799
800   /**
801    * A BltBufferStrategy for windows.
802    */
803   private class WindowBltBufferStrategy extends BltBufferStrategy
804   {
805     /**
806      * Creates a block transfer strategy for this window.
807      *
808      * @param numBuffers the number of buffers in this strategy
809      * @param accelerated true if the buffer should be accelerated,
810      * false otherwise
811      */
812     WindowBltBufferStrategy(int numBuffers, boolean accelerated)
813     {
814       super(numBuffers,
815             new BufferCapabilities(new ImageCapabilities(accelerated),
816                                    new ImageCapabilities(accelerated),
817                                    BufferCapabilities.FlipContents.COPIED));
818     }
819   }
820
821   /**
822    * A FlipBufferStrategy for windows.
823    */
824   private class WindowFlipBufferStrategy extends FlipBufferStrategy
825   {
826     /**
827      * Creates a flip buffer strategy for this window.
828      *
829      * @param numBuffers the number of buffers in this strategy
830      *
831      * @throws AWTException if the requested number of buffers is not
832      * supported
833      */
834     WindowFlipBufferStrategy(int numBuffers)
835       throws AWTException
836     {
837       super(numBuffers,
838             new BufferCapabilities(new ImageCapabilities(true),
839                                    new ImageCapabilities(true),
840                                    BufferCapabilities.FlipContents.COPIED));
841     }
842   }
843
844   /**
845    * Creates a buffering strategy that manages how this window is
846    * repainted.  This method attempts to create the optimum strategy
847    * based on the desired number of buffers.  Hardware or software
848    * acceleration may be used.
849    *
850    * createBufferStrategy attempts different levels of optimization,
851    * but guarantees that some strategy with the requested number of
852    * buffers will be created even if it is not optimal.  First it
853    * attempts to create a page flipping strategy, then an accelerated
854    * blitting strategy, then an unaccelerated blitting strategy.
855    *
856    * Calling this method causes any existing buffer strategy to be
857    * destroyed.
858    *
859    * @param numBuffers the number of buffers in this strategy
860    *
861    * @throws IllegalArgumentException if requested number of buffers
862    * is less than one
863    * @throws IllegalStateException if this window is not displayable
864    *
865    * @since 1.4
866    */
867   public void createBufferStrategy(int numBuffers)
868   {
869     if (numBuffers < 1)
870       throw new IllegalArgumentException("Window.createBufferStrategy: number"
871                                          + " of buffers is less than one");
872
873     if (!isDisplayable())
874       throw new IllegalStateException("Window.createBufferStrategy: window is"
875                                       + " not displayable");
876
877     // try a flipping strategy
878     try
879       {
880         bufferStrategy = new WindowFlipBufferStrategy(numBuffers);
881         return;
882       }
883     catch (AWTException e)
884       {
885       }
886
887     // try an accelerated blitting strategy
888     try
889       {
890         bufferStrategy = new WindowBltBufferStrategy(numBuffers, true);
891       }
892     catch (AWTException e)
893       {
894       }
895
896     // fall back to an unaccelerated blitting strategy
897     try
898       {
899         bufferStrategy = new WindowBltBufferStrategy(numBuffers, false);
900       }
901     catch (AWTException e)
902       {
903       }
904   }
905
906   /**
907    * Creates a buffering strategy that manages how this window is
908    * repainted.  This method attempts to create a strategy based on
909    * the specified capabilities and throws an exception if the
910    * requested strategy is not supported.
911    *
912    * Calling this method causes any existing buffer strategy to be
913    * destroyed.
914    *
915    * @param numBuffers the number of buffers in this strategy
916    * @param caps the requested buffering capabilities
917    *
918    * @throws AWTException if the requested capabilities are not
919    * supported
920    * @throws IllegalArgumentException if requested number of buffers
921    * is less than one or if caps is null
922    *
923    * @since 1.4
924    */
925   public void createBufferStrategy(int numBuffers,
926                                    BufferCapabilities caps)
927   {
928     if (numBuffers < 1)
929       throw new IllegalArgumentException("Window.createBufferStrategy: number"
930                                          + " of buffers is less than one");
931
932     if (caps == null)
933       throw new IllegalArgumentException("Window.createBufferStrategy:"
934                                          + " capabilities object is null");
935
936     // a flipping strategy was requested
937     if (caps.isPageFlipping())
938       {
939         try
940           {
941             bufferStrategy = new WindowFlipBufferStrategy(numBuffers);
942           }
943         catch (AWTException e)
944           {
945           }
946       }
947     else
948       bufferStrategy = new WindowBltBufferStrategy(numBuffers, true);
949   }
950
951   /**
952    * Returns the buffer strategy used by the window.
953    *
954    * @return the buffer strategy.
955    * @since 1.4
956    */
957   public BufferStrategy getBufferStrategy()
958   {
959     return bufferStrategy;
960   }
961
962   /**
963    * @since 1.2
964    *
965    * @deprecated
966    */
967   public void applyResourceBundle(ResourceBundle rb)
968   {
969     throw new Error ("Not implemented");
970   }
971
972   /**
973    * @since 1.2
974    *
975    * @deprecated
976    */
977   public void applyResourceBundle(String rbName)
978   {
979     ResourceBundle rb = ResourceBundle.getBundle(rbName, Locale.getDefault(),
980       ClassLoader.getSystemClassLoader());
981     if (rb != null)
982       applyResourceBundle(rb);    
983   }
984
985   /**
986    * Gets the AccessibleContext associated with this <code>Window</code>.
987    * The context is created, if necessary.
988    *
989    * @return the associated context
990    */
991   public AccessibleContext getAccessibleContext()
992   {
993     /* Create the context if this is the first request */
994     if (accessibleContext == null)
995       accessibleContext = new AccessibleAWTWindow();
996     return accessibleContext;
997   }
998
999   /** 
1000    * Get graphics configuration.  The implementation for Window will
1001    * not ask any parent containers, since Window is a toplevel
1002    * window and not actually embedded in the parent component.
1003    */
1004   public GraphicsConfiguration getGraphicsConfiguration()
1005   {
1006     if (graphicsConfiguration != null) return graphicsConfiguration;
1007     if (peer != null) return peer.getGraphicsConfiguration();
1008     return null;
1009   }
1010
1011   protected void processWindowFocusEvent(WindowEvent event)
1012   {
1013     if (windowFocusListener != null)
1014       {
1015         switch (event.getID ())
1016           {
1017           case WindowEvent.WINDOW_GAINED_FOCUS:
1018             windowFocusListener.windowGainedFocus (event);
1019             break;
1020             
1021           case WindowEvent.WINDOW_LOST_FOCUS:
1022             windowFocusListener.windowLostFocus (event);
1023             break;
1024             
1025           default:
1026             break;
1027           }
1028       }
1029   }
1030   
1031   /**
1032    * @since 1.4
1033    */
1034   protected void processWindowStateEvent(WindowEvent event)
1035   {
1036     if (windowStateListener != null
1037         && event.getID () == WindowEvent.WINDOW_STATE_CHANGED)
1038       windowStateListener.windowStateChanged (event);
1039   }
1040
1041   /**
1042    * Returns whether this <code>Window</code> can get the focus or not.
1043    *
1044    * @since 1.4
1045    */
1046   public final boolean isFocusableWindow ()
1047   {
1048     if (getFocusableWindowState () == false)
1049       return false;
1050
1051     if (this instanceof Dialog
1052         || this instanceof Frame)
1053       return true;
1054
1055     // FIXME: Implement more possible cases for returning true.
1056
1057     return false;
1058   }
1059   
1060   /**
1061    * Returns the value of the focusableWindowState property.
1062    * 
1063    * @since 1.4
1064    */
1065   public boolean getFocusableWindowState ()
1066   {
1067     return focusableWindowState;
1068   }
1069
1070   /**
1071    * Sets the value of the focusableWindowState property.
1072    * 
1073    * @since 1.4
1074    */
1075   public void setFocusableWindowState (boolean focusableWindowState)
1076   {
1077     this.focusableWindowState = focusableWindowState;
1078   }
1079
1080   // setBoundsCallback is needed so that when a user moves a window,
1081   // the Window's location can be updated without calling the peer's
1082   // setBounds method.  When a user moves a window the peer window's
1083   // location is updated automatically and the windowing system sends
1084   // a message back to the application informing it of its updated
1085   // dimensions.  We must update the AWT Window class with these new
1086   // dimensions.  But we don't want to call the peer's setBounds
1087   // method, because the peer's dimensions have already been updated.
1088   // (Under X, having this method prevents Configure event loops when
1089   // moving windows: Component.setBounds -> peer.setBounds ->
1090   // postConfigureEvent -> Component.setBounds -> ...  In some cases
1091   // Configure event loops cause windows to jitter back and forth
1092   // continuously).
1093   void setBoundsCallback (int x, int y, int w, int h)
1094   {
1095     if (this.x == x && this.y == y && width == w && height == h)
1096       return;
1097     invalidate();
1098     boolean resized = width != w || height != h;
1099     boolean moved = this.x != x || this.y != y;
1100     this.x = x;
1101     this.y = y;
1102     width = w;
1103     height = h;
1104     if (resized && isShowing ())
1105       {
1106         ComponentEvent ce =
1107           new ComponentEvent(this, ComponentEvent.COMPONENT_RESIZED);
1108         getToolkit().getSystemEventQueue().postEvent(ce);
1109       }
1110     if (moved && isShowing ())
1111       {
1112         ComponentEvent ce =
1113           new ComponentEvent(this, ComponentEvent.COMPONENT_MOVED);
1114         getToolkit().getSystemEventQueue().postEvent(ce);
1115       }
1116   }
1117
1118   /**
1119    * Generate a unique name for this window.
1120    *
1121    * @return A unique name for this window.
1122    */
1123   String generateName()
1124   {
1125     return "win" + getUniqueLong();
1126   }
1127
1128   private static synchronized long getUniqueLong()
1129   {
1130     return next_window_number++;
1131   }
1132 }