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