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