1 /* 2 * Copyright (c) 2003, 2013, 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 package sun.awt.X11; 26 27 import java.awt.*; 28 import java.awt.geom.Point2D; 29 import java.lang.ref.WeakReference; 30 31 import sun.awt.IconInfo; 32 import sun.awt.AWTAccessor; 33 import sun.awt.SunToolkit; 34 35 class XWarningWindow extends XWindow { 36 private static final int SHOWING_DELAY = 330; 37 private static final int HIDING_DELAY = 2000; 38 39 private final Window ownerWindow; 40 private WeakReference<XWindowPeer> ownerPeer; 41 private long parentWindow; 42 43 private static final String OWNER = "OWNER"; 44 private InfoWindow.Tooltip tooltip; 45 46 /** 47 * Animation stage. 48 */ 49 private volatile int currentIcon = 0; 50 51 /* -1 - uninitialized. 52 * 0 - 16x16 53 * 1 - 24x24 54 * 2 - 32x32 55 * 3 - 48x48 56 */ 57 private int currentSize = -1; 58 private static IconInfo[][] icons; 59 private static IconInfo getSecurityIconInfo(int size, int num) { 60 synchronized (XWarningWindow.class) { 61 if (icons == null) { 62 icons = new IconInfo[4][3]; 63 if (XlibWrapper.dataModel == 32) { 64 icons[0][0] = new IconInfo(sun.awt.AWTIcon32_security_icon_bw16_png.security_icon_bw16_png); 65 icons[0][1] = new IconInfo(sun.awt.AWTIcon32_security_icon_interim16_png.security_icon_interim16_png); 66 icons[0][2] = new IconInfo(sun.awt.AWTIcon32_security_icon_yellow16_png.security_icon_yellow16_png); 67 icons[1][0] = new IconInfo(sun.awt.AWTIcon32_security_icon_bw24_png.security_icon_bw24_png); 68 icons[1][1] = new IconInfo(sun.awt.AWTIcon32_security_icon_interim24_png.security_icon_interim24_png); 69 icons[1][2] = new IconInfo(sun.awt.AWTIcon32_security_icon_yellow24_png.security_icon_yellow24_png); 70 icons[2][0] = new IconInfo(sun.awt.AWTIcon32_security_icon_bw32_png.security_icon_bw32_png); 71 icons[2][1] = new IconInfo(sun.awt.AWTIcon32_security_icon_interim32_png.security_icon_interim32_png); 72 icons[2][2] = new IconInfo(sun.awt.AWTIcon32_security_icon_yellow32_png.security_icon_yellow32_png); 73 icons[3][0] = new IconInfo(sun.awt.AWTIcon32_security_icon_bw48_png.security_icon_bw48_png); 74 icons[3][1] = new IconInfo(sun.awt.AWTIcon32_security_icon_interim48_png.security_icon_interim48_png); 75 icons[3][2] = new IconInfo(sun.awt.AWTIcon32_security_icon_yellow48_png.security_icon_yellow48_png); 76 } else { 77 icons[0][0] = new IconInfo(sun.awt.AWTIcon64_security_icon_bw16_png.security_icon_bw16_png); 78 icons[0][1] = new IconInfo(sun.awt.AWTIcon64_security_icon_interim16_png.security_icon_interim16_png); 79 icons[0][2] = new IconInfo(sun.awt.AWTIcon64_security_icon_yellow16_png.security_icon_yellow16_png); 80 icons[1][0] = new IconInfo(sun.awt.AWTIcon64_security_icon_bw24_png.security_icon_bw24_png); 81 icons[1][1] = new IconInfo(sun.awt.AWTIcon64_security_icon_interim24_png.security_icon_interim24_png); 82 icons[1][2] = new IconInfo(sun.awt.AWTIcon64_security_icon_yellow24_png.security_icon_yellow24_png); 83 icons[2][0] = new IconInfo(sun.awt.AWTIcon64_security_icon_bw32_png.security_icon_bw32_png); 84 icons[2][1] = new IconInfo(sun.awt.AWTIcon64_security_icon_interim32_png.security_icon_interim32_png); 85 icons[2][2] = new IconInfo(sun.awt.AWTIcon64_security_icon_yellow32_png.security_icon_yellow32_png); 86 icons[3][0] = new IconInfo(sun.awt.AWTIcon64_security_icon_bw48_png.security_icon_bw48_png); 87 icons[3][1] = new IconInfo(sun.awt.AWTIcon64_security_icon_interim48_png.security_icon_interim48_png); 88 icons[3][2] = new IconInfo(sun.awt.AWTIcon64_security_icon_yellow48_png.security_icon_yellow48_png); 89 } 90 } 91 } 92 final int sizeIndex = size % icons.length; 93 return icons[sizeIndex][num % icons[sizeIndex].length]; 94 } 95 96 private void updateIconSize() { 97 int newSize = -1; 98 99 if (ownerWindow != null) { 100 Insets insets = ownerWindow.getInsets(); 101 int max = Math.max(insets.top, Math.max(insets.bottom, 102 Math.max(insets.left, insets.right))); 103 if (max < 24) { 104 newSize = 0; 105 } else if (max < 32) { 106 newSize = 1; 107 } else if (max < 48) { 108 newSize = 2; 109 } else { 110 newSize = 3; 111 } 112 } 113 // Make sure we have a valid size 114 if (newSize == -1) { 115 newSize = 0; 116 } 117 118 // Note: this is not the most wise solution to use awtLock here, 119 // this should have been sync'ed with the stateLock. However, 120 // the awtLock must be taken first (see XBaseWindow.getStateLock()), 121 // and we need the awtLock anyway to update the shape of the icon. 122 // So it's easier to use just one lock instead. 123 XToolkit.awtLock(); 124 try { 125 if (newSize != currentSize) { 126 currentSize = newSize; 127 IconInfo ico = getSecurityIconInfo(currentSize, 0); 128 XlibWrapper.SetBitmapShape(XToolkit.getDisplay(), getWindow(), 129 ico.getWidth(), ico.getHeight(), ico.getIntData()); 130 AWTAccessor.getWindowAccessor().setSecurityWarningSize( 131 ownerWindow, ico.getWidth(), ico.getHeight()); 132 } 133 } finally { 134 XToolkit.awtUnlock(); 135 } 136 } 137 138 private IconInfo getSecurityIconInfo() { 139 updateIconSize(); 140 return getSecurityIconInfo(currentSize, currentIcon); 141 } 142 143 XWarningWindow(final Window ownerWindow, long parentWindow, XWindowPeer ownerPeer) { 144 super(new XCreateWindowParams(new Object[] { 145 TARGET, ownerWindow, 146 OWNER, Long.valueOf(parentWindow) 147 })); 148 this.ownerWindow = ownerWindow; 149 this.parentWindow = parentWindow; 150 this.tooltip = new InfoWindow.Tooltip(null, getTarget(), 151 new InfoWindow.Tooltip.LiveArguments() { 152 public boolean isDisposed() { 153 return XWarningWindow.this.isDisposed(); 154 } 155 public Rectangle getBounds() { 156 return XWarningWindow.this.getBounds(); 157 } 158 public String getTooltipString() { 159 return XWarningWindow.this.ownerWindow.getWarningString(); 160 } 161 }); 162 this.ownerPeer = new WeakReference<XWindowPeer>(ownerPeer); 163 } 164 165 private void requestNoTaskbar() { 166 XNETProtocol netProtocol = XWM.getWM().getNETProtocol(); 167 if (netProtocol != null) { 168 netProtocol.requestState(this, netProtocol.XA_NET_WM_STATE_SKIP_TASKBAR, true); 169 } 170 } 171 172 @Override 173 void postInit(XCreateWindowParams params) { 174 super.postInit(params); 175 XToolkit.awtLock(); 176 try { 177 XWM.setMotifDecor(this, false, 0, 0); 178 XWM.setOLDecor(this, false, 0); 179 180 long parentWindow = ((Long)params.get(OWNER)).longValue(); 181 XlibWrapper.XSetTransientFor(XToolkit.getDisplay(), 182 getWindow(), parentWindow); 183 184 XWMHints hints = getWMHints(); 185 hints.set_flags(hints.get_flags() | (int)XUtilConstants.InputHint | (int)XUtilConstants.StateHint); 186 hints.set_input(false); 187 hints.set_initial_state(XUtilConstants.NormalState); 188 XlibWrapper.XSetWMHints(XToolkit.getDisplay(), getWindow(), hints.pData); 189 190 initWMProtocols(); 191 requestNoTaskbar(); 192 } finally { 193 XToolkit.awtUnlock(); 194 } 195 } 196 197 /** 198 * @param x,y,w,h coordinates of the untrusted window 199 */ 200 public void reposition(int x, int y, int w, int h) { 201 Point2D point = AWTAccessor.getWindowAccessor(). 202 calculateSecurityWarningPosition(ownerWindow, 203 x, y, w, h); 204 reshape((int)point.getX(), (int)point.getY(), getWidth(), getHeight()); 205 } 206 207 protected String getWMName() { 208 return "Warning window"; 209 } 210 211 public Graphics getGraphics() { 212 if ((surfaceData == null) || (ownerWindow == null)) return null; 213 return getGraphics(surfaceData, 214 getColor(), 215 getBackground(), 216 getFont()); 217 } 218 void paint(Graphics g, int x, int y, int width, int height) { 219 g.drawImage(getSecurityIconInfo().getImage(), 0, 0, null); 220 } 221 222 String getWarningString() { 223 return ownerWindow.getWarningString(); 224 } 225 226 int getWidth() { 227 return getSecurityIconInfo().getWidth(); 228 } 229 230 int getHeight() { 231 return getSecurityIconInfo().getHeight(); 232 } 233 234 Color getBackground() { 235 return SystemColor.window; 236 } 237 Color getColor() { 238 return Color.black; 239 } 240 Font getFont () { 241 return ownerWindow.getFont(); 242 } 243 244 @Override 245 public void repaint() { 246 final Rectangle bounds = getBounds(); 247 final Graphics g = getGraphics(); 248 if (g != null) { 249 try { 250 paint(g, 0, 0, bounds.width, bounds.height); 251 } finally { 252 g.dispose(); 253 } 254 } 255 } 256 @Override 257 public void handleExposeEvent(XEvent xev) { 258 super.handleExposeEvent(xev); 259 260 XExposeEvent xe = xev.get_xexpose(); 261 final int x = scaleDown(xe.get_x()); 262 final int y = scaleDown(xe.get_y()); 263 final int width = scaleDown(xe.get_width()); 264 final int height = scaleDown(xe.get_height()); 265 SunToolkit.executeOnEventHandlerThread(target, 266 new Runnable() { 267 public void run() { 268 final Graphics g = getGraphics(); 269 if (g != null) { 270 try { 271 paint(g, x, y, width, height); 272 } finally { 273 g.dispose(); 274 } 275 } 276 } 277 }); 278 } 279 280 @Override 281 protected boolean isEventDisabled(XEvent e) { 282 return true; 283 } 284 285 /** Send a synthetic UnmapNotify in order to withdraw the window. 286 */ 287 private void withdraw() { 288 XEvent req = new XEvent(); 289 try { 290 long root; 291 XToolkit.awtLock(); 292 try { 293 root = XlibWrapper.RootWindow(XToolkit.getDisplay(), getScreenNumber()); 294 } 295 finally { 296 XToolkit.awtUnlock(); 297 } 298 299 req.set_type(XConstants.UnmapNotify); 300 301 XUnmapEvent umev = req.get_xunmap(); 302 303 umev.set_event(root); 304 umev.set_window(getWindow()); 305 umev.set_from_configure(false); 306 307 XToolkit.awtLock(); 308 try { 309 XlibWrapper.XSendEvent(XToolkit.getDisplay(), 310 root, 311 false, 312 XConstants.SubstructureRedirectMask | XConstants.SubstructureNotifyMask, 313 req.pData); 314 } 315 finally { 316 XToolkit.awtUnlock(); 317 } 318 } finally { 319 req.dispose(); 320 } 321 } 322 323 @Override 324 protected void stateChanged(long time, int oldState, int newState) { 325 if (newState == XUtilConstants.IconicState) { 326 super.xSetVisible(false); 327 withdraw(); 328 } 329 } 330 331 @Override 332 protected void setMouseAbove(boolean above) { 333 super.setMouseAbove(above); 334 XWindowPeer p = ownerPeer.get(); 335 if (p != null) { 336 p.updateSecurityWarningVisibility(); 337 } 338 } 339 340 @Override 341 protected void enterNotify(long window) { 342 super.enterNotify(window); 343 if (window == getWindow()) { 344 tooltip.enter(); 345 } 346 } 347 348 @Override 349 protected void leaveNotify(long window) { 350 super.leaveNotify(window); 351 if (window == getWindow()) { 352 tooltip.exit(); 353 } 354 } 355 356 @Override 357 public void xSetVisible(boolean visible) { 358 super.xSetVisible(visible); 359 360 // The _NET_WM_STATE_SKIP_TASKBAR got reset upon hiding/showing, 361 // so we request it every time whenever we change the visibility. 362 requestNoTaskbar(); 363 } 364 365 private final Runnable hidingTask = new Runnable() { 366 public void run() { 367 xSetVisible(false); 368 } 369 }; 370 371 private final Runnable showingTask = new Runnable() { 372 public void run() { 373 if (!isVisible()) { 374 xSetVisible(true); 375 updateIconSize(); 376 XWindowPeer peer = ownerPeer.get(); 377 if (peer != null) { 378 peer.repositionSecurityWarning(); 379 } 380 } 381 repaint(); 382 if (currentIcon > 0) { 383 currentIcon--; 384 XToolkit.schedule(showingTask, SHOWING_DELAY); 385 } 386 } 387 }; 388 389 public void setSecurityWarningVisible(boolean visible, boolean doSchedule) { 390 if (visible) { 391 XToolkit.remove(hidingTask); 392 XToolkit.remove(showingTask); 393 if (isVisible()) { 394 currentIcon = 0; 395 } else { 396 currentIcon = 3; 397 } 398 if (doSchedule) { 399 XToolkit.schedule(showingTask, 1); 400 } else { 401 showingTask.run(); 402 } 403 } else { 404 XToolkit.remove(showingTask); 405 XToolkit.remove(hidingTask); 406 if (!isVisible()) { 407 return; 408 } 409 if (doSchedule) { 410 XToolkit.schedule(hidingTask, HIDING_DELAY); 411 } else { 412 hidingTask.run(); 413 } 414 } 415 } 416 }