OSDN Git Service

74e0dc2121271dbf7cf541fc80342b1e63769192
[pf3gnuchains/gcc-fork.git] / libjava / gnu / awt / xlib / XCanvasPeer.java
1 /* Copyright (C) 2000, 2002, 2003  Free Software Foundation
2
3    This file is part of libgcj.
4
5 This software is copyrighted work licensed under the terms of the
6 Libgcj License.  Please consult the file "LIBGCJ_LICENSE" for
7 details.  */
8
9 package gnu.awt.xlib;
10
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;
20 import java.awt.Font;
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;
28
29 import java.awt.peer.*;
30 import java.awt.image.*;
31
32 import java.awt.event.MouseListener;
33 import java.awt.event.PaintEvent;
34
35 import java.util.EventListener;
36
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;
44
45 import gnu.awt.j2d.*;
46
47 public class XCanvasPeer implements CanvasPeer
48 {
49   static final Dimension MIN_SIZE = new Dimension(1, 1);
50   
51   public // temporary
52   
53   Window window;
54   Window parent;
55
56   Component component;
57   XGraphicsConfiguration config;
58   private WindowAttributes attributes = new WindowAttributes();
59   private long eventMask;
60   
61   public XCanvasPeer(Component component)
62   {
63     this.component = component;
64     
65     // Set up graphics configuration (ie. screen + visual):
66
67     config = (XGraphicsConfiguration)
68       component.getGraphicsConfiguration();
69
70     if (config == null)
71       {
72         // This will usually only happen for toplevel windows
73         config = getXToolkit().getDefaultXGraphicsConfiguration();
74       } 
75
76     Rectangle bounds = component.getBounds();
77     parent = locateParentWindow(bounds);
78         
79     // Windows in X must atleast be of size 1x1
80     boolean boundsChanged = false;
81     if (bounds.width < 1)
82       {
83         boundsChanged = true;
84         bounds.width = 1;
85       }
86     if (bounds.height < 1)
87       {
88         boundsChanged = true;
89         bounds.height = 1;
90       }
91         
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
94        object. */
95     component.setBounds(bounds);
96             
97
98     /* Set background color */
99     Color bg = component.getBackground();
100     if (bg != null)
101       {
102         int[] components =
103         {
104           bg.getRed(),
105           bg.getGreen(),
106           bg.getBlue(),
107           0xff
108         };
109
110         ColorModel cm = config.getColorModel();
111         long pixel = cm.getDataElement(components, 0);
112         attributes.setBackground(pixel);
113       }
114         
115     /* Set exposure mask so that we get exposure events
116        that can be translated into paint() calls. */
117     long eventMask = WindowAttributes.MASK_EXPOSURE;
118
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. */
128
129     attributes.setEventMask(eventMask);
130         
131             
132     // TODO: set more window attributes?
133
134     /* don't allow event queue to process events from the newly
135        created window before this peer has been registered as client
136        data. */
137     synchronized (getXToolkit().eventLoop)
138       {
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
142                                        XEventQueue. */
143       }
144     
145     initWindowProperties();
146
147     if (component.isVisible())
148       EventQueue.invokeLater(new DoMap(window));
149   }
150
151   /**
152    * Override this in subclasses to implement other ways of obtaining
153    * parent windows.  Toplevel windows will typically have a different
154    * implementation.
155    */
156   gnu.gcj.xlib.Window locateParentWindow(Rectangle bounds)
157   {
158     Container parent = component.getParent();
159     while (parent.isLightweight())
160       {
161         bounds.x += parent.getX();
162         bounds.y += parent.getY();
163         parent = parent.getParent();
164         // a null pointer here is a genuine error
165       }
166     
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;
175   }
176     
177
178   /** 
179    * Template method to allow subclasses to apply properties to X11
180    * window right after creation.
181    */
182   void initWindowProperties()
183   {
184   }
185     
186   XToolkit getXToolkit()
187   {
188     return XToolkit.INSTANCE;
189   }
190
191   protected void ensureFlush()
192   {
193     getXToolkit().flushIfIdle();
194   }
195
196   public Component getComponent()
197   {
198     return component;
199   }
200   
201   long getBasicEventMask()
202   {
203     return WindowAttributes.MASK_EXPOSURE;
204   }
205     
206   // -------- java.awt.peer.ComponentPeer implementation
207
208   public int checkImage(Image img, int width, int height, ImageObserver o)
209   {
210     throw new UnsupportedOperationException("FIXME, not implemented");
211   }
212   public Image createImage(ImageProducer prod)
213   {
214     return new XOffScreenImage (config, window, prod, config.getColorModel());
215   }
216   public Image createImage(int width, int height)
217   {
218     return new XOffScreenImage (config, window, width, height, config.getColorModel());
219   }
220   public void dispose()
221   {
222     throw new UnsupportedOperationException("FIXME, not implemented");
223   }
224
225   public GraphicsConfiguration getGraphicsConfiguration()
226   {
227     return config;
228   }
229
230   public FontMetrics getFontMetrics(Font f)
231   {
232     throw new UnsupportedOperationException("FIXME, not implemented");
233   }
234
235   public ColorModel getColorModel ()
236   {
237     return null;
238   }
239
240   public Graphics getGraphics()
241   {
242     DirectRasterGraphics gfxDevice = new XGraphics(window, config);
243     IntegerGraphicsState igState = new IntegerGraphicsState(gfxDevice);
244     Graphics2DImpl gfx2d = new Graphics2DImpl(config);
245
246     gfx2d.setState(igState);
247     gfx2d.setColor(component.getBackground());
248     return gfx2d;
249   }
250     
251   public Point getLocationOnScreen()
252   {
253     throw new UnsupportedOperationException("FIXME, not implemented");
254   }
255
256   public Dimension getMinimumSize ()
257   {
258     return MIN_SIZE;
259   }
260
261   public Dimension minimumSize ()
262   {
263     return getMinimumSize ();
264   }
265
266   public Dimension getPreferredSize ()
267   {
268     return component.getSize();
269   }
270     
271   public Dimension preferredSize ()
272   {
273     return getPreferredSize();
274   }
275     
276   public Toolkit getToolkit()
277   {
278     return getXToolkit();
279   }
280
281   public void handleEvent(AWTEvent event)
282   {
283     int id = event.getID ();
284     
285     switch (id)
286     {
287       case PaintEvent.PAINT:
288       case PaintEvent.UPDATE:
289       {
290         try
291         {
292           Graphics g = getGraphics ();
293           g.setClip (((PaintEvent)event).getUpdateRect ());
294           
295           if (id == PaintEvent.PAINT)
296             component.paint (g);
297           else
298             component.update (g);
299           
300           g.dispose ();
301         }
302         catch (InternalError e)
303         {
304           System.err.println (e);
305         }
306       }
307       break;
308     }
309   }
310
311   public boolean isFocusTraversable()
312   {
313     throw new UnsupportedOperationException("FIXME, not implemented");
314   }
315
316   public void paint(Graphics gfx)
317   {
318     // do nothing by default
319   }
320     
321   public boolean prepareImage(Image img, int width, int height,
322                               ImageObserver o)
323   {
324     throw new UnsupportedOperationException("FIXME, not implemented");
325   }
326
327   public void print(Graphics graphics)
328   {
329     paint(graphics);
330   }
331
332   public void repaint(long tm, int x, int y, int w, int h)
333   {
334     /* TODO?
335
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. */
339     
340     PaintEvent updateEvent = new PaintEvent(component,
341                                             PaintEvent.UPDATE,
342                                             new Rectangle(x, y, w, h));
343     getXToolkit().queue.postEvent(updateEvent);
344   }
345     
346   public void requestFocus()
347   {
348     throw new UnsupportedOperationException("FIXME, not implemented");
349   }
350
351   public void setBackground(Color color)
352   {
353     if (color != null)
354     {
355       int[] components =
356       {
357         color.getRed (),
358         color.getGreen (),
359         color.getBlue (),
360         0xff
361       };
362       
363       ColorModel cm = config.getColorModel ();
364       long pixel = cm.getDataElement (components, 0);
365       attributes.setBackground (pixel);
366       window.setAttributes (attributes);
367     }
368   }
369
370   public void setBounds(int x, int y, int width, int height)
371   {
372     width  = Math.max(width,  1);
373     height = Math.max(height, 1);
374     window.setBounds(x, y, width, height);
375     ensureFlush();          
376   }
377     
378   public void reshape (int x, int y, int width, int height)
379   {
380     setBounds (x, y, width, height);
381   }
382
383   public void setCursor(Cursor cursor)
384   {
385     throw new UnsupportedOperationException("FIXME, not implemented");
386   }
387
388   public void setEnabled(boolean enabled)
389   {
390     throw new UnsupportedOperationException("FIXME, not implemented");
391   }
392
393   public void enable ()
394   {
395     setEnabled (true);
396   }
397
398   public void disable ()
399   {
400     setEnabled (false);
401   }
402
403   public void setEventMask(long eventMask)
404   {
405     if (this.eventMask != eventMask)
406     {
407       this.eventMask = eventMask;
408       long xEventMask = getBasicEventMask ();
409       
410       if ((eventMask & AWTEvent.MOUSE_EVENT_MASK) != 0)
411       {
412         xEventMask |=
413           WindowAttributes.MASK_BUTTON_PRESS |
414           WindowAttributes.MASK_BUTTON_RELEASE;
415       }
416       
417       attributes.setEventMask (xEventMask);
418       window.setAttributes (attributes);
419       ensureFlush ();
420     }
421   }
422
423   public void setFont(Font font)
424   {
425     /* default canvas peer does not keep track of font, since it won't
426        paint anything. */
427   }
428
429   public void setForeground(Color color)
430   {
431     /* default canvas peer does not keep track of foreground, since it won't
432        paint anything. */
433   }
434         
435   public void setVisible(boolean visible)
436   {
437     if (visible)
438       {
439         window.map();
440         ensureFlush();      
441       }
442     else
443       {
444         window.unmap();
445         ensureFlush();      
446       }
447   }
448         
449   public void show ()
450   {
451     setVisible (true);
452   }
453
454   public void hide ()
455   {
456     setVisible (false);
457   }
458
459   public boolean isFocusable ()
460   {
461     return false;
462   }
463
464   public boolean requestFocus (Component source, boolean b1, 
465                                boolean b2, long x)
466   {
467     return false;
468   }
469
470   public boolean isObscured ()
471   {
472     return false;
473   }
474
475   public boolean canDetermineObscurity ()
476   {
477     return false;
478   }
479
480   public void coalescePaintEvent (PaintEvent e)
481   {
482   }
483
484   public void updateCursorImmediately ()
485   {
486   }
487
488   public VolatileImage createVolatileImage (int width, int height)
489   {
490     return null;
491   }
492
493   public boolean handlesWheelScrolling ()
494   {
495     return false;
496   }
497
498   public void createBuffers (int x, BufferCapabilities capabilities)
499     throws java.awt.AWTException
500
501   {
502   }
503
504   public Image getBackBuffer ()
505   {
506     return null;
507   }
508
509   public void flip (BufferCapabilities.FlipContents contents)
510   {
511   }
512
513   public void destroyBuffers ()
514   {
515   }
516
517   static class DoMap implements Runnable 
518   {
519     Window window;
520     public DoMap(Window w) 
521     {
522       this.window = w;
523     }
524     
525     public void run() 
526     {
527       window.map();
528     }
529   }
530
531   /**
532    * @since 1.5
533    */
534   public boolean isRestackSupported ()
535   {
536     return false;
537   }
538
539   /**
540    * @since 1.5
541    */
542   public void cancelPendingPaint (int x, int y, int width, int height)
543   {
544   }
545
546   /**
547    * @since 1.5
548    */
549   public void restack ()
550   {
551   }
552
553   /**
554    * @since 1.5
555    */
556   public Rectangle getBounds ()
557   {
558     return null;
559   }
560
561   /**
562    * @since 1.5
563    */
564   public void reparent (ContainerPeer parent)
565   {
566   }
567
568   /**
569    * @since 1.5
570    */
571   public void setBounds (int x, int y, int width, int height, int z)
572   {
573   }
574
575   /**
576    * @since 1.5
577    */
578   public boolean isReparentSupported ()
579   {
580     return false;
581   }
582
583   /**
584    * @since 1.5
585    */
586   public void layout ()
587   {
588   }
589 }