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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libjava/] [classpath/] [gnu/] [java/] [awt/] [peer/] [x/] [XEventPump.java] - Blame information for rev 769

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 769 jeremybenn
/* XEventPump.java -- Pumps events from X to AWT
2
   Copyright (C) 2006 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 gnu.java.awt.peer.x;
40
 
41
import java.awt.AWTEvent;
42
import java.awt.Component;
43
import java.awt.Container;
44
import java.awt.Graphics;
45
import java.awt.Insets;
46
import java.awt.Rectangle;
47
import java.awt.Toolkit;
48
import java.awt.Window;
49
import java.awt.event.ComponentEvent;
50
import java.awt.event.KeyEvent;
51
import java.awt.event.MouseEvent;
52
import java.awt.event.PaintEvent;
53
import java.awt.event.WindowEvent;
54
import java.util.HashMap;
55
 
56
import gnu.java.awt.ComponentReshapeEvent;
57
import gnu.x11.Atom;
58
import gnu.x11.Display;
59
import gnu.x11.event.ButtonPress;
60
import gnu.x11.event.ButtonRelease;
61
import gnu.x11.event.ClientMessage;
62
import gnu.x11.event.ConfigureNotify;
63
import gnu.x11.event.DestroyNotify;
64
import gnu.x11.event.Event;
65
import gnu.x11.event.Expose;
66
import gnu.x11.event.Input;
67
import gnu.x11.event.KeyPress;
68
import gnu.x11.event.KeyRelease;
69
import gnu.x11.event.MotionNotify;
70
import gnu.x11.event.PropertyNotify;
71
import gnu.x11.event.ResizeRequest;
72
import gnu.x11.event.UnmapNotify;
73
 
74
/**
75
 * Fetches events from X, translates them to AWT events and pumps them up
76
 * into the AWT event queue.
77
 *
78
 * @author Roman Kennke (kennke@aicas.com)
79
 */
80
public class XEventPump
81
  implements Runnable
82
{
83
 
84
  /**
85
   * The X Display from which we fetch and pump up events.
86
   */
87
  private Display display;
88
 
89
  /**
90
   * Maps X Windows to AWT Windows to be able to correctly determine the
91
   * event targets.
92
   */
93
  private HashMap windows;
94
 
95
  /**
96
   * Indicates if we are currently inside a drag operation. This is
97
   * set to the button ID when a button is pressed and to -1 (indicating
98
   * that no drag is active) when the mouse is released.
99
   */
100
  private int drag;
101
 
102
  /**
103
   * Creates a new XEventPump for the specified X Display.
104
   *
105
   * @param d the X Display
106
   */
107
  XEventPump(Display d)
108
  {
109
    display = d;
110
    windows = new HashMap();
111
    drag = -1;
112
    Thread thread = new Thread(this, "X Event Pump");
113
    thread.setDaemon(true);
114
    thread.start();
115
  }
116
 
117
  /**
118
   * The main event pump loop. This basically fetches events from the
119
   * X Display and pumps them into the system event queue.
120
   */
121
  public void run()
122
  {
123
    while (display.connected)
124
      {
125
        try
126
          {
127
            Event xEvent = display.next_event();
128
            handleEvent(xEvent);
129
          }
130
        catch (ThreadDeath death)
131
          {
132
            // If someone wants to kill us, let them.
133
            return;
134
          }
135
        catch (Throwable x)
136
          {
137
            System.err.println("Exception during event dispatch:");
138
            x.printStackTrace(System.err);
139
          }
140
      }
141
  }
142
 
143
  /**
144
   * Adds an X Window to AWT Window mapping. This is required so that the
145
   * event pump can correctly determine the event targets.
146
   *
147
   * @param xWindow the X Window
148
   * @param awtWindow the AWT Window
149
   */
150
  void registerWindow(gnu.x11.Window xWindow, Window awtWindow)
151
  {
152
    if (XToolkit.DEBUG)
153
      System.err.println("registering window id: " + xWindow.id);
154
    windows.put(new Integer(xWindow.id), awtWindow);
155
  }
156
 
157
  void unregisterWindow(gnu.x11.Window xWindow)
158
  {
159
    windows.remove(new Integer(xWindow.id));
160
  }
161
 
162
  private void handleButtonPress(ButtonPress event)
163
  {
164
    Integer key = new Integer(event.getEventWindowID());
165
    Window awtWindow = (Window) windows.get(key);
166
 
167
    // Create and post the mouse event.
168
    int button = event.detail();
169
 
170
    // AWT cannot handle more than 3 buttons and expects 0 instead.
171
    if (button >= gnu.x11.Input.BUTTON3)
172
      button = 0;
173
    drag = button;
174
 
175
    Component target =
176
      findMouseEventTarget(awtWindow, event.getEventX(), event.getEventY());
177
    if(target == null)
178
      {
179
        target = awtWindow;
180
      }
181
 
182
    MouseEvent mp = new MouseEvent(target, MouseEvent.MOUSE_PRESSED,
183
                                   System.currentTimeMillis(),
184
                                   KeyboardMapping.mapModifiers(event.getState())
185
                                     | buttonToModifier(button),
186
                                   event.getEventX(), event.getEventY(),
187
                                   1, false, button);
188
    Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent(mp);
189
  }
190
 
191
  private void handleButtonRelease(ButtonRelease event)
192
  {
193
    Integer key = new Integer(event.getEventWindowID());
194
    Window awtWindow = (Window) windows.get(key);
195
 
196
    int button = event.detail();
197
 
198
    // AWT cannot handle more than 3 buttons and expects 0 instead.
199
    if (button >= gnu.x11.Input.BUTTON3)
200
      button = 0;
201
    drag = -1;
202
 
203
    Component target =
204
      findMouseEventTarget(awtWindow, event.getEventX(), event.getEventY());
205
    if(target == null)
206
      {
207
        target = awtWindow;
208
      }
209
 
210
    MouseEvent mr = new MouseEvent(target, MouseEvent.MOUSE_RELEASED,
211
                                   System.currentTimeMillis(),
212
                                   KeyboardMapping.mapModifiers(event.getState())
213
                                     | buttonToModifier(button),
214
                                   event.getEventX(), event.getEventY(),
215
                                   1, false, button);
216
    Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent(mr);
217
  }
218
 
219
 
220
  private void handleMotionNotify(MotionNotify event)
221
  {
222
    Integer key = new Integer(event.getEventWindowID());
223
    Window awtWindow = (Window) windows.get(key);
224
 
225
    int button = event.detail();
226
 
227
    // AWT cannot handle more than 3 buttons and expects 0 instead.
228
    if (button >= gnu.x11.Input.BUTTON3)
229
      button = 0;
230
 
231
    MouseEvent mm = null;
232
    if (drag == -1)
233
      {
234
        mm = new MouseEvent(awtWindow, MouseEvent.MOUSE_MOVED,
235
                            System.currentTimeMillis(),
236
                            KeyboardMapping.mapModifiers(event.getState())
237
                              | buttonToModifier(button),
238
                            event.getEventX(), event.getEventY(),
239
                            1, false);
240
 
241
      }
242
    else
243
      {
244
        mm = new MouseEvent(awtWindow, MouseEvent.MOUSE_DRAGGED,
245
                            System.currentTimeMillis(),
246
                            KeyboardMapping.mapModifiers(event.getState())
247
                              | buttonToModifier(drag),
248
                            event.getEventX(), event.getEventY(),
249
                            1, false);
250
      }
251
    Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent(mm);
252
  }
253
 
254
  // FIME: refactor and make faster, maybe caching the event and handle
255
  // and/or check timing (timing is generated for PropertyChange)?
256
  private void handleExpose(Expose event)
257
  {
258
    Integer key = new Integer(event.window_id);
259
    Window awtWindow = (Window) windows.get(key);
260
 
261
    if (XToolkit.DEBUG)
262
      System.err.println("expose request for window id: " + key);
263
 
264
    Rectangle r = new Rectangle(event.x(), event.y(), event.width(),
265
                                event.height());
266
    // We need to clear the background of the exposed rectangle.
267
    assert awtWindow != null : "awtWindow == null for window ID: " + key;
268
 
269
    Graphics g = awtWindow.getGraphics();
270
    g.clearRect(r.x, r.y, r.width, r.height);
271
    g.dispose();
272
 
273
    XWindowPeer xwindow = (XWindowPeer) awtWindow.getPeer();
274
    Insets i = xwindow.insets();
275
    if (event.width() != awtWindow.getWidth() - i.left - i.right
276
        || event.height() != awtWindow.getHeight() - i.top - i.bottom)
277
      {
278
        int w = event.width();
279
        int h = event.height();
280
        int x = xwindow.xwindow.x;
281
        int y = xwindow.xwindow.y;
282
 
283
        if (XToolkit.DEBUG)
284
          System.err.println("Setting size on AWT window: " + w
285
                           + ", " + h + ", " + awtWindow.getWidth()
286
                           + ", " + awtWindow.getHeight());
287
 
288
        // new width and height
289
        xwindow.xwindow.width = w;
290
        xwindow.xwindow.height = h;
291
 
292
        // reshape the window
293
        ComponentReshapeEvent cre =
294
          new ComponentReshapeEvent(awtWindow, x, y, w, h);
295
        awtWindow.dispatchEvent(cre);
296
      }
297
 
298
    ComponentEvent ce =
299
      new ComponentEvent(awtWindow, ComponentEvent.COMPONENT_RESIZED);
300
    awtWindow.dispatchEvent(ce);
301
 
302
    PaintEvent pev = new PaintEvent(awtWindow, PaintEvent.UPDATE, r);
303
    Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent(pev);
304
  }
305
 
306
  private void handleDestroyNotify(DestroyNotify destroyNotify)
307
  {
308
    if (XToolkit.DEBUG)
309
      System.err.println("DestroyNotify event: " + destroyNotify);
310
 
311
    Integer key = new Integer(destroyNotify.event_window_id);
312
    Window awtWindow = (Window) windows.get(key);
313
 
314
    AWTEvent event = new WindowEvent(awtWindow, WindowEvent.WINDOW_CLOSED);
315
    Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent(event);
316
  }
317
 
318
  private void handleClientMessage(ClientMessage clientMessage)
319
  {
320
    if (XToolkit.DEBUG)
321
      System.err.println("ClientMessage event: " + clientMessage);
322
 
323
    if (clientMessage.delete_window())
324
      {
325
        if (XToolkit.DEBUG)
326
          System.err.println("ClientMessage is a delete_window event");
327
 
328
        Integer key = new Integer(clientMessage.window_id);
329
        Window awtWindow = (Window) windows.get(key);
330
 
331
        AWTEvent event = new WindowEvent(awtWindow, WindowEvent.WINDOW_CLOSING);
332
        Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent(event);
333
      }
334
  }
335
 
336
  private void handleEvent(Event xEvent)
337
  {
338
    if (XToolkit.DEBUG)
339
      System.err.println("fetched event: " + xEvent);
340
 
341
    switch (xEvent.code() & 0x7f)
342
    {
343
    case ButtonPress.CODE:
344
      this.handleButtonPress((ButtonPress) xEvent);
345
      break;
346
    case ButtonRelease.CODE:
347
      this.handleButtonRelease((ButtonRelease) xEvent);
348
      break;
349
    case MotionNotify.CODE:
350
      this.handleMotionNotify((MotionNotify) xEvent);
351
      break;
352
    case Expose.CODE:
353
      this.handleExpose((Expose) xEvent);
354
      break;
355
    case KeyPress.CODE:
356
    case KeyRelease.CODE:
357
      Integer key = new Integer(((Input) xEvent).getEventWindowID());
358
      Window awtWindow = (Window) windows.get(key);
359
      handleKeyEvent(xEvent, awtWindow);
360
      break;
361
    case DestroyNotify.CODE:
362
      this.handleDestroyNotify((DestroyNotify) xEvent);
363
      break;
364
    case ClientMessage.CODE:
365
      this.handleClientMessage((ClientMessage) xEvent);
366
      break;
367
    case PropertyNotify.CODE:
368
      key = new Integer (((PropertyNotify) xEvent).getWindowID());
369
      awtWindow = (Window) windows.get(key);
370
      AWTEvent event = new WindowEvent(awtWindow, WindowEvent.WINDOW_STATE_CHANGED);
371
      Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent(event);
372
      break;
373
    default:
374
      if (XToolkit.DEBUG)
375
        System.err.println("Unhandled X event: " + xEvent);
376
    }
377
  }
378
 
379
  /**
380
   * Handles key events from X.
381
   *
382
   * @param xEvent the X event
383
   * @param awtWindow the AWT window to which the event gets posted
384
   */
385
  private void handleKeyEvent(Event xEvent, Window awtWindow)
386
  {
387
    Input keyEvent = (Input) xEvent;
388
    int xKeyCode = keyEvent.detail();
389
    int xMods = keyEvent.getState();
390
    int keyCode = KeyboardMapping.mapToKeyCode(xEvent.display.input, xKeyCode,
391
                                               xMods);
392
    char keyChar = KeyboardMapping.mapToKeyChar(xEvent.display.input, xKeyCode,
393
                                                xMods);
394
    if (XToolkit.DEBUG)
395
      System.err.println("XEventPump.handleKeyEvent: " + xKeyCode + ", "
396
                         + xMods + ": " + ((int) keyChar) + ", " + keyCode);
397
    int awtMods = KeyboardMapping.mapModifiers(xMods);
398
    long when = System.currentTimeMillis();
399
    KeyEvent ke;
400
    if (keyEvent.code() == KeyPress.CODE)
401
      {
402
        ke = new KeyEvent(awtWindow, KeyEvent.KEY_PRESSED, when,
403
                          awtMods, keyCode,
404
                          KeyEvent.CHAR_UNDEFINED);
405
        Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent(ke);
406
        if (keyChar != KeyEvent.CHAR_UNDEFINED)
407
          {
408
            ke = new KeyEvent(awtWindow, KeyEvent.KEY_TYPED, when,
409
                              awtMods, KeyEvent.VK_UNDEFINED,
410
                              keyChar);
411
            Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent(ke);
412
          }
413
 
414
      }
415
    else
416
      {
417
        ke = new KeyEvent(awtWindow, KeyEvent.KEY_RELEASED, when,
418
                          awtMods, keyCode,
419
                          KeyEvent.CHAR_UNDEFINED);
420
        Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent(ke);
421
      }
422
 
423
  }
424
 
425
  /** Translates an X button identifier to the AWT's MouseEvent modifier
426
   *  mask. As the AWT cannot handle more than 3 buttons those return
427
   *  <code>0</code>.
428
   */
429
  static int buttonToModifier(int button)
430
  {
431
    switch (button)
432
    {
433
      case gnu.x11.Input.BUTTON1:
434
        return MouseEvent.BUTTON1_DOWN_MASK | MouseEvent.BUTTON1_MASK;
435
      case gnu.x11.Input.BUTTON2:
436
        return MouseEvent.BUTTON2_DOWN_MASK | MouseEvent.BUTTON2_MASK;
437
      case gnu.x11.Input.BUTTON3:
438
        return MouseEvent.BUTTON3_DOWN_MASK | MouseEvent.BUTTON3_MASK;
439
    }
440
 
441
    return 0;
442
  }
443
 
444
  /**
445
   * Finds the heavyweight mouse event target.
446
   *
447
   * @param src the original source of the event
448
   *
449
   * @param pt the event coordinates
450
   *
451
   * @return the real mouse event target
452
   */
453
  private Component findMouseEventTarget(Component src, int x, int y)
454
  {
455
    Component found = null;
456
    if (src instanceof Container)
457
      {
458
        Container cont = (Container) src;
459
        int numChildren = cont.getComponentCount();
460
        for (int i = 0; i < numChildren && found == null; i++)
461
          {
462
            Component child = cont.getComponent(i);
463
            if (child != null && child.isVisible()
464
                && child.contains(x - child.getX(), y - child.getY()))
465
              {
466
                if (child instanceof Container)
467
                  {
468
                    Component deeper = findMouseEventTarget(child,
469
                                                            x - child.getX(),
470
                                                            y - child.getY());
471
                    if (deeper != null)
472
                      found = deeper;
473
                  }
474
                else if (! child.isLightweight())
475
                  found = child;
476
              }
477
          }
478
      }
479
 
480
    // Consider the source itself.
481
    if (found == null && src.contains(x, y) && ! src.isLightweight())
482
      found = src;
483
 
484
    return found;
485
  }
486
}

powered by: WebSVN 2.1.0

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