FSF GCC merge 02/23/03
[official-gcc.git] / libjava / gnu / awt / xlib / XEventLoop.java
blob4d2932089397d86dcdd4ade37110489f4a37d7f8
1 package gnu.awt.xlib;
3 /* Copyright (C) 2000 Free Software Foundation
5 This file is part of libgcj.
7 This software is copyrighted work licensed under the terms of the
8 Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
9 details. */
11 import java.awt.*;
13 import gnu.awt.LightweightRedirector;
14 import gnu.gcj.xlib.Display;
15 import gnu.gcj.xlib.XAnyEvent;
16 import gnu.gcj.xlib.XExposeEvent;
17 import gnu.gcj.xlib.XButtonEvent;
18 import gnu.gcj.xlib.XConfigureEvent;
19 import java.awt.event.PaintEvent;
20 import java.awt.event.InputEvent;
21 import java.awt.event.MouseEvent;
22 import java.util.Vector;
24 public class XEventLoop implements Runnable
26 Display display;
27 EventQueue queue;
28 XAnyEvent anyEvent;
29 Thread eventLoopThread;
31 LightweightRedirector lightweightRedirector = new LightweightRedirector();
33 public XEventLoop(Display display, EventQueue queue)
35 this.display = display;
36 this.queue = queue;
38 anyEvent = new XAnyEvent(display);
39 eventLoopThread = new Thread(this, "AWT thread for XEventLoop");
40 eventLoopThread.start();
43 public void run()
45 while (true)
46 postNextEvent();
49 void postNextEvent()
51 try
53 AWTEvent evt = getNextEvent();
54 queue.postEvent(evt);
57 catch (InterruptedException ie)
59 // FIXME: what now?
60 System.err.println(ie);
64 /** get next event. Will block until events become available. */
66 public AWTEvent getNextEvent()
68 // ASSERT:
69 if (isIdle())
70 throw new Error("should not be idle");
72 AWTEvent event = null;
73 while (event == null)
75 loadNextEvent();
76 event = createEvent();
79 event = lightweightRedirector.redirect(event);
81 return event;
84 void loadNextEvent()
86 try
88 setIdle(true);
90 /* The code below will result in an XFlush(). However,
91 while we are waiting for events after calling XFlush(),
92 new X requests issued on other threads will not
93 automatically be flushed. This can lead to a deadlock
94 since XFlush() will not be called before after the
95 processing of the next event, and new events arriving
96 might be dependent on the delivery of the X
97 requests.
99 Code that issues X requests should therefore call
100 flushIfIdle() after they're done, to ensure that the
101 requests are delivered in a timely manner. XFlush is not
102 run if event processing is underway, since we are assured
103 that the event loop execution will return to this point,
104 where requests are flushed again, before waiting for new
105 events.
107 Alternatively, do the work on the AWT thread, since the
108 XEventQueue knows how to flush the display when it runs out
109 of events. */
111 //display.flush(); // implicit?
112 anyEvent.loadNext();
114 catch (RuntimeException re)
116 System.err.println("Exception thrown on event thread:" + re);
118 finally
120 setIdle(false);
125 * @returns an AWT event created based on the current XEvent.
126 * Returns null if the current XEvent does not map to any perticular
127 * AWT event.
130 AWTEvent createEvent()
132 /* avoid attempting to get client data before client data has
133 been set. */
134 Object peer;
135 synchronized (this)
137 peer = anyEvent.getWindow().getClientData();
140 Component source = null;
142 // Try to identify source component
144 if (peer instanceof XCanvasPeer)
146 source = ((XCanvasPeer) peer).getComponent();
149 if (source == null)
151 String msg = "unable to locate source for event (" +
152 anyEvent + ")";
153 throw new RuntimeException(msg);
156 /* if a mapping from anyEvent to AWTEvent is possible, construct a
157 new AWTEvent and return it. */
159 int type = anyEvent.getType();
160 switch (type)
162 case XAnyEvent.TYPE_EXPOSE:
163 return createPaintEvent(source);
164 case XAnyEvent.TYPE_BUTTON_PRESS:
165 case XAnyEvent.TYPE_BUTTON_RELEASE:
166 return createMouseEvent(type, source);
167 case XAnyEvent.TYPE_UNMAP_NOTIFY:
168 case XAnyEvent.TYPE_MAP_NOTIFY:
169 case XAnyEvent.TYPE_REPARENT_NOTIFY:
170 return null; // ignore for now
171 case XAnyEvent.TYPE_CONFIGURE_NOTIFY:
172 configureNotify(peer);
173 return null;
175 default:
176 String msg = "Do no know how to handle event (" + anyEvent + ")";
177 throw new RuntimeException(msg);
181 AWTEvent createPaintEvent(Component src)
183 XExposeEvent expose = new XExposeEvent(anyEvent);
184 PaintEvent pe = new PaintEvent(src, PaintEvent.PAINT,
185 expose.getBounds());
186 return pe;
189 AWTEvent createMouseEvent(int type, Component src)
191 XButtonEvent buttonEvt = new XButtonEvent(anyEvent);
193 int modifiers = 0; //buttonToModifierMap[buttonEvt.button];
195 /* Warning: this makes assumptions on the contents of
196 X.h... Button1 = 1, Button2 = 2, etc... */
197 switch (buttonEvt.button)
199 case 1:
200 modifiers = InputEvent.BUTTON1_MASK;
201 break;
202 case 2:
203 modifiers = InputEvent.BUTTON2_MASK;
204 break;
205 case 3:
206 modifiers = InputEvent.BUTTON2_MASK;
207 break;
210 int state = buttonEvt.state;
212 // remap bits from state to modifiers:
214 if ((state & XButtonEvent.MASK_SHIFT) != 0)
215 modifiers |= InputEvent.SHIFT_MASK;
218 if ((state & XButtonEvent.MASK_CONTROL) != 0)
219 modifiers |= InputEvent.CTRL_MASK;
222 /* FIXME: we need additional X code to properly map MODn states to
223 input modifiers */
225 int clickCount = 1; // FIXME... Can't get this from X.
226 boolean popupTrigger = false; // FIXME: look up policy somewhere
228 int x = buttonEvt.x;
229 int y = buttonEvt.y;
231 int id = (type == XAnyEvent.TYPE_BUTTON_PRESS) ?
232 MouseEvent.MOUSE_PRESSED :
233 MouseEvent.MOUSE_RELEASED;
235 MouseEvent me = new MouseEvent(src,
237 buttonEvt.time, modifiers,
238 buttonEvt.x, buttonEvt.y,
239 clickCount, popupTrigger);
240 return me;
243 void configureNotify(Object peerObj)
245 XConfigureEvent configEvent = new XConfigureEvent(anyEvent);
246 XFramePeer peer = (XFramePeer) peerObj;
248 peer.configureNotify(configEvent);
251 public void flushIfIdle()
253 if (isIdle())
254 display.flush();
257 volatile boolean idle = false;
259 final synchronized void setIdle(boolean idle)
261 this.idle = idle;
264 final synchronized boolean isIdle()
266 return idle;