mirror of
git://gcc.gnu.org/git/gcc.git
synced 2024-12-23 07:38:57 +08:00
2622c79d2d
* Makefile.am: Added rules for libgcjx library. * Makefile.in: Rebuilt. * configure.in: Added check for X. * configure: Rebuilt. * gnu/awt/LightweightRedirector.java: New file. * gnu/awt/j2d/AbstractGraphicsState.java: New file. * gnu/awt/j2d/DirectRasterGraphics.java: New file. * gnu/awt/j2d/Graphics2DImpl.java: New file. * gnu/awt/j2d/IntegerGraphicsState.java: New file. * gnu/awt/j2d/MappedRaster.java: New file. * gnu/awt/xlib/XCanvasPeer.java: New file. * gnu/awt/xlib/XEventLoop.java: New file. * gnu/awt/xlib/XEventQueue.java: New file. * gnu/awt/xlib/XFontMetrics.java: New file. * gnu/awt/xlib/XFramePeer.java: New file. * gnu/awt/xlib/XGraphics.java: New file. * gnu/awt/xlib/XGraphicsConfiguration.java: New file. * gnu/awt/xlib/XPanelPeer.java: New file. * gnu/awt/xlib/XToolkit.java: New file. * gnu/gcj/xlib/Clip.java: New file. * gnu/gcj/xlib/Colormap.java: New file. * gnu/gcj/xlib/Display.java: New file. * gnu/gcj/xlib/Drawable.java: New file. * gnu/gcj/xlib/Font.java: New file. * gnu/gcj/xlib/GC.java: New file. * gnu/gcj/xlib/Pixmap.java: New file. * gnu/gcj/xlib/Screen.java: New file. * gnu/gcj/xlib/Visual.java: New file. * gnu/gcj/xlib/WMSizeHints.java: New file. * gnu/gcj/xlib/Window.java: New file. * gnu/gcj/xlib/WindowAttributes.java: New file. * gnu/gcj/xlib/XAnyEvent.java: New file. * gnu/gcj/xlib/XButtonEvent.java: New file. * gnu/gcj/xlib/XColor.java: New file. * gnu/gcj/xlib/XConfigureEvent.java: New file. * gnu/gcj/xlib/XConnectException.java: New file. * gnu/gcj/xlib/XEvent.java: New file. * gnu/gcj/xlib/XException.java: New file. * gnu/gcj/xlib/XExposeEvent.java: New file. * gnu/gcj/xlib/XID.java: New file. * gnu/gcj/xlib/XImage.java: New file. * gnu/gcj/xlib/XUnmapEvent.java: New file. * gnu/gcj/xlib/natClip.cc: New file. * gnu/gcj/xlib/natColormap.cc: New file. * gnu/gcj/xlib/natDisplay.cc: New file. * gnu/gcj/xlib/natDrawable.cc: New file. * gnu/gcj/xlib/natFont.cc: New file. * gnu/gcj/xlib/natGC.cc: New file. * gnu/gcj/xlib/natPixmap.cc: New file. * gnu/gcj/xlib/natScreen.cc: New file. * gnu/gcj/xlib/natVisual.cc: New file. * gnu/gcj/xlib/natWMSizeHints.cc: New file. * gnu/gcj/xlib/natWindow.cc: New file. * gnu/gcj/xlib/natWindowAttributes.cc: New file. * gnu/gcj/xlib/natXAnyEvent.cc: New file. * gnu/gcj/xlib/natXButtonEvent.cc: New file. * gnu/gcj/xlib/natXColor.cc: New file. * gnu/gcj/xlib/natXConfigureEvent.cc: New file. * gnu/gcj/xlib/natXException.cc: New file. * gnu/gcj/xlib/natXExposeEvent.cc: New file. * gnu/gcj/xlib/natXImage.cc: New file. * gnu/gcj/xlib/natXUnmapEvent.cc: New file. * java/awt/EventDispatchThread.java: Start thead on creation. From-SVN: r37005
269 lines
6.3 KiB
Java
269 lines
6.3 KiB
Java
package gnu.awt.xlib;
|
|
|
|
/* Copyright (C) 2000 Free Software Foundation
|
|
|
|
This file is part of libgcj.
|
|
|
|
This software is copyrighted work licensed under the terms of the
|
|
Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
|
|
details. */
|
|
|
|
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)
|
|
{
|
|
// FIXME: what now?
|
|
System.err.println(ie);
|
|
}
|
|
}
|
|
|
|
/** get next event. Will block until events become available. */
|
|
|
|
public AWTEvent getNextEvent()
|
|
{
|
|
// ASSERT:
|
|
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);
|
|
|
|
/* The code below will result in an XFlush(). However,
|
|
while we are waiting for events after calling XFlush(),
|
|
new X requests issued on other threads will not
|
|
automatically be flushed. This can lead to a deadlock
|
|
since XFlush() will not be called before after the
|
|
processing of the next event, and new events arriving
|
|
might be dependent on the delivery of the X
|
|
requests.
|
|
|
|
Code that issues X requests should therefore call
|
|
flushIfIdle() after they're done, to ensure that the
|
|
requests are delivered in a timely manner. XFlush is not
|
|
run if event processing is underway, since we are assured
|
|
that the event loop execution will return to this point,
|
|
where requests are flushed again, before waiting for new
|
|
events.
|
|
|
|
Alternatively, do the work on the AWT thread, since the
|
|
XEventQueue knows how to flush the display when it runs out
|
|
of events. */
|
|
|
|
//display.flush(); // implicit?
|
|
anyEvent.loadNext();
|
|
}
|
|
catch (RuntimeException re)
|
|
{
|
|
System.err.println("Exception thrown on event thread:" + re);
|
|
}
|
|
finally
|
|
{
|
|
setIdle(false);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @returns an AWT event created based on the current XEvent.
|
|
* Returns null if the current XEvent does not map to any perticular
|
|
* AWT event.
|
|
*/
|
|
|
|
AWTEvent createEvent()
|
|
{
|
|
/* avoid attempting to get client data before client data has
|
|
been set. */
|
|
Object peer;
|
|
synchronized (this)
|
|
{
|
|
peer = anyEvent.getWindow().getClientData();
|
|
}
|
|
|
|
Component source = null;
|
|
|
|
// Try to identify source component
|
|
|
|
if (peer instanceof XCanvasPeer)
|
|
{
|
|
source = ((XCanvasPeer) peer).getComponent();
|
|
}
|
|
|
|
if (source == null)
|
|
{
|
|
String msg = "unable to locate source for event (" +
|
|
anyEvent + ")";
|
|
throw new RuntimeException(msg);
|
|
}
|
|
|
|
/* if a mapping from anyEvent to AWTEvent is possible, construct a
|
|
new AWTEvent and return it. */
|
|
|
|
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; // ignore for now
|
|
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; //buttonToModifierMap[buttonEvt.button];
|
|
|
|
/* Warning: this makes assumptions on the contents of
|
|
X.h... Button1 = 1, Button2 = 2, etc... */
|
|
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;
|
|
|
|
// remap bits from state to modifiers:
|
|
|
|
if ((state & XButtonEvent.MASK_SHIFT) != 0)
|
|
modifiers |= InputEvent.SHIFT_MASK;
|
|
|
|
|
|
if ((state & XButtonEvent.MASK_CONTROL) != 0)
|
|
modifiers |= InputEvent.CTRL_MASK;
|
|
|
|
|
|
/* FIXME: we need additional X code to properly map MODn states to
|
|
input modifiers */
|
|
|
|
int clickCount = 1; // FIXME... Can't get this from X.
|
|
boolean popupTrigger = false; // FIXME: look up policy somewhere
|
|
|
|
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;
|
|
}
|
|
}
|