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