JDK-4344900 : Keyboard accelerators not working with canvas
  • Type: Bug
  • Component: client-libs
  • Sub-Component: javax.swing
  • Affected Version: 1.2.2,1.3.0
  • Priority: P3
  • Status: Resolved
  • Resolution: Fixed
  • OS: solaris_8,windows_nt
  • CPU: x86,sparc
  • Submitted: 2000-06-12
  • Updated: 2000-12-13
  • Resolved: 2000-12-13
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
Other
1.4.0 betaFixed
Related Reports
Duplicate :  
Relates :  
Description

Name: skT45625			Date: 06/12/2000


Java(TM) 2 Runtime Environment, Standard Edition (build 1.3.0-C)
Java HotSpot(TM) Client VM (build 1.3.0-C, mixed mode)


Recently, I switched to JDK 1.3 and my menu's keyboard accelerators
stopped working.  Since I was using Magician OpenGL, I first suspected
that it might be related to the GL component I was using.  I tried
replacing it with a JPanel and, sure enough, the keyboard accelerators
started working again.  Since the GL component extends Canvas, I decided
to try a canvas instead, but this caused the keyboard accelerators to
stop working.

The code below brings up two frames.  One with a Canvas inside and one
with a JPanel inside.  If you try the Ctrl-A command on either, it will
bring up a confirmation dialog box.  But after you click inside the
canvas area, that frame will no longer respond to the keyboard
shortcut.  It works if you have clicked on the title area or menu area,
but stops working once the canvas area has been clicked.  The frame with
the JPanel continues to respond regardless of where you click inside it.

You don't need Magician to run this code.  Hopefully, solving this
problem will help me fix the real application, which uses Magician.
It may be a problem with focus or heavyweight components.  You might
also try using it in JDK 1.3 versus 1.2.2.  My Magician-based app
works perfectly under 1.2.2, but not 1.3.


=====================================================================

//Bug test for menu accelerators.

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class TestFrame extends JFrame implements WindowListener{

    // Member variables...
        JFrame parentFrame = this;


//---------------------------------------------------------------------------
// Constructor...
        public TestFrame(String title, boolean useJPanel) {

        super (title);

        AbstractAction action;
        JMenuBar menuBar = new JMenuBar();
        JMenuItem mi;

        // Set up the File menu...
        JMenu fileMenu = new JMenu("File");             // ---> File Menu
        action = new Action1(); // Action 1
        mi = fileMenu.add(action);        // Ctrl-A
                mi.setAccelerator(KeyStroke.getKeyStroke(
                KeyEvent.VK_A, ActionEvent.CTRL_MASK));

        action = new ActionExit();      // Exit
        mi = fileMenu.add(action);        // Ctrl-Q
                mi.setAccelerator(KeyStroke.getKeyStroke(
                KeyEvent.VK_Q, ActionEvent.CTRL_MASK));

        fileMenu.getPopupMenu().setLightWeightPopupEnabled(false);
        menuBar.add(fileMenu);
        setJMenuBar(menuBar);

        setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);

        setSize(200, 100);
        show();


        // Keyboard shortcuts don't work in the canvas frame after the
        // canvas area has been clicked.
        if (useJPanel) {
                JPanel panel = new JPanel();
            panel.setSize(200, 100);
                panel.setBackground(Color.red);
                getContentPane().add(panel);
            repaint();
        }
        else {
                Canvas canvas = new Canvas();
            canvas.setSize(200, 100);
                canvas.setBackground(Color.blue);
                getContentPane().add(canvas);
            repaint();
        }
    }

//==========================================================================
    /** Action class. */
    class Action1 extends AbstractAction {
       
//----------------------------------------------------------------------
        public Action1() {
            super( "Action 1..." );
            putValue(Action.SHORT_DESCRIPTION, "Action 1...");
        }

       
//----------------------------------------------------------------------
        public void actionPerformed(ActionEvent e) {
                JOptionPane.showMessageDialog(parentFrame,
                "Action 1", "Action Performed",
                    JOptionPane.INFORMATION_MESSAGE);
        }
    }

   

//==========================================================================
    /** Action class. */
    class ActionExit extends AbstractAction {
       
//----------------------------------------------------------------------
        public ActionExit() {
            super( "Exit" );
            putValue(Action.SHORT_DESCRIPTION, "Exit");
        }

       
//----------------------------------------------------------------------
        public void actionPerformed(ActionEvent e) {
                System.exit(0);
        }
    }


//------------------------------------------------------------------------------
// Window listener methods that must be defined...
    public void windowClosed ( WindowEvent evt ) {}
    public void windowActivated( WindowEvent evt ) {}
    public void windowDeactivated( WindowEvent evt ) {}
    public void windowDeiconified( WindowEvent evt ) {}
    public void windowIconified( WindowEvent evt ) {}
    public void windowOpened( WindowEvent evt ) {}


//------------------------------------------------------------------------------
/*
 * When the user closes the window, destroy everything and close the program.
 */
    public void windowClosing( WindowEvent evt ) {

        dispose();
        System.exit( 0 );
    }


//------------------------------------------------------------------------------
/*
 * Create two instances of the frame.
 * One with a Canvas in which keyboard accelerators do not work, and one
 * with a JPanel in which they do.
 */
    static public void main (String args[]) {

        TestFrame canvasFrame = new TestFrame("Canvas", false);
        TestFrame jPanelFrame = new TestFrame("JPanel", true);
    }
}
(Review ID: 106011) 
======================================================================

jocelyn.charbonneau@Eng 2000-12-11
I tried the fix in JDK1.4, beta-43 and beta-44 and it is clearly not sufficiant
for the context of BugID #4395074, where it was deemed a duplicate of this one.  The fix makes accelerators an mnemonics work when the pointer is not on top of 
the heavyweight component, but it doesn't work otherwise.

[pf, 12/12/2000]
   As Jocelyn points out, this does not fix his original bug report
(4395074) even in JDK1.4.  Besides, having a fix in 1.4 is not a
solution for our product, since we need the fix in the versions of
Java which go in Solaris 8, and Solaris 8 updates, and Solaris 9.

Comments
CONVERTED DATA BugTraq+ Release Management Values COMMIT TO FIX: merlin-beta FIXED IN: merlin-beta INTEGRATED IN: merlin-beta
14-06-2004

WORK AROUND stuart.findlay@ireland 2001-02-09 I have a workaround for this bug which passes the appropriate keyEvent from the lightweight to the parent. See file TestFram_Workaround.java in attachments. Name: skT45625 Date: 06/12/2000 Use 1.2 instead of 1.3. ======================================================================
11-06-2004

EVALUATION Swings keyboard navigation is triggered from JComponent.processKeyEvent, as such, when a non-JComponent has focus JComponent.processKeyEvent will never be called and the bindings will never be used. We such provide a method that people can call into if they are using a mix of JComponent and non JComponent classes. scott.violet@eng 2000-07-06 To accomodate this we will add SwingUtilities.processKeyBindings(KeyEvent). When creating a non-JComponent that can get focus, or a JComponent that does not invoke super.processKeyEvent, you will then have to do the following to process JComponent key bindings: canvas.addKeyListener(new KeyListener() { public void keyTyped(KeyEvent e) { SwingUtilities.processKeyBindings(e); } public void keyPressed(KeyEvent e) { SwingUtilities.processKeyBindings(e); } public void keyReleased(KeyEvent e) { SwingUtilities.processKeyBindings(e); } }); scott.violet@eng 2000-07-14 Moving back to integrated. Customer will escalate if they need patch. scott.violet@eng 2000-12-12
14-07-2000