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
{
Display display;
EventQueue queue;
XAnyEvent anyEvent;
LightweightRedirector lightweightRedirector = new LightweightRedirector();
public XEventLoop(Display display, EventQueue queue)
{
this.display = display;
this.queue = queue;
anyEvent = new XAnyEvent(display);
}
void interrupt()
{
anyEvent.interrupt();
}
void postNextEvent(boolean block)
{
AWTEvent evt = getNextEvent(block);
if (evt != null)
queue.postEvent(evt);
}
public AWTEvent getNextEvent(boolean block)
{
if (isIdle())
throw new Error("should not be idle");
AWTEvent event = null;
if (loadNextEvent(block))
{
event = createEvent();
event = lightweightRedirector.redirect(event);
}
return event;
}
boolean loadNextEvent(boolean block)
{
boolean gotEvent = false;
try
{
setIdle(true);
gotEvent = anyEvent.loadNext(block);
}
catch (RuntimeException re)
{
System.err.println("Exception thrown on event thread:" + re);
}
finally
{
setIdle(false);
}
return gotEvent;
}
AWTEvent createEvent ()
{
int type = anyEvent.getType ();
switch (type)
{
case XAnyEvent.TYPE_NO_EXPOSE:
case XAnyEvent.TYPE_UNMAP_NOTIFY: case XAnyEvent.TYPE_MAP_NOTIFY: case XAnyEvent.TYPE_REPARENT_NOTIFY: return null;
default:
break; }
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 + "): peer=" + peer;
throw new RuntimeException (msg);
}
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_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_DOWN_MASK;
break;
case 2:
modifiers = InputEvent.BUTTON2_DOWN_MASK;
break;
case 3:
modifiers = InputEvent.BUTTON2_DOWN_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;
}
}