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