Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-4131761

What is the correct focusing behavior

XMLWordPrintable

    • Icon: Enhancement Enhancement
    • Resolution: Duplicate
    • Icon: P4 P4
    • None
    • 1.1.6
    • client-libs
    • x86
    • windows_nt

      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 object 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 object which initially has focus, which is not sun.applet.AppletViewer, but rather sun.applet.AppletViewerPanel. Anyway, our "FocusTransfer" object listens for focus on the AppletViewer object 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 object 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 object 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 object will switch the focus to another object
      // FOCUSTRANSFER is a WORKAROUND
      class FocusTransfer implements FocusListener
      {
          // The object we want to switch focus to
          Component component = null;

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

          // when we hear a focus message, automatically request
          // focus on the target object 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);
          }
      }

            dmendenhsunw David Mendenhall (Inactive)
            duke J. Duke
            Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

              Created:
              Updated:
              Resolved:
              Imported:
              Indexed: