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
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
29 Thread eventLoopThread
;
31 LightweightRedirector lightweightRedirector
= new LightweightRedirector();
33 public XEventLoop(Display display
, EventQueue queue
)
35 this.display
= display
;
38 anyEvent
= new XAnyEvent(display
);
39 eventLoopThread
= new Thread(this, "AWT thread for XEventLoop");
40 eventLoopThread
.start();
51 AWTEvent evt
= getNextEvent();
55 /** get next event. Will block until events become available. */
57 public AWTEvent
getNextEvent()
61 throw new Error("should not be idle");
63 AWTEvent event
= null;
67 event
= createEvent();
70 event
= lightweightRedirector
.redirect(event
);
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
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
98 Alternatively, do the work on the AWT thread, since the
99 XEventQueue knows how to flush the display when it runs out
102 //display.flush(); // implicit?
105 catch (RuntimeException re
)
107 System
.err
.println("Exception thrown on event thread:" + re
);
116 * @returns an AWT event created based on the current XEvent.
117 * Returns null if the current XEvent does not map to any perticular
121 AWTEvent
createEvent ()
123 int type
= anyEvent
.getType ();
124 // Ignore some events without further processing
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
135 break; // continue processing events not in ignore list
137 /* avoid attempting to get client data before client data has
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 ();
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. */
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
);
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
,
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
)
200 modifiers
= InputEvent
.BUTTON1_MASK
;
203 modifiers
= InputEvent
.BUTTON2_MASK
;
206 modifiers
= InputEvent
.BUTTON2_MASK
;
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
225 int clickCount
= 1; // FIXME... Can't get this from X.
226 boolean popupTrigger
= false; // FIXME: look up policy somewhere
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
);
243 void configureNotify(Object peerObj
)
245 XConfigureEvent configEvent
= new XConfigureEvent(anyEvent
);
246 XFramePeer peer
= (XFramePeer
) peerObj
;
248 peer
.configureNotify(configEvent
);
251 public void flushIfIdle()
257 volatile boolean idle
= false;
259 final synchronized void setIdle(boolean idle
)
264 final synchronized boolean isIdle()