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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libjava/] [classpath/] [java/] [awt/] [DefaultKeyboardFocusManager.java] - Blame information for rev 771

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 771 jeremybenn
/* 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
          {
167
            setGlobalFocusedWindow (target);
168
            FocusTraversalPolicy p = target.getFocusTraversalPolicy();
169
            Component toFocus = p.getInitialComponent(target);
170
            if (toFocus != null)
171
              toFocus.requestFocusInWindow();
172
          }
173
        else if (e.id != WindowEvent.WINDOW_LOST_FOCUS
174
                 && e.id != WindowEvent.WINDOW_DEACTIVATED)
175
          return false;
176
 
177
        redispatchEvent(target, e);
178
        return true;
179
      }
180
    else if (e instanceof FocusEvent)
181
      {
182
        FocusEvent fe = (FocusEvent) e;
183
        Component target = fe.getComponent ();
184
 
185
        boolean retval = false;
186
        if (e.id == FocusEvent.FOCUS_GAINED)
187
          {
188
            retval = handleFocusGained(fe);
189
          }
190
        else if (e.id == FocusEvent.FOCUS_LOST)
191
          {
192
            retval = handleFocusLost(fe);
193
          }
194
        return true;
195
      }
196
    else if (e instanceof KeyEvent)
197
      {
198
        // Loop through all registered KeyEventDispatchers, giving
199
        // each a chance to handle this event.
200
        Iterator i = getKeyEventDispatchers().iterator();
201
 
202
        while (i.hasNext ())
203
          {
204
            KeyEventDispatcher dispatcher = (KeyEventDispatcher) i.next ();
205
            if (dispatcher.dispatchKeyEvent ((KeyEvent) e))
206
              return true;
207
          }
208
 
209
        // processKeyEvent checks if this event represents a focus
210
        // traversal key stroke.
211
        Component focusOwner = getGlobalPermanentFocusOwner ();
212
 
213
        if (focusOwner != null)
214
          processKeyEvent (focusOwner, (KeyEvent) e);
215
 
216
        if (e.isConsumed ())
217
          return true;
218
 
219
        if (enqueueKeyEvent ((KeyEvent) e))
220
          // This event was enqueued for dispatch at a later time.
221
          return true;
222
        else
223
          // This event wasn't handled by any of the registered
224
          // KeyEventDispatchers, and wasn't enqueued for dispatch
225
          // later, so send it to the default dispatcher.
226
          return dispatchKeyEvent ((KeyEvent) e);
227
      }
228
 
229
    return false;
230
  }
231
 
232
  /**
233
   * Handles FOCUS_GAINED events in {@link #dispatchEvent(AWTEvent)}.
234
   *
235
   * @param fe the focus event
236
   */
237
  private boolean handleFocusGained(FocusEvent fe)
238
  {
239
    Component target = fe.getComponent ();
240
 
241
    // If old focus owner != new focus owner, notify old focus
242
    // owner that it has lost focus.
243
    Component oldFocusOwner = getGlobalFocusOwner();
244
    if (oldFocusOwner != null && oldFocusOwner != target)
245
      {
246
        FocusEvent lost = new FocusEvent(oldFocusOwner,
247
                                         FocusEvent.FOCUS_LOST,
248
                                         fe.isTemporary(), target);
249
        oldFocusOwner.dispatchEvent(lost);
250
      }
251
 
252
     setGlobalFocusOwner (target);
253
     if (target != getGlobalFocusOwner())
254
       {
255
         // Focus transfer was rejected, like when the target is not
256
         // focusable.
257
         dequeueKeyEvents(-1, target);
258
         // FIXME: Restore focus somehow.
259
       }
260
     else
261
       {
262
         if (! fe.isTemporary())
263
           {
264
             setGlobalPermanentFocusOwner (target);
265
             if (target != getGlobalPermanentFocusOwner())
266
               {
267
                 // Focus transfer was rejected, like when the target is not
268
                 // focusable.
269
                 dequeueKeyEvents(-1, target);
270
                 // FIXME: Restore focus somehow.
271
               }
272
             else
273
               {
274
                 redispatchEvent(target, fe);
275
               }
276
           }
277
       }
278
 
279
     return true;
280
  }
281
 
282
  /**
283
   * Handles FOCUS_LOST events for {@link #dispatchEvent(AWTEvent)}.
284
   *
285
   * @param fe the focus event
286
   *
287
   * @return if the event has been handled
288
   */
289
  private boolean handleFocusLost(FocusEvent fe)
290
  {
291
    Component currentFocus = getGlobalFocusOwner();
292
    if (currentFocus != fe.getOppositeComponent())
293
      {
294
        setGlobalFocusOwner(null);
295
        if (getGlobalFocusOwner() != null)
296
          {
297
            // TODO: Is this possible? If so, then we should try to restore
298
            // the focus.
299
          }
300
        else
301
          {
302
            if (! fe.isTemporary())
303
              {
304
                setGlobalPermanentFocusOwner(null);
305
                if (getGlobalPermanentFocusOwner() != null)
306
                  {
307
                    // TODO: Is this possible? If so, then we should try to
308
                    // restore the focus.
309
                  }
310
                else
311
                  {
312
                    fe.setSource(currentFocus);
313
                    redispatchEvent(currentFocus, fe);
314
                  }
315
              }
316
          }
317
      }
318
    return true;
319
  }
320
 
321
  private boolean enqueueKeyEvent (KeyEvent e)
322
  {
323
    Iterator i = delayRequests.iterator ();
324
    boolean oneEnqueued = false;
325
    while (i.hasNext ())
326
      {
327
        EventDelayRequest request = (EventDelayRequest) i.next ();
328
        if (e.getWhen () > request.timestamp)
329
          {
330
            request.enqueueEvent (e);
331
            oneEnqueued = true;
332
          }
333
      }
334
    return oneEnqueued;
335
  }
336
 
337
  public boolean dispatchKeyEvent (KeyEvent e)
338
  {
339
    Component focusOwner = getFocusOwner();
340
    if (focusOwner == null)
341
      focusOwner = getFocusedWindow();
342
 
343
    if (focusOwner != null)
344
      redispatchEvent(focusOwner, e);
345
 
346
    // Loop through all registered KeyEventPostProcessors, giving
347
    // each a chance to process this event.
348
    Iterator i = getKeyEventPostProcessors().iterator();
349
 
350
    while (i.hasNext ())
351
      {
352
        KeyEventPostProcessor processor = (KeyEventPostProcessor) i.next ();
353
        if (processor.postProcessKeyEvent (e))
354
          return true;
355
      }
356
 
357
    // The event hasn't been consumed yet.  Check if it is an
358
    // MenuShortcut.
359
    if (postProcessKeyEvent (e))
360
      return true;
361
 
362
    // Always return true.
363
    return true;
364
  }
365
 
366
  public boolean postProcessKeyEvent (KeyEvent e)
367
  {
368
    // Check if this event represents a menu shortcut.
369
 
370
    // MenuShortcuts are activated by Ctrl- KeyEvents, only on KEY_PRESSED.
371
    int modifiers = e.getModifiersEx ();
372
    if (e.getID() == KeyEvent.KEY_PRESSED
373
        && (modifiers & KeyEvent.CTRL_DOWN_MASK) != 0)
374
      {
375
        Window focusedWindow = getGlobalFocusedWindow ();
376
        if (focusedWindow instanceof Frame)
377
          {
378
            MenuBar menubar = ((Frame) focusedWindow).getMenuBar ();
379
 
380
            if (menubar != null)
381
              {
382
                // If there's a menubar, loop through all menu items,
383
                // checking whether each one has a shortcut, and if
384
                // so, whether this key event should activate it.
385
                int numMenus = menubar.getMenuCount ();
386
 
387
                for (int i = 0; i < numMenus; i++)
388
                  {
389
                    Menu menu = menubar.getMenu (i);
390
                    int numItems = menu.getItemCount ();
391
 
392
                    for (int j = 0; j < numItems; j++)
393
                      {
394
                        MenuItem item = menu.getItem (j);
395
                        MenuShortcut shortcut = item.getShortcut ();
396
 
397
                        if (item.isEnabled() && shortcut != null)
398
                          {
399
                            // Dispatch a new ActionEvent if:
400
                            //
401
                            //     a) this is a Shift- KeyEvent, and the
402
                            //        shortcut requires the Shift modifier
403
                            //
404
                            // or, b) this is not a Shift- KeyEvent, and the
405
                            //        shortcut does not require the Shift
406
                            //        modifier.
407
                            if (shortcut.getKey () == e.getKeyCode ()
408
                                && ((shortcut.usesShiftModifier ()
409
                                     && (modifiers & KeyEvent.SHIFT_DOWN_MASK) != 0)
410
                                    || (! shortcut.usesShiftModifier ()
411
                                        && (modifiers & KeyEvent.SHIFT_DOWN_MASK) == 0)))
412
                              {
413
                                item.dispatchEvent (new ActionEvent (item,
414
                                                                     ActionEvent.ACTION_PERFORMED,
415
                                                                     item.getActionCommand (),
416
                                                                     modifiers));
417
                                // The event was dispatched.
418
                                return true;
419
                              }
420
                          }
421
                      }
422
                  }
423
              }
424
          }
425
      }
426
    return false;
427
  }
428
 
429
  public void processKeyEvent (Component comp, KeyEvent e)
430
  {
431
    AWTKeyStroke eventKeystroke = AWTKeyStroke.getAWTKeyStrokeForEvent (e);
432
    // For every focus traversal keystroke, we need to also consume
433
    // the other two key event types for the same key (e.g. if
434
    // KEY_PRESSED TAB is a focus traversal keystroke, we also need to
435
    // consume KEY_RELEASED and KEY_TYPED TAB key events).
436
    // consuming KEY_RELEASED is easy, because their keyCodes matches
437
    // the KEY_PRESSED event. Consuming the intermediate KEY_TYPED is
438
    // very difficult because their is no clean way that we can know
439
    // which KEY_TYPED belongs to a focusTraversalKey and which not.
440
    // To address this problem we swallow every KEY_TYPE between the
441
    // KEY_PRESSED event that matches a focusTraversalKey and the
442
    // corresponding KEY_RELEASED.
443
    AWTKeyStroke oppositeKeystroke = AWTKeyStroke.getAWTKeyStroke (e.getKeyCode (),
444
                                                                   e.getModifiersEx (),
445
                                                                   !(e.id == KeyEvent.KEY_RELEASED));
446
 
447
    // Here we check if we are currently waiting for a KEY_RELEASED and
448
    // swallow all KeyEvents that are to be delivered in between. This
449
    // should only be the KEY_TYPED events that correspond to the
450
    // focusTraversalKey's KEY_PRESSED event
451
    if (waitForKeyStroke != null)
452
      {
453
        if (eventKeystroke.equals(waitForKeyStroke))
454
          // release this lock
455
          waitForKeyStroke = null;
456
 
457
        // as long as we are waiting for the KEY_RELEASED, we swallow every
458
        // KeyEvent, including the KEY_RELEASED
459
        e.consume();
460
        return;
461
      }
462
 
463
    Set forwardKeystrokes = comp.getFocusTraversalKeys (KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS);
464
    Set backwardKeystrokes = comp.getFocusTraversalKeys (KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS);
465
    Set upKeystrokes = comp.getFocusTraversalKeys (KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS);
466
    Set downKeystrokes = null;
467
    if (comp instanceof Container)
468
      downKeystrokes = comp.getFocusTraversalKeys (KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS);
469
 
470
    if (forwardKeystrokes.contains (eventKeystroke))
471
      {
472
        waitForKeyStroke = oppositeKeystroke;
473
        focusNextComponent (comp);
474
        e.consume ();
475
      }
476
    else if (backwardKeystrokes.contains (eventKeystroke))
477
      {
478
        waitForKeyStroke = oppositeKeystroke;
479
        focusPreviousComponent (comp);
480
        e.consume ();
481
      }
482
    else if (upKeystrokes.contains (eventKeystroke))
483
      {
484
        waitForKeyStroke = oppositeKeystroke;
485
        upFocusCycle (comp);
486
        e.consume ();
487
      }
488
    else if (comp instanceof Container
489
             && downKeystrokes.contains (eventKeystroke))
490
      {
491
        waitForKeyStroke = oppositeKeystroke;
492
        downFocusCycle ((Container) comp);
493
        e.consume ();
494
      }
495
  }
496
 
497
  protected void enqueueKeyEvents (long after, Component untilFocused)
498
  {
499
    delayRequests.add (new EventDelayRequest (after, untilFocused));
500
  }
501
 
502
  protected void dequeueKeyEvents (long after, Component untilFocused)
503
  {
504
    // FIXME: need synchronization on delayRequests and enqueuedKeyEvents.
505
 
506
    // Remove the KeyEvent with the oldest timestamp, which should be
507
    // the first element in the SortedSet.
508
    if (after < 0)
509
      {
510
        int size = delayRequests.size ();
511
        if (size > 0)
512
          delayRequests.remove (delayRequests.first ());
513
      }
514
    else
515
      {
516
        EventDelayRequest template = new EventDelayRequest (after, untilFocused);
517
        if (delayRequests.contains (template))
518
          {
519
            EventDelayRequest actual = (EventDelayRequest) delayRequests.tailSet (template).first ();
520
            delayRequests.remove (actual);
521
            actual.dispatchEvents ();
522
          }
523
      }
524
  }
525
 
526
  protected void discardKeyEvents (Component comp)
527
  {
528
    // FIXME: need synchronization on delayRequests and enqueuedKeyEvents.
529
 
530
    Iterator i = delayRequests.iterator ();
531
 
532
    while (i.hasNext ())
533
      {
534
        EventDelayRequest request = (EventDelayRequest) i.next ();
535
 
536
        if (request.focusedComp == comp
537
            || (comp instanceof Container
538
                && ((Container) comp).isAncestorOf (request.focusedComp)))
539
          request.discardEvents ();
540
      }
541
  }
542
 
543
  public void focusPreviousComponent (Component comp)
544
  {
545
    if (comp != null)
546
      comp.transferFocusBackward();
547
  }
548
 
549
  public void focusNextComponent (Component comp)
550
  {
551
    if (comp != null)
552
      comp.transferFocus();
553
  }
554
 
555
  public void upFocusCycle (Component comp)
556
  {
557
    if (comp != null)
558
      comp.transferFocusUpCycle();
559
  }
560
 
561
  public void downFocusCycle (Container cont)
562
  {
563
    if (cont != null)
564
      cont.transferFocusDownCycle();
565
  }
566
} // class DefaultKeyboardFocusManager

powered by: WebSVN 2.1.0

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