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