PageRenderTime 42ms CodeModel.GetById 15ms RepoModel.GetById 0ms 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
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, 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. package org.gjt.sp.jedit.gui;
  23. //{{{ Imports
  24. import java.awt.event.*;
  25. import org.gjt.sp.jedit.Debug;
  26. //}}}
  27. /**
  28. * Various hacks to get keyboard event handling to behave in a consistent manner
  29. * across Java implementations.
  30. *
  31. * @author Slava Pestov
  32. * @version $Id: KeyEventWorkaround.java 5025 2004-04-22 19:09:24Z spestov $
  33. */
  34. public class KeyEventWorkaround
  35. {
  36. //{{{ processKeyEvent() method
  37. public static KeyEvent processKeyEvent(KeyEvent evt)
  38. {
  39. int keyCode = evt.getKeyCode();
  40. char ch = evt.getKeyChar();
  41. switch(evt.getID())
  42. {
  43. //{{{ KEY_PRESSED...
  44. case KeyEvent.KEY_PRESSED:
  45. lastKeyTime = evt.getWhen();
  46. // get rid of keys we never need to handle
  47. switch(keyCode)
  48. {
  49. case KeyEvent.VK_DEAD_GRAVE:
  50. case KeyEvent.VK_DEAD_ACUTE:
  51. case KeyEvent.VK_DEAD_CIRCUMFLEX:
  52. case KeyEvent.VK_DEAD_TILDE:
  53. case KeyEvent.VK_DEAD_MACRON:
  54. case KeyEvent.VK_DEAD_BREVE:
  55. case KeyEvent.VK_DEAD_ABOVEDOT:
  56. case KeyEvent.VK_DEAD_DIAERESIS:
  57. case KeyEvent.VK_DEAD_ABOVERING:
  58. case KeyEvent.VK_DEAD_DOUBLEACUTE:
  59. case KeyEvent.VK_DEAD_CARON:
  60. case KeyEvent.VK_DEAD_CEDILLA:
  61. case KeyEvent.VK_DEAD_OGONEK:
  62. case KeyEvent.VK_DEAD_IOTA:
  63. case KeyEvent.VK_DEAD_VOICED_SOUND:
  64. case KeyEvent.VK_DEAD_SEMIVOICED_SOUND:
  65. case '\0':
  66. return null;
  67. case KeyEvent.VK_ALT:
  68. modifiers |= InputEvent.ALT_MASK;
  69. return null;
  70. case KeyEvent.VK_ALT_GRAPH:
  71. modifiers |= InputEvent.ALT_GRAPH_MASK;
  72. return null;
  73. case KeyEvent.VK_CONTROL:
  74. modifiers |= InputEvent.CTRL_MASK;
  75. return null;
  76. case KeyEvent.VK_SHIFT:
  77. modifiers |= InputEvent.SHIFT_MASK;
  78. return null;
  79. case KeyEvent.VK_META:
  80. modifiers |= InputEvent.META_MASK;
  81. return null;
  82. default:
  83. if(!evt.isMetaDown())
  84. {
  85. if(evt.isControlDown()
  86. && evt.isAltDown())
  87. {
  88. lastKeyTime = 0L;
  89. }
  90. else if(!evt.isControlDown()
  91. && !evt.isAltDown())
  92. {
  93. lastKeyTime = 0L;
  94. if(keyCode >= KeyEvent.VK_0
  95. && keyCode <= KeyEvent.VK_9)
  96. {
  97. return null;
  98. }
  99. if(keyCode >= KeyEvent.VK_A
  100. && keyCode <= KeyEvent.VK_Z)
  101. {
  102. return null;
  103. }
  104. }
  105. }
  106. if(Debug.ALT_KEY_PRESSED_DISABLED)
  107. {
  108. /* we don't handle key pressed A+ */
  109. /* they're too troublesome */
  110. if((modifiers & InputEvent.ALT_MASK) != 0)
  111. return null;
  112. }
  113. switch(keyCode)
  114. {
  115. case KeyEvent.VK_NUMPAD0:
  116. case KeyEvent.VK_NUMPAD1:
  117. case KeyEvent.VK_NUMPAD2:
  118. case KeyEvent.VK_NUMPAD3:
  119. case KeyEvent.VK_NUMPAD4:
  120. case KeyEvent.VK_NUMPAD5:
  121. case KeyEvent.VK_NUMPAD6:
  122. case KeyEvent.VK_NUMPAD7:
  123. case KeyEvent.VK_NUMPAD8:
  124. case KeyEvent.VK_NUMPAD9:
  125. case KeyEvent.VK_MULTIPLY:
  126. case KeyEvent.VK_ADD:
  127. /* case KeyEvent.VK_SEPARATOR: */
  128. case KeyEvent.VK_SUBTRACT:
  129. case KeyEvent.VK_DECIMAL:
  130. case KeyEvent.VK_DIVIDE:
  131. last = LAST_NUMKEYPAD;
  132. break;
  133. default:
  134. last = LAST_NOTHING;
  135. break;
  136. }
  137. return evt;
  138. }
  139. //}}}
  140. //{{{ KEY_TYPED...
  141. case KeyEvent.KEY_TYPED:
  142. // need to let \b through so that backspace will work
  143. // in HistoryTextFields
  144. if((ch < 0x20 || ch == 0x7f || ch == 0xff)
  145. && ch != '\b' && ch != '\t' && ch != '\n')
  146. {
  147. return null;
  148. }
  149. if(evt.getWhen() - lastKeyTime < 750)
  150. {
  151. if(!Debug.ALTERNATIVE_DISPATCHER)
  152. {
  153. if(((modifiers & InputEvent.CTRL_MASK) != 0
  154. ^ (modifiers & InputEvent.ALT_MASK) != 0)
  155. || (modifiers & InputEvent.META_MASK) != 0)
  156. {
  157. return null;
  158. }
  159. }
  160. // if the last key was a numeric keypad key
  161. // and NumLock is off, filter it out
  162. if(last == LAST_NUMKEYPAD)
  163. {
  164. last = LAST_NOTHING;
  165. if((ch >= '0' && ch <= '9') || ch == '.'
  166. || ch == '/' || ch == '*'
  167. || ch == '-' || ch == '+')
  168. {
  169. return null;
  170. }
  171. }
  172. // Windows JDK workaround
  173. else if(last == LAST_ALT)
  174. {
  175. last = LAST_NOTHING;
  176. switch(ch)
  177. {
  178. case 'B':
  179. case 'M':
  180. case 'X':
  181. case 'c':
  182. case '!':
  183. case ',':
  184. case '?':
  185. return null;
  186. }
  187. }
  188. }
  189. else
  190. {
  191. if((modifiers & InputEvent.SHIFT_MASK) != 0)
  192. {
  193. switch(ch)
  194. {
  195. case '\n':
  196. case '\t':
  197. return null;
  198. }
  199. }
  200. modifiers = 0;
  201. }
  202. return evt;
  203. //}}}
  204. //{{{ KEY_RELEASED...
  205. case KeyEvent.KEY_RELEASED:
  206. switch(keyCode)
  207. {
  208. case KeyEvent.VK_ALT:
  209. modifiers &= ~InputEvent.ALT_MASK;
  210. lastKeyTime = evt.getWhen();
  211. // we consume this to work around the bug
  212. // where A+TAB window switching activates
  213. // the menu bar on Windows.
  214. evt.consume();
  215. return null;
  216. case KeyEvent.VK_ALT_GRAPH:
  217. modifiers &= ~InputEvent.ALT_GRAPH_MASK;
  218. return null;
  219. case KeyEvent.VK_CONTROL:
  220. modifiers &= ~InputEvent.CTRL_MASK;
  221. return null;
  222. case KeyEvent.VK_SHIFT:
  223. modifiers &= ~InputEvent.SHIFT_MASK;
  224. return null;
  225. case KeyEvent.VK_META:
  226. modifiers &= ~InputEvent.META_MASK;
  227. return null;
  228. case KeyEvent.VK_LEFT:
  229. case KeyEvent.VK_RIGHT:
  230. case KeyEvent.VK_UP:
  231. case KeyEvent.VK_DOWN:
  232. case KeyEvent.VK_PAGE_UP:
  233. case KeyEvent.VK_PAGE_DOWN:
  234. case KeyEvent.VK_END:
  235. case KeyEvent.VK_HOME:
  236. /* workaround for A+keys producing
  237. * garbage on Windows */
  238. if(modifiers == InputEvent.ALT_MASK)
  239. last = LAST_ALT;
  240. break;
  241. }
  242. return evt;
  243. //}}}
  244. default:
  245. return evt;
  246. }
  247. } //}}}
  248. //{{{ numericKeypadKey() method
  249. /**
  250. * A workaround for non-working NumLock status in some Java versions.
  251. * @since jEdit 4.0pre8
  252. */
  253. public static void numericKeypadKey()
  254. {
  255. last = LAST_NOTHING;
  256. } //}}}
  257. //{{{ Package-private members
  258. static long lastKeyTime;
  259. static int modifiers;
  260. //}}}
  261. //{{{ Private members
  262. private static int last;
  263. private static final int LAST_NOTHING = 0;
  264. private static final int LAST_NUMKEYPAD = 1;
  265. private static final int LAST_ALT = 2;
  266. //}}}
  267. }