blob: ee44dbf09c9279b5d4d4691df6369eef54ae173c [file] [log] [blame]
/*
* Copyright (c) 2013, 2016, 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.java2d.SunGraphics2D;
import sun.java2d.SurfaceData;
import sun.java2d.opengl.CGLLayer;
import sun.lwawt.LWWindowPeer;
import sun.lwawt.PlatformEventNotifier;
import sun.lwawt.SecurityWarningWindow;
import java.awt.*;
import java.awt.event.MouseEvent;
import java.awt.geom.Point2D;
import java.lang.ref.WeakReference;
public final class CWarningWindow extends CPlatformWindow
implements SecurityWarningWindow, PlatformEventNotifier {
private static class Lock {}
private final Lock lock = new Lock();
private static final int SHOWING_DELAY = 300;
private static final 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<>(_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 (taskLock) {
cancelTasks();
if (visible) {
if (isVisible()) {
currentIcon = 0;
} else {
currentIcon = 2;
}
showHideTask = new ShowingTask();
LWCToolkit.performOnMainThreadAfterDelay(showHideTask, 50);
} else {
if (!isVisible()) {
return;
}
showHideTask = new HidingTask();
if (doSchedule) {
LWCToolkit.performOnMainThreadAfterDelay(showHideTask, HIDING_DELAY);
} else {
LWCToolkit.performOnMainThreadAfterDelay(showHideTask, 50);
}
}
}
}
@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(int id, long when, int button, int x, int y,
int absX, int absY, 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 absX,
int absY, 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;
}
};
}
};
}
@Override
public void dispose() {
cancelTasks();
SurfaceData surfaceData = contentView.getSurfaceData();
if (surfaceData != null) {
surfaceData.invalidate();
}
super.dispose();
}
private void cancelTasks() {
synchronized (taskLock) {
if (showHideTask != null) {
showHideTask.cancel();
showHideTask = null;
}
}
}
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 Graphics getGraphics() {
SurfaceData sd = contentView.getSurfaceData();
if (ownerWindow == null || sd == null) {
return null;
}
return 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 Lock taskLock = new Lock();
private CancelableRunnable showHideTask;
private abstract static class CancelableRunnable implements Runnable {
private volatile boolean perform = true;
public final void cancel() {
perform = false;
}
@Override
public final void run() {
if (perform) {
perform();
}
}
public abstract void perform();
}
private class HidingTask extends CancelableRunnable {
@Override
public void perform() {
synchronized (lock) {
setVisible(false);
}
synchronized (taskLock) {
showHideTask = null;
}
}
}
private class ShowingTask extends CancelableRunnable {
@Override
public void perform() {
synchronized (lock) {
if (!isVisible()) {
setVisible(true);
}
repaint();
}
synchronized (taskLock) {
if (currentIcon > 0) {
currentIcon--;
showHideTask = new ShowingTask();
LWCToolkit.performOnMainThreadAfterDelay(showHideTask, SHOWING_DELAY);
} else {
showHideTask = null;
}
}
}
}
}