1 /*
   2  * Copyright (c) 2002, 2018, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 package sun.awt.X11;
  26 
  27 import java.awt.*;
  28 
  29 import java.awt.event.ComponentEvent;
  30 import java.awt.event.InvocationEvent;
  31 import java.awt.event.WindowEvent;
  32 import java.util.Collections;
  33 import java.util.HashMap;
  34 import java.util.Map;
  35 
  36 import sun.awt.IconInfo;
  37 import sun.util.logging.PlatformLogger;
  38 
  39 import sun.awt.AWTAccessor;
  40 import sun.awt.SunToolkit;
  41 import sun.font.FontUtilities;
  42 
  43 abstract class XDecoratedPeer extends XWindowPeer {
  44     private static final PlatformLogger log = PlatformLogger.getLogger("sun.awt.X11.XDecoratedPeer");
  45     private static final PlatformLogger insLog = PlatformLogger.getLogger("sun.awt.X11.insets.XDecoratedPeer");
  46     private static final PlatformLogger focusLog = PlatformLogger.getLogger("sun.awt.X11.focus.XDecoratedPeer");
  47     private static final PlatformLogger iconLog = PlatformLogger.getLogger("sun.awt.X11.icon.XDecoratedPeer");
  48 
  49     // Set to true when we get the first ConfigureNotify after being
  50     // reparented - indicates that WM has adopted the top-level.
  51     boolean configure_seen;
  52     boolean insets_corrected;
  53 
  54     XIconWindow iconWindow;
  55     volatile WindowDimensions dimensions;
  56     XContentWindow content;
  57     volatile Insets currentInsets;
  58     XFocusProxyWindow focusProxy;
  59     static final Map<Class<?>,Insets> lastKnownInsets =
  60                                    Collections.synchronizedMap(new HashMap<>());
  61 
  62     XDecoratedPeer(Window target) {
  63         super(target);
  64     }
  65 
  66     XDecoratedPeer(XCreateWindowParams params) {
  67         super(params);
  68     }
  69 
  70     public long getShell() {
  71         return window;
  72     }
  73 
  74     public long getContentWindow() {
  75         return (content == null) ? window : content.getWindow();
  76     }
  77 
  78     void preInit(XCreateWindowParams params) {
  79         super.preInit(params);
  80         winAttr.initialFocus = true;
  81 
  82         currentInsets = new Insets(0,0,0,0);
  83         if (XWM.getWMID() == XWM.UNITY_COMPIZ_WM) {
  84             currentInsets = lastKnownInsets.get(getClass());
  85         }
  86         applyGuessedInsets();
  87 
  88         Rectangle bounds = (Rectangle)params.get(BOUNDS);
  89         dimensions = new WindowDimensions(bounds, getRealInsets(), false);
  90         params.put(BOUNDS, dimensions.getClientRect());
  91         if (insLog.isLoggable(PlatformLogger.Level.FINE)) {
  92             insLog.fine("Initial dimensions {0}", dimensions);
  93         }
  94 
  95         // Deny default processing of these events on the shell - proxy will take care of
  96         // them instead
  97         Long eventMask = (Long)params.get(EVENT_MASK);
  98         params.add(EVENT_MASK, Long.valueOf(eventMask.longValue() & ~(XConstants.FocusChangeMask | XConstants.KeyPressMask | XConstants.KeyReleaseMask)));
  99     }
 100 
 101     void postInit(XCreateWindowParams params) {
 102         // The size hints must be set BEFORE mapping the window (see 6895647)
 103         updateSizeHints(dimensions);
 104 
 105         // The super method maps the window if it's visible on the shared level
 106         super.postInit(params);
 107 
 108         // The lines that follow need to be in a postInit, so they
 109         // happen after the X window is created.
 110         setResizable(winAttr.initialResizability);
 111         XWM.requestWMExtents(getWindow());
 112 
 113         content = XContentWindow.createContent(this);
 114 
 115         if (warningWindow != null) {
 116             warningWindow.toFront();
 117         }
 118         focusProxy = createFocusProxy();
 119     }
 120 
 121     void setIconHints(java.util.List<IconInfo> icons) {
 122         if (!XWM.getWM().setNetWMIcon(this, icons)) {
 123             if (icons.size() > 0) {
 124                 if (iconWindow == null) {
 125                     iconWindow = new XIconWindow(this);
 126                 }
 127                 iconWindow.setIconImages(icons);
 128             }
 129         }
 130     }
 131 
 132     public void updateMinimumSize() {
 133         super.updateMinimumSize();
 134         XToolkit.awtLock();
 135         try {
 136             updateMinSizeHints();
 137         } finally {
 138             XToolkit.awtUnlock();
 139         }
 140     }
 141 
 142     private void updateMinSizeHints() {
 143         if (isResizable()) {
 144             Dimension minimumSize = getTargetMinimumSize();
 145             if (minimumSize != null) {
 146                 Insets insets = getRealInsets();
 147                 int minWidth = minimumSize.width - insets.left - insets.right;
 148                 int minHeight = minimumSize.height - insets.top - insets.bottom;
 149                 if (minWidth < 0) minWidth = 0;
 150                 if (minHeight < 0) minHeight = 0;
 151                 setSizeHints(XUtilConstants.PMinSize | (isLocationByPlatform()?0:(XUtilConstants.PPosition | XUtilConstants.USPosition)),
 152                              getX(), getY(), minWidth, minHeight);
 153                 if (isVisible()) {
 154                     Rectangle bounds = getShellBounds();
 155                     int nw = (bounds.width < minWidth) ? minWidth : bounds.width;
 156                     int nh = (bounds.height < minHeight) ? minHeight : bounds.height;
 157                     if (nw != bounds.width || nh != bounds.height) {
 158                         setShellSize(new Rectangle(0, 0, nw, nh));
 159                     }
 160                 }
 161             } else {
 162                 boolean isMinSizeSet = isMinSizeSet();
 163                 XWM.removeSizeHints(this, XUtilConstants.PMinSize);
 164                 /* Some WMs need remap to redecorate the window */
 165                 if (isMinSizeSet && isShowing() && XWM.needRemap(this)) {
 166                     /*
 167                      * Do the re/mapping at the Xlib level.  Since we essentially
 168                      * work around a WM bug we don't want this hack to be exposed
 169                      * to Intrinsics (i.e. don't mess with grabs, callbacks etc).
 170                      */
 171                     xSetVisible(false);
 172                     XToolkit.XSync();
 173                     xSetVisible(true);
 174                 }
 175             }
 176         }
 177     }
 178 
 179     XFocusProxyWindow createFocusProxy() {
 180         return new XFocusProxyWindow(this);
 181     }
 182 
 183     protected XAtomList getWMProtocols() {
 184         XAtomList protocols = super.getWMProtocols();
 185         protocols.add(wm_delete_window);
 186         protocols.add(wm_take_focus);
 187         return protocols;
 188     }
 189 
 190     public Graphics getGraphics() {
 191         AWTAccessor.ComponentAccessor compAccessor = AWTAccessor.getComponentAccessor();
 192         return getGraphics(content.surfaceData,
 193                            compAccessor.getForeground(target),
 194                            compAccessor.getBackground(target),
 195                            compAccessor.getFont(target));
 196     }
 197 
 198     public void setTitle(String title) {
 199         if (log.isLoggable(PlatformLogger.Level.FINE)) {
 200             log.fine("Title is " + title);
 201         }
 202         XToolkit.awtLock();
 203         try {
 204             winAttr.title = title;
 205             updateWMName();
 206         } finally {
 207             XToolkit.awtUnlock();
 208         }
 209     }
 210 
 211     protected String getWMName() {
 212         if (winAttr.title == null || winAttr.title.trim().equals("")) {
 213             return " ";
 214         } else {
 215             return winAttr.title;
 216         }
 217     }
 218 
 219     void updateWMName() {
 220         XToolkit.awtLock();
 221         try {
 222             super.updateWMName();
 223             String name = getWMName();
 224             if (name == null || name.trim().equals("")) {
 225                 name = "Java";
 226             }
 227             XAtom iconNameAtom = XAtom.get(XAtom.XA_WM_ICON_NAME);
 228             iconNameAtom.setProperty(getWindow(), name);
 229             XAtom netIconNameAtom = XAtom.get("_NET_WM_ICON_NAME");
 230             netIconNameAtom.setPropertyUTF8(getWindow(), name);
 231         } finally {
 232             XToolkit.awtUnlock();
 233         }
 234     }
 235 
 236     // NOTE: This method may be called by privileged threads.
 237     //       DO NOT INVOKE CLIENT CODE ON THIS THREAD!
 238     public void handleIconify() {
 239         postEvent(new WindowEvent((Window)target, WindowEvent.WINDOW_ICONIFIED));
 240     }
 241 
 242     // NOTE: This method may be called by privileged threads.
 243     //       DO NOT INVOKE CLIENT CODE ON THIS THREAD!
 244     public void handleDeiconify() {
 245         postEvent(new WindowEvent((Window)target, WindowEvent.WINDOW_DEICONIFIED));
 246     }
 247 
 248     public void handleFocusEvent(XEvent xev) {
 249         super.handleFocusEvent(xev);
 250         XFocusChangeEvent xfe = xev.get_xfocus();
 251 
 252         // If we somehow received focus events forward it instead to proxy
 253         // FIXME: Shouldn't we instead check for inferrior?
 254         if (focusLog.isLoggable(PlatformLogger.Level.FINER)) {
 255             focusLog.finer("Received focus event on shell: " + xfe);
 256         }
 257 //         focusProxy.xRequestFocus();
 258    }
 259 
 260 /***************************************************************************************
 261  *                             I N S E T S   C O D E
 262  **************************************************************************************/
 263 
 264     protected boolean isInitialReshape() {
 265         return false;
 266     }
 267 
 268     private static Insets difference(Insets i1, Insets i2) {
 269         return new Insets(i1.top-i2.top, i1.left - i2.left, i1.bottom-i2.bottom, i1.right-i2.right);
 270     }
 271 
 272     private static boolean isNull(Insets i) {
 273         return (i == null) || ((i.left | i.top | i.right | i.bottom) == 0);
 274     }
 275 
 276     private static Insets copy(Insets i) {
 277         return new Insets(i.top, i.left, i.bottom, i.right);
 278     }
 279 
 280     private Insets copyAndScaleDown(Insets i) {
 281         return new Insets(scaleDown(i.top), scaleDown(i.left),
 282                           scaleDown(i.bottom), scaleDown(i.right));
 283     }
 284 
 285 
 286     // insets which we get from WM (e.g from _NET_FRAME_EXTENTS)
 287     private Insets wm_set_insets;
 288 
 289     private Insets getWMSetInsets(XAtom changedAtom) {
 290         if (isEmbedded()) {
 291             return null;
 292         }
 293 
 294         if (wm_set_insets != null) {
 295             return wm_set_insets;
 296         }
 297 
 298         if (changedAtom == null) {
 299             wm_set_insets = XWM.getInsetsFromExtents(getWindow());
 300         } else {
 301             wm_set_insets = XWM.getInsetsFromProp(getWindow(), changedAtom);
 302         }
 303 
 304         if (insLog.isLoggable(PlatformLogger.Level.FINER)) {
 305             insLog.finer("FRAME_EXTENTS: {0}", wm_set_insets);
 306         }
 307 
 308         if (wm_set_insets != null) {
 309             wm_set_insets = copyAndScaleDown(wm_set_insets);
 310         }
 311         return wm_set_insets;
 312     }
 313 
 314     private void resetWMSetInsets() {
 315         if (XWM.getWMID() != XWM.UNITY_COMPIZ_WM) {
 316             currentInsets = new Insets(0, 0, 0, 0);
 317             wm_set_insets = null;
 318         } else {
 319             insets_corrected = false;
 320         }
 321     }
 322 
 323     public void handlePropertyNotify(XEvent xev) {
 324         super.handlePropertyNotify(xev);
 325 
 326         XPropertyEvent ev = xev.get_xproperty();
 327         if( !insets_corrected && isReparented() &&
 328                                          XWM.getWMID() == XWM.UNITY_COMPIZ_WM) {
 329             int state = XWM.getWM().getState(this);
 330             if ((state & Frame.MAXIMIZED_BOTH) ==  Frame.MAXIMIZED_BOTH) {
 331                 // Stop ignoring ConfigureNotify because no extents will be sent
 332                 // by WM for initially maximized decorated window.
 333                 // Re-request window bounds to ensure actual dimensions and
 334                 // notify the target with the initial size.
 335                 insets_corrected = true;
 336                 XlibWrapper.XConfigureWindow(XToolkit.getDisplay(),
 337                                                              getWindow(), 0, 0);
 338             }
 339         }
 340         if (ev.get_atom() == XWM.XA_KDE_NET_WM_FRAME_STRUT.getAtom()
 341             || ev.get_atom() == XWM.XA_NET_FRAME_EXTENTS.getAtom())
 342         {
 343             if (XWM.getWMID() != XWM.UNITY_COMPIZ_WM) {
 344                 getWMSetInsets(XAtom.get(ev.get_atom()));
 345             } else {
 346                 if (!isReparented()) {
 347                     return;
 348                 }
 349                 wm_set_insets = null;
 350                 Insets in = getWMSetInsets(XAtom.get(ev.get_atom()));
 351                 if (isNull(in)) {
 352                     return;
 353                 }
 354                 if (!isEmbedded() && !isTargetUndecorated()) {
 355                     lastKnownInsets.put(getClass(), in);
 356                 }
 357                 if (!in.equals(dimensions.getInsets())) {
 358                     if (insets_corrected || isMaximized()) {
 359                         currentInsets = in;
 360                         insets_corrected = true;
 361                         // insets were changed by WM. To handle this situation
 362                         // re-request window bounds because the current
 363                         // dimensions may be not actual as well.
 364                         XlibWrapper.XConfigureWindow(XToolkit.getDisplay(),
 365                                                              getWindow(), 0, 0);
 366                     } else {
 367                         // recalculate dimensions when window is just created
 368                         // and the initially guessed insets were wrong
 369                         handleCorrectInsets(in);
 370                     }
 371                 } else if (!insets_corrected || !dimensions.isClientSizeSet()) {
 372                     insets_corrected = true;
 373                     // initial insets were guessed correctly. Re-request
 374                     // frame bounds because they may be changed by WM if the
 375                     // initial window position overlapped desktop's toolbars.
 376                     // This should initiate the final ConfigureNotify upon which
 377                     // the target will be notified with the final size.
 378                     XlibWrapper.XConfigureWindow(XToolkit.getDisplay(),
 379                                                              getWindow(), 0, 0);
 380                 }
 381             }
 382         }
 383     }
 384 
 385     long reparent_serial = 0;
 386 
 387     public void handleReparentNotifyEvent(XEvent xev) {
 388         XReparentEvent  xe = xev.get_xreparent();
 389         if (insLog.isLoggable(PlatformLogger.Level.FINE)) {
 390             insLog.fine(xe.toString());
 391         }
 392         reparent_serial = xe.get_serial();
 393         long root = XlibWrapper.RootWindow(XToolkit.getDisplay(), getScreenNumber());
 394 
 395         if (isEmbedded()) {
 396             setReparented(true);
 397             insets_corrected = true;
 398             return;
 399         }
 400         if (getDecorations() == XWindowAttributesData.AWT_DECOR_NONE) {
 401             setReparented(true);
 402             insets_corrected = true;
 403             reshape(dimensions, SET_SIZE, false);
 404         } else if (xe.get_parent() == root) {
 405             configure_seen = false;
 406             insets_corrected = false;
 407 
 408             /*
 409              * We can be repareted to root for two reasons:
 410              *   . setVisible(false)
 411              *   . WM exited
 412              */
 413             if (isVisible()) { /* WM exited */
 414                 /* Work around 4775545 */
 415                 XWM.getWM().unshadeKludge(this);
 416                 insLog.fine("- WM exited");
 417             } else {
 418                 insLog.fine(" - reparent due to hide");
 419             }
 420         } else { /* reparented to WM frame, figure out our insets */
 421             setReparented(true);
 422             insets_corrected = false;
 423             if (XWM.getWMID() == XWM.UNITY_COMPIZ_WM) {
 424                 return;
 425             }
 426 
 427             // Check if we have insets provided by the WM
 428             Insets correctWM = getWMSetInsets(null);
 429             if (correctWM != null) {
 430                 if (insLog.isLoggable(PlatformLogger.Level.FINER)) {
 431                     insLog.finer("wm-provided insets {0}", correctWM);
 432                 }
 433                 // If these insets are equal to our current insets - no actions are necessary
 434                 Insets dimInsets = dimensions.getInsets();
 435                 if (correctWM.equals(dimInsets)) {
 436                     insLog.finer("Insets are the same as estimated - no additional reshapes necessary");
 437                     no_reparent_artifacts = true;
 438                     insets_corrected = true;
 439                     applyGuessedInsets();
 440                     return;
 441                 }
 442             } else {
 443                 correctWM = XWM.getWM().getInsets(this, xe.get_window(), xe.get_parent());
 444                 if (correctWM != null) {
 445                     correctWM = copyAndScaleDown(correctWM);
 446                 }
 447 
 448                 if (insLog.isLoggable(PlatformLogger.Level.FINER)) {
 449                     if (correctWM != null) {
 450                         insLog.finer("correctWM {0}", correctWM);
 451                     } else {
 452                         insLog.finer("correctWM insets are not available, waiting for configureNotify");
 453                     }
 454                 }
 455             }
 456 
 457             if (correctWM != null) {
 458                 handleCorrectInsets(correctWM);
 459             }
 460         }
 461     }
 462 
 463     private void handleCorrectInsets(Insets correctWM) {
 464         /*
 465          * Ok, now see if we need adjust window size because
 466          * initial insets were wrong (most likely they were).
 467          */
 468         Insets correction = difference(correctWM, currentInsets);
 469         if (insLog.isLoggable(PlatformLogger.Level.FINEST)) {
 470             insLog.finest("Corrention {0}", correction);
 471         }
 472         if (!isNull(correction)) {
 473             currentInsets = copy(correctWM);
 474             applyGuessedInsets();
 475 
 476             //Fix for 6318109: PIT: Min Size is not honored properly when a
 477             //smaller size is specified in setSize(), XToolkit
 478             //update minimum size hints
 479             updateMinSizeHints();
 480         }
 481         if (insLog.isLoggable(PlatformLogger.Level.FINER)) {
 482             insLog.finer("Dimensions before reparent: " + dimensions);
 483         }
 484         WindowDimensions newDimensions = new WindowDimensions(dimensions);
 485         newDimensions.setInsets(getRealInsets());
 486         dimensions = newDimensions;
 487         insets_corrected = true;
 488 
 489         if (isMaximized()) {
 490             return;
 491         }
 492 
 493         /*
 494          * If this window has been sized by a pack() we need
 495          * to keep the interior geometry intact.  Since pack()
 496          * computed width and height with wrong insets, we
 497          * must adjust the target dimensions appropriately.
 498          */
 499         if ((getHints().get_flags() & (XUtilConstants.USPosition | XUtilConstants.PPosition)) != 0) {
 500             reshape(dimensions, SET_BOUNDS, false);
 501         } else {
 502             reshape(dimensions, SET_SIZE, false);
 503         }
 504     }
 505 
 506     void handleMoved(WindowDimensions dims) {
 507         Point loc = dims.getLocation();
 508         AWTAccessor.getComponentAccessor().setLocation(target, loc.x, loc.y);
 509         postEvent(new ComponentEvent(target, ComponentEvent.COMPONENT_MOVED));
 510     }
 511 
 512 
 513     private Insets guessInsets() {
 514         if (isEmbedded() || isTargetUndecorated()) {
 515             return new Insets(0, 0, 0, 0);
 516         } else {
 517             if (!isNull(currentInsets)) {
 518                 /* insets were set on wdata by System Properties */
 519                 return copy(currentInsets);
 520             } else {
 521                 Insets res = getWMSetInsets(null);
 522                 if (res == null) {
 523                     res = XWM.getWM().guessInsets(this);
 524                     if (res != null) {
 525                         res = copyAndScaleDown(res);
 526                     }
 527                 }
 528                 return res;
 529             }
 530         }
 531     }
 532 
 533     private void applyGuessedInsets() {
 534         Insets guessed = guessInsets();
 535         currentInsets = copy(guessed);
 536     }
 537 
 538     private Insets getRealInsets() {
 539         if (isNull(currentInsets)) {
 540             applyGuessedInsets();
 541         }
 542         return currentInsets;
 543     }
 544 
 545     public Insets getInsets() {
 546         Insets in = copy(getRealInsets());
 547         in.top += getMenuBarHeight();
 548         if (insLog.isLoggable(PlatformLogger.Level.FINEST)) {
 549             insLog.finest("Get insets returns {0}", in);
 550         }
 551         return in;
 552     }
 553 
 554     boolean gravityBug() {
 555         return XWM.configureGravityBuggy();
 556     }
 557 
 558     // The height of area used to display current active input method
 559     int getInputMethodHeight() {
 560         return 0;
 561     }
 562 
 563     void updateSizeHints(WindowDimensions dims) {
 564         Rectangle rec = dims.getClientRect();
 565         checkShellRect(rec);
 566         updateSizeHints(rec.x, rec.y, rec.width, rec.height);
 567     }
 568 
 569     void updateSizeHints() {
 570         updateSizeHints(dimensions);
 571     }
 572 
 573     // Coordinates are that of the target
 574     // Called only on Toolkit thread
 575     private void reshape(WindowDimensions newDimensions, int op,
 576                         boolean userReshape)
 577     {
 578         if (insLog.isLoggable(PlatformLogger.Level.FINE)) {
 579             insLog.fine("Reshaping " + this + " to " + newDimensions + " op " + op + " user reshape " + userReshape);
 580         }
 581         if (userReshape) {
 582             // We handle only userReshape == true cases. It means that
 583             // if the window manager or any other part of the windowing
 584             // system sets inappropriate size for this window, we can
 585             // do nothing but accept it.
 586             Rectangle newBounds = newDimensions.getBounds();
 587             Insets insets = newDimensions.getInsets();
 588             // Inherit isClientSizeSet from newDimensions
 589             if (newDimensions.isClientSizeSet()) {
 590                 newBounds = new Rectangle(newBounds.x, newBounds.y,
 591                                           newBounds.width - insets.left - insets.right,
 592                                           newBounds.height - insets.top - insets.bottom);
 593             }
 594             newDimensions = new WindowDimensions(newBounds, insets, newDimensions.isClientSizeSet());
 595         }
 596         if (!isReparented() || !isVisible()) {
 597             if (insLog.isLoggable(PlatformLogger.Level.FINE)) {
 598                 insLog.fine("- not reparented({0}) or not visible({1}), default reshape",
 599                        Boolean.valueOf(isReparented()), Boolean.valueOf(visible));
 600             }
 601 
 602             // Fix for 6323293.
 603             // This actually is needed to preserve compatibility with previous releases -
 604             // some of licensees are expecting componentMoved event on invisible one while
 605             // its location changes.
 606             Point oldLocation = getLocation();
 607 
 608             Point newLocation = new Point(AWTAccessor.getComponentAccessor().getX(target),
 609                                           AWTAccessor.getComponentAccessor().getY(target));
 610 
 611             if (!newLocation.equals(oldLocation)) {
 612                 handleMoved(newDimensions);
 613             }
 614 
 615             dimensions = new WindowDimensions(newDimensions);
 616             updateSizeHints(dimensions);
 617             Rectangle client = dimensions.getClientRect();
 618             checkShellRect(client);
 619             setShellBounds(client);
 620             if (content != null &&
 621                 !content.getSize().equals(newDimensions.getSize()))
 622             {
 623                 reconfigureContentWindow(newDimensions);
 624             }
 625             return;
 626         }
 627 
 628         updateChildrenSizes();
 629         applyGuessedInsets();
 630 
 631         Rectangle shellRect = newDimensions.getClientRect();
 632 
 633         if (gravityBug()) {
 634             Insets in = newDimensions.getInsets();
 635             shellRect.translate(in.left, in.top);
 636         }
 637 
 638         if ((op & NO_EMBEDDED_CHECK) == 0 && isEmbedded()) {
 639             shellRect.setLocation(0, 0);
 640         }
 641 
 642         checkShellRectSize(shellRect);
 643         if (!isEmbedded()) {
 644             checkShellRectPos(shellRect);
 645         }
 646 
 647         op = op & ~NO_EMBEDDED_CHECK;
 648 
 649         if (op == SET_LOCATION) {
 650             setShellPosition(shellRect);
 651         } else if (isResizable()) {
 652             if (op == SET_BOUNDS) {
 653                 setShellBounds(shellRect);
 654             } else {
 655                 setShellSize(shellRect);
 656             }
 657         } else {
 658             XWM.setShellNotResizable(this, newDimensions, shellRect, true);
 659             if (op == SET_BOUNDS) {
 660                 setShellPosition(shellRect);
 661             }
 662         }
 663 
 664         reconfigureContentWindow(newDimensions);
 665     }
 666 
 667     /**
 668      * @param x, y, width, heith - dimensions of the window with insets
 669      */
 670     private void reshape(int x, int y, int width, int height, int operation,
 671                          boolean userReshape)
 672     {
 673         WindowDimensions dims = new WindowDimensions(dimensions);
 674         switch (operation & (~NO_EMBEDDED_CHECK)) {
 675           case SET_LOCATION:
 676               // Set location always sets bounds location. However, until the window is mapped we
 677               // should use client coordinates
 678               dims.setLocation(x, y);
 679               break;
 680           case SET_SIZE:
 681               // Set size sets bounds size. However, until the window is mapped we
 682               // should use client coordinates
 683               dims.setSize(width, height);
 684               break;
 685           case SET_CLIENT_SIZE: {
 686               // Sets client rect size. Width and height contain insets.
 687               Insets in = currentInsets;
 688               width -= in.left+in.right;
 689               height -= in.top+in.bottom;
 690               dims.setClientSize(width, height);
 691               break;
 692           }
 693           case SET_BOUNDS:
 694           default:
 695               dims.setLocation(x, y);
 696               dims.setSize(width, height);
 697               break;
 698         }
 699         if (insLog.isLoggable(PlatformLogger.Level.FINE)) {
 700             insLog.fine("For the operation {0} new dimensions are {1}",
 701                         operationToString(operation), dims);
 702         }
 703 
 704         reshape(dims, operation, userReshape);
 705     }
 706 
 707     // This method gets overriden in XFramePeer & XDialogPeer.
 708     abstract boolean isTargetUndecorated();
 709 
 710     /**
 711      * @see java.awt.peer.ComponentPeer#setBounds
 712      */
 713     public void setBounds(int x, int y, int width, int height, int op) {
 714         // TODO: Rewrite with WindowDimensions
 715         XToolkit.awtLock();
 716         try {
 717             reshape(x, y, width, height, op, true);
 718         } finally {
 719             XToolkit.awtUnlock();
 720         }
 721         validateSurface();
 722     }
 723 
 724     // Coordinates are that of the shell
 725     void reconfigureContentWindow(WindowDimensions dims) {
 726         if (content == null) {
 727             insLog.fine("WARNING: Content window is null");
 728             return;
 729         }
 730         content.setContentBounds(dims);
 731     }
 732 
 733     boolean no_reparent_artifacts = false;
 734     public void handleConfigureNotifyEvent(XEvent xev) {
 735         if (XWM.getWMID() == XWM.UNITY_COMPIZ_WM && !insets_corrected) {
 736             return;
 737         }
 738         assert (SunToolkit.isAWTLockHeldByCurrentThread());
 739         XConfigureEvent xe = xev.get_xconfigure();
 740         if (insLog.isLoggable(PlatformLogger.Level.FINE)) {
 741             insLog.fine("Configure notify {0}", xe);
 742         }
 743 
 744         // XXX: should really only consider synthetic events, but
 745         if (isReparented()) {
 746             configure_seen = true;
 747         }
 748 
 749         if (!isMaximized()
 750             && (xe.get_serial() == reparent_serial || xe.get_window() != getShell())
 751             && !no_reparent_artifacts)
 752         {
 753             insLog.fine("- reparent artifact, skipping");
 754             return;
 755         }
 756         no_reparent_artifacts = false;
 757 
 758         /**
 759          * When there is a WM we receive some CN before being visible and after.
 760          * We should skip all CN which are before being visible, because we assume
 761          * the gravity is in action while it is not yet.
 762          *
 763          * When there is no WM we receive CN only _before_ being visible.
 764          * We should process these CNs.
 765          */
 766         if (!isVisible() && XWM.getWMID() != XWM.NO_WM) {
 767             insLog.fine(" - not visible, skipping");
 768             return;
 769         }
 770 
 771         /*
 772          * Some window managers configure before we are reparented and
 773          * the send event flag is set! ugh... (Enlighetenment for one,
 774          * possibly MWM as well).  If we haven't been reparented yet
 775          * this is just the WM shuffling us into position.  Ignore
 776          * it!!!! or we wind up in a bogus location.
 777          */
 778         int runningWM = XWM.getWMID();
 779         if (insLog.isLoggable(PlatformLogger.Level.FINE)) {
 780             insLog.fine("reparented={0}, visible={1}, WM={2}, decorations={3}",
 781                         isReparented(), isVisible(), runningWM, getDecorations());
 782         }
 783         if (!isReparented() && isVisible() && runningWM != XWM.NO_WM
 784                 &&  !XWM.isNonReparentingWM()
 785                 && getDecorations() != XWindowAttributesData.AWT_DECOR_NONE) {
 786             insLog.fine("- visible but not reparented, skipping");
 787             return;
 788         }
 789         //Last chance to correct insets
 790         if (!insets_corrected && getDecorations() != XWindowAttributesData.AWT_DECOR_NONE) {
 791             long parent = XlibUtil.getParentWindow(window);
 792             Insets correctWM = (parent != -1) ? XWM.getWM().getInsets(this, window, parent) : null;
 793             if (insLog.isLoggable(PlatformLogger.Level.FINER)) {
 794                 if (correctWM != null) {
 795                     insLog.finer("Configure notify - insets : " + correctWM);
 796                 } else {
 797                     insLog.finer("Configure notify - insets are still not available");
 798                 }
 799             }
 800             if (correctWM != null) {
 801                 handleCorrectInsets(copyAndScaleDown(correctWM));
 802             } else {
 803                 //Only one attempt to correct insets is made (to lower risk)
 804                 //if insets are still not available we simply set the flag
 805                 insets_corrected = true;
 806             }
 807         }
 808 
 809         updateChildrenSizes();
 810 
 811         Point newLocation = getNewLocation(xe, currentInsets.left, currentInsets.top);
 812         if (XWM.isMotif()) {
 813             if (!isFocusableWindow() && FontUtilities.isAIX) {
 814                 Rectangle targetBounds = AWTAccessor.getComponentAccessor().getBounds(target);
 815                 newLocation = targetBounds.getLocation();
 816             }
 817         }
 818         WindowDimensions newDimensions =
 819                 new WindowDimensions(newLocation,
 820                                      new Dimension(scaleDown(xe.get_width()),
 821                                                    scaleDown(xe.get_height())),
 822                                      copy(currentInsets), true);
 823 
 824         if (insLog.isLoggable(PlatformLogger.Level.FINER)) {
 825             insLog.finer("Insets are {0}, new dimensions {1}",
 826                      currentInsets, newDimensions);
 827         }
 828 
 829         checkIfOnNewScreen(newDimensions.getBounds());
 830 
 831         Point oldLocation = getLocation();
 832         dimensions = newDimensions;
 833         if (!newLocation.equals(oldLocation)) {
 834             handleMoved(newDimensions);
 835         }
 836         reconfigureContentWindow(newDimensions);
 837         updateChildrenSizes();
 838 
 839         repositionSecurityWarning();
 840     }
 841 
 842     private void checkShellRectSize(Rectangle shellRect) {
 843         shellRect.width = Math.max(MIN_SIZE, shellRect.width);
 844         shellRect.height = Math.max(MIN_SIZE, shellRect.height);
 845     }
 846 
 847     private void checkShellRectPos(Rectangle shellRect) {
 848         int wm = XWM.getWMID();
 849         if (wm == XWM.MOTIF_WM || wm == XWM.CDE_WM) {
 850             if (shellRect.x == 0 && shellRect.y == 0) {
 851                 shellRect.x = shellRect.y = 1;
 852             }
 853         }
 854     }
 855 
 856     private void checkShellRect(Rectangle shellRect) {
 857         checkShellRectSize(shellRect);
 858         checkShellRectPos(shellRect);
 859     }
 860 
 861     private void setShellBounds(Rectangle rec) {
 862         if (insLog.isLoggable(PlatformLogger.Level.FINE)) {
 863             insLog.fine("Setting shell bounds on " + this + " to " + rec);
 864         }
 865         updateSizeHints(rec.x, rec.y, rec.width, rec.height);
 866         XlibWrapper.XMoveResizeWindow(XToolkit.getDisplay(), getShell(),
 867                                       scaleUp(rec.x), scaleUp(rec.y),
 868                                       scaleUp(rec.width), scaleUp(rec.height));
 869     }
 870 
 871     private void setShellSize(Rectangle rec) {
 872         if (insLog.isLoggable(PlatformLogger.Level.FINE)) {
 873             insLog.fine("Setting shell size on " + this + " to " + rec);
 874         }
 875         updateSizeHints(rec.x, rec.y, rec.width, rec.height);
 876         XlibWrapper.XResizeWindow(XToolkit.getDisplay(), getShell(),
 877                                   scaleUp(rec.width), scaleUp(rec.height));
 878     }
 879 
 880     private void setShellPosition(Rectangle rec) {
 881         if (insLog.isLoggable(PlatformLogger.Level.FINE)) {
 882             insLog.fine("Setting shell position on " + this + " to " + rec);
 883         }
 884         updateSizeHints(rec.x, rec.y, rec.width, rec.height);
 885         XlibWrapper.XMoveWindow(XToolkit.getDisplay(), getShell(),
 886                                 scaleUp(rec.x), scaleUp(rec.y));
 887     }
 888 
 889     public void setResizable(boolean resizable) {
 890         XToolkit.awtLock();
 891         try {
 892             int fs = winAttr.functions;
 893             if (!isResizable() && resizable) {
 894                 resetWMSetInsets();
 895                 if (!isEmbedded()) {
 896                     setReparented(false);
 897                 }
 898                 winAttr.isResizable = resizable;
 899                 if ((fs & MWMConstants.MWM_FUNC_ALL) != 0) {
 900                     fs &= ~(MWMConstants.MWM_FUNC_RESIZE
 901                           | MWMConstants.MWM_FUNC_MAXIMIZE);
 902                 } else {
 903                     fs |= (MWMConstants.MWM_FUNC_RESIZE
 904                          | MWMConstants.MWM_FUNC_MAXIMIZE);
 905                 }
 906                 winAttr.functions = fs;
 907                 XWM.setShellResizable(this);
 908             } else if (isResizable() && !resizable) {
 909                 resetWMSetInsets();
 910                 if (!isEmbedded()) {
 911                     setReparented(false);
 912                 }
 913                 winAttr.isResizable = resizable;
 914                 if ((fs & MWMConstants.MWM_FUNC_ALL) != 0) {
 915                     fs |= (MWMConstants.MWM_FUNC_RESIZE
 916                          | MWMConstants.MWM_FUNC_MAXIMIZE);
 917                 } else {
 918                     fs &= ~(MWMConstants.MWM_FUNC_RESIZE
 919                           | MWMConstants.MWM_FUNC_MAXIMIZE);
 920                 }
 921                 winAttr.functions = fs;
 922                 XWM.setShellNotResizable(this, dimensions,
 923                         XWM.getWMID() == XWM.UNITY_COMPIZ_WM && configure_seen ?
 924                         dimensions.getScreenBounds() :
 925                         dimensions.getBounds(), false);
 926             }
 927         } finally {
 928             XToolkit.awtUnlock();
 929         }
 930     }
 931 
 932     Rectangle getShellBounds() {
 933         return dimensions.getClientRect();
 934     }
 935 
 936     public Rectangle getBounds() {
 937         return dimensions.getBounds();
 938     }
 939 
 940     public Dimension getSize() {
 941         return dimensions.getSize();
 942     }
 943 
 944     public int getX() {
 945         return dimensions.getLocation().x;
 946     }
 947 
 948     public int getY() {
 949         return dimensions.getLocation().y;
 950     }
 951 
 952     public Point getLocation() {
 953         return dimensions.getLocation();
 954     }
 955 
 956     public int getAbsoluteX() {
 957         // NOTE: returning this peer's location which is shell location
 958         return dimensions.getScreenBounds().x;
 959     }
 960 
 961     public int getAbsoluteY() {
 962         // NOTE: returning this peer's location which is shell location
 963         return dimensions.getScreenBounds().y;
 964     }
 965 
 966     public int getWidth() {
 967         return getSize().width;
 968     }
 969 
 970     public int getHeight() {
 971         return getSize().height;
 972     }
 973 
 974     public final WindowDimensions getDimensions() {
 975         return dimensions;
 976     }
 977 
 978     public Point getLocationOnScreen() {
 979         XToolkit.awtLock();
 980         try {
 981             if (configure_seen) {
 982                 return toGlobal(0,0);
 983             }
 984         } finally {
 985             XToolkit.awtUnlock();
 986         }
 987         Point location = target.getLocation();
 988         if (insLog.isLoggable(PlatformLogger.Level.FINE)) {
 989             insLog.fine("getLocationOnScreen {0} not reparented: {1} ",
 990                         this, location);
 991         }
 992         return location;
 993     }
 994 
 995 
 996 /***************************************************************************************
 997  *              END            OF             I N S E T S   C O D E
 998  **************************************************************************************/
 999 
1000     protected boolean isEventDisabled(XEvent e) {
1001         switch (e.get_type()) {
1002             // Do not generate MOVED/RESIZED events since we generate them by ourselves
1003           case XConstants.ConfigureNotify:
1004               return true;
1005           case XConstants.EnterNotify:
1006           case XConstants.LeaveNotify:
1007               // Disable crossing event on outer borders of Frame so
1008               // we receive only one set of cross notifications(first set is from content window)
1009               return true;
1010           default:
1011               return super.isEventDisabled(e);
1012         }
1013     }
1014 
1015     int getDecorations() {
1016         return winAttr.decorations;
1017     }
1018 
1019     int getFunctions() {
1020         return winAttr.functions;
1021     }
1022 
1023     public void setVisible(boolean vis) {
1024         if (log.isLoggable(PlatformLogger.Level.FINER)) {
1025             log.finer("Setting {0} to visible {1}", this, Boolean.valueOf(vis));
1026         }
1027         if (vis && !isVisible()) {
1028             XWM.setShellDecor(this);
1029             super.setVisible(vis);
1030             if (winAttr.isResizable) {
1031                 //Fix for 4320050: Minimum size for java.awt.Frame is not being enforced.
1032                 //We need to update frame's minimum size, not to reset it
1033                 XWM.removeSizeHints(this, XUtilConstants.PMaxSize);
1034                 updateMinimumSize();
1035             }
1036         } else {
1037             super.setVisible(vis);
1038         }
1039     }
1040 
1041     protected void suppressWmTakeFocus(boolean doSuppress) {
1042         XAtomList protocols = getWMProtocols();
1043         if (doSuppress) {
1044             protocols.remove(wm_take_focus);
1045         } else {
1046             protocols.add(wm_take_focus);
1047         }
1048         wm_protocols.setAtomListProperty(this, protocols);
1049     }
1050 
1051     public void dispose() {
1052         if (content != null) {
1053             content.destroy();
1054         }
1055         focusProxy.destroy();
1056 
1057         if (iconWindow != null) {
1058             iconWindow.destroy();
1059         }
1060 
1061         super.dispose();
1062     }
1063 
1064     public void handleClientMessage(XEvent xev) {
1065         super.handleClientMessage(xev);
1066         XClientMessageEvent cl = xev.get_xclient();
1067         if ((wm_protocols != null) && (cl.get_message_type() == wm_protocols.getAtom())) {
1068             if (cl.get_data(0) == wm_delete_window.getAtom()) {
1069                 handleQuit();
1070             } else if (cl.get_data(0) == wm_take_focus.getAtom()) {
1071                 handleWmTakeFocus(cl);
1072             }
1073         }
1074     }
1075 
1076     private void handleWmTakeFocus(XClientMessageEvent cl) {
1077         if (focusLog.isLoggable(PlatformLogger.Level.FINE)) {
1078             focusLog.fine("WM_TAKE_FOCUS on {0}", this);
1079         }
1080 
1081         if (XWM.getWMID() == XWM.UNITY_COMPIZ_WM) {
1082             // JDK-8159460
1083             Window focusedWindow = XKeyboardFocusManagerPeer.getInstance()
1084                     .getCurrentFocusedWindow();
1085             Window activeWindow = XWindowPeer.getDecoratedOwner(focusedWindow);
1086             if (activeWindow != target) {
1087                 requestWindowFocus(cl.get_data(1), true);
1088             } else {
1089                 WindowEvent we = new WindowEvent(focusedWindow,
1090                         WindowEvent.WINDOW_GAINED_FOCUS);
1091                 sendEvent(we);
1092             }
1093         } else {
1094             requestWindowFocus(cl.get_data(1), true);
1095         }
1096     }
1097 
1098     /**
1099      * Requests focus to this decorated top-level by requesting X input focus
1100      * to the shell window.
1101      */
1102     protected void requestXFocus(long time, boolean timeProvided) {
1103         // We have proxied focus mechanism - instead of shell the focus is held
1104         // by "proxy" - invisible mapped window. When we want to set X input focus to
1105         // toplevel set it on proxy instead.
1106         if (focusProxy == null) {
1107             if (focusLog.isLoggable(PlatformLogger.Level.WARNING)) {
1108                 focusLog.warning("Focus proxy is null for " + this);
1109             }
1110         } else {
1111             if (focusLog.isLoggable(PlatformLogger.Level.FINE)) {
1112                 focusLog.fine("Requesting focus to proxy: " + focusProxy);
1113             }
1114             if (timeProvided) {
1115                 focusProxy.xRequestFocus(time);
1116             } else {
1117                 focusProxy.xRequestFocus();
1118             }
1119         }
1120     }
1121 
1122     XFocusProxyWindow getFocusProxy() {
1123         return focusProxy;
1124     }
1125 
1126     private void handleQuit() {
1127         postEvent(new WindowEvent((Window)target, WindowEvent.WINDOW_CLOSING));
1128     }
1129 
1130     final void dumpMe() {
1131         System.err.println(">>> Peer: " + x + ", " + y + ", " + width + ", " + height);
1132     }
1133 
1134     final void dumpTarget() {
1135         AWTAccessor.ComponentAccessor compAccessor = AWTAccessor.getComponentAccessor();
1136         int getWidth = compAccessor.getWidth(target);
1137         int getHeight = compAccessor.getHeight(target);
1138         int getTargetX = compAccessor.getX(target);
1139         int getTargetY = compAccessor.getY(target);
1140         System.err.println(">>> Target: " + getTargetX + ", " + getTargetY + ", " + getWidth + ", " + getHeight);
1141     }
1142 
1143     final void dumpShell() {
1144         dumpWindow("Shell", getShell());
1145     }
1146     final void dumpContent() {
1147         dumpWindow("Content", getContentWindow());
1148     }
1149     final void dumpParent() {
1150         long parent = XlibUtil.getParentWindow(getShell());
1151         if (parent != 0)
1152         {
1153             dumpWindow("Parent", parent);
1154         }
1155         else
1156         {
1157             System.err.println(">>> NO PARENT");
1158         }
1159     }
1160 
1161     final void dumpWindow(String id, long window) {
1162         XWindowAttributes pattr = new XWindowAttributes();
1163         try {
1164             XToolkit.awtLock();
1165             try {
1166                 int status =
1167                     XlibWrapper.XGetWindowAttributes(XToolkit.getDisplay(),
1168                                                      window, pattr.pData);
1169             }
1170             finally {
1171                 XToolkit.awtUnlock();
1172             }
1173             System.err.println(">>>> " + id + ": " + pattr.get_x()
1174                                + ", " + pattr.get_y() + ", " + pattr.get_width()
1175                                + ", " + pattr.get_height());
1176         } finally {
1177             pattr.dispose();
1178         }
1179     }
1180 
1181     final void dumpAll() {
1182         dumpTarget();
1183         dumpMe();
1184         dumpParent();
1185         dumpShell();
1186         dumpContent();
1187     }
1188 
1189     boolean isMaximized() {
1190         return false;
1191     }
1192 
1193     @Override
1194     boolean isOverrideRedirect() {
1195         return Window.Type.POPUP.equals(getWindowType());
1196     }
1197 
1198     public boolean requestWindowFocus(long time, boolean timeProvided) {
1199         focusLog.fine("Request for decorated window focus");
1200         // If this is Frame or Dialog we can't assure focus request success - but we still can try
1201         // If this is Window and its owner Frame is active we can be sure request succedded.
1202         Window focusedWindow = XKeyboardFocusManagerPeer.getInstance().getCurrentFocusedWindow();
1203         Window activeWindow = XWindowPeer.getDecoratedOwner(focusedWindow);
1204 
1205         if (focusLog.isLoggable(PlatformLogger.Level.FINER)) {
1206             focusLog.finer("Current window is: active={0}, focused={1}",
1207                        Boolean.valueOf(target == activeWindow),
1208                        Boolean.valueOf(target == focusedWindow));
1209         }
1210 
1211         XWindowPeer toFocus = this;
1212         while (toFocus.nextTransientFor != null) {
1213             toFocus = toFocus.nextTransientFor;
1214         }
1215         if (toFocus == null || !toFocus.focusAllowedFor()) {
1216             // This might change when WM will have property to determine focus policy.
1217             // Right now, because policy is unknown we can't be sure we succedded
1218             return false;
1219         }
1220         if (this == toFocus) {
1221             if (isWMStateNetHidden()) {
1222                 focusLog.fine("The window is unmapped, so rejecting the request");
1223                 return false;
1224             }
1225             if (target == activeWindow && target != focusedWindow) {
1226                 // Happens when an owned window is currently focused
1227                 focusLog.fine("Focus is on child window - transferring it back to the owner");
1228                 handleWindowFocusInSync(-1);
1229                 return true;
1230             }
1231             Window realNativeFocusedWindow = XWindowPeer.getNativeFocusedWindow();
1232             if (focusLog.isLoggable(PlatformLogger.Level.FINEST)) {
1233                 focusLog.finest("Real native focused window: " + realNativeFocusedWindow +
1234                             "\nKFM's focused window: " + focusedWindow);
1235             }
1236 
1237             // A workaround for Metacity. See 6522725, 6613426, 7147075.
1238             if (target == realNativeFocusedWindow && XWM.getWMID() == XWM.METACITY_WM) {
1239                 if (focusLog.isLoggable(PlatformLogger.Level.FINE)) {
1240                     focusLog.fine("The window is already natively focused.");
1241                 }
1242                 return true;
1243             }
1244         }
1245         if (focusLog.isLoggable(PlatformLogger.Level.FINE)) {
1246             focusLog.fine("Requesting focus to " + (this == toFocus ? "this window" : toFocus));
1247         }
1248 
1249         if (timeProvided) {
1250             toFocus.requestXFocus(time);
1251         } else {
1252             toFocus.requestXFocus();
1253         }
1254         return (this == toFocus);
1255     }
1256 
1257     XWindowPeer actualFocusedWindow = null;
1258     void setActualFocusedWindow(XWindowPeer actualFocusedWindow) {
1259         synchronized(getStateLock()) {
1260             this.actualFocusedWindow = actualFocusedWindow;
1261         }
1262     }
1263 
1264     boolean requestWindowFocus(XWindowPeer actualFocusedWindow,
1265                                long time, boolean timeProvided)
1266     {
1267         setActualFocusedWindow(actualFocusedWindow);
1268         return requestWindowFocus(time, timeProvided);
1269     }
1270     public void handleWindowFocusIn(long serial) {
1271         if (null == actualFocusedWindow) {
1272             super.handleWindowFocusIn(serial);
1273         } else {
1274             /*
1275              * Fix for 6314575.
1276              * If this is a result of clicking on one of the Frame's component
1277              * then 'actualFocusedWindow' shouldn't be focused. A decision of focusing
1278              * it or not should be made after the appropriate Java mouse event (if any)
1279              * is handled by the component where 'actualFocusedWindow' value may be reset.
1280              *
1281              * The fix is based on the empiric fact consisting in that the component
1282              * receives native mouse event nearly at the same time the Frame receives
1283              * WM_TAKE_FOCUS (when FocusIn is generated via XSetInputFocus call) but
1284              * definetely before the Frame gets FocusIn event (when this method is called).
1285              */
1286             postEvent(new InvocationEvent(target, new Runnable() {
1287                 public void run() {
1288                     XWindowPeer fw = null;
1289                     synchronized (getStateLock()) {
1290                         fw = actualFocusedWindow;
1291                         actualFocusedWindow = null;
1292                         if (null == fw || !fw.isVisible() || !fw.isFocusableWindow()) {
1293                             fw = XDecoratedPeer.this;
1294                         }
1295                     }
1296                     fw.handleWindowFocusIn_Dispatch();
1297                 }
1298             }));
1299         }
1300     }
1301 
1302     public void handleWindowFocusOut(Window oppositeWindow, long serial) {
1303         Window actualFocusedWindow = XKeyboardFocusManagerPeer.getInstance().getCurrentFocusedWindow();
1304 
1305         // If the actual focused window is not this decorated window then retain it.
1306         if (actualFocusedWindow != null && actualFocusedWindow != target) {
1307             Window owner = XWindowPeer.getDecoratedOwner(actualFocusedWindow);
1308 
1309             if (owner != null && owner == target) {
1310                 setActualFocusedWindow(AWTAccessor.getComponentAccessor().getPeer(actualFocusedWindow));
1311             }
1312         }
1313         super.handleWindowFocusOut(oppositeWindow, serial);
1314     }
1315 }