SUGGESTED FIX
Name: azR10139 Date: 10/07/2002
------- WindowsLookAndFeel.java -------
*** /tmp/sccs.lUaOZx Mon Oct 7 19:40:57 2002
--- WindowsLookAndFeel.java Fri Oct 4 19:13:06 2002
***************
*** 139,144 ****
--- 139,146 ----
// do this if we know it's 98/2000 or greater....
PopupFactory.setSharedInstance(new WindowsPopupFactory());
}
+ KeyboardFocusManager.getCurrentKeyboardFocusManager().
+ addKeyEventPostProcessor(WindowsRootPaneUI.altProcessor);
}
/**
***************
*** 1496,1506 ****
if (WindowsPopupMenuUI.mnemonicListener != null) {
MenuSelectionManager.defaultManager().
removeChangeListener(WindowsPopupMenuUI.mnemonicListener);
}
! if (WindowsPopupMenuUI.altProcessor != null) {
! KeyboardFocusManager.getCurrentKeyboardFocusManager().
! removeKeyEventPostProcessor(WindowsPopupMenuUI.altProcessor);
! }
DesktopProperty.flushUnreferencedProperties();
}
--- 1498,1507 ----
if (WindowsPopupMenuUI.mnemonicListener != null) {
MenuSelectionManager.defaultManager().
removeChangeListener(WindowsPopupMenuUI.mnemonicListener);
+ WindowsPopupMenuUI.mnemonicListener = null;
}
! KeyboardFocusManager.getCurrentKeyboardFocusManager().
! removeKeyEventPostProcessor(WindowsRootPaneUI.altProcessor);
DesktopProperty.flushUnreferencedProperties();
}
------- WindowsPopupMenuUI.java -------
*** /tmp/sccs.luaa0x Mon Oct 7 19:41:24 2002
--- WindowsPopupMenuUI.java Fri Oct 4 19:13:26 2002
***************
*** 30,36 ****
public class WindowsPopupMenuUI extends BasicPopupMenuUI {
static MnemonicListener mnemonicListener = null;
- static KeyEventPostProcessor altProcessor = null;
public static ComponentUI createUI(JComponent c) {
return new WindowsPopupMenuUI();
--- 30,35 ----
***************
*** 45,56 ****
MenuSelectionManager.defaultManager().
addChangeListener(mnemonicListener);
}
-
- if (altProcessor == null) {
- altProcessor = new AltProcessor();
- KeyboardFocusManager.getCurrentKeyboardFocusManager().
- addKeyEventPostProcessor(altProcessor);
- }
}
/**
--- 44,49 ----
***************
*** 85,148 ****
}
}
}
-
- static class AltProcessor implements KeyEventPostProcessor {
- static boolean altKeyPressed = false;
- static boolean menuCanceledOnPress = false;
-
- void altPressed() {
- MenuSelectionManager msm =
- MenuSelectionManager.defaultManager();
- MenuElement[] path = msm.getSelectedPath();
- if (path.length > 0 && ! (path[0] instanceof ComboPopup)) {
- msm.clearSelectedPath();
- menuCanceledOnPress = true;
- } else {
- menuCanceledOnPress = false;
- }
- }
-
- void altReleased(KeyEvent ev) {
- if (menuCanceledOnPress) {
- return;
- }
-
- MenuSelectionManager msm =
- MenuSelectionManager.defaultManager();
- if (msm.getSelectedPath().length == 0) {
- // if no menu is active, we try activating the menubar
- JRootPane root = SwingUtilities.getRootPane(ev.getComponent());
- java.awt.Window w = SwingUtilities.getWindowAncestor(root);
-
- JMenuBar mbar = root != null ? root.getJMenuBar() : null;
- JMenu menu = mbar != null ? mbar.getMenu(0) : null;
-
- if (menu != null) {
- MenuElement[] path = new MenuElement[2];
- path[0] = mbar;
- path[1] = menu;
- msm.setSelectedPath(path);
- }
- }
- }
-
- public boolean postProcessKeyEvent(KeyEvent ev) {
- if (ev.getKeyCode() == KeyEvent.VK_ALT) {
- if (ev.getID() == KeyEvent.KEY_PRESSED) {
- if (!altKeyPressed) {
- altPressed();
- }
- altKeyPressed = true;
- } else if (ev.getID() == KeyEvent.KEY_RELEASED) {
- if (altKeyPressed) {
- altReleased(ev);
- }
- altKeyPressed = false;
- }
- } else {
- altKeyPressed = false;
- }
- return false;
- }
- }
}
--- 78,81 ----
------- WindowsRootPaneUI.java -------
*** /tmp/sccs.11aO1x Mon Oct 7 19:43:29 2002
--- WindowsRootPaneUI.java Mon Oct 7 19:43:20 2002
***************
*** 8,14 ****
--- 8,17 ----
package com.sun.java.swing.plaf.windows;
import java.awt.Component;
+ import java.awt.Container;
import java.awt.Event;
+ import java.awt.KeyEventPostProcessor;
+ import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
***************
*** 21,26 ****
--- 24,35 ----
import javax.swing.JRootPane;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
+ import javax.swing.AbstractButton;
+ import javax.swing.JFrame;
+ import javax.swing.JMenu;
+ import javax.swing.JMenuBar;
+ import javax.swing.MenuElement;
+ import javax.swing.MenuSelectionManager;
import javax.swing.plaf.ActionMapUIResource;
import javax.swing.plaf.ComponentUI;
***************
*** 27,32 ****
--- 36,42 ----
import javax.swing.plaf.InputMapUIResource;
import javax.swing.plaf.basic.BasicRootPaneUI;
+ import javax.swing.plaf.basic.ComboPopup;
/**
* Windows implementation of RootPaneUI, there is one shared between all
***************
*** 39,87 ****
public class WindowsRootPaneUI extends BasicRootPaneUI {
private final static WindowsRootPaneUI windowsRootPaneUI = new WindowsRootPaneUI();
! private final static AltAction altAction = new AltAction();
public static ComponentUI createUI(JComponent c) {
return windowsRootPaneUI;
}
! protected void installKeyboardActions(JRootPane root) {
! super.installKeyboardActions(root);
! InputMap km = SwingUtilities.getUIInputMap(root,
! JComponent.WHEN_IN_FOCUSED_WINDOW);
! if (km == null) {
! km = new InputMapUIResource();
! SwingUtilities.replaceUIInputMap(root,
! JComponent.WHEN_IN_FOCUSED_WINDOW, km);
! }
! km.put(KeyStroke.getKeyStroke(KeyEvent.VK_ALT, Event.ALT_MASK, false), "repaint");
! ActionMap am = SwingUtilities.getUIActionMap(root);
! if (am == null) {
! am = new ActionMapUIResource();
! SwingUtilities.replaceUIActionMap(root, am);
! }
! am.put("repaint", altAction);
! }
! protected void uninstallKeyboardActions(JRootPane root) {
! super.uninstallKeyboardActions(root);
!
! SwingUtilities.replaceUIInputMap(root, JComponent.WHEN_IN_FOCUSED_WINDOW, null);
! SwingUtilities.replaceUIActionMap(root, null);
! }
! /**
! * Repaints the hierarchy if the Alt key is pressed.
! */
! static class AltAction extends AbstractAction {
! public void actionPerformed(ActionEvent e) {
! WindowsLookAndFeel.setMnemonicHidden(false);
! Object object = e.getSource();
! if (object instanceof Component) {
! WindowsLookAndFeel.repaintRootPane((Component)object);
! }
! }
}
}
--- 49,186 ----
public class WindowsRootPaneUI extends BasicRootPaneUI {
private final static WindowsRootPaneUI windowsRootPaneUI = new WindowsRootPaneUI();
! static final AltProcessor altProcessor = new AltProcessor();
public static ComponentUI createUI(JComponent c) {
return windowsRootPaneUI;
}
! static class AltProcessor implements KeyEventPostProcessor {
! static boolean altKeyPressed = false;
! static boolean menuCanceledOnPress = false;
! static JRootPane root = null;
! static Window winAncestor = null;
! void repaintMnemonicsInWindow(Window w) {
! if(w == null || !w.isShowing()) {
! return;
! }
! Window[] ownedWindows = w.getOwnedWindows();
! for(int i=0;i<ownedWindows.length;i++) {
! repaintMnemonicsInWindow(ownedWindows[i]);
! }
! repaintMnemonicsInComponents(w.getComponents());
! }
! void repaintMnemonicsInComponents(Component[] c) {
! for(int i=0;i<c.length;i++) {
! if(c[i] instanceof AbstractButton
! && ((AbstractButton)c[i]).getMnemonic() != '\0') {
! c[i].repaint();
! continue;
! }
! if(c[i] instanceof Container) {
! repaintMnemonicsInComponents(
! ((Container)c[i]).getComponents());
! }
! }
! }
!
! void altPressed(KeyEvent ev) {
! MenuSelectionManager msm =
! MenuSelectionManager.defaultManager();
! MenuElement[] path = msm.getSelectedPath();
! if (path.length > 0 && ! (path[0] instanceof ComboPopup)) {
! msm.clearSelectedPath();
! menuCanceledOnPress = true;
! ev.consume();
! } else if(path.length > 0) { // We are in ComboBox
! menuCanceledOnPress = false;
! WindowsLookAndFeel.setMnemonicHidden(false);
! repaintMnemonicsInWindow(winAncestor);
! ev.consume();
! } else {
! menuCanceledOnPress = false;
! WindowsLookAndFeel.setMnemonicHidden(false);
! repaintMnemonicsInWindow(winAncestor);
! JMenuBar mbar = root != null ? root.getJMenuBar() : null;
! if(mbar == null && winAncestor instanceof JFrame) {
! mbar = ((JFrame)winAncestor).getJMenuBar();
! }
! JMenu menu = mbar != null ? mbar.getMenu(0) : null;
! if(menu != null) {
! ev.consume();
! }
! }
! }
!
! void altReleased(KeyEvent ev) {
! if (menuCanceledOnPress) {
! WindowsLookAndFeel.setMnemonicHidden(true);
! repaintMnemonicsInWindow(winAncestor);
! return;
! }
!
! MenuSelectionManager msm =
! MenuSelectionManager.defaultManager();
! if (msm.getSelectedPath().length == 0) {
! // if no menu is active, we try activating the menubar
!
! JMenuBar mbar = root != null ? root.getJMenuBar() : null;
! if(mbar == null && winAncestor instanceof JFrame) {
! mbar = ((JFrame)winAncestor).getJMenuBar();
! }
! JMenu menu = mbar != null ? mbar.getMenu(0) : null;
!
! if (menu != null) {
! MenuElement[] path = new MenuElement[2];
! path[0] = mbar;
! path[1] = menu;
! msm.setSelectedPath(path);
! } else if(!WindowsLookAndFeel.isMnemonicHidden()) {
! WindowsLookAndFeel.setMnemonicHidden(true);
! repaintMnemonicsInWindow(winAncestor);
! }
! } else {
! if((msm.getSelectedPath())[0] instanceof ComboPopup) {
! WindowsLookAndFeel.setMnemonicHidden(true);
! repaintMnemonicsInWindow(winAncestor);
! }
! }
!
! }
!
! public boolean postProcessKeyEvent(KeyEvent ev) {
! if (ev.getKeyCode() == KeyEvent.VK_ALT) {
! root = SwingUtilities.getRootPane(ev.getComponent());
! winAncestor = SwingUtilities.getWindowAncestor(root);
!
! if (ev.getID() == KeyEvent.KEY_PRESSED) {
! if (!altKeyPressed) {
! altPressed(ev);
! }
! altKeyPressed = true;
! return true;
! } else if (ev.getID() == KeyEvent.KEY_RELEASED) {
! if (altKeyPressed) {
! altReleased(ev);
! } else {
! MenuSelectionManager msm =
! MenuSelectionManager.defaultManager();
! MenuElement[] path = msm.getSelectedPath();
! if (path.length <= 0) {
! WindowsLookAndFeel.setMnemonicHidden(true);
! repaintMnemonicsInWindow(winAncestor);
! }
! }
! altKeyPressed = false;
! }
! } else {
! altKeyPressed = false;
! }
! return false;
! }
}
}
======================================================================
|
EVALUATION
Yes, this is a regression. WindowsRootPaneUI's installKeyboardActions is
broken.
SwingSet isn't helping though, it does not do a setJMenuBar for its menu when
it should.
###@###.### 2002-08-23
There are two problems here:
1. SwingSet2 does not install the menubar via setJMenuBar. There is no
reason for this and it should be chaged.
2. WindowsRootPaneUI is getting the UI InputMap and placing bindings into it.
Because BasicRootPaneUI will occasionally clear this InputMap the bindings
that WindowsRootPaneUI installed are lost. WindowsRootPaneUI should be
creating a new UI InputMap and setting the parent to point to that of the
InputMap from Basic.
###@###.### 2002-08-26
Name: azR10139 Date: 10/07/2002
The reason of this bug is that BasicRootPaneUI class resets keyboard action
table every time BasicRootPaneUI.installKeyboardActions() method is called.
This makes usege of inputmap unstable. Also we are turning mnemonic
displaying on and off in different classes. The idea of suggestede fix is
to collect all the functionality, related to the Alt pressing and releasing in
one class. The logic now is similar to logic used for native Win32 apps in
W2K/WXP environment.
1. User press Alt.
1.1. If no menu selected and we do have JMenuBar in this RootPane or in
root JFrame we turn mnemonic on, set flag to select first menu in JMenuBar
on Alt releasing if no other key pressed and consuming event to prevent AWT
from selecting system menu of this window on Alt release.
1.2. If no menu selected and we can't find JMenuBar to select we are turn
mnemonic on and do not consume event.
1.3. If there are menu selected we are clearing menu selection, setting the
flag that we are cancelled menu on press and consuming event.
2. User releases Alt
2.1. If menu are cancelled on Alt or no JMenuBar accessible press we just
turning mnemonics off.
2.2. If there are JMenuBar accessible and no button were pressed since Alt
we are selecting first menu in JMenuBar.
Turning mnemonic on and off consist from calling
BasicLookAndFeel.setMnemonicHidden() with appropriate parameter and repainting
all the components which do have mnemonics in window where event origins and
all the owned windows. This optimisation also deals with bug 4748780:
1.4 REGRESSION: Pressing ALT key causes JThree to repaint in Windows L&F
In the WindowsLookAndFeel.uninitialize() method i also added uninitialisation
of WindowsPopupMenuUI.mnemonicListener which eliminates bug 4692725:
WindowsPopupMenuUI.MenuListener does not reset repaintRoot on UI change.
This bug originally must be named as
'WindowsPopupMenuUI.MnemonicListener does not reset repaintRoot on UI change.'
because there were no MenuListener class in the WindowsPopupMenuUI.java
Also, because we are eliminating inner class AltProcessor from
BasicPopupMenuUI bug 4692727:
WindowsPopupMenuUI.MenuListener does not get reinstalled on second windows inst
which relates on WindowsPopupMenuUI.AltProcessor class.
###@###.### 10/07/2002
======================================================================
|
WORK AROUND
Install the binding in the InputMap associated with JRootPane, which will
not be blown away by BasicRootPaneUI:
frame.getRootPane().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(
KeyStroke.getKeyStroke(KeyEvent.VK_ALT, Event.ALT_MASK, false),
"repaint");
This will work for apps that invoke setJMenuBar(mb).
###@###.### 2002-08-26
|