1 /* 2 * Copyright (c) 2000, 2006, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package com.sun.java.swing.plaf.windows; 27 28 import java.awt.Component; 29 import java.awt.Container; 30 import java.awt.Event; 31 import java.awt.KeyEventPostProcessor; 32 import java.awt.Window; 33 import java.awt.Toolkit; 34 35 import sun.awt.AWTAccessor; 36 import sun.awt.SunToolkit; 37 38 import java.awt.event.ActionEvent; 39 import java.awt.event.KeyEvent; 40 41 import javax.swing.AbstractAction; 42 import javax.swing.ActionMap; 43 import javax.swing.InputMap; 44 import javax.swing.KeyStroke; 45 import javax.swing.JComponent; 46 import javax.swing.JLabel; 47 import javax.swing.JRootPane; 48 import javax.swing.SwingUtilities; 49 import javax.swing.UIManager; 50 import javax.swing.AbstractButton; 51 import javax.swing.JFrame; 52 import javax.swing.JMenu; 53 import javax.swing.JMenuBar; 54 import javax.swing.MenuElement; 55 import javax.swing.MenuSelectionManager; 56 57 import javax.swing.plaf.ActionMapUIResource; 58 import javax.swing.plaf.ComponentUI; 59 import javax.swing.plaf.InputMapUIResource; 60 61 import javax.swing.plaf.basic.BasicRootPaneUI; 62 import javax.swing.plaf.basic.ComboPopup; 63 64 /** 65 * Windows implementation of RootPaneUI, there is one shared between all 66 * JRootPane instances. 67 * 68 * @author Mark Davidson 69 * @since 1.4 70 */ 71 public class WindowsRootPaneUI extends BasicRootPaneUI { 72 73 private final static WindowsRootPaneUI windowsRootPaneUI = new WindowsRootPaneUI(); 74 static final AltProcessor altProcessor = new AltProcessor(); 75 76 public static ComponentUI createUI(JComponent c) { 77 return windowsRootPaneUI; 78 } 79 80 static class AltProcessor implements KeyEventPostProcessor { 81 static boolean altKeyPressed = false; 82 static boolean menuCanceledOnPress = false; 83 static JRootPane root = null; 84 static Window winAncestor = null; 85 86 void altPressed(KeyEvent ev) { 87 MenuSelectionManager msm = 88 MenuSelectionManager.defaultManager(); 89 MenuElement[] path = msm.getSelectedPath(); 90 if (path.length > 0 && ! (path[0] instanceof ComboPopup)) { 91 msm.clearSelectedPath(); 92 menuCanceledOnPress = true; 93 ev.consume(); 94 } else if(path.length > 0) { // We are in ComboBox 95 menuCanceledOnPress = false; 96 WindowsLookAndFeel.setMnemonicHidden(false); 97 WindowsGraphicsUtils.repaintMnemonicsInWindow(winAncestor); 98 ev.consume(); 99 } else { 100 menuCanceledOnPress = false; 101 WindowsLookAndFeel.setMnemonicHidden(false); 102 WindowsGraphicsUtils.repaintMnemonicsInWindow(winAncestor); 103 JMenuBar mbar = root != null ? root.getJMenuBar() : null; 104 if(mbar == null && winAncestor instanceof JFrame) { 105 mbar = ((JFrame)winAncestor).getJMenuBar(); 106 } 107 JMenu menu = mbar != null ? mbar.getMenu(0) : null; 108 if(menu != null) { 109 ev.consume(); 110 } 111 } 112 } 113 114 void altReleased(KeyEvent ev) { 115 if (menuCanceledOnPress) { 116 WindowsLookAndFeel.setMnemonicHidden(true); 117 WindowsGraphicsUtils.repaintMnemonicsInWindow(winAncestor); 118 return; 119 } 120 121 MenuSelectionManager msm = 122 MenuSelectionManager.defaultManager(); 123 if (msm.getSelectedPath().length == 0) { 124 // if no menu is active, we try activating the menubar 125 126 JMenuBar mbar = root != null ? root.getJMenuBar() : null; 127 if(mbar == null && winAncestor instanceof JFrame) { 128 mbar = ((JFrame)winAncestor).getJMenuBar(); 129 } 130 JMenu menu = mbar != null ? mbar.getMenu(0) : null; 131 132 // It might happen that the altRelease event is processed 133 // with a reasonable delay since it has been generated. 134 // Here we check the last deactivation time of the containing 135 // window. If this time appears to be greater than the altRelease 136 // event time the event is skipped to avoid unexpected menu 137 // activation. See 7121442. 138 boolean skip = false; 139 Toolkit tk = Toolkit.getDefaultToolkit(); 140 if (tk instanceof SunToolkit) { 141 skip = ev.getWhen() <= ((SunToolkit)tk).getWindowDeactivationTime(winAncestor); 142 } 143 // We must insure that original source of key event belongs to the same window object as winAncestor. 144 if (!skip) { 145 Component originalSource = AWTAccessor.getKeyEventAccessor() 146 .getOriginalSource(ev); 147 skip = !(originalSource == winAncestor || 148 SwingUtilities.getWindowAncestor(originalSource) == winAncestor); 149 } 150 151 if (menu != null && !skip) { 152 MenuElement[] path = new MenuElement[2]; 153 path[0] = mbar; 154 path[1] = menu; 155 msm.setSelectedPath(path); 156 } else if(!WindowsLookAndFeel.isMnemonicHidden()) { 157 WindowsLookAndFeel.setMnemonicHidden(true); 158 WindowsGraphicsUtils.repaintMnemonicsInWindow(winAncestor); 159 } 160 } else { 161 if((msm.getSelectedPath())[0] instanceof ComboPopup) { 162 WindowsLookAndFeel.setMnemonicHidden(true); 163 WindowsGraphicsUtils.repaintMnemonicsInWindow(winAncestor); 164 } 165 } 166 167 } 168 169 public boolean postProcessKeyEvent(KeyEvent ev) { 170 if(ev.isConsumed()) { 171 // do not manage consumed event 172 return false; 173 } 174 if (ev.getKeyCode() == KeyEvent.VK_ALT) { 175 root = SwingUtilities.getRootPane(ev.getComponent()); 176 winAncestor = (root == null ? null : 177 SwingUtilities.getWindowAncestor(root)); 178 179 if (ev.getID() == KeyEvent.KEY_PRESSED) { 180 if (!altKeyPressed) { 181 altPressed(ev); 182 } 183 altKeyPressed = true; 184 return true; 185 } else if (ev.getID() == KeyEvent.KEY_RELEASED) { 186 if (altKeyPressed) { 187 altReleased(ev); 188 } else { 189 MenuSelectionManager msm = 190 MenuSelectionManager.defaultManager(); 191 MenuElement[] path = msm.getSelectedPath(); 192 if (path.length <= 0) { 193 WindowsLookAndFeel.setMnemonicHidden(true); 194 WindowsGraphicsUtils.repaintMnemonicsInWindow(winAncestor); 195 } 196 } 197 altKeyPressed = false; 198 } 199 root = null; 200 winAncestor = null; 201 } else { 202 altKeyPressed = false; 203 } 204 return false; 205 } 206 } 207 }