Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: org/gjt/sp/jedit/gui/KeyEventWorkaround.java


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  
23  package org.gjt.sp.jedit.gui;
24  
25  //{{{ Imports
26  import java.awt.event.*;
27  import java.awt.*;
28  import 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,v 1.3 2002/10/25 17:29:57 gfx Exp $
38   */
39  public 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  
79          if(!OperatingSystem.isMacOS())
80            handleBrokenKeys(evt,keyCode);
81          else
82            last = LAST_NOTHING;
83          break;
84        }
85  
86        return evt;
87      //}}}
88      //{{{ KEY_TYPED...
89      case KeyEvent.KEY_TYPED:
90        // need to let \b through so that backspace will work
91        // in HistoryTextFields
92        if((ch < 0x20 || ch == 0x7f || ch == 0xff) && ch != '\b')
93          return null;
94  
95        // "Alt" is the option key on MacOS, and it can generate
96        // user input
97        if(OperatingSystem.isMacOS())
98        {
99          if(evt.isControlDown() || evt.isMetaDown())
100           return null;
101       }
102       else
103       {
104         if((evt.isControlDown() ^ evt.isAltDown())
105           || evt.isMetaDown())
106           return null;
107       }
108 
109       // On JDK 1.4 with Windows, some Alt-key sequences send
110       // bullshit in a KEY_TYPED afterwards. We filter it out
111       // here
112       if(last == LAST_MOD)
113       {
114         switch(ch)
115         {
116         case 'B':
117         case 'M':
118         case 'X':
119         case 'c':
120         case '!':
121         case ',':
122         case '?':
123           last = LAST_NOTHING;
124           return null;
125         }
126       }
127 
128       // if the last key was a broken key, filter
129       // out all except 'a'-'z' that occur 750 ms after.
130       else if(last == LAST_BROKEN && System.currentTimeMillis()
131         - lastKeyTime < 750 && !Character.isLetter(ch))
132       {
133         last = LAST_NOTHING;
134         return null;
135       }
136       // otherwise, if it was ALT, filter out everything.
137       else if(last == LAST_ALT && System.currentTimeMillis()
138         - lastKeyTime < 750)
139       {
140         last = LAST_NOTHING;
141         return null;
142       }
143 
144       return evt;
145     //}}}
146     //{{{ KEY_RELEASED...
147     case KeyEvent.KEY_RELEASED:
148       if(keyCode == KeyEvent.VK_ALT)
149       {
150         // bad workaround... on Windows JDK 1.4, some
151         // Alt-sequences generate random crap afterwards
152         if(OperatingSystem.isWindows()
153           && OperatingSystem.hasJava14())
154           last = LAST_MOD;
155       }
156       return evt;
157     //}}}
158     default:
159       return evt;
160     }
161   } //}}}
162 
163   //{{{ numericKeypadKey() method
164   /**
165    * A workaround for non-working NumLock status in some Java versions.
166    * @since jEdit 4.0pre8
167    */
168   public static void numericKeypadKey()
169   {
170     last = LAST_NOTHING;
171   } //}}}
172 
173   //{{{ Private members
174 
175   //{{{ Static variables
176   private static long lastKeyTime;
177 
178   private static int last;
179   private static final int LAST_NOTHING = 0;
180   private static final int LAST_ALT = 1;
181   private static final int LAST_BROKEN = 2;
182   private static final int LAST_NUMKEYPAD = 3;
183   private static final int LAST_MOD = 4;
184   //}}}
185 
186   //{{{ handleBrokenKeys() method
187   private static void handleBrokenKeys(KeyEvent evt, int keyCode)
188   {
189     if(evt.isAltDown() && evt.isControlDown()
190       && !evt.isMetaDown())
191     {
192       last = LAST_NOTHING;
193       return;
194     }
195     else if(!(evt.isAltDown() || evt.isControlDown() || evt.isMetaDown()))
196     {
197       last = LAST_NOTHING;
198       return;
199     }
200 
201     if(evt.isAltDown())
202       last = LAST_ALT;
203 
204     switch(keyCode)
205     {
206       case KeyEvent.VK_LEFT:      case KeyEvent.VK_RIGHT:
207       case KeyEvent.VK_UP:        case KeyEvent.VK_DOWN:
208       case KeyEvent.VK_DELETE:    case KeyEvent.VK_BACK_SPACE:
209       case KeyEvent.VK_TAB:       case KeyEvent.VK_ENTER:
210         last = LAST_NOTHING;
211         break;
212       default:
213         if(keyCode < KeyEvent.VK_A || keyCode > KeyEvent.VK_Z)
214           last = LAST_BROKEN;
215         else
216           last = LAST_NOTHING;
217         break;
218     }
219 
220     lastKeyTime = System.currentTimeMillis();
221   } //}}}
222 
223   //}}}
224 }