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