1 /* Copyright (C) 2000, 2002, 2003 Free Software Foundation
3 This file is part of libgcj.
5 This software is copyrighted work licensed under the terms of the
6 Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
11 import java.awt.Dimension;
12 import java.awt.BufferCapabilities;
13 import java.awt.Component;
14 import java.awt.EventQueue;
15 import java.awt.Rectangle;
16 import java.awt.Color;
17 import java.awt.Container;
18 import java.awt.Image;
19 import java.awt.GraphicsConfiguration;
21 import java.awt.FontMetrics;
22 import java.awt.Graphics;
23 import java.awt.Point;
24 import java.awt.Toolkit;
25 import java.awt.AWTEvent;
26 import java.awt.Cursor;
27 import java.awt.Shape;
29 import java.awt.peer.*;
30 import java.awt.image.*;
32 import java.awt.event.MouseListener;
33 import java.awt.event.PaintEvent;
35 import java.util.EventListener;
37 import gnu.gcj.xlib.WMSizeHints;
38 import gnu.gcj.xlib.Window;
39 import gnu.gcj.xlib.WindowAttributes;
40 import gnu.gcj.xlib.Display;
41 import gnu.gcj.xlib.Visual;
42 import gnu.gcj.xlib.Screen;
43 import gnu.gcj.xlib.XImage;
47 public class XCanvasPeer implements CanvasPeer
49 static final Dimension MIN_SIZE = new Dimension(1, 1);
57 XGraphicsConfiguration config;
58 private WindowAttributes attributes = new WindowAttributes();
59 private long eventMask;
61 public XCanvasPeer(Component component)
63 this.component = component;
65 // Set up graphics configuration (ie. screen + visual):
67 config = (XGraphicsConfiguration)
68 component.getGraphicsConfiguration();
72 // This will usually only happen for toplevel windows
73 config = getXToolkit().getDefaultXGraphicsConfiguration();
76 Rectangle bounds = component.getBounds();
77 parent = locateParentWindow(bounds);
79 // Windows in X must atleast be of size 1x1
80 boolean boundsChanged = false;
86 if (bounds.height < 1)
92 /* don't worry about this calling back to us, since the real
93 component object has not yet received a reference to this peer
95 component.setBounds(bounds);
98 /* Set background color */
99 Color bg = component.getBackground();
110 ColorModel cm = config.getColorModel();
111 long pixel = cm.getDataElement(components, 0);
112 attributes.setBackground(pixel);
115 /* Set exposure mask so that we get exposure events
116 that can be translated into paint() calls. */
117 long eventMask = WindowAttributes.MASK_EXPOSURE;
119 /* It would be nice to set up all other required events here, but
120 it is not possible to do so before after all the children of
121 this component has been realized. The reason is that it is not
122 determined whether a component is lightweight before after the
123 addNotify() method has been called. Thus, it is not possible
124 for parent component to determine what events it needs to
125 furnish for lightweight children. Instead, we currently rely
126 on the component calling our setEventMask() method after the
127 correct event mask has been determined. */
129 attributes.setEventMask(eventMask);
132 // TODO: set more window attributes?
134 /* don't allow event queue to process events from the newly
135 created window before this peer has been registered as client
137 synchronized (getXToolkit().eventLoop)
139 window = new gnu.gcj.xlib.Window(parent, bounds, attributes);
140 window.setClientData(this); /* make it possible to find back
141 to this peer object. Used by
145 initWindowProperties();
147 if (component.isVisible())
148 EventQueue.invokeLater(new DoMap(window));
152 * Override this in subclasses to implement other ways of obtaining
153 * parent windows. Toplevel windows will typically have a different
156 gnu.gcj.xlib.Window locateParentWindow(Rectangle bounds)
158 Container parent = component.getParent();
159 while (parent.isLightweight())
161 bounds.x += parent.getX();
162 bounds.y += parent.getY();
163 parent = parent.getParent();
164 // a null pointer here is a genuine error
167 XCanvasPeer parentPeer = (XCanvasPeer) parent.getPeer();
168 if (parentPeer == null)
169 throw new NullPointerException("Parent has no peer. This should " +
170 "not be possible, since the " +
171 "calls leading here should come " +
172 "from parent, after it has " +
173 "set the parent peer.");
174 return parentPeer.window;
179 * Template method to allow subclasses to apply properties to X11
180 * window right after creation.
182 void initWindowProperties()
186 XToolkit getXToolkit()
188 return XToolkit.INSTANCE;
191 protected void ensureFlush()
193 getXToolkit().flushIfIdle();
196 public Component getComponent()
201 long getBasicEventMask()
203 return WindowAttributes.MASK_EXPOSURE;
206 // -------- java.awt.peer.ComponentPeer implementation
208 public int checkImage(Image img, int width, int height, ImageObserver o)
210 throw new UnsupportedOperationException("FIXME, not implemented");
212 public Image createImage(ImageProducer prod)
214 return new XOffScreenImage (config, window, prod, config.getColorModel());
216 public Image createImage(int width, int height)
218 return new XOffScreenImage (config, window, width, height, config.getColorModel());
220 public void dispose()
222 throw new UnsupportedOperationException("FIXME, not implemented");
225 public GraphicsConfiguration getGraphicsConfiguration()
230 public FontMetrics getFontMetrics(Font f)
232 throw new UnsupportedOperationException("FIXME, not implemented");
235 public ColorModel getColorModel ()
240 public Graphics getGraphics()
242 DirectRasterGraphics gfxDevice = new XGraphics(window, config);
243 IntegerGraphicsState igState = new IntegerGraphicsState(gfxDevice);
244 Graphics2DImpl gfx2d = new Graphics2DImpl(config);
246 gfx2d.setState(igState);
247 gfx2d.setColor(component.getBackground());
251 public Point getLocationOnScreen()
253 throw new UnsupportedOperationException("FIXME, not implemented");
256 public Dimension getMinimumSize ()
261 public Dimension minimumSize ()
263 return getMinimumSize ();
266 public Dimension getPreferredSize ()
268 return component.getSize();
271 public Dimension preferredSize ()
273 return getPreferredSize();
276 public Toolkit getToolkit()
278 return getXToolkit();
281 public void handleEvent(AWTEvent event)
283 int id = event.getID ();
287 case PaintEvent.PAINT:
288 case PaintEvent.UPDATE:
292 Graphics g = getGraphics ();
293 g.setClip (((PaintEvent)event).getUpdateRect ());
295 if (id == PaintEvent.PAINT)
298 component.update (g);
302 catch (InternalError e)
304 System.err.println (e);
311 public boolean isFocusTraversable()
313 throw new UnsupportedOperationException("FIXME, not implemented");
316 public void paint(Graphics gfx)
318 // do nothing by default
321 public boolean prepareImage(Image img, int width, int height,
324 throw new UnsupportedOperationException("FIXME, not implemented");
327 public void print(Graphics graphics)
332 public void repaint(long tm, int x, int y, int w, int h)
336 X allows intelligent X servers to do smart
337 refreshing. Perhaps involve X in repainting of components,
338 rather that keeping it all within the local event queue. */
340 PaintEvent updateEvent = new PaintEvent(component,
342 new Rectangle(x, y, w, h));
343 getXToolkit().queue.postEvent(updateEvent);
346 public void requestFocus()
348 throw new UnsupportedOperationException("FIXME, not implemented");
351 public void setBackground(Color color)
363 ColorModel cm = config.getColorModel ();
364 long pixel = cm.getDataElement (components, 0);
365 attributes.setBackground (pixel);
366 window.setAttributes (attributes);
370 public void setBounds(int x, int y, int width, int height)
372 width = Math.max(width, 1);
373 height = Math.max(height, 1);
374 window.setBounds(x, y, width, height);
378 public void reshape (int x, int y, int width, int height)
380 setBounds (x, y, width, height);
383 public void setCursor(Cursor cursor)
385 throw new UnsupportedOperationException("FIXME, not implemented");
388 public void setEnabled(boolean enabled)
390 throw new UnsupportedOperationException("FIXME, not implemented");
393 public void enable ()
398 public void disable ()
403 public void setEventMask(long eventMask)
405 if (this.eventMask != eventMask)
407 this.eventMask = eventMask;
408 long xEventMask = getBasicEventMask ();
410 if ((eventMask & AWTEvent.MOUSE_EVENT_MASK) != 0)
413 WindowAttributes.MASK_BUTTON_PRESS |
414 WindowAttributes.MASK_BUTTON_RELEASE;
417 attributes.setEventMask (xEventMask);
418 window.setAttributes (attributes);
423 public void setFont(Font font)
425 /* default canvas peer does not keep track of font, since it won't
429 public void setForeground(Color color)
431 /* default canvas peer does not keep track of foreground, since it won't
435 public void setVisible(boolean visible)
459 public boolean isFocusable ()
464 public boolean requestFocus (Component source, boolean b1,
470 public boolean isObscured ()
475 public boolean canDetermineObscurity ()
480 public void coalescePaintEvent (PaintEvent e)
484 public void updateCursorImmediately ()
488 public VolatileImage createVolatileImage (int width, int height)
493 public boolean handlesWheelScrolling ()
498 public void createBuffers (int x, BufferCapabilities capabilities)
499 throws java.awt.AWTException
504 public Image getBackBuffer ()
509 public void flip (BufferCapabilities.FlipContents contents)
513 public void destroyBuffers ()
517 static class DoMap implements Runnable
520 public DoMap(Window w)
534 public boolean isRestackSupported ()
542 public void cancelPendingPaint (int x, int y, int width, int height)
549 public void restack ()
556 public Rectangle getBounds ()
564 public void reparent (ContainerPeer parent)
571 public void setBounds (int x, int y, int width, int height, int z)
578 public boolean isReparentSupported ()
586 public void layout ()