1 /*
2 * Copyright (c) 2005, 2015, 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
38 import sun.awt.AWTAccessor;
39 import sun.awt.SunToolkit;
40 import sun.awt.image.IntegerComponentRaster;
41
42 final class WTrayIconPeer extends WObjectPeer implements TrayIconPeer {
43 static final int TRAY_ICON_WIDTH = 16;
44 static final int TRAY_ICON_HEIGHT = 16;
45 static final int TRAY_ICON_MASK_SIZE = (TRAY_ICON_WIDTH * TRAY_ICON_HEIGHT) / 8;
46
47 IconObserver observer = new IconObserver();
48 boolean firstUpdate = true;
49 Frame popupParent = new Frame("PopupMessageWindow");
50 PopupMenu popup;
51
52 @Override
53 protected void disposeImpl() {
54 if (popupParent != null) {
55 popupParent.dispose();
56 }
57 popupParent.dispose();
58 _dispose();
59 WToolkit.targetDisposedPeer(target, this);
60 }
61
62 WTrayIconPeer(TrayIcon target) {
63 this.target = target;
64 popupParent.addNotify();
65 create();
66 updateImage();
67 }
68
69 @Override
70 public void updateImage() {
71 Image image = ((TrayIcon)target).getImage();
72 if (image != null) {
73 updateNativeImage(image);
74 }
75 }
76
77 @Override
78 public native void setToolTip(String tooltip);
79
80 @Override
81 public synchronized void showPopupMenu(final int x, final int y) {
82 if (isDisposed())
83 return;
84
85 SunToolkit.executeOnEventHandlerThread(target, () -> {
86 PopupMenu newPopup = ((TrayIcon)target).getPopupMenu();
87 if (popup != newPopup) {
88 if (popup != null) {
89 popupParent.remove(popup);
90 }
91 if (newPopup != null) {
92 popupParent.add(newPopup);
93 }
94 popup = newPopup;
95 }
96 if (popup != null) {
97 WPopupMenuPeer peer = AWTAccessor.getMenuComponentAccessor()
98 .getPeer(popup);
99 peer.show(popupParent, new Point(x, y));
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}, 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 }
--- EOF ---