PageRenderTime 174ms CodeModel.GetById 154ms app.highlight 15ms RepoModel.GetById 2ms app.codeStats 0ms

/jEdit/tags/jedit-4-1-pre5/org/gjt/sp/jedit/gui/KeyEventWorkaround.java

#
Java | 251 lines | 169 code | 19 blank | 63 comment | 53 complexity | cfcb91b4929b4f469be7adf589963b12 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, 2001, 2002 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 java.awt.*;
 28import org.gjt.sp.jedit.OperatingSystem;
 29//}}}
 30
 31/**
 32 * This class contains various hacks to get keyboard event handling to behave in
 33 * a consistent manner across Java implementations, many of which are
 34 * hopelessly broken in this regard.
 35 *
 36 * @author Slava Pestov
 37 * @version $Id: KeyEventWorkaround.java 4117 2002-03-28 04:08:42Z spestov $
 38 */
 39public class KeyEventWorkaround
 40{
 41	//{{{ processKeyEvent() method
 42	public static KeyEvent processKeyEvent(KeyEvent evt)
 43	{
 44		int keyCode = evt.getKeyCode();
 45		char ch = evt.getKeyChar();
 46
 47		switch(evt.getID())
 48		{
 49		//{{{ KEY_PRESSED...
 50		case KeyEvent.KEY_PRESSED:
 51			// get rid of keys we never need to handle
 52			switch(keyCode)
 53			{
 54			case KeyEvent.VK_ALT:
 55			case KeyEvent.VK_ALT_GRAPH:
 56			case KeyEvent.VK_CONTROL:
 57			case KeyEvent.VK_SHIFT:
 58			case KeyEvent.VK_META:
 59			case KeyEvent.VK_DEAD_GRAVE:
 60			case KeyEvent.VK_DEAD_ACUTE:
 61			case KeyEvent.VK_DEAD_CIRCUMFLEX:
 62			case KeyEvent.VK_DEAD_TILDE:
 63			case KeyEvent.VK_DEAD_MACRON:
 64			case KeyEvent.VK_DEAD_BREVE:
 65			case KeyEvent.VK_DEAD_ABOVEDOT:
 66			case KeyEvent.VK_DEAD_DIAERESIS:
 67			case KeyEvent.VK_DEAD_ABOVERING:
 68			case KeyEvent.VK_DEAD_DOUBLEACUTE:
 69			case KeyEvent.VK_DEAD_CARON:
 70			case KeyEvent.VK_DEAD_CEDILLA:
 71			case KeyEvent.VK_DEAD_OGONEK:
 72			case KeyEvent.VK_DEAD_IOTA:
 73			case KeyEvent.VK_DEAD_VOICED_SOUND:
 74			case KeyEvent.VK_DEAD_SEMIVOICED_SOUND:
 75			case '\0':
 76				return null;
 77			default:
 78				switch(keyCode)
 79				{
 80					case KeyEvent.VK_NUMPAD0:   case KeyEvent.VK_NUMPAD1:
 81					case KeyEvent.VK_NUMPAD2:   case KeyEvent.VK_NUMPAD3:
 82					case KeyEvent.VK_NUMPAD4:   case KeyEvent.VK_NUMPAD5:
 83					case KeyEvent.VK_NUMPAD6:   case KeyEvent.VK_NUMPAD7:
 84					case KeyEvent.VK_NUMPAD8:   case KeyEvent.VK_NUMPAD9:
 85					case KeyEvent.VK_MULTIPLY:  case KeyEvent.VK_ADD:
 86					/* case KeyEvent.VK_SEPARATOR: */ case KeyEvent.VK_SUBTRACT:
 87					case KeyEvent.VK_DECIMAL:   case KeyEvent.VK_DIVIDE:
 88						last = LAST_NUMKEYPAD;
 89						lastKeyTime = System.currentTimeMillis();
 90						return evt;
 91				}
 92
 93				if(!OperatingSystem.isMacOS())
 94					handleBrokenKeys(evt,keyCode);
 95				else
 96					last = LAST_NOTHING;
 97				break;
 98			}
 99
100			return evt;
101		//}}}
102		//{{{ KEY_TYPED...
103		case KeyEvent.KEY_TYPED:
104			// need to let \b through so that backspace will work
105			// in HistoryTextFields
106			if((ch < 0x20 || ch == 0x7f || ch == 0xff) && ch != '\b')
107				return null;
108
109			// "Alt" is the option key on MacOS, and it can generate
110			// user input
111			if(OperatingSystem.isMacOS())
112			{
113				if(evt.isControlDown() || evt.isMetaDown())
114					return null;
115			}
116			else
117			{
118				if((evt.isControlDown() ^ evt.isAltDown())
119					|| evt.isMetaDown())
120					return null;
121			}
122
123			// On JDK 1.4 with Windows, some Alt-key sequences send
124			// bullshit in a KEY_TYPED afterwards. We filter it out
125			// here
126			if(last == LAST_MOD)
127			{
128				switch(ch)
129				{
130				case 'B':
131				case 'M':
132				case 'X':
133				case 'c':
134				case '!':
135				case ',':
136				case '?':
137					last = LAST_NOTHING;
138					return null;
139				}
140			}
141
142			// if the last key was a numeric keypad key
143			// and NumLock is off, filter it out
144			if(last == LAST_NUMKEYPAD && System.currentTimeMillis()
145				- lastKeyTime < 750)
146			{
147				last = LAST_NOTHING;
148				if((ch >= '0' && ch <= '9') || ch == '.'
149					|| ch == '/' || ch == '*'
150					|| ch == '-' || ch == '+')
151				{
152					return null;
153				}
154			}
155			// if the last key was a broken key, filter
156			// out all except 'a'-'z' that occur 750 ms after.
157			else if(last == LAST_BROKEN && System.currentTimeMillis()
158				- lastKeyTime < 750 && !Character.isLetter(ch))
159			{
160				last = LAST_NOTHING;
161				return null;
162			}
163			// otherwise, if it was ALT, filter out everything.
164			else if(last == LAST_ALT && System.currentTimeMillis()
165				- lastKeyTime < 750)
166			{
167				last = LAST_NOTHING;
168				return null;
169			}
170
171			return evt;
172		//}}}
173		//{{{ KEY_RELEASED...
174		case KeyEvent.KEY_RELEASED:
175			if(keyCode == KeyEvent.VK_ALT)
176			{
177				// bad workaround... on Windows JDK 1.4, some
178				// Alt-sequences generate random crap afterwards
179				if(OperatingSystem.isWindows()
180					&& OperatingSystem.hasJava14())
181					last = LAST_MOD;
182			}
183			return evt;
184		//}}}
185		default:
186			return evt;
187		}
188	} //}}}
189
190	//{{{ numericKeypadKey() method
191	/**
192	 * A workaround for non-working NumLock status in some Java versions.
193	 * @since jEdit 4.0pre8
194	 */
195	public static void numericKeypadKey()
196	{
197		last = LAST_NOTHING;
198	} //}}}
199
200	//{{{ Private members
201
202	//{{{ Static variables
203	private static long lastKeyTime;
204
205	private static int last;
206	private static final int LAST_NOTHING = 0;
207	private static final int LAST_ALT = 1;
208	private static final int LAST_BROKEN = 2;
209	private static final int LAST_NUMKEYPAD = 3;
210	private static final int LAST_MOD = 4;
211	//}}}
212
213	//{{{ handleBrokenKeys() method
214	private static void handleBrokenKeys(KeyEvent evt, int keyCode)
215	{
216		if(evt.isAltDown() && evt.isControlDown()
217			&& !evt.isMetaDown())
218		{
219			last = LAST_NOTHING;
220			return;
221		}
222		else if(!(evt.isAltDown() || evt.isControlDown() || evt.isMetaDown()))
223		{
224			last = LAST_NOTHING;
225			return;
226		}
227
228		if(evt.isAltDown())
229			last = LAST_ALT;
230
231		switch(keyCode)
232		{
233			case KeyEvent.VK_LEFT:      case KeyEvent.VK_RIGHT:
234			case KeyEvent.VK_UP:        case KeyEvent.VK_DOWN:
235			case KeyEvent.VK_DELETE:    case KeyEvent.VK_BACK_SPACE:
236			case KeyEvent.VK_TAB:       case KeyEvent.VK_ENTER:
237				last = LAST_NOTHING;
238				break;
239			default:
240				if(keyCode < KeyEvent.VK_A || keyCode > KeyEvent.VK_Z)
241					last = LAST_BROKEN;
242				else
243					last = LAST_NOTHING;
244				break;
245		}
246
247		lastKeyTime = System.currentTimeMillis();
248	} //}}}
249
250	//}}}
251}