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