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"); } } }