/*
 * Copyright 2005-2007 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.event.*;
import java.awt.peer.TrayIconPeer;
import sun.awt.*;
import java.awt.image.*;
import java.text.BreakIterator;
import java.util.Vector;
import java.lang.reflect.Field;
import java.util.logging.Logger;
import java.util.logging.Level;
import java.util.AbstractQueue;
import java.util.concurrent.ArrayBlockingQueue;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.lang.reflect.InvocationTargetException;

public class XTrayIconPeer implements TrayIconPeer {
    private static final Logger ctrLog = Logger.getLogger("sun.awt.X11.XTrayIconPeer.centering");

    TrayIcon target;
    TrayIconEventProxy eventProxy;
    XTrayIconEmbeddedFrame eframe;
    TrayIconCanvas canvas;
    Balloon balloon;
    Tooltip tooltip;
    PopupMenu popup;
    String tooltipString;
    boolean isTrayIconDisplayed;
    long eframeParentID;
    final XEventDispatcher parentXED, eframeXED;

    static final XEventDispatcher dummyXED = new XEventDispatcher() {
            public void dispatchEvent(XEvent ev) {}
        };

    volatile boolean isDisposed;

    boolean isParentWindowLocated;
    int old_x, old_y;
    int ex_width, ex_height;

    final static int TRAY_ICON_WIDTH = 24;
    final static int TRAY_ICON_HEIGHT = 24;

    XTrayIconPeer(TrayIcon target)
      throws AWTException
    {
        this.target = target;

        eventProxy = new TrayIconEventProxy(this);

        canvas = new TrayIconCanvas(target, TRAY_ICON_WIDTH, TRAY_ICON_HEIGHT);

        eframe = new XTrayIconEmbeddedFrame();

        eframe.setSize(TRAY_ICON_WIDTH, TRAY_ICON_HEIGHT);
        eframe.add(canvas);

        // Fix for 6317038: as EmbeddedFrame is instance of Frame, it is blocked
        // by modal dialogs, but in the case of TrayIcon it shouldn't. So we
        // set ModalExclusion property on it.
        AccessController.doPrivileged(new PrivilegedAction() {
            public Object run() {
                eframe.setModalExclusionType(Dialog.ModalExclusionType.TOOLKIT_EXCLUDE);
                return null;
            }
        });


        if (XWM.getWMID() != XWM.METACITY_WM) {
            parentXED = dummyXED; // We don't like to leave it 'null'.

        } else {
            parentXED = new XEventDispatcher() {
                // It's executed under AWTLock.
                public void dispatchEvent(XEvent ev) {
                    if (isDisposed() || ev.get_type() != XlibWrapper.ConfigureNotify) {
                        return;
                    }

                    XConfigureEvent ce = ev.get_xconfigure();

                    ctrLog.log(Level.FINE, "ConfigureNotify on parent of {0}: {1}x{2}+{3}+{4} (old: {5}+{6})",
                               new Object[] { XTrayIconPeer.this, ce.get_width(), ce.get_height(),
                                              ce.get_x(), ce.get_y(), old_x, old_y });

                    // A workaround for Gnome/Metacity (it doesn't affect the behaviour on KDE).
                    // On Metacity the EmbeddedFrame's parent window bounds are larger
                    // than TrayIcon size required (that is we need a square but a rectangle
                    // is provided by the Panel Notification Area). The parent's background color
                    // differs from the Panel's one. To hide the background we resize parent
                    // window so that it fits the EmbeddedFrame.
                    // However due to resizing the parent window it loses centering in the Panel.
                    // We center it when discovering that some of its side is of size greater
                    // than the fixed value. Centering is being done by "X" (when the parent's width
                    // is greater) and by "Y" (when the parent's height is greater).

                    // Actually we need this workaround until we could detect taskbar color.

                    if (ce.get_height() != TRAY_ICON_HEIGHT && ce.get_width() != TRAY_ICON_WIDTH) {

                        // If both the height and the width differ from the fixed size then WM
                        // must level at least one side to the fixed size. For some reason it may take
                        // a few hops (even after reparenting) and we have to skip the intermediate ones.
                        ctrLog.log(Level.FINE, "ConfigureNotify on parent of {0}. Skipping as intermediate resizing.",
                                   XTrayIconPeer.this);
                        return;

                    } else if (ce.get_height() > TRAY_ICON_HEIGHT) {

                        ctrLog.log(Level.FINE, "ConfigureNotify on parent of {0}. Centering by \"Y\".",
                                   XTrayIconPeer.this);

                        XlibWrapper.XMoveResizeWindow(XToolkit.getDisplay(), eframeParentID,
                                                      ce.get_x(),
                                                      ce.get_y()+ce.get_height()/2-TRAY_ICON_HEIGHT/2,
                                                      TRAY_ICON_WIDTH,
                                                      TRAY_ICON_HEIGHT);
                        ex_height = ce.get_height();
                        ex_width = 0;

                    } else if (ce.get_width() > TRAY_ICON_WIDTH) {

                        ctrLog.log(Level.FINE, "ConfigureNotify on parent of {0}. Centering by \"X\".",
                                   XTrayIconPeer.this);

                        XlibWrapper.XMoveResizeWindow(XToolkit.getDisplay(), eframeParentID,
                                                      ce.get_x()+ce.get_width()/2 - TRAY_ICON_WIDTH/2,
                                                      ce.get_y(),
                                                      TRAY_ICON_WIDTH,
                                                      TRAY_ICON_HEIGHT);
                        ex_width = ce.get_width();
                        ex_height = 0;

                    } else if (isParentWindowLocated && ce.get_x() != old_x && ce.get_y() != old_y) {
                        // If moving by both "X" and "Y".
                        // When some tray icon gets removed from the tray, a Java icon may be repositioned.
                        // In this case the parent window also lose centering. We have to restore it.

                        if (ex_height != 0) {

                            ctrLog.log(Level.FINE, "ConfigureNotify on parent of {0}. Move detected. Centering by \"Y\".",
                                       XTrayIconPeer.this);

                            XlibWrapper.XMoveWindow(XToolkit.getDisplay(), eframeParentID,
                                                    ce.get_x(),
                                                    ce.get_y() + ex_height/2 - TRAY_ICON_HEIGHT/2);

                        } else if (ex_width != 0) {

                            ctrLog.log(Level.FINE, "ConfigureNotify on parent of {0}. Move detected. Centering by \"X\".",
                                       XTrayIconPeer.this);

                            XlibWrapper.XMoveWindow(XToolkit.getDisplay(), eframeParentID,
                                                    ce.get_x() + ex_width/2 - TRAY_ICON_WIDTH/2,
                                                    ce.get_y());
                        } else {
                            ctrLog.log(Level.FINE, "ConfigureNotify on parent of {0}. Move detected. Skipping.",
                                       XTrayIconPeer.this);
                        }
                    }
                    old_x = ce.get_x();
                    old_y = ce.get_y();
                    isParentWindowLocated = true;
                }
            };
        }
        eframeXED = new XEventDispatcher() {
                // It's executed under AWTLock.
                XTrayIconPeer xtiPeer = XTrayIconPeer.this;

                public void dispatchEvent(XEvent ev) {
                    if (isDisposed() || ev.get_type() != XlibWrapper.ReparentNotify) {
                        return;
                    }

                    XReparentEvent re = ev.get_xreparent();
                    eframeParentID = re.get_parent();

                    if (eframeParentID == XToolkit.getDefaultRootWindow()) {

                        if (isTrayIconDisplayed) { // most likely Notification Area was removed
                            SunToolkit.executeOnEventHandlerThread(xtiPeer.target, new Runnable() {
                                    public void run() {
                                        SystemTray.getSystemTray().remove(xtiPeer.target);
                                    }
                                });
                        }
                        return;
                    }

                    if (!isTrayIconDisplayed) {
                        addXED(eframeParentID, parentXED, XlibWrapper.StructureNotifyMask);

                        isTrayIconDisplayed = true;
                        XToolkit.awtLockNotifyAll();
                    }
                }
            };

        addXED(getWindow(), eframeXED, XlibWrapper.StructureNotifyMask);

        XSystemTrayPeer.getPeerInstance().addTrayIcon(this); // throws AWTException

        // Wait till the EmbeddedFrame is reparented
        long start = System.currentTimeMillis();
        final long PERIOD = 2000L;
        XToolkit.awtLock();
        try {
            while (!isTrayIconDisplayed) {
                try {
                    XToolkit.awtLockWait(PERIOD);
                } catch (InterruptedException e) {
                    break;
                }
                if (System.currentTimeMillis() - start > PERIOD) {
                    break;
                }
            }
        } finally {
            XToolkit.awtUnlock();
        }

        // This is unlikely to happen.
        if (!isTrayIconDisplayed || eframeParentID == 0 ||
            eframeParentID == XToolkit.getDefaultRootWindow())
        {
            throw new AWTException("TrayIcon couldn't be displayed.");
        }

        eframe.setVisible(true);
        updateImage();

        balloon = new Balloon(this, eframe);
        tooltip = new Tooltip(this, eframe);

        addListeners();
    }

    public void dispose() {
        if (SunToolkit.isDispatchThreadForAppContext(target)) {
            disposeOnEDT();
        } else {
            try {
                SunToolkit.executeOnEDTAndWait(target, new Runnable() {
                        public void run() {
                            disposeOnEDT();
                        }
                    });
            } catch (InterruptedException ie) {
            } catch (InvocationTargetException ite) {}
        }
    }

    private void disposeOnEDT() {
        // All actions that is to be synchronized with disposal
        // should be executed either under AWTLock, or on EDT.
        // isDisposed value must be checked.
        XToolkit.awtLock();
        isDisposed = true;
        XToolkit.awtUnlock();

        removeXED(getWindow(), eframeXED);
        removeXED(eframeParentID, parentXED);
        eframe.realDispose();
        balloon.dispose();
        isTrayIconDisplayed = false;
        XToolkit.targetDisposedPeer(target, this);
    }

    public static void suppressWarningString(Window w) {
        WindowAccessor.setTrayIconWindow(w, true);
    }

    public void setToolTip(String tooltip) {
        tooltipString = tooltip;
    }

    public void updateImage() {
        Runnable r = new Runnable() {
                public void run() {
                    canvas.updateImage(target.getImage());
                }
            };

        if (!SunToolkit.isDispatchThreadForAppContext(target)) {
            SunToolkit.executeOnEventHandlerThread(target, r);
        } else {
            r.run();
        }
    }

    public void displayMessage(String caption, String text, String messageType) {
        Point loc = getLocationOnScreen();
        Rectangle screen = eframe.getGraphicsConfiguration().getBounds();

        // Check if the tray icon is in the bounds of a screen.
        if (!(loc.x < screen.x || loc.x >= screen.x + screen.width ||
              loc.y < screen.y || loc.y >= screen.y + screen.height))
        {
            balloon.display(caption, text, messageType);
        }
    }

    // It's synchronized with disposal by EDT.
    public void showPopupMenu(int x, int y) {
        if (isDisposed())
            return;

        assert SunToolkit.isDispatchThreadForAppContext(target);

        PopupMenu newPopup = target.getPopupMenu();
        if (popup != newPopup) {
            if (popup != null) {
                eframe.remove(popup);
            }
            if (newPopup != null) {
                eframe.add(newPopup);
            }
            popup = newPopup;
        }

        if (popup != null) {
            Point loc = ((XBaseWindow)eframe.getPeer()).toLocal(new Point(x, y));
            popup.show(eframe, loc.x, loc.y);
        }
    }


    // ******************************************************************
    // ******************************************************************


    private void addXED(long window, XEventDispatcher xed, long mask) {
        if (window == 0) {
            return;
        }
        XToolkit.awtLock();
        try {
            XlibWrapper.XSelectInput(XToolkit.getDisplay(), window, mask);
        } finally {
            XToolkit.awtUnlock();
        }
        XToolkit.addEventDispatcher(window, xed);
    }

    private void removeXED(long window, XEventDispatcher xed) {
        if (window == 0) {
            return;
        }
        XToolkit.awtLock();
        try {
            XToolkit.removeEventDispatcher(window, xed);
        } finally {
            XToolkit.awtUnlock();
        }
    }

    // Private method for testing purposes.
    private Point getLocationOnScreen() {
        return eframe.getLocationOnScreen();
    }

    private Rectangle getBounds() {
        Point loc = getLocationOnScreen();
        return new Rectangle(loc.x, loc.y, loc.x + TRAY_ICON_WIDTH, loc.y + TRAY_ICON_HEIGHT);
    }

    void addListeners() {
        canvas.addMouseListener(eventProxy);
        canvas.addMouseMotionListener(eventProxy);
    }

    long getWindow() {
        return ((XEmbeddedFramePeer)eframe.getPeer()).getWindow();
    }

    boolean isDisposed() {
        return isDisposed;
    }

    static class TrayIconEventProxy implements MouseListener, MouseMotionListener {
        XTrayIconPeer xtiPeer;

        TrayIconEventProxy(XTrayIconPeer xtiPeer) {
            this.xtiPeer = xtiPeer;
        }

        public void handleEvent(MouseEvent e) {
            //prevent DRAG events from being posted with TrayIcon source(CR 6565779)
            if (e.getID() == MouseEvent.MOUSE_DRAGGED) {
                return;
            }

            // Event handling is synchronized with disposal by EDT.
            if (xtiPeer.isDisposed()) {
                return;
            }
            Point coord = XBaseWindow.toOtherWindow(xtiPeer.getWindow(),
                                                    XToolkit.getDefaultRootWindow(),
                                                    e.getX(), e.getY());

            if (e.isPopupTrigger()) {
                xtiPeer.showPopupMenu(coord.x, coord.y);
            }

            e.translatePoint(coord.x - e.getX(), coord.y - e.getY());
            // This is a hack in order to set non-Component source to MouseEvent
            // instance.
            // In some cases this could lead to unpredictable result (e.g. when
            // other class tries to cast source field to Component).
            // We already filter DRAG events out (CR 6565779).
            e.setSource(xtiPeer.target);
            Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent(e);
        }
        public void mouseClicked(MouseEvent e) {
            if ((e.getClickCount() > 1 || xtiPeer.balloon.isVisible()) &&
                e.getButton() == MouseEvent.BUTTON1)
            {
                ActionEvent aev = new ActionEvent(xtiPeer.target, ActionEvent.ACTION_PERFORMED,
                                                  xtiPeer.target.getActionCommand(), e.getWhen(),
                                                  e.getModifiers());
                Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent(aev);
            }
            if (xtiPeer.balloon.isVisible()) {
                xtiPeer.balloon.hide();
            }
            handleEvent(e);
        }
        public void mouseEntered(MouseEvent e) {
            xtiPeer.tooltip.enter();
            handleEvent(e);
        }
        public void mouseExited(MouseEvent e) {
            xtiPeer.tooltip.exit();
            handleEvent(e);
        }
        public void mousePressed(MouseEvent e) {
            handleEvent(e);
        }
        public void mouseReleased(MouseEvent e) {
            handleEvent(e);
        }
        public void mouseDragged(MouseEvent e) {
            handleEvent(e);
        }
        public void mouseMoved(MouseEvent e) {
            handleEvent(e);
        }
    }

    static boolean isTrayIconStuffWindow(Window w) {
        return (w instanceof Tooltip) ||
               (w instanceof Balloon) ||
               (w instanceof XTrayIconEmbeddedFrame);
    }

    // ***************************************
    // Special embedded frame for tray icon
    // ***************************************

    private static class XTrayIconEmbeddedFrame extends XEmbeddedFrame {
        public XTrayIconEmbeddedFrame(){
            super(XToolkit.getDefaultRootWindow(), true, true);
        }

        public boolean isUndecorated() {
            return true;
        }

        public boolean isResizable() {
            return false;
        }

        // embedded frame for tray icon shouldn't be disposed by anyone except tray icon
        public void dispose(){
        }

        public void realDispose(){
            super.dispose();
        }
    };

    // ***************************************
    // Classes for painting an image on canvas
    // ***************************************

    static class TrayIconCanvas extends IconCanvas {
        TrayIcon target;
        boolean autosize;

        TrayIconCanvas(TrayIcon target, int width, int height) {
            super(width, height);
            this.target = target;
        }

        // Invoke on EDT.
        protected void repaintImage(boolean doClear) {
            boolean old_autosize = autosize;
            autosize = target.isImageAutoSize();

            curW = autosize ? width : image.getWidth(observer);
            curH = autosize ? height : image.getHeight(observer);

            super.repaintImage(doClear || (old_autosize != autosize));
        }
    }

    static class IconCanvas extends Canvas {
        volatile Image image;
        IconObserver observer;
        int width, height;
        int curW, curH;

        IconCanvas(int width, int height) {
            this.width = curW = width;
            this.height = curH = height;
        }

        // Invoke on EDT.
        public void updateImage(Image image) {
            this.image = image;
            if (observer == null) {
                observer = new IconObserver();
            }
            repaintImage(true);
        }

        // Invoke on EDT.
        protected void repaintImage(boolean doClear) {
            Graphics g = getGraphics();
            if (g != null) {
                try {
                    if (isVisible()) {
                        if (doClear) {
                            update(g);
                        } else {
                            paint(g);
                        }
                    }
                } finally {
                    g.dispose();
                }
            }
        }

        // Invoke on EDT.
        public void paint(Graphics g) {
            if (g != null && curW > 0 && curH > 0) {
                BufferedImage bufImage = new BufferedImage(curW, curH, BufferedImage.TYPE_INT_ARGB);
                Graphics2D gr = bufImage.createGraphics();
                if (gr != null) {
                    try {
                        gr.setColor(getBackground());
                        gr.fillRect(0, 0, curW, curH);
                        gr.drawImage(image, 0, 0, curW, curH, observer);
                        gr.dispose();

                        g.drawImage(bufImage, 0, 0, curW, curH, null);
                    } finally {
                        gr.dispose();
                    }
                }
            }
        }

        class IconObserver implements ImageObserver {
            public boolean imageUpdate(final Image image, final int flags, int x, int y, int width, int height) {
                if (image != IconCanvas.this.image || // if the image has been changed
                    !IconCanvas.this.isVisible())
                {
                    return false;
                }
                if ((flags & (ImageObserver.FRAMEBITS | ImageObserver.ALLBITS |
                              ImageObserver.WIDTH | ImageObserver.HEIGHT)) != 0)
                {
                    SunToolkit.executeOnEventHandlerThread(IconCanvas.this, new Runnable() {
                            public void run() {
                                repaintImage(false);
                            }
                        });
                }
                return (flags & ImageObserver.ALLBITS) == 0;
            }
        }
    }

    // ***************************************
    // Classes for toolitp and balloon windows
    // ***************************************

    static class Tooltip extends InfoWindow {
        XTrayIconPeer xtiPeer;
        Label textLabel = new Label("");
        Runnable starter = new Runnable() {
                public void run() {
                    display();
                }};

        final static int TOOLTIP_SHOW_TIME = 10000;
        final static int TOOLTIP_START_DELAY_TIME = 1000;
        final static int TOOLTIP_MAX_LENGTH = 64;
        final static int TOOLTIP_MOUSE_CURSOR_INDENT = 5;
        final static Color TOOLTIP_BACKGROUND_COLOR = new Color(255, 255, 220);
        final static Font TOOLTIP_TEXT_FONT = XWindow.defaultFont;

        Tooltip(XTrayIconPeer xtiPeer, Frame parent) {
            super(parent, Color.black);
            this.xtiPeer = xtiPeer;

            suppressWarningString(this);

            setCloser(null, TOOLTIP_SHOW_TIME);
            textLabel.setBackground(TOOLTIP_BACKGROUND_COLOR);
            textLabel.setFont(TOOLTIP_TEXT_FONT);
            add(textLabel);
        }

        /*
         * WARNING: this method is executed on Toolkit thread!
         */
        void display() {
            String tip = xtiPeer.tooltipString;
            if (tip == null) {
                return;
            } else if (tip.length() >  TOOLTIP_MAX_LENGTH) {
                textLabel.setText(tip.substring(0, TOOLTIP_MAX_LENGTH));
            } else {
                textLabel.setText(tip);
            }

            // Execute on EDT to avoid deadlock (see 6280857).
            SunToolkit.executeOnEventHandlerThread(xtiPeer.target, new Runnable() {
                    public void run() {
                        if (xtiPeer.isDisposed()) {
                            return;
                        }
                        Point pointer = (Point)AccessController.doPrivileged(new PrivilegedAction() {
                                public Object run() {
                                    if (!isPointerOverTrayIcon(xtiPeer.getBounds())) {
                                        return null;
                                    }
                                    return MouseInfo.getPointerInfo().getLocation();
                                }
                            });
                        if (pointer == null) {
                            return;
                        }
                        show(new Point(pointer.x, pointer.y), TOOLTIP_MOUSE_CURSOR_INDENT);
                    }
                });
        }

        void enter() {
            XToolkit.schedule(starter, TOOLTIP_START_DELAY_TIME);
        }

        void exit() {
            XToolkit.remove(starter);
            if (isVisible()) {
                hide();
            }
        }

        boolean isPointerOverTrayIcon(Rectangle trayRect) {
            Point p = MouseInfo.getPointerInfo().getLocation();
            return !(p.x < trayRect.x || p.x > (trayRect.x + trayRect.width) ||
                     p.y < trayRect.y || p.y > (trayRect.y + trayRect.height));
        }
    }

    static class Balloon extends InfoWindow {
        final static int BALLOON_SHOW_TIME = 10000;
        final static int BALLOON_TEXT_MAX_LENGTH = 256;
        final static int BALLOON_WORD_LINE_MAX_LENGTH = 16;
        final static int BALLOON_WORD_LINE_MAX_COUNT = 4;
        final static int BALLOON_ICON_WIDTH = 32;
        final static int BALLOON_ICON_HEIGHT = 32;
        final static int BALLOON_TRAY_ICON_INDENT = 0;
        final static Color BALLOON_CAPTION_BACKGROUND_COLOR = new Color(200, 200 ,255);
        final static Font BALLOON_CAPTION_FONT = new Font(Font.DIALOG, Font.BOLD, 12);

        XTrayIconPeer xtiPeer;
        Panel mainPanel = new Panel();
        Panel captionPanel = new Panel();
        Label captionLabel = new Label("");
        Button closeButton = new Button("X");
        Panel textPanel = new Panel();
        IconCanvas iconCanvas = new IconCanvas(BALLOON_ICON_WIDTH, BALLOON_ICON_HEIGHT);
        Label[] lineLabels = new Label[BALLOON_WORD_LINE_MAX_COUNT];
        ActionPerformer ap = new ActionPerformer();

        Image iconImage;
        Image errorImage;
        Image warnImage;
        Image infoImage;
        boolean gtkImagesLoaded;

        Displayer displayer = new Displayer();

        Balloon(final XTrayIconPeer xtiPeer, Frame parent) {
            super(parent, new Color(90, 80 ,190));
            this.xtiPeer = xtiPeer;

            suppressWarningString(this);

            setCloser(new Runnable() {
                    public void run() {
                        if (textPanel != null) {
                            textPanel.removeAll();
                            textPanel.setSize(0, 0);
                            iconCanvas.setSize(0, 0);
                            XToolkit.awtLock();
                            try {
                                displayer.isDisplayed = false;
                                XToolkit.awtLockNotifyAll();
                            } finally {
                                XToolkit.awtUnlock();
                            }
                        }
                    }
                }, BALLOON_SHOW_TIME);

            add(mainPanel);

            captionLabel.setFont(BALLOON_CAPTION_FONT);
            captionLabel.addMouseListener(ap);

            captionPanel.setLayout(new BorderLayout());
            captionPanel.add(captionLabel, BorderLayout.WEST);
            captionPanel.add(closeButton, BorderLayout.EAST);
            captionPanel.setBackground(BALLOON_CAPTION_BACKGROUND_COLOR);
            captionPanel.addMouseListener(ap);

            closeButton.addActionListener(new ActionListener() {
                    public void actionPerformed(ActionEvent e) {
                        hide();
                    }
                });

            mainPanel.setLayout(new BorderLayout());
            mainPanel.setBackground(Color.white);
            mainPanel.add(captionPanel, BorderLayout.NORTH);
            mainPanel.add(iconCanvas, BorderLayout.WEST);
            mainPanel.add(textPanel, BorderLayout.CENTER);

            iconCanvas.addMouseListener(ap);

            for (int i = 0; i < BALLOON_WORD_LINE_MAX_COUNT; i++) {
                lineLabels[i] = new Label();
                lineLabels[i].addMouseListener(ap);
                lineLabels[i].setBackground(Color.white);
            }

            displayer.start();
        }

        void display(String caption, String text, String messageType) {
            if (!gtkImagesLoaded) {
                loadGtkImages();
            }
            displayer.display(caption, text, messageType);
        }

        private void _display(String caption, String text, String messageType) {
            captionLabel.setText(caption);

            BreakIterator iter = BreakIterator.getWordInstance();
            if (text != null) {
                iter.setText(text);
                int start = iter.first(), end;
                int nLines = 0;

                do {
                    end = iter.next();

                    if (end == BreakIterator.DONE ||
                        text.substring(start, end).length() >= 50)
                    {
                        lineLabels[nLines].setText(text.substring(start, end == BreakIterator.DONE ?
                                                                  iter.last() : end));
                        textPanel.add(lineLabels[nLines++]);
                        start = end;
                    }
                    if (nLines == BALLOON_WORD_LINE_MAX_COUNT) {
                        if (end != BreakIterator.DONE) {
                            lineLabels[nLines - 1].setText(
                                new String(lineLabels[nLines - 1].getText() + " ..."));
                        }
                        break;
                    }
                } while (end != BreakIterator.DONE);


                textPanel.setLayout(new GridLayout(nLines, 1));
            }

            if ("ERROR".equals(messageType)) {
                iconImage = errorImage;
            } else if ("WARNING".equals(messageType)) {
                iconImage = warnImage;
            } else if ("INFO".equals(messageType)) {
                iconImage = infoImage;
            } else {
                iconImage = null;
            }

            if (iconImage != null) {
                Dimension tpSize = textPanel.getSize();
                iconCanvas.setSize(BALLOON_ICON_WIDTH, (BALLOON_ICON_HEIGHT > tpSize.height ?
                                                        BALLOON_ICON_HEIGHT : tpSize.height));
            }

            SunToolkit.executeOnEventHandlerThread(xtiPeer.target, new Runnable() {
                    public void run() {
                        if (xtiPeer.isDisposed()) {
                            return;
                        }
                        Point parLoc = getParent().getLocationOnScreen();
                        Dimension parSize = getParent().getSize();
                        show(new Point(parLoc.x + parSize.width/2, parLoc.y + parSize.height/2),
                             BALLOON_TRAY_ICON_INDENT);
                        if (iconImage != null) {
                            iconCanvas.updateImage(iconImage); // call it after the show(..) above
                        }
                    }
                });
        }

        public void dispose() {
            displayer.interrupt();
            super.dispose();
        }

        void loadGtkImages() {
            if (!gtkImagesLoaded) {
                errorImage = (Image)Toolkit.getDefaultToolkit().getDesktopProperty(
                    "gtk.icon.gtk-dialog-error.6.rtl");
                warnImage = (Image)Toolkit.getDefaultToolkit().getDesktopProperty(
                    "gtk.icon.gtk-dialog-warning.6.rtl");
                infoImage = (Image)Toolkit.getDefaultToolkit().getDesktopProperty(
                    "gtk.icon.gtk-dialog-info.6.rtl");
                gtkImagesLoaded = true;
            }
        }

        class ActionPerformer extends MouseAdapter {
            public void mouseClicked(MouseEvent e) {
                // hide the balloon by any click
                hide();
                if (e.getButton() == MouseEvent.BUTTON1) {
                    ActionEvent aev = new ActionEvent(xtiPeer.target, ActionEvent.ACTION_PERFORMED,
                                                      xtiPeer.target.getActionCommand(),
                                                      e.getWhen(), e.getModifiers());
                    Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent(aev);
                }
            }
        }

        class Displayer extends Thread {
            final int MAX_CONCURRENT_MSGS = 10;

            ArrayBlockingQueue<Message> messageQueue = new ArrayBlockingQueue<Message>(MAX_CONCURRENT_MSGS);
            boolean isDisplayed;

            Displayer() {
                setDaemon(true);
            }

            public void run() {
                while (true) {
                    Message msg = null;
                    try {
                        msg = (Message)messageQueue.take();
                    } catch (InterruptedException e) {
                        return;
                    }

                    /*
                     * Wait till the previous message is displayed if any
                     */
                    XToolkit.awtLock();
                    try {
                        while (isDisplayed) {
                            try {
                                XToolkit.awtLockWait();
                            } catch (InterruptedException e) {
                                return;
                            }
                        }
                        isDisplayed = true;
                    } finally {
                        XToolkit.awtUnlock();
                    }
                    _display(msg.caption, msg.text, msg.messageType);
                }
            }

            void display(String caption, String text, String messageType) {
                messageQueue.offer(new Message(caption, text, messageType));
            }
        }

        class Message {
            String caption, text, messageType;

            Message(String caption, String text, String messageType) {
                this.caption = caption;
                this.text = text;
                this.messageType = messageType;
            }
        }
    }

    static class InfoWindow extends Window {
        Container container;
        Closer closer;

        InfoWindow(Frame parent, Color borderColor) {
            super(parent);
            container = new Container() {
                    public Insets getInsets() {
                        return new Insets(1, 1, 1, 1);
                    }
                };
            setLayout(new BorderLayout());
            setBackground(borderColor);
            add(container, BorderLayout.CENTER);
            container.setLayout(new BorderLayout());

            closer = new Closer();
        }

        public Component add(Component c) {
            container.add(c, BorderLayout.CENTER);
            return c;
        }

        void setCloser(Runnable action, int time) {
            closer.set(action, time);
        }

        // Must be executed on EDT.
        protected void show(Point corner, int indent) {
            assert SunToolkit.isDispatchThreadForAppContext(InfoWindow.this);

            pack();

            Dimension size = getSize();
            // TODO: When 6356322 is fixed we should get screen bounds in
            // this way: eframe.getGraphicsConfiguration().getBounds().
            Dimension scrSize = Toolkit.getDefaultToolkit().getScreenSize();

            if (corner.x < scrSize.width/2 && corner.y < scrSize.height/2) { // 1st square
                setLocation(corner.x + indent, corner.y + indent);

            } else if (corner.x >= scrSize.width/2 && corner.y < scrSize.height/2) { // 2nd square
                setLocation(corner.x - indent - size.width, corner.y + indent);

            } else if (corner.x < scrSize.width/2 && corner.y >= scrSize.height/2) { // 3rd square
                setLocation(corner.x + indent, corner.y - indent - size.height);

            } else if (corner.x >= scrSize.width/2 && corner.y >= scrSize.height/2) { // 4th square
                setLocation(corner.x - indent - size.width, corner.y - indent - size.height);
            }

            InfoWindow.super.show();
            InfoWindow.this.closer.schedule();
        }

        public void hide() {
            closer.close();
        }

        class Closer implements Runnable {
            Runnable action;
            int time;

            public void run() {
                doClose();
            }

            void set(Runnable action, int time) {
                this.action = action;
                this.time = time;
            }

            void schedule() {
                XToolkit.schedule(this, time);
            }

            void close() {
                XToolkit.remove(this);
                doClose();
            }

            // WARNING: this method may be executed on Toolkit thread.
            private void doClose() {
                SunToolkit.executeOnEventHandlerThread(InfoWindow.this, new Runnable() {
                        public void run() {
                            InfoWindow.super.hide();
                            invalidate();
                            if (action != null) {
                                action.run();
                            }
                        }
                    });
            }
        }
    }
}
