2003-12-26 Guilhem Lavaux <guilhem@kaffe.org>
[official-gcc.git] / libjava / gnu / awt / xlib / XEventLoop.java
blob5f5026b0cdb79c5821923a29f007966254c5595c
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 AWTEvent evt = getNextEvent();
52 queue.postEvent(evt);
55 /** get next event. Will block until events become available. */
57 public AWTEvent getNextEvent()
59 // ASSERT:
60 if (isIdle())
61 throw new Error("should not be idle");
63 AWTEvent event = null;
64 while (event == null)
66 loadNextEvent();
67 event = createEvent();
70 event = lightweightRedirector.redirect(event);
72 return event;
75 void loadNextEvent()
77 try
79 setIdle(true);
81 /* The code below will result in an XFlush(). However,
82 while we are waiting for events after calling XFlush(),
83 new X requests issued on other threads will not
84 automatically be flushed. This can lead to a deadlock
85 since XFlush() will not be called before after the
86 processing of the next event, and new events arriving
87 might be dependent on the delivery of the X
88 requests.
90 Code that issues X requests should therefore call
91 flushIfIdle() after they're done, to ensure that the
92 requests are delivered in a timely manner. XFlush is not
93 run if event processing is underway, since we are assured
94 that the event loop execution will return to this point,
95 where requests are flushed again, before waiting for new
96 events.
98 Alternatively, do the work on the AWT thread, since the
99 XEventQueue knows how to flush the display when it runs out
100 of events. */
102 //display.flush(); // implicit?
103 anyEvent.loadNext();
105 catch (RuntimeException re)
107 System.err.println("Exception thrown on event thread:" + re);
109 finally
111 setIdle(false);
116 * @returns an AWT event created based on the current XEvent.
117 * Returns null if the current XEvent does not map to any perticular
118 * AWT event.
121 AWTEvent createEvent ()
123 int type = anyEvent.getType ();
124 // Ignore some events without further processing
125 switch (type)
127 // ignore "no expose" events, which are generated whenever a pixmap
128 // is copied to copied to a window which is entirely unobscured
129 case XAnyEvent.TYPE_NO_EXPOSE:
130 case XAnyEvent.TYPE_UNMAP_NOTIFY: // ignore for now
131 case XAnyEvent.TYPE_MAP_NOTIFY: // ignore for now
132 case XAnyEvent.TYPE_REPARENT_NOTIFY: // ignore for now
133 return null;
134 default:
135 break; // continue processing events not in ignore list
137 /* avoid attempting to get client data before client data has
138 been set. */
139 Object peer;
140 synchronized (this)
142 peer = anyEvent.getWindow ().getClientData ();
145 Component source = null;
147 // Try to identify source component
149 if (peer instanceof XCanvasPeer)
151 source = ((XCanvasPeer) peer).getComponent ();
154 if (source == null)
156 String msg = "unable to locate source for event (" +
157 anyEvent + "): peer=" + peer;
158 throw new RuntimeException (msg);
161 /* if a mapping from anyEvent to AWTEvent is possible, construct a
162 new AWTEvent and return it. */
164 switch (type)
166 case XAnyEvent.TYPE_EXPOSE:
167 return createPaintEvent (source);
168 case XAnyEvent.TYPE_BUTTON_PRESS:
169 case XAnyEvent.TYPE_BUTTON_RELEASE:
170 return createMouseEvent (type, source);
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;