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