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