]> gcc.gnu.org Git - gcc.git/blob - libjava/gnu/awt/xlib/XEventLoop.java
AbstractGraphicsState.java (clone): Handle CloneNotSupportedException.
[gcc.git] / libjava / gnu / awt / xlib / XEventLoop.java
1 package gnu.awt.xlib;
2
3 /* Copyright (C) 2000 Free Software Foundation
4
5 This file is part of libgcj.
6
7 This software is copyrighted work licensed under the terms of the
8 Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
9 details. */
10
11 import java.awt.*;
12
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;
23
24 public class XEventLoop implements Runnable
25 {
26 Display display;
27 EventQueue queue;
28 XAnyEvent anyEvent;
29 Thread eventLoopThread;
30
31 LightweightRedirector lightweightRedirector = new LightweightRedirector();
32
33 public XEventLoop(Display display, EventQueue queue)
34 {
35 this.display = display;
36 this.queue = queue;
37
38 anyEvent = new XAnyEvent(display);
39 eventLoopThread = new Thread(this, "AWT thread for XEventLoop");
40 eventLoopThread.start();
41 }
42
43 public void run()
44 {
45 while (true)
46 postNextEvent();
47 }
48
49 void postNextEvent()
50 {
51 AWTEvent evt = getNextEvent();
52 queue.postEvent(evt);
53 }
54
55 /** get next event. Will block until events become available. */
56
57 public AWTEvent getNextEvent()
58 {
59 // ASSERT:
60 if (isIdle())
61 throw new Error("should not be idle");
62
63 AWTEvent event = null;
64 while (event == null)
65 {
66 loadNextEvent();
67 event = createEvent();
68 }
69
70 event = lightweightRedirector.redirect(event);
71
72 return event;
73 }
74
75 void loadNextEvent()
76 {
77 try
78 {
79 setIdle(true);
80
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.
89
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.
97
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. */
101
102 //display.flush(); // implicit?
103 anyEvent.loadNext();
104 }
105 catch (RuntimeException re)
106 {
107 System.err.println("Exception thrown on event thread:" + re);
108 }
109 finally
110 {
111 setIdle(false);
112 }
113 }
114
115 /**
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.
119 */
120
121 AWTEvent createEvent()
122 {
123 /* avoid attempting to get client data before client data has
124 been set. */
125 Object peer;
126 synchronized (this)
127 {
128 peer = anyEvent.getWindow().getClientData();
129 }
130
131 Component source = null;
132
133 // Try to identify source component
134
135 if (peer instanceof XCanvasPeer)
136 {
137 source = ((XCanvasPeer) peer).getComponent();
138 }
139
140 if (source == null)
141 {
142 String msg = "unable to locate source for event (" +
143 anyEvent + ")";
144 throw new RuntimeException(msg);
145 }
146
147 /* if a mapping from anyEvent to AWTEvent is possible, construct a
148 new AWTEvent and return it. */
149
150 int type = anyEvent.getType();
151 switch (type)
152 {
153 case XAnyEvent.TYPE_EXPOSE:
154 return createPaintEvent(source);
155 case XAnyEvent.TYPE_BUTTON_PRESS:
156 case XAnyEvent.TYPE_BUTTON_RELEASE:
157 return createMouseEvent(type, source);
158 case XAnyEvent.TYPE_UNMAP_NOTIFY:
159 case XAnyEvent.TYPE_MAP_NOTIFY:
160 case XAnyEvent.TYPE_REPARENT_NOTIFY:
161 return null; // ignore for now
162 case XAnyEvent.TYPE_CONFIGURE_NOTIFY:
163 configureNotify(peer);
164 return null;
165
166 default:
167 String msg = "Do no know how to handle event (" + anyEvent + ")";
168 throw new RuntimeException(msg);
169 }
170 }
171
172 AWTEvent createPaintEvent(Component src)
173 {
174 XExposeEvent expose = new XExposeEvent(anyEvent);
175 PaintEvent pe = new PaintEvent(src, PaintEvent.PAINT,
176 expose.getBounds());
177 return pe;
178 }
179
180 AWTEvent createMouseEvent(int type, Component src)
181 {
182 XButtonEvent buttonEvt = new XButtonEvent(anyEvent);
183
184 int modifiers = 0; //buttonToModifierMap[buttonEvt.button];
185
186 /* Warning: this makes assumptions on the contents of
187 X.h... Button1 = 1, Button2 = 2, etc... */
188 switch (buttonEvt.button)
189 {
190 case 1:
191 modifiers = InputEvent.BUTTON1_MASK;
192 break;
193 case 2:
194 modifiers = InputEvent.BUTTON2_MASK;
195 break;
196 case 3:
197 modifiers = InputEvent.BUTTON2_MASK;
198 break;
199 }
200
201 int state = buttonEvt.state;
202
203 // remap bits from state to modifiers:
204
205 if ((state & XButtonEvent.MASK_SHIFT) != 0)
206 modifiers |= InputEvent.SHIFT_MASK;
207
208
209 if ((state & XButtonEvent.MASK_CONTROL) != 0)
210 modifiers |= InputEvent.CTRL_MASK;
211
212
213 /* FIXME: we need additional X code to properly map MODn states to
214 input modifiers */
215
216 int clickCount = 1; // FIXME... Can't get this from X.
217 boolean popupTrigger = false; // FIXME: look up policy somewhere
218
219 int x = buttonEvt.x;
220 int y = buttonEvt.y;
221
222 int id = (type == XAnyEvent.TYPE_BUTTON_PRESS) ?
223 MouseEvent.MOUSE_PRESSED :
224 MouseEvent.MOUSE_RELEASED;
225
226 MouseEvent me = new MouseEvent(src,
227 id,
228 buttonEvt.time, modifiers,
229 buttonEvt.x, buttonEvt.y,
230 clickCount, popupTrigger);
231 return me;
232 }
233
234 void configureNotify(Object peerObj)
235 {
236 XConfigureEvent configEvent = new XConfigureEvent(anyEvent);
237 XFramePeer peer = (XFramePeer) peerObj;
238
239 peer.configureNotify(configEvent);
240 }
241
242 public void flushIfIdle()
243 {
244 if (isIdle())
245 display.flush();
246 }
247
248 volatile boolean idle = false;
249
250 final synchronized void setIdle(boolean idle)
251 {
252 this.idle = idle;
253 }
254
255 final synchronized boolean isIdle()
256 {
257 return idle;
258 }
259 }
This page took 0.044807 seconds and 5 git commands to generate.