diff options
Diffstat (limited to 'libjava/gnu/awt/xlib/XCanvasPeer.java')
-rw-r--r-- | libjava/gnu/awt/xlib/XCanvasPeer.java | 388 |
1 files changed, 388 insertions, 0 deletions
diff --git a/libjava/gnu/awt/xlib/XCanvasPeer.java b/libjava/gnu/awt/xlib/XCanvasPeer.java new file mode 100644 index 00000000000..5674f5bf2ad --- /dev/null +++ b/libjava/gnu/awt/xlib/XCanvasPeer.java @@ -0,0 +1,388 @@ +/* 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. */ + +package gnu.awt.xlib; + +import java.awt.Dimension; +import java.awt.Component; +import java.awt.EventQueue; +import java.awt.Rectangle; +import java.awt.Color; +import java.awt.Container; +import java.awt.Image; +import java.awt.GraphicsConfiguration; +import java.awt.Font; +import java.awt.FontMetrics; +import java.awt.Graphics; +import java.awt.Point; +import java.awt.Toolkit; +import java.awt.AWTEvent; +import java.awt.Cursor; +import java.awt.Shape; + +import java.awt.peer.*; +import java.awt.image.*; + +import java.awt.event.MouseListener; +import java.awt.event.PaintEvent; + +import java.util.EventListener; + +import gnu.gcj.xlib.WMSizeHints; +import gnu.gcj.xlib.Window; +import gnu.gcj.xlib.WindowAttributes; +import gnu.gcj.xlib.Display; +import gnu.gcj.xlib.Visual; +import gnu.gcj.xlib.Screen; +import gnu.gcj.xlib.XImage; + +import gnu.awt.j2d.*; + +public class XCanvasPeer implements CanvasPeer +{ + static final Dimension MIN_SIZE = new Dimension(1, 1); + + public // temporary + + Window window; + Window parent; + + Component component; + XGraphicsConfiguration config; + + public XCanvasPeer(Component component) + { + this.component = component; + + // Set up graphics configuration (ie. screen + visual): + + config = (XGraphicsConfiguration) + component.getGraphicsConfiguration(); + + if (config == null) + { + // This will usually only happen for toplevel windows + config = getXToolkit().getDefaultXGraphicsConfiguration(); + } + + Rectangle bounds = component.getBounds(); + parent = locateParentWindow(bounds); + + // Windows in X must atleast be of size 1x1 + boolean boundsChanged = false; + if (bounds.width < 1) + { + boundsChanged = true; + bounds.width = 1; + } + if (bounds.height < 1) + { + boundsChanged = true; + bounds.height = 1; + } + + /* don't worry about this calling back to us, since the real + component object has not yet received a reference to this peer + object. */ + component.setBounds(bounds); + + WindowAttributes attributes = new WindowAttributes(); + + /* Set background color */ + Color bg = component.getBackground(); + if (bg != null) + { + int[] components = + { + bg.getRed(), + bg.getGreen(), + bg.getBlue(), + 0xff + }; + + ColorModel cm = config.getColorModel(); + long pixel = cm.getDataElement(components, 0); + attributes.setBackground(pixel); + } + + /* Set exposure mask so that we get exposure events + that can be translated into paint() calls. */ + long eventMask = WindowAttributes.MASK_EXPOSURE; + + /* It would be nice to set up all other required events here, but + it is not possible to do so before after all the children of + this component has been realized. The reason is that it is not + determined whether a component is lightweight before after the + addNotify() method has been called. Thus, it is not possible + for parent component to determine what events it needs to + furnish for lightweight children. Instead, we currently rely + on the component calling our setEventMask() method after the + correct event mask has been determined. */ + + attributes.setEventMask(eventMask); + + + // TODO: set more window attributes? + + /* don't allow event queue to process events from the newly + created window before this peer has been registered as client + data. */ + synchronized (getXToolkit().eventLoop) + { + window = new gnu.gcj.xlib.Window(parent, bounds, attributes); + window.setClientData(this); /* make it possible to find back + to this peer object. Used by + XEventQueue. */ + } + + initWindowProperties(); + + if (component.isVisible()) + EventQueue.invokeLater(new DoMap(window)); + } + + /** + * Override this in subclasses to implement other ways of obtaining + * parent windows. Toplevel windows will typically have a different + * implementation. + */ + gnu.gcj.xlib.Window locateParentWindow(Rectangle bounds) + { + Container parent = component.getParent(); + while (parent.isLightweight()) + { + bounds.x += parent.getX(); + bounds.y += parent.getY(); + parent = parent.getParent(); + // a null pointer here is a genuine error + } + + XCanvasPeer parentPeer = (XCanvasPeer) parent.getPeer(); + if (parentPeer == null) + throw new NullPointerException("Parent has no peer. This should " + + "not be possible, since the " + + "calls leading here should come " + + "from parent, after it has " + + "set the parent peer."); + return parentPeer.window; + } + + + /** + * Template method to allow subclasses to apply properties to X11 + * window right after creation. + */ + void initWindowProperties() + { + } + + XToolkit getXToolkit() + { + return XToolkit.INSTANCE; + } + + protected void ensureFlush() + { + getXToolkit().flushIfIdle(); + } + + public Component getComponent() + { + return component; + } + + long getBasicEventMask() + { + return WindowAttributes.MASK_EXPOSURE; + } + + // -------- java.awt.peer.ComponentPeer implementation + + public int checkImage(Image img, int width, int height, ImageObserver o) + { + throw new UnsupportedOperationException("FIXME, not implemented"); + } + public Image createImage(ImageProducer prod) + { + throw new UnsupportedOperationException("FIXME, not implemented"); + } + public Image createImage(int width, int height) + { + throw new UnsupportedOperationException("FIXME, not implemented"); + } + public void dispose() + { + throw new UnsupportedOperationException("FIXME, not implemented"); + } + + public GraphicsConfiguration getGraphicsConfiguration() + { + return config; + } + + public FontMetrics getFontMetrics(Font f) + { + throw new UnsupportedOperationException("FIXME, not implemented"); + } + + public Graphics getGraphics() + { + DirectRasterGraphics gfxDevice = new XGraphics(window, config); + IntegerGraphicsState igState = new IntegerGraphicsState(gfxDevice); + Graphics2DImpl gfx2d = new Graphics2DImpl(config); + + gfx2d.setState(igState); + gfx2d.setColor(component.getBackground()); + return gfx2d; + } + + public Point getLocationOnScreen() + { + throw new UnsupportedOperationException("FIXME, not implemented"); + } + + public Dimension getMinimumSize () + { + return MIN_SIZE; + } + + public Dimension getPreferredSize () + { + return component.getSize(); + } + + public Toolkit getToolkit() + { + return getXToolkit(); + } + + public void handleEvent(AWTEvent event) + { + } + + public boolean isFocusTraversable() + { + throw new UnsupportedOperationException("FIXME, not implemented"); + } + + public void paint(Graphics gfx) + { + // do nothing by default + } + + public boolean prepareImage(Image img, int width, int height, + ImageObserver o) + { + throw new UnsupportedOperationException("FIXME, not implemented"); + } + + public void print(Graphics graphics) + { + paint(graphics); + } + + public void repaint(long tm, int x, int y, int w, int h) + { + /* TODO? + + X allows intelligent X servers to do smart + refreshing. Perhaps involve X in repainting of components, + rather that keeping it all within the local event queue. */ + + PaintEvent updateEvent = new PaintEvent(component, + PaintEvent.UPDATE, + new Rectangle(x, y, w, h)); + getXToolkit().queue.postEvent(updateEvent); + } + + public void requestFocus() + { + throw new UnsupportedOperationException("FIXME, not implemented"); + } + + public void setBackground(Color color) + { + throw new UnsupportedOperationException("not implemented"); + } + + public void setBounds(int x, int y, int width, int height) + { + width = Math.max(width, 1); + height = Math.max(height, 1); + window.setBounds(x, y, width, height); + ensureFlush(); + } + + public void setCursor(Cursor cursor) + { + throw new UnsupportedOperationException("FIXME, not implemented"); + } + + public void setEnabled(boolean enabled) + { + throw new UnsupportedOperationException("FIXME, not implemented"); + } + + public void setEventMask(long eventMask) + { + WindowAttributes attributes = new WindowAttributes(); + + long xEventMask = getBasicEventMask(); + + if ((eventMask & AWTEvent.MOUSE_EVENT_MASK) != 0) + { + xEventMask |= + WindowAttributes.MASK_BUTTON_PRESS | + WindowAttributes.MASK_BUTTON_RELEASE; + } + + attributes.setEventMask(xEventMask); + window.setAttributes(attributes); + ensureFlush(); + } + + public void setFont(Font font) + { + /* default canvas peer does keep track of font, since it won't + write anything. */ + } + + public void setForeground(Color color) + { + /* default canvas peer does keep track of foreground, since it won't + paint anything. */ + } + + public void setVisible(boolean visible) + { + if (visible) + { + window.map(); + ensureFlush(); + } + else + { + throw new UnsupportedOperationException("unmap not implemented"); + } + } + + static class DoMap implements Runnable + { + Window window; + public DoMap(Window w) + { + this.window = w; + } + + public void run() + { + window.map(); + } + } +} + |