1 19 20 package org.netbeans.core.windows; 21 22 import java.util.Collections ; 23 import java.util.Set ; 24 import org.netbeans.core.NbKeymap; 25 import org.netbeans.core.windows.view.ui.KeyboardPopupSwitcher; 26 import org.openide.actions.ActionManager; 27 import org.openide.awt.StatusDisplayer; 28 import org.openide.util.Lookup; 29 import org.openide.util.Utilities; 30 31 import javax.swing.*; 32 import javax.swing.text.Keymap ; 33 import java.awt.*; 34 import java.awt.event.ActionEvent ; 35 import java.awt.event.InputEvent ; 36 import java.awt.event.KeyEvent ; 37 import java.lang.reflect.Method ; 38 import org.netbeans.core.NbTopManager; 39 40 41 49 final class ShortcutAndMenuKeyEventProcessor implements KeyEventDispatcher, KeyEventPostProcessor { 50 51 private static ShortcutAndMenuKeyEventProcessor defaultInstance; 52 53 private static boolean installed = false; 54 55 56 private static Set <AWTKeyStroke> defaultForward; 57 58 private static Set <AWTKeyStroke> defaultBackward; 59 60 61 private ShortcutAndMenuKeyEventProcessor() { 62 } 63 64 65 private static synchronized ShortcutAndMenuKeyEventProcessor getDefault() { 66 if(defaultInstance == null) { 67 defaultInstance = new ShortcutAndMenuKeyEventProcessor(); 68 } 69 70 return defaultInstance; 71 } 72 73 74 public static synchronized void install() { 75 if(installed) { 76 return; 77 } 78 79 ShortcutAndMenuKeyEventProcessor instance = getDefault(); 80 81 KeyboardFocusManager keyboardFocusManager = KeyboardFocusManager.getCurrentKeyboardFocusManager(); 82 keyboardFocusManager.addKeyEventDispatcher(instance); 83 keyboardFocusManager.addKeyEventPostProcessor(instance); 84 defaultForward = keyboardFocusManager.getDefaultFocusTraversalKeys( 87 KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS); 88 defaultBackward = keyboardFocusManager.getDefaultFocusTraversalKeys( 89 KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS); 90 keyboardFocusManager.setDefaultFocusTraversalKeys( 91 KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, 92 Collections.singleton(AWTKeyStroke.getAWTKeyStroke(KeyEvent.VK_TAB, 0)) 93 ); 94 keyboardFocusManager.setDefaultFocusTraversalKeys( 95 KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS, 96 Collections.singleton(AWTKeyStroke.getAWTKeyStroke(KeyEvent.VK_TAB, KeyEvent.SHIFT_DOWN_MASK)) 97 ); 98 } 99 100 public static synchronized void uninstall() { 101 if(!installed) { 102 return; 103 } 104 105 ShortcutAndMenuKeyEventProcessor instance = getDefault(); 106 107 KeyboardFocusManager keyboardFocusManager = KeyboardFocusManager.getCurrentKeyboardFocusManager(); 108 keyboardFocusManager.removeKeyEventDispatcher(instance); 109 keyboardFocusManager.removeKeyEventPostProcessor(instance); 110 keyboardFocusManager.setDefaultFocusTraversalKeys( 112 KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, defaultForward 113 ); 114 keyboardFocusManager.setDefaultFocusTraversalKeys( 115 KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS, defaultBackward 116 ); 117 defaultBackward = null; 118 defaultForward = null; 119 } 120 121 private boolean wasPopupDisplayed; 122 private int lastModifiers; 123 private char lastKeyChar; 124 private boolean lastSampled = false; 125 private boolean skipNextTyped = false; 126 127 public boolean postProcessKeyEvent(KeyEvent ev) { 128 if (ev.isConsumed()) 129 return false; 130 131 if (processShortcut(ev)) 132 return true; 133 134 Window w = SwingUtilities.windowForComponent(ev.getComponent()); 135 if (w instanceof Dialog && !WindowManagerImpl.isSeparateWindow(w)) 136 return false; 137 138 JFrame mw = (JFrame)WindowManagerImpl.getInstance().getMainWindow(); 139 if (w == mw) { 140 return false; 141 } 142 143 JMenuBar mb = mw.getJMenuBar(); 144 if (mb == null) 145 return false; 146 boolean pressed = (ev.getID() == KeyEvent.KEY_PRESSED); 147 boolean res = invokeProcessKeyBindingsForAllComponents(ev, mw, pressed); 148 149 if (res) 150 ev.consume(); 151 return res; 152 } 153 154 public boolean dispatchKeyEvent(KeyEvent ev) { 155 if (Utilities.getOperatingSystem() == Utilities.OS_LINUX) { 159 int mods = ev.getModifiers(); 160 if (mods == InputEvent.META_MASK) { 161 mods = (mods & ~ InputEvent.META_MASK) | InputEvent.ALT_MASK; 162 ev.setModifiers(mods); 163 } 164 } 165 166 if (NbKeymap.getContext().length != 0) { 168 if (ev.getID() != KeyEvent.KEY_PRESSED) { 170 ev.consume(); 171 return true; 172 } 173 174 skipNextTyped = true; 175 176 Component comp = ev.getComponent(); 177 if (!(comp instanceof JComponent) || 178 ((JComponent)comp).getClientProperty("context-api-aware") == null) { 179 processShortcut(ev); 181 return true; 183 } 184 } 185 186 if (ev.getID() == KeyEvent.KEY_PRESSED 187 && ev.getModifiers() == (InputEvent.CTRL_MASK | InputEvent.SHIFT_MASK) 188 && (ev.getKeyCode() == KeyEvent.VK_PAUSE 189 || ev.getKeyCode() == KeyEvent.VK_CANCEL) 190 ) { 191 Object source = ev.getSource(); 192 if (source instanceof Component) { 193 Component focused = KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner(); 194 System.err.println("*** ShortcutAndMenuKeyEventProcessor: current focus owner = " + focused); } 196 ev.consume(); 197 return true; 198 } 199 200 201 if (ev.getID() == KeyEvent.KEY_TYPED && skipNextTyped) { 203 ev.consume(); 204 skipNextTyped = false; 205 return true; 206 } 207 208 if (ev.getID() == KeyEvent.KEY_RELEASED) { 209 skipNextTyped = false; 210 } 211 212 if (ev.getID() == KeyEvent.KEY_PRESSED) { 213 lastKeyChar = ev.getKeyChar(); 215 lastModifiers = ev.getModifiers(); 216 lastSampled = true; 217 } 218 219 MenuElement[] arr = MenuSelectionManager.defaultManager().getSelectedPath(); 220 if (arr == null || arr.length == 0) { 221 wasPopupDisplayed = false; 222 223 232 if (Utilities.isWindows() 233 && ev.getModifiers() == InputEvent.SHIFT_MASK 234 && ev.getKeyCode() == KeyEvent.VK_F10 235 ) { 236 return processShortcut(ev); 237 } 238 239 return KeyboardPopupSwitcher.processShortcut(ev); 246 } 247 248 if (!wasPopupDisplayed 249 && lastSampled == true 250 && ev.getID() == KeyEvent.KEY_TYPED 251 && lastModifiers == InputEvent.ALT_MASK 252 && ev.getModifiers() == InputEvent.ALT_MASK 253 && lastKeyChar == ev.getKeyChar() 254 ) { 255 wasPopupDisplayed = true; 256 ev.consume(); 257 return true; 258 } 259 260 wasPopupDisplayed = true; 261 262 MenuSelectionManager.defaultManager().processKeyEvent(ev); 263 264 if (!ev.isConsumed() && arr[0] instanceof JMenuBar) { 265 ev.setSource(WindowManagerImpl.getInstance().getMainWindow()); 266 } 267 return ev.isConsumed(); 268 } 269 270 private boolean processShortcut(KeyEvent ev) { 271 if( NbTopManager.get().isExiting() ) { 273 ev.consume(); 274 return true; 275 } 276 277 KeyStroke ks = KeyStroke.getKeyStrokeForEvent(ev); 278 Window w = SwingUtilities.windowForComponent(ev.getComponent()); 279 280 if ((w instanceof JFrame) && ((JFrame)w).getRootPane().getClientProperty("netbeans.helpframe") != null) return true; 283 284 if ((w instanceof Dialog) && 288 !WindowManagerImpl.getInstance().isSeparateWindow(w) && 289 !isTransmodalAction(ks)) { 290 return false; 291 } 292 293 ActionEvent aev = new ActionEvent ( 296 ev.getSource(), ActionEvent.ACTION_PERFORMED, Utilities.keyToString(ks)); 297 298 Keymap root = (Keymap)Lookup.getDefault().lookup(Keymap.class); 299 Action a = root.getAction (ks); 300 if (a != null && a.isEnabled()) { 301 ActionManager am = (ActionManager)Lookup.getDefault().lookup(ActionManager.class); 302 am.invokeAction(a, aev); 303 ev.consume(); 304 return true; 305 } 306 return false; 307 } 308 309 private static boolean invokeProcessKeyBindingsForAllComponents( 310 KeyEvent e, Container container, boolean pressed) 311 { 312 try { 313 Method m = JComponent.class.getDeclaredMethod( 314 "processKeyBindingsForAllComponents", new Class [] { KeyEvent .class, Container.class, Boolean.TYPE }); 316 if (m == null) 317 return false; 318 319 m.setAccessible(true); 320 Boolean b = (Boolean ) m.invoke(null, new Object [] { e, container, pressed ? Boolean.TRUE : Boolean.FALSE }); 321 return b.booleanValue(); 322 } catch (Exception ex) { 323 } 325 326 return false; 327 } 328 329 340 private static boolean isTransmodalAction (KeyStroke key) { 341 Keymap root = (Keymap)Lookup.getDefault().lookup(Keymap.class); 342 Action a = root.getAction (key); 343 if (a == null) return false; 344 Object val = a.getValue ("OpenIDE-Transmodal-Action"); return val != null && val.equals (Boolean.TRUE); 346 } 347 348 } 349 | Popular Tags |