<AWT Dev> Hi. About awt WindowDeactivatedEvent.getOppositeWindow() returning null

Paulo Levi i30817 at gmail.com
Fri Jun 29 14:26:37 PDT 2007


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

    }

}
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://mail.openjdk.java.net/pipermail/awt-dev/attachments/20070629/3d885b5c/attachment.html 


More information about the awt-dev mailing list