--- old/src/java.desktop/macosx/classes/sun/lwawt/macosx/CTrayIcon.java 2017-09-27 07:55:54.000000000 -0700 +++ new/src/java.desktop/macosx/classes/sun/lwawt/macosx/CTrayIcon.java 2017-09-27 07:55:53.000000000 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2017, 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 @@ -25,26 +25,37 @@ package sun.lwawt.macosx; -import sun.awt.AWTAccessor; -import sun.awt.SunToolkit; - -import javax.swing.*; -import java.awt.*; -import java.awt.event.*; +import java.awt.AWTEvent; +import java.awt.Button; +import java.awt.Frame; +import java.awt.Graphics2D; +import java.awt.GraphicsConfiguration; +import java.awt.GraphicsDevice; +import java.awt.GraphicsEnvironment; +import java.awt.Image; +import java.awt.MediaTracker; +import java.awt.PopupMenu; +import java.awt.RenderingHints; +import java.awt.Toolkit; +import java.awt.Transparency; +import java.awt.TrayIcon; +import java.awt.event.ActionEvent; +import java.awt.event.MouseEvent; import java.awt.geom.Point2D; import java.awt.image.BufferedImage; import java.awt.peer.TrayIconPeer; -import java.beans.PropertyChangeEvent; -import java.beans.PropertyChangeListener; -import java.util.concurrent.atomic.AtomicReference; -import static sun.awt.AWTAccessor.*; +import javax.swing.Icon; +import javax.swing.UIManager; + +import sun.awt.SunToolkit; + +import static sun.awt.AWTAccessor.MenuComponentAccessor; +import static sun.awt.AWTAccessor.getMenuComponentAccessor; public class CTrayIcon extends CFRetainedResource implements TrayIconPeer { private TrayIcon target; private PopupMenu popup; - private JDialog messageDialog; - private DialogEventHandler handler; // In order to construct MouseEvent object, we need to specify a // Component target. Because TrayIcon isn't Component's subclass, @@ -59,8 +70,6 @@ CTrayIcon(TrayIcon target) { super(0, true); - this.messageDialog = null; - this.handler = null; this.target = target; this.popup = target.getPopupMenu(); this.dummyFrame = new Frame(); @@ -129,28 +138,25 @@ */ public void displayMessage(final String caption, final String text, final String messageType) { - - if (SwingUtilities.isEventDispatchThread()) { - displayMessageOnEDT(caption, text, messageType); + // obtain icon to show along the message + Icon icon = getIconForMessageType(messageType); + CImage cimage = null; + if (icon != null) { + BufferedImage image = scaleIcon(icon, 0.75); + cimage = CImage.getCreator().createFromImage(image); + } + if (cimage != null) { + cimage.execute(imagePtr -> { + execute(ptr -> nativeShowNotification(ptr, caption, text, + imagePtr)); + }); } else { - try { - SwingUtilities.invokeAndWait(new Runnable() { - public void run() { - displayMessageOnEDT(caption, text, messageType); - } - }); - } catch (Exception e) { - throw new AssertionError(e); - } + execute(ptr -> nativeShowNotification(ptr, caption, text, 0)); } } @Override public void dispose() { - if (messageDialog != null) { - disposeMessageDialog(); - } - dummyFrame.dispose(); if (popup != null) { @@ -276,154 +282,14 @@ } } - private native Point2D nativeGetIconLocation(long trayIconModel); - - public void displayMessageOnEDT(String caption, String text, - String messageType) { - if (messageDialog != null) { - disposeMessageDialog(); - } - - // obtain icon to show along the message - Icon icon = getIconForMessageType(messageType); - if (icon != null) { - icon = new ImageIcon(scaleIcon(icon, 0.75)); - } - - // We want the message dialog text area to be about 1/8 of the screen - // size. There is nothing special about this value, it's just makes the - // message dialog to look nice - Dimension screenSize = java.awt.Toolkit.getDefaultToolkit().getScreenSize(); - int textWidth = screenSize.width / 8; - - // create dialog to show - messageDialog = createMessageDialog(caption, text, textWidth, icon); - - // finally, show the dialog to user - showMessageDialog(); - } + private native void nativeShowNotification(long trayIconModel, + String caption, String text, + long nsimage); /** - * Creates dialog window used to display the message + * Used by the automated tests. */ - private JDialog createMessageDialog(String caption, String text, - int textWidth, Icon icon) { - JDialog dialog; - handler = new DialogEventHandler(); - - JTextArea captionArea = null; - if (caption != null) { - captionArea = createTextArea(caption, textWidth, false, true); - } - - JTextArea textArea = null; - if (text != null){ - textArea = createTextArea(text, textWidth, true, false); - } - - Object[] panels = null; - if (captionArea != null) { - if (textArea != null) { - panels = new Object[] {captionArea, new JLabel(), textArea}; - } else { - panels = new Object[] {captionArea}; - } - } else { - if (textArea != null) { - panels = new Object[] {textArea}; - } - } - - // We want message dialog with small title bar. There is a client - // property property that does it, however, it must be set before - // dialog's native window is created. This is why we create option - // pane and dialog separately - final JOptionPane op = new JOptionPane(panels); - op.setIcon(icon); - op.addPropertyChangeListener(handler); - - // Make Ok button small. Most likely won't work for L&F other then Aqua - try { - JPanel buttonPanel = (JPanel)op.getComponent(1); - JButton ok = (JButton)buttonPanel.getComponent(0); - ok.putClientProperty("JComponent.sizeVariant", "small"); - } catch (Throwable t) { - // do nothing, we tried and failed, no big deal - } - - dialog = new JDialog((Dialog) null); - JRootPane rp = dialog.getRootPane(); - - // gives us dialog window with small title bar and not zoomable - rp.putClientProperty(CPlatformWindow.WINDOW_STYLE, "small"); - rp.putClientProperty(CPlatformWindow.WINDOW_ZOOMABLE, "false"); - - dialog.setDefaultCloseOperation(JDialog.DO_NOTHING_ON_CLOSE); - dialog.setModal(false); - dialog.setModalExclusionType(Dialog.ModalExclusionType.TOOLKIT_EXCLUDE); - dialog.setAlwaysOnTop(true); - dialog.setAutoRequestFocus(false); - dialog.setResizable(false); - dialog.setContentPane(op); - - dialog.addWindowListener(handler); - - // suppress security warning for untrusted windows - AWTAccessor.getWindowAccessor().setTrayIconWindow(dialog, true); - - dialog.pack(); - - return dialog; - } - - private void showMessageDialog() { - - Dimension screenSize = java.awt.Toolkit.getDefaultToolkit().getScreenSize(); - AtomicReference ref = new AtomicReference<>(); - execute(ptr -> { - ref.set(nativeGetIconLocation(ptr)); - }); - Point2D iconLoc = ref.get(); - if (iconLoc == null) { - return; - } - - int dialogY = (int)iconLoc.getY(); - int dialogX = (int)iconLoc.getX(); - if (dialogX + messageDialog.getWidth() > screenSize.width) { - dialogX = screenSize.width - messageDialog.getWidth(); - } - - messageDialog.setLocation(dialogX, dialogY); - messageDialog.setVisible(true); - } - - private void disposeMessageDialog() { - if (SwingUtilities.isEventDispatchThread()) { - disposeMessageDialogOnEDT(); - } else { - try { - SwingUtilities.invokeAndWait(new Runnable() { - public void run() { - disposeMessageDialogOnEDT(); - } - }); - } catch (Exception e) { - throw new AssertionError(e); - } - } - } - - private void disposeMessageDialogOnEDT() { - if (messageDialog != null) { - messageDialog.removeWindowListener(handler); - messageDialog.removePropertyChangeListener(handler); - messageDialog.dispose(); - - messageDialog = null; - handler = null; - } - } + private native Point2D nativeGetIconLocation(long trayIconModel); /** * Scales an icon using specified scale factor @@ -480,56 +346,5 @@ return UIManager.getIcon("OptionPane.informationIcon"); } } - - private static JTextArea createTextArea(String text, int width, - boolean isSmall, boolean isBold) { - JTextArea textArea = new JTextArea(text); - - textArea.setLineWrap(true); - textArea.setWrapStyleWord(true); - textArea.setEditable(false); - textArea.setFocusable(false); - textArea.setBorder(null); - textArea.setBackground(new JLabel().getBackground()); - - if (isSmall) { - textArea.putClientProperty("JComponent.sizeVariant", "small"); - } - - if (isBold) { - Font font = textArea.getFont(); - Font boldFont = new Font(font.getName(), Font.BOLD, font.getSize()); - textArea.setFont(boldFont); - } - - textArea.setSize(width, 1); - - return textArea; - } - - /** - * Implements all the Listeners needed by message dialog - */ - private final class DialogEventHandler extends WindowAdapter - implements PropertyChangeListener { - - public void windowClosing(WindowEvent we) { - disposeMessageDialog(); - } - - public void propertyChange(PropertyChangeEvent e) { - if (messageDialog == null) { - return; - } - - String prop = e.getPropertyName(); - Container cp = messageDialog.getContentPane(); - - if (messageDialog.isVisible() && e.getSource() == cp && - (prop.equals(JOptionPane.VALUE_PROPERTY))) { - disposeMessageDialog(); - } - } - } }