Source for gnu.java.awt.peer.x.XWindowPeer

   1: /* XWindowPeer.java -- Window peer for X
   2:    Copyright (C) 2006 Free Software Foundation, Inc.
   3: 
   4: This file is part of GNU Classpath.
   5: 
   6: GNU Classpath is free software; you can redistribute it and/or modify
   7: it under the terms of the GNU General Public License as published by
   8: the Free Software Foundation; either version 2, or (at your option)
   9: any later version.
  10: 
  11: GNU Classpath is distributed in the hope that it will be useful, but
  12: WITHOUT ANY WARRANTY; without even the implied warranty of
  13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  14: General Public License for more details.
  15: 
  16: You should have received a copy of the GNU General Public License
  17: along with GNU Classpath; see the file COPYING.  If not, write to the
  18: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  19: 02110-1301 USA.
  20: 
  21: Linking this library statically or dynamically with other modules is
  22: making a combined work based on this library.  Thus, the terms and
  23: conditions of the GNU General Public License cover the whole
  24: combination.
  25: 
  26: As a special exception, the copyright holders of this library give you
  27: permission to link this library with independent modules to produce an
  28: executable, regardless of the license terms of these independent
  29: modules, and to copy and distribute the resulting executable under
  30: terms of your choice, provided that you also meet, for each linked
  31: independent module, the terms and conditions of the license of that
  32: module.  An independent module is a module which is not derived from
  33: or based on this library.  If you modify this library, you may extend
  34: this exception to your version of the library, but you are not
  35: obligated to do so.  If you do not wish to do so, delete this
  36: exception statement from your version. */
  37: 
  38: 
  39: package gnu.java.awt.peer.x;
  40: 
  41: import java.awt.Component;
  42: import java.awt.Dialog;
  43: import java.awt.EventQueue;
  44: import java.awt.Font;
  45: import java.awt.FontMetrics;
  46: import java.awt.Frame;
  47: import java.awt.Graphics;
  48: import java.awt.GraphicsConfiguration;
  49: import java.awt.GraphicsDevice;
  50: import java.awt.GraphicsEnvironment;
  51: import java.awt.Image;
  52: import java.awt.Insets;
  53: import java.awt.Point;
  54: import java.awt.Rectangle;
  55: import java.awt.event.PaintEvent;
  56: import java.awt.event.WindowEvent;
  57: import java.awt.image.VolatileImage;
  58: 
  59: import gnu.x11.Atom;
  60: import gnu.x11.Window;
  61: import gnu.x11.event.Event;
  62: 
  63: import gnu.java.awt.font.OpenTypeFontPeer;
  64: import gnu.java.awt.peer.ClasspathFontPeer;
  65: import gnu.java.awt.peer.swing.SwingWindowPeer;
  66: 
  67: public class XWindowPeer
  68:     extends SwingWindowPeer
  69: {
  70: 
  71:   private static int standardSelect = Event.BUTTON_PRESS_MASK
  72:                                       | Event.BUTTON_RELEASE_MASK
  73:                                       | Event.POINTER_MOTION_MASK
  74:                                      // | Event.RESIZE_REDIRECT_MASK //
  75:                                       | Event.EXPOSURE_MASK
  76:                                       | Event.PROPERTY_CHANGE_MASK
  77:                                       //| Event.STRUCTURE_NOTIFY_MASK
  78:                                       //| Event.SUBSTRUCTURE_NOTIFY_MASK
  79:                                       | Event.KEY_PRESS_MASK
  80:                                       | Event.KEY_RELEASE_MASK
  81:                                       //| Event.VISIBILITY_CHANGE_MASK //
  82:                                       ;
  83: 
  84:   /**
  85:    * The X window.
  86:    */
  87:   protected Window xwindow;
  88: 
  89:   /**
  90:    * The frame insets. These get updated in {@link #show()}.
  91:    */
  92:   private Insets insets;
  93: 
  94:   XWindowPeer(java.awt.Window window)
  95:   {
  96:     super(window);
  97:     XGraphicsDevice dev = XToolkit.getDefaultDevice();
  98: 
  99:     // TODO: Maybe initialize lazily in show().
 100:     Window.Attributes atts = new Window.Attributes();
 101:     // FIXME: Howto generate a Window without decorations?
 102:     int x = Math.max(window.getX(), 0);
 103:     int y = Math.max(window.getY(), 0);
 104:     int w = Math.max(window.getWidth(), 1);
 105:     int h = Math.max(window.getHeight(), 1);
 106:     xwindow = new Window(dev.getDisplay().default_root, x, y, w, h, 0, atts);
 107:     xwindow.select_input(standardSelect);
 108: 
 109:     dev.getEventPump().registerWindow(xwindow, window);
 110:     xwindow.set_wm_delete_window();
 111: 
 112:     boolean undecorated;
 113:     if (awtComponent instanceof Frame)
 114:       {
 115:         Frame f = (Frame) awtComponent;
 116:         undecorated = f.isUndecorated();
 117:       }
 118:     else if (awtComponent instanceof Dialog)
 119:       {
 120:         Dialog d = (Dialog) awtComponent;
 121:         undecorated = d.isUndecorated();
 122:       }
 123:     else
 124:       {
 125:         undecorated = true;
 126:       }
 127:     if (undecorated)
 128:       {
 129:         // First try the Motif implementation of undecorated frames. This
 130:         // is semantically closest and supported by all major window
 131:         // managers.
 132:         // TODO: At the time of writing this, there's no freedesktop.org
 133:         // standard extension that matches the required semantic. Maybe
 134:         // undecorated frames are added in the future, if so, then use these.
 135:         Atom at = Atom.intern(dev.getDisplay(), "_MOTIF_WM_HINTS");
 136:         if (at != null)
 137:           {
 138:             xwindow.change_property(Window.REPLACE, at, at, 32,
 139:                                     new int[]{1 << 1, 0, 0, 0, 0}, 0, 5);
 140:           }
 141:       }
 142:     insets = new Insets(0, 0, 0, 0);
 143:   }
 144: 
 145:   public void toBack()
 146:   {
 147:     // TODO Auto-generated method stub
 148: 
 149:   }
 150: 
 151:   public void toFront()
 152:   {
 153:     // TODO Auto-generated method stub
 154: 
 155:   }
 156: 
 157:   public void updateAlwaysOnTop()
 158:   {
 159:     // TODO Auto-generated method stub
 160: 
 161:   }
 162: 
 163:   public boolean requestWindowFocus()
 164:   {
 165:     // TODO Auto-generated method stub
 166:     return false;
 167:   }
 168: 
 169:   public Point getLocationOnScreen()
 170:   {
 171:     return new Point(xwindow.x, xwindow.y);
 172:   }
 173: 
 174:   /**
 175:    * Returns a XGraphics suitable for drawing on this frame.
 176:    *
 177:    * @return a XGraphics suitable for drawing on this frame
 178:    */
 179:   public Graphics getGraphics()
 180:   {
 181:         XGraphics2D xg2d = new XGraphics2D(xwindow);
 182:         xg2d.setColor(awtComponent.getForeground());
 183:         xg2d.setBackground(awtComponent.getBackground());
 184:         xg2d.setFont(awtComponent.getFont());
 185:         return xg2d;
 186:   }
 187: 
 188:   public Image createImage(int w, int h)
 189:   {
 190:     // FIXME: Should return a buffered image.
 191:     return createVolatileImage(w, h);
 192:   }
 193: 
 194:   @Override
 195:   public VolatileImage createVolatileImage(int width, int height)
 196:   {
 197:     GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
 198:     GraphicsDevice gd = ge.getDefaultScreenDevice();
 199:     GraphicsConfiguration gc = gd.getDefaultConfiguration();
 200:     return gc.createCompatibleVolatileImage(width, height);
 201:   }
 202: 
 203:   /**
 204:    * Makes the component visible. This is called by {@link Component#show()}.
 205:    *
 206:    * This is implemented to call setVisible(true) on the Swing component.
 207:    */
 208:   public void show()
 209:   {
 210:     // Prevent ResizeRedirect events.
 211:     //xwindow.select_input(Event.NO_EVENT_MASK);
 212:     //xwindow.select_input(noResizeRedirectSelect);
 213: 
 214:     XGraphicsDevice dev = XToolkit.getDefaultDevice();
 215:     xwindow.map();
 216:     EventQueue eq = XToolkit.getDefaultToolkit().getSystemEventQueue();
 217:     java.awt.Window w = (java.awt.Window) super.awtComponent;
 218:     eq.postEvent(new WindowEvent(w, WindowEvent.WINDOW_OPENED));
 219:     eq.postEvent(new PaintEvent(w, PaintEvent.PAINT,
 220:                                 new Rectangle(0, 0, w.getWidth(),
 221:                                               w.getHeight())));
 222: 
 223:     Graphics g = getGraphics();
 224:     g.clearRect(0, 0, awtComponent.getWidth(), awtComponent.getHeight());
 225:     g.dispose();
 226: //    // Reset input selection.
 227: //    atts.set_override_redirect(false);
 228: //    xwindow.change_attributes(atts);
 229: 
 230:     // Determine the frame insets.
 231:     Atom atom = (Atom) Atom.intern(dev.getDisplay(), "_NET_FRAME_EXTENTS");
 232:     Window.Property p = xwindow.get_property(false, atom, Atom.CARDINAL, 0,
 233:                                              Window.MAX_WM_LENGTH);
 234:     if (p.format() != 0)
 235:       {
 236:         insets = new Insets(p.value(0), p.value(1), p.value(2), p.value(3));
 237:         Window.Changes ch = new Window.Changes();
 238:         ch.width(awtComponent.getWidth() - insets.left - insets.top);
 239:         ch.height(awtComponent.getHeight() - insets.top - insets.bottom);
 240:         xwindow.configure(ch);
 241:       }
 242: 
 243:   }
 244: 
 245:   /**
 246:    * Makes the component invisible. This is called from
 247:    * {@link Component#hide()}.
 248:    *
 249:    * This is implemented to call setVisible(false) on the Swing component.
 250:    */
 251:   public void hide()
 252:   {
 253:     xwindow.unmap();
 254:   }
 255: 
 256:   /**
 257:    * Notifies the peer that the bounds of this component have changed. This
 258:    * is called by {@link Component#reshape(int, int, int, int)}.
 259:    *
 260:    * This is implemented to call setBounds() on the Swing component.
 261:    *
 262:    * @param x the X coordinate of the upper left corner of the component
 263:    * @param y the Y coordinate of the upper left corner of the component
 264:    * @param width the width of the component
 265:    * @param height the height of the component
 266:    */
 267:   public void reshape(int x, int y, int width, int height)
 268:   {
 269:     Insets i = insets;
 270:     xwindow.move_resize(x - i.left, y - i.right, width - i.left - i.right,
 271:                         height - i.top - i.bottom);
 272:   }
 273: 
 274:   public Insets insets()
 275:   {
 276:     return (Insets) insets.clone();
 277:   }
 278: 
 279:   /**
 280:    * Returns the font metrics for the specified font.
 281:    *
 282:    * @return the font metrics for the specified font
 283:    */
 284:   public FontMetrics getFontMetrics(Font font)
 285:   {
 286:     ClasspathFontPeer fontPeer = (ClasspathFontPeer) font.getPeer();
 287:     return fontPeer.getFontMetrics(font);
 288:   }
 289: 
 290:   /**
 291:    * Unregisters the window in the event pump when it is closed.
 292:    */
 293:   protected void finalize()
 294:   {
 295:     XGraphicsDevice dev = XToolkit.getDefaultDevice();
 296:     dev.getEventPump().unregisterWindow(xwindow);
 297:   }
 298: 
 299:   public Window getXwindow()
 300:   {
 301:     return xwindow;
 302:   }
 303: }