1 /* 2 * Copyright (c) 2013, 2015, 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 static final int SHOWING_DELAY = 300; 49 private static final 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 absX, int absY, 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 absX, 243 int absY, int modifiers, int scrollType, 244 int scrollAmount, int wheelRotation, 245 double preciseWheelRotation, 246 byte[] bdata) { 247 } 248 249 @Override 250 public void notifyKeyEvent(int id, long when, int modifiers, int keyCode, 251 char keyChar, int keyLocation) { 252 } 253 254 protected int getInitialStyleBits() { 255 int styleBits = 0; 256 CPlatformWindow.SET(styleBits, CPlatformWindow.UTILITY, true); 257 return styleBits; 258 } 259 260 protected void deliverMoveResizeEvent(int x, int y, int width, int height, 261 boolean byUser) { 262 263 boolean isResize; 264 synchronized (lock) { 265 isResize = (bounds.width != width || bounds.height != height); 266 bounds = new Rectangle(x, y, width, height); 267 } 268 269 if (isResize) { 270 replaceSurface(); 271 } 272 273 super.deliverMoveResizeEvent(x, y, width, height, byUser); 274 } 275 276 protected CPlatformResponder createPlatformResponder() { 277 return new CPlatformResponder(this, false); 278 } 279 280 protected CPlatformView createContentView() { 281 return new CPlatformView() { 282 public GraphicsConfiguration getGraphicsConfiguration() { 283 LWWindowPeer peer = ownerPeer.get(); 284 return peer.getGraphicsConfiguration(); 285 } 286 287 public Rectangle getBounds() { 288 return CWarningWindow.this.getBounds(); 289 } 290 291 public CGLLayer createCGLayer() { 292 return new CGLLayer(null) { 293 public Rectangle getBounds() { 294 return CWarningWindow.this.getBounds(); 295 } 296 297 public GraphicsConfiguration getGraphicsConfiguration() { 298 LWWindowPeer peer = ownerPeer.get(); 299 return peer.getGraphicsConfiguration(); 300 } 301 302 public boolean isOpaque() { 303 return false; 304 } 305 }; 306 } 307 }; 308 } 309 310 @Override 311 public void dispose() { 312 cancelTasks(); 313 SurfaceData surfaceData = contentView.getSurfaceData(); 314 if (surfaceData != null) { 315 surfaceData.invalidate(); 316 } 317 super.dispose(); 318 } 319 320 private void cancelTasks() { 321 synchronized (taskLock) { 322 if (showHideTask != null) { 323 showHideTask.cancel(); 324 showHideTask = null; 325 } 326 } 327 } 328 329 private void updateIconSize() { 330 int newSize = -1; 331 332 if (ownerWindow != null) { 333 Insets insets = ownerWindow.getInsets(); 334 int max = Math.max(insets.top, Math.max(insets.bottom, 335 Math.max(insets.left, insets.right))); 336 if (max < 24) { 337 newSize = 0; 338 } else if (max < 32) { 339 newSize = 1; 340 } else if (max < 48) { 341 newSize = 2; 342 } else { 343 newSize = 3; 344 } 345 } 346 // Make sure we have a valid size 347 if (newSize == -1) { 348 newSize = 0; 349 } 350 351 synchronized (lock) { 352 if (newSize != currentSize) { 353 currentSize = newSize; 354 IconInfo ico = getSecurityIconInfo(currentSize, 0); 355 AWTAccessor.getWindowAccessor().setSecurityWarningSize( 356 ownerWindow, ico.getWidth(), ico.getHeight()); 357 } 358 } 359 } 360 361 private Graphics getGraphics() { 362 SurfaceData sd = contentView.getSurfaceData(); 363 if (ownerWindow == null || sd == null) { 364 return null; 365 } 366 367 return transformGraphics(new SunGraphics2D(sd, SystemColor.windowText, 368 SystemColor.window, ownerWindow.getFont())); 369 } 370 371 372 private void repaint() { 373 final Graphics g = getGraphics(); 374 if (g != null) { 375 try { 376 ((Graphics2D) g).setComposite(AlphaComposite.Src); 377 g.drawImage(getSecurityIconInfo().getImage(), 0, 0, null); 378 } finally { 379 g.dispose(); 380 } 381 } 382 } 383 384 private void replaceSurface() { 385 SurfaceData oldData = contentView.getSurfaceData(); 386 387 replaceSurfaceData(); 388 389 if (oldData != null && oldData != contentView.getSurfaceData()) { 390 oldData.flush(); 391 } 392 } 393 394 private int getWidth() { 395 return getSecurityIconInfo().getWidth(); 396 } 397 398 private int getHeight() { 399 return getSecurityIconInfo().getHeight(); 400 } 401 402 private IconInfo getSecurityIconInfo() { 403 return getSecurityIconInfo(currentSize, currentIcon); 404 } 405 406 private final Lock taskLock = new Lock(); 407 private CancelableRunnable showHideTask; 408 409 private abstract static class CancelableRunnable implements Runnable { 410 private volatile boolean perform = true; 411 412 public final void cancel() { 413 perform = false; 414 } 415 416 @Override 417 public final void run() { 418 if (perform) { 419 perform(); 420 } 421 } 422 423 public abstract void perform(); 424 } 425 426 private class HidingTask extends CancelableRunnable { 427 @Override 428 public void perform() { 429 synchronized (lock) { 430 setVisible(false); 431 } 432 433 synchronized (taskLock) { 434 showHideTask = null; 435 } 436 } 437 } 438 439 private class ShowingTask extends CancelableRunnable { 440 @Override 441 public void perform() { 442 synchronized (lock) { 443 if (!isVisible()) { 444 setVisible(true); 445 } 446 repaint(); 447 } 448 449 synchronized (taskLock) { 450 if (currentIcon > 0) { 451 currentIcon--; 452 showHideTask = new ShowingTask(); 453 LWCToolkit.performOnMainThreadAfterDelay(showHideTask, SHOWING_DELAY); 454 } else { 455 showHideTask = null; 456 } 457 } 458 } 459 } 460 } 461