1 /* 2 * Copyright (c) 2002, 2010, 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 29 import java.awt.event.ComponentEvent; 30 import java.awt.event.FocusEvent; 31 import java.awt.event.WindowEvent; 32 33 import java.awt.image.BufferedImage; 34 35 import java.awt.peer.ComponentPeer; 36 import java.awt.peer.WindowPeer; 37 38 import java.io.UnsupportedEncodingException; 39 40 import java.security.AccessController; 41 import java.security.PrivilegedAction; 42 43 import java.util.ArrayList; 44 import java.util.HashSet; 45 import java.util.Iterator; 46 import java.util.Set; 47 import java.util.Vector; 48 49 import java.util.concurrent.atomic.AtomicBoolean; 50 51 import sun.util.logging.PlatformLogger; 52 53 import sun.awt.AWTAccessor; 54 import sun.awt.DisplayChangedListener; 55 import sun.awt.SunToolkit; 56 import sun.awt.X11GraphicsDevice; 57 import sun.awt.X11GraphicsEnvironment; 58 59 import sun.java2d.pipe.Region; 60 61 class XWindowPeer extends XPanelPeer implements WindowPeer, 62 DisplayChangedListener { 63 64 private static final PlatformLogger log = PlatformLogger.getLogger("sun.awt.X11.XWindowPeer"); 65 private static final PlatformLogger focusLog = PlatformLogger.getLogger("sun.awt.X11.focus.XWindowPeer"); 66 private static final PlatformLogger insLog = PlatformLogger.getLogger("sun.awt.X11.insets.XWindowPeer"); 67 private static final PlatformLogger grabLog = PlatformLogger.getLogger("sun.awt.X11.grab.XWindowPeer"); 68 private static final PlatformLogger iconLog = PlatformLogger.getLogger("sun.awt.X11.icon.XWindowPeer"); 69 70 // should be synchronized on awtLock 71 private static Set<XWindowPeer> windows = new HashSet<XWindowPeer>(); 72 73 74 private boolean cachedFocusableWindow; 75 XWarningWindow warningWindow; 76 77 private boolean alwaysOnTop; 78 private boolean locationByPlatform; 79 80 Dialog modalBlocker; 81 boolean delayedModalBlocking = false; 82 Dimension targetMinimumSize = null; 83 84 private XWindowPeer ownerPeer; 85 86 // used for modal blocking to keep existing z-order 87 protected XWindowPeer prevTransientFor, nextTransientFor; 88 // value of WM_TRANSIENT_FOR hint set on this window 89 private XWindowPeer curRealTransientFor; 90 91 private boolean grab = false; // Whether to do a grab during showing 92 93 private boolean isMapped = false; // Is this window mapped or not 94 private boolean mustControlStackPosition = false; // Am override-redirect not on top 95 private XEventDispatcher rootPropertyEventDispatcher = null; 96 97 private static final AtomicBoolean isStartupNotificationRemoved = new AtomicBoolean(); 98 99 /* 100 * Focus related flags 101 */ 102 private boolean isUnhiding = false; // Is the window unhiding. 103 private boolean isBeforeFirstMapNotify = false; // Is the window (being shown) between 104 // setVisible(true) & handleMapNotify(). 105 106 /** 107 * The type of the window. 108 * 109 * The type is supposed to be immutable while the peer object exists. 110 * The value gets initialized in the preInit() method. 111 */ 112 private Window.Type windowType = Window.Type.NORMAL; 113 114 public final Window.Type getWindowType() { 115 return windowType; 116 } 117 118 // It need to be accessed from XFramePeer. 119 protected Vector <ToplevelStateListener> toplevelStateListeners = new Vector<ToplevelStateListener>(); 120 XWindowPeer(XCreateWindowParams params) { 121 super(params.putIfNull(PARENT_WINDOW, Long.valueOf(0))); 122 } 123 124 XWindowPeer(Window target) { 125 super(new XCreateWindowParams(new Object[] { 126 TARGET, target, 127 PARENT_WINDOW, Long.valueOf(0)})); 128 } 129 130 /* 131 * This constant defines icon size recommended for using. 132 * Apparently, we should use XGetIconSizes which should 133 * return icon sizes would be most appreciated by the WM. 134 * However, XGetIconSizes always returns 0 for some reason. 135 * So the constant has been introduced. 136 */ 137 private static final int PREFERRED_SIZE_FOR_ICON = 128; 138 139 /* 140 * Sometimes XChangeProperty(_NET_WM_ICON) doesn't work if 141 * image buffer is too large. This constant holds maximum 142 * length of buffer which can be used with _NET_WM_ICON hint. 143 * It holds int's value. 144 */ 145 private static final int MAXIMUM_BUFFER_LENGTH_NET_WM_ICON = (2<<15) - 1; 146 147 void preInit(XCreateWindowParams params) { 148 target = (Component)params.get(TARGET); 149 windowType = ((Window)target).getType(); 150 params.put(REPARENTED, 151 Boolean.valueOf(isOverrideRedirect() || isSimpleWindow())); 152 super.preInit(params); 153 params.putIfNull(BIT_GRAVITY, Integer.valueOf(XConstants.NorthWestGravity)); 154 155 long eventMask = 0; 156 if (params.containsKey(EVENT_MASK)) { 157 eventMask = ((Long)params.get(EVENT_MASK)); 158 } 159 eventMask |= XConstants.VisibilityChangeMask; 160 params.put(EVENT_MASK, eventMask); 161 162 XA_NET_WM_STATE = XAtom.get("_NET_WM_STATE"); 163 164 165 params.put(OVERRIDE_REDIRECT, Boolean.valueOf(isOverrideRedirect())); 166 167 SunToolkit.awtLock(); 168 try { 169 windows.add(this); 170 } finally { 171 SunToolkit.awtUnlock(); 172 } 173 174 cachedFocusableWindow = isFocusableWindow(); 175 176 Font f = target.getFont(); 177 if (f == null) { 178 f = XWindow.getDefaultFont(); 179 target.setFont(f); 180 // we should not call setFont because it will call a repaint 181 // which the peer may not be ready to do yet. 182 } 183 Color c = target.getBackground(); 184 if (c == null) { 185 Color background = SystemColor.window; 186 target.setBackground(background); 187 // we should not call setBackGround because it will call a repaint 188 // which the peer may not be ready to do yet. 189 } 190 c = target.getForeground(); 191 if (c == null) { 192 target.setForeground(SystemColor.windowText); 193 // we should not call setForeGround because it will call a repaint 194 // which the peer may not be ready to do yet. 195 } 196 197 alwaysOnTop = ((Window)target).isAlwaysOnTop() && ((Window)target).isAlwaysOnTopSupported(); 198 199 GraphicsConfiguration gc = getGraphicsConfiguration(); 200 ((X11GraphicsDevice)gc.getDevice()).addDisplayChangedListener(this); 201 } 202 203 protected String getWMName() { 204 String name = target.getName(); 205 if (name == null || name.trim().equals("")) { 206 name = " "; 207 } 208 return name; 209 } 210 211 private static native String getLocalHostname(); 212 private static native int getJvmPID(); 213 214 void postInit(XCreateWindowParams params) { 215 super.postInit(params); 216 217 // Init WM_PROTOCOLS atom 218 initWMProtocols(); 219 220 // Set _NET_WM_PID and WM_CLIENT_MACHINE using this JVM 221 XAtom.get("WM_CLIENT_MACHINE").setProperty(getWindow(), getLocalHostname()); 222 XAtom.get("_NET_WM_PID").setCard32Property(getWindow(), getJvmPID()); 223 224 // Set WM_TRANSIENT_FOR and group_leader 225 Window t_window = (Window)target; 226 Window owner = t_window.getOwner(); 227 if (owner != null) { 228 ownerPeer = (XWindowPeer)owner.getPeer(); 229 if (focusLog.isLoggable(PlatformLogger.FINER)) { 230 focusLog.fine("Owner is " + owner); 231 focusLog.fine("Owner peer is " + ownerPeer); 232 focusLog.fine("Owner X window " + Long.toHexString(ownerPeer.getWindow())); 233 focusLog.fine("Owner content X window " + Long.toHexString(ownerPeer.getContentWindow())); 234 } 235 // as owner window may be an embedded window, we must get a toplevel window 236 // to set as TRANSIENT_FOR hint 237 long ownerWindow = ownerPeer.getWindow(); 238 if (ownerWindow != 0) { 239 XToolkit.awtLock(); 240 try { 241 // Set WM_TRANSIENT_FOR 242 if (focusLog.isLoggable(PlatformLogger.FINE)) focusLog.fine("Setting transient on " + Long.toHexString(getWindow()) 243 + " for " + Long.toHexString(ownerWindow)); 244 setToplevelTransientFor(this, ownerPeer, false, true); 245 246 // Set group leader 247 XWMHints hints = getWMHints(); 248 hints.set_flags(hints.get_flags() | (int)XUtilConstants.WindowGroupHint); 249 hints.set_window_group(ownerWindow); 250 XlibWrapper.XSetWMHints(XToolkit.getDisplay(), getWindow(), hints.pData); 251 } 252 finally { 253 XToolkit.awtUnlock(); 254 } 255 } 256 } 257 258 // Init warning window(for applets) 259 if (((Window)target).getWarningString() != null) { 260 // accessSystemTray permission allows to display TrayIcon, TrayIcon tooltip 261 // and TrayIcon balloon windows without a warning window. 262 if (!AWTAccessor.getWindowAccessor().isTrayIconWindow((Window)target)) { 263 warningWindow = new XWarningWindow((Window)target, getWindow(), this); 264 } 265 } 266 267 setSaveUnder(true); 268 269 updateIconImages(); 270 271 updateShape(); 272 updateOpacity(); 273 // no need in updateOpaque() as it is no-op 274 } 275 276 public void updateIconImages() { 277 Window target = (Window)this.target; 278 java.util.List<Image> iconImages = ((Window)target).getIconImages(); 279 XWindowPeer ownerPeer = getOwnerPeer(); 280 winAttr.icons = new ArrayList<XIconInfo>(); 281 if (iconImages.size() != 0) { 282 //read icon images from target 283 winAttr.iconsInherited = false; 284 for (Iterator<Image> i = iconImages.iterator(); i.hasNext(); ) { 285 Image image = i.next(); 286 if (image == null) { 287 if (log.isLoggable(PlatformLogger.FINEST)) { 288 log.finest("XWindowPeer.updateIconImages: Skipping the image passed into Java because it's null."); 289 } 290 continue; 291 } 292 XIconInfo iconInfo; 293 try { 294 iconInfo = new XIconInfo(image); 295 } catch (Exception e){ 296 if (log.isLoggable(PlatformLogger.FINEST)) { 297 log.finest("XWindowPeer.updateIconImages: Perhaps the image passed into Java is broken. Skipping this icon."); 298 } 299 continue; 300 } 301 if (iconInfo.isValid()) { 302 winAttr.icons.add(iconInfo); 303 } 304 } 305 } 306 307 // Fix for CR#6425089 308 winAttr.icons = normalizeIconImages(winAttr.icons); 309 310 if (winAttr.icons.size() == 0) { 311 //target.icons is empty or all icon images are broken 312 if (ownerPeer != null) { 313 //icon is inherited from parent 314 winAttr.iconsInherited = true; 315 winAttr.icons = ownerPeer.getIconInfo(); 316 } else { 317 //default icon is used 318 winAttr.iconsInherited = false; 319 winAttr.icons = getDefaultIconInfo(); 320 } 321 } 322 recursivelySetIcon(winAttr.icons); 323 } 324 325 /* 326 * Sometimes XChangeProperty(_NET_WM_ICON) doesn't work if 327 * image buffer is too large. This function help us accommodate 328 * initial list of the icon images to certainly-acceptable. 329 * It does scale some of these icons to appropriate size 330 * if it's necessary. 331 */ 332 static java.util.List<XIconInfo> normalizeIconImages(java.util.List<XIconInfo> icons) { 333 java.util.List<XIconInfo> result = new ArrayList<XIconInfo>(); 334 int totalLength = 0; 335 boolean haveLargeIcon = false; 336 337 for (XIconInfo icon : icons) { 338 int width = icon.getWidth(); 339 int height = icon.getHeight(); 340 int length = icon.getRawLength(); 341 342 if (width > PREFERRED_SIZE_FOR_ICON || height > PREFERRED_SIZE_FOR_ICON) { 343 if (haveLargeIcon) { 344 continue; 345 } 346 int scaledWidth = width; 347 int scaledHeight = height; 348 while (scaledWidth > PREFERRED_SIZE_FOR_ICON || 349 scaledHeight > PREFERRED_SIZE_FOR_ICON) { 350 scaledWidth = scaledWidth / 2; 351 scaledHeight = scaledHeight / 2; 352 } 353 354 icon.setScaledSize(scaledWidth, scaledHeight); 355 length = icon.getRawLength(); 356 } 357 358 if (totalLength + length <= MAXIMUM_BUFFER_LENGTH_NET_WM_ICON) { 359 totalLength += length; 360 result.add(icon); 361 if (width > PREFERRED_SIZE_FOR_ICON || height > PREFERRED_SIZE_FOR_ICON) { 362 haveLargeIcon = true; 363 } 364 } 365 } 366 367 if (iconLog.isLoggable(PlatformLogger.FINEST)) { 368 iconLog.finest(">>> Length_ of buffer of icons data: " + totalLength + 369 ", maximum length: " + MAXIMUM_BUFFER_LENGTH_NET_WM_ICON); 370 } 371 372 return result; 373 } 374 375 /* 376 * Dumps each icon from the list 377 */ 378 static void dumpIcons(java.util.List<XIconInfo> icons) { 379 if (iconLog.isLoggable(PlatformLogger.FINEST)) { 380 iconLog.finest(">>> Sizes of icon images:"); 381 for (Iterator<XIconInfo> i = icons.iterator(); i.hasNext(); ) { 382 iconLog.finest(" {0}", i.next()); 383 } 384 } 385 } 386 387 public void recursivelySetIcon(java.util.List<XIconInfo> icons) { 388 dumpIcons(winAttr.icons); 389 setIconHints(icons); 390 Window target = (Window)this.target; 391 Window[] children = target.getOwnedWindows(); 392 int cnt = children.length; 393 for (int i = 0; i < cnt; i++) { 394 ComponentPeer childPeer = children[i].getPeer(); 395 if (childPeer != null && childPeer instanceof XWindowPeer) { 396 if (((XWindowPeer)childPeer).winAttr.iconsInherited) { 397 ((XWindowPeer)childPeer).winAttr.icons = icons; 398 ((XWindowPeer)childPeer).recursivelySetIcon(icons); 399 } 400 } 401 } 402 } 403 404 java.util.List<XIconInfo> getIconInfo() { 405 return winAttr.icons; 406 } 407 void setIconHints(java.util.List<XIconInfo> icons) { 408 //This does nothing for XWindowPeer, 409 //It's overriden in XDecoratedPeer 410 } 411 412 private static ArrayList<XIconInfo> defaultIconInfo; 413 protected synchronized static java.util.List<XIconInfo> getDefaultIconInfo() { 414 if (defaultIconInfo == null) { 415 defaultIconInfo = new ArrayList<XIconInfo>(); 416 if (XlibWrapper.dataModel == 32) { 417 defaultIconInfo.add(new XIconInfo(XAWTIcon32_java_icon16_png.java_icon16_png)); 418 defaultIconInfo.add(new XIconInfo(XAWTIcon32_java_icon24_png.java_icon24_png)); 419 defaultIconInfo.add(new XIconInfo(XAWTIcon32_java_icon32_png.java_icon32_png)); 420 defaultIconInfo.add(new XIconInfo(XAWTIcon32_java_icon48_png.java_icon48_png)); 421 } else { 422 defaultIconInfo.add(new XIconInfo(XAWTIcon64_java_icon16_png.java_icon16_png)); 423 defaultIconInfo.add(new XIconInfo(XAWTIcon64_java_icon24_png.java_icon24_png)); 424 defaultIconInfo.add(new XIconInfo(XAWTIcon64_java_icon32_png.java_icon32_png)); 425 defaultIconInfo.add(new XIconInfo(XAWTIcon64_java_icon48_png.java_icon48_png)); 426 } 427 } 428 return defaultIconInfo; 429 } 430 431 private void updateShape() { 432 // Shape shape = ((Window)target).getShape(); 433 Shape shape = AWTAccessor.getWindowAccessor().getShape((Window)target); 434 if (shape != null) { 435 applyShape(Region.getInstance(shape, null)); 436 } 437 } 438 439 private void updateOpacity() { 440 // float opacity = ((Window)target).getOpacity(); 441 float opacity = AWTAccessor.getWindowAccessor().getOpacity((Window)target); 442 if (opacity < 1.0f) { 443 setOpacity(opacity); 444 } 445 } 446 447 public void updateMinimumSize() { 448 //This function only saves minimumSize value in XWindowPeer 449 //Setting WMSizeHints is implemented in XDecoratedPeer 450 targetMinimumSize = (((Component)target).isMinimumSizeSet()) ? 451 ((Component)target).getMinimumSize() : null; 452 } 453 454 public Dimension getTargetMinimumSize() { 455 return (targetMinimumSize == null) ? null : new Dimension(targetMinimumSize); 456 } 457 458 public XWindowPeer getOwnerPeer() { 459 return ownerPeer; 460 } 461 462 //Fix for 6318144: PIT:Setting Min Size bigger than current size enlarges 463 //the window but fails to revalidate, Sol-CDE 464 //This bug is regression for 465 //5025858: Resizing a decorated frame triggers componentResized event twice. 466 //Since events are not posted from Component.setBounds we need to send them here. 467 //Note that this function is overriden in XDecoratedPeer so event 468 //posting is not changing for decorated peers 469 public void setBounds(int x, int y, int width, int height, int op) { 470 XToolkit.awtLock(); 471 try { 472 Rectangle oldBounds = getBounds(); 473 474 super.setBounds(x, y, width, height, op); 475 476 Rectangle bounds = getBounds(); 477 478 XSizeHints hints = getHints(); 479 setSizeHints(hints.get_flags() | XUtilConstants.PPosition | XUtilConstants.PSize, 480 bounds.x, bounds.y, bounds.width, bounds.height); 481 XWM.setMotifDecor(this, false, 0, 0); 482 483 XNETProtocol protocol = XWM.getWM().getNETProtocol(); 484 if (protocol != null && protocol.active()) { 485 XAtomList net_wm_state = getNETWMState(); 486 net_wm_state.add(protocol.XA_NET_WM_STATE_SKIP_TASKBAR); 487 setNETWMState(net_wm_state); 488 } 489 490 491 boolean isResized = !bounds.getSize().equals(oldBounds.getSize()); 492 boolean isMoved = !bounds.getLocation().equals(oldBounds.getLocation()); 493 if (isMoved || isResized) { 494 repositionSecurityWarning(); 495 } 496 if (isResized) { 497 postEventToEventQueue(new ComponentEvent(getEventSource(), ComponentEvent.COMPONENT_RESIZED)); 498 } 499 if (isMoved) { 500 postEventToEventQueue(new ComponentEvent(getEventSource(), ComponentEvent.COMPONENT_MOVED)); 501 } 502 } finally { 503 XToolkit.awtUnlock(); 504 } 505 } 506 507 void updateFocusability() { 508 updateFocusableWindowState(); 509 XToolkit.awtLock(); 510 try { 511 XWMHints hints = getWMHints(); 512 hints.set_flags(hints.get_flags() | (int)XUtilConstants.InputHint); 513 hints.set_input(false/*isNativelyNonFocusableWindow() ? (0):(1)*/); 514 XlibWrapper.XSetWMHints(XToolkit.getDisplay(), getWindow(), hints.pData); 515 } 516 finally { 517 XToolkit.awtUnlock(); 518 } 519 } 520 521 public Insets getInsets() { 522 return new Insets(0, 0, 0, 0); 523 } 524 525 // NOTE: This method may be called by privileged threads. 526 // DO NOT INVOKE CLIENT CODE ON THIS THREAD! 527 public void handleIconify() { 528 postEvent(new WindowEvent((Window)target, WindowEvent.WINDOW_ICONIFIED)); 529 } 530 531 // NOTE: This method may be called by privileged threads. 532 // DO NOT INVOKE CLIENT CODE ON THIS THREAD! 533 public void handleDeiconify() { 534 postEvent(new WindowEvent((Window)target, WindowEvent.WINDOW_DEICONIFIED)); 535 } 536 537 // NOTE: This method may be called by privileged threads. 538 // DO NOT INVOKE CLIENT CODE ON THIS THREAD! 539 public void handleStateChange(int oldState, int newState) { 540 postEvent(new WindowEvent((Window)target, 541 WindowEvent.WINDOW_STATE_CHANGED, 542 oldState, newState)); 543 } 544 545 /** 546 * DEPRECATED: Replaced by getInsets(). 547 */ 548 public Insets insets() { 549 return getInsets(); 550 } 551 552 boolean isAutoRequestFocus() { 553 if (XToolkit.isToolkitThread()) { 554 return AWTAccessor.getWindowAccessor().isAutoRequestFocus((Window)target); 555 } else { 556 return ((Window)target).isAutoRequestFocus(); 557 } 558 } 559 560 /* 561 * Retrives real native focused window and converts it into Java peer. 562 */ 563 static XWindowPeer getNativeFocusedWindowPeer() { 564 XBaseWindow baseWindow = XToolkit.windowToXWindow(xGetInputFocus()); 565 return (baseWindow instanceof XWindowPeer) ? (XWindowPeer)baseWindow : 566 (baseWindow instanceof XFocusProxyWindow) ? 567 ((XFocusProxyWindow)baseWindow).getOwner() : null; 568 } 569 570 /* 571 * Retrives real native focused window and converts it into Java window. 572 */ 573 static Window getNativeFocusedWindow() { 574 XWindowPeer peer = getNativeFocusedWindowPeer(); 575 return peer != null ? (Window)peer.target : null; 576 } 577 578 boolean isFocusableWindow() { 579 if (XToolkit.isToolkitThread() || SunToolkit.isAWTLockHeldByCurrentThread()) 580 { 581 return cachedFocusableWindow; 582 } else { 583 return ((Window)target).isFocusableWindow(); 584 } 585 } 586 587 /* WARNING: don't call client code in this method! */ 588 boolean isFocusedWindowModalBlocker() { 589 return false; 590 } 591 592 long getFocusTargetWindow() { 593 return getContentWindow(); 594 } 595 596 /** 597 * Returns whether or not this window peer has native X window 598 * configured as non-focusable window. It might happen if: 599 * - Java window is non-focusable 600 * - Java window is simple Window(not Frame or Dialog) 601 */ 602 boolean isNativelyNonFocusableWindow() { 603 if (XToolkit.isToolkitThread() || SunToolkit.isAWTLockHeldByCurrentThread()) 604 { 605 return isSimpleWindow() || !cachedFocusableWindow; 606 } else { 607 return isSimpleWindow() || !(((Window)target).isFocusableWindow()); 608 } 609 } 610 611 public void handleWindowFocusIn_Dispatch() { 612 if (EventQueue.isDispatchThread()) { 613 XKeyboardFocusManagerPeer.setCurrentNativeFocusedWindow((Window) target); 614 WindowEvent we = new WindowEvent((Window)target, WindowEvent.WINDOW_GAINED_FOCUS); 615 SunToolkit.setSystemGenerated(we); 616 target.dispatchEvent(we); 617 } 618 } 619 620 public void handleWindowFocusInSync(long serial) { 621 WindowEvent we = new WindowEvent((Window)target, WindowEvent.WINDOW_GAINED_FOCUS); 622 XKeyboardFocusManagerPeer.setCurrentNativeFocusedWindow((Window) target); 623 sendEvent(we); 624 } 625 // NOTE: This method may be called by privileged threads. 626 // DO NOT INVOKE CLIENT CODE ON THIS THREAD! 627 public void handleWindowFocusIn(long serial) { 628 WindowEvent we = new WindowEvent((Window)target, WindowEvent.WINDOW_GAINED_FOCUS); 629 /* wrap in Sequenced, then post*/ 630 XKeyboardFocusManagerPeer.setCurrentNativeFocusedWindow((Window) target); 631 postEvent(wrapInSequenced((AWTEvent) we)); 632 } 633 634 // NOTE: This method may be called by privileged threads. 635 // DO NOT INVOKE CLIENT CODE ON THIS THREAD! 636 public void handleWindowFocusOut(Window oppositeWindow, long serial) { 637 WindowEvent we = new WindowEvent((Window)target, WindowEvent.WINDOW_LOST_FOCUS, oppositeWindow); 638 XKeyboardFocusManagerPeer.setCurrentNativeFocusedWindow(null); 639 XKeyboardFocusManagerPeer.setCurrentNativeFocusOwner(null); 640 /* wrap in Sequenced, then post*/ 641 postEvent(wrapInSequenced((AWTEvent) we)); 642 } 643 public void handleWindowFocusOutSync(Window oppositeWindow, long serial) { 644 WindowEvent we = new WindowEvent((Window)target, WindowEvent.WINDOW_LOST_FOCUS, oppositeWindow); 645 XKeyboardFocusManagerPeer.setCurrentNativeFocusedWindow(null); 646 XKeyboardFocusManagerPeer.setCurrentNativeFocusOwner(null); 647 sendEvent(we); 648 } 649 650 /* --- DisplayChangedListener Stuff --- */ 651 652 /* Xinerama 653 * called to check if we've been moved onto a different screen 654 * Based on checkNewXineramaScreen() in awt_GraphicsEnv.c 655 */ 656 public void checkIfOnNewScreen(Rectangle newBounds) { 657 if (!XToolkit.localEnv.runningXinerama()) { 658 return; 659 } 660 661 if (log.isLoggable(PlatformLogger.FINEST)) { 662 log.finest("XWindowPeer: Check if we've been moved to a new screen since we're running in Xinerama mode"); 663 } 664 665 int area = newBounds.width * newBounds.height; 666 int intAmt, vertAmt, horizAmt; 667 int largestAmt = 0; 668 int curScreenNum = ((X11GraphicsDevice)getGraphicsConfiguration().getDevice()).getScreen(); 669 int newScreenNum = 0; 670 GraphicsDevice gds[] = XToolkit.localEnv.getScreenDevices(); 671 GraphicsConfiguration newGC = null; 672 Rectangle screenBounds; 673 674 for (int i = 0; i < gds.length; i++) { 675 screenBounds = gds[i].getDefaultConfiguration().getBounds(); 676 if (newBounds.intersects(screenBounds)) { 677 horizAmt = Math.min(newBounds.x + newBounds.width, 678 screenBounds.x + screenBounds.width) - 679 Math.max(newBounds.x, screenBounds.x); 680 vertAmt = Math.min(newBounds.y + newBounds.height, 681 screenBounds.y + screenBounds.height)- 682 Math.max(newBounds.y, screenBounds.y); 683 intAmt = horizAmt * vertAmt; 684 if (intAmt == area) { 685 // Completely on this screen - done! 686 newScreenNum = i; 687 newGC = gds[i].getDefaultConfiguration(); 688 break; 689 } 690 if (intAmt > largestAmt) { 691 largestAmt = intAmt; 692 newScreenNum = i; 693 newGC = gds[i].getDefaultConfiguration(); 694 } 695 } 696 } 697 if (newScreenNum != curScreenNum) { 698 if (log.isLoggable(PlatformLogger.FINEST)) { 699 log.finest("XWindowPeer: Moved to a new screen"); 700 } 701 executeDisplayChangedOnEDT(newGC); 702 } 703 } 704 705 /** 706 * Helper method that executes the displayChanged(screen) method on 707 * the event dispatch thread. This method is used in the Xinerama case 708 * and after display mode change events. 709 */ 710 private void executeDisplayChangedOnEDT(final GraphicsConfiguration gc) { 711 Runnable dc = new Runnable() { 712 public void run() { 713 AWTAccessor.getComponentAccessor(). 714 setGraphicsConfiguration((Component)target, gc); 715 } 716 }; 717 SunToolkit.executeOnEventHandlerThread((Component)target, dc); 718 } 719 720 /** 721 * From the DisplayChangedListener interface; called from 722 * X11GraphicsDevice when the display mode has been changed. 723 */ 724 public void displayChanged() { 725 executeDisplayChangedOnEDT(getGraphicsConfiguration()); 726 } 727 728 /** 729 * From the DisplayChangedListener interface; top-levels do not need 730 * to react to this event. 731 */ 732 public void paletteChanged() { 733 } 734 735 /* 736 * Overridden to check if we need to update our GraphicsDevice/Config 737 * Added for 4934052. 738 */ 739 @Override 740 public void handleConfigureNotifyEvent(XEvent xev) { 741 // TODO: We create an XConfigureEvent every time we override 742 // handleConfigureNotify() - too many! 743 XConfigureEvent xe = xev.get_xconfigure(); 744 checkIfOnNewScreen(new Rectangle(xe.get_x(), 745 xe.get_y(), 746 xe.get_width(), 747 xe.get_height())); 748 749 // Don't call super until we've handled a screen change. Otherwise 750 // there could be a race condition in which a ComponentListener could 751 // see the old screen. 752 super.handleConfigureNotifyEvent(xev); 753 repositionSecurityWarning(); 754 } 755 756 final void requestXFocus(long time) { 757 requestXFocus(time, true); 758 } 759 760 final void requestXFocus() { 761 requestXFocus(0, false); 762 } 763 764 /** 765 * Requests focus to this top-level. Descendants should override to provide 766 * implementations based on a class of top-level. 767 */ 768 protected void requestXFocus(long time, boolean timeProvided) { 769 // Since in XAWT focus is synthetic and all basic Windows are 770 // override_redirect all we can do is check whether our parent 771 // is active. If it is - we can freely synthesize focus transfer. 772 // Luckily, this logic is already implemented in requestWindowFocus. 773 if (focusLog.isLoggable(PlatformLogger.FINE)) focusLog.fine("Requesting window focus"); 774 requestWindowFocus(time, timeProvided); 775 } 776 777 public final boolean focusAllowedFor() { 778 if (isNativelyNonFocusableWindow()) { 779 return false; 780 } 781 /* 782 Window target = (Window)this.target; 783 if (!target.isVisible() || 784 !target.isEnabled() || 785 !target.isFocusable()) 786 { 787 return false; 788 } 789 */ 790 if (isModalBlocked()) { 791 return false; 792 } 793 return true; 794 } 795 796 public void handleFocusEvent(XEvent xev) { 797 XFocusChangeEvent xfe = xev.get_xfocus(); 798 FocusEvent fe; 799 focusLog.fine("{0}", xfe); 800 if (isEventDisabled(xev)) { 801 return; 802 } 803 if (xev.get_type() == XConstants.FocusIn) 804 { 805 // If this window is non-focusable don't post any java focus event 806 if (focusAllowedFor()) { 807 if (xfe.get_mode() == XConstants.NotifyNormal // Normal notify 808 || xfe.get_mode() == XConstants.NotifyWhileGrabbed) // Alt-Tab notify 809 { 810 handleWindowFocusIn(xfe.get_serial()); 811 } 812 } 813 } 814 else 815 { 816 if (xfe.get_mode() == XConstants.NotifyNormal // Normal notify 817 || xfe.get_mode() == XConstants.NotifyWhileGrabbed) // Alt-Tab notify 818 { 819 // If this window is non-focusable don't post any java focus event 820 if (!isNativelyNonFocusableWindow()) { 821 XWindowPeer oppositeXWindow = getNativeFocusedWindowPeer(); 822 Object oppositeTarget = (oppositeXWindow!=null)? oppositeXWindow.getTarget() : null; 823 Window oppositeWindow = null; 824 if (oppositeTarget instanceof Window) { 825 oppositeWindow = (Window) oppositeTarget; 826 } 827 // Check if opposite window is non-focusable. In that case we don't want to 828 // post any event. 829 if (oppositeXWindow != null && oppositeXWindow.isNativelyNonFocusableWindow()) { 830 return; 831 } 832 if (this == oppositeXWindow) { 833 oppositeWindow = null; 834 } else if (oppositeXWindow instanceof XDecoratedPeer) { 835 if (((XDecoratedPeer) oppositeXWindow).actualFocusedWindow != null) { 836 oppositeXWindow = ((XDecoratedPeer) oppositeXWindow).actualFocusedWindow; 837 oppositeTarget = oppositeXWindow.getTarget(); 838 if (oppositeTarget instanceof Window 839 && oppositeXWindow.isVisible() 840 && oppositeXWindow.isNativelyNonFocusableWindow()) 841 { 842 oppositeWindow = ((Window) oppositeTarget); 843 } 844 } 845 } 846 handleWindowFocusOut(oppositeWindow, xfe.get_serial()); 847 } 848 } 849 } 850 } 851 852 void setSaveUnder(boolean state) {} 853 854 public void toFront() { 855 if (isOverrideRedirect() && mustControlStackPosition) { 856 mustControlStackPosition = false; 857 removeRootPropertyEventDispatcher(); 858 } 859 if (isVisible()) { 860 super.toFront(); 861 if (isFocusableWindow() && isAutoRequestFocus() && 862 !isModalBlocked() && !isWithdrawn()) 863 { 864 requestInitialFocus(); 865 } 866 } else { 867 setVisible(true); 868 } 869 } 870 871 public void toBack() { 872 XToolkit.awtLock(); 873 try { 874 if(!isOverrideRedirect()) { 875 XlibWrapper.XLowerWindow(XToolkit.getDisplay(), getWindow()); 876 }else{ 877 lowerOverrideRedirect(); 878 } 879 } 880 finally { 881 XToolkit.awtUnlock(); 882 } 883 } 884 private void lowerOverrideRedirect() { 885 // 886 // make new hash of toplevels of all windows from 'windows' hash. 887 // FIXME: do not call them "toplevel" as it is misleading. 888 // 889 HashSet toplevels = new HashSet(); 890 long topl = 0, mytopl = 0; 891 892 for (XWindowPeer xp : windows) { 893 topl = getToplevelWindow( xp.getWindow() ); 894 if( xp.equals( this ) ) { 895 mytopl = topl; 896 } 897 if( topl > 0 ) 898 toplevels.add( Long.valueOf( topl ) ); 899 } 900 901 // 902 // find in the root's tree: 903 // (1) my toplevel, (2) lowest java toplevel, (3) desktop 904 // We must enforce (3), (1), (2) order, upward; 905 // note that nautilus on the next restacking will do (1),(3),(2). 906 // 907 long laux, wDesktop = -1, wBottom = -1; 908 int iMy = -1, iDesktop = -1, iBottom = -1; 909 int i = 0; 910 XQueryTree xqt = new XQueryTree(XToolkit.getDefaultRootWindow()); 911 try { 912 if( xqt.execute() > 0 ) { 913 int nchildren = xqt.get_nchildren(); 914 long children = xqt.get_children(); 915 for(i = 0; i < nchildren; i++) { 916 laux = Native.getWindow(children, i); 917 if( laux == mytopl ) { 918 iMy = i; 919 }else if( isDesktopWindow( laux ) ) { 920 // we need topmost desktop of them all. 921 iDesktop = i; 922 wDesktop = laux; 923 }else if(iBottom < 0 && 924 toplevels.contains( Long.valueOf(laux) ) && 925 laux != mytopl) { 926 iBottom = i; 927 wBottom = laux; 928 } 929 } 930 } 931 932 if( (iMy < iBottom || iBottom < 0 )&& iDesktop < iMy) 933 return; // no action necessary 934 935 long to_restack = Native.allocateLongArray(2); 936 Native.putLong(to_restack, 0, wBottom); 937 Native.putLong(to_restack, 1, mytopl); 938 XlibWrapper.XRestackWindows(XToolkit.getDisplay(), to_restack, 2); 939 XlibWrapper.unsafe.freeMemory(to_restack); 940 941 942 if( !mustControlStackPosition ) { 943 mustControlStackPosition = true; 944 // add root window property listener: 945 // somebody (eg nautilus desktop) may obscure us 946 addRootPropertyEventDispatcher(); 947 } 948 } finally { 949 xqt.dispose(); 950 } 951 } 952 /** 953 Get XID of closest to root window in a given window hierarchy. 954 FIXME: do not call it "toplevel" as it is misleading. 955 On error return 0. 956 */ 957 private long getToplevelWindow( long w ) { 958 long wi = w, ret, root; 959 do { 960 ret = wi; 961 XQueryTree qt = new XQueryTree(wi); 962 try { 963 if (qt.execute() == 0) { 964 return 0; 965 } 966 root = qt.get_root(); 967 wi = qt.get_parent(); 968 } finally { 969 qt.dispose(); 970 } 971 972 } while (wi != root); 973 974 return ret; 975 } 976 977 private static boolean isDesktopWindow( long wi ) { 978 return XWM.getWM().isDesktopWindow( wi ); 979 } 980 981 private void updateAlwaysOnTop() { 982 log.fine("Promoting always-on-top state {0}", Boolean.valueOf(alwaysOnTop)); 983 XWM.getWM().setLayer(this, 984 alwaysOnTop ? 985 XLayerProtocol.LAYER_ALWAYS_ON_TOP : 986 XLayerProtocol.LAYER_NORMAL); 987 } 988 989 public void setAlwaysOnTop(boolean alwaysOnTop) { 990 this.alwaysOnTop = alwaysOnTop; 991 updateAlwaysOnTop(); 992 } 993 994 boolean isLocationByPlatform() { 995 return locationByPlatform; 996 } 997 998 private void promoteDefaultPosition() { 999 this.locationByPlatform = ((Window)target).isLocationByPlatform(); 1000 if (locationByPlatform) { 1001 XToolkit.awtLock(); 1002 try { 1003 Rectangle bounds = getBounds(); 1004 XSizeHints hints = getHints(); 1005 setSizeHints(hints.get_flags() & ~(XUtilConstants.USPosition | XUtilConstants.PPosition), 1006 bounds.x, bounds.y, bounds.width, bounds.height); 1007 } finally { 1008 XToolkit.awtUnlock(); 1009 } 1010 } 1011 } 1012 1013 public void setVisible(boolean vis) { 1014 if (!isVisible() && vis) { 1015 isBeforeFirstMapNotify = true; 1016 winAttr.initialFocus = isAutoRequestFocus(); 1017 if (!winAttr.initialFocus) { 1018 /* 1019 * It's easier and safer to temporary suppress WM_TAKE_FOCUS 1020 * protocol itself than to ignore WM_TAKE_FOCUS client message. 1021 * Because we will have to make the difference between 1022 * the message come after showing and the message come after 1023 * activation. Also, on Metacity, for some reason, we have _two_ 1024 * WM_TAKE_FOCUS client messages when showing a frame/dialog. 1025 */ 1026 suppressWmTakeFocus(true); 1027 } 1028 } 1029 updateFocusability(); 1030 promoteDefaultPosition(); 1031 if (!vis && warningWindow != null) { 1032 warningWindow.setSecurityWarningVisible(false, false); 1033 } 1034 super.setVisible(vis); 1035 if (!vis && !isWithdrawn()) { 1036 // ICCCM, 4.1.4. Changing Window State: 1037 // "Iconic -> Withdrawn - The client should unmap the window and follow it 1038 // with a synthetic UnmapNotify event as described later in this section." 1039 // The same is true for Normal -> Withdrawn 1040 XToolkit.awtLock(); 1041 try { 1042 XUnmapEvent unmap = new XUnmapEvent(); 1043 unmap.set_window(window); 1044 unmap.set_event(XToolkit.getDefaultRootWindow()); 1045 unmap.set_type((int)XConstants.UnmapNotify); 1046 unmap.set_from_configure(false); 1047 XlibWrapper.XSendEvent(XToolkit.getDisplay(), XToolkit.getDefaultRootWindow(), 1048 false, XConstants.SubstructureNotifyMask | XConstants.SubstructureRedirectMask, 1049 unmap.pData); 1050 unmap.dispose(); 1051 } 1052 finally { 1053 XToolkit.awtUnlock(); 1054 } 1055 } 1056 // method called somewhere in parent does not generate configure-notify 1057 // event for override-redirect. 1058 // Ergo, no reshape and bugs like 5085647 in case setBounds was 1059 // called before setVisible. 1060 if (isOverrideRedirect() && vis) { 1061 updateChildrenSizes(); 1062 } 1063 repositionSecurityWarning(); 1064 } 1065 1066 protected void suppressWmTakeFocus(boolean doSuppress) { 1067 } 1068 1069 final boolean isSimpleWindow() { 1070 return !(target instanceof Frame || target instanceof Dialog); 1071 } 1072 boolean hasWarningWindow() { 1073 return ((Window)target).getWarningString() != null; 1074 } 1075 1076 // The height of menu bar window 1077 int getMenuBarHeight() { 1078 return 0; 1079 } 1080 1081 // Called when shell changes its size and requires children windows 1082 // to update their sizes appropriately 1083 void updateChildrenSizes() { 1084 } 1085 1086 public void repositionSecurityWarning() { 1087 // NOTE: On KWin if the window/border snapping option is enabled, 1088 // the Java window may be swinging while it's being moved. 1089 // This doesn't make the application unusable though looks quite ugly. 1090 // Probobly we need to find some hint to assign to our Security 1091 // Warning window in order to exclude it from the snapping option. 1092 // We are not currently aware of existance of such a property. 1093 if (warningWindow != null) { 1094 // We can't use the coordinates stored in the XBaseWindow since 1095 // they are zeros for decorated frames. 1096 AWTAccessor.ComponentAccessor compAccessor = AWTAccessor.getComponentAccessor(); 1097 int x = compAccessor.getX(target); 1098 int y = compAccessor.getY(target); 1099 int width = compAccessor.getWidth(target); 1100 int height = compAccessor.getHeight(target); 1101 warningWindow.reposition(x, y, width, height); 1102 } 1103 } 1104 1105 @Override 1106 protected void setMouseAbove(boolean above) { 1107 super.setMouseAbove(above); 1108 updateSecurityWarningVisibility(); 1109 } 1110 1111 @Override 1112 public void setFullScreenExclusiveModeState(boolean state) { 1113 super.setFullScreenExclusiveModeState(state); 1114 updateSecurityWarningVisibility(); 1115 } 1116 1117 public void updateSecurityWarningVisibility() { 1118 if (warningWindow == null) { 1119 return; 1120 } 1121 1122 if (!isVisible()) { 1123 return; // The warning window should already be hidden. 1124 } 1125 1126 boolean show = false; 1127 1128 if (!isFullScreenExclusiveMode()) { 1129 int state = getWMState(); 1130 1131 // getWMState() always returns 0 (Withdrawn) for simple windows. Hence 1132 // we ignore the state for such windows. 1133 if (isVisible() && (state == XUtilConstants.NormalState || isSimpleWindow())) { 1134 if (XKeyboardFocusManagerPeer.getCurrentNativeFocusedWindow() == 1135 getTarget()) 1136 { 1137 show = true; 1138 } 1139 1140 if (isMouseAbove() || warningWindow.isMouseAbove()) 1141 { 1142 show = true; 1143 } 1144 } 1145 } 1146 1147 warningWindow.setSecurityWarningVisible(show, true); 1148 } 1149 1150 boolean isOverrideRedirect() { 1151 return XWM.getWMID() == XWM.OPENLOOK_WM || 1152 Window.Type.POPUP.equals(getWindowType()); 1153 } 1154 1155 final boolean isOLWMDecorBug() { 1156 return XWM.getWMID() == XWM.OPENLOOK_WM && 1157 winAttr.nativeDecor == false; 1158 } 1159 1160 public void dispose() { 1161 SunToolkit.awtLock(); 1162 try { 1163 windows.remove(this); 1164 } finally { 1165 SunToolkit.awtUnlock(); 1166 } 1167 if (warningWindow != null) { 1168 warningWindow.destroy(); 1169 } 1170 removeRootPropertyEventDispatcher(); 1171 mustControlStackPosition = false; 1172 super.dispose(); 1173 1174 /* 1175 * Fix for 6457980. 1176 * When disposing an owned Window we should implicitly 1177 * return focus to its decorated owner because it won't 1178 * receive WM_TAKE_FOCUS. 1179 */ 1180 if (isSimpleWindow()) { 1181 if (target == XKeyboardFocusManagerPeer.getCurrentNativeFocusedWindow()) { 1182 Window owner = getDecoratedOwner((Window)target); 1183 ((XWindowPeer)AWTAccessor.getComponentAccessor().getPeer(owner)).requestWindowFocus(); 1184 } 1185 } 1186 } 1187 boolean isResizable() { 1188 return winAttr.isResizable; 1189 } 1190 1191 public void handleVisibilityEvent(XEvent xev) { 1192 super.handleVisibilityEvent(xev); 1193 XVisibilityEvent ve = xev.get_xvisibility(); 1194 winAttr.visibilityState = ve.get_state(); 1195 // if (ve.get_state() == XlibWrapper.VisibilityUnobscured) { 1196 // // raiseInputMethodWindow 1197 // } 1198 repositionSecurityWarning(); 1199 } 1200 1201 void handleRootPropertyNotify(XEvent xev) { 1202 XPropertyEvent ev = xev.get_xproperty(); 1203 if( mustControlStackPosition && 1204 ev.get_atom() == XAtom.get("_NET_CLIENT_LIST_STACKING").getAtom()){ 1205 // Restore stack order unhadled/spoiled by WM or some app (nautilus). 1206 // As of now, don't use any generic machinery: just 1207 // do toBack() again. 1208 if(isOverrideRedirect()) { 1209 toBack(); 1210 } 1211 } 1212 } 1213 1214 private void removeStartupNotification() { 1215 if (isStartupNotificationRemoved.getAndSet(true)) { 1216 return; 1217 } 1218 1219 final String desktopStartupId = AccessController.doPrivileged(new PrivilegedAction<String>() { 1220 public String run() { 1221 return XToolkit.getEnv("DESKTOP_STARTUP_ID"); 1222 } 1223 }); 1224 if (desktopStartupId == null) { 1225 return; 1226 } 1227 1228 final StringBuilder messageBuilder = new StringBuilder("remove: ID="); 1229 messageBuilder.append('"'); 1230 for (int i = 0; i < desktopStartupId.length(); i++) { 1231 if (desktopStartupId.charAt(i) == '"' || desktopStartupId.charAt(i) == '\\') { 1232 messageBuilder.append('\\'); 1233 } 1234 messageBuilder.append(desktopStartupId.charAt(i)); 1235 } 1236 messageBuilder.append('"'); 1237 messageBuilder.append('\0'); 1238 final byte[] message; 1239 try { 1240 message = messageBuilder.toString().getBytes("UTF-8"); 1241 } catch (UnsupportedEncodingException cannotHappen) { 1242 return; 1243 } 1244 1245 XClientMessageEvent req = null; 1246 1247 XToolkit.awtLock(); 1248 try { 1249 final XAtom netStartupInfoBeginAtom = XAtom.get("_NET_STARTUP_INFO_BEGIN"); 1250 final XAtom netStartupInfoAtom = XAtom.get("_NET_STARTUP_INFO"); 1251 1252 req = new XClientMessageEvent(); 1253 req.set_type(XConstants.ClientMessage); 1254 req.set_window(getWindow()); 1255 req.set_message_type(netStartupInfoBeginAtom.getAtom()); 1256 req.set_format(8); 1257 1258 for (int pos = 0; pos < message.length; pos += 20) { 1259 final int msglen = Math.min(message.length - pos, 20); 1260 int i = 0; 1261 for (; i < msglen; i++) { 1262 XlibWrapper.unsafe.putByte(req.get_data() + i, message[pos + i]); 1263 } 1264 for (; i < 20; i++) { 1265 XlibWrapper.unsafe.putByte(req.get_data() + i, (byte)0); 1266 } 1267 XlibWrapper.XSendEvent(XToolkit.getDisplay(), 1268 XlibWrapper.RootWindow(XToolkit.getDisplay(), getScreenNumber()), 1269 false, 1270 XConstants.PropertyChangeMask, 1271 req.pData); 1272 req.set_message_type(netStartupInfoAtom.getAtom()); 1273 } 1274 } finally { 1275 XToolkit.awtUnlock(); 1276 if (req != null) { 1277 req.dispose(); 1278 } 1279 } 1280 } 1281 1282 public void handleMapNotifyEvent(XEvent xev) { 1283 removeStartupNotification(); 1284 1285 // See 6480534. 1286 isUnhiding |= isWMStateNetHidden(); 1287 1288 super.handleMapNotifyEvent(xev); 1289 if (!winAttr.initialFocus) { 1290 suppressWmTakeFocus(false); // restore the protocol. 1291 /* 1292 * For some reason, on Metacity, a frame/dialog being shown 1293 * without WM_TAKE_FOCUS protocol doesn't get moved to the front. 1294 * So, we do it evidently. 1295 */ 1296 XToolkit.awtLock(); 1297 try { 1298 XlibWrapper.XRaiseWindow(XToolkit.getDisplay(), getWindow()); 1299 } finally { 1300 XToolkit.awtUnlock(); 1301 } 1302 } 1303 if (shouldFocusOnMapNotify()) { 1304 focusLog.fine("Automatically request focus on window"); 1305 requestInitialFocus(); 1306 } 1307 isUnhiding = false; 1308 isBeforeFirstMapNotify = false; 1309 updateAlwaysOnTop(); 1310 1311 synchronized (getStateLock()) { 1312 if (!isMapped) { 1313 isMapped = true; 1314 } 1315 } 1316 } 1317 1318 public void handleUnmapNotifyEvent(XEvent xev) { 1319 super.handleUnmapNotifyEvent(xev); 1320 1321 // On Metacity UnmapNotify comes before PropertyNotify (for _NET_WM_STATE_HIDDEN). 1322 // So we also check for the property later in MapNotify. See 6480534. 1323 isUnhiding |= isWMStateNetHidden(); 1324 1325 synchronized (getStateLock()) { 1326 if (isMapped) { 1327 isMapped = false; 1328 } 1329 } 1330 } 1331 1332 private boolean shouldFocusOnMapNotify() { 1333 boolean res = false; 1334 1335 if (isBeforeFirstMapNotify) { 1336 res = (winAttr.initialFocus || // Window.autoRequestFocus 1337 isFocusedWindowModalBlocker()); 1338 } else { 1339 res = isUnhiding; // Unhiding 1340 } 1341 res = res && 1342 isFocusableWindow() && // General focusability 1343 !isModalBlocked(); // Modality 1344 1345 return res; 1346 } 1347 1348 protected boolean isWMStateNetHidden() { 1349 XNETProtocol protocol = XWM.getWM().getNETProtocol(); 1350 return (protocol != null && protocol.isWMStateNetHidden(this)); 1351 } 1352 1353 protected void requestInitialFocus() { 1354 requestXFocus(); 1355 } 1356 1357 public void addToplevelStateListener(ToplevelStateListener l){ 1358 toplevelStateListeners.add(l); 1359 } 1360 1361 public void removeToplevelStateListener(ToplevelStateListener l){ 1362 toplevelStateListeners.remove(l); 1363 } 1364 1365 /** 1366 * Override this methods to get notifications when top-level window state changes. The state is 1367 * meant in terms of ICCCM: WithdrawnState, IconicState, NormalState 1368 */ 1369 @Override 1370 protected void stateChanged(long time, int oldState, int newState) { 1371 // Fix for 6401700, 6412803 1372 // If this window is modal blocked, it is put into the transient_for 1373 // chain using prevTransientFor and nextTransientFor hints. However, 1374 // the real WM_TRANSIENT_FOR hint shouldn't be set for windows in 1375 // different WM states (except for owner-window relationship), so 1376 // if the window changes its state, its real WM_TRANSIENT_FOR hint 1377 // should be updated accordingly. 1378 updateTransientFor(); 1379 1380 for (ToplevelStateListener topLevelListenerTmp : toplevelStateListeners) { 1381 topLevelListenerTmp.stateChangedICCCM(oldState, newState); 1382 } 1383 1384 updateSecurityWarningVisibility(); 1385 } 1386 1387 boolean isWithdrawn() { 1388 return getWMState() == XUtilConstants.WithdrawnState; 1389 } 1390 1391 boolean hasDecorations(int decor) { 1392 if (!winAttr.nativeDecor) { 1393 return false; 1394 } 1395 else { 1396 int myDecor = winAttr.decorations; 1397 boolean hasBits = ((myDecor & decor) == decor); 1398 if ((myDecor & XWindowAttributesData.AWT_DECOR_ALL) != 0) 1399 return !hasBits; 1400 else 1401 return hasBits; 1402 } 1403 } 1404 1405 void setReparented(boolean newValue) { 1406 super.setReparented(newValue); 1407 XToolkit.awtLock(); 1408 try { 1409 if (isReparented() && delayedModalBlocking) { 1410 addToTransientFors((XDialogPeer) AWTAccessor.getComponentAccessor().getPeer(modalBlocker)); 1411 delayedModalBlocking = false; 1412 } 1413 } finally { 1414 XToolkit.awtUnlock(); 1415 } 1416 } 1417 1418 /* 1419 * Returns a Vector of all Java top-level windows, 1420 * sorted by their current Z-order 1421 */ 1422 static Vector<XWindowPeer> collectJavaToplevels() { 1423 Vector<XWindowPeer> javaToplevels = new Vector<XWindowPeer>(); 1424 Vector<Long> v = new Vector<Long>(); 1425 X11GraphicsEnvironment ge = 1426 (X11GraphicsEnvironment)GraphicsEnvironment.getLocalGraphicsEnvironment(); 1427 GraphicsDevice[] gds = ge.getScreenDevices(); 1428 if (!ge.runningXinerama() && (gds.length > 1)) { 1429 for (GraphicsDevice gd : gds) { 1430 int screen = ((X11GraphicsDevice)gd).getScreen(); 1431 long rootWindow = XlibWrapper.RootWindow(XToolkit.getDisplay(), screen); 1432 v.add(rootWindow); 1433 } 1434 } else { 1435 v.add(XToolkit.getDefaultRootWindow()); 1436 } 1437 final int windowsCount = windows.size(); 1438 while ((v.size() > 0) && (javaToplevels.size() < windowsCount)) { 1439 long win = v.remove(0); 1440 XQueryTree qt = new XQueryTree(win); 1441 try { 1442 if (qt.execute() != 0) { 1443 int nchildren = qt.get_nchildren(); 1444 long children = qt.get_children(); 1445 // XQueryTree returns window children ordered by z-order 1446 for (int i = 0; i < nchildren; i++) { 1447 long child = Native.getWindow(children, i); 1448 XBaseWindow childWindow = XToolkit.windowToXWindow(child); 1449 // filter out Java non-toplevels 1450 if ((childWindow != null) && !(childWindow instanceof XWindowPeer)) { 1451 continue; 1452 } else { 1453 v.add(child); 1454 } 1455 if (childWindow instanceof XWindowPeer) { 1456 XWindowPeer np = (XWindowPeer)childWindow; 1457 javaToplevels.add(np); 1458 // XQueryTree returns windows sorted by their z-order. However, 1459 // if WM has not handled transient for hint for a child window, 1460 // it may appear in javaToplevels before its owner. Move such 1461 // children after their owners. 1462 int k = 0; 1463 XWindowPeer toCheck = javaToplevels.get(k); 1464 while (toCheck != np) { 1465 XWindowPeer toCheckOwnerPeer = toCheck.getOwnerPeer(); 1466 if (toCheckOwnerPeer == np) { 1467 javaToplevels.remove(k); 1468 javaToplevels.add(toCheck); 1469 } else { 1470 k++; 1471 } 1472 toCheck = javaToplevels.get(k); 1473 } 1474 } 1475 } 1476 } 1477 } finally { 1478 qt.dispose(); 1479 } 1480 } 1481 return javaToplevels; 1482 } 1483 1484 public void setModalBlocked(Dialog d, boolean blocked) { 1485 setModalBlocked(d, blocked, null); 1486 } 1487 public void setModalBlocked(Dialog d, boolean blocked, 1488 Vector<XWindowPeer> javaToplevels) 1489 { 1490 XToolkit.awtLock(); 1491 try { 1492 // State lock should always be after awtLock 1493 synchronized(getStateLock()) { 1494 XDialogPeer blockerPeer = (XDialogPeer) AWTAccessor.getComponentAccessor().getPeer(d); 1495 if (blocked) { 1496 log.fine("{0} is blocked by {1}", this, blockerPeer); 1497 modalBlocker = d; 1498 1499 if (isReparented() || XWM.isNonReparentingWM()) { 1500 addToTransientFors(blockerPeer, javaToplevels); 1501 } else { 1502 delayedModalBlocking = true; 1503 } 1504 } else { 1505 if (d != modalBlocker) { 1506 throw new IllegalStateException("Trying to unblock window blocked by another dialog"); 1507 } 1508 modalBlocker = null; 1509 1510 if (isReparented() || XWM.isNonReparentingWM()) { 1511 removeFromTransientFors(); 1512 } else { 1513 delayedModalBlocking = false; 1514 } 1515 } 1516 1517 updateTransientFor(); 1518 } 1519 } finally { 1520 XToolkit.awtUnlock(); 1521 } 1522 } 1523 1524 /* 1525 * Sets the TRANSIENT_FOR hint to the given top-level window. This 1526 * method is used when a window is modal blocked/unblocked or 1527 * changed its state from/to NormalState to/from other states. 1528 * If window or transientForWindow are embedded frames, the containing 1529 * top-level windows are used. 1530 * 1531 * @param window specifies the top-level window that the hint 1532 * is to be set to 1533 * @param transientForWindow the top-level window 1534 * @param updateChain specifies if next/prevTransientFor fields are 1535 * to be updated 1536 * @param allStates if set to <code>true</code> then TRANSIENT_FOR hint 1537 * is set regardless of the state of window and transientForWindow, 1538 * otherwise it is set only if both are in the same state 1539 */ 1540 static void setToplevelTransientFor(XWindowPeer window, XWindowPeer transientForWindow, 1541 boolean updateChain, boolean allStates) 1542 { 1543 if ((window == null) || (transientForWindow == null)) { 1544 return; 1545 } 1546 if (updateChain) { 1547 window.prevTransientFor = transientForWindow; 1548 transientForWindow.nextTransientFor = window; 1549 } 1550 if (window.curRealTransientFor == transientForWindow) { 1551 return; 1552 } 1553 if (!allStates && (window.getWMState() != transientForWindow.getWMState())) { 1554 return; 1555 } 1556 if (window.getScreenNumber() != transientForWindow.getScreenNumber()) { 1557 return; 1558 } 1559 long bpw = window.getWindow(); 1560 while (!XlibUtil.isToplevelWindow(bpw) && !XlibUtil.isXAWTToplevelWindow(bpw)) { 1561 bpw = XlibUtil.getParentWindow(bpw); 1562 } 1563 long tpw = transientForWindow.getWindow(); 1564 while (!XlibUtil.isToplevelWindow(tpw) && !XlibUtil.isXAWTToplevelWindow(tpw)) { 1565 tpw = XlibUtil.getParentWindow(tpw); 1566 } 1567 XlibWrapper.XSetTransientFor(XToolkit.getDisplay(), bpw, tpw); 1568 window.curRealTransientFor = transientForWindow; 1569 } 1570 1571 /* 1572 * This method does nothing if this window is not blocked by any modal dialog. 1573 * For modal blocked windows this method looks up for the nearest 1574 * prevTransiendFor window that is in the same state (Normal/Iconified/Withdrawn) 1575 * as this one and makes this window transient for it. The same operation is 1576 * performed for nextTransientFor window. 1577 * Values of prevTransientFor and nextTransientFor fields are not changed. 1578 */ 1579 void updateTransientFor() { 1580 int state = getWMState(); 1581 XWindowPeer p = prevTransientFor; 1582 while ((p != null) && ((p.getWMState() != state) || (p.getScreenNumber() != getScreenNumber()))) { 1583 p = p.prevTransientFor; 1584 } 1585 if (p != null) { 1586 setToplevelTransientFor(this, p, false, false); 1587 } else { 1588 restoreTransientFor(this); 1589 } 1590 XWindowPeer n = nextTransientFor; 1591 while ((n != null) && ((n.getWMState() != state) || (n.getScreenNumber() != getScreenNumber()))) { 1592 n = n.nextTransientFor; 1593 } 1594 if (n != null) { 1595 setToplevelTransientFor(n, this, false, false); 1596 } 1597 } 1598 1599 /* 1600 * Removes the TRANSIENT_FOR hint from the given top-level window. 1601 * If window or transientForWindow are embedded frames, the containing 1602 * top-level windows are used. 1603 * 1604 * @param window specifies the top-level window that the hint 1605 * is to be removed from 1606 */ 1607 private static void removeTransientForHint(XWindowPeer window) { 1608 XAtom XA_WM_TRANSIENT_FOR = XAtom.get(XAtom.XA_WM_TRANSIENT_FOR); 1609 long bpw = window.getWindow(); 1610 while (!XlibUtil.isToplevelWindow(bpw) && !XlibUtil.isXAWTToplevelWindow(bpw)) { 1611 bpw = XlibUtil.getParentWindow(bpw); 1612 } 1613 XlibWrapper.XDeleteProperty(XToolkit.getDisplay(), bpw, XA_WM_TRANSIENT_FOR.getAtom()); 1614 window.curRealTransientFor = null; 1615 } 1616 1617 /* 1618 * When a modal dialog is shown, all its blocked windows are lined up into 1619 * a chain in such a way that each window is a transient_for window for 1620 * the next one. That allows us to keep the modal dialog above all its 1621 * blocked windows (even if there are some another modal dialogs between 1622 * them). 1623 * This method adds this top-level window to the chain of the given modal 1624 * dialog. To keep the current relative z-order, we should use the 1625 * XQueryTree to find the place to insert this window to. As each window 1626 * can be blocked by only one modal dialog (such checks are performed in 1627 * shared code), both this and blockerPeer are on the top of their chains 1628 * (chains may be empty). 1629 * If this window is a modal dialog and has its own chain, these chains are 1630 * merged according to the current z-order (XQueryTree is used again). 1631 * Below are some simple examples (z-order is from left to right, -- is 1632 * modal blocking). 1633 * 1634 * Example 0: 1635 * T (current chain of this, no windows are blocked by this) 1636 * W1---B (current chain of blockerPeer, W2 is blocked by blockerPeer) 1637 * Result is: 1638 * W1-T-B (merged chain, all the windows are blocked by blockerPeer) 1639 * 1640 * Example 1: 1641 * W1-T (current chain of this, W1 is blocked by this) 1642 * W2-B (current chain of blockerPeer, W2 is blocked by blockerPeer) 1643 * Result is: 1644 * W1-T-W2-B (merged chain, all the windows are blocked by blockerPeer) 1645 * 1646 * Example 2: 1647 * W1----T (current chain of this, W1 is blocked by this) 1648 * W2---B (current chain of blockerPeer, W2 is blocked by blockerPeer) 1649 * Result is: 1650 * W1-W2-T-B (merged chain, all the windows are blocked by blockerPeer) 1651 * 1652 * This method should be called under the AWT lock. 1653 * 1654 * @see #removeFromTransientFors 1655 * @see #setModalBlocked 1656 */ 1657 private void addToTransientFors(XDialogPeer blockerPeer) { 1658 addToTransientFors(blockerPeer, null); 1659 } 1660 1661 private void addToTransientFors(XDialogPeer blockerPeer, Vector<XWindowPeer> javaToplevels) 1662 { 1663 // blockerPeer chain iterator 1664 XWindowPeer blockerChain = blockerPeer; 1665 while (blockerChain.prevTransientFor != null) { 1666 blockerChain = blockerChain.prevTransientFor; 1667 } 1668 // this window chain iterator 1669 // each window can be blocked no more than once, so this window 1670 // is on top of its chain 1671 XWindowPeer thisChain = this; 1672 while (thisChain.prevTransientFor != null) { 1673 thisChain = thisChain.prevTransientFor; 1674 } 1675 // if there are no windows blocked by modalBlocker, simply add this window 1676 // and its chain to blocker's chain 1677 if (blockerChain == blockerPeer) { 1678 setToplevelTransientFor(blockerPeer, this, true, false); 1679 } else { 1680 // Collect all the Java top-levels, if required 1681 if (javaToplevels == null) { 1682 javaToplevels = collectJavaToplevels(); 1683 } 1684 // merged chain tail 1685 XWindowPeer mergedChain = null; 1686 for (XWindowPeer w : javaToplevels) { 1687 XWindowPeer prevMergedChain = mergedChain; 1688 if (w == thisChain) { 1689 if (thisChain == this) { 1690 if (prevMergedChain != null) { 1691 setToplevelTransientFor(this, prevMergedChain, true, false); 1692 } 1693 setToplevelTransientFor(blockerChain, this, true, false); 1694 break; 1695 } else { 1696 mergedChain = thisChain; 1697 thisChain = thisChain.nextTransientFor; 1698 } 1699 } else if (w == blockerChain) { 1700 mergedChain = blockerChain; 1701 blockerChain = blockerChain.nextTransientFor; 1702 } else { 1703 continue; 1704 } 1705 if (prevMergedChain == null) { 1706 mergedChain.prevTransientFor = null; 1707 } else { 1708 setToplevelTransientFor(mergedChain, prevMergedChain, true, false); 1709 mergedChain.updateTransientFor(); 1710 } 1711 if (blockerChain == blockerPeer) { 1712 setToplevelTransientFor(thisChain, mergedChain, true, false); 1713 setToplevelTransientFor(blockerChain, this, true, false); 1714 break; 1715 } 1716 } 1717 } 1718 1719 XToolkit.XSync(); 1720 } 1721 1722 static void restoreTransientFor(XWindowPeer window) { 1723 XWindowPeer ownerPeer = window.getOwnerPeer(); 1724 if (ownerPeer != null) { 1725 setToplevelTransientFor(window, ownerPeer, false, true); 1726 } else { 1727 removeTransientForHint(window); 1728 } 1729 } 1730 1731 /* 1732 * When a window is modally unblocked, it should be removed from its blocker 1733 * chain, see {@link #addToTransientFor addToTransientFors} method for the 1734 * chain definition. 1735 * The problem is that we cannot simply restore window's original 1736 * TRANSIENT_FOR hint (if any) and link prevTransientFor and 1737 * nextTransientFor together as the whole chain could be created as a merge 1738 * of two other chains in addToTransientFors. In that case, if this window is 1739 * a modal dialog, it would lost all its own chain, if we simply exclude it 1740 * from the chain. 1741 * The correct behaviour of this method should be to split the chain, this 1742 * window is currently in, into two chains. First chain is this window own 1743 * chain (i. e. all the windows blocked by this one, directly or indirectly), 1744 * if any, and the rest windows from the current chain. 1745 * 1746 * Example: 1747 * Original state: 1748 * W1-B1 (window W1 is blocked by B1) 1749 * W2-B2 (window W2 is blocked by B2) 1750 * B3 is shown and blocks B1 and B2: 1751 * W1-W2-B1-B2-B3 (a single chain after B1.addToTransientFors() and B2.addToTransientFors()) 1752 * If we then unblock B1, the state should be: 1753 * W1-B1 (window W1 is blocked by B1) 1754 * W2-B2-B3 (window W2 is blocked by B2 and B2 is blocked by B3) 1755 * 1756 * This method should be called under the AWT lock. 1757 * 1758 * @see #addToTransientFors 1759 * @see #setModalBlocked 1760 */ 1761 private void removeFromTransientFors() { 1762 // the head of the chain of this window 1763 XWindowPeer thisChain = this; 1764 // the head of the current chain 1765 // nextTransientFor is always not null as this window is in the chain 1766 XWindowPeer otherChain = nextTransientFor; 1767 // the set of blockers in this chain: if this dialog blocks some other 1768 // modal dialogs, their blocked windows should stay in this dialog's chain 1769 Set<XWindowPeer> thisChainBlockers = new HashSet<XWindowPeer>(); 1770 thisChainBlockers.add(this); 1771 // current chain iterator in the order from next to prev 1772 XWindowPeer chainToSplit = prevTransientFor; 1773 while (chainToSplit != null) { 1774 XWindowPeer blocker = (XWindowPeer) AWTAccessor.getComponentAccessor().getPeer(chainToSplit.modalBlocker); 1775 if (thisChainBlockers.contains(blocker)) { 1776 // add to this dialog's chain 1777 setToplevelTransientFor(thisChain, chainToSplit, true, false); 1778 thisChain = chainToSplit; 1779 thisChainBlockers.add(chainToSplit); 1780 } else { 1781 // leave in the current chain 1782 setToplevelTransientFor(otherChain, chainToSplit, true, false); 1783 otherChain = chainToSplit; 1784 } 1785 chainToSplit = chainToSplit.prevTransientFor; 1786 } 1787 restoreTransientFor(thisChain); 1788 thisChain.prevTransientFor = null; 1789 restoreTransientFor(otherChain); 1790 otherChain.prevTransientFor = null; 1791 nextTransientFor = null; 1792 1793 XToolkit.XSync(); 1794 } 1795 1796 boolean isModalBlocked() { 1797 return modalBlocker != null; 1798 } 1799 1800 static Window getDecoratedOwner(Window window) { 1801 while ((null != window) && !(window instanceof Frame || window instanceof Dialog)) { 1802 window = (Window) AWTAccessor.getComponentAccessor().getParent(window); 1803 } 1804 return window; 1805 } 1806 1807 public boolean requestWindowFocus(XWindowPeer actualFocusedWindow) { 1808 setActualFocusedWindow(actualFocusedWindow); 1809 return requestWindowFocus(); 1810 } 1811 1812 public boolean requestWindowFocus() { 1813 return requestWindowFocus(0, false); 1814 } 1815 1816 public boolean requestWindowFocus(long time, boolean timeProvided) { 1817 focusLog.fine("Request for window focus"); 1818 // If this is Frame or Dialog we can't assure focus request success - but we still can try 1819 // If this is Window and its owner Frame is active we can be sure request succedded. 1820 Window ownerWindow = XWindowPeer.getDecoratedOwner((Window)target); 1821 Window focusedWindow = XKeyboardFocusManagerPeer.getCurrentNativeFocusedWindow(); 1822 Window activeWindow = XWindowPeer.getDecoratedOwner(focusedWindow); 1823 1824 if (isWMStateNetHidden()) { 1825 focusLog.fine("The window is unmapped, so rejecting the request"); 1826 return false; 1827 } 1828 if (activeWindow == ownerWindow) { 1829 focusLog.fine("Parent window is active - generating focus for this window"); 1830 handleWindowFocusInSync(-1); 1831 return true; 1832 } 1833 focusLog.fine("Parent window is not active"); 1834 1835 XDecoratedPeer wpeer = (XDecoratedPeer)AWTAccessor.getComponentAccessor().getPeer(ownerWindow); 1836 if (wpeer != null && wpeer.requestWindowFocus(this, time, timeProvided)) { 1837 focusLog.fine("Parent window accepted focus request - generating focus for this window"); 1838 return true; 1839 } 1840 focusLog.fine("Denied - parent window is not active and didn't accept focus request"); 1841 return false; 1842 } 1843 1844 // This method is to be overriden in XDecoratedPeer. 1845 void setActualFocusedWindow(XWindowPeer actualFocusedWindow) { 1846 } 1847 1848 /** 1849 * Applies the current window type. 1850 */ 1851 private void applyWindowType() { 1852 XNETProtocol protocol = XWM.getWM().getNETProtocol(); 1853 if (protocol == null) { 1854 return; 1855 } 1856 1857 XAtom typeAtom = null; 1858 1859 switch (getWindowType()) 1860 { 1861 case NORMAL: 1862 typeAtom = protocol.XA_NET_WM_WINDOW_TYPE_NORMAL; 1863 break; 1864 case UTILITY: 1865 typeAtom = protocol.XA_NET_WM_WINDOW_TYPE_UTILITY; 1866 break; 1867 case POPUP: 1868 typeAtom = protocol.XA_NET_WM_WINDOW_TYPE_POPUP_MENU; 1869 break; 1870 } 1871 1872 if (typeAtom != null) { 1873 XAtomList wtype = new XAtomList(); 1874 wtype.add(typeAtom); 1875 protocol.XA_NET_WM_WINDOW_TYPE. 1876 setAtomListProperty(getWindow(), wtype); 1877 } else { 1878 protocol.XA_NET_WM_WINDOW_TYPE. 1879 DeleteProperty(getWindow()); 1880 } 1881 } 1882 1883 @Override 1884 public void xSetVisible(boolean visible) { 1885 if (log.isLoggable(PlatformLogger.FINE)) log.fine("Setting visible on " + this + " to " + visible); 1886 XToolkit.awtLock(); 1887 try { 1888 this.visible = visible; 1889 if (visible) { 1890 applyWindowType(); 1891 XlibWrapper.XMapRaised(XToolkit.getDisplay(), getWindow()); 1892 } else { 1893 XlibWrapper.XUnmapWindow(XToolkit.getDisplay(), getWindow()); 1894 } 1895 XlibWrapper.XFlush(XToolkit.getDisplay()); 1896 } 1897 finally { 1898 XToolkit.awtUnlock(); 1899 } 1900 } 1901 1902 // should be synchronized on awtLock 1903 private int dropTargetCount = 0; 1904 1905 public void addDropTarget() { 1906 XToolkit.awtLock(); 1907 try { 1908 if (dropTargetCount == 0) { 1909 long window = getWindow(); 1910 if (window != 0) { 1911 XDropTargetRegistry.getRegistry().registerDropSite(window); 1912 } 1913 } 1914 dropTargetCount++; 1915 } finally { 1916 XToolkit.awtUnlock(); 1917 } 1918 } 1919 1920 public void removeDropTarget() { 1921 XToolkit.awtLock(); 1922 try { 1923 dropTargetCount--; 1924 if (dropTargetCount == 0) { 1925 long window = getWindow(); 1926 if (window != 0) { 1927 XDropTargetRegistry.getRegistry().unregisterDropSite(window); 1928 } 1929 } 1930 } finally { 1931 XToolkit.awtUnlock(); 1932 } 1933 } 1934 void addRootPropertyEventDispatcher() { 1935 if( rootPropertyEventDispatcher == null ) { 1936 rootPropertyEventDispatcher = new XEventDispatcher() { 1937 public void dispatchEvent(XEvent ev) { 1938 if( ev.get_type() == XConstants.PropertyNotify ) { 1939 handleRootPropertyNotify( ev ); 1940 } 1941 } 1942 }; 1943 XlibWrapper.XSelectInput( XToolkit.getDisplay(), 1944 XToolkit.getDefaultRootWindow(), 1945 XConstants.PropertyChangeMask); 1946 XToolkit.addEventDispatcher(XToolkit.getDefaultRootWindow(), 1947 rootPropertyEventDispatcher); 1948 } 1949 } 1950 void removeRootPropertyEventDispatcher() { 1951 if( rootPropertyEventDispatcher != null ) { 1952 XToolkit.removeEventDispatcher(XToolkit.getDefaultRootWindow(), 1953 rootPropertyEventDispatcher); 1954 rootPropertyEventDispatcher = null; 1955 } 1956 } 1957 public void updateFocusableWindowState() { 1958 cachedFocusableWindow = isFocusableWindow(); 1959 } 1960 1961 XAtom XA_NET_WM_STATE; 1962 XAtomList net_wm_state; 1963 public XAtomList getNETWMState() { 1964 if (net_wm_state == null) { 1965 net_wm_state = XA_NET_WM_STATE.getAtomListPropertyList(this); 1966 } 1967 return net_wm_state; 1968 } 1969 1970 public void setNETWMState(XAtomList state) { 1971 net_wm_state = state; 1972 if (state != null) { 1973 XA_NET_WM_STATE.setAtomListProperty(this, state); 1974 } 1975 } 1976 1977 public PropMwmHints getMWMHints() { 1978 if (mwm_hints == null) { 1979 mwm_hints = new PropMwmHints(); 1980 if (!XWM.XA_MWM_HINTS.getAtomData(getWindow(), mwm_hints.pData, MWMConstants.PROP_MWM_HINTS_ELEMENTS)) { 1981 mwm_hints.zero(); 1982 } 1983 } 1984 return mwm_hints; 1985 } 1986 1987 public void setMWMHints(PropMwmHints hints) { 1988 mwm_hints = hints; 1989 if (hints != null) { 1990 XWM.XA_MWM_HINTS.setAtomData(getWindow(), mwm_hints.pData, MWMConstants.PROP_MWM_HINTS_ELEMENTS); 1991 } 1992 } 1993 1994 protected void updateDropTarget() { 1995 XToolkit.awtLock(); 1996 try { 1997 if (dropTargetCount > 0) { 1998 long window = getWindow(); 1999 if (window != 0) { 2000 XDropTargetRegistry.getRegistry().unregisterDropSite(window); 2001 XDropTargetRegistry.getRegistry().registerDropSite(window); 2002 } 2003 } 2004 } finally { 2005 XToolkit.awtUnlock(); 2006 } 2007 } 2008 2009 public void setGrab(boolean grab) { 2010 this.grab = grab; 2011 if (grab) { 2012 pressTarget = this; 2013 grabInput(); 2014 } else { 2015 ungrabInput(); 2016 } 2017 } 2018 2019 public boolean isGrabbed() { 2020 return grab && XAwtState.getGrabWindow() == this; 2021 } 2022 2023 public void handleXCrossingEvent(XEvent xev) { 2024 XCrossingEvent xce = xev.get_xcrossing(); 2025 if (grabLog.isLoggable(PlatformLogger.FINE)) { 2026 grabLog.fine("{0}, when grabbed {1}, contains {2}", 2027 xce, isGrabbed(), containsGlobal(xce.get_x_root(), xce.get_y_root())); 2028 } 2029 if (isGrabbed()) { 2030 // When window is grabbed, all events are dispatched to 2031 // it. Retarget them to the corresponding windows (notice 2032 // that XBaseWindow.dispatchEvent does the opposite 2033 // translation) 2034 // Note that we need to retarget XCrossingEvents to content window 2035 // since it generates MOUSE_ENTERED/MOUSE_EXITED for frame and dialog. 2036 // (fix for 6390326) 2037 XBaseWindow target = XToolkit.windowToXWindow(xce.get_window()); 2038 grabLog.finer(" - Grab event target {0}", target); 2039 if (target != null && target != this) { 2040 target.dispatchEvent(xev); 2041 return; 2042 } 2043 } 2044 super.handleXCrossingEvent(xev); 2045 } 2046 2047 public void handleMotionNotify(XEvent xev) { 2048 XMotionEvent xme = xev.get_xmotion(); 2049 if (grabLog.isLoggable(PlatformLogger.FINE)) { 2050 grabLog.finer("{0}, when grabbed {1}, contains {2}", 2051 xme, isGrabbed(), containsGlobal(xme.get_x_root(), xme.get_y_root())); 2052 } 2053 if (isGrabbed()) { 2054 boolean dragging = false; 2055 final int buttonsNumber = ((SunToolkit)(Toolkit.getDefaultToolkit())).getNumberOfButtons(); 2056 2057 for (int i = 0; i < buttonsNumber; i++){ 2058 // here is the bug in WM: extra buttons doesn't have state!=0 as they should. 2059 if ((i != 4) && (i != 5)){ 2060 dragging = dragging || ((xme.get_state() & XConstants.buttonsMask[i]) != 0); 2061 } 2062 } 2063 // When window is grabbed, all events are dispatched to 2064 // it. Retarget them to the corresponding windows (notice 2065 // that XBaseWindow.dispatchEvent does the opposite 2066 // translation) 2067 XBaseWindow target = XToolkit.windowToXWindow(xme.get_window()); 2068 if (dragging && pressTarget != target) { 2069 // for some reasons if we grab input MotionNotify for drag is reported with target 2070 // to underlying window, not to window on which we have initiated drag 2071 // so we need to retarget them. Here I use simplified logic which retarget all 2072 // such events to source of mouse press (or the grabber). It helps with fix for 6390326. 2073 // So, I do not want to implement complicated logic for better retargeting. 2074 target = pressTarget.isVisible() ? pressTarget : this; 2075 xme.set_window(target.getWindow()); 2076 Point localCoord = target.toLocal(xme.get_x_root(), xme.get_y_root()); 2077 xme.set_x(localCoord.x); 2078 xme.set_y(localCoord.y); 2079 } 2080 grabLog.finer(" - Grab event target {0}", target); 2081 if (target != null) { 2082 if (target != getContentXWindow() && target != this) { 2083 target.dispatchEvent(xev); 2084 return; 2085 } 2086 } 2087 2088 // note that we need to pass dragging events to the grabber (6390326) 2089 // see comment above for more inforamtion. 2090 if (!containsGlobal(xme.get_x_root(), xme.get_y_root()) && !dragging) { 2091 // Outside of Java 2092 return; 2093 } 2094 } 2095 super.handleMotionNotify(xev); 2096 } 2097 2098 // we use it to retarget mouse drag and mouse release during grab. 2099 private XBaseWindow pressTarget = this; 2100 2101 public void handleButtonPressRelease(XEvent xev) { 2102 XButtonEvent xbe = xev.get_xbutton(); 2103 2104 /* 2105 * Ignore the buttons above 20 due to the bit limit for 2106 * InputEvent.BUTTON_DOWN_MASK. 2107 * One more bit is reserved for FIRST_HIGH_BIT. 2108 */ 2109 if (xbe.get_button() > SunToolkit.MAX_BUTTONS_SUPPORTED) { 2110 return; 2111 } 2112 if (grabLog.isLoggable(PlatformLogger.FINE)) { 2113 grabLog.fine("{0}, when grabbed {1}, contains {2} ({3}, {4}, {5}x{6})", 2114 xbe, isGrabbed(), containsGlobal(xbe.get_x_root(), xbe.get_y_root()), getAbsoluteX(), getAbsoluteY(), getWidth(), getHeight()); 2115 } 2116 if (isGrabbed()) { 2117 // When window is grabbed, all events are dispatched to 2118 // it. Retarget them to the corresponding windows (notice 2119 // that XBaseWindow.dispatchEvent does the opposite 2120 // translation) 2121 XBaseWindow target = XToolkit.windowToXWindow(xbe.get_window()); 2122 try { 2123 grabLog.finer(" - Grab event target {0} (press target {1})", target, pressTarget); 2124 if (xbe.get_type() == XConstants.ButtonPress 2125 && xbe.get_button() == XConstants.buttons[0]) 2126 { 2127 // need to keep it to retarget mouse release 2128 pressTarget = target; 2129 } else if (xbe.get_type() == XConstants.ButtonRelease 2130 && xbe.get_button() == XConstants.buttons[0] 2131 && pressTarget != target) 2132 { 2133 // during grab we do receive mouse release on different component (not on the source 2134 // of mouse press). So we need to retarget it. 2135 // see 6390326 for more information. 2136 target = pressTarget.isVisible() ? pressTarget : this; 2137 xbe.set_window(target.getWindow()); 2138 Point localCoord = target.toLocal(xbe.get_x_root(), xbe.get_y_root()); 2139 xbe.set_x(localCoord.x); 2140 xbe.set_y(localCoord.y); 2141 pressTarget = this; 2142 } 2143 if (target != null && target != getContentXWindow() && target != this) { 2144 target.dispatchEvent(xev); 2145 return; 2146 } 2147 } finally { 2148 if (target != null) { 2149 // Target is either us or our content window - 2150 // check that event is inside. 'Us' in case of 2151 // shell will mean that this will also filter out press on title 2152 if ((target == this || target == getContentXWindow()) && !containsGlobal(xbe.get_x_root(), xbe.get_y_root())) { 2153 // Outside this toplevel hierarchy 2154 // According to the specification of UngrabEvent, post it 2155 // when press occurs outside of the window and not on its owned windows 2156 if (xbe.get_type() == XConstants.ButtonPress) { 2157 grabLog.fine("Generating UngrabEvent on {0} because not inside of shell", this); 2158 postEventToEventQueue(new sun.awt.UngrabEvent(getEventSource())); 2159 return; 2160 } 2161 } 2162 // First, get the toplevel 2163 XWindowPeer toplevel = target.getToplevelXWindow(); 2164 if (toplevel != null) { 2165 Window w = (Window)toplevel.target; 2166 while (w != null && toplevel != this && !(toplevel instanceof XDialogPeer)) { 2167 w = (Window) AWTAccessor.getComponentAccessor().getParent(w); 2168 if (w != null) { 2169 toplevel = (XWindowPeer) AWTAccessor.getComponentAccessor().getPeer(w); 2170 } 2171 } 2172 if (w == null || (w != this.target && w instanceof Dialog)) { 2173 // toplevel == null - outside of 2174 // hierarchy, toplevel is Dialog - should 2175 // send ungrab (but shouldn't for Window) 2176 grabLog.fine("Generating UngrabEvent on {0} because hierarchy ended", this); 2177 postEventToEventQueue(new sun.awt.UngrabEvent(getEventSource())); 2178 } 2179 } else { 2180 // toplevel is null - outside of hierarchy 2181 grabLog.fine("Generating UngrabEvent on {0} because toplevel is null", this); 2182 postEventToEventQueue(new sun.awt.UngrabEvent(getEventSource())); 2183 return; 2184 } 2185 } else { 2186 // target doesn't map to XAWT window - outside of hierarchy 2187 grabLog.fine("Generating UngrabEvent on because target is null {0}", this); 2188 postEventToEventQueue(new sun.awt.UngrabEvent(getEventSource())); 2189 return; 2190 } 2191 } 2192 } 2193 super.handleButtonPressRelease(xev); 2194 } 2195 2196 public void print(Graphics g) { 2197 // We assume we print the whole frame, 2198 // so we expect no clip was set previously 2199 Shape shape = AWTAccessor.getWindowAccessor().getShape((Window)target); 2200 if (shape != null) { 2201 g.setClip(shape); 2202 } 2203 super.print(g); 2204 } 2205 2206 @Override 2207 public void setOpacity(float opacity) { 2208 final long maxOpacity = 0xffffffffl; 2209 long iOpacity = (long)(opacity * maxOpacity); 2210 if (iOpacity < 0) { 2211 iOpacity = 0; 2212 } 2213 if (iOpacity > maxOpacity) { 2214 iOpacity = maxOpacity; 2215 } 2216 2217 XAtom netWmWindowOpacityAtom = XAtom.get("_NET_WM_WINDOW_OPACITY"); 2218 2219 if (iOpacity == maxOpacity) { 2220 netWmWindowOpacityAtom.DeleteProperty(getWindow()); 2221 } else { 2222 netWmWindowOpacityAtom.setCard32Property(getWindow(), iOpacity); 2223 } 2224 } 2225 2226 @Override 2227 public void setOpaque(boolean isOpaque) { 2228 // no-op 2229 } 2230 2231 @Override 2232 public void updateWindow() { 2233 // no-op 2234 } 2235 }