1 /* 2 * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package sun.awt.windows; 27 28 import java.awt.Graphics2D; 29 import java.awt.AWTEvent; 30 import java.awt.Frame; 31 import java.awt.PopupMenu; 32 import java.awt.Point; 33 import java.awt.TrayIcon; 34 import java.awt.Image; 35 import java.awt.peer.TrayIconPeer; 36 import java.awt.image.*; 37 import sun.awt.SunToolkit; 38 import sun.awt.image.IntegerComponentRaster; 39 40 final class WTrayIconPeer extends WObjectPeer implements TrayIconPeer { 41 final static int TRAY_ICON_WIDTH = 16; 42 final static int TRAY_ICON_HEIGHT = 16; 43 final static int TRAY_ICON_MASK_SIZE = (TRAY_ICON_WIDTH * TRAY_ICON_HEIGHT) / 8; 44 45 IconObserver observer = new IconObserver(); 46 boolean firstUpdate = true; 47 Frame popupParent = new Frame("PopupMessageWindow"); 48 PopupMenu popup; 49 50 @Override 51 protected void disposeImpl() { 52 if (popupParent != null) { 53 popupParent.dispose(); 54 } 55 popupParent.dispose(); 56 _dispose(); 57 WToolkit.targetDisposedPeer(target, this); 58 } 59 60 WTrayIconPeer(TrayIcon target) { 61 this.target = target; 62 popupParent.addNotify(); 63 create(); 64 updateImage(); 65 } 66 67 @Override 68 public void updateImage() { 69 Image image = ((TrayIcon)target).getImage(); 70 if (image != null) { 71 updateNativeImage(image); 72 } 73 } 74 75 @Override 76 public native void setToolTip(String tooltip); 77 78 @Override 79 public synchronized void showPopupMenu(final int x, final int y) { 80 if (isDisposed()) 81 return; 82 83 SunToolkit.executeOnEventHandlerThread(target, new Runnable() { 84 @Override 85 @SuppressWarnings("deprecation") 86 public void run() { 87 PopupMenu newPopup = ((TrayIcon)target).getPopupMenu(); 88 if (popup != newPopup) { 89 if (popup != null) { 90 popupParent.remove(popup); 91 } 92 if (newPopup != null) { 93 popupParent.add(newPopup); 94 } 95 popup = newPopup; 96 } 97 if (popup != null) { 98 ((WPopupMenuPeer)popup.getPeer()).show(popupParent, new Point(x, y)); 99 } 100 } 101 }); 102 } 103 104 @Override 105 public void displayMessage(String caption, String text, String messageType) { 106 // The situation when both caption and text are null is processed in the shared code. 107 if (caption == null) { 108 caption = ""; 109 } 110 if (text == null) { 111 text = ""; 112 } 113 _displayMessage(caption, text, messageType); 114 } 115 116 117 // *********************************************** 118 // *********************************************** 119 120 121 synchronized void updateNativeImage(Image image) { 122 if (isDisposed()) 123 return; 124 125 boolean autosize = ((TrayIcon)target).isImageAutoSize(); 126 127 BufferedImage bufImage = new BufferedImage(TRAY_ICON_WIDTH, TRAY_ICON_HEIGHT, 128 BufferedImage.TYPE_INT_ARGB); 129 Graphics2D gr = bufImage.createGraphics(); 130 if (gr != null) { 131 try { 132 gr.setPaintMode(); 133 134 gr.drawImage(image, 0, 0, (autosize ? TRAY_ICON_WIDTH : image.getWidth(observer)), 135 (autosize ? TRAY_ICON_HEIGHT : image.getHeight(observer)), observer); 136 137 createNativeImage(bufImage); 138 139 updateNativeIcon(!firstUpdate); 140 if (firstUpdate) firstUpdate = false; 141 142 } finally { 143 gr.dispose(); 144 } 145 } 146 } 147 148 void createNativeImage(BufferedImage bimage) { 149 Raster raster = bimage.getRaster(); 150 byte[] andMask = new byte[TRAY_ICON_MASK_SIZE]; 151 int pixels[] = ((DataBufferInt)raster.getDataBuffer()).getData(); 152 int npixels = pixels.length; 153 int ficW = raster.getWidth(); 154 155 for (int i = 0; i < npixels; i++) { 156 int ibyte = i / 8; 157 int omask = 1 << (7 - (i % 8)); 158 159 if ((pixels[i] & 0xff000000) == 0) { 160 // Transparent bit 161 if (ibyte < andMask.length) { 162 andMask[ibyte] |= omask; 163 } 164 } 165 } 166 167 if (raster instanceof IntegerComponentRaster) { 168 ficW = ((IntegerComponentRaster)raster).getScanlineStride(); 169 } 170 setNativeIcon(((DataBufferInt)bimage.getRaster().getDataBuffer()).getData(), 171 andMask, ficW, raster.getWidth(), raster.getHeight()); 172 } 173 174 void postEvent(AWTEvent event) { 175 WToolkit.postEvent(WToolkit.targetToAppContext(target), event); 176 } 177 178 native void create(); 179 synchronized native void _dispose(); 180 181 /* 182 * Updates/adds the icon in/to the system tray. 183 * @param doUpdate if <code>true</code>, updates the icon, 184 * otherwise, adds the icon 185 */ 186 native void updateNativeIcon(boolean doUpdate); 187 188 native void setNativeIcon(int[] rData, byte[] andMask, int nScanStride, 189 int width, int height); 190 191 native void _displayMessage(String caption, String text, String messageType); 192 193 class IconObserver implements ImageObserver { 194 @Override 195 public boolean imageUpdate(Image image, int flags, int x, int y, int width, int height) { 196 if (image != ((TrayIcon)target).getImage() || // if the image has been changed 197 isDisposed()) 198 { 199 return false; 200 } 201 if ((flags & (ImageObserver.FRAMEBITS | ImageObserver.ALLBITS | 202 ImageObserver.WIDTH | ImageObserver.HEIGHT)) != 0) 203 { 204 updateNativeImage(image); 205 } 206 return (flags & ImageObserver.ALLBITS) == 0; 207 } 208 } 209 }