PageRenderTime 165ms CodeModel.GetById 152ms app.highlight 10ms RepoModel.GetById 1ms app.codeStats 0ms

/jEdit/tags/jedit-4-2-pre14/org/gjt/sp/jedit/gui/KeyEventWorkaround.java

#
Java | 282 lines | 207 code | 15 blank | 60 comment | 52 complexity | 6f04f4e6952022d4626adab64b60e9e7 MD5 | raw file
  1/*
  2 * KeyEventWorkaround.java - Works around bugs in Java event handling
  3 * :tabSize=8:indentSize=8:noTabs=false:
  4 * :folding=explicit:collapseFolds=1:
  5 *
  6 * Copyright (C) 2000, 2004 Slava Pestov
  7 *
  8 * This program is free software; you can redistribute it and/or
  9 * modify it under the terms of the GNU General Public License
 10 * as published by the Free Software Foundation; either version 2
 11 * of the License, or any later version.
 12 *
 13 * This program is distributed in the hope that it will be useful,
 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 16 * GNU General Public License for more details.
 17 *
 18 * You should have received a copy of the GNU General Public License
 19 * along with this program; if not, write to the Free Software
 20 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 21 */
 22
 23package org.gjt.sp.jedit.gui;
 24
 25//{{{ Imports
 26import java.awt.event.*;
 27import org.gjt.sp.jedit.Debug;
 28//}}}
 29
 30/**
 31 * Various hacks to get keyboard event handling to behave in a consistent manner
 32 * across Java implementations.
 33 *
 34 * @author Slava Pestov
 35 * @version $Id: KeyEventWorkaround.java 5025 2004-04-22 19:09:24Z spestov $
 36 */
 37public class KeyEventWorkaround
 38{
 39	//{{{ processKeyEvent() method
 40	public static KeyEvent processKeyEvent(KeyEvent evt)
 41	{
 42		int keyCode = evt.getKeyCode();
 43		char ch = evt.getKeyChar();
 44
 45		switch(evt.getID())
 46		{
 47		//{{{ KEY_PRESSED...
 48		case KeyEvent.KEY_PRESSED:
 49			lastKeyTime = evt.getWhen();
 50			// get rid of keys we never need to handle
 51			switch(keyCode)
 52			{
 53			case KeyEvent.VK_DEAD_GRAVE:
 54			case KeyEvent.VK_DEAD_ACUTE:
 55			case KeyEvent.VK_DEAD_CIRCUMFLEX:
 56			case KeyEvent.VK_DEAD_TILDE:
 57			case KeyEvent.VK_DEAD_MACRON:
 58			case KeyEvent.VK_DEAD_BREVE:
 59			case KeyEvent.VK_DEAD_ABOVEDOT:
 60			case KeyEvent.VK_DEAD_DIAERESIS:
 61			case KeyEvent.VK_DEAD_ABOVERING:
 62			case KeyEvent.VK_DEAD_DOUBLEACUTE:
 63			case KeyEvent.VK_DEAD_CARON:
 64			case KeyEvent.VK_DEAD_CEDILLA:
 65			case KeyEvent.VK_DEAD_OGONEK:
 66			case KeyEvent.VK_DEAD_IOTA:
 67			case KeyEvent.VK_DEAD_VOICED_SOUND:
 68			case KeyEvent.VK_DEAD_SEMIVOICED_SOUND:
 69			case '\0':
 70				return null;
 71			case KeyEvent.VK_ALT:
 72				modifiers |= InputEvent.ALT_MASK;
 73				return null;
 74			case KeyEvent.VK_ALT_GRAPH:
 75				modifiers |= InputEvent.ALT_GRAPH_MASK;
 76				return null;
 77			case KeyEvent.VK_CONTROL:
 78				modifiers |= InputEvent.CTRL_MASK;
 79				return null;
 80			case KeyEvent.VK_SHIFT:
 81				modifiers |= InputEvent.SHIFT_MASK;
 82				return null;
 83			case KeyEvent.VK_META:
 84				modifiers |= InputEvent.META_MASK;
 85				return null;
 86			default:
 87				if(!evt.isMetaDown())
 88				{
 89					if(evt.isControlDown()
 90						&& evt.isAltDown())
 91					{
 92						lastKeyTime = 0L;
 93					}
 94					else if(!evt.isControlDown()
 95						&& !evt.isAltDown())
 96					{
 97						lastKeyTime = 0L;
 98
 99						if(keyCode >= KeyEvent.VK_0
100							&& keyCode <= KeyEvent.VK_9)
101						{
102							return null;
103						}
104
105						if(keyCode >= KeyEvent.VK_A
106							&& keyCode <= KeyEvent.VK_Z)
107						{
108							return null;
109						}
110					}
111				}
112
113				if(Debug.ALT_KEY_PRESSED_DISABLED)
114				{
115					/* we don't handle key pressed A+ */
116					/* they're too troublesome */
117					if((modifiers & InputEvent.ALT_MASK) != 0)
118						return null;
119				}
120
121				switch(keyCode)
122				{
123				case KeyEvent.VK_NUMPAD0:
124				case KeyEvent.VK_NUMPAD1:
125				case KeyEvent.VK_NUMPAD2:
126				case KeyEvent.VK_NUMPAD3:
127				case KeyEvent.VK_NUMPAD4:
128				case KeyEvent.VK_NUMPAD5:
129				case KeyEvent.VK_NUMPAD6:
130				case KeyEvent.VK_NUMPAD7:
131				case KeyEvent.VK_NUMPAD8:
132				case KeyEvent.VK_NUMPAD9:
133				case KeyEvent.VK_MULTIPLY:
134				case KeyEvent.VK_ADD:
135				/* case KeyEvent.VK_SEPARATOR: */
136				case KeyEvent.VK_SUBTRACT:
137				case KeyEvent.VK_DECIMAL:
138				case KeyEvent.VK_DIVIDE:
139					last = LAST_NUMKEYPAD;
140					break;
141				default:
142					last = LAST_NOTHING;
143					break;
144				}
145
146				return evt;
147			}
148		//}}}
149		//{{{ KEY_TYPED...
150		case KeyEvent.KEY_TYPED:
151			// need to let \b through so that backspace will work
152			// in HistoryTextFields
153			if((ch < 0x20 || ch == 0x7f || ch == 0xff)
154				&& ch != '\b' && ch != '\t' && ch != '\n')
155			{
156				return null;
157			}
158
159			if(evt.getWhen() - lastKeyTime < 750)
160			{
161				if(!Debug.ALTERNATIVE_DISPATCHER)
162				{
163					if(((modifiers & InputEvent.CTRL_MASK) != 0
164						^ (modifiers & InputEvent.ALT_MASK) != 0)
165						|| (modifiers & InputEvent.META_MASK) != 0)
166					{
167						return null;
168					}
169				}
170
171				// if the last key was a numeric keypad key
172				// and NumLock is off, filter it out
173				if(last == LAST_NUMKEYPAD)
174				{
175					last = LAST_NOTHING;
176					if((ch >= '0' && ch <= '9') || ch == '.'
177						|| ch == '/' || ch == '*'
178						|| ch == '-' || ch == '+')
179					{
180						return null;
181					}
182				}
183				// Windows JDK workaround
184				else if(last == LAST_ALT)
185				{
186					last = LAST_NOTHING;
187					switch(ch)
188					{
189					case 'B':
190					case 'M':
191					case 'X':
192					case 'c':
193					case '!':
194					case ',':
195					case '?':
196						return null;
197					}
198				}
199			}
200			else
201			{
202				if((modifiers & InputEvent.SHIFT_MASK) != 0)
203				{
204					switch(ch)
205					{
206					case '\n':
207					case '\t':
208						return null;
209					}
210				}
211				modifiers = 0;
212			}
213
214			return evt;
215		//}}}
216		//{{{ KEY_RELEASED...
217		case KeyEvent.KEY_RELEASED:
218			switch(keyCode)
219			{
220			case KeyEvent.VK_ALT:
221				modifiers &= ~InputEvent.ALT_MASK;
222				lastKeyTime = evt.getWhen();
223				// we consume this to work around the bug
224				// where A+TAB window switching activates
225				// the menu bar on Windows.
226				evt.consume();
227				return null;
228			case KeyEvent.VK_ALT_GRAPH:
229				modifiers &= ~InputEvent.ALT_GRAPH_MASK;
230				return null;
231			case KeyEvent.VK_CONTROL:
232				modifiers &= ~InputEvent.CTRL_MASK;
233				return null;
234			case KeyEvent.VK_SHIFT:
235				modifiers &= ~InputEvent.SHIFT_MASK;
236				return null;
237			case KeyEvent.VK_META:
238				modifiers &= ~InputEvent.META_MASK;
239				return null;
240			case KeyEvent.VK_LEFT:
241			case KeyEvent.VK_RIGHT:
242			case KeyEvent.VK_UP:
243			case KeyEvent.VK_DOWN:
244			case KeyEvent.VK_PAGE_UP:
245			case KeyEvent.VK_PAGE_DOWN:
246			case KeyEvent.VK_END:
247			case KeyEvent.VK_HOME:
248				/* workaround for A+keys producing
249				 * garbage on Windows */
250				if(modifiers == InputEvent.ALT_MASK)
251					last = LAST_ALT;
252				break;
253			}
254			return evt;
255		//}}}
256		default:
257			return evt;
258		}
259	} //}}}
260
261	//{{{ numericKeypadKey() method
262	/**
263	 * A workaround for non-working NumLock status in some Java versions.
264	 * @since jEdit 4.0pre8
265	 */
266	public static void numericKeypadKey()
267	{
268		last = LAST_NOTHING;
269	} //}}}
270
271	//{{{ Package-private members
272	static long lastKeyTime;
273	static int modifiers;
274	//}}}
275
276	//{{{ Private members
277	private static int last;
278	private static final int LAST_NOTHING = 0;
279	private static final int LAST_NUMKEYPAD = 1;
280	private static final int LAST_ALT = 2;
281	//}}}
282}