--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/solaris/classes/sun/awt/X11/XIconWindow.java Sat Dec 01 00:00:00 2007 +0000
@@ -0,0 +1,510 @@
+/*
+ * Copyright 2003-2006 Sun Microsystems, Inc. All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+package sun.awt.X11;
+
+import java.awt.*;
+import java.awt.image.*;
+import sun.awt.X11GraphicsConfig;
+import sun.awt.image.ToolkitImage;
+import sun.awt.image.ImageRepresentation;
+
+import java.util.logging.*;
+
+public class XIconWindow extends XBaseWindow {
+ private final static Logger log = Logger.getLogger("sun.awt.X11.XIconWindow");
+ XDecoratedPeer parent;
+ Dimension size;
+ long iconPixmap = 0;
+ long iconMask = 0;
+ int iconWidth = 0;
+ int iconHeight = 0;
+ XIconWindow(XDecoratedPeer parent) {
+ super(new XCreateWindowParams(new Object[] {
+ PARENT, parent,
+ DELAYED, Boolean.TRUE}));
+ }
+
+ void instantPreInit(XCreateWindowParams params) {
+ super.instantPreInit(params);
+ this.parent = (XDecoratedPeer)params.get(PARENT);
+ }
+
+ /**
+ * @return array of XIconsSize structures, caller must free this array after use.
+ */
+ private XIconSize[] getIconSizes() {
+ XToolkit.awtLock();
+ try {
+ AwtGraphicsConfigData adata = parent.getGraphicsConfigurationData();
+ final long screen = adata.get_awt_visInfo().get_screen();
+ final long display = XToolkit.getDisplay();
+
+ if (log.isLoggable(Level.FINEST)) log.finest(adata.toString());
+
+ long status =
+ XlibWrapper.XGetIconSizes(display, XToolkit.getDefaultRootWindow(),
+ XlibWrapper.larg1, XlibWrapper.iarg1);
+ if (status == 0) {
+ return null;
+ }
+ int count = Native.getInt(XlibWrapper.iarg1);
+ long sizes_ptr = Native.getLong(XlibWrapper.larg1); // XIconSize*
+ log.log(Level.FINEST, "count = {1}, sizes_ptr = {0}", new Object[] {Long.valueOf(sizes_ptr), Integer.valueOf(count)});
+ XIconSize[] res = new XIconSize[count];
+ for (int i = 0; i < count; i++, sizes_ptr += XIconSize.getSize()) {
+ res[i] = new XIconSize(sizes_ptr);
+ log.log(Level.FINEST, "sizes_ptr[{1}] = {0}", new Object[] {res[i], Integer.valueOf(i)});
+ }
+ return res;
+ } finally {
+ XToolkit.awtUnlock();
+ }
+ }
+
+ private Dimension calcIconSize(int widthHint, int heightHint) {
+ if (XWM.getWMID() == XWM.ICE_WM) {
+ // ICE_WM has a bug - it only displays icons of the size
+ // 16x16, while reporting 32x32 in its size list
+ log.log(Level.FINEST, "Returning ICE_WM icon size: 16x16");
+ return new Dimension(16, 16);
+ }
+
+ XIconSize[] sizeList = getIconSizes();
+ log.log(Level.FINEST, "Icon sizes: {0}", new Object[] {sizeList});
+ if (sizeList == null) {
+ // No icon sizes so we simply fall back to 16x16
+ return new Dimension(16, 16);
+ }
+ boolean found = false;
+ int dist = 0xffffffff, newDist, diff = 0, closestHeight, closestWidth;
+ int saveWidth = 0, saveHeight = 0;
+ for (int i = 0; i < sizeList.length; i++) {
+ if (widthHint >= sizeList[i].get_min_width() &&
+ widthHint <= sizeList[i].get_max_width() &&
+ heightHint >= sizeList[i].get_min_height() &&
+ heightHint <= sizeList[i].get_max_height()) {
+ found = true;
+ if ((((widthHint-sizeList[i].get_min_width())
+ % sizeList[i].get_width_inc()) == 0) &&
+ (((heightHint-sizeList[i].get_min_height())
+ % sizeList[i].get_height_inc()) ==0)) {
+ /* Found an exact match */
+ saveWidth = widthHint;
+ saveHeight = heightHint;
+ dist = 0;
+ break;
+ }
+ diff = widthHint - sizeList[i].get_min_width();
+ if (diff == 0) {
+ closestWidth = widthHint;
+ } else {
+ diff = diff%sizeList[i].get_width_inc();
+ closestWidth = widthHint - diff;
+ }
+ diff = heightHint - sizeList[i].get_min_height();
+ if (diff == 0) {
+ closestHeight = heightHint;
+ } else {
+ diff = diff%sizeList[i].get_height_inc();
+ closestHeight = heightHint - diff;
+ }
+ newDist = closestWidth*closestWidth +
+ closestHeight*closestHeight;
+ if (dist > newDist) {
+ saveWidth = closestWidth;
+ saveHeight = closestHeight;
+ dist = newDist;
+ }
+ }
+ }
+ if (log.isLoggable(Level.FINEST)) {
+ log.finest("found=" + found);
+ }
+ if (!found) {
+ if (log.isLoggable(Level.FINEST)) {
+ log.finest("widthHint=" + widthHint + ", heightHint=" + heightHint
+ + ", saveWidth=" + saveWidth + ", saveHeight=" + saveHeight
+ + ", max_width=" + sizeList[0].get_max_width()
+ + ", max_height=" + sizeList[0].get_max_height()
+ + ", min_width=" + sizeList[0].get_min_width()
+ + ", min_height=" + sizeList[0].get_min_height());
+ }
+
+ if (widthHint > sizeList[0].get_max_width() ||
+ heightHint > sizeList[0].get_max_height())
+ {
+ // Icon image too big
+ /* determine which way to scale */
+ int wdiff = widthHint - sizeList[0].get_max_width();
+ int hdiff = heightHint - sizeList[0].get_max_height();
+ if (log.isLoggable(Level.FINEST)) {
+ log.finest("wdiff=" + wdiff + ", hdiff=" + hdiff);
+ }
+ if (wdiff >= hdiff) { /* need to scale width more */
+ saveWidth = sizeList[0].get_max_width();
+ saveHeight =
+ (int)(((double)sizeList[0].get_max_width()/widthHint) * heightHint);
+ } else {
+ saveWidth =
+ (int)(((double)sizeList[0].get_max_height()/heightHint) * widthHint);
+ saveHeight = sizeList[0].get_max_height();
+ }
+ } else if (widthHint < sizeList[0].get_min_width() ||
+ heightHint < sizeList[0].get_min_height())
+ {
+ // Icon image too small
+ saveWidth = (sizeList[0].get_min_width()+sizeList[0].get_max_width())/2;
+ saveHeight = (sizeList[0].get_min_height()+sizeList[0].get_max_height())/2;
+ } else {
+ // Icon image fits within right size
+ saveWidth = widthHint;
+ saveHeight = widthHint;
+ }
+ }
+
+ XToolkit.awtLock();
+ try {
+ XlibWrapper.XFree(sizeList[0].pData);
+ } finally {
+ XToolkit.awtUnlock();
+ }
+
+ if (log.isLoggable(Level.FINEST)) {
+ log.finest("return " + saveWidth + "x" + saveHeight);
+ }
+ return new Dimension(saveWidth, saveHeight);
+ }
+
+ /**
+ * @return preffered icon size calculated from specific icon
+ */
+ Dimension getIconSize(int widthHint, int heightHint) {
+ if (size == null) {
+ size = calcIconSize(widthHint, heightHint);
+ }
+ return size;
+ }
+
+ /**
+ * This function replaces iconPixmap handle with new image
+ * It does not replace window's hints, so it should be
+ * called only from setIconImage()
+ */
+ void replaceImage(Image img)
+ {
+ if (parent == null) {
+ return;
+ }
+ //Prepare image
+ //create new buffered image of desired size
+ //in current window's color model
+ BufferedImage bi = null;
+ if (img != null && iconWidth != 0 && iconHeight != 0) {
+ GraphicsConfiguration defaultGC = parent.getGraphicsConfiguration().getDevice().getDefaultConfiguration();
+ ColorModel model = defaultGC.getColorModel();
+ WritableRaster raster = model.createCompatibleWritableRaster(iconWidth, iconHeight);
+ bi = new BufferedImage(model, raster, model.isAlphaPremultiplied(), null);
+ Graphics g = bi.getGraphics();
+ try {
+ //We need to draw image on SystemColors.window
+ //for using as iconWindow's background
+ g.setColor(SystemColor.window);
+ g.fillRect(0, 0, iconWidth, iconHeight);
+ if (g instanceof Graphics2D) {
+ ((Graphics2D)g).setComposite(AlphaComposite.Src);
+ }
+ g.drawImage(img, 0, 0, iconWidth, iconHeight, null);
+ } finally {
+ g.dispose();
+ }
+ }
+ //create pixmap
+ XToolkit.awtLock();
+ try {
+ if (iconPixmap != 0) {
+ XlibWrapper.XFreePixmap(XToolkit.getDisplay(), iconPixmap);
+ iconPixmap = 0;
+ log.finest("Freed previous pixmap");
+ }
+ if (bi == null || iconWidth == 0 || iconHeight == 0) {
+ return; //The iconPixmap is 0 now, we have done everything
+ }
+ AwtGraphicsConfigData adata = parent.getGraphicsConfigurationData();
+ awtImageData awtImage = adata.get_awtImage(0);
+ XVisualInfo visInfo = adata.get_awt_visInfo();
+ iconPixmap = XlibWrapper.XCreatePixmap(XToolkit.getDisplay(),
+ XlibWrapper.RootWindow(XToolkit.getDisplay(), visInfo.get_screen()),
+ iconWidth,
+ iconHeight,
+ awtImage.get_Depth()
+ );
+ if (iconPixmap == 0) {
+ log.finest("Can't create new pixmap for icon");
+ return; //Can't do nothing
+ }
+ //Transform image data
+ long bytes = 0;
+ DataBuffer srcBuf = bi.getData().getDataBuffer();
+ if (srcBuf instanceof DataBufferByte) {
+ byte[] buf = ((DataBufferByte)srcBuf).getData();
+ ColorData cdata = adata.get_color_data(0);
+ int num_colors = cdata.get_awt_numICMcolors();
+ for (int i = 0; i < buf.length; i++) {
+ buf[i] = (buf[i] >= num_colors) ?
+ 0 : cdata.get_awt_icmLUT2Colors(buf[i]);
+ }
+ bytes = Native.toData(buf);
+ } else if (srcBuf instanceof DataBufferInt) {
+ bytes = Native.toData(((DataBufferInt)srcBuf).getData());
+ } else if (srcBuf instanceof DataBufferUShort) {
+ bytes = Native.toData(((DataBufferUShort)srcBuf).getData());
+ } else {
+ throw new IllegalArgumentException("Unknown data buffer: " + srcBuf);
+ }
+ int bpp = awtImage.get_wsImageFormat().get_bits_per_pixel();
+ int slp =awtImage.get_wsImageFormat().get_scanline_pad();
+ int bpsl = paddedwidth(iconWidth*bpp, slp) >> 3;
+ if (((bpsl << 3) / bpp) < iconWidth) {
+ log.finest("Image format doesn't fit to icon width");
+ return;
+ }
+ long dst = XlibWrapper.XCreateImage(XToolkit.getDisplay(),
+ visInfo.get_visual(),
+ (int)awtImage.get_Depth(),
+ (int)XlibWrapper.ZPixmap,
+ 0,
+ bytes,
+ iconWidth,
+ iconHeight,
+ 32,
+ bpsl);
+ if (dst == 0) {
+ log.finest("Can't create XImage for icon");
+ XlibWrapper.XFreePixmap(XToolkit.getDisplay(), iconPixmap);
+ iconPixmap = 0;
+ return;
+ } else {
+ log.finest("Created XImage for icon");
+ }
+ long gc = XlibWrapper.XCreateGC(XToolkit.getDisplay(), iconPixmap, 0, 0);
+ if (gc == 0) {
+ log.finest("Can't create GC for pixmap");
+ XlibWrapper.XFreePixmap(XToolkit.getDisplay(), iconPixmap);
+ iconPixmap = 0;
+ return;
+ } else {
+ log.finest("Created GC for pixmap");
+ }
+ try {
+ XlibWrapper.XPutImage(XToolkit.getDisplay(), iconPixmap, gc,
+ dst, 0, 0, 0, 0, iconWidth, iconHeight);
+ } finally {
+ XlibWrapper.XFreeGC(XToolkit.getDisplay(), gc);
+ }
+ } finally {
+ XToolkit.awtUnlock();
+ }
+ }
+
+ /**
+ * This function replaces iconPixmap handle with new image
+ * It does not replace window's hints, so it should be
+ * called only from setIconImage()
+ */
+ void replaceMask(Image img) {
+ if (parent == null) {
+ return;
+ }
+ //Prepare image
+ BufferedImage bi = null;
+ if (img != null && iconWidth != 0 && iconHeight != 0) {
+ bi = new BufferedImage(iconWidth, iconHeight, BufferedImage.TYPE_INT_ARGB);
+ Graphics g = bi.getGraphics();
+ try {
+ g.drawImage(img, 0, 0, iconWidth, iconHeight, null);
+ } finally {
+ g.dispose();
+ }
+ }
+ //create mask
+ XToolkit.awtLock();
+ try {
+ if (iconMask != 0) {
+ XlibWrapper.XFreePixmap(XToolkit.getDisplay(), iconMask);
+ iconMask = 0;
+ log.finest("Freed previous mask");
+ }
+ if (bi == null || iconWidth == 0 || iconHeight == 0) {
+ return; //The iconMask is 0 now, we have done everything
+ }
+ AwtGraphicsConfigData adata = parent.getGraphicsConfigurationData();
+ awtImageData awtImage = adata.get_awtImage(0);
+ XVisualInfo visInfo = adata.get_awt_visInfo();
+ ColorModel cm = bi.getColorModel();
+ DataBuffer srcBuf = bi.getRaster().getDataBuffer();
+ int sidx = 0;//index of source element
+ int bpl = (iconWidth + 7) >> 3;//bytes per line
+ byte[] destBuf = new byte[bpl * iconHeight];
+ int didx = 0;//index of destination element
+ for (int i = 0; i < iconHeight; i++) {
+ int dbit = 0;//index of current bit
+ int cv = 0;
+ for (int j = 0; j < iconWidth; j++) {
+ if (cm.getAlpha(srcBuf.getElem(sidx)) != 0 ) {
+ cv = cv + (1 << dbit);
+ }
+ dbit++;
+ if (dbit == 8) {
+ destBuf[didx] = (byte)cv;
+ cv = 0;
+ dbit = 0;
+ didx++;
+ }
+ sidx++;
+ }
+ }
+ iconMask = XlibWrapper.XCreateBitmapFromData(XToolkit.getDisplay(),
+ XlibWrapper.RootWindow(XToolkit.getDisplay(), visInfo.get_screen()),
+ Native.toData(destBuf),
+ iconWidth, iconHeight);
+ } finally {
+ XToolkit.awtUnlock();
+ }
+ }
+
+ /**
+ * Sets icon image by selecting one of the images from the list.
+ * The selected image is the one having the best matching size.
+ */
+ void setIconImages(java.util.List<XIconInfo> icons) {
+ if (icons == null || icons.size() == 0) return;
+
+ int minDiff = Integer.MAX_VALUE;
+ Image min = null;
+ for (XIconInfo iconInfo : icons) {
+ if (iconInfo.isValid()) {
+ Image image = iconInfo.getImage();
+ Dimension dim = calcIconSize(image.getWidth(null), image.getHeight(null));
+ int widthDiff = Math.abs(dim.width - image.getWidth(null));
+ int heightDiff = Math.abs(image.getHeight(null) - dim.height);
+
+ // "=" below allows to select the best matching icon
+ if (minDiff >= (widthDiff + heightDiff)) {
+ minDiff = (widthDiff + heightDiff);
+ min = image;
+ }
+ }
+ }
+ if (min != null) {
+ log.log(Level.FINER, "Icon: {0}x{1}", new Object[] { min.getWidth(null), min.getHeight(null)});
+ setIconImage(min);
+ }
+ }
+
+ void setIconImage(Image img) {
+ if (img == null) {
+ //if image is null, reset to default image
+ replaceImage(null);
+ replaceMask(null);
+ } else {
+ //get image size
+ int width;
+ int height;
+ if (img instanceof ToolkitImage) {
+ ImageRepresentation ir = ((ToolkitImage)img).getImageRep();
+ ir.reconstruct(ImageObserver.ALLBITS);
+ width = ir.getWidth();
+ height = ir.getHeight();
+ }
+ else {
+ width = img.getWidth(null);
+ height = img.getHeight(null);
+ }
+ Dimension iconSize = getIconSize(width, height);
+ if (iconSize != null) {
+ log.log(Level.FINEST, "Icon size: {0}", iconSize);
+ iconWidth = iconSize.width;
+ iconHeight = iconSize.height;
+ } else {
+ log.finest("Error calculating image size");
+ iconWidth = 0;
+ iconHeight = 0;
+ }
+ replaceImage(img);
+ replaceMask(img);
+ }
+ //create icon window and set XWMHints
+ XToolkit.awtLock();
+ try {
+ AwtGraphicsConfigData adata = parent.getGraphicsConfigurationData();
+ awtImageData awtImage = adata.get_awtImage(0);
+ XVisualInfo visInfo = adata.get_awt_visInfo();
+ XWMHints hints = parent.getWMHints();
+ window = hints.get_icon_window();
+ if (window == 0) {
+ log.finest("Icon window wasn't set");
+ XCreateWindowParams params = getDelayedParams();
+ params.add(BORDER_PIXEL, Long.valueOf(XToolkit.getAwtDefaultFg()));
+ params.add(BACKGROUND_PIXMAP, iconPixmap);
+ params.add(COLORMAP, adata.get_awt_cmap());
+ params.add(DEPTH, awtImage.get_Depth());
+ params.add(VISUAL_CLASS, (int)XlibWrapper.InputOutput);
+ params.add(VISUAL, visInfo.get_visual());
+ params.add(VALUE_MASK, XlibWrapper.CWBorderPixel | XlibWrapper.CWColormap | XlibWrapper.CWBackPixmap);
+ params.add(PARENT_WINDOW, XlibWrapper.RootWindow(XToolkit.getDisplay(), visInfo.get_screen()));
+ params.add(BOUNDS, new Rectangle(0, 0, iconWidth, iconHeight));
+ params.remove(DELAYED);
+ init(params);
+ if (getWindow() == 0) {
+ log.finest("Can't create new icon window");
+ } else {
+ log.finest("Created new icon window");
+ }
+ }
+ if (getWindow() != 0) {
+ XlibWrapper.XSetWindowBackgroundPixmap(XToolkit.getDisplay(), getWindow(), iconPixmap);
+ XlibWrapper.XClearWindow(XToolkit.getDisplay(), getWindow());
+ }
+ // Provide both pixmap and window, WM or Taskbar will use the one they find more appropriate
+ long newFlags = hints.get_flags() | XlibWrapper.IconPixmapHint | XlibWrapper.IconMaskHint;
+ if (getWindow() != 0) {
+ newFlags |= XlibWrapper.IconWindowHint;
+ }
+ hints.set_flags(newFlags);
+ hints.set_icon_pixmap(iconPixmap);
+ hints.set_icon_mask(iconMask);
+ hints.set_icon_window(getWindow());
+ XlibWrapper.XSetWMHints(XToolkit.getDisplay(), parent.getShell(), hints.pData);
+ log.finest("Set icon window hint");
+ } finally {
+ XToolkit.awtUnlock();
+ }
+ }
+
+ static int paddedwidth(int number, int boundary)
+ {
+ return (((number) + ((boundary) - 1)) & (~((boundary) - 1)));
+ }
+}