src/solaris/classes/sun/awt/X11/XWM.java

Print this page




 131           case LG3D_WM:
 132               return "LookingGlass";
 133           case CWM_WM:
 134               return "CWM";
 135           case MUTTER_WM:
 136               return "Mutter";
 137           case UNDETERMINED_WM:
 138           default:
 139               return "Undetermined WM";
 140         }
 141     }
 142 
 143 
 144     int WMID;
 145     static final Insets zeroInsets = new Insets(0, 0, 0, 0);
 146     static final Insets defaultInsets = new Insets(25, 5, 5, 5);
 147 
 148     XWM(int WMID) {
 149         this.WMID = WMID;
 150         initializeProtocols();
 151         if (log.isLoggable(PlatformLogger.FINE)) {
 152             log.fine("Window manager: " + toString());
 153         }
 154     }
 155     int getID() {
 156         return WMID;
 157     }
 158 
 159 
 160     static Insets normalize(Insets insets) {
 161         if (insets.top > 64 || insets.top < 0) {
 162             insets.top = 28;
 163         }
 164         if (insets.left > 32 || insets.left < 0) {
 165             insets.left = 6;
 166         }
 167         if (insets.right > 32 || insets.right < 0) {
 168             insets.right = 6;
 169         }
 170         if (insets.bottom > 32 || insets.bottom < 0) {
 171             insets.bottom = 6;


 237      *
 238      * No selection owner, but, perhaps it is not ICCCM compliant WM
 239      * (e.g. CDE/Sawfish).
 240      * Try selecting for SubstructureRedirect, that only one client
 241      * can select for, and if the request fails, than some other WM is
 242      * already running.
 243      *
 244      * We also treat eXcursion as NO_WM.
 245      */
 246     private static boolean isNoWM() {
 247         /*
 248          * Quick checks for specific servers.
 249          */
 250         String vendor_string = XlibWrapper.ServerVendor(XToolkit.getDisplay());
 251         if (vendor_string.indexOf("eXcursion") != -1) {
 252             /*
 253              * Use NO_WM since in all other aspects eXcursion is like not
 254              * having a window manager running. I.e. it does not reparent
 255              * top level shells.
 256              */
 257             if (insLog.isLoggable(PlatformLogger.FINER)) {
 258                 insLog.finer("eXcursion means NO_WM");
 259             }
 260             return true;
 261         }
 262 
 263         XSetWindowAttributes substruct = new XSetWindowAttributes();
 264         try {
 265             /*
 266              * Let's check an owner of WM_Sn selection for the default screen.
 267              */
 268             final long default_screen_number =
 269                 XlibWrapper.DefaultScreen(XToolkit.getDisplay());
 270             final String selection_name = "WM_S" + default_screen_number;
 271 
 272             long selection_owner =
 273                 XlibWrapper.XGetSelectionOwner(XToolkit.getDisplay(),
 274                                                XAtom.get(selection_name).getAtom());
 275             if (insLog.isLoggable(PlatformLogger.FINER)) {
 276                 insLog.finer("selection owner of " + selection_name
 277                              + " is " + selection_owner);
 278             }
 279 
 280             if (selection_owner != XConstants.None) {
 281                 return false;
 282             }
 283 
 284             winmgr_running = false;
 285             substruct.set_event_mask(XConstants.SubstructureRedirectMask);
 286 
 287             XErrorHandlerUtil.WITH_XERROR_HANDLER(detectWMHandler);
 288             XlibWrapper.XChangeWindowAttributes(XToolkit.getDisplay(),
 289                                                 XToolkit.getDefaultRootWindow(),
 290                                                 XConstants.CWEventMask,
 291                                                 substruct.pData);
 292             XErrorHandlerUtil.RESTORE_XERROR_HANDLER();
 293 
 294             /*
 295              * If no WM is running then our selection for SubstructureRedirect
 296              * succeeded and needs to be undone (hey we are *not* a WM ;-).
 297              */
 298             if (!winmgr_running) {
 299                 substruct.set_event_mask(0);
 300                 XlibWrapper.XChangeWindowAttributes(XToolkit.getDisplay(),
 301                                                     XToolkit.getDefaultRootWindow(),
 302                                                     XConstants.CWEventMask,
 303                                                     substruct.pData);
 304                 if (insLog.isLoggable(PlatformLogger.FINER)) {
 305                     insLog.finer("It looks like there is no WM thus NO_WM");
 306                 }
 307             }
 308 
 309             return !winmgr_running;
 310         } finally {
 311             substruct.dispose();
 312         }
 313     }
 314 
 315     static XAtom XA_ENLIGHTENMENT_COMMS = new XAtom("ENLIGHTENMENT_COMMS", false);
 316     /*
 317      * Helper function for isEnlightenment().
 318      * Enlightenment uses STRING property for its comms window id.  Gaaa!
 319      * The property is ENLIGHTENMENT_COMMS, STRING/8 and the string format
 320      * is "WINID %8x".  Gee, I haven't been using scanf for *ages*... :-)
 321      */
 322     static long getECommsWindowIDProperty(long window) {
 323 
 324         if (!XA_ENLIGHTENMENT_COMMS.isInterned()) {


 328         WindowPropertyGetter getter =
 329             new WindowPropertyGetter(window, XA_ENLIGHTENMENT_COMMS, 0, 14, false,
 330                                      XAtom.XA_STRING);
 331         try {
 332             int status = getter.execute(XErrorHandler.IgnoreBadWindowHandler.getInstance());
 333             if (status != XConstants.Success || getter.getData() == 0) {
 334                 return 0;
 335             }
 336 
 337             if (getter.getActualType() != XAtom.XA_STRING
 338                 || getter.getActualFormat() != 8
 339                 || getter.getNumberOfItems() != 14 || getter.getBytesAfter() != 0)
 340             {
 341                 return 0;
 342             }
 343 
 344             // Convert data to String, ASCII
 345             byte[] bytes = XlibWrapper.getStringBytes(getter.getData());
 346             String id = new String(bytes);
 347 
 348             if (log.isLoggable(PlatformLogger.FINER)) {
 349                 log.finer("ENLIGHTENMENT_COMMS is " + id);
 350             }
 351 
 352             // Parse WINID
 353             Pattern winIdPat = Pattern.compile("WINID\\s+(\\p{XDigit}{0,8})");
 354             try {
 355                 Matcher match = winIdPat.matcher(id);
 356                 if (match.matches()) {
 357                     if (log.isLoggable(PlatformLogger.FINEST)) {
 358                         log.finest("Match group count: " + match.groupCount());
 359                     }
 360                     String longId = match.group(1);
 361                     if (log.isLoggable(PlatformLogger.FINEST)) {
 362                         log.finest("Match group 1 " + longId);
 363                     }
 364                     long winid = Long.parseLong(longId, 16);
 365                     if (log.isLoggable(PlatformLogger.FINER)) {
 366                         log.finer("Enlightenment communication window " + winid);
 367                     }
 368                     return winid;
 369                 } else {
 370                     log.finer("ENLIGHTENMENT_COMMS has wrong format");
 371                     return 0;
 372                 }
 373             } catch (Exception e) {
 374                 if (log.isLoggable(PlatformLogger.FINER)) {
 375                     e.printStackTrace();
 376                 }
 377                 return 0;
 378             }
 379         } finally {
 380             getter.dispose();
 381         }
 382     }
 383 
 384     /*
 385      * Is Enlightenment WM running?  Congruent to awt_wm_checkAnchor, but
 386      * uses STRING property peculiar to Enlightenment.
 387      */
 388     static boolean isEnlightenment() {
 389 
 390         long root_xref = getECommsWindowIDProperty(XToolkit.getDefaultRootWindow());
 391         if (root_xref == 0) {
 392             return false;
 393         }
 394 


 400         return true;
 401     }
 402 
 403     /*
 404      * Is CDE running?
 405      *
 406      * XXX: This is hairy...  CDE is MWM as well.  It seems we simply test
 407      * for default setup and will be bitten if user changes things...
 408      *
 409      * Check for _DT_SM_WINDOW_INFO(_DT_SM_WINDOW_INFO) on root.  Take the
 410      * second element of the property and check for presence of
 411      * _DT_SM_STATE_INFO(_DT_SM_STATE_INFO) on that window.
 412      *
 413      * XXX: Any header that defines this structures???
 414      */
 415     static final XAtom XA_DT_SM_WINDOW_INFO = new XAtom("_DT_SM_WINDOW_INFO", false);
 416     static final XAtom XA_DT_SM_STATE_INFO = new XAtom("_DT_SM_STATE_INFO", false);
 417     static boolean isCDE() {
 418 
 419         if (!XA_DT_SM_WINDOW_INFO.isInterned()) {
 420             if (log.isLoggable(PlatformLogger.FINER)) {
 421                 log.finer("{0} is not interned", XA_DT_SM_WINDOW_INFO);
 422             }
 423             return false;
 424         }
 425 
 426         WindowPropertyGetter getter =
 427             new WindowPropertyGetter(XToolkit.getDefaultRootWindow(),
 428                                      XA_DT_SM_WINDOW_INFO, 0, 2,
 429                                      false, XA_DT_SM_WINDOW_INFO);
 430         try {
 431             int status = getter.execute();
 432             if (status != XConstants.Success || getter.getData() == 0) {
 433                 log.finer("Getting of _DT_SM_WINDOW_INFO is not successfull");
 434                 return false;
 435             }
 436             if (getter.getActualType() != XA_DT_SM_WINDOW_INFO.getAtom()
 437                 || getter.getActualFormat() != 32
 438                 || getter.getNumberOfItems() != 2 || getter.getBytesAfter() != 0)
 439             {
 440                 log.finer("Wrong format of _DT_SM_WINDOW_INFO");
 441                 return false;
 442             }
 443 
 444             long wmwin = Native.getWindow(getter.getData(), 1); //unsafe.getInt(getter.getData()+4);
 445 
 446             if (wmwin == 0) {
 447                 log.fine("WARNING: DT_SM_WINDOW_INFO exists but returns zero windows");
 448                 return false;
 449             }
 450 
 451             /* Now check that this window has _DT_SM_STATE_INFO (ignore contents) */
 452             if (!XA_DT_SM_STATE_INFO.isInterned()) {
 453                 if (log.isLoggable(PlatformLogger.FINER)) {
 454                     log.finer("{0} is not interned", XA_DT_SM_STATE_INFO);
 455                 }
 456                 return false;
 457             }
 458             WindowPropertyGetter getter2 =
 459                 new WindowPropertyGetter(wmwin, XA_DT_SM_STATE_INFO, 0, 1,
 460                                          false, XA_DT_SM_STATE_INFO);
 461             try {
 462                 status = getter2.execute(XErrorHandler.IgnoreBadWindowHandler.getInstance());
 463 
 464 
 465                 if (status != XConstants.Success || getter2.getData() == 0) {
 466                     log.finer("Getting of _DT_SM_STATE_INFO is not successfull");
 467                     return false;
 468                 }
 469                 if (getter2.getActualType() != XA_DT_SM_STATE_INFO.getAtom()
 470                     || getter2.getActualFormat() != 32)
 471                 {
 472                     log.finer("Wrong format of _DT_SM_STATE_INFO");
 473                     return false;


 607      *
 608      * But messing with PropertyNotify here is way too much trouble, so
 609      * approximate the check by setting the property in this function and
 610      * checking if it still exists later on.
 611      *
 612      * Gaa, dirty dances...
 613      */
 614     static final XAtom XA_ICEWM_WINOPTHINT = new XAtom("_ICEWM_WINOPTHINT", false);
 615     static final char opt[] = {
 616         'A','W','T','_','I','C','E','W','M','_','T','E','S','T','\0',
 617         'a','l','l','W','o','r','k','s','p','a','c','e','s','\0',
 618         '0','\0'
 619     };
 620     static boolean prepareIsIceWM() {
 621         /*
 622          * Choose something innocuous: "AWT_ICEWM_TEST allWorkspaces 0".
 623          * IceWM expects "class\0option\0arg\0" with zero bytes as delimiters.
 624          */
 625 
 626         if (!XA_ICEWM_WINOPTHINT.isInterned()) {
 627             if (log.isLoggable(PlatformLogger.FINER)) {
 628                 log.finer("{0} is not interned", XA_ICEWM_WINOPTHINT);
 629             }
 630             return false;
 631         }
 632 
 633         XToolkit.awtLock();
 634         try {
 635             XErrorHandlerUtil.WITH_XERROR_HANDLER(XErrorHandler.VerifyChangePropertyHandler.getInstance());
 636             XlibWrapper.XChangePropertyS(XToolkit.getDisplay(), XToolkit.getDefaultRootWindow(),
 637                                          XA_ICEWM_WINOPTHINT.getAtom(),
 638                                          XA_ICEWM_WINOPTHINT.getAtom(),
 639                                          8, XConstants.PropModeReplace,
 640                                          new String(opt));
 641             XErrorHandlerUtil.RESTORE_XERROR_HANDLER();
 642 
 643             if ((XErrorHandlerUtil.saved_error != null) &&
 644                 (XErrorHandlerUtil.saved_error.get_error_code() != XConstants.Success)) {
 645                 log.finer("Erorr getting XA_ICEWM_WINOPTHINT property");
 646                 return false;
 647             }
 648             log.finer("Prepared for IceWM detection");
 649             return true;
 650         } finally {
 651             XToolkit.awtUnlock();
 652         }
 653     }
 654 
 655     /*
 656      * Is IceWM running?
 657      *
 658      * Note well: Only call this if awt_wm_prepareIsIceWM succeeded, or a
 659      * false positive will be reported.
 660      */
 661     static boolean isIceWM() {
 662         if (!XA_ICEWM_WINOPTHINT.isInterned()) {
 663             if (log.isLoggable(PlatformLogger.FINER)) {
 664                 log.finer("{0} is not interned", XA_ICEWM_WINOPTHINT);
 665             }
 666             return false;
 667         }
 668 
 669         WindowPropertyGetter getter =
 670             new WindowPropertyGetter(XToolkit.getDefaultRootWindow(),
 671                                      XA_ICEWM_WINOPTHINT, 0, 0xFFFF,
 672                                      true, XA_ICEWM_WINOPTHINT);
 673         try {
 674             int status = getter.execute();
 675             boolean res = (status == XConstants.Success && getter.getActualType() != 0);
 676             if (log.isLoggable(PlatformLogger.FINER)) {
 677                 log.finer("Status getting XA_ICEWM_WINOPTHINT: " + !res);
 678             }
 679             return !res || isNetWMName("IceWM");
 680         } finally {
 681             getter.dispose();
 682         }
 683     }
 684 
 685     /*
 686      * Is OpenLook WM running?
 687      *
 688      * This one is pretty lame, but the only property peculiar to OLWM is
 689      * _SUN_WM_PROTOCOLS(ATOM[]).  Fortunately, olwm deletes it on exit.
 690      */
 691     static final XAtom XA_SUN_WM_PROTOCOLS = new XAtom("_SUN_WM_PROTOCOLS", false);
 692     static boolean isOpenLook() {
 693         if (!XA_SUN_WM_PROTOCOLS.isInterned()) {
 694             return false;
 695         }
 696 


 712                 winmgr_running = true;
 713                 return 0;
 714             }
 715             return super.handleError(display, err);
 716         }
 717     };
 718 
 719     /*
 720      * Make an educated guess about running window manager.
 721      * XXX: ideally, we should detect wm restart.
 722      */
 723     static int awt_wmgr = XWM.UNDETERMINED_WM;
 724     static XWM wm;
 725     static XWM getWM() {
 726         if (wm == null) {
 727             wm = new XWM(awt_wmgr = getWMID()/*XWM.OTHER_WM*/);
 728         }
 729         return wm;
 730     }
 731     static int getWMID() {
 732         if (insLog.isLoggable(PlatformLogger.FINEST)) {
 733             insLog.finest("awt_wmgr = " + awt_wmgr);
 734         }
 735         /*
 736          * Ideally, we should support cases when a different WM is started
 737          * during a Java app lifetime.
 738          */
 739 
 740         if (awt_wmgr != XWM.UNDETERMINED_WM) {
 741             return awt_wmgr;
 742         }
 743 
 744         XSetWindowAttributes substruct = new XSetWindowAttributes();
 745         XToolkit.awtLock();
 746         try {
 747             if (isNoWM()) {
 748                 awt_wmgr = XWM.NO_WM;
 749                 return awt_wmgr;
 750             }
 751 
 752             // Initialize _NET protocol - used to detect Window Manager.
 753             // Later, WM will initialize its own version of protocol
 754             XNETProtocol l_net_protocol = g_net_protocol = new XNETProtocol();
 755             l_net_protocol.detect();
 756             if (log.isLoggable(PlatformLogger.FINE) && l_net_protocol.active()) {
 757                 log.fine("_NET_WM_NAME is " + l_net_protocol.getWMName());
 758             }
 759             XWINProtocol win = g_win_protocol = new XWINProtocol();
 760             win.detect();
 761 
 762             /* actual check for IceWM to follow below */
 763             boolean doIsIceWM = prepareIsIceWM(); /* and let IceWM to act */
 764 
 765             /*
 766              * Ok, some WM is out there.  Check which one by testing for
 767              * "distinguishing" atoms.
 768              */
 769             if (isEnlightenment()) {
 770                 awt_wmgr = XWM.ENLIGHTEN_WM;
 771             } else if (isMetacity()) {
 772                 awt_wmgr = XWM.METACITY_WM;
 773             } else if (isMutter()) {
 774                 awt_wmgr = XWM.MUTTER_WM;
 775             } else if (isSawfish()) {
 776                 awt_wmgr = XWM.SAWFISH_WM;


 820  * Size and decoration hints ...
 821  *
 822 \*****************************************************************************/
 823 
 824 
 825     /*
 826      * Remove size hints specified by the mask.
 827      * XXX: Why do we need this in the first place???
 828      */
 829     static void removeSizeHints(XDecoratedPeer window, long mask) {
 830         mask &= XUtilConstants.PMaxSize | XUtilConstants.PMinSize;
 831 
 832         XToolkit.awtLock();
 833         try {
 834             XSizeHints hints = window.getHints();
 835             if ((hints.get_flags() & mask) == 0) {
 836                 return;
 837             }
 838 
 839             hints.set_flags(hints.get_flags() & ~mask);
 840             if (insLog.isLoggable(PlatformLogger.FINER)) {
 841                 insLog.finer("Setting hints, flags " + XlibWrapper.hintsToString(hints.get_flags()));
 842             }
 843             XlibWrapper.XSetWMNormalHints(XToolkit.getDisplay(),
 844                                           window.getWindow(),
 845                                           hints.pData);
 846         } finally {
 847             XToolkit.awtUnlock();
 848         }
 849     }
 850 
 851     /*
 852      * If MWM_DECOR_ALL bit is set, then the rest of the bit-mask is taken
 853      * to be subtracted from the decorations.  Normalize decoration spec
 854      * so that we can map motif decor to something else bit-by-bit in the
 855      * rest of the code.
 856      */
 857     static int normalizeMotifDecor(int decorations) {
 858         if ((decorations & MWMConstants.MWM_DECOR_ALL) == 0) {
 859             return decorations;
 860         }


 879         int f = MWMConstants.MWM_FUNC_RESIZE |
 880                 MWMConstants.MWM_FUNC_MOVE |
 881                 MWMConstants.MWM_FUNC_MAXIMIZE |
 882                 MWMConstants.MWM_FUNC_MINIMIZE |
 883                 MWMConstants.MWM_FUNC_CLOSE;
 884         f &= ~functions;
 885         return f;
 886     }
 887 
 888     /*
 889      * Infer OL properties from MWM decorations.
 890      * Use _OL_DECOR_DEL(ATOM[]) to remove unwanted ones.
 891      */
 892     static void setOLDecor(XWindow window, boolean resizable, int decorations) {
 893         if (window == null) {
 894             return;
 895         }
 896 
 897         XAtomList decorDel = new XAtomList();
 898         decorations = normalizeMotifDecor(decorations);
 899         if (insLog.isLoggable(PlatformLogger.FINER)) {
 900             insLog.finer("Setting OL_DECOR to " + Integer.toBinaryString(decorations));
 901         }
 902         if ((decorations & MWMConstants.MWM_DECOR_TITLE) == 0) {
 903             decorDel.add(XA_OL_DECOR_HEADER);
 904         }
 905         if ((decorations & (MWMConstants.MWM_DECOR_RESIZEH | MWMConstants.MWM_DECOR_MAXIMIZE)) == 0) {
 906             decorDel.add(XA_OL_DECOR_RESIZE);
 907         }
 908         if ((decorations & (MWMConstants.MWM_DECOR_MENU |
 909                             MWMConstants.MWM_DECOR_MAXIMIZE |
 910                             MWMConstants.MWM_DECOR_MINIMIZE)) == 0)
 911         {
 912             decorDel.add(XA_OL_DECOR_CLOSE);
 913         }
 914         if (decorDel.size() == 0) {
 915             insLog.finer("Deleting OL_DECOR");
 916             XA_OL_DECOR_DEL.DeleteProperty(window);
 917         } else {
 918             if (insLog.isLoggable(PlatformLogger.FINER)) {
 919                 insLog.finer("Setting OL_DECOR to " + decorDel);
 920             }
 921             XA_OL_DECOR_DEL.setAtomListProperty(window, decorDel);
 922         }
 923     }
 924 
 925     /*
 926      * Set MWM decorations.  Set MWM functions depending on resizability.
 927      */
 928     static void setMotifDecor(XWindow window, boolean resizable, int decorations, int functions) {
 929         /* Apparently some WMs don't implement MWM_*_ALL semantic correctly */
 930         if ((decorations & MWMConstants.MWM_DECOR_ALL) != 0
 931             && (decorations != MWMConstants.MWM_DECOR_ALL))
 932         {
 933             decorations = normalizeMotifDecor(decorations);
 934         }
 935         if ((functions & MWMConstants.MWM_FUNC_ALL) != 0
 936             && (functions != MWMConstants.MWM_FUNC_ALL))
 937         {
 938             functions = normalizeMotifFunc(functions);
 939         }
 940 
 941         PropMwmHints hints = window.getMWMHints();
 942         hints.set_flags(hints.get_flags() |
 943                         MWMConstants.MWM_HINTS_FUNCTIONS |
 944                         MWMConstants.MWM_HINTS_DECORATIONS);
 945         hints.set_functions(functions);
 946         hints.set_decorations(decorations);
 947 
 948         if (stateLog.isLoggable(PlatformLogger.FINER)) {
 949             stateLog.finer("Setting MWM_HINTS to " + hints);
 950         }
 951         window.setMWMHints(hints);
 952     }
 953 
 954     /*
 955      * Under some window managers if shell is already mapped, we MUST
 956      * unmap and later remap in order to effect the changes we make in the
 957      * window manager decorations.
 958      *
 959      * N.B.  This unmapping / remapping of the shell exposes a bug in
 960      * X/Motif or the Motif Window Manager.  When you attempt to map a
 961      * widget which is positioned (partially) off-screen, the window is
 962      * relocated to be entirely on screen. Good idea.  But if both the x
 963      * and the y coordinates are less than the origin (0,0), the first
 964      * (re)map will move the window to the origin, and any subsequent
 965      * (re)map will relocate the window at some other point on the screen.
 966      * I have written a short Motif test program to discover this bug.
 967      * This should occur infrequently and it does not cause any real
 968      * problem.  So for now we'll let it be.


 992         setMotifDecor(window, resizable, decorations, functions);
 993         setOLDecor(window, resizable, decorations);
 994 
 995         /* Some WMs need remap to redecorate the window */
 996         if (window.isShowing() && needRemap(window)) {
 997             /*
 998              * Do the re/mapping at the Xlib level.  Since we essentially
 999              * work around a WM bug we don't want this hack to be exposed
1000              * to Intrinsics (i.e. don't mess with grabs, callbacks etc).
1001              */
1002             window.xSetVisible(false);
1003             XToolkit.XSync();
1004             window.xSetVisible(true);
1005         }
1006     }
1007 
1008     /*
1009      * Make specified shell resizable.
1010      */
1011     static void setShellResizable(XDecoratedPeer window) {
1012         if (insLog.isLoggable(PlatformLogger.FINE)) {
1013             insLog.fine("Setting shell resizable " + window);
1014         }
1015         XToolkit.awtLock();
1016         try {
1017             Rectangle shellBounds = window.getShellBounds();
1018             shellBounds.translate(-window.currentInsets.left, -window.currentInsets.top);
1019             window.updateSizeHints(window.getDimensions());
1020             requestWMExtents(window.getWindow());
1021             XlibWrapper.XMoveResizeWindow(XToolkit.getDisplay(), window.getShell(),
1022                                           shellBounds.x, shellBounds.y, shellBounds.width, shellBounds.height);
1023             /* REMINDER: will need to revisit when setExtendedStateBounds is added */
1024             //Fix for 4320050: Minimum size for java.awt.Frame is not being enforced.
1025             //We need to update frame's minimum size, not to reset it
1026             removeSizeHints(window, XUtilConstants.PMaxSize);
1027             window.updateMinimumSize();
1028 
1029             /* Restore decorations */
1030             setShellDecor(window);
1031         } finally {
1032             XToolkit.awtUnlock();
1033         }
1034     }
1035 
1036     /*
1037      * Make specified shell non-resizable.
1038      * If justChangeSize is false, update decorations as well.
1039      * @param shellBounds bounds of the shell window
1040      */
1041     static void setShellNotResizable(XDecoratedPeer window, WindowDimensions newDimensions, Rectangle shellBounds,
1042                                      boolean justChangeSize)
1043     {
1044         if (insLog.isLoggable(PlatformLogger.FINE)) {
1045             insLog.fine("Setting non-resizable shell " + window + ", dimensions " + newDimensions +
1046                         ", shellBounds " + shellBounds +", just change size: " + justChangeSize);
1047         }
1048         XToolkit.awtLock();
1049         try {
1050             /* Fix min/max size hints at the specified values */
1051             if (!shellBounds.isEmpty()) {
1052                 window.updateSizeHints(newDimensions);
1053                 requestWMExtents(window.getWindow());
1054                 XToolkit.XSync();
1055                 XlibWrapper.XMoveResizeWindow(XToolkit.getDisplay(), window.getShell(),
1056                                               shellBounds.x, shellBounds.y, shellBounds.width, shellBounds.height);
1057             }
1058             if (!justChangeSize) {  /* update decorations */
1059                 setShellDecor(window);
1060             }
1061         } finally {
1062             XToolkit.awtUnlock();
1063         }
1064     }


1158  *
1159  * Notice window state change when WM changes a property on the window ...
1160  *
1161 \*****************************************************************************/
1162 
1163 
1164     /*
1165      * Check if property change is a window state protocol message.
1166      */
1167     boolean isStateChange(XDecoratedPeer window, XPropertyEvent e) {
1168         if (!window.isShowing()) {
1169             stateLog.finer("Window is not showing");
1170             return false;
1171         }
1172 
1173         int wm_state = window.getWMState();
1174         if (wm_state == XUtilConstants.WithdrawnState) {
1175             stateLog.finer("WithdrawnState");
1176             return false;
1177         } else {
1178             if (stateLog.isLoggable(PlatformLogger.FINER)) {
1179                 stateLog.finer("Window WM_STATE is " + wm_state);
1180             }
1181         }
1182         boolean is_state_change = false;
1183         if (e.get_atom() == XA_WM_STATE.getAtom()) {
1184             is_state_change = true;
1185         }
1186 
1187         for (XStateProtocol proto : getProtocols(XStateProtocol.class)) {
1188             is_state_change |= proto.isStateChange(e);
1189             if (stateLog.isLoggable(PlatformLogger.FINEST)) {
1190                 stateLog.finest(proto + ": is state changed = " + is_state_change);
1191             }
1192         }
1193         return is_state_change;
1194     }
1195 
1196     /*
1197      * Returns current state (including extended) of a given window.
1198      */
1199     int getState(XDecoratedPeer window) {
1200         int res = 0;
1201         final int wm_state = window.getWMState();
1202         if (wm_state == XUtilConstants.IconicState) {
1203             res = Frame.ICONIFIED;
1204         } else {
1205             res = Frame.NORMAL;
1206         }
1207         res |= getExtendedState(window);
1208         return res;
1209     }


1323     Insets guessInsets(XDecoratedPeer window) {
1324         Insets res = (Insets)storedInsets.get(window.getClass());
1325         if (res == null) {
1326             switch (WMID) {
1327               case ENLIGHTEN_WM:
1328                   res = new Insets(19, 4, 4, 4);
1329                   break;
1330               case CDE_WM:
1331                   res = new Insets(28, 6, 6, 6);
1332                   break;
1333               case NO_WM:
1334               case LG3D_WM:
1335                   res = zeroInsets;
1336                   break;
1337               case MOTIF_WM:
1338               case OPENLOOK_WM:
1339               default:
1340                   res = defaultInsets;
1341             }
1342         }
1343         if (insLog.isLoggable(PlatformLogger.FINEST)) {
1344             insLog.finest("WM guessed insets: " + res);
1345         }
1346         return res;
1347     }
1348     /*
1349      * Some buggy WMs ignore window gravity when processing
1350      * ConfigureRequest and position window as if the gravity is Static.
1351      * We work around this in MWindowPeer.pReshape().
1352      *
1353      * Starting with 1.5 we have introduced an Environment variable
1354      * _JAVA_AWT_WM_STATIC_GRAVITY that can be set to indicate to Java
1355      * explicitly that the WM has this behaviour, example is FVWM.
1356      */
1357 
1358     static int awtWMStaticGravity = -1;
1359     static boolean configureGravityBuggy() {
1360 
1361         if (awtWMStaticGravity == -1) {
1362             awtWMStaticGravity = (XToolkit.getEnv("_JAVA_AWT_WM_STATIC_GRAVITY") != null) ? 1 : 0;
1363         }


1394               return true;
1395           case XWM.ENLIGHTEN_WM:
1396               /* At least E16 is buggy. */
1397               return true;
1398           default:
1399               return false;
1400         }
1401     }
1402 
1403     /*
1404      * @return if WM implements the insets property - returns insets with values
1405      * specified in that property, null otherwise.
1406      */
1407     public static Insets getInsetsFromExtents(long window) {
1408         if (window == XConstants.None) {
1409             return null;
1410         }
1411         XNETProtocol net_protocol = getWM().getNETProtocol();
1412         if (net_protocol != null && net_protocol.active()) {
1413             Insets insets = getInsetsFromProp(window, XA_NET_FRAME_EXTENTS);
1414             if (insLog.isLoggable(PlatformLogger.FINE)) {
1415                 insLog.fine("_NET_FRAME_EXTENTS: {0}", insets);
1416             }
1417 
1418             if (insets != null) {
1419                 return insets;
1420             }
1421         }
1422         switch(getWMID()) {
1423           case XWM.KDE2_WM:
1424               return getInsetsFromProp(window, XA_KDE_NET_WM_FRAME_STRUT);
1425           case XWM.ENLIGHTEN_WM:
1426               return getInsetsFromProp(window, XA_E_FRAME_SIZE);
1427           default:
1428               return null;
1429         }
1430     }
1431 
1432     /**
1433      * Helper function reads property of type CARDINAL[4] = { left, right, top, bottom }
1434      * and converts it to Insets object.


1537          * peeking at it.  [Future versions of wm-spec might add a
1538          * standardized hint for this].
1539          *
1540          * Otherwise we do some special casing.  Actually the
1541          * fallback code ("default" case) seems to cover most of
1542          * the existing WMs (modulo Reparent/Configure order
1543          * perhaps?).
1544          *
1545          * Fallback code tries to account for the two most common cases:
1546          *
1547          * . single reparenting
1548          *       parent window is the WM frame
1549          *       [twm, olwm, sawfish]
1550          *
1551          * . double reparenting
1552          *       parent is a lining exactly the size of the client
1553          *       grandpa is the WM frame
1554          *       [mwm, e!, kwin, fvwm2 ... ]
1555          */
1556         Insets correctWM = XWM.getInsetsFromExtents(window);
1557         if (insLog.isLoggable(PlatformLogger.FINER)) {
1558             insLog.finer("Got insets from property: {0}", correctWM);
1559         }
1560 
1561         if (correctWM == null) {
1562             correctWM = new Insets(0,0,0,0);
1563 
1564             correctWM.top = -1;
1565             correctWM.left = -1;
1566 
1567             XWindowAttributes lwinAttr = new XWindowAttributes();
1568             XWindowAttributes pattr = new XWindowAttributes();
1569             try {
1570                 switch (XWM.getWMID()) {
1571                   /* should've been done in awt_wm_getInsetsFromProp */
1572                   case XWM.ENLIGHTEN_WM: {
1573                       /* enlightenment does double reparenting */
1574                       syncTopLevelPos(parent, lwinAttr);
1575                       correctWM.left = lwinAttr.get_x();
1576                       correctWM.top = lwinAttr.get_y();
1577                       /*


1600                           correctWM.left = lwinAttr.get_x();
1601                           correctWM.right = correctWM.left;
1602                           correctWM.bottom = correctWM.left;
1603                       } else {
1604                           return null;
1605                       }
1606                       break;
1607                   }
1608                   case XWM.SAWFISH_WM:
1609                   case XWM.OPENLOOK_WM: {
1610                       /* single reparenting */
1611                       syncTopLevelPos(window, lwinAttr);
1612                       correctWM.top    = lwinAttr.get_y();
1613                       correctWM.left   = lwinAttr.get_x();
1614                       correctWM.right  = correctWM.left;
1615                       correctWM.bottom = correctWM.left;
1616                       break;
1617                   }
1618                   case XWM.OTHER_WM:
1619                   default: {                /* this is very similar to the E! case above */
1620                       if (insLog.isLoggable(PlatformLogger.FINEST)) {
1621                           insLog.finest("Getting correct insets for OTHER_WM/default, parent: {0}", parent);
1622                       }
1623                       syncTopLevelPos(parent, lwinAttr);
1624                       int status = XlibWrapper.XGetWindowAttributes(XToolkit.getDisplay(),
1625                                                                     window, lwinAttr.pData);
1626                       status = XlibWrapper.XGetWindowAttributes(XToolkit.getDisplay(),
1627                                                                 parent, pattr.pData);
1628                       if (lwinAttr.get_root() == parent) {
1629                           insLog.finest("our parent is root so insets should be zero");
1630                           correctWM = new Insets(0, 0, 0, 0);
1631                           break;
1632                       }
1633 
1634                       /*
1635                        * Check for double-reparenting WM.
1636                        *
1637                        * If the parent is exactly the same size as the
1638                        * top-level assume taht it's the "lining" window and
1639                        * that the grandparent is the actual frame (NB: we
1640                        * have already handled undecorated windows).
1641                        *
1642                        * XXX: what about timing issues that syncTopLevelPos
1643                        * is supposed to work around?
1644                        */
1645                       if (lwinAttr.get_x() == 0 && lwinAttr.get_y() == 0
1646                           && lwinAttr.get_width()+2*lwinAttr.get_border_width() == pattr.get_width()
1647                           && lwinAttr.get_height()+2*lwinAttr.get_border_width() == pattr.get_height())
1648                       {
1649                           if (insLog.isLoggable(PlatformLogger.FINEST)) {
1650                               insLog.finest("Double reparenting detected, pattr({2})={0}, lwinAttr({3})={1}",
1651                                         lwinAttr, pattr, parent, window);
1652                           }
1653                           lwinAttr.set_x(pattr.get_x());
1654                           lwinAttr.set_y(pattr.get_y());
1655                           lwinAttr.set_border_width(lwinAttr.get_border_width()+pattr.get_border_width());
1656 
1657                           final long grand_parent = XlibUtil.getParentWindow(parent);
1658 
1659                           if (grand_parent == lwinAttr.get_root()) {
1660                               // This is not double-reparenting in a
1661                               // general sense - we simply don't have
1662                               // correct insets - return null to try to
1663                               // get insets later
1664                               return null;
1665                           } else {
1666                               parent = grand_parent;
1667                               XlibWrapper.XGetWindowAttributes(XToolkit.getDisplay(),
1668                                                                parent,
1669                                                                pattr.pData);
1670                           }
1671                       }
1672                       /*
1673                        * XXX: To be absolutely correct, we'd need to take
1674                        * parent's border-width into account too, but the
1675                        * rest of the code is happily unaware about border
1676                        * widths and inner/outer distinction, so for the time
1677                        * being, just ignore it.
1678                        */
1679                       if (insLog.isLoggable(PlatformLogger.FINEST)) {
1680                           insLog.finest("Attrs before calculation: pattr({2})={0}, lwinAttr({3})={1}",
1681                                     lwinAttr, pattr, parent, window);
1682                       }
1683                       correctWM = new Insets(lwinAttr.get_y() + lwinAttr.get_border_width(),
1684                                              lwinAttr.get_x() + lwinAttr.get_border_width(),
1685                                              pattr.get_height() - (lwinAttr.get_y() + lwinAttr.get_height() + 2*lwinAttr.get_border_width()),
1686                                              pattr.get_width() -  (lwinAttr.get_x() + lwinAttr.get_width() + 2*lwinAttr.get_border_width()));
1687                       break;
1688                   } /* default */
1689                 } /* switch (runningWM) */
1690             } finally {
1691                 lwinAttr.dispose();
1692                 pattr.dispose();
1693             }
1694         }
1695         if (storedInsets.get(win.getClass()) == null) {
1696             storedInsets.put(win.getClass(), correctWM);
1697         }
1698         return correctWM;
1699     }




 131           case LG3D_WM:
 132               return "LookingGlass";
 133           case CWM_WM:
 134               return "CWM";
 135           case MUTTER_WM:
 136               return "Mutter";
 137           case UNDETERMINED_WM:
 138           default:
 139               return "Undetermined WM";
 140         }
 141     }
 142 
 143 
 144     int WMID;
 145     static final Insets zeroInsets = new Insets(0, 0, 0, 0);
 146     static final Insets defaultInsets = new Insets(25, 5, 5, 5);
 147 
 148     XWM(int WMID) {
 149         this.WMID = WMID;
 150         initializeProtocols();
 151         if (log.isLoggable(PlatformLogger.Level.FINE)) {
 152             log.fine("Window manager: " + toString());
 153         }
 154     }
 155     int getID() {
 156         return WMID;
 157     }
 158 
 159 
 160     static Insets normalize(Insets insets) {
 161         if (insets.top > 64 || insets.top < 0) {
 162             insets.top = 28;
 163         }
 164         if (insets.left > 32 || insets.left < 0) {
 165             insets.left = 6;
 166         }
 167         if (insets.right > 32 || insets.right < 0) {
 168             insets.right = 6;
 169         }
 170         if (insets.bottom > 32 || insets.bottom < 0) {
 171             insets.bottom = 6;


 237      *
 238      * No selection owner, but, perhaps it is not ICCCM compliant WM
 239      * (e.g. CDE/Sawfish).
 240      * Try selecting for SubstructureRedirect, that only one client
 241      * can select for, and if the request fails, than some other WM is
 242      * already running.
 243      *
 244      * We also treat eXcursion as NO_WM.
 245      */
 246     private static boolean isNoWM() {
 247         /*
 248          * Quick checks for specific servers.
 249          */
 250         String vendor_string = XlibWrapper.ServerVendor(XToolkit.getDisplay());
 251         if (vendor_string.indexOf("eXcursion") != -1) {
 252             /*
 253              * Use NO_WM since in all other aspects eXcursion is like not
 254              * having a window manager running. I.e. it does not reparent
 255              * top level shells.
 256              */
 257             if (insLog.isLoggable(PlatformLogger.Level.FINER)) {
 258                 insLog.finer("eXcursion means NO_WM");
 259             }
 260             return true;
 261         }
 262 
 263         XSetWindowAttributes substruct = new XSetWindowAttributes();
 264         try {
 265             /*
 266              * Let's check an owner of WM_Sn selection for the default screen.
 267              */
 268             final long default_screen_number =
 269                 XlibWrapper.DefaultScreen(XToolkit.getDisplay());
 270             final String selection_name = "WM_S" + default_screen_number;
 271 
 272             long selection_owner =
 273                 XlibWrapper.XGetSelectionOwner(XToolkit.getDisplay(),
 274                                                XAtom.get(selection_name).getAtom());
 275             if (insLog.isLoggable(PlatformLogger.Level.FINER)) {
 276                 insLog.finer("selection owner of " + selection_name
 277                              + " is " + selection_owner);
 278             }
 279 
 280             if (selection_owner != XConstants.None) {
 281                 return false;
 282             }
 283 
 284             winmgr_running = false;
 285             substruct.set_event_mask(XConstants.SubstructureRedirectMask);
 286 
 287             XErrorHandlerUtil.WITH_XERROR_HANDLER(detectWMHandler);
 288             XlibWrapper.XChangeWindowAttributes(XToolkit.getDisplay(),
 289                                                 XToolkit.getDefaultRootWindow(),
 290                                                 XConstants.CWEventMask,
 291                                                 substruct.pData);
 292             XErrorHandlerUtil.RESTORE_XERROR_HANDLER();
 293 
 294             /*
 295              * If no WM is running then our selection for SubstructureRedirect
 296              * succeeded and needs to be undone (hey we are *not* a WM ;-).
 297              */
 298             if (!winmgr_running) {
 299                 substruct.set_event_mask(0);
 300                 XlibWrapper.XChangeWindowAttributes(XToolkit.getDisplay(),
 301                                                     XToolkit.getDefaultRootWindow(),
 302                                                     XConstants.CWEventMask,
 303                                                     substruct.pData);
 304                 if (insLog.isLoggable(PlatformLogger.Level.FINER)) {
 305                     insLog.finer("It looks like there is no WM thus NO_WM");
 306                 }
 307             }
 308 
 309             return !winmgr_running;
 310         } finally {
 311             substruct.dispose();
 312         }
 313     }
 314 
 315     static XAtom XA_ENLIGHTENMENT_COMMS = new XAtom("ENLIGHTENMENT_COMMS", false);
 316     /*
 317      * Helper function for isEnlightenment().
 318      * Enlightenment uses STRING property for its comms window id.  Gaaa!
 319      * The property is ENLIGHTENMENT_COMMS, STRING/8 and the string format
 320      * is "WINID %8x".  Gee, I haven't been using scanf for *ages*... :-)
 321      */
 322     static long getECommsWindowIDProperty(long window) {
 323 
 324         if (!XA_ENLIGHTENMENT_COMMS.isInterned()) {


 328         WindowPropertyGetter getter =
 329             new WindowPropertyGetter(window, XA_ENLIGHTENMENT_COMMS, 0, 14, false,
 330                                      XAtom.XA_STRING);
 331         try {
 332             int status = getter.execute(XErrorHandler.IgnoreBadWindowHandler.getInstance());
 333             if (status != XConstants.Success || getter.getData() == 0) {
 334                 return 0;
 335             }
 336 
 337             if (getter.getActualType() != XAtom.XA_STRING
 338                 || getter.getActualFormat() != 8
 339                 || getter.getNumberOfItems() != 14 || getter.getBytesAfter() != 0)
 340             {
 341                 return 0;
 342             }
 343 
 344             // Convert data to String, ASCII
 345             byte[] bytes = XlibWrapper.getStringBytes(getter.getData());
 346             String id = new String(bytes);
 347 
 348             if (log.isLoggable(PlatformLogger.Level.FINER)) {
 349                 log.finer("ENLIGHTENMENT_COMMS is " + id);
 350             }
 351 
 352             // Parse WINID
 353             Pattern winIdPat = Pattern.compile("WINID\\s+(\\p{XDigit}{0,8})");
 354             try {
 355                 Matcher match = winIdPat.matcher(id);
 356                 if (match.matches()) {
 357                     if (log.isLoggable(PlatformLogger.Level.FINEST)) {
 358                         log.finest("Match group count: " + match.groupCount());
 359                     }
 360                     String longId = match.group(1);
 361                     if (log.isLoggable(PlatformLogger.Level.FINEST)) {
 362                         log.finest("Match group 1 " + longId);
 363                     }
 364                     long winid = Long.parseLong(longId, 16);
 365                     if (log.isLoggable(PlatformLogger.Level.FINER)) {
 366                         log.finer("Enlightenment communication window " + winid);
 367                     }
 368                     return winid;
 369                 } else {
 370                     log.finer("ENLIGHTENMENT_COMMS has wrong format");
 371                     return 0;
 372                 }
 373             } catch (Exception e) {
 374                 if (log.isLoggable(PlatformLogger.Level.FINER)) {
 375                     e.printStackTrace();
 376                 }
 377                 return 0;
 378             }
 379         } finally {
 380             getter.dispose();
 381         }
 382     }
 383 
 384     /*
 385      * Is Enlightenment WM running?  Congruent to awt_wm_checkAnchor, but
 386      * uses STRING property peculiar to Enlightenment.
 387      */
 388     static boolean isEnlightenment() {
 389 
 390         long root_xref = getECommsWindowIDProperty(XToolkit.getDefaultRootWindow());
 391         if (root_xref == 0) {
 392             return false;
 393         }
 394 


 400         return true;
 401     }
 402 
 403     /*
 404      * Is CDE running?
 405      *
 406      * XXX: This is hairy...  CDE is MWM as well.  It seems we simply test
 407      * for default setup and will be bitten if user changes things...
 408      *
 409      * Check for _DT_SM_WINDOW_INFO(_DT_SM_WINDOW_INFO) on root.  Take the
 410      * second element of the property and check for presence of
 411      * _DT_SM_STATE_INFO(_DT_SM_STATE_INFO) on that window.
 412      *
 413      * XXX: Any header that defines this structures???
 414      */
 415     static final XAtom XA_DT_SM_WINDOW_INFO = new XAtom("_DT_SM_WINDOW_INFO", false);
 416     static final XAtom XA_DT_SM_STATE_INFO = new XAtom("_DT_SM_STATE_INFO", false);
 417     static boolean isCDE() {
 418 
 419         if (!XA_DT_SM_WINDOW_INFO.isInterned()) {
 420             if (log.isLoggable(PlatformLogger.Level.FINER)) {
 421                 log.finer("{0} is not interned", XA_DT_SM_WINDOW_INFO);
 422             }
 423             return false;
 424         }
 425 
 426         WindowPropertyGetter getter =
 427             new WindowPropertyGetter(XToolkit.getDefaultRootWindow(),
 428                                      XA_DT_SM_WINDOW_INFO, 0, 2,
 429                                      false, XA_DT_SM_WINDOW_INFO);
 430         try {
 431             int status = getter.execute();
 432             if (status != XConstants.Success || getter.getData() == 0) {
 433                 log.finer("Getting of _DT_SM_WINDOW_INFO is not successfull");
 434                 return false;
 435             }
 436             if (getter.getActualType() != XA_DT_SM_WINDOW_INFO.getAtom()
 437                 || getter.getActualFormat() != 32
 438                 || getter.getNumberOfItems() != 2 || getter.getBytesAfter() != 0)
 439             {
 440                 log.finer("Wrong format of _DT_SM_WINDOW_INFO");
 441                 return false;
 442             }
 443 
 444             long wmwin = Native.getWindow(getter.getData(), 1); //unsafe.getInt(getter.getData()+4);
 445 
 446             if (wmwin == 0) {
 447                 log.fine("WARNING: DT_SM_WINDOW_INFO exists but returns zero windows");
 448                 return false;
 449             }
 450 
 451             /* Now check that this window has _DT_SM_STATE_INFO (ignore contents) */
 452             if (!XA_DT_SM_STATE_INFO.isInterned()) {
 453                 if (log.isLoggable(PlatformLogger.Level.FINER)) {
 454                     log.finer("{0} is not interned", XA_DT_SM_STATE_INFO);
 455                 }
 456                 return false;
 457             }
 458             WindowPropertyGetter getter2 =
 459                 new WindowPropertyGetter(wmwin, XA_DT_SM_STATE_INFO, 0, 1,
 460                                          false, XA_DT_SM_STATE_INFO);
 461             try {
 462                 status = getter2.execute(XErrorHandler.IgnoreBadWindowHandler.getInstance());
 463 
 464 
 465                 if (status != XConstants.Success || getter2.getData() == 0) {
 466                     log.finer("Getting of _DT_SM_STATE_INFO is not successfull");
 467                     return false;
 468                 }
 469                 if (getter2.getActualType() != XA_DT_SM_STATE_INFO.getAtom()
 470                     || getter2.getActualFormat() != 32)
 471                 {
 472                     log.finer("Wrong format of _DT_SM_STATE_INFO");
 473                     return false;


 607      *
 608      * But messing with PropertyNotify here is way too much trouble, so
 609      * approximate the check by setting the property in this function and
 610      * checking if it still exists later on.
 611      *
 612      * Gaa, dirty dances...
 613      */
 614     static final XAtom XA_ICEWM_WINOPTHINT = new XAtom("_ICEWM_WINOPTHINT", false);
 615     static final char opt[] = {
 616         'A','W','T','_','I','C','E','W','M','_','T','E','S','T','\0',
 617         'a','l','l','W','o','r','k','s','p','a','c','e','s','\0',
 618         '0','\0'
 619     };
 620     static boolean prepareIsIceWM() {
 621         /*
 622          * Choose something innocuous: "AWT_ICEWM_TEST allWorkspaces 0".
 623          * IceWM expects "class\0option\0arg\0" with zero bytes as delimiters.
 624          */
 625 
 626         if (!XA_ICEWM_WINOPTHINT.isInterned()) {
 627             if (log.isLoggable(PlatformLogger.Level.FINER)) {
 628                 log.finer("{0} is not interned", XA_ICEWM_WINOPTHINT);
 629             }
 630             return false;
 631         }
 632 
 633         XToolkit.awtLock();
 634         try {
 635             XErrorHandlerUtil.WITH_XERROR_HANDLER(XErrorHandler.VerifyChangePropertyHandler.getInstance());
 636             XlibWrapper.XChangePropertyS(XToolkit.getDisplay(), XToolkit.getDefaultRootWindow(),
 637                                          XA_ICEWM_WINOPTHINT.getAtom(),
 638                                          XA_ICEWM_WINOPTHINT.getAtom(),
 639                                          8, XConstants.PropModeReplace,
 640                                          new String(opt));
 641             XErrorHandlerUtil.RESTORE_XERROR_HANDLER();
 642 
 643             if ((XErrorHandlerUtil.saved_error != null) &&
 644                 (XErrorHandlerUtil.saved_error.get_error_code() != XConstants.Success)) {
 645                 log.finer("Erorr getting XA_ICEWM_WINOPTHINT property");
 646                 return false;
 647             }
 648             log.finer("Prepared for IceWM detection");
 649             return true;
 650         } finally {
 651             XToolkit.awtUnlock();
 652         }
 653     }
 654 
 655     /*
 656      * Is IceWM running?
 657      *
 658      * Note well: Only call this if awt_wm_prepareIsIceWM succeeded, or a
 659      * false positive will be reported.
 660      */
 661     static boolean isIceWM() {
 662         if (!XA_ICEWM_WINOPTHINT.isInterned()) {
 663             if (log.isLoggable(PlatformLogger.Level.FINER)) {
 664                 log.finer("{0} is not interned", XA_ICEWM_WINOPTHINT);
 665             }
 666             return false;
 667         }
 668 
 669         WindowPropertyGetter getter =
 670             new WindowPropertyGetter(XToolkit.getDefaultRootWindow(),
 671                                      XA_ICEWM_WINOPTHINT, 0, 0xFFFF,
 672                                      true, XA_ICEWM_WINOPTHINT);
 673         try {
 674             int status = getter.execute();
 675             boolean res = (status == XConstants.Success && getter.getActualType() != 0);
 676             if (log.isLoggable(PlatformLogger.Level.FINER)) {
 677                 log.finer("Status getting XA_ICEWM_WINOPTHINT: " + !res);
 678             }
 679             return !res || isNetWMName("IceWM");
 680         } finally {
 681             getter.dispose();
 682         }
 683     }
 684 
 685     /*
 686      * Is OpenLook WM running?
 687      *
 688      * This one is pretty lame, but the only property peculiar to OLWM is
 689      * _SUN_WM_PROTOCOLS(ATOM[]).  Fortunately, olwm deletes it on exit.
 690      */
 691     static final XAtom XA_SUN_WM_PROTOCOLS = new XAtom("_SUN_WM_PROTOCOLS", false);
 692     static boolean isOpenLook() {
 693         if (!XA_SUN_WM_PROTOCOLS.isInterned()) {
 694             return false;
 695         }
 696 


 712                 winmgr_running = true;
 713                 return 0;
 714             }
 715             return super.handleError(display, err);
 716         }
 717     };
 718 
 719     /*
 720      * Make an educated guess about running window manager.
 721      * XXX: ideally, we should detect wm restart.
 722      */
 723     static int awt_wmgr = XWM.UNDETERMINED_WM;
 724     static XWM wm;
 725     static XWM getWM() {
 726         if (wm == null) {
 727             wm = new XWM(awt_wmgr = getWMID()/*XWM.OTHER_WM*/);
 728         }
 729         return wm;
 730     }
 731     static int getWMID() {
 732         if (insLog.isLoggable(PlatformLogger.Level.FINEST)) {
 733             insLog.finest("awt_wmgr = " + awt_wmgr);
 734         }
 735         /*
 736          * Ideally, we should support cases when a different WM is started
 737          * during a Java app lifetime.
 738          */
 739 
 740         if (awt_wmgr != XWM.UNDETERMINED_WM) {
 741             return awt_wmgr;
 742         }
 743 
 744         XSetWindowAttributes substruct = new XSetWindowAttributes();
 745         XToolkit.awtLock();
 746         try {
 747             if (isNoWM()) {
 748                 awt_wmgr = XWM.NO_WM;
 749                 return awt_wmgr;
 750             }
 751 
 752             // Initialize _NET protocol - used to detect Window Manager.
 753             // Later, WM will initialize its own version of protocol
 754             XNETProtocol l_net_protocol = g_net_protocol = new XNETProtocol();
 755             l_net_protocol.detect();
 756             if (log.isLoggable(PlatformLogger.Level.FINE) && l_net_protocol.active()) {
 757                 log.fine("_NET_WM_NAME is " + l_net_protocol.getWMName());
 758             }
 759             XWINProtocol win = g_win_protocol = new XWINProtocol();
 760             win.detect();
 761 
 762             /* actual check for IceWM to follow below */
 763             boolean doIsIceWM = prepareIsIceWM(); /* and let IceWM to act */
 764 
 765             /*
 766              * Ok, some WM is out there.  Check which one by testing for
 767              * "distinguishing" atoms.
 768              */
 769             if (isEnlightenment()) {
 770                 awt_wmgr = XWM.ENLIGHTEN_WM;
 771             } else if (isMetacity()) {
 772                 awt_wmgr = XWM.METACITY_WM;
 773             } else if (isMutter()) {
 774                 awt_wmgr = XWM.MUTTER_WM;
 775             } else if (isSawfish()) {
 776                 awt_wmgr = XWM.SAWFISH_WM;


 820  * Size and decoration hints ...
 821  *
 822 \*****************************************************************************/
 823 
 824 
 825     /*
 826      * Remove size hints specified by the mask.
 827      * XXX: Why do we need this in the first place???
 828      */
 829     static void removeSizeHints(XDecoratedPeer window, long mask) {
 830         mask &= XUtilConstants.PMaxSize | XUtilConstants.PMinSize;
 831 
 832         XToolkit.awtLock();
 833         try {
 834             XSizeHints hints = window.getHints();
 835             if ((hints.get_flags() & mask) == 0) {
 836                 return;
 837             }
 838 
 839             hints.set_flags(hints.get_flags() & ~mask);
 840             if (insLog.isLoggable(PlatformLogger.Level.FINER)) {
 841                 insLog.finer("Setting hints, flags " + XlibWrapper.hintsToString(hints.get_flags()));
 842             }
 843             XlibWrapper.XSetWMNormalHints(XToolkit.getDisplay(),
 844                                           window.getWindow(),
 845                                           hints.pData);
 846         } finally {
 847             XToolkit.awtUnlock();
 848         }
 849     }
 850 
 851     /*
 852      * If MWM_DECOR_ALL bit is set, then the rest of the bit-mask is taken
 853      * to be subtracted from the decorations.  Normalize decoration spec
 854      * so that we can map motif decor to something else bit-by-bit in the
 855      * rest of the code.
 856      */
 857     static int normalizeMotifDecor(int decorations) {
 858         if ((decorations & MWMConstants.MWM_DECOR_ALL) == 0) {
 859             return decorations;
 860         }


 879         int f = MWMConstants.MWM_FUNC_RESIZE |
 880                 MWMConstants.MWM_FUNC_MOVE |
 881                 MWMConstants.MWM_FUNC_MAXIMIZE |
 882                 MWMConstants.MWM_FUNC_MINIMIZE |
 883                 MWMConstants.MWM_FUNC_CLOSE;
 884         f &= ~functions;
 885         return f;
 886     }
 887 
 888     /*
 889      * Infer OL properties from MWM decorations.
 890      * Use _OL_DECOR_DEL(ATOM[]) to remove unwanted ones.
 891      */
 892     static void setOLDecor(XWindow window, boolean resizable, int decorations) {
 893         if (window == null) {
 894             return;
 895         }
 896 
 897         XAtomList decorDel = new XAtomList();
 898         decorations = normalizeMotifDecor(decorations);
 899         if (insLog.isLoggable(PlatformLogger.Level.FINER)) {
 900             insLog.finer("Setting OL_DECOR to " + Integer.toBinaryString(decorations));
 901         }
 902         if ((decorations & MWMConstants.MWM_DECOR_TITLE) == 0) {
 903             decorDel.add(XA_OL_DECOR_HEADER);
 904         }
 905         if ((decorations & (MWMConstants.MWM_DECOR_RESIZEH | MWMConstants.MWM_DECOR_MAXIMIZE)) == 0) {
 906             decorDel.add(XA_OL_DECOR_RESIZE);
 907         }
 908         if ((decorations & (MWMConstants.MWM_DECOR_MENU |
 909                             MWMConstants.MWM_DECOR_MAXIMIZE |
 910                             MWMConstants.MWM_DECOR_MINIMIZE)) == 0)
 911         {
 912             decorDel.add(XA_OL_DECOR_CLOSE);
 913         }
 914         if (decorDel.size() == 0) {
 915             insLog.finer("Deleting OL_DECOR");
 916             XA_OL_DECOR_DEL.DeleteProperty(window);
 917         } else {
 918             if (insLog.isLoggable(PlatformLogger.Level.FINER)) {
 919                 insLog.finer("Setting OL_DECOR to " + decorDel);
 920             }
 921             XA_OL_DECOR_DEL.setAtomListProperty(window, decorDel);
 922         }
 923     }
 924 
 925     /*
 926      * Set MWM decorations.  Set MWM functions depending on resizability.
 927      */
 928     static void setMotifDecor(XWindow window, boolean resizable, int decorations, int functions) {
 929         /* Apparently some WMs don't implement MWM_*_ALL semantic correctly */
 930         if ((decorations & MWMConstants.MWM_DECOR_ALL) != 0
 931             && (decorations != MWMConstants.MWM_DECOR_ALL))
 932         {
 933             decorations = normalizeMotifDecor(decorations);
 934         }
 935         if ((functions & MWMConstants.MWM_FUNC_ALL) != 0
 936             && (functions != MWMConstants.MWM_FUNC_ALL))
 937         {
 938             functions = normalizeMotifFunc(functions);
 939         }
 940 
 941         PropMwmHints hints = window.getMWMHints();
 942         hints.set_flags(hints.get_flags() |
 943                         MWMConstants.MWM_HINTS_FUNCTIONS |
 944                         MWMConstants.MWM_HINTS_DECORATIONS);
 945         hints.set_functions(functions);
 946         hints.set_decorations(decorations);
 947 
 948         if (stateLog.isLoggable(PlatformLogger.Level.FINER)) {
 949             stateLog.finer("Setting MWM_HINTS to " + hints);
 950         }
 951         window.setMWMHints(hints);
 952     }
 953 
 954     /*
 955      * Under some window managers if shell is already mapped, we MUST
 956      * unmap and later remap in order to effect the changes we make in the
 957      * window manager decorations.
 958      *
 959      * N.B.  This unmapping / remapping of the shell exposes a bug in
 960      * X/Motif or the Motif Window Manager.  When you attempt to map a
 961      * widget which is positioned (partially) off-screen, the window is
 962      * relocated to be entirely on screen. Good idea.  But if both the x
 963      * and the y coordinates are less than the origin (0,0), the first
 964      * (re)map will move the window to the origin, and any subsequent
 965      * (re)map will relocate the window at some other point on the screen.
 966      * I have written a short Motif test program to discover this bug.
 967      * This should occur infrequently and it does not cause any real
 968      * problem.  So for now we'll let it be.


 992         setMotifDecor(window, resizable, decorations, functions);
 993         setOLDecor(window, resizable, decorations);
 994 
 995         /* Some WMs need remap to redecorate the window */
 996         if (window.isShowing() && needRemap(window)) {
 997             /*
 998              * Do the re/mapping at the Xlib level.  Since we essentially
 999              * work around a WM bug we don't want this hack to be exposed
1000              * to Intrinsics (i.e. don't mess with grabs, callbacks etc).
1001              */
1002             window.xSetVisible(false);
1003             XToolkit.XSync();
1004             window.xSetVisible(true);
1005         }
1006     }
1007 
1008     /*
1009      * Make specified shell resizable.
1010      */
1011     static void setShellResizable(XDecoratedPeer window) {
1012         if (insLog.isLoggable(PlatformLogger.Level.FINE)) {
1013             insLog.fine("Setting shell resizable " + window);
1014         }
1015         XToolkit.awtLock();
1016         try {
1017             Rectangle shellBounds = window.getShellBounds();
1018             shellBounds.translate(-window.currentInsets.left, -window.currentInsets.top);
1019             window.updateSizeHints(window.getDimensions());
1020             requestWMExtents(window.getWindow());
1021             XlibWrapper.XMoveResizeWindow(XToolkit.getDisplay(), window.getShell(),
1022                                           shellBounds.x, shellBounds.y, shellBounds.width, shellBounds.height);
1023             /* REMINDER: will need to revisit when setExtendedStateBounds is added */
1024             //Fix for 4320050: Minimum size for java.awt.Frame is not being enforced.
1025             //We need to update frame's minimum size, not to reset it
1026             removeSizeHints(window, XUtilConstants.PMaxSize);
1027             window.updateMinimumSize();
1028 
1029             /* Restore decorations */
1030             setShellDecor(window);
1031         } finally {
1032             XToolkit.awtUnlock();
1033         }
1034     }
1035 
1036     /*
1037      * Make specified shell non-resizable.
1038      * If justChangeSize is false, update decorations as well.
1039      * @param shellBounds bounds of the shell window
1040      */
1041     static void setShellNotResizable(XDecoratedPeer window, WindowDimensions newDimensions, Rectangle shellBounds,
1042                                      boolean justChangeSize)
1043     {
1044         if (insLog.isLoggable(PlatformLogger.Level.FINE)) {
1045             insLog.fine("Setting non-resizable shell " + window + ", dimensions " + newDimensions +
1046                         ", shellBounds " + shellBounds +", just change size: " + justChangeSize);
1047         }
1048         XToolkit.awtLock();
1049         try {
1050             /* Fix min/max size hints at the specified values */
1051             if (!shellBounds.isEmpty()) {
1052                 window.updateSizeHints(newDimensions);
1053                 requestWMExtents(window.getWindow());
1054                 XToolkit.XSync();
1055                 XlibWrapper.XMoveResizeWindow(XToolkit.getDisplay(), window.getShell(),
1056                                               shellBounds.x, shellBounds.y, shellBounds.width, shellBounds.height);
1057             }
1058             if (!justChangeSize) {  /* update decorations */
1059                 setShellDecor(window);
1060             }
1061         } finally {
1062             XToolkit.awtUnlock();
1063         }
1064     }


1158  *
1159  * Notice window state change when WM changes a property on the window ...
1160  *
1161 \*****************************************************************************/
1162 
1163 
1164     /*
1165      * Check if property change is a window state protocol message.
1166      */
1167     boolean isStateChange(XDecoratedPeer window, XPropertyEvent e) {
1168         if (!window.isShowing()) {
1169             stateLog.finer("Window is not showing");
1170             return false;
1171         }
1172 
1173         int wm_state = window.getWMState();
1174         if (wm_state == XUtilConstants.WithdrawnState) {
1175             stateLog.finer("WithdrawnState");
1176             return false;
1177         } else {
1178             if (stateLog.isLoggable(PlatformLogger.Level.FINER)) {
1179                 stateLog.finer("Window WM_STATE is " + wm_state);
1180             }
1181         }
1182         boolean is_state_change = false;
1183         if (e.get_atom() == XA_WM_STATE.getAtom()) {
1184             is_state_change = true;
1185         }
1186 
1187         for (XStateProtocol proto : getProtocols(XStateProtocol.class)) {
1188             is_state_change |= proto.isStateChange(e);
1189             if (stateLog.isLoggable(PlatformLogger.Level.FINEST)) {
1190                 stateLog.finest(proto + ": is state changed = " + is_state_change);
1191             }
1192         }
1193         return is_state_change;
1194     }
1195 
1196     /*
1197      * Returns current state (including extended) of a given window.
1198      */
1199     int getState(XDecoratedPeer window) {
1200         int res = 0;
1201         final int wm_state = window.getWMState();
1202         if (wm_state == XUtilConstants.IconicState) {
1203             res = Frame.ICONIFIED;
1204         } else {
1205             res = Frame.NORMAL;
1206         }
1207         res |= getExtendedState(window);
1208         return res;
1209     }


1323     Insets guessInsets(XDecoratedPeer window) {
1324         Insets res = (Insets)storedInsets.get(window.getClass());
1325         if (res == null) {
1326             switch (WMID) {
1327               case ENLIGHTEN_WM:
1328                   res = new Insets(19, 4, 4, 4);
1329                   break;
1330               case CDE_WM:
1331                   res = new Insets(28, 6, 6, 6);
1332                   break;
1333               case NO_WM:
1334               case LG3D_WM:
1335                   res = zeroInsets;
1336                   break;
1337               case MOTIF_WM:
1338               case OPENLOOK_WM:
1339               default:
1340                   res = defaultInsets;
1341             }
1342         }
1343         if (insLog.isLoggable(PlatformLogger.Level.FINEST)) {
1344             insLog.finest("WM guessed insets: " + res);
1345         }
1346         return res;
1347     }
1348     /*
1349      * Some buggy WMs ignore window gravity when processing
1350      * ConfigureRequest and position window as if the gravity is Static.
1351      * We work around this in MWindowPeer.pReshape().
1352      *
1353      * Starting with 1.5 we have introduced an Environment variable
1354      * _JAVA_AWT_WM_STATIC_GRAVITY that can be set to indicate to Java
1355      * explicitly that the WM has this behaviour, example is FVWM.
1356      */
1357 
1358     static int awtWMStaticGravity = -1;
1359     static boolean configureGravityBuggy() {
1360 
1361         if (awtWMStaticGravity == -1) {
1362             awtWMStaticGravity = (XToolkit.getEnv("_JAVA_AWT_WM_STATIC_GRAVITY") != null) ? 1 : 0;
1363         }


1394               return true;
1395           case XWM.ENLIGHTEN_WM:
1396               /* At least E16 is buggy. */
1397               return true;
1398           default:
1399               return false;
1400         }
1401     }
1402 
1403     /*
1404      * @return if WM implements the insets property - returns insets with values
1405      * specified in that property, null otherwise.
1406      */
1407     public static Insets getInsetsFromExtents(long window) {
1408         if (window == XConstants.None) {
1409             return null;
1410         }
1411         XNETProtocol net_protocol = getWM().getNETProtocol();
1412         if (net_protocol != null && net_protocol.active()) {
1413             Insets insets = getInsetsFromProp(window, XA_NET_FRAME_EXTENTS);
1414             if (insLog.isLoggable(PlatformLogger.Level.FINE)) {
1415                 insLog.fine("_NET_FRAME_EXTENTS: {0}", insets);
1416             }
1417 
1418             if (insets != null) {
1419                 return insets;
1420             }
1421         }
1422         switch(getWMID()) {
1423           case XWM.KDE2_WM:
1424               return getInsetsFromProp(window, XA_KDE_NET_WM_FRAME_STRUT);
1425           case XWM.ENLIGHTEN_WM:
1426               return getInsetsFromProp(window, XA_E_FRAME_SIZE);
1427           default:
1428               return null;
1429         }
1430     }
1431 
1432     /**
1433      * Helper function reads property of type CARDINAL[4] = { left, right, top, bottom }
1434      * and converts it to Insets object.


1537          * peeking at it.  [Future versions of wm-spec might add a
1538          * standardized hint for this].
1539          *
1540          * Otherwise we do some special casing.  Actually the
1541          * fallback code ("default" case) seems to cover most of
1542          * the existing WMs (modulo Reparent/Configure order
1543          * perhaps?).
1544          *
1545          * Fallback code tries to account for the two most common cases:
1546          *
1547          * . single reparenting
1548          *       parent window is the WM frame
1549          *       [twm, olwm, sawfish]
1550          *
1551          * . double reparenting
1552          *       parent is a lining exactly the size of the client
1553          *       grandpa is the WM frame
1554          *       [mwm, e!, kwin, fvwm2 ... ]
1555          */
1556         Insets correctWM = XWM.getInsetsFromExtents(window);
1557         if (insLog.isLoggable(PlatformLogger.Level.FINER)) {
1558             insLog.finer("Got insets from property: {0}", correctWM);
1559         }
1560 
1561         if (correctWM == null) {
1562             correctWM = new Insets(0,0,0,0);
1563 
1564             correctWM.top = -1;
1565             correctWM.left = -1;
1566 
1567             XWindowAttributes lwinAttr = new XWindowAttributes();
1568             XWindowAttributes pattr = new XWindowAttributes();
1569             try {
1570                 switch (XWM.getWMID()) {
1571                   /* should've been done in awt_wm_getInsetsFromProp */
1572                   case XWM.ENLIGHTEN_WM: {
1573                       /* enlightenment does double reparenting */
1574                       syncTopLevelPos(parent, lwinAttr);
1575                       correctWM.left = lwinAttr.get_x();
1576                       correctWM.top = lwinAttr.get_y();
1577                       /*


1600                           correctWM.left = lwinAttr.get_x();
1601                           correctWM.right = correctWM.left;
1602                           correctWM.bottom = correctWM.left;
1603                       } else {
1604                           return null;
1605                       }
1606                       break;
1607                   }
1608                   case XWM.SAWFISH_WM:
1609                   case XWM.OPENLOOK_WM: {
1610                       /* single reparenting */
1611                       syncTopLevelPos(window, lwinAttr);
1612                       correctWM.top    = lwinAttr.get_y();
1613                       correctWM.left   = lwinAttr.get_x();
1614                       correctWM.right  = correctWM.left;
1615                       correctWM.bottom = correctWM.left;
1616                       break;
1617                   }
1618                   case XWM.OTHER_WM:
1619                   default: {                /* this is very similar to the E! case above */
1620                       if (insLog.isLoggable(PlatformLogger.Level.FINEST)) {
1621                           insLog.finest("Getting correct insets for OTHER_WM/default, parent: {0}", parent);
1622                       }
1623                       syncTopLevelPos(parent, lwinAttr);
1624                       int status = XlibWrapper.XGetWindowAttributes(XToolkit.getDisplay(),
1625                                                                     window, lwinAttr.pData);
1626                       status = XlibWrapper.XGetWindowAttributes(XToolkit.getDisplay(),
1627                                                                 parent, pattr.pData);
1628                       if (lwinAttr.get_root() == parent) {
1629                           insLog.finest("our parent is root so insets should be zero");
1630                           correctWM = new Insets(0, 0, 0, 0);
1631                           break;
1632                       }
1633 
1634                       /*
1635                        * Check for double-reparenting WM.
1636                        *
1637                        * If the parent is exactly the same size as the
1638                        * top-level assume taht it's the "lining" window and
1639                        * that the grandparent is the actual frame (NB: we
1640                        * have already handled undecorated windows).
1641                        *
1642                        * XXX: what about timing issues that syncTopLevelPos
1643                        * is supposed to work around?
1644                        */
1645                       if (lwinAttr.get_x() == 0 && lwinAttr.get_y() == 0
1646                           && lwinAttr.get_width()+2*lwinAttr.get_border_width() == pattr.get_width()
1647                           && lwinAttr.get_height()+2*lwinAttr.get_border_width() == pattr.get_height())
1648                       {
1649                           if (insLog.isLoggable(PlatformLogger.Level.FINEST)) {
1650                               insLog.finest("Double reparenting detected, pattr({2})={0}, lwinAttr({3})={1}",
1651                                         lwinAttr, pattr, parent, window);
1652                           }
1653                           lwinAttr.set_x(pattr.get_x());
1654                           lwinAttr.set_y(pattr.get_y());
1655                           lwinAttr.set_border_width(lwinAttr.get_border_width()+pattr.get_border_width());
1656 
1657                           final long grand_parent = XlibUtil.getParentWindow(parent);
1658 
1659                           if (grand_parent == lwinAttr.get_root()) {
1660                               // This is not double-reparenting in a
1661                               // general sense - we simply don't have
1662                               // correct insets - return null to try to
1663                               // get insets later
1664                               return null;
1665                           } else {
1666                               parent = grand_parent;
1667                               XlibWrapper.XGetWindowAttributes(XToolkit.getDisplay(),
1668                                                                parent,
1669                                                                pattr.pData);
1670                           }
1671                       }
1672                       /*
1673                        * XXX: To be absolutely correct, we'd need to take
1674                        * parent's border-width into account too, but the
1675                        * rest of the code is happily unaware about border
1676                        * widths and inner/outer distinction, so for the time
1677                        * being, just ignore it.
1678                        */
1679                       if (insLog.isLoggable(PlatformLogger.Level.FINEST)) {
1680                           insLog.finest("Attrs before calculation: pattr({2})={0}, lwinAttr({3})={1}",
1681                                     lwinAttr, pattr, parent, window);
1682                       }
1683                       correctWM = new Insets(lwinAttr.get_y() + lwinAttr.get_border_width(),
1684                                              lwinAttr.get_x() + lwinAttr.get_border_width(),
1685                                              pattr.get_height() - (lwinAttr.get_y() + lwinAttr.get_height() + 2*lwinAttr.get_border_width()),
1686                                              pattr.get_width() -  (lwinAttr.get_x() + lwinAttr.get_width() + 2*lwinAttr.get_border_width()));
1687                       break;
1688                   } /* default */
1689                 } /* switch (runningWM) */
1690             } finally {
1691                 lwinAttr.dispose();
1692                 pattr.dispose();
1693             }
1694         }
1695         if (storedInsets.get(win.getClass()) == null) {
1696             storedInsets.put(win.getClass(), correctWM);
1697         }
1698         return correctWM;
1699     }