--- a/jdk/src/solaris/classes/sun/awt/X11/XWarningWindow.java Wed Mar 25 13:37:08 2009 +0300
+++ b/jdk/src/solaris/classes/sun/awt/X11/XWarningWindow.java Thu Mar 26 14:38:46 2009 +0300
@@ -25,16 +25,194 @@
package sun.awt.X11;
import java.awt.*;
+import java.awt.event.*;
+import java.awt.geom.Point2D;
+import java.lang.ref.WeakReference;
+import sun.java2d.SunGraphics2D;
+import sun.java2d.pipe.Region;
+import sun.awt.AWTAccessor;
+import sun.awt.SunToolkit;
class XWarningWindow extends XWindow {
- final static int defaultHeight = 27;
+ private final static int showingDelay = 330;
+ private final static int hidingDelay = 2000;
+
+ private final Window ownerWindow;
+ private WeakReference<XWindowPeer> ownerPeer;
+
+ public final Window getOwnerWindow() {
+ return ownerWindow;
+ }
+ private long parentWindow;
+
+ private final static String OWNER = "OWNER";
+
+ private static XIconInfo[][] icons;
+
+ private InfoWindow.Tooltip tooltip;
+
+ private static synchronized XIconInfo getSecurityIconInfo(int size, int num) {
+ if (icons == null) {
+ icons = new XIconInfo[4][3];
+ if (XlibWrapper.dataModel == 32) {
+ icons[0][0] = new XIconInfo(XAWTIcon32_security_icon_bw16_png.security_icon_bw16_png);
+ icons[0][1] = new XIconInfo(XAWTIcon32_security_icon_interim16_png.security_icon_interim16_png);
+ icons[0][2] = new XIconInfo(XAWTIcon32_security_icon_yellow16_png.security_icon_yellow16_png);
+ icons[1][0] = new XIconInfo(XAWTIcon32_security_icon_bw24_png.security_icon_bw24_png);
+ icons[1][1] = new XIconInfo(XAWTIcon32_security_icon_interim24_png.security_icon_interim24_png);
+ icons[1][2] = new XIconInfo(XAWTIcon32_security_icon_yellow24_png.security_icon_yellow24_png);
+ icons[2][0] = new XIconInfo(XAWTIcon32_security_icon_bw32_png.security_icon_bw32_png);
+ icons[2][1] = new XIconInfo(XAWTIcon32_security_icon_interim32_png.security_icon_interim32_png);
+ icons[2][2] = new XIconInfo(XAWTIcon32_security_icon_yellow32_png.security_icon_yellow32_png);
+ icons[3][0] = new XIconInfo(XAWTIcon32_security_icon_bw48_png.security_icon_bw48_png);
+ icons[3][1] = new XIconInfo(XAWTIcon32_security_icon_interim48_png.security_icon_interim48_png);
+ icons[3][2] = new XIconInfo(XAWTIcon32_security_icon_yellow48_png.security_icon_yellow48_png);
+ } else {
+ icons[0][0] = new XIconInfo(XAWTIcon64_security_icon_bw16_png.security_icon_bw16_png);
+ icons[0][1] = new XIconInfo(XAWTIcon64_security_icon_interim16_png.security_icon_interim16_png);
+ icons[0][2] = new XIconInfo(XAWTIcon64_security_icon_yellow16_png.security_icon_yellow16_png);
+ icons[1][0] = new XIconInfo(XAWTIcon64_security_icon_bw24_png.security_icon_bw24_png);
+ icons[1][1] = new XIconInfo(XAWTIcon64_security_icon_interim24_png.security_icon_interim24_png);
+ icons[1][2] = new XIconInfo(XAWTIcon64_security_icon_yellow24_png.security_icon_yellow24_png);
+ icons[2][0] = new XIconInfo(XAWTIcon64_security_icon_bw32_png.security_icon_bw32_png);
+ icons[2][1] = new XIconInfo(XAWTIcon64_security_icon_interim32_png.security_icon_interim32_png);
+ icons[2][2] = new XIconInfo(XAWTIcon64_security_icon_yellow32_png.security_icon_yellow32_png);
+ icons[3][0] = new XIconInfo(XAWTIcon64_security_icon_bw48_png.security_icon_bw48_png);
+ icons[3][1] = new XIconInfo(XAWTIcon64_security_icon_interim48_png.security_icon_interim48_png);
+ icons[3][2] = new XIconInfo(XAWTIcon64_security_icon_yellow48_png.security_icon_yellow48_png);
+ }
+ }
+ final int sizeIndex = size % icons.length;
+ return icons[sizeIndex][num % icons[sizeIndex].length];
+ }
+
+ private volatile int currentIcon = 0;
+
+ /* -1 - uninitialized yet
+ * 0 - 16x16
+ * 1 - 24x24
+ * 2 - 32x32
+ * 3 - 48x48
+ */
+ private volatile int currentSize = -1;
+
+ /** Indicates whether the shape of the window must be updated
+ */
+ private volatile boolean sizeUpdated = true;
+
+ private synchronized boolean updateIconSize() {
+ int newSize = currentSize;
+
+ 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;
+ }
+ }
+ if (newSize != currentSize) {
+ currentSize = newSize;
+ sizeUpdated = true;
+ }
+ return sizeUpdated;
+ }
- Window ownerWindow;
- XWarningWindow(Window ownerWindow, long parentWindow) {
- super(ownerWindow, parentWindow);
+ private synchronized XIconInfo getSecurityIconInfo() {
+ updateIconSize();
+ return getSecurityIconInfo(currentSize, currentIcon);
+ }
+
+ XWarningWindow(final Window ownerWindow, long parentWindow, XWindowPeer ownerPeer) {
+ super(new XCreateWindowParams(new Object[] {
+ TARGET, ownerWindow,
+ OWNER, Long.valueOf(parentWindow)
+ }));
this.ownerWindow = ownerWindow;
- xSetVisible(true);
- toFront();
+ this.parentWindow = parentWindow;
+ this.tooltip = new InfoWindow.Tooltip(null, getTarget(),
+ new InfoWindow.Tooltip.LiveArguments() {
+ public boolean isDisposed() {
+ return XWarningWindow.this.isDisposed();
+ }
+ public Rectangle getBounds() {
+ return XWarningWindow.this.getBounds();
+ }
+ public String getTooltipString() {
+ return XWarningWindow.this.ownerWindow.getWarningString();
+ }
+ });
+ this.ownerPeer = new WeakReference<XWindowPeer>(ownerPeer);
+ }
+
+ private void requestNoTaskbar() {
+ XNETProtocol netProtocol = XWM.getWM().getNETProtocol();
+ if (netProtocol != null) {
+ netProtocol.requestState(this, netProtocol.XA_NET_WM_STATE_SKIP_TASKBAR, true);
+ }
+ }
+
+ @Override
+ void postInit(XCreateWindowParams params) {
+ super.postInit(params);
+ XToolkit.awtLock();
+ try {
+ XWM.setMotifDecor(this, false, 0, 0);
+ XWM.setOLDecor(this, false, 0);
+
+ long parentWindow = ((Long)params.get(OWNER)).longValue();
+ XlibWrapper.XSetTransientFor(XToolkit.getDisplay(),
+ getWindow(), parentWindow);
+
+ XWMHints hints = getWMHints();
+ hints.set_flags(hints.get_flags() | (int)XUtilConstants.InputHint | (int)XUtilConstants.StateHint);
+ hints.set_input(false);
+ hints.set_initial_state(XUtilConstants.NormalState);
+ XlibWrapper.XSetWMHints(XToolkit.getDisplay(), getWindow(), hints.pData);
+
+ initWMProtocols();
+ requestNoTaskbar();
+ } finally {
+ XToolkit.awtUnlock();
+ }
+ }
+
+ private void updateWarningWindowBounds() {
+ XWindowPeer peer = ownerPeer.get();
+ if (peer != null) {
+ synchronized (this) {
+ if (updateIconSize()) {
+ XIconInfo ico = getSecurityIconInfo();
+ XToolkit.awtLock();
+ try {
+ XlibWrapper.SetBitmapShape(XToolkit.getDisplay(), getWindow(),
+ ico.getWidth(), ico.getHeight(), ico.getIntData());
+ } finally {
+ XToolkit.awtUnlock();
+ }
+ sizeUpdated = false;
+ AWTAccessor.getWindowAccessor().setSecurityWarningSize(
+ ownerWindow, ico.getWidth(), ico.getHeight());
+ }
+ }
+ peer.repositionSecurityWarning();
+ }
+ }
+
+ /**
+ * @param x,y,w,h coordinates of the untrusted window
+ */
+ public void reposition(int x, int y, int w, int h) {
+ Point2D point = AWTAccessor.getWindowAccessor().
+ calculateSecurityWarningPosition(ownerWindow,
+ x, y, w, h);
+ reshape((int)point.getX(), (int)point.getY(), getWidth(), getHeight());
}
protected String getWMName() {
@@ -49,33 +227,19 @@
getFont());
}
void paint(Graphics g, int x, int y, int width, int height) {
- String warningString = getWarningString();
- Rectangle bounds = getBounds();
- bounds.x = 0;
- bounds.y = 0;
- Rectangle updateRect = new Rectangle(x, y, width, height);
- if (updateRect.intersects(bounds)) {
- Rectangle updateArea = updateRect.intersection(bounds);
- g.setClip(updateArea);
- g.setColor(getBackground());
- g.fillRect(updateArea.x, updateArea.y, updateArea.width, updateArea.height);
- g.setColor(getColor());
- g.setFont(getFont());
- FontMetrics fm = g.getFontMetrics();
- int warningWidth = fm.stringWidth(warningString);
- int w_x = (bounds.width - warningWidth)/2;
- int w_y = (bounds.height + fm.getMaxAscent() - fm.getMaxDescent())/2;
- g.drawString(warningString, w_x, w_y);
- g.drawLine(bounds.x, bounds.y+bounds.height-1, bounds.x+bounds.width-1, bounds.y+bounds.height-1);
- }
+ g.drawImage(getSecurityIconInfo().getImage(), 0, 0, null);
}
String getWarningString() {
return ownerWindow.getWarningString();
}
+ int getWidth() {
+ return getSecurityIconInfo().getWidth();
+ }
+
int getHeight() {
- return defaultHeight; // should implement depending on Font
+ return getSecurityIconInfo().getHeight();
}
Color getBackground() {
@@ -97,6 +261,7 @@
}
}
+ @Override
public void handleExposeEvent(XEvent xev) {
super.handleExposeEvent(xev);
@@ -105,18 +270,156 @@
final int y = xe.get_y();
final int width = xe.get_width();
final int height = xe.get_height();
- EventQueue.invokeLater(new Runnable() {
- public void run() {
- Graphics g = getGraphics();
- try {
- paint(g, x, y, width, height);
- } finally {
- g.dispose();
- }
- }
- });
+ SunToolkit.executeOnEventHandlerThread(target,
+ new Runnable() {
+ public void run() {
+ Graphics g = getGraphics();
+ try {
+ paint(g, x, y, width, height);
+ } finally {
+ g.dispose();
+ }
+ }
+ });
}
+
+ @Override
protected boolean isEventDisabled(XEvent e) {
return true;
}
+
+ /** Send a synthetic UnmapNotify in order to withdraw the window.
+ */
+ private void withdraw() {
+ XEvent req = new XEvent();
+ try {
+ long root;
+ XToolkit.awtLock();
+ try {
+ root = XlibWrapper.RootWindow(XToolkit.getDisplay(), getScreenNumber());
+ }
+ finally {
+ XToolkit.awtUnlock();
+ }
+
+ req.set_type(XConstants.UnmapNotify);
+
+ XUnmapEvent umev = req.get_xunmap();
+
+ umev.set_event(root);
+ umev.set_window(getWindow());
+ umev.set_from_configure(false);
+
+ XToolkit.awtLock();
+ try {
+ XlibWrapper.XSendEvent(XToolkit.getDisplay(),
+ root,
+ false,
+ XConstants.SubstructureRedirectMask | XConstants.SubstructureNotifyMask,
+ req.pData);
+ }
+ finally {
+ XToolkit.awtUnlock();
+ }
+ } finally {
+ req.dispose();
+ }
+ }
+
+ @Override
+ protected void stateChanged(long time, int oldState, int newState) {
+ if (newState == XUtilConstants.IconicState) {
+ super.xSetVisible(false);
+ withdraw();
+ }
+ }
+
+ @Override
+ protected void setMouseAbove(boolean above) {
+ super.setMouseAbove(above);
+ XWindowPeer p = ownerPeer.get();
+ if (p != null) {
+ p.updateSecurityWarningVisibility();
+ }
+ }
+
+ @Override
+ protected void enterNotify(long window) {
+ super.enterNotify(window);
+ if (window == getWindow()) {
+ tooltip.enter();
+ }
+ }
+
+ @Override
+ protected void leaveNotify(long window) {
+ super.leaveNotify(window);
+ if (window == getWindow()) {
+ tooltip.exit();
+ }
+ }
+
+ @Override
+ public void xSetVisible(boolean visible) {
+ super.xSetVisible(visible);
+
+ // The _NET_WM_STATE_SKIP_TASKBAR got reset upon hiding/showing,
+ // so we request it every time whenever we change the visibility.
+ requestNoTaskbar();
+ }
+
+ private final Runnable hidingTask = new Runnable() {
+ public void run() {
+ xSetVisible(false);
+ }
+ };
+
+ private final Runnable showingTask = new Runnable() {
+ public void run() {
+ new Thread() {
+ public void run() {
+ if (!isVisible()) {
+ xSetVisible(true);
+ updateWarningWindowBounds();
+ }
+ repaint();
+ if (currentIcon > 0) {
+ currentIcon--;
+ XToolkit.schedule(showingTask, showingDelay);
+ }
+ }}.start();
+ }
+ };
+
+ public void setSecurityWarningVisible(boolean visible) {
+ setSecurityWarningVisible(visible, true);
+ }
+
+ public void setSecurityWarningVisible(boolean visible, boolean doSchedule) {
+ if (visible) {
+ XToolkit.remove(hidingTask);
+ XToolkit.remove(showingTask);
+ if (isVisible()) {
+ currentIcon = 0;
+ } else {
+ currentIcon = 3;
+ }
+ if (doSchedule) {
+ XToolkit.schedule(showingTask, 1);
+ } else {
+ showingTask.run();
+ }
+ } else {
+ XToolkit.remove(showingTask);
+ XToolkit.remove(hidingTask);
+ if (!isVisible()) {
+ return;
+ }
+ if (doSchedule) {
+ XToolkit.schedule(hidingTask, hidingDelay);
+ } else {
+ hidingTask.run();
+ }
+ }
+ }
}