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)) log.fine("Window manager: " + toString());


 152     }
 153     int getID() {
 154         return WMID;
 155     }
 156 
 157 
 158     static Insets normalize(Insets insets) {
 159         if (insets.top > 64 || insets.top < 0) {
 160             insets.top = 28;
 161         }
 162         if (insets.left > 32 || insets.left < 0) {
 163             insets.left = 6;
 164         }
 165         if (insets.right > 32 || insets.right < 0) {
 166             insets.right = 6;
 167         }
 168         if (insets.bottom > 32 || insets.bottom < 0) {
 169             insets.bottom = 6;
 170         }
 171         return insets;


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


 326         WindowPropertyGetter getter =
 327             new WindowPropertyGetter(window, XA_ENLIGHTENMENT_COMMS, 0, 14, false,
 328                                      XAtom.XA_STRING);
 329         try {
 330             int status = getter.execute(XErrorHandler.IgnoreBadWindowHandler.getInstance());
 331             if (status != XConstants.Success || getter.getData() == 0) {
 332                 return 0;
 333             }
 334 
 335             if (getter.getActualType() != XAtom.XA_STRING
 336                 || getter.getActualFormat() != 8
 337                 || getter.getNumberOfItems() != 14 || getter.getBytesAfter() != 0)
 338             {
 339                 return 0;
 340             }
 341 
 342             // Convert data to String, ASCII
 343             byte[] bytes = XlibWrapper.getStringBytes(getter.getData());
 344             String id = new String(bytes);
 345 

 346             log.finer("ENLIGHTENMENT_COMMS is " + id);

 347 
 348             // Parse WINID
 349             Pattern winIdPat = Pattern.compile("WINID\\s+(\\p{XDigit}{0,8})");
 350             try {
 351                 Matcher match = winIdPat.matcher(id);
 352                 if (match.matches()) {

 353                     log.finest("Match group count: " + match.groupCount());

 354                     String longId = match.group(1);

 355                     log.finest("Match group 1 " + longId);

 356                     long winid = Long.parseLong(longId, 16);

 357                     log.finer("Enlightenment communication window " + winid);

 358                     return winid;
 359                 } else {
 360                     log.finer("ENLIGHTENMENT_COMMS has wrong format");
 361                     return 0;
 362                 }
 363             } catch (Exception e) {
 364                 if (log.isLoggable(PlatformLogger.FINER)) {
 365                     e.printStackTrace();
 366                 }
 367                 return 0;
 368             }
 369         } finally {
 370             getter.dispose();
 371         }
 372     }
 373 
 374     /*
 375      * Is Enlightenment WM running?  Congruent to awt_wm_checkAnchor, but
 376      * uses STRING property peculiar to Enlightenment.
 377      */


 637 
 638     /*
 639      * Is IceWM running?
 640      *
 641      * Note well: Only call this if awt_wm_prepareIsIceWM succeeded, or a
 642      * false positive will be reported.
 643      */
 644     static boolean isIceWM() {
 645         if (!XA_ICEWM_WINOPTHINT.isInterned()) {
 646             log.finer("{0} is not interned", XA_ICEWM_WINOPTHINT);
 647             return false;
 648         }
 649 
 650         WindowPropertyGetter getter =
 651             new WindowPropertyGetter(XToolkit.getDefaultRootWindow(),
 652                                      XA_ICEWM_WINOPTHINT, 0, 0xFFFF,
 653                                      true, XA_ICEWM_WINOPTHINT);
 654         try {
 655             int status = getter.execute();
 656             boolean res = (status == XConstants.Success && getter.getActualType() != 0);

 657             log.finer("Status getting XA_ICEWM_WINOPTHINT: " + !res);

 658             return !res || isNetWMName("IceWM");
 659         } finally {
 660             getter.dispose();
 661         }
 662     }
 663 
 664     /*
 665      * Is OpenLook WM running?
 666      *
 667      * This one is pretty lame, but the only property peculiar to OLWM is
 668      * _SUN_WM_PROTOCOLS(ATOM[]).  Fortunately, olwm deletes it on exit.
 669      */
 670     static final XAtom XA_SUN_WM_PROTOCOLS = new XAtom("_SUN_WM_PROTOCOLS", false);
 671     static boolean isOpenLook() {
 672         if (!XA_SUN_WM_PROTOCOLS.isInterned()) {
 673             return false;
 674         }
 675 
 676         XAtom[] list = XA_SUN_WM_PROTOCOLS.getAtomListProperty(XToolkit.getDefaultRootWindow());
 677         return (list.length != 0);


 799  * Size and decoration hints ...
 800  *
 801 \*****************************************************************************/
 802 
 803 
 804     /*
 805      * Remove size hints specified by the mask.
 806      * XXX: Why do we need this in the first place???
 807      */
 808     static void removeSizeHints(XDecoratedPeer window, long mask) {
 809         mask &= XUtilConstants.PMaxSize | XUtilConstants.PMinSize;
 810 
 811         XToolkit.awtLock();
 812         try {
 813             XSizeHints hints = window.getHints();
 814             if ((hints.get_flags() & mask) == 0) {
 815                 return;
 816             }
 817 
 818             hints.set_flags(hints.get_flags() & ~mask);
 819             if (insLog.isLoggable(PlatformLogger.FINER)) insLog.finer("Setting hints, flags " + XlibWrapper.hintsToString(hints.get_flags()));


 820             XlibWrapper.XSetWMNormalHints(XToolkit.getDisplay(),
 821                                           window.getWindow(),
 822                                           hints.pData);
 823         } finally {
 824             XToolkit.awtUnlock();
 825         }
 826     }
 827 
 828     /*
 829      * If MWM_DECOR_ALL bit is set, then the rest of the bit-mask is taken
 830      * to be subtracted from the decorations.  Normalize decoration spec
 831      * so that we can map motif decor to something else bit-by-bit in the
 832      * rest of the code.
 833      */
 834     static int normalizeMotifDecor(int decorations) {
 835         if ((decorations & MWMConstants.MWM_DECOR_ALL) == 0) {
 836             return decorations;
 837         }
 838         int d = MWMConstants.MWM_DECOR_BORDER | MWMConstants.MWM_DECOR_RESIZEH
 839             | MWMConstants.MWM_DECOR_TITLE


 856         int f = MWMConstants.MWM_FUNC_RESIZE |
 857                 MWMConstants.MWM_FUNC_MOVE |
 858                 MWMConstants.MWM_FUNC_MAXIMIZE |
 859                 MWMConstants.MWM_FUNC_MINIMIZE |
 860                 MWMConstants.MWM_FUNC_CLOSE;
 861         f &= ~functions;
 862         return f;
 863     }
 864 
 865     /*
 866      * Infer OL properties from MWM decorations.
 867      * Use _OL_DECOR_DEL(ATOM[]) to remove unwanted ones.
 868      */
 869     static void setOLDecor(XWindow window, boolean resizable, int decorations) {
 870         if (window == null) {
 871             return;
 872         }
 873 
 874         XAtomList decorDel = new XAtomList();
 875         decorations = normalizeMotifDecor(decorations);
 876         if (insLog.isLoggable(PlatformLogger.FINER)) insLog.finer("Setting OL_DECOR to " + Integer.toBinaryString(decorations));


 877         if ((decorations & MWMConstants.MWM_DECOR_TITLE) == 0) {
 878             decorDel.add(XA_OL_DECOR_HEADER);
 879         }
 880         if ((decorations & (MWMConstants.MWM_DECOR_RESIZEH | MWMConstants.MWM_DECOR_MAXIMIZE)) == 0) {
 881             decorDel.add(XA_OL_DECOR_RESIZE);
 882         }
 883         if ((decorations & (MWMConstants.MWM_DECOR_MENU |
 884                             MWMConstants.MWM_DECOR_MAXIMIZE |
 885                             MWMConstants.MWM_DECOR_MINIMIZE)) == 0)
 886         {
 887             decorDel.add(XA_OL_DECOR_CLOSE);
 888         }
 889         if (decorDel.size() == 0) {
 890             insLog.finer("Deleting OL_DECOR");
 891             XA_OL_DECOR_DEL.DeleteProperty(window);
 892         } else {
 893             if (insLog.isLoggable(PlatformLogger.FINER)) insLog.finer("Setting OL_DECOR to " + decorDel);


 894             XA_OL_DECOR_DEL.setAtomListProperty(window, decorDel);
 895         }
 896     }
 897 
 898     /*
 899      * Set MWM decorations.  Set MWM functions depending on resizability.
 900      */
 901     static void setMotifDecor(XWindow window, boolean resizable, int decorations, int functions) {
 902         /* Apparently some WMs don't implement MWM_*_ALL semantic correctly */
 903         if ((decorations & MWMConstants.MWM_DECOR_ALL) != 0
 904             && (decorations != MWMConstants.MWM_DECOR_ALL))
 905         {
 906             decorations = normalizeMotifDecor(decorations);
 907         }
 908         if ((functions & MWMConstants.MWM_FUNC_ALL) != 0
 909             && (functions != MWMConstants.MWM_FUNC_ALL))
 910         {
 911             functions = normalizeMotifFunc(functions);
 912         }
 913 
 914         PropMwmHints hints = window.getMWMHints();
 915         hints.set_flags(hints.get_flags() |
 916                         MWMConstants.MWM_HINTS_FUNCTIONS |
 917                         MWMConstants.MWM_HINTS_DECORATIONS);
 918         hints.set_functions(functions);
 919         hints.set_decorations(decorations);
 920 
 921         if (stateLog.isLoggable(PlatformLogger.FINER)) stateLog.finer("Setting MWM_HINTS to " + hints);


 922         window.setMWMHints(hints);
 923     }
 924 
 925     /*
 926      * Under some window managers if shell is already mapped, we MUST
 927      * unmap and later remap in order to effect the changes we make in the
 928      * window manager decorations.
 929      *
 930      * N.B.  This unmapping / remapping of the shell exposes a bug in
 931      * X/Motif or the Motif Window Manager.  When you attempt to map a
 932      * widget which is positioned (partially) off-screen, the window is
 933      * relocated to be entirely on screen. Good idea.  But if both the x
 934      * and the y coordinates are less than the origin (0,0), the first
 935      * (re)map will move the window to the origin, and any subsequent
 936      * (re)map will relocate the window at some other point on the screen.
 937      * I have written a short Motif test program to discover this bug.
 938      * This should occur infrequently and it does not cause any real
 939      * problem.  So for now we'll let it be.
 940      */
 941     static boolean needRemap(XDecoratedPeer window) {


 963         setMotifDecor(window, resizable, decorations, functions);
 964         setOLDecor(window, resizable, decorations);
 965 
 966         /* Some WMs need remap to redecorate the window */
 967         if (window.isShowing() && needRemap(window)) {
 968             /*
 969              * Do the re/mapping at the Xlib level.  Since we essentially
 970              * work around a WM bug we don't want this hack to be exposed
 971              * to Intrinsics (i.e. don't mess with grabs, callbacks etc).
 972              */
 973             window.xSetVisible(false);
 974             XToolkit.XSync();
 975             window.xSetVisible(true);
 976         }
 977     }
 978 
 979     /*
 980      * Make specified shell resizable.
 981      */
 982     static void setShellResizable(XDecoratedPeer window) {
 983         if (insLog.isLoggable(PlatformLogger.FINE)) insLog.fine("Setting shell resizable " + window);


 984         XToolkit.awtLock();
 985         try {
 986             Rectangle shellBounds = window.getShellBounds();
 987             shellBounds.translate(-window.currentInsets.left, -window.currentInsets.top);
 988             window.updateSizeHints(window.getDimensions());
 989             requestWMExtents(window.getWindow());
 990             XlibWrapper.XMoveResizeWindow(XToolkit.getDisplay(), window.getShell(),
 991                                           shellBounds.x, shellBounds.y, shellBounds.width, shellBounds.height);
 992             /* REMINDER: will need to revisit when setExtendedStateBounds is added */
 993             //Fix for 4320050: Minimum size for java.awt.Frame is not being enforced.
 994             //We need to update frame's minimum size, not to reset it
 995             removeSizeHints(window, XUtilConstants.PMaxSize);
 996             window.updateMinimumSize();
 997 
 998             /* Restore decorations */
 999             setShellDecor(window);
1000         } finally {
1001             XToolkit.awtUnlock();
1002         }
1003     }
1004 
1005     /*
1006      * Make specified shell non-resizable.
1007      * If justChangeSize is false, update decorations as well.
1008      * @param shellBounds bounds of the shell window
1009      */
1010     static void setShellNotResizable(XDecoratedPeer window, WindowDimensions newDimensions, Rectangle shellBounds,
1011                                      boolean justChangeSize)
1012     {
1013         if (insLog.isLoggable(PlatformLogger.FINE)) insLog.fine("Setting non-resizable shell " + window + ", dimensions " + newDimensions +

1014                                                        ", shellBounds " + shellBounds +", just change size: " + justChangeSize);

1015         XToolkit.awtLock();
1016         try {
1017             /* Fix min/max size hints at the specified values */
1018             if (!shellBounds.isEmpty()) {
1019                 window.updateSizeHints(newDimensions);
1020                 requestWMExtents(window.getWindow());
1021                 XToolkit.XSync();
1022                 XlibWrapper.XMoveResizeWindow(XToolkit.getDisplay(), window.getShell(),
1023                                               shellBounds.x, shellBounds.y, shellBounds.width, shellBounds.height);
1024             }
1025             if (!justChangeSize) {  /* update decorations */
1026                 setShellDecor(window);
1027             }
1028         } finally {
1029             XToolkit.awtUnlock();
1030         }
1031     }
1032 
1033 /*****************************************************************************\
1034  * Protocols support


1125  *
1126  * Notice window state change when WM changes a property on the window ...
1127  *
1128 \*****************************************************************************/
1129 
1130 
1131     /*
1132      * Check if property change is a window state protocol message.
1133      */
1134     boolean isStateChange(XDecoratedPeer window, XPropertyEvent e) {
1135         if (!window.isShowing()) {
1136             stateLog.finer("Window is not showing");
1137             return false;
1138         }
1139 
1140         int wm_state = window.getWMState();
1141         if (wm_state == XUtilConstants.WithdrawnState) {
1142             stateLog.finer("WithdrawnState");
1143             return false;
1144         } else {

1145             stateLog.finer("Window WM_STATE is " + wm_state);
1146         }

1147         boolean is_state_change = false;
1148         if (e.get_atom() == XA_WM_STATE.getAtom()) {
1149             is_state_change = true;
1150         }
1151 
1152         for (XStateProtocol proto : getProtocols(XStateProtocol.class)) {
1153             is_state_change |= proto.isStateChange(e);

1154             stateLog.finest(proto + ": is state changed = " + is_state_change);
1155         }

1156         return is_state_change;
1157     }
1158 
1159     /*
1160      * Returns current state (including extended) of a given window.
1161      */
1162     int getState(XDecoratedPeer window) {
1163         int res = 0;
1164         final int wm_state = window.getWMState();
1165         if (wm_state == XUtilConstants.IconicState) {
1166             res = Frame.ICONIFIED;
1167         } else {
1168             res = Frame.NORMAL;
1169         }
1170         res |= getExtendedState(window);
1171         return res;
1172     }
1173 
1174 /*****************************************************************************\
1175  *


1286     Insets guessInsets(XDecoratedPeer window) {
1287         Insets res = (Insets)storedInsets.get(window.getClass());
1288         if (res == null) {
1289             switch (WMID) {
1290               case ENLIGHTEN_WM:
1291                   res = new Insets(19, 4, 4, 4);
1292                   break;
1293               case CDE_WM:
1294                   res = new Insets(28, 6, 6, 6);
1295                   break;
1296               case NO_WM:
1297               case LG3D_WM:
1298                   res = zeroInsets;
1299                   break;
1300               case MOTIF_WM:
1301               case OPENLOOK_WM:
1302               default:
1303                   res = defaultInsets;
1304             }
1305         }
1306         if (insLog.isLoggable(PlatformLogger.FINEST)) insLog.finest("WM guessed insets: " + res);


1307         return res;
1308     }
1309     /*
1310      * Some buggy WMs ignore window gravity when processing
1311      * ConfigureRequest and position window as if the gravity is Static.
1312      * We work around this in MWindowPeer.pReshape().
1313      *
1314      * Starting with 1.5 we have introduced an Environment variable
1315      * _JAVA_AWT_WM_STATIC_GRAVITY that can be set to indicate to Java
1316      * explicitly that the WM has this behaviour, example is FVWM.
1317      */
1318 
1319     static int awtWMStaticGravity = -1;
1320     static boolean configureGravityBuggy() {
1321 
1322         if (awtWMStaticGravity == -1) {
1323             awtWMStaticGravity = (XToolkit.getEnv("_JAVA_AWT_WM_STATIC_GRAVITY") != null) ? 1 : 0;
1324         }
1325 
1326         if (awtWMStaticGravity == 1) {




 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;
 172         }
 173         return insets;


 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             XToolkit.WITH_XERROR_HANDLER(detectWMHandler);
 288             XlibWrapper.XChangeWindowAttributes(XToolkit.getDisplay(),
 289                                                 XToolkit.getDefaultRootWindow(),
 290                                                 XConstants.CWEventMask,
 291                                                 substruct.pData);
 292             XToolkit.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      */


 647 
 648     /*
 649      * Is IceWM running?
 650      *
 651      * Note well: Only call this if awt_wm_prepareIsIceWM succeeded, or a
 652      * false positive will be reported.
 653      */
 654     static boolean isIceWM() {
 655         if (!XA_ICEWM_WINOPTHINT.isInterned()) {
 656             log.finer("{0} is not interned", XA_ICEWM_WINOPTHINT);
 657             return false;
 658         }
 659 
 660         WindowPropertyGetter getter =
 661             new WindowPropertyGetter(XToolkit.getDefaultRootWindow(),
 662                                      XA_ICEWM_WINOPTHINT, 0, 0xFFFF,
 663                                      true, XA_ICEWM_WINOPTHINT);
 664         try {
 665             int status = getter.execute();
 666             boolean res = (status == XConstants.Success && getter.getActualType() != 0);
 667             if (log.isLoggable(PlatformLogger.FINER)) {
 668                 log.finer("Status getting XA_ICEWM_WINOPTHINT: " + !res);
 669             }
 670             return !res || isNetWMName("IceWM");
 671         } finally {
 672             getter.dispose();
 673         }
 674     }
 675 
 676     /*
 677      * Is OpenLook WM running?
 678      *
 679      * This one is pretty lame, but the only property peculiar to OLWM is
 680      * _SUN_WM_PROTOCOLS(ATOM[]).  Fortunately, olwm deletes it on exit.
 681      */
 682     static final XAtom XA_SUN_WM_PROTOCOLS = new XAtom("_SUN_WM_PROTOCOLS", false);
 683     static boolean isOpenLook() {
 684         if (!XA_SUN_WM_PROTOCOLS.isInterned()) {
 685             return false;
 686         }
 687 
 688         XAtom[] list = XA_SUN_WM_PROTOCOLS.getAtomListProperty(XToolkit.getDefaultRootWindow());
 689         return (list.length != 0);


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


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


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


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


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