I've recently found that it can have a null value in X window managers even
when the focused window is part of the application. I made this class and
test case that have a bug. I've not been able to hack the jdk for finding
the problem but i think it is related to the bug fix for
http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4390189
or where the fix was really made:
http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4453933
this was made in 1.4. Seems like a case was missed. I've not seen the X code
to really see what case is missed but where is the test case:

*import* java.awt.AWTEvent;
*import* java.awt.Cursor;
*import* java.awt.EventQueue;
*import* java.awt.Image;
*import* java.awt.Point;
*import* java.awt.Rectangle;
*import* java.awt.Toolkit;
*import* java.awt.event.AWTEventListener;
*import* java.awt.event.ActionEvent;
*import* java.awt.event.ActionListener;
*import* java.awt.event.WindowEvent;
*import* java.awt.image.MemoryImageSource;
*import* java.io.IOException;
*import* java.io.ObjectInputStream;
*import* java.io.ObjectOutputStream;
*import* java.io.Serializable;
*import* javax.swing.Timer;


/**
* A jframe with full screen functionality that can be serialized
* the only serializable information is the fullscreen state
* (no serialization of jcomponents)
*
*  @author i30817
*/
*public* *class* JFrame *extends* javax.swing.JFrame *implements* Serializable{

   *private* Rectangle applicationPosition = *new* Rectangle();
   *private* *boolean* MAXIMIZED = *false*;
   *private* *boolean* PROCESS_WINDOW_EVENTS = *true*;


   //Static for serialization
   *private* *static* Cursor emptyCursor = createEmptyCursor();

   //These cannot be static since they use methods of the instance,
so recreate on readObject
   *private* *transient* Timer timeToHideMouse = *new* Timer(1500,
*new* HideMouse());
   *private* *class* HideMouse *implements* ActionListener{
       *public* *void* actionPerformed(ActionEvent e) {
           setCursor(emptyCursor);
       }
   }

   *private* *transient* AWTEventListener scheduleHideMouse = *new*
HideMouseStart();
   *private* *class* HideMouseStart *implements* AWTEventListener{
       *public* *void* eventDispatched(AWTEvent e) {
           *if*(MAXIMIZED){
               setCursor(Cursor.getDefaultCursor());
               timeToHideMouse.restart();
               timeToHideMouse.setRepeats(*false*);
           }
       }
   }
   //used to minimize on (any) window deactivation
   //Is a AWTListener since there is no way to be notified of
parenting a window
   *private* *transient* AWTEventListener minimizeListener = *new*
DoMinimize();
   *private* *class* DoMinimize *implements* AWTEventListener{
       *public* *void* eventDispatched(AWTEvent e) {
           WindowEvent evt = (WindowEvent) e;

           *if*(PROCESS_WINDOW_EVENTS && evt.getID() == evt.WINDOW_DEACTIVATED
                   && evt.getOppositeWindow() == *null* &&
JFrame.this.isFullScreen()){
               JFrame.this.setExtendedState(JFrame.ICONIFIED);
           }
       }
   }



   *private* *static* Cursor createEmptyCursor(){
       *int*[] pixels = *new* *int*[0/*16 * 16*/];
       Image image = Toolkit.getDefaultToolkit().createImage(*new*
MemoryImageSource(0, 0, pixels, 0, 0));
       *return* Toolkit.getDefaultToolkit().createCustomCursor(
image, *new* Point(0,0), "InvisibleCursor");
   }

   *public* JFrame(){
       *this*(*null*);
   }

   *public* JFrame(String s){
       *super*(s);
       //A more sensible default.
       setBounds(*new* Rectangle(Toolkit.getDefaultToolkit().getScreenSize()));
       Toolkit.getDefaultToolkit().addAWTEventListener(minimizeListener,
AWTEvent.WINDOW_EVENT_MASK);
   }

   *public* *boolean* isFullScreen(){
       *return* MAXIMIZED;
   }


   /**
    * This method places the JFrame in full screen mode. This means
    * 1) Not resizble. 2) Undecorated if possible. 3) Always on top.
    * Moreover it also installs a mouse listener that hides the cursor if it
    * is not moved in more than 1.5s and shows it when moved.
    * @param setFull : set the fullscreen
    */
   *public* *void* setFullScreen(*final* *boolean* setFull ){
       *if*(setFull != MAXIMIZED){
           //stop processing window events now
           PROCESS_WINDOW_EVENTS = *false*;
           *final* *boolean* wasVisible = isVisible();

           setVisible(*false*);
           dispose();

           *if* (setFull) {

Toolkit.getDefaultToolkit().addAWTEventListener(scheduleHideMouse,
AWTEvent.MOUSE_MOTION_EVENT_MASK);
               //timeToHideMouse.start();
               getBounds(applicationPosition);
               setBounds(*new*
java.awt.Rectangle(java.awt.Toolkit.getDefaultToolkit().getScreenSize()));
           } *else* {

Toolkit.getDefaultToolkit().removeAWTEventListener(scheduleHideMouse);
               timeToHideMouse.stop();
               setCursor(Cursor.getDefaultCursor());
               setBounds(applicationPosition);
           }
           setAlwaysOnTop(setFull);
           setUndecorated(setFull);
           setResizable(!setFull);
           validate();
           setVisible(wasVisible);
           MAXIMIZED = setFull;
           //the events posted here are in front of
           //this control event
           EventQueue.invokeLater(*new* Runnable(){
               *public* *void* run() {
                   PROCESS_WINDOW_EVENTS = *true*;
                   repaint();
               }
           });
       }
   }

   /*
    * Overriden to stop WindowEvents when disposing internally.
    */
   *protected* *void* processWindowEvent(WindowEvent we) {
       *if*(PROCESS_WINDOW_EVENTS)
           super.processWindowEvent(we);
   }



   *protected* *void* readObject(ObjectInputStream s) *throws*
IOException, ClassNotFoundException{
       PROCESS_WINDOW_EVENTS = *true*;
       timeToHideMouse = *new* Timer(1500, *new* HideMouse());
       scheduleHideMouse = *new* HideMouseStart();
       setBounds((Rectangle) s.readObject());
       setFullScreen(s.readBoolean());
       applicationPosition = (Rectangle) s.readObject();
       //requestFocus();
   }

   *protected* *void* writeObject(ObjectOutputStream s) *throws* IOException{
       s.writeObject(getBounds());
       s.writeBoolean(MAXIMIZED);
       s.writeObject(applicationPosition);
   }

}

and


*import* java.awt.event.ActionEvent;
*import* javax.swing.AbstractAction;
*import* javax.swing.JButton;
*import* javax.swing.JOptionPane;
*import* javax.swing.JPanel;
*import* javax.swing.SwingUtilities;
*import* ui.JFrame;
/*
* testcase.java
*
* Created on 26/Jun/2007, 21:09:15
*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/

/**
*
* @author i30817
*/
*public* *class* testcase {

   *static* JFrame f;
   *public* testcase() {

   }

   *public* *static* *void* main(*final* String args[]){


       SwingUtilities.invokeLater(*new* Runnable() {*public* *void* run() {
           f = *new* JFrame();

           f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
           JPanel p = *new* JPanel();
           p.add(*new* JButton(*new* PopAction("click me for dialog")));
           p.add(*new* JButton(*new* Full("click me to toogle fullscreen")));
           f.add(p);


           f.pack();
           f.setVisible(*true*);

       }});
   }

   *static* *class* Full *extends* AbstractAction{

       *public* Full(String name){
           *super*(name);
       }
       *public* *void* actionPerformed(ActionEvent e) {

          f.setFullScreen(!f.isFullScreen());
       }

   }

   *static* *class* PopAction *extends* AbstractAction{

       *public* PopAction(String name){
           *super*(name);
       }
       *public* *void* actionPerformed(ActionEvent e) {
          JOptionPane.showMessageDialog(f,"Click esc to see a bug in linux");
       }

   }

}

Reply via email to