package gnu.awt.xlib;
import java.awt.*;
import gnu.awt.LightweightRedirector;
import gnu.gcj.xlib.Display;
import gnu.gcj.xlib.XAnyEvent;
import gnu.gcj.xlib.XExposeEvent;
import gnu.gcj.xlib.XButtonEvent;
import gnu.gcj.xlib.XConfigureEvent;
import java.awt.event.PaintEvent;
import java.awt.event.InputEvent;
import java.awt.event.MouseEvent;
import java.util.Vector;
public class XEventLoop implements Runnable
{
Display display;
EventQueue queue;
XAnyEvent anyEvent;
Thread eventLoopThread;
LightweightRedirector lightweightRedirector = new LightweightRedirector();
public XEventLoop(Display display, EventQueue queue)
{
this.display = display;
this.queue = queue;
anyEvent = new XAnyEvent(display);
eventLoopThread = new Thread(this, "AWT thread for XEventLoop");
eventLoopThread.start();
}
public void run()
{
while (true)
postNextEvent();
}
void postNextEvent()
{
try
{
AWTEvent evt = getNextEvent();
queue.postEvent(evt);
}
catch (InterruptedException ie)
{
System.err.println(ie);
}
}
public AWTEvent getNextEvent()
{
if (isIdle())
throw new Error("should not be idle");
AWTEvent event = null;
while (event == null)
{
loadNextEvent();
event = createEvent();
}
event = lightweightRedirector.redirect(event);
return event;
}
void loadNextEvent()
{
try
{
setIdle(true);
anyEvent.loadNext();
}
catch (RuntimeException re)
{
System.err.println("Exception thrown on event thread:" + re);
}
finally
{
setIdle(false);
}
}
AWTEvent createEvent()
{
Object peer;
synchronized (this)
{
peer = anyEvent.getWindow().getClientData();
}
Component source = null;
if (peer instanceof XCanvasPeer)
{
source = ((XCanvasPeer) peer).getComponent();
}
if (source == null)
{
String msg = "unable to locate source for event (" +
anyEvent + ")";
throw new RuntimeException(msg);
}
int type = anyEvent.getType();
switch (type)
{
case XAnyEvent.TYPE_EXPOSE:
return createPaintEvent(source);
case XAnyEvent.TYPE_BUTTON_PRESS:
case XAnyEvent.TYPE_BUTTON_RELEASE:
return createMouseEvent(type, source);
case XAnyEvent.TYPE_UNMAP_NOTIFY:
case XAnyEvent.TYPE_MAP_NOTIFY:
case XAnyEvent.TYPE_REPARENT_NOTIFY:
return null; case XAnyEvent.TYPE_CONFIGURE_NOTIFY:
configureNotify(peer);
return null;
default:
String msg = "Do no know how to handle event (" + anyEvent + ")";
throw new RuntimeException(msg);
}
}
AWTEvent createPaintEvent(Component src)
{
XExposeEvent expose = new XExposeEvent(anyEvent);
PaintEvent pe = new PaintEvent(src, PaintEvent.PAINT,
expose.getBounds());
return pe;
}
AWTEvent createMouseEvent(int type, Component src)
{
XButtonEvent buttonEvt = new XButtonEvent(anyEvent);
int modifiers = 0;
switch (buttonEvt.button)
{
case 1:
modifiers = InputEvent.BUTTON1_MASK;
break;
case 2:
modifiers = InputEvent.BUTTON2_MASK;
break;
case 3:
modifiers = InputEvent.BUTTON2_MASK;
break;
}
int state = buttonEvt.state;
if ((state & XButtonEvent.MASK_SHIFT) != 0)
modifiers |= InputEvent.SHIFT_MASK;
if ((state & XButtonEvent.MASK_CONTROL) != 0)
modifiers |= InputEvent.CTRL_MASK;
int clickCount = 1; boolean popupTrigger = false;
int x = buttonEvt.x;
int y = buttonEvt.y;
int id = (type == XAnyEvent.TYPE_BUTTON_PRESS) ?
MouseEvent.MOUSE_PRESSED :
MouseEvent.MOUSE_RELEASED;
MouseEvent me = new MouseEvent(src,
id,
buttonEvt.time, modifiers,
buttonEvt.x, buttonEvt.y,
clickCount, popupTrigger);
return me;
}
void configureNotify(Object peerObj)
{
XConfigureEvent configEvent = new XConfigureEvent(anyEvent);
XFramePeer peer = (XFramePeer) peerObj;
peer.configureNotify(configEvent);
}
public void flushIfIdle()
{
if (isIdle())
display.flush();
}
volatile boolean idle = false;
final synchronized void setIdle(boolean idle)
{
this.idle = idle;
}
final synchronized boolean isIdle()
{
return idle;
}
}