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