1 /* 2 * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package sun.lwawt.macosx; 27 28 import sun.awt.AWTAccessor; 29 import sun.awt.IconInfo; 30 import sun.java2d.SunGraphics2D; 31 import sun.java2d.SurfaceData; 32 import sun.java2d.opengl.CGLLayer; 33 import sun.lwawt.LWWindowPeer; 34 import sun.lwawt.PlatformEventNotifier; 35 import sun.lwawt.SecurityWarningWindow; 36 37 import java.awt.*; 38 import java.awt.event.MouseEvent; 39 import java.awt.geom.Point2D; 40 import java.lang.ref.WeakReference; 41 42 public final class CWarningWindow extends CPlatformWindow 43 implements SecurityWarningWindow, PlatformEventNotifier { 44 45 private static class Lock {} 46 private final Lock lock = new Lock(); 47 48 private final static int SHOWING_DELAY = 300; 49 private final static int HIDING_DELAY = 2000; 50 51 private Rectangle bounds = new Rectangle(); 52 private final WeakReference<LWWindowPeer> ownerPeer; 53 private final Window ownerWindow; 54 55 /** 56 * Animation stage. 57 */ 58 private volatile int currentIcon = 0; 59 60 /* -1 - uninitialized. 61 * 0 - 16x16 62 * 1 - 24x24 63 * 2 - 32x32 64 * 3 - 48x48 65 */ 66 private int currentSize = -1; 67 private static IconInfo[][] icons; 68 private static IconInfo getSecurityIconInfo(int size, int num) { 69 synchronized (CWarningWindow.class) { 70 if (icons == null) { 71 icons = new IconInfo[4][3]; 72 icons[0][0] = new IconInfo(sun.awt.AWTIcon32_security_icon_bw16_png.security_icon_bw16_png); 73 icons[0][1] = new IconInfo(sun.awt.AWTIcon32_security_icon_interim16_png.security_icon_interim16_png); 74 icons[0][2] = new IconInfo(sun.awt.AWTIcon32_security_icon_yellow16_png.security_icon_yellow16_png); 75 icons[1][0] = new IconInfo(sun.awt.AWTIcon32_security_icon_bw24_png.security_icon_bw24_png); 76 icons[1][1] = new IconInfo(sun.awt.AWTIcon32_security_icon_interim24_png.security_icon_interim24_png); 77 icons[1][2] = new IconInfo(sun.awt.AWTIcon32_security_icon_yellow24_png.security_icon_yellow24_png); 78 icons[2][0] = new IconInfo(sun.awt.AWTIcon32_security_icon_bw32_png.security_icon_bw32_png); 79 icons[2][1] = new IconInfo(sun.awt.AWTIcon32_security_icon_interim32_png.security_icon_interim32_png); 80 icons[2][2] = new IconInfo(sun.awt.AWTIcon32_security_icon_yellow32_png.security_icon_yellow32_png); 81 icons[3][0] = new IconInfo(sun.awt.AWTIcon32_security_icon_bw48_png.security_icon_bw48_png); 82 icons[3][1] = new IconInfo(sun.awt.AWTIcon32_security_icon_interim48_png.security_icon_interim48_png); 83 icons[3][2] = new IconInfo(sun.awt.AWTIcon32_security_icon_yellow48_png.security_icon_yellow48_png); 84 } 85 } 86 final int sizeIndex = size % icons.length; 87 return icons[sizeIndex][num % icons[sizeIndex].length]; 88 } 89 90 public CWarningWindow(final Window _ownerWindow, final LWWindowPeer _ownerPeer) { 91 super(); 92 93 this.ownerPeer = new WeakReference<>(_ownerPeer); 94 this.ownerWindow = _ownerWindow; 95 96 initialize(null, null, _ownerPeer.getPlatformWindow()); 97 98 setOpaque(false); 99 100 String warningString = ownerWindow.getWarningString(); 101 if (warningString != null) { 102 contentView.setToolTip(ownerWindow.getWarningString()); 103 } 104 105 updateIconSize(); 106 } 107 108 /** 109 * @param x,y,w,h coordinates of the untrusted window 110 */ 111 public void reposition(int x, int y, int w, int h) { 112 final Point2D point = AWTAccessor.getWindowAccessor(). 113 calculateSecurityWarningPosition(ownerWindow, x, y, w, h); 114 setBounds((int)point.getX(), (int)point.getY(), getWidth(), getHeight()); 115 } 116 117 public void setVisible(boolean visible, boolean doSchedule) { 118 synchronized (taskLock) { 119 cancelTasks(); 120 121 if (visible) { 122 if (isVisible()) { 123 currentIcon = 0; 124 } else { 125 currentIcon = 2; 126 } 127 128 showHideTask = new ShowingTask(); 129 LWCToolkit.performOnMainThreadAfterDelay(showHideTask, 50); 130 } else { 131 if (!isVisible()) { 132 return; 133 } 134 135 showHideTask = new HidingTask(); 136 if (doSchedule) { 137 LWCToolkit.performOnMainThreadAfterDelay(showHideTask, HIDING_DELAY); 138 } else { 139 LWCToolkit.performOnMainThreadAfterDelay(showHideTask, 50); 140 } 141 } 142 } 143 } 144 145 @Override 146 public void notifyIconify(boolean iconify) { 147 } 148 149 @Override 150 public void notifyZoom(boolean isZoomed) { 151 } 152 153 @Override 154 public void notifyExpose(final Rectangle r) { 155 repaint(); 156 } 157 158 @Override 159 public void notifyReshape(int x, int y, int w, int h) { 160 } 161 162 @Override 163 public void notifyUpdateCursor() { 164 } 165 166 @Override 167 public void notifyActivation(boolean activation, LWWindowPeer opposite) { 168 } 169 170 @Override 171 public void notifyNCMouseDown() { 172 } 173 174 @Override 175 public void notifyMouseEvent(int id, long when, int button, int x, int y, 176 int screenX, int screenY, int modifiers, 177 int clickCount, boolean popupTrigger, 178 byte[] bdata) { 179 LWWindowPeer peer = ownerPeer.get(); 180 if (id == MouseEvent.MOUSE_EXITED) { 181 if (peer != null) { 182 peer.updateSecurityWarningVisibility(); 183 } 184 } else if(id == MouseEvent.MOUSE_ENTERED) { 185 if (peer != null) { 186 peer.updateSecurityWarningVisibility(); 187 } 188 } 189 } 190 191 public Rectangle getBounds() { 192 synchronized (lock) { 193 return bounds.getBounds(); 194 } 195 } 196 197 @Override 198 public boolean isVisible() { 199 synchronized (lock) { 200 return visible; 201 } 202 } 203 204 @Override 205 public void setVisible(boolean visible) { 206 synchronized (lock) { 207 final long nsWindowPtr = getNSWindowPtr(); 208 209 // Process parent-child relationship when hiding 210 if (!visible) { 211 // Unparent myself 212 if (owner != null && owner.isVisible()) { 213 CWrapper.NSWindow.removeChildWindow( 214 owner.getNSWindowPtr(), nsWindowPtr); 215 } 216 } 217 218 // Actually show or hide the window 219 if (visible) { 220 CWrapper.NSWindow.orderFront(nsWindowPtr); 221 } else { 222 CWrapper.NSWindow.orderOut(nsWindowPtr); 223 } 224 225 this.visible = visible; 226 227 // Manage parent-child relationship when showing 228 if (visible) { 229 // Add myself as a child 230 if (owner != null && owner.isVisible()) { 231 CWrapper.NSWindow.addChildWindow(owner.getNSWindowPtr(), 232 nsWindowPtr, CWrapper.NSWindow.NSWindowAbove); 233 234 // do not allow security warning to be obscured by other windows 235 applyWindowLevel(ownerWindow); 236 } 237 } 238 } 239 } 240 241 @Override 242 public void notifyMouseWheelEvent(long when, int x, int y, int modifiers, 243 int scrollType, int scrollAmount, 244 int wheelRotation, double preciseWheelRotation, 245 byte[] bdata) { 246 } 247 248 @Override 249 public void notifyKeyEvent(int id, long when, int modifiers, int keyCode, 250 char keyChar, int keyLocation) { 251 } 252 253 protected int getInitialStyleBits() { 254 int styleBits = 0; 255 CPlatformWindow.SET(styleBits, CPlatformWindow.UTILITY, true); 256 return styleBits; 257 } 258 259 protected void deliverMoveResizeEvent(int x, int y, int width, int height, 260 boolean byUser) { 261 262 boolean isResize; 263 synchronized (lock) { 264 isResize = (bounds.width != width || bounds.height != height); 265 bounds = new Rectangle(x, y, width, height); 266 } 267 268 if (isResize) { 269 replaceSurface(); 270 } 271 272 super.deliverMoveResizeEvent(x, y, width, height, byUser); 273 } 274 275 protected CPlatformResponder createPlatformResponder() { 276 return new CPlatformResponder(this, false); 277 } 278 279 protected CPlatformView createContentView() { 280 return new CPlatformView() { 281 public GraphicsConfiguration getGraphicsConfiguration() { 282 LWWindowPeer peer = ownerPeer.get(); 283 return peer.getGraphicsConfiguration(); 284 } 285 286 public Rectangle getBounds() { 287 return CWarningWindow.this.getBounds(); 288 } 289 290 public CGLLayer createCGLayer() { 291 return new CGLLayer(null) { 292 public Rectangle getBounds() { 293 return CWarningWindow.this.getBounds(); 294 } 295 296 public GraphicsConfiguration getGraphicsConfiguration() { 297 LWWindowPeer peer = ownerPeer.get(); 298 return peer.getGraphicsConfiguration(); 299 } 300 301 public boolean isOpaque() { 302 return false; 303 } 304 }; 305 } 306 }; 307 } 308 309 @Override 310 public void dispose() { 311 cancelTasks(); 312 SurfaceData surfaceData = contentView.getSurfaceData(); 313 if (surfaceData != null) { 314 surfaceData.invalidate(); 315 } 316 super.dispose(); 317 } 318 319 private void cancelTasks() { 320 synchronized (taskLock) { 321 if (showHideTask != null) { 322 showHideTask.cancel(); 323 showHideTask = null; 324 } 325 } 326 } 327 328 private void updateIconSize() { 329 int newSize = -1; 330 331 if (ownerWindow != null) { 332 Insets insets = ownerWindow.getInsets(); 333 int max = Math.max(insets.top, Math.max(insets.bottom, 334 Math.max(insets.left, insets.right))); 335 if (max < 24) { 336 newSize = 0; 337 } else if (max < 32) { 338 newSize = 1; 339 } else if (max < 48) { 340 newSize = 2; 341 } else { 342 newSize = 3; 343 } 344 } 345 // Make sure we have a valid size 346 if (newSize == -1) { 347 newSize = 0; 348 } 349 350 synchronized (lock) { 351 if (newSize != currentSize) { 352 currentSize = newSize; 353 IconInfo ico = getSecurityIconInfo(currentSize, 0); 354 AWTAccessor.getWindowAccessor().setSecurityWarningSize( 355 ownerWindow, ico.getWidth(), ico.getHeight()); 356 } 357 } 358 } 359 360 private Graphics getGraphics() { 361 SurfaceData sd = contentView.getSurfaceData(); 362 if (ownerWindow == null || sd == null) { 363 return null; 364 } 365 366 return transformGraphics(new SunGraphics2D(sd, SystemColor.windowText, 367 SystemColor.window, ownerWindow.getFont())); 368 } 369 370 371 private void repaint() { 372 final Graphics g = getGraphics(); 373 if (g != null) { 374 try { 375 ((Graphics2D) g).setComposite(AlphaComposite.Src); 376 g.drawImage(getSecurityIconInfo().getImage(), 0, 0, null); 377 } finally { 378 g.dispose(); 379 } 380 } 381 } 382 383 private void replaceSurface() { 384 SurfaceData oldData = contentView.getSurfaceData(); 385 386 replaceSurfaceData(); 387 388 if (oldData != null && oldData != contentView.getSurfaceData()) { 389 oldData.flush(); 390 } 391 } 392 393 private int getWidth() { 394 return getSecurityIconInfo().getWidth(); 395 } 396 397 private int getHeight() { 398 return getSecurityIconInfo().getHeight(); 399 } 400 401 private IconInfo getSecurityIconInfo() { 402 return getSecurityIconInfo(currentSize, currentIcon); 403 } 404 405 private final Lock taskLock = new Lock(); 406 private CancelableRunnable showHideTask; 407 408 private static abstract class CancelableRunnable implements Runnable { 409 private volatile boolean perform = true; 410 411 public final void cancel() { 412 perform = false; 413 } 414 415 @Override 416 public final void run() { 417 if (perform) { 418 perform(); 419 } 420 } 421 422 public abstract void perform(); 423 } 424 425 private class HidingTask extends CancelableRunnable { 426 @Override 427 public void perform() { 428 synchronized (lock) { 429 setVisible(false); 430 } 431 432 synchronized (taskLock) { 433 showHideTask = null; 434 } 435 } 436 } 437 438 private class ShowingTask extends CancelableRunnable { 439 @Override 440 public void perform() { 441 synchronized (lock) { 442 if (!isVisible()) { 443 setVisible(true); 444 } 445 repaint(); 446 } 447 448 synchronized (taskLock) { 449 if (currentIcon > 0) { 450 currentIcon--; 451 showHideTask = new ShowingTask(); 452 LWCToolkit.performOnMainThreadAfterDelay(showHideTask, SHOWING_DELAY); 453 } else { 454 showHideTask = null; 455 } 456 } 457 } 458 } 459 } 460