mirror of git://gcc.gnu.org/git/gcc.git
				
				
				
			
		
			
				
	
	
		
			921 lines
		
	
	
		
			26 KiB
		
	
	
	
		
			Java
		
	
	
	
			
		
		
	
	
			921 lines
		
	
	
		
			26 KiB
		
	
	
	
		
			Java
		
	
	
	
/* GtkComponentPeer.java -- Implements ComponentPeer with GTK
 | 
						|
   Copyright (C) 1998, 1999, 2002, 2004, 2005, 2006
 | 
						|
   Free Software Foundation, Inc.
 | 
						|
 | 
						|
This file is part of GNU Classpath.
 | 
						|
 | 
						|
GNU Classpath is free software; you can redistribute it and/or modify
 | 
						|
it under the terms of the GNU General Public License as published by
 | 
						|
the Free Software Foundation; either version 2, or (at your option)
 | 
						|
any later version.
 | 
						|
 | 
						|
GNU Classpath is distributed in the hope that it will be useful, but
 | 
						|
WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
						|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 | 
						|
General Public License for more details.
 | 
						|
 | 
						|
You should have received a copy of the GNU General Public License
 | 
						|
along with GNU Classpath; see the file COPYING.  If not, write to the
 | 
						|
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 | 
						|
02110-1301 USA.
 | 
						|
 | 
						|
Linking this library statically or dynamically with other modules is
 | 
						|
making a combined work based on this library.  Thus, the terms and
 | 
						|
conditions of the GNU General Public License cover the whole
 | 
						|
combination.
 | 
						|
 | 
						|
As a special exception, the copyright holders of this library give you
 | 
						|
permission to link this library with independent modules to produce an
 | 
						|
executable, regardless of the license terms of these independent
 | 
						|
modules, and to copy and distribute the resulting executable under
 | 
						|
terms of your choice, provided that you also meet, for each linked
 | 
						|
independent module, the terms and conditions of the license of that
 | 
						|
module.  An independent module is a module which is not derived from
 | 
						|
or based on this library.  If you modify this library, you may extend
 | 
						|
this exception to your version of the library, but you are not
 | 
						|
obligated to do so.  If you do not wish to do so, delete this
 | 
						|
exception statement from your version. */
 | 
						|
 | 
						|
 | 
						|
package gnu.java.awt.peer.gtk;
 | 
						|
 | 
						|
import java.awt.AWTEvent;
 | 
						|
import java.awt.AWTException;
 | 
						|
import java.awt.BufferCapabilities;
 | 
						|
import java.awt.Color;
 | 
						|
import java.awt.Component;
 | 
						|
import java.awt.Container;
 | 
						|
import java.awt.Cursor;
 | 
						|
import java.awt.Dimension;
 | 
						|
import java.awt.EventQueue;
 | 
						|
import java.awt.Font;
 | 
						|
import java.awt.FontMetrics;
 | 
						|
import java.awt.Graphics;
 | 
						|
import java.awt.GraphicsConfiguration;
 | 
						|
import java.awt.GraphicsDevice;
 | 
						|
import java.awt.GraphicsEnvironment;
 | 
						|
import java.awt.Image;
 | 
						|
import java.awt.Insets;
 | 
						|
import java.awt.ItemSelectable;
 | 
						|
import java.awt.KeyboardFocusManager;
 | 
						|
import java.awt.Point;
 | 
						|
import java.awt.Rectangle;
 | 
						|
import java.awt.Toolkit;
 | 
						|
import java.awt.Window;
 | 
						|
import java.awt.event.FocusEvent;
 | 
						|
import java.awt.event.ItemEvent;
 | 
						|
import java.awt.event.KeyEvent;
 | 
						|
import java.awt.event.MouseEvent;
 | 
						|
import java.awt.event.MouseWheelEvent;
 | 
						|
import java.awt.event.PaintEvent;
 | 
						|
import java.awt.event.TextEvent;
 | 
						|
import java.awt.image.ColorModel;
 | 
						|
import java.awt.image.ImageObserver;
 | 
						|
import java.awt.image.ImageProducer;
 | 
						|
import java.awt.image.VolatileImage;
 | 
						|
import java.awt.peer.ComponentPeer;
 | 
						|
import java.awt.peer.ContainerPeer;
 | 
						|
import java.awt.peer.LightweightPeer;
 | 
						|
import java.util.Timer;
 | 
						|
import java.util.TimerTask;
 | 
						|
 | 
						|
public class GtkComponentPeer extends GtkGenericPeer
 | 
						|
  implements ComponentPeer
 | 
						|
{
 | 
						|
  VolatileImage backBuffer;
 | 
						|
  BufferCapabilities caps;
 | 
						|
 | 
						|
  Component awtComponent;
 | 
						|
 | 
						|
  Insets insets;
 | 
						|
 | 
						|
  /**
 | 
						|
   * The current repaint area. Use should be guarded by synchronizing on this.
 | 
						|
   */
 | 
						|
  private Rectangle currentPaintArea;
 | 
						|
 | 
						|
  /* this isEnabled differs from Component.isEnabled, in that it
 | 
						|
     knows if a parent is disabled.  In that case Component.isEnabled
 | 
						|
     may return true, but our isEnabled will always return false */
 | 
						|
  native boolean isEnabled ();
 | 
						|
  static native boolean modalHasGrab();
 | 
						|
 | 
						|
  native int[] gtkWidgetGetForeground ();
 | 
						|
  native int[] gtkWidgetGetBackground ();
 | 
						|
  native void gtkWidgetGetDimensions (int[] dim);
 | 
						|
  native void gtkWidgetGetPreferredDimensions (int[] dim);
 | 
						|
  native void gtkWindowGetLocationOnScreen (int[] point);
 | 
						|
  native void gtkWindowGetLocationOnScreenUnlocked (int[] point);
 | 
						|
  native void gtkWidgetGetLocationOnScreen (int[] point);
 | 
						|
  native void gtkWidgetGetLocationOnScreenUnlocked (int[] point);
 | 
						|
  native void gtkWidgetSetCursor (int type, GtkImage image, int x, int y);
 | 
						|
  native void gtkWidgetSetCursorUnlocked (int type, GtkImage image,
 | 
						|
                                          int x, int y);
 | 
						|
  native void gtkWidgetSetBackground (int red, int green, int blue);
 | 
						|
  native void gtkWidgetSetForeground (int red, int green, int blue);
 | 
						|
  native void gtkWidgetSetSensitive (boolean sensitive);
 | 
						|
  native void gtkWidgetSetParent (ComponentPeer parent);
 | 
						|
  native void gtkWidgetRequestFocus ();
 | 
						|
  native void gtkWidgetDispatchKeyEvent (int id, long when, int mods,
 | 
						|
                                         int keyCode, int keyLocation);
 | 
						|
  native boolean gtkWidgetHasFocus();
 | 
						|
  native boolean gtkWidgetCanFocus();
 | 
						|
 | 
						|
  native void realize();
 | 
						|
  native void setNativeEventMask ();
 | 
						|
 | 
						|
  void create ()
 | 
						|
  {
 | 
						|
    throw new RuntimeException ();
 | 
						|
  }
 | 
						|
 | 
						|
  native void connectSignals ();
 | 
						|
 | 
						|
  protected GtkComponentPeer (Component awtComponent)
 | 
						|
  {
 | 
						|
    super (awtComponent);
 | 
						|
    this.awtComponent = awtComponent;
 | 
						|
    insets = new Insets (0, 0, 0, 0);
 | 
						|
 | 
						|
    create ();
 | 
						|
 | 
						|
    connectSignals ();
 | 
						|
 | 
						|
    if (awtComponent.getForeground () != null)
 | 
						|
      setForeground (awtComponent.getForeground ());
 | 
						|
    if (awtComponent.getBackground () != null)
 | 
						|
      setBackground (awtComponent.getBackground ());
 | 
						|
    if (awtComponent.getFont() != null)
 | 
						|
      setFont(awtComponent.getFont());
 | 
						|
 | 
						|
    Component parent = awtComponent.getParent ();
 | 
						|
 | 
						|
    setParentAndBounds ();
 | 
						|
 | 
						|
    setNativeEventMask ();
 | 
						|
 | 
						|
    // This peer is guaranteed to have an X window upon construction.
 | 
						|
    // That is, native methods such as those in GdkGraphics can rely
 | 
						|
    // on this component's widget->window field being non-null.
 | 
						|
    realize ();
 | 
						|
 | 
						|
    if (awtComponent.isCursorSet())
 | 
						|
      setCursor ();
 | 
						|
  }
 | 
						|
 | 
						|
  void setParentAndBounds ()
 | 
						|
  {
 | 
						|
    setParent ();
 | 
						|
 | 
						|
    setComponentBounds ();
 | 
						|
 | 
						|
    setVisibleAndEnabled ();
 | 
						|
  }
 | 
						|
 | 
						|
  void setParent ()
 | 
						|
  {
 | 
						|
    ComponentPeer p;
 | 
						|
    Component component = awtComponent;
 | 
						|
    do
 | 
						|
      {
 | 
						|
        component = component.getParent ();
 | 
						|
        p = component.getPeer ();
 | 
						|
      }
 | 
						|
    while (p instanceof java.awt.peer.LightweightPeer);
 | 
						|
 | 
						|
    if (p != null)
 | 
						|
      gtkWidgetSetParent (p);
 | 
						|
  }
 | 
						|
 | 
						|
  /*
 | 
						|
   * Set the bounds of this peer's AWT Component based on dimensions
 | 
						|
   * returned by the native windowing system.  Most Components impose
 | 
						|
   * their dimensions on the peers which is what the default
 | 
						|
   * implementation does.  However some peers, like GtkFileDialogPeer,
 | 
						|
   * need to pass their size back to the AWT Component.
 | 
						|
   */
 | 
						|
  void setComponentBounds ()
 | 
						|
  {
 | 
						|
    Rectangle bounds = awtComponent.getBounds ();
 | 
						|
    setBounds (bounds.x, bounds.y, bounds.width, bounds.height);
 | 
						|
  }
 | 
						|
 | 
						|
  void setVisibleAndEnabled ()
 | 
						|
  {
 | 
						|
    setVisible (awtComponent.isVisible ());
 | 
						|
    setEnabled (awtComponent.isEnabled ());
 | 
						|
  }
 | 
						|
 | 
						|
  public int checkImage (Image image, int width, int height,
 | 
						|
                         ImageObserver observer)
 | 
						|
  {
 | 
						|
    return getToolkit().checkImage(image, width, height, observer);
 | 
						|
  }
 | 
						|
 | 
						|
  public Image createImage (ImageProducer producer)
 | 
						|
  {
 | 
						|
    return new GtkImage (producer);
 | 
						|
  }
 | 
						|
 | 
						|
  public Image createImage (int width, int height)
 | 
						|
  {
 | 
						|
    return CairoSurface.getBufferedImage(width, height);
 | 
						|
  }
 | 
						|
 | 
						|
  public void disable ()
 | 
						|
  {
 | 
						|
    setEnabled (false);
 | 
						|
  }
 | 
						|
 | 
						|
  public void enable ()
 | 
						|
  {
 | 
						|
    setEnabled (true);
 | 
						|
  }
 | 
						|
 | 
						|
  public ColorModel getColorModel ()
 | 
						|
  {
 | 
						|
    return ColorModel.getRGBdefault ();
 | 
						|
  }
 | 
						|
 | 
						|
  public FontMetrics getFontMetrics (Font font)
 | 
						|
  {
 | 
						|
    return getToolkit().getFontMetrics(font);
 | 
						|
  }
 | 
						|
 | 
						|
  // getGraphics may be overridden by derived classes but it should
 | 
						|
  // never return null.
 | 
						|
  public Graphics getGraphics ()
 | 
						|
  {
 | 
						|
    return ComponentGraphics.getComponentGraphics(this);
 | 
						|
  }
 | 
						|
 | 
						|
  public Point getLocationOnScreen ()
 | 
						|
  {
 | 
						|
    int point[] = new int[2];
 | 
						|
    if (Thread.currentThread() == GtkMainThread.mainThread)
 | 
						|
        gtkWidgetGetLocationOnScreenUnlocked (point);
 | 
						|
    else
 | 
						|
        gtkWidgetGetLocationOnScreen (point);
 | 
						|
    return new Point (point[0], point[1]);
 | 
						|
  }
 | 
						|
 | 
						|
  public Dimension getMinimumSize ()
 | 
						|
  {
 | 
						|
    return minimumSize ();
 | 
						|
  }
 | 
						|
 | 
						|
  public Dimension getPreferredSize ()
 | 
						|
  {
 | 
						|
    return preferredSize ();
 | 
						|
  }
 | 
						|
 | 
						|
  public Toolkit getToolkit ()
 | 
						|
  {
 | 
						|
    return Toolkit.getDefaultToolkit();
 | 
						|
  }
 | 
						|
 | 
						|
  public void handleEvent (AWTEvent event)
 | 
						|
  {
 | 
						|
    int id = event.getID();
 | 
						|
    KeyEvent ke = null;
 | 
						|
 | 
						|
    switch (id)
 | 
						|
      {
 | 
						|
      case PaintEvent.PAINT:
 | 
						|
        paintComponent((PaintEvent) event);
 | 
						|
        break;
 | 
						|
      case PaintEvent.UPDATE:
 | 
						|
        updateComponent((PaintEvent) event);
 | 
						|
        break;
 | 
						|
      case KeyEvent.KEY_PRESSED:
 | 
						|
        ke = (KeyEvent) event;
 | 
						|
        gtkWidgetDispatchKeyEvent (ke.getID (), ke.getWhen (), ke.getModifiersEx (),
 | 
						|
                                   ke.getKeyCode (), ke.getKeyLocation ());
 | 
						|
        break;
 | 
						|
      case KeyEvent.KEY_RELEASED:
 | 
						|
        ke = (KeyEvent) event;
 | 
						|
        gtkWidgetDispatchKeyEvent (ke.getID (), ke.getWhen (), ke.getModifiersEx (),
 | 
						|
                                   ke.getKeyCode (), ke.getKeyLocation ());
 | 
						|
        break;
 | 
						|
      }
 | 
						|
  }
 | 
						|
 | 
						|
  // This method and its overrides are the only methods in the peers
 | 
						|
  // that should call awtComponent.paint.
 | 
						|
  protected void paintComponent (PaintEvent event)
 | 
						|
  {
 | 
						|
    // Do not call Component.paint if the component is not showing or
 | 
						|
    // if its bounds form a degenerate rectangle.
 | 
						|
    if (!awtComponent.isShowing()
 | 
						|
        || (awtComponent.getWidth() < 1 || awtComponent.getHeight() < 1))
 | 
						|
      return;
 | 
						|
 | 
						|
    // Creating and disposing a GdkGraphics every time paint is called
 | 
						|
    // seems expensive.  However, the graphics state does not carry
 | 
						|
    // over between calls to paint, and resetting the graphics object
 | 
						|
    // may even be more costly than simply creating a new one.
 | 
						|
 | 
						|
    // Make sure that the paintArea includes the area from the event
 | 
						|
    // in the case when an application sends PaintEvents directly.
 | 
						|
    coalescePaintEvent(event);
 | 
						|
    Rectangle paintArea;
 | 
						|
    synchronized (this)
 | 
						|
      {
 | 
						|
        paintArea = currentPaintArea;
 | 
						|
        currentPaintArea = null;
 | 
						|
      }
 | 
						|
 | 
						|
    if (paintArea != null)
 | 
						|
      {
 | 
						|
        Graphics g = getGraphics();
 | 
						|
        try
 | 
						|
          {
 | 
						|
            g.setClip(paintArea);
 | 
						|
            awtComponent.paint(g);
 | 
						|
          }
 | 
						|
        finally
 | 
						|
          {
 | 
						|
            g.dispose();
 | 
						|
          }
 | 
						|
      }
 | 
						|
  }
 | 
						|
 | 
						|
  // This method and its overrides are the only methods in the peers
 | 
						|
  // that should call awtComponent.update.
 | 
						|
  protected void updateComponent (PaintEvent event)
 | 
						|
  {
 | 
						|
    // Do not call Component.update if the component is not showing or
 | 
						|
    // if its bounds form a degenerate rectangle.
 | 
						|
    if (!awtComponent.isShowing()
 | 
						|
        || (awtComponent.getWidth() < 1 || awtComponent.getHeight() < 1))
 | 
						|
      return;
 | 
						|
 | 
						|
    // Make sure that the paintArea includes the area from the event
 | 
						|
    // in the case when an application sends PaintEvents directly.
 | 
						|
    coalescePaintEvent(event);
 | 
						|
    Rectangle paintArea;
 | 
						|
    synchronized (this)
 | 
						|
      {
 | 
						|
        paintArea = currentPaintArea;
 | 
						|
        currentPaintArea = null;
 | 
						|
      }
 | 
						|
 | 
						|
    if (paintArea != null)
 | 
						|
    {
 | 
						|
      Graphics g = getGraphics();
 | 
						|
      try
 | 
						|
        {
 | 
						|
          g.setClip(paintArea);
 | 
						|
          awtComponent.update(g);
 | 
						|
        }
 | 
						|
      finally
 | 
						|
        {
 | 
						|
          g.dispose();
 | 
						|
        }
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  public boolean isFocusTraversable ()
 | 
						|
  {
 | 
						|
    return true;
 | 
						|
  }
 | 
						|
 | 
						|
  public Dimension minimumSize ()
 | 
						|
  {
 | 
						|
    int dim[] = new int[2];
 | 
						|
 | 
						|
    gtkWidgetGetPreferredDimensions (dim);
 | 
						|
 | 
						|
    return new Dimension (dim[0], dim[1]);
 | 
						|
  }
 | 
						|
 | 
						|
  public void paint (Graphics g)
 | 
						|
  {
 | 
						|
  }
 | 
						|
 | 
						|
  public Dimension preferredSize ()
 | 
						|
  {
 | 
						|
    int dim[] = new int[2];
 | 
						|
 | 
						|
    gtkWidgetGetPreferredDimensions (dim);
 | 
						|
 | 
						|
    return new Dimension (dim[0], dim[1]);
 | 
						|
  }
 | 
						|
 | 
						|
  public boolean prepareImage (Image image, int width, int height,
 | 
						|
                               ImageObserver observer)
 | 
						|
  {
 | 
						|
    return getToolkit().prepareImage(image, width, height, observer);
 | 
						|
  }
 | 
						|
 | 
						|
  public void print (Graphics g)
 | 
						|
  {
 | 
						|
    g.drawImage( ComponentGraphics.grab( this ), 0, 0, null );
 | 
						|
  }
 | 
						|
 | 
						|
  public void repaint (long tm, int x, int y, int width, int height)
 | 
						|
  {
 | 
						|
    if (width < 1 || height < 1)
 | 
						|
      return;
 | 
						|
 | 
						|
    if (tm <= 0)
 | 
						|
      q().postEvent(new PaintEvent(awtComponent, PaintEvent.UPDATE,
 | 
						|
                                   new Rectangle(x, y, width, height)));
 | 
						|
    else
 | 
						|
      RepaintTimerTask.schedule(tm, x, y, width, height, awtComponent);
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Used for scheduling delayed paint updates on the event queue.
 | 
						|
   */
 | 
						|
  private static class RepaintTimerTask extends TimerTask
 | 
						|
  {
 | 
						|
    private static final Timer repaintTimer = new Timer(true);
 | 
						|
 | 
						|
    private int x, y, width, height;
 | 
						|
    private Component awtComponent;
 | 
						|
 | 
						|
    RepaintTimerTask(Component c, int x, int y, int width, int height)
 | 
						|
    {
 | 
						|
      this.x = x;
 | 
						|
      this.y = y;
 | 
						|
      this.width = width;
 | 
						|
      this.height = height;
 | 
						|
      this.awtComponent = c;
 | 
						|
    }
 | 
						|
 | 
						|
    public void run()
 | 
						|
    {
 | 
						|
      q().postEvent (new PaintEvent (awtComponent, PaintEvent.UPDATE,
 | 
						|
                                     new Rectangle (x, y, width, height)));
 | 
						|
    }
 | 
						|
 | 
						|
    static void schedule(long tm, int x, int y, int width, int height,
 | 
						|
                         Component c)
 | 
						|
    {
 | 
						|
      repaintTimer.schedule(new RepaintTimerTask(c, x, y, width, height), tm);
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  public void requestFocus ()
 | 
						|
  {
 | 
						|
    assert false: "Call new requestFocus() method instead";
 | 
						|
  }
 | 
						|
 | 
						|
  public void reshape (int x, int y, int width, int height)
 | 
						|
  {
 | 
						|
    setBounds (x, y, width, height);
 | 
						|
  }
 | 
						|
 | 
						|
  public void setBackground (Color c)
 | 
						|
  {
 | 
						|
    gtkWidgetSetBackground (c.getRed(), c.getGreen(), c.getBlue());
 | 
						|
  }
 | 
						|
 | 
						|
  native void setNativeBounds (int x, int y, int width, int height);
 | 
						|
 | 
						|
  public void setBounds (int x, int y, int width, int height)
 | 
						|
  {
 | 
						|
    int new_x = x;
 | 
						|
    int new_y = y;
 | 
						|
 | 
						|
    Component parent = awtComponent.getParent ();
 | 
						|
 | 
						|
    // Heavyweight components that are children of one or more
 | 
						|
    // lightweight containers have to be handled specially.  Because
 | 
						|
    // calls to GLightweightPeer.setBounds do nothing, GTK has no
 | 
						|
    // knowledge of the lightweight containers' positions.  So we have
 | 
						|
    // to add the offsets manually when placing a heavyweight
 | 
						|
    // component within a lightweight container.  The lightweight
 | 
						|
    // container may itself be in a lightweight container and so on,
 | 
						|
    // so we need to continue adding offsets until we reach a
 | 
						|
    // container whose position GTK knows -- that is, the first
 | 
						|
    // non-lightweight.
 | 
						|
    Insets i;
 | 
						|
    while (parent.isLightweight())
 | 
						|
      {
 | 
						|
        i = ((Container) parent).getInsets();
 | 
						|
 | 
						|
        new_x += parent.getX() + i.left;
 | 
						|
        new_y += parent.getY() + i.top;
 | 
						|
 | 
						|
        parent = parent.getParent();
 | 
						|
      }
 | 
						|
    // We only need to convert from Java to GTK coordinates if we're
 | 
						|
    // placing a heavyweight component in a Window.
 | 
						|
    if (parent instanceof Window)
 | 
						|
      {
 | 
						|
        GtkWindowPeer peer = (GtkWindowPeer) parent.getPeer ();
 | 
						|
        // important: we want the window peer's insets here, not the
 | 
						|
        // window's, since user sub-classes of Window can override
 | 
						|
        // getInset and we only want to correct for the frame borders,
 | 
						|
        // not for any user-defined inset values
 | 
						|
        Insets insets = peer.getInsets ();
 | 
						|
 | 
						|
        int menuBarHeight = 0;
 | 
						|
        if (peer instanceof GtkFramePeer)
 | 
						|
          menuBarHeight = ((GtkFramePeer) peer).getMenuBarHeight ();
 | 
						|
 | 
						|
        new_x -= insets.left;
 | 
						|
        new_y -= insets.top;
 | 
						|
        new_y += menuBarHeight;
 | 
						|
      }
 | 
						|
 | 
						|
    setNativeBounds (new_x, new_y, width, height);
 | 
						|
 | 
						|
    // If the height or width were (or are now) smaller than zero
 | 
						|
    // then we want to adjust the visibility.
 | 
						|
    setVisible(awtComponent.isVisible());
 | 
						|
  }
 | 
						|
 | 
						|
  void setCursor ()
 | 
						|
  {
 | 
						|
    setCursor (awtComponent.getCursor ());
 | 
						|
  }
 | 
						|
 | 
						|
  public void setCursor (Cursor cursor)
 | 
						|
  {
 | 
						|
    int x, y;
 | 
						|
    GtkImage image;
 | 
						|
    int type = cursor.getType();
 | 
						|
    if (cursor instanceof GtkCursor)
 | 
						|
      {
 | 
						|
        GtkCursor gtkCursor = (GtkCursor) cursor;
 | 
						|
        image = gtkCursor.getGtkImage();
 | 
						|
        Point hotspot = gtkCursor.getHotspot();
 | 
						|
        x = hotspot.x;
 | 
						|
        y = hotspot.y;
 | 
						|
      }
 | 
						|
    else
 | 
						|
      {
 | 
						|
        image = null;
 | 
						|
        x = 0;
 | 
						|
        y = 0;
 | 
						|
      }
 | 
						|
 | 
						|
    if (Thread.currentThread() == GtkMainThread.mainThread)
 | 
						|
      gtkWidgetSetCursorUnlocked(cursor.getType(), image, x, y);
 | 
						|
    else
 | 
						|
      gtkWidgetSetCursor(cursor.getType(), image, x, y);
 | 
						|
  }
 | 
						|
 | 
						|
  public void setEnabled (boolean b)
 | 
						|
  {
 | 
						|
    gtkWidgetSetSensitive (b);
 | 
						|
  }
 | 
						|
 | 
						|
  public void setFont (Font f)
 | 
						|
  {
 | 
						|
    // FIXME: This should really affect the widget tree below me.
 | 
						|
    // Currently this is only handled if the call is made directly on
 | 
						|
    // a text widget, which implements setFont() itself.
 | 
						|
    gtkWidgetModifyFont(f.getName(), f.getStyle(), f.getSize());
 | 
						|
  }
 | 
						|
 | 
						|
  public void setForeground (Color c)
 | 
						|
  {
 | 
						|
    gtkWidgetSetForeground (c.getRed(), c.getGreen(), c.getBlue());
 | 
						|
  }
 | 
						|
 | 
						|
  public Color getForeground ()
 | 
						|
  {
 | 
						|
    int rgb[] = gtkWidgetGetForeground ();
 | 
						|
    return new Color (rgb[0], rgb[1], rgb[2]);
 | 
						|
  }
 | 
						|
 | 
						|
  public Color getBackground ()
 | 
						|
  {
 | 
						|
    int rgb[] = gtkWidgetGetBackground ();
 | 
						|
    return new Color (rgb[0], rgb[1], rgb[2]);
 | 
						|
  }
 | 
						|
 | 
						|
  public native void setVisibleNative (boolean b);
 | 
						|
  public native void setVisibleNativeUnlocked (boolean b);
 | 
						|
 | 
						|
  public void setVisible (boolean b)
 | 
						|
  {
 | 
						|
    // Only really set visible when component is bigger than zero pixels.
 | 
						|
    if (b && ! (awtComponent instanceof Window))
 | 
						|
      {
 | 
						|
        Rectangle bounds = awtComponent.getBounds();
 | 
						|
        b = (bounds.width > 0) && (bounds.height > 0);
 | 
						|
      }
 | 
						|
 | 
						|
    if (Thread.currentThread() == GtkMainThread.mainThread)
 | 
						|
      setVisibleNativeUnlocked (b);
 | 
						|
    else
 | 
						|
      setVisibleNative (b);
 | 
						|
  }
 | 
						|
 | 
						|
  public void hide ()
 | 
						|
  {
 | 
						|
    setVisible (false);
 | 
						|
  }
 | 
						|
 | 
						|
  public void show ()
 | 
						|
  {
 | 
						|
    setVisible (true);
 | 
						|
  }
 | 
						|
 | 
						|
  protected void postMouseEvent(int id, long when, int mods, int x, int y,
 | 
						|
                                int clickCount, boolean popupTrigger)
 | 
						|
  {
 | 
						|
    // It is important to do the getLocationOnScreen() here, instead
 | 
						|
    // of using the old MouseEvent constructors, because
 | 
						|
    // Component.getLocationOnScreen() locks on the AWT lock, which can
 | 
						|
    // trigger a deadlock. You don't want this.
 | 
						|
    Point locOnScreen = getLocationOnScreen();
 | 
						|
    q().postEvent(new MouseEvent(awtComponent, id, when, mods, x, y,
 | 
						|
                                 locOnScreen.x + x, locOnScreen.y + y,
 | 
						|
                                 clickCount, popupTrigger,
 | 
						|
                                 MouseEvent.NOBUTTON));
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Callback for component_scroll_cb.
 | 
						|
   */
 | 
						|
  protected void postMouseWheelEvent(int id, long when, int mods,
 | 
						|
                                     int x, int y, int clickCount,
 | 
						|
                                     boolean popupTrigger,
 | 
						|
                                     int type, int amount, int rotation)
 | 
						|
  {
 | 
						|
    q().postEvent(new MouseWheelEvent(awtComponent, id, when, mods,
 | 
						|
                                      x, y, clickCount, popupTrigger,
 | 
						|
                                      type, amount, rotation));
 | 
						|
  }
 | 
						|
 | 
						|
  protected void postExposeEvent (int x, int y, int width, int height)
 | 
						|
  {
 | 
						|
    q().postEvent (new PaintEvent (awtComponent, PaintEvent.PAINT,
 | 
						|
                                   new Rectangle (x, y, width, height)));
 | 
						|
  }
 | 
						|
 | 
						|
  protected void postKeyEvent (int id, long when, int mods,
 | 
						|
                               int keyCode, char keyChar, int keyLocation)
 | 
						|
  {
 | 
						|
    KeyEvent keyEvent = new KeyEvent (awtComponent, id, when, mods,
 | 
						|
                                      keyCode, keyChar, keyLocation);
 | 
						|
 | 
						|
    EventQueue q = q();
 | 
						|
 | 
						|
    // Also post a KEY_TYPED event if keyEvent is a key press that
 | 
						|
    // doesn't represent an action or modifier key.
 | 
						|
    if (keyEvent.getID () == KeyEvent.KEY_PRESSED
 | 
						|
        && (!keyEvent.isActionKey ()
 | 
						|
            && keyCode != KeyEvent.VK_SHIFT
 | 
						|
            && keyCode != KeyEvent.VK_CONTROL
 | 
						|
            && keyCode != KeyEvent.VK_ALT))
 | 
						|
      {
 | 
						|
        synchronized(q)
 | 
						|
          {
 | 
						|
            q.postEvent(keyEvent);
 | 
						|
            keyEvent = new KeyEvent(awtComponent, KeyEvent.KEY_TYPED, when,
 | 
						|
                                    mods, KeyEvent.VK_UNDEFINED, keyChar,
 | 
						|
                                    keyLocation);
 | 
						|
            q.postEvent(keyEvent);
 | 
						|
          }
 | 
						|
      }
 | 
						|
    else
 | 
						|
      q.postEvent(keyEvent);
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Referenced from native code.
 | 
						|
   *
 | 
						|
   * @param id
 | 
						|
   * @param temporary
 | 
						|
   */
 | 
						|
  protected void postFocusEvent (int id, boolean temporary)
 | 
						|
  {
 | 
						|
    q().postEvent (new FocusEvent (awtComponent, id, temporary));
 | 
						|
  }
 | 
						|
 | 
						|
  protected void postItemEvent (Object item, int stateChange)
 | 
						|
  {
 | 
						|
    q().postEvent (new ItemEvent ((ItemSelectable)awtComponent,
 | 
						|
                                  ItemEvent.ITEM_STATE_CHANGED,
 | 
						|
                                  item, stateChange));
 | 
						|
  }
 | 
						|
 | 
						|
  protected void postTextEvent ()
 | 
						|
  {
 | 
						|
    q().postEvent (new TextEvent (awtComponent, TextEvent.TEXT_VALUE_CHANGED));
 | 
						|
  }
 | 
						|
 | 
						|
  public GraphicsConfiguration getGraphicsConfiguration ()
 | 
						|
  {
 | 
						|
    // FIXME: The component might be showing on a non-default screen.
 | 
						|
    GraphicsEnvironment env = GraphicsEnvironment.getLocalGraphicsEnvironment();
 | 
						|
    GraphicsDevice dev = env.getDefaultScreenDevice();
 | 
						|
    return dev.getDefaultConfiguration();
 | 
						|
  }
 | 
						|
 | 
						|
  public void setEventMask (long mask)
 | 
						|
  {
 | 
						|
    // FIXME: just a stub for now.
 | 
						|
  }
 | 
						|
 | 
						|
  public boolean isFocusable ()
 | 
						|
  {
 | 
						|
    return false;
 | 
						|
  }
 | 
						|
 | 
						|
  public boolean requestFocus (Component request, boolean temporary,
 | 
						|
                               boolean allowWindowFocus, long time)
 | 
						|
  {
 | 
						|
    assert request == awtComponent || isLightweightDescendant(request);
 | 
						|
    boolean retval = false;
 | 
						|
    if (gtkWidgetHasFocus())
 | 
						|
      {
 | 
						|
        KeyboardFocusManager kfm =
 | 
						|
          KeyboardFocusManager.getCurrentKeyboardFocusManager();
 | 
						|
        Component currentFocus = kfm.getFocusOwner();
 | 
						|
        if (currentFocus == request)
 | 
						|
          // Nothing to do in this trivial case.
 | 
						|
          retval = true;
 | 
						|
        else
 | 
						|
          {
 | 
						|
            // Requested component is a lightweight descendant of this one
 | 
						|
            // or the actual heavyweight.
 | 
						|
            // Since this (native) component is already focused, we simply
 | 
						|
            // change the actual focus and be done.
 | 
						|
            postFocusEvent(FocusEvent.FOCUS_GAINED, temporary);
 | 
						|
            retval = true;
 | 
						|
          }
 | 
						|
      }
 | 
						|
    else
 | 
						|
      {
 | 
						|
        if (gtkWidgetCanFocus())
 | 
						|
          {
 | 
						|
            if (allowWindowFocus)
 | 
						|
              {
 | 
						|
                Window window = getWindowFor(request);
 | 
						|
                GtkWindowPeer wPeer = (GtkWindowPeer) window.getPeer();
 | 
						|
                if (! wPeer.gtkWindowHasFocus())
 | 
						|
                  wPeer.requestWindowFocus();
 | 
						|
              }
 | 
						|
            // Store requested focus component so that the corresponding
 | 
						|
            // event is dispatched correctly.
 | 
						|
            gtkWidgetRequestFocus();
 | 
						|
            retval = true;
 | 
						|
          }
 | 
						|
      }
 | 
						|
    return retval;
 | 
						|
  }
 | 
						|
 | 
						|
  private Window getWindowFor(Component c)
 | 
						|
  {
 | 
						|
    Component comp = c;
 | 
						|
    while (! (comp instanceof Window))
 | 
						|
      comp = comp.getParent();
 | 
						|
    return (Window) comp;
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Returns <code>true</code> if the component is a direct (== no intermediate
 | 
						|
   * heavyweights) lightweight descendant of this peer's component.
 | 
						|
   *
 | 
						|
   * @param c the component to check
 | 
						|
   *
 | 
						|
   * @return <code>true</code> if the component is a direct (== no intermediate
 | 
						|
   *         heavyweights) lightweight descendant of this peer's component
 | 
						|
   */
 | 
						|
  protected boolean isLightweightDescendant(Component c)
 | 
						|
  {
 | 
						|
    Component comp = c;
 | 
						|
    while (comp.getPeer() instanceof LightweightPeer)
 | 
						|
      comp = comp.getParent();
 | 
						|
    return comp == awtComponent;
 | 
						|
  }
 | 
						|
 | 
						|
  public boolean isObscured ()
 | 
						|
  {
 | 
						|
    return false;
 | 
						|
  }
 | 
						|
 | 
						|
  public boolean canDetermineObscurity ()
 | 
						|
  {
 | 
						|
    return false;
 | 
						|
  }
 | 
						|
 | 
						|
  public void coalescePaintEvent (PaintEvent e)
 | 
						|
  {
 | 
						|
    synchronized (this)
 | 
						|
    {
 | 
						|
      Rectangle newRect = e.getUpdateRect();
 | 
						|
      if (currentPaintArea == null)
 | 
						|
        currentPaintArea = newRect;
 | 
						|
      else
 | 
						|
        Rectangle.union(currentPaintArea, newRect, currentPaintArea);
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  public void updateCursorImmediately ()
 | 
						|
  {
 | 
						|
    if (awtComponent.getCursor() != null)
 | 
						|
      setCursor(awtComponent.getCursor());
 | 
						|
  }
 | 
						|
 | 
						|
  public boolean handlesWheelScrolling ()
 | 
						|
  {
 | 
						|
    return false;
 | 
						|
  }
 | 
						|
 | 
						|
  // Convenience method to create a new volatile image on the screen
 | 
						|
  // on which this component is displayed.
 | 
						|
  public VolatileImage createVolatileImage (int width, int height)
 | 
						|
  {
 | 
						|
    return new GtkVolatileImage (this, width, height, null);
 | 
						|
  }
 | 
						|
 | 
						|
  // Creates buffers used in a buffering strategy.
 | 
						|
  public void createBuffers (int numBuffers, BufferCapabilities caps)
 | 
						|
    throws AWTException
 | 
						|
  {
 | 
						|
    // numBuffers == 2 implies double-buffering, meaning one back
 | 
						|
    // buffer and one front buffer.
 | 
						|
    if (numBuffers == 2)
 | 
						|
      backBuffer = new GtkVolatileImage(this, awtComponent.getWidth(),
 | 
						|
                                        awtComponent.getHeight(),
 | 
						|
                                        caps.getBackBufferCapabilities());
 | 
						|
    else
 | 
						|
      throw new AWTException("GtkComponentPeer.createBuffers:"
 | 
						|
                             + " multi-buffering not supported");
 | 
						|
    this.caps = caps;
 | 
						|
  }
 | 
						|
 | 
						|
  // Return the back buffer.
 | 
						|
  public Image getBackBuffer ()
 | 
						|
  {
 | 
						|
    return backBuffer;
 | 
						|
  }
 | 
						|
 | 
						|
  // FIXME: flip should be implemented as a fast native operation
 | 
						|
  public void flip (BufferCapabilities.FlipContents contents)
 | 
						|
  {
 | 
						|
    getGraphics().drawImage(backBuffer,
 | 
						|
                            awtComponent.getWidth(),
 | 
						|
                            awtComponent.getHeight(),
 | 
						|
                            null);
 | 
						|
 | 
						|
    // create new back buffer and clear it to the background color.
 | 
						|
    if (contents == BufferCapabilities.FlipContents.BACKGROUND)
 | 
						|
        {
 | 
						|
          backBuffer = createVolatileImage(awtComponent.getWidth(),
 | 
						|
                                           awtComponent.getHeight());
 | 
						|
          backBuffer.getGraphics().clearRect(0, 0,
 | 
						|
                                             awtComponent.getWidth(),
 | 
						|
                                             awtComponent.getHeight());
 | 
						|
        }
 | 
						|
    // FIXME: support BufferCapabilities.FlipContents.PRIOR
 | 
						|
  }
 | 
						|
 | 
						|
  // Release the resources allocated to back buffers.
 | 
						|
  public void destroyBuffers ()
 | 
						|
  {
 | 
						|
    backBuffer.flush();
 | 
						|
  }
 | 
						|
 | 
						|
  public String toString ()
 | 
						|
  {
 | 
						|
    return "peer of " + awtComponent.toString();
 | 
						|
  }
 | 
						|
  public Rectangle getBounds()
 | 
						|
  {
 | 
						|
      // FIXME: implement
 | 
						|
    return null;
 | 
						|
  }
 | 
						|
  public void reparent(ContainerPeer parent)
 | 
						|
  {
 | 
						|
    // FIXME: implement
 | 
						|
 | 
						|
  }
 | 
						|
  public void setBounds(int x, int y, int width, int height, int z)
 | 
						|
  {
 | 
						|
    // FIXME: implement
 | 
						|
      setBounds (x, y, width, height);
 | 
						|
 | 
						|
  }
 | 
						|
  public boolean isReparentSupported()
 | 
						|
  {
 | 
						|
    // FIXME: implement
 | 
						|
 | 
						|
    return false;
 | 
						|
  }
 | 
						|
  public void layout()
 | 
						|
  {
 | 
						|
    // FIXME: implement
 | 
						|
 | 
						|
  }
 | 
						|
 | 
						|
  public boolean requestFocus(Component lightweightChild, boolean temporary,
 | 
						|
                              boolean focusedWindowChangeAllowed,
 | 
						|
                              long time, sun.awt.CausedFocusEvent.Cause cause)
 | 
						|
  {
 | 
						|
    // TODO: Implement this properly and remove the other requestFocus()
 | 
						|
    // methods.
 | 
						|
    return true;
 | 
						|
  }
 | 
						|
 | 
						|
}
 |