blob: d488a4526b915924e04ffff115b63906753c9312 [file] [log] [blame]
/*
* Copyright (c) 2013, 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.lwawt.macosx;
import sun.awt.AWTAccessor;
import sun.awt.IconInfo;
import sun.awt.SunToolkit;
import sun.java2d.SunGraphics2D;
import sun.java2d.SurfaceData;
import sun.java2d.opengl.CGLLayer;
import sun.lwawt.LWWindowPeer;
import sun.lwawt.PlatformEventNotifier;
import sun.lwawt.PlatformWindow;
import sun.lwawt.SecurityWarningWindow;
import java.awt.*;
import java.awt.event.MouseEvent;
import java.awt.geom.Point2D;
import java.lang.ref.WeakReference;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
public final class CWarningWindow extends CPlatformWindow
implements SecurityWarningWindow, PlatformEventNotifier {
private static class Lock {};
private final Lock lock = new Lock();
private final static int SHOWING_DELAY = 300;
private final static int HIDING_DELAY = 2000;
private Rectangle bounds = new Rectangle();
private final WeakReference<LWWindowPeer> ownerPeer;
private final Window ownerWindow;
/**
* Animation stage.
*/
private volatile int currentIcon = 0;
/* -1 - uninitialized.
* 0 - 16x16
* 1 - 24x24
* 2 - 32x32
* 3 - 48x48
*/
private int currentSize = -1;
private static IconInfo[][] icons;
private static IconInfo getSecurityIconInfo(int size, int num) {
synchronized (CWarningWindow.class) {
if (icons == null) {
icons = new IconInfo[4][3];
icons[0][0] = new IconInfo(sun.awt.AWTIcon32_security_icon_bw16_png.security_icon_bw16_png);
icons[0][1] = new IconInfo(sun.awt.AWTIcon32_security_icon_interim16_png.security_icon_interim16_png);
icons[0][2] = new IconInfo(sun.awt.AWTIcon32_security_icon_yellow16_png.security_icon_yellow16_png);
icons[1][0] = new IconInfo(sun.awt.AWTIcon32_security_icon_bw24_png.security_icon_bw24_png);
icons[1][1] = new IconInfo(sun.awt.AWTIcon32_security_icon_interim24_png.security_icon_interim24_png);
icons[1][2] = new IconInfo(sun.awt.AWTIcon32_security_icon_yellow24_png.security_icon_yellow24_png);
icons[2][0] = new IconInfo(sun.awt.AWTIcon32_security_icon_bw32_png.security_icon_bw32_png);
icons[2][1] = new IconInfo(sun.awt.AWTIcon32_security_icon_interim32_png.security_icon_interim32_png);
icons[2][2] = new IconInfo(sun.awt.AWTIcon32_security_icon_yellow32_png.security_icon_yellow32_png);
icons[3][0] = new IconInfo(sun.awt.AWTIcon32_security_icon_bw48_png.security_icon_bw48_png);
icons[3][1] = new IconInfo(sun.awt.AWTIcon32_security_icon_interim48_png.security_icon_interim48_png);
icons[3][2] = new IconInfo(sun.awt.AWTIcon32_security_icon_yellow48_png.security_icon_yellow48_png);
}
}
final int sizeIndex = size % icons.length;
return icons[sizeIndex][num % icons[sizeIndex].length];
}
public CWarningWindow(final Window _ownerWindow, final LWWindowPeer _ownerPeer) {
super();
this.ownerPeer = new WeakReference<LWWindowPeer>(_ownerPeer);
this.ownerWindow = _ownerWindow;
initialize(null, null, _ownerPeer.getPlatformWindow());
setOpaque(false);
String warningString = ownerWindow.getWarningString();
if (warningString != null) {
contentView.setToolTip(ownerWindow.getWarningString());
}
updateIconSize();
}
/**
* @param x,y,w,h coordinates of the untrusted window
*/
public void reposition(int x, int y, int w, int h) {
final Point2D point = AWTAccessor.getWindowAccessor().
calculateSecurityWarningPosition(ownerWindow, x, y, w, h);
setBounds((int)point.getX(), (int)point.getY(), getWidth(), getHeight());
}
public void setVisible(boolean visible, boolean doSchedule) {
synchronized (scheduler) {
if (showingTaskHandle != null) {
showingTaskHandle.cancel(false);
showingTaskHandle = null;
}
if (hidingTaskHandle != null) {
hidingTaskHandle.cancel(false);
hidingTaskHandle = null;
}
if (visible) {
if (isVisible()) {
currentIcon = 0;
} else {
currentIcon = 2;
}
showingTaskHandle = scheduler.schedule(showingTask, 50,
TimeUnit.MILLISECONDS);
} else {
if (!isVisible()) {
return;
}
if (doSchedule) {
hidingTaskHandle = scheduler.schedule(hidingTask, HIDING_DELAY,
TimeUnit.MILLISECONDS);
} else {
hidingTaskHandle = scheduler.schedule(hidingTask, 50,
TimeUnit.MILLISECONDS);
}
}
}
}
@Override
public void notifyIconify(boolean iconify) {
}
@Override
public void notifyZoom(boolean isZoomed) {
}
@Override
public void notifyExpose(final Rectangle r) {
repaint();
}
@Override
public void notifyReshape(int x, int y, int w, int h) {
}
@Override
public void notifyUpdateCursor() {
}
@Override
public void notifyActivation(boolean activation, LWWindowPeer opposite) {
}
@Override
public void notifyNCMouseDown() {
}
@Override
public void notifyMouseEvent(PlatformWindow platformWindow, int id, long when, int button, int x, int y,
int screenX, int screenY, int modifiers,
int clickCount, boolean popupTrigger,
byte[] bdata) {
LWWindowPeer peer = ownerPeer.get();
if (id == MouseEvent.MOUSE_EXITED) {
if (peer != null) {
peer.updateSecurityWarningVisibility();
}
} else if(id == MouseEvent.MOUSE_ENTERED) {
if (peer != null) {
peer.updateSecurityWarningVisibility();
}
}
}
public Rectangle getBounds() {
synchronized (lock) {
return bounds.getBounds();
}
}
@Override
public boolean isVisible() {
synchronized (lock) {
return visible;
}
}
@Override
public void setVisible(boolean visible) {
synchronized (lock) {
final long nsWindowPtr = getNSWindowPtr();
// Actually show or hide the window
if (visible) {
CWrapper.NSWindow.orderFront(nsWindowPtr);
} else {
CWrapper.NSWindow.orderOut(nsWindowPtr);
}
this.visible = visible;
// Manage parent-child relationship when showing
if (visible) {
// Order myself above my parent
if (owner != null && owner.isVisible()) {
CWrapper.NSWindow.orderWindow(nsWindowPtr,
CWrapper.NSWindow.NSWindowAbove, owner.getNSWindowPtr());
// do not allow security warning to be obscured by other windows
applyWindowLevel(ownerWindow);
}
}
}
}
@Override
public void notifyMouseWheelEvent(long when, int x, int y, int modifiers,
int scrollType, int scrollAmount,
int wheelRotation, double preciseWheelRotation,
byte[] bdata) {
}
@Override
public void notifyKeyEvent(int id, long when, int modifiers, int keyCode,
char keyChar, int keyLocation) {
}
protected int getInitialStyleBits() {
int styleBits = 0;
CPlatformWindow.SET(styleBits, CPlatformWindow.UTILITY, true);
return styleBits;
}
protected void deliverMoveResizeEvent(int x, int y, int width, int height,
boolean byUser) {
boolean isResize;
synchronized (lock) {
isResize = (bounds.width != width || bounds.height != height);
bounds = new Rectangle(x, y, width, height);
}
if (isResize) {
replaceSurface();
}
super.deliverMoveResizeEvent(x, y, width, height, byUser);
}
protected CPlatformResponder createPlatformResponder() {
return new CPlatformResponder(this, false);
}
protected CPlatformView createContentView() {
return new CPlatformView() {
public GraphicsConfiguration getGraphicsConfiguration() {
LWWindowPeer peer = ownerPeer.get();
return peer.getGraphicsConfiguration();
}
public Rectangle getBounds() {
return CWarningWindow.this.getBounds();
}
public CGLLayer createCGLayer() {
return new CGLLayer(null) {
public Rectangle getBounds() {
return CWarningWindow.this.getBounds();
}
public GraphicsConfiguration getGraphicsConfiguration() {
LWWindowPeer peer = ownerPeer.get();
return peer.getGraphicsConfiguration();
}
public boolean isOpaque() {
return false;
}
};
}
};
}
private void updateIconSize() {
int newSize = -1;
if (ownerWindow != null) {
Insets insets = ownerWindow.getInsets();
int max = Math.max(insets.top, Math.max(insets.bottom,
Math.max(insets.left, insets.right)));
if (max < 24) {
newSize = 0;
} else if (max < 32) {
newSize = 1;
} else if (max < 48) {
newSize = 2;
} else {
newSize = 3;
}
}
// Make sure we have a valid size
if (newSize == -1) {
newSize = 0;
}
synchronized (lock) {
if (newSize != currentSize) {
currentSize = newSize;
IconInfo ico = getSecurityIconInfo(currentSize, 0);
AWTAccessor.getWindowAccessor().setSecurityWarningSize(
ownerWindow, ico.getWidth(), ico.getHeight());
}
}
}
private final Graphics getGraphics() {
SurfaceData sd = contentView.getSurfaceData();
if (ownerWindow == null || sd == null) {
return null;
}
return transformGraphics(new SunGraphics2D(sd, SystemColor.windowText,
SystemColor.window, ownerWindow.getFont()));
}
private void repaint() {
final Graphics g = getGraphics();
if (g != null) {
try {
((Graphics2D) g).setComposite(AlphaComposite.Src);
g.drawImage(getSecurityIconInfo().getImage(), 0, 0, null);
} finally {
g.dispose();
}
}
}
private void replaceSurface() {
SurfaceData oldData = contentView.getSurfaceData();
replaceSurfaceData();
if (oldData != null && oldData != contentView.getSurfaceData()) {
oldData.flush();
}
}
private int getWidth() {
return getSecurityIconInfo().getWidth();
}
private int getHeight() {
return getSecurityIconInfo().getHeight();
}
private IconInfo getSecurityIconInfo() {
return getSecurityIconInfo(currentSize, currentIcon);
}
private final Runnable hidingTask = new Runnable() {
public void run() {
synchronized (lock) {
setVisible(false);
}
synchronized (scheduler) {
hidingTaskHandle = null;
}
}
};
private final Runnable showingTask = new Runnable() {
public void run() {
synchronized (lock) {
if (!isVisible()) {
setVisible(true);
}
repaint();
}
synchronized (scheduler) {
if (currentIcon > 0) {
currentIcon--;
showingTaskHandle = scheduler.schedule(showingTask, SHOWING_DELAY,
TimeUnit.MILLISECONDS);
} else {
showingTaskHandle = null;
}
}
}
};
private final ScheduledExecutorService scheduler =
Executors.newSingleThreadScheduledExecutor();
private ScheduledFuture hidingTaskHandle;
private ScheduledFuture showingTaskHandle;
}