Java Solaris Communities Sun Store Join SDN My Profile Why Join?
 
Bug Database
Bug Detail
Quick Lists
Top 25 Bugs
Top 25 RFE's
Recently Closed Bugs
Printable Page Printable Page


Bug Database
Bug ID: 4131761
Votes 14
Synopsis What is the correct focusing behavior
Category java:classes_awt
Reported Against 1.1.6
Release Fixed
State 11-Closed, duplicate of 4290675, request for enhancement
Priority: 4-Low
Related Bugs 4138263 , 4290675
Submit Date 22-APR-1998
Description
A group of Focus issues.
----------------------------------------------------

The applet consists of two simple lightweight components which are KeyListeners (these are prototypical lightweight InputField objects). When the applet is started via appletviewer, the first  customer  to have focus is NOT the applet, but rather: sun.applet.AppletViewerPanel.  We must explicitly call requestFocus() in the init() method of the applet to get focus onto it.

Key presses are recorded by the applet's KeyListener at this point, but not by the two simple lightweight components.  This is correct behavior.

Click off of the applet to an outside application. You will notice on the console that the applet loses the focus.  Again, this is correct behavior.  Click back on the applet, being careful not to click on either of the lightweight components.  You will notice on the console that it is not the applet that regains focus (which as I understand it, is what should happen) but rather: sun.applet.AppletViewer. Interestingly enough, this is not the  customer  which initially has focus, which is not sun.applet.AppletViewer, but rather sun.applet.AppletViewerPanel.  Anyway, our "FocusTransfer"  customer  listens for focus on the AppletViewer  customer  and correctly transfers the focus back to the applet.  This can be verified on the console by appropriate messages.  THIS IS A WORKAROUND.

Next, click on one of the two lightweight components. It will get focus.  A message is printed on the console to this effect.  It will now get key press events. HOWEVER, no  customer  lost focus - I would expect the applet to.  In addition, the applet's own KeyListener continues to get key events.  It seems that the applet and the lightweight component have focus at the same time.  Is this the correct behavior?  I am unsure.

Switching between the two lightweights (by clicking) seems to behave correctly, although the applet continues to have focus at this time.

Finally, while one of the lightweight components has the focus, click on an outside application to remove the focus, then click back on the applet.  According to the console output, AppletViewer once again gets the focus, although I believe the correct behavior should be that the last component to have focus (the lightweight) should get it again.  Interestingly enough, our FocusTransfer  customer  hears the FocusEvent on the AppletViewer and reacts.  However, although it's response is to call requestFocus() on the applet, it is the lightweight component that gets focus instead!  I am unsure as to why this occurs.

----------------------------------------------------

To see this applet, use the following HTML code:
  <APPLET CODE="InputFocusBug.class" WIDTH=430 HEIGHT=270></APPLET>
 
  This has been tested with the JDK 1.1.6M appletviewer on
  Windows NT Server 4.0 on a Pentium Pro 180 with 64 megabytes.



------------------- Code -------------------


import java.applet.Applet;
import java.awt.event.FocusListener;
import java.awt.event.KeyListener;
import java.awt.Color;
import java.awt.event.FocusEvent;
import java.awt.event.KeyEvent;
import java.awt.Graphics;
import java.awt.Component;
import java.awt.event.MouseListener;
import java.awt.event.MouseEvent;

// This is the main applet to demonstrate the problem.
public class InputFocusBug extends Applet implements FocusListener, KeyListener
{
    SimpleKeyInput inputOne;
    SimpleKeyInput inputTwo;
    boolean inFocus = false;
    char lastKey = ' ';

    public void init( )
    {
        // basic setup
        setLayout( null);
        setBackground( Color.white);
        setForeground( Color.black);
        setSize( 430, 270);

        // add the focus and key listeners
        addFocusListener( this);
    	addKeyListener( this);

        // add the "simple input"s to the applet
        inputOne = new SimpleKeyInput( );
        inputTwo = new SimpleKeyInput( );
        inputOne.setBounds( 36, 56, 144, 24);
        inputTwo.setBounds( 36, 86, 144, 24);
        add( inputOne);
        add( inputTwo);

        // make sure we're showing everything!
        validate( );
        repaint( );

        // get the focus to start off
        requestFocus( );

        // This is an attempt to make sure whenever part of
        // appletviewer gets the focus (either the AppletViewer
        // itself, or the AppletViewerPanel), we switch the
        // focus to the applet again.
        FocusTransfer theTransferObject = new FocusTransfer( this);
        getParent( ).addFocusListener( theTransferObject);
        getParent( ).getParent( ).addFocusListener( theTransferObject);
    }

    // set our internal state to know we've got the focus, then repaint
    public void focusGained( FocusEvent evt)
    {
        System.out.println( evt.getSource( ) + " got focus.");
        System.out.flush( );
        inFocus = true;
        repaint( );
    }

    // set our internal state to know we've lost the focus, then repaint
    public void focusLost( FocusEvent evt)
    {
        System.out.println( evt.getSource( ) + " lost focus.");
        System.out.flush( );
        inFocus = false;
        repaint( );
    }

    // set our internal record of the key that was typed, then repaint
    public void keyTyped( KeyEvent evt)
    {
        lastKey = evt.getKeyChar( );
        repaint( );
    }

    // these two methods aren't used
    public void keyPressed( KeyEvent evt) {}
    public void keyReleased( KeyEvent evt) {}

    public synchronized void update( Graphics g)
    {
        paint( g);
    }

    public void paint( Graphics g)
    {
        // paint the background
        g.setColor( getBackground( ));
        g.fillRect( 0, 0, 430, 270);

        // paint what the last key typed was
        g.setColor( getForeground( ));
        g.drawString( "Last Key: " + lastKey, 20, 150);

        // paint whether or not we have focus
        if( inFocus)
        {
            g.drawString( "Applet Has Focus", 20, 170);
        }
        else
        {
            g.drawString( "Applet Does Not Have Focus", 20, 170);
        }

        // paint the inputs
        super.paint( g);
    }
}

// This  customer  will switch the focus to another  customer 
// FOCUSTRANSFER is a WORKAROUND
class FocusTransfer implements FocusListener
{
    // The  customer  we want to switch focus to
    Component component = null;

    // The constructor, setting up the target  customer 
    public FocusTransfer( Component component)
    {
        this.component = component;
    }

    // when we hear a focus message, automatically request
    // focus on the target  customer  after printing out a
    // status message
    public void focusGained( FocusEvent evt)
    {
        System.out.println( evt.getSource( ) + " got focus.");
        System.out.flush( );
        System.out.println( "Calling requestFocus() on " + component);
        System.out.flush( );
        component.requestFocus( );
    }

    // merely print out a status message when whatever we
    // are listening to loses focus
    public void focusLost( FocusEvent evt)
    {
        System.out.println( evt.getSource( ) + " lost focus.");
        System.out.flush( );
    }
}

// This is out simple input class
class SimpleKeyInput extends Component implements MouseListener, KeyListener, FocusListener
{
    char lastKey = ' ';
    boolean inFocus = false;

    public SimpleKeyInput( )
    {
        // should get keyboard input
        addKeyListener( this);

        // get ready to listen for clicks
        addMouseListener( this);

        // make sure we know when we get and lose focus
        addFocusListener( this);
    }

    // these methods are not used
    public void mouseClicked( MouseEvent e) {}
    public void mouseEntered( MouseEvent e) {}
    public void mouseExited( MouseEvent e) {}
    public void mousePressed( MouseEvent e) {}
    public void keyPressed( KeyEvent evt) {}
    public void keyReleased( KeyEvent evt) {}

    // set our internal state to know we've got the focus, then repaint
    public void focusGained( FocusEvent evt)
    {
        System.out.println( evt.getSource( ) + " got focus.");
        System.out.flush( );
        inFocus = true;
        repaint( );
    }

    // set our internal state to know we've lost the focus, then repaint
    public void focusLost( FocusEvent evt)
    {
        System.out.println( evt.getSource( ) + " lost focus.");
        System.out.flush( );
        inFocus = false;
        repaint( );
    }

    // set our internal record of the key that was typed, then repaint
    public void keyTyped( KeyEvent evt)
    {
        lastKey = evt.getKeyChar( );
        repaint( );
    }

    // if the button was clicked, let our listeners know
    public void mouseReleased( MouseEvent e)
    {
        requestFocus( );
    }

    // paint the simplekeylistener
    public void paint( Graphics g)
    {
        g.setColor( getBackground( ));
        g.fillRect( 0, 0, getSize( ).width, getSize( ).height);
        g.setColor( getForeground( ));
        if( inFocus)
        {
            g.drawString( "FOCUSED: " + lastKey, 5, getSize( ).height - 3);
        }
        else
        {
            g.drawString( "UNFOCUSED: " + lastKey, 5, getSize( ).height - 3);
        }
        g.drawRect( 0, 0, getSize( ).width - 1, getSize( ).height - 1);
    }
}
Work Around
N/A
Evaluation
Currently planning to implement this functionality, or equivalent
functionality, in the merlin focus enhancements.
  xxxxx@xxxxx   1999-12-14
Comments
  
  Include a link with my name & email   

Submitted On 06-MAY-1998
DLevine
This really isn't an RFE.  Instead it is a
series of questions about focusing behavior,
trying to determine if the behavior shown
by this applet is really what is supposed to
happen.  If so, it is not intuitive.  First,
the Applet should have focus immediately,
without having to call requestFocus.  Didn't
it, originally?  Second, clicking on the
Applet should bring it into focus.  Didn't
it, originally?  Third, switching focus to
an outside application and then back again
should cause the last component that had
focus to regain focus.  The above applet has
workarounds to make sure that all these
things occur (although in the case of the
last issue, I'm not sure why the workaround
works), but it probably shouldn't need them.
So my question remains: is this the correct
behavior?



PLEASE NOTE: JDK6 is formerly known as Project Mustang