blob: 93dc4b19db39e5ffce2b9b912145ab4209017cbc [file] [log] [blame]
/*
* Copyright (c) 2005, 2007, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.awt.windows;
import java.awt.Graphics2D;
import java.awt.AWTEvent;
import java.awt.Frame;
import java.awt.PopupMenu;
import java.awt.Point;
import java.awt.TrayIcon;
import java.awt.Image;
import java.awt.peer.TrayIconPeer;
import java.awt.image.*;
import sun.awt.SunToolkit;
import sun.awt.image.IntegerComponentRaster;
import sun.awt.windows.WPopupMenuPeer;
public class WTrayIconPeer extends WObjectPeer implements TrayIconPeer {
final static int TRAY_ICON_WIDTH = 16;
final static int TRAY_ICON_HEIGHT = 16;
final static int TRAY_ICON_MASK_SIZE = (TRAY_ICON_WIDTH * TRAY_ICON_HEIGHT) / 8;
IconObserver observer = new IconObserver();
boolean firstUpdate = true;
Frame popupParent = new Frame("PopupMessageWindow");
PopupMenu popup;
protected void disposeImpl() {
if (popupParent != null) {
popupParent.dispose();
}
popupParent.dispose();
_dispose();
WToolkit.targetDisposedPeer(target, this);
}
WTrayIconPeer(TrayIcon target) {
this.target = target;
popupParent.addNotify();
create();
updateImage();
}
public void updateImage() {
Image image = ((TrayIcon)target).getImage();
if (image != null) {
updateNativeImage(image);
}
}
public native void setToolTip(String tooltip);
public synchronized void showPopupMenu(final int x, final int y) {
if (isDisposed())
return;
SunToolkit.executeOnEventHandlerThread(target, new Runnable() {
public void run() {
PopupMenu newPopup = ((TrayIcon)target).getPopupMenu();
if (popup != newPopup) {
if (popup != null) {
popupParent.remove(popup);
}
if (newPopup != null) {
popupParent.add(newPopup);
}
popup = newPopup;
}
if (popup != null) {
((WPopupMenuPeer)popup.getPeer()).show(popupParent, new Point(x, y));
}
}
});
}
public void displayMessage(String caption, String text, String messageType) {
// The situation when both caption and text are null is processed in the shared code.
if (caption == null) {
caption = "";
}
if (text == null) {
text = "";
}
_displayMessage(caption, text, messageType);
}
// ***********************************************
// ***********************************************
synchronized void updateNativeImage(Image image) {
if (isDisposed())
return;
boolean autosize = ((TrayIcon)target).isImageAutoSize();
BufferedImage bufImage = new BufferedImage(TRAY_ICON_WIDTH, TRAY_ICON_HEIGHT,
BufferedImage.TYPE_INT_ARGB);
Graphics2D gr = bufImage.createGraphics();
if (gr != null) {
try {
gr.setPaintMode();
gr.drawImage(image, 0, 0, (autosize ? TRAY_ICON_WIDTH : image.getWidth(observer)),
(autosize ? TRAY_ICON_HEIGHT : image.getHeight(observer)), observer);
createNativeImage(bufImage);
updateNativeIcon(!firstUpdate);
if (firstUpdate) firstUpdate = false;
} finally {
gr.dispose();
}
}
}
void createNativeImage(BufferedImage bimage) {
Raster raster = bimage.getRaster();
byte[] andMask = new byte[TRAY_ICON_MASK_SIZE];
int pixels[] = ((DataBufferInt)raster.getDataBuffer()).getData();
int npixels = pixels.length;
int ficW = raster.getWidth();
for (int i = 0; i < npixels; i++) {
int ibyte = i / 8;
int omask = 1 << (7 - (i % 8));
if ((pixels[i] & 0xff000000) == 0) {
// Transparent bit
if (ibyte < andMask.length) {
andMask[ibyte] |= omask;
}
}
}
if (raster instanceof IntegerComponentRaster) {
ficW = ((IntegerComponentRaster)raster).getScanlineStride();
}
setNativeIcon(((DataBufferInt)bimage.getRaster().getDataBuffer()).getData(),
andMask, ficW, raster.getWidth(), raster.getHeight());
}
void postEvent(AWTEvent event) {
WToolkit.postEvent(WToolkit.targetToAppContext(target), event);
}
native void create();
synchronized native void _dispose();
/*
* Updates/adds the icon in/to the system tray.
* @param doUpdate if <code>true</code>, updates the icon,
* otherwise, adds the icon
*/
native void updateNativeIcon(boolean doUpdate);
native void setNativeIcon(int[] rData, byte[] andMask, int nScanStride,
int width, int height);
native void _displayMessage(String caption, String text, String messageType);
class IconObserver implements ImageObserver {
public boolean imageUpdate(Image image, int flags, int x, int y, int width, int height) {
if (image != ((TrayIcon)target).getImage() || // if the image has been changed
isDisposed())
{
return false;
}
if ((flags & (ImageObserver.FRAMEBITS | ImageObserver.ALLBITS |
ImageObserver.WIDTH | ImageObserver.HEIGHT)) != 0)
{
updateNativeImage(image);
}
return (flags & ImageObserver.ALLBITS) == 0;
}
}
}