OpenCores
URL https://opencores.org/ocsvn/scarts/scarts/trunk

Subversion Repositories scarts

[/] [scarts/] [trunk/] [toolchain/] [scarts-gcc/] [gcc-4.1.1/] [libjava/] [classpath/] [java/] [awt/] [DefaultKeyboardFocusManager.java] - Blame information for rev 14

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 14 jlechner
/* DefaultKeyboardFocusManager.java --
2
   Copyright (C) 2002, 2004  Free Software Foundation, Inc.
3
 
4
This file is part of GNU Classpath.
5
 
6
GNU Classpath is free software; you can redistribute it and/or modify
7
it under the terms of the GNU General Public License as published by
8
the Free Software Foundation; either version 2, or (at your option)
9
any later version.
10
 
11
GNU Classpath is distributed in the hope that it will be useful, but
12
WITHOUT ANY WARRANTY; without even the implied warranty of
13
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
General Public License for more details.
15
 
16
You should have received a copy of the GNU General Public License
17
along with GNU Classpath; see the file COPYING.  If not, write to the
18
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19
02110-1301 USA.
20
 
21
Linking this library statically or dynamically with other modules is
22
making a combined work based on this library.  Thus, the terms and
23
conditions of the GNU General Public License cover the whole
24
combination.
25
 
26
As a special exception, the copyright holders of this library give you
27
permission to link this library with independent modules to produce an
28
executable, regardless of the license terms of these independent
29
modules, and to copy and distribute the resulting executable under
30
terms of your choice, provided that you also meet, for each linked
31
independent module, the terms and conditions of the license of that
32
module.  An independent module is a module which is not derived from
33
or based on this library.  If you modify this library, you may extend
34
this exception to your version of the library, but you are not
35
obligated to do so.  If you do not wish to do so, delete this
36
exception statement from your version. */
37
 
38
 
39
package java.awt;
40
 
41
import java.awt.event.ActionEvent;
42
import java.awt.event.FocusEvent;
43
import java.awt.event.KeyEvent;
44
import java.awt.event.WindowEvent;
45
import java.util.Iterator;
46
import java.util.LinkedList;
47
import java.util.Set;
48
import java.util.SortedSet;
49
import java.util.TreeSet;
50
 
51
// FIXME: finish documentation
52
public class DefaultKeyboardFocusManager extends KeyboardFocusManager
53
{
54
  /**
55
   * This class models a request to delay the dispatch of events that
56
   * arrive after a certain time, until a certain component becomes
57
   * the focus owner.
58
   */
59
  private class EventDelayRequest implements Comparable
60
  {
61
    /** A {@link java.util.List} of {@link java.awt.event.KeyEvent}s
62
        that are being delayed, pending this request's {@link
63
        Component} receiving the keyboard focus. */
64
    private LinkedList enqueuedKeyEvents = new LinkedList ();
65
 
66
    /** An event timestamp.  All events that arrive after this time
67
        should be queued in the {@link #enqueuedKeyEvents} {@link
68
        java.util.List}. */
69
    public long timestamp;
70
    /** When this {@link Component} becomes focused, all events
71
        between this EventDelayRequest and the next one in will be
72
        dispatched from {@link #enqueuedKeyEvents}. */
73
    public Component focusedComp;
74
 
75
    /**
76
     * Construct a new EventDelayRequest.
77
     *
78
     * @param timestamp events that arrive after this time will be
79
     * delayed
80
     * @param focusedComp the Component that needs to receive focus
81
     * before events are dispatched
82
     */
83
    public EventDelayRequest (long timestamp, Component focusedComp)
84
    {
85
      this.timestamp = timestamp;
86
      this.focusedComp = focusedComp;
87
    }
88
 
89
    public int compareTo (Object o)
90
    {
91
      if (!(o instanceof EventDelayRequest))
92
        throw new ClassCastException ();
93
 
94
      EventDelayRequest request = (EventDelayRequest) o;
95
 
96
      if (request.timestamp < timestamp)
97
        return -1;
98
      else if (request.timestamp == timestamp)
99
        return 0;
100
      else
101
        return 1;
102
    }
103
 
104
    public boolean equals (Object o)
105
    {
106
      if (!(o instanceof EventDelayRequest) || o == null)
107
        return false;
108
 
109
      EventDelayRequest request = (EventDelayRequest) o;
110
 
111
      return (request.timestamp == timestamp
112
              && request.focusedComp == focusedComp);
113
    }
114
 
115
    public void enqueueEvent (KeyEvent e)
116
    {
117
      KeyEvent last = (KeyEvent) enqueuedKeyEvents.getLast ();
118
      if (last != null && e.getWhen () < last.getWhen ())
119
        throw new RuntimeException ("KeyEvents enqueued out-of-order");
120
 
121
      if (e.getWhen () <= timestamp)
122
        throw new RuntimeException ("KeyEvents enqueued before starting timestamp");
123
 
124
      enqueuedKeyEvents.add (e);
125
    }
126
 
127
    public void dispatchEvents ()
128
    {
129
      int size = enqueuedKeyEvents.size ();
130
      for (int i = 0; i < size; i++)
131
        {
132
          KeyEvent e = (KeyEvent) enqueuedKeyEvents.remove (0);
133
          dispatchKeyEvent (e);
134
        }
135
    }
136
 
137
    public void discardEvents ()
138
    {
139
      enqueuedKeyEvents.clear ();
140
    }
141
  }
142
 
143
  /**
144
   * This flag indicates for which focus traversal key release event we
145
   * possibly wait, before letting any more KEY_TYPED events through.
146
   */
147
  private AWTKeyStroke waitForKeyStroke = null;
148
 
149
  /** The {@link java.util.SortedSet} of current
150
   * {@link EventDelayRequest}s. */
151
  private SortedSet delayRequests = new TreeSet ();
152
 
153
  public DefaultKeyboardFocusManager ()
154
  {
155
  }
156
 
157
  public boolean dispatchEvent (AWTEvent e)
158
  {
159
    if (e instanceof WindowEvent)
160
      {
161
        Window target = (Window) e.getSource ();
162
 
163
        if (e.id == WindowEvent.WINDOW_ACTIVATED)
164
          setGlobalActiveWindow (target);
165
        else if (e.id == WindowEvent.WINDOW_GAINED_FOCUS)
166
          setGlobalFocusedWindow (target);
167
        else if (e.id != WindowEvent.WINDOW_LOST_FOCUS
168
                 && e.id != WindowEvent.WINDOW_DEACTIVATED)
169
          return false;
170
 
171
        redispatchEvent(target, e);
172
        return true;
173
      }
174
    else if (e instanceof FocusEvent)
175
      {
176
        Component target = (Component) e.getSource ();
177
 
178
        if (e.id == FocusEvent.FOCUS_GAINED)
179
          {
180
            if (! (target instanceof Window))
181
              {
182
                if (((FocusEvent) e).isTemporary ())
183
                  setGlobalFocusOwner (target);
184
                else
185
                  setGlobalPermanentFocusOwner (target);
186
              }
187
 
188
            // Keep track of this window's focus owner.
189
 
190
            // Find the target Component's top-level ancestor.  target
191
            // may be a window.
192
            Container parent = target.getParent ();
193
 
194
            while (parent != null
195
                   && !(parent instanceof Window))
196
              parent = parent.getParent ();
197
 
198
            // If the parent is null and target is not a window, then target is an
199
            // unanchored component and so we don't want to set the focus owner.
200
            if (! (parent == null && ! (target instanceof Window)))
201
              {
202
                Window toplevel = parent == null ?
203
                  (Window) target : (Window) parent;
204
 
205
                Component focusOwner = getFocusOwner ();
206
                if (focusOwner != null
207
                    && ! (focusOwner instanceof Window))
208
                  toplevel.setFocusOwner (focusOwner);
209
              }
210
          }
211
        else if (e.id == FocusEvent.FOCUS_LOST)
212
          {
213
            if (((FocusEvent) e).isTemporary ())
214
              setGlobalFocusOwner (null);
215
            else
216
              setGlobalPermanentFocusOwner (null);
217
          }
218
 
219
        redispatchEvent(target, e);
220
 
221
        return true;
222
      }
223
    else if (e instanceof KeyEvent)
224
      {
225
        // Loop through all registered KeyEventDispatchers, giving
226
        // each a chance to handle this event.
227
        Iterator i = getKeyEventDispatchers().iterator();
228
 
229
        while (i.hasNext ())
230
          {
231
            KeyEventDispatcher dispatcher = (KeyEventDispatcher) i.next ();
232
            if (dispatcher.dispatchKeyEvent ((KeyEvent) e))
233
              return true;
234
          }
235
 
236
        // processKeyEvent checks if this event represents a focus
237
        // traversal key stroke.
238
        Component focusOwner = getGlobalPermanentFocusOwner ();
239
 
240
        if (focusOwner != null)
241
          processKeyEvent (focusOwner, (KeyEvent) e);
242
 
243
        if (e.isConsumed ())
244
          return true;
245
 
246
        if (enqueueKeyEvent ((KeyEvent) e))
247
          // This event was enqueued for dispatch at a later time.
248
          return true;
249
        else
250
          // This event wasn't handled by any of the registered
251
          // KeyEventDispatchers, and wasn't enqueued for dispatch
252
          // later, so send it to the default dispatcher.
253
          return dispatchKeyEvent ((KeyEvent) e);
254
      }
255
 
256
    return false;
257
  }
258
 
259
  private boolean enqueueKeyEvent (KeyEvent e)
260
  {
261
    Iterator i = delayRequests.iterator ();
262
    boolean oneEnqueued = false;
263
    while (i.hasNext ())
264
      {
265
        EventDelayRequest request = (EventDelayRequest) i.next ();
266
        if (e.getWhen () > request.timestamp)
267
          {
268
            request.enqueueEvent (e);
269
            oneEnqueued = true;
270
          }
271
      }
272
    return oneEnqueued;
273
  }
274
 
275
  public boolean dispatchKeyEvent (KeyEvent e)
276
  {
277
    Component focusOwner = getGlobalPermanentFocusOwner ();
278
 
279
    if (focusOwner != null)
280
      redispatchEvent(focusOwner, e);
281
 
282
    // Loop through all registered KeyEventPostProcessors, giving
283
    // each a chance to process this event.
284
    Iterator i = getKeyEventPostProcessors().iterator();
285
 
286
    while (i.hasNext ())
287
      {
288
        KeyEventPostProcessor processor = (KeyEventPostProcessor) i.next ();
289
        if (processor.postProcessKeyEvent ((KeyEvent) e))
290
          return true;
291
      }
292
 
293
    // The event hasn't been consumed yet.  Check if it is an
294
    // MenuShortcut.
295
    if (postProcessKeyEvent (e))
296
      return true;
297
 
298
    // Always return true.
299
    return true;
300
  }
301
 
302
  public boolean postProcessKeyEvent (KeyEvent e)
303
  {
304
    // Check if this event represents a menu shortcut.
305
 
306
    // MenuShortcuts are activated by Ctrl- KeyEvents, only on KEY_PRESSED.
307
    int modifiers = e.getModifiersEx ();
308
    if (e.getID() == KeyEvent.KEY_PRESSED
309
        && (modifiers & KeyEvent.CTRL_DOWN_MASK) != 0)
310
      {
311
        Window focusedWindow = getGlobalFocusedWindow ();
312
        if (focusedWindow instanceof Frame)
313
          {
314
            MenuBar menubar = ((Frame) focusedWindow).getMenuBar ();
315
 
316
            if (menubar != null)
317
              {
318
                // If there's a menubar, loop through all menu items,
319
                // checking whether each one has a shortcut, and if
320
                // so, whether this key event should activate it.
321
                int numMenus = menubar.getMenuCount ();
322
 
323
                for (int i = 0; i < numMenus; i++)
324
                  {
325
                    Menu menu = menubar.getMenu (i);
326
                    int numItems = menu.getItemCount ();
327
 
328
                    for (int j = 0; j < numItems; j++)
329
                      {
330
                        MenuItem item = menu.getItem (j);
331
                        MenuShortcut shortcut = item.getShortcut ();
332
 
333
                        if (item.isEnabled() && shortcut != null)
334
                          {
335
                            // Dispatch a new ActionEvent if:
336
                            //
337
                            //     a) this is a Shift- KeyEvent, and the
338
                            //        shortcut requires the Shift modifier
339
                            //
340
                            // or, b) this is not a Shift- KeyEvent, and the
341
                            //        shortcut does not require the Shift
342
                            //        modifier.
343
                            if (shortcut.getKey () == e.getKeyCode ()
344
                                && ((shortcut.usesShiftModifier ()
345
                                     && (modifiers & KeyEvent.SHIFT_DOWN_MASK) != 0)
346
                                    || (! shortcut.usesShiftModifier ()
347
                                        && (modifiers & KeyEvent.SHIFT_DOWN_MASK) == 0)))
348
                              {
349
                                item.dispatchEvent (new ActionEvent (item,
350
                                                                     ActionEvent.ACTION_PERFORMED,
351
                                                                     item.getActionCommand (),
352
                                                                     modifiers));
353
                                // The event was dispatched.
354
                                return true;
355
                              }
356
                          }
357
                      }
358
                  }
359
              }
360
          }
361
      }
362
    return false;
363
  }
364
 
365
  public void processKeyEvent (Component comp, KeyEvent e)
366
  {
367
    AWTKeyStroke eventKeystroke = AWTKeyStroke.getAWTKeyStrokeForEvent (e);
368
    // For every focus traversal keystroke, we need to also consume
369
    // the other two key event types for the same key (e.g. if
370
    // KEY_PRESSED TAB is a focus traversal keystroke, we also need to
371
    // consume KEY_RELEASED and KEY_TYPED TAB key events).
372
    // consuming KEY_RELEASED is easy, because their keyCodes matches
373
    // the KEY_PRESSED event. Consuming the intermediate KEY_TYPED is
374
    // very difficult because their is no clean way that we can know
375
    // which KEY_TYPED belongs to a focusTraversalKey and which not.
376
    // To address this problem we swallow every KEY_TYPE between the
377
    // KEY_PRESSED event that matches a focusTraversalKey and the
378
    // corresponding KEY_RELEASED.
379
    AWTKeyStroke oppositeKeystroke = AWTKeyStroke.getAWTKeyStroke (e.getKeyCode (),
380
                                                                   e.getModifiersEx (),
381
                                                                   !(e.id == KeyEvent.KEY_RELEASED));
382
 
383
    // Here we check if we are currently waiting for a KEY_RELEASED and
384
    // swallow all KeyEvents that are to be delivered in between. This
385
    // should only be the KEY_TYPED events that correspond to the
386
    // focusTraversalKey's KEY_PRESSED event
387
    if (waitForKeyStroke != null)
388
      {
389
        if (eventKeystroke.equals(waitForKeyStroke))
390
          // release this lock
391
          waitForKeyStroke = null;
392
 
393
        // as long as we are waiting for the KEY_RELEASED, we swallow every
394
        // KeyEvent, including the KEY_RELEASED
395
        e.consume();
396
        return;
397
      }
398
 
399
    Set forwardKeystrokes = comp.getFocusTraversalKeys (KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS);
400
    Set backwardKeystrokes = comp.getFocusTraversalKeys (KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS);
401
    Set upKeystrokes = comp.getFocusTraversalKeys (KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS);
402
    Set downKeystrokes = null;
403
    if (comp instanceof Container)
404
      downKeystrokes = comp.getFocusTraversalKeys (KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS);
405
 
406
    if (forwardKeystrokes.contains (eventKeystroke))
407
      {
408
        waitForKeyStroke = oppositeKeystroke;
409
        focusNextComponent (comp);
410
        e.consume ();
411
      }
412
    else if (backwardKeystrokes.contains (eventKeystroke))
413
      {
414
        waitForKeyStroke = oppositeKeystroke;
415
        focusPreviousComponent (comp);
416
        e.consume ();
417
      }
418
    else if (upKeystrokes.contains (eventKeystroke))
419
      {
420
        waitForKeyStroke = oppositeKeystroke;
421
        upFocusCycle (comp);
422
        e.consume ();
423
      }
424
    else if (comp instanceof Container
425
             && downKeystrokes.contains (eventKeystroke))
426
      {
427
        waitForKeyStroke = oppositeKeystroke;
428
        downFocusCycle ((Container) comp);
429
        e.consume ();
430
      }
431
  }
432
 
433
  protected void enqueueKeyEvents (long after, Component untilFocused)
434
  {
435
    delayRequests.add (new EventDelayRequest (after, untilFocused));
436
  }
437
 
438
  protected void dequeueKeyEvents (long after, Component untilFocused)
439
  {
440
    // FIXME: need synchronization on delayRequests and enqueuedKeyEvents.
441
 
442
    // Remove the KeyEvent with the oldest timestamp, which should be
443
    // the first element in the SortedSet.
444
    if (after < 0)
445
      {
446
        int size = delayRequests.size ();
447
        if (size > 0)
448
          delayRequests.remove (delayRequests.first ());
449
      }
450
    else
451
      {
452
        EventDelayRequest template = new EventDelayRequest (after, untilFocused);
453
        if (delayRequests.contains (template))
454
          {
455
            EventDelayRequest actual = (EventDelayRequest) delayRequests.tailSet (template).first ();
456
            delayRequests.remove (actual);
457
            actual.dispatchEvents ();
458
          }
459
      }
460
  }
461
 
462
  protected void discardKeyEvents (Component comp)
463
  {
464
    // FIXME: need synchronization on delayRequests and enqueuedKeyEvents.
465
 
466
    Iterator i = delayRequests.iterator ();
467
 
468
    while (i.hasNext ())
469
      {
470
        EventDelayRequest request = (EventDelayRequest) i.next ();
471
 
472
        if (request.focusedComp == comp
473
            || (comp instanceof Container
474
                && ((Container) comp).isAncestorOf (request.focusedComp)))
475
          request.discardEvents ();
476
      }
477
  }
478
 
479
  public void focusPreviousComponent (Component comp)
480
  {
481
    Component focusComp = (comp == null) ? getGlobalFocusOwner () : comp;
482
    Container focusCycleRoot = focusComp.getFocusCycleRootAncestor ();
483
    FocusTraversalPolicy policy = focusCycleRoot.getFocusTraversalPolicy ();
484
 
485
    Component previous = policy.getComponentBefore (focusCycleRoot, focusComp);
486
    if (previous != null)
487
      previous.requestFocusInWindow ();
488
  }
489
 
490
  public void focusNextComponent (Component comp)
491
  {
492
    Component focusComp = (comp == null) ? getGlobalFocusOwner () : comp;
493
    Container focusCycleRoot = focusComp.getFocusCycleRootAncestor ();
494
    FocusTraversalPolicy policy = focusCycleRoot.getFocusTraversalPolicy ();
495
 
496
    Component next = policy.getComponentAfter (focusCycleRoot, focusComp);
497
    if (next != null)
498
      next.requestFocusInWindow ();
499
  }
500
 
501
  public void upFocusCycle (Component comp)
502
  {
503
    Component focusComp = (comp == null) ? getGlobalFocusOwner () : comp;
504
    Container focusCycleRoot = focusComp.getFocusCycleRootAncestor ();
505
 
506
    if (focusCycleRoot instanceof Window)
507
      {
508
        FocusTraversalPolicy policy = focusCycleRoot.getFocusTraversalPolicy ();
509
        Component defaultComponent = policy.getDefaultComponent (focusCycleRoot);
510
        if (defaultComponent != null)
511
          defaultComponent.requestFocusInWindow ();
512
      }
513
    else
514
      {
515
        Container parentFocusCycleRoot = focusCycleRoot.getFocusCycleRootAncestor ();
516
 
517
        focusCycleRoot.requestFocusInWindow ();
518
        setGlobalCurrentFocusCycleRoot (parentFocusCycleRoot);
519
      }
520
  }
521
 
522
  public void downFocusCycle (Container cont)
523
  {
524
    if (cont == null)
525
      return;
526
 
527
    if (cont.isFocusCycleRoot (cont))
528
      {
529
        FocusTraversalPolicy policy = cont.getFocusTraversalPolicy ();
530
        Component defaultComponent = policy.getDefaultComponent (cont);
531
        if (defaultComponent != null)
532
          defaultComponent.requestFocusInWindow ();
533
        setGlobalCurrentFocusCycleRoot (cont);
534
      }
535
  }
536
} // class DefaultKeyboardFocusManager

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.