< prev index next >

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

Print this page
rev 1571 : 8010297: Missing isLoggable() checks in logging code
Summary: Add isLoggable() checks
Reviewed-by: anthony, mchung, serb
Contributed-by: Laurent Bourges <bourges.laurent@gmail.com>


 122           case METACITY_WM:
 123               return "Metacity";
 124           case COMPIZ_WM:
 125               return "Compiz";
 126           case LG3D_WM:
 127               return "LookingGlass";
 128           case UNDETERMINED_WM:
 129           default:
 130               return "Undetermined WM";
 131         }
 132     }
 133 
 134 
 135     int WMID;
 136     static final Insets zeroInsets = new Insets(0, 0, 0, 0);
 137     static final Insets defaultInsets = new Insets(25, 5, 5, 5);
 138 
 139     XWM(int WMID) {
 140         this.WMID = WMID;
 141         initializeProtocols();
 142         if (log.isLoggable(Level.FINE)) log.fine("Window manager: " + toString());


 143     }
 144     int getID() {
 145         return WMID;
 146     }
 147 
 148 
 149     static Insets normalize(Insets insets) {
 150         if (insets.top > 64 || insets.top < 0) {
 151             insets.top = 28;
 152         }
 153         if (insets.left > 32 || insets.left < 0) {
 154             insets.left = 6;
 155         }
 156         if (insets.right > 32 || insets.right < 0) {
 157             insets.right = 6;
 158         }
 159         if (insets.bottom > 32 || insets.bottom < 0) {
 160             insets.bottom = 6;
 161         }
 162         return insets;


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


 317         WindowPropertyGetter getter =
 318             new WindowPropertyGetter(window, XA_ENLIGHTENMENT_COMMS, 0, 14, false,
 319                                      XAtom.XA_STRING);
 320         try {
 321             int status = getter.execute(XErrorHandler.IgnoreBadWindowHandler.getInstance());
 322             if (status != XlibWrapper.Success || getter.getData() == 0) {
 323                 return 0;
 324             }
 325 
 326             if (getter.getActualType() != XAtom.XA_STRING
 327                 || getter.getActualFormat() != 8
 328                 || getter.getNumberOfItems() != 14 || getter.getBytesAfter() != 0)
 329             {
 330                 return 0;
 331             }
 332 
 333             // Convert data to String, ASCII
 334             byte[] bytes = XlibWrapper.getStringBytes(getter.getData());
 335             String id = new String(bytes);
 336 

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

 338 
 339             // Parse WINID
 340             Pattern winIdPat = Pattern.compile("WINID\\s+(\\p{XDigit}{0,8})");
 341             try {
 342                 Matcher match = winIdPat.matcher(id);
 343                 if (match.matches()) {

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

 345                     String longId = match.group(1);

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

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

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

 349                     return winid;
 350                 } else {
 351                     log.finer("ENLIGHTENMENT_COMMS has wrong format");
 352                     return 0;
 353                 }
 354             } catch (Exception e) {
 355                 if (log.isLoggable(Level.FINER)) {
 356                     e.printStackTrace();
 357                 }
 358                 return 0;
 359             }
 360         } finally {
 361             getter.dispose();
 362         }
 363     }
 364 
 365     /*
 366      * Is Enlightenment WM running?  Congruent to awt_wm_checkAnchor, but
 367      * uses STRING property peculiar to Enlightenment.
 368      */


 632      *
 633      * Note well: Only call this if awt_wm_prepareIsIceWM succeeded, or a
 634      * false positive will be reported.
 635      */
 636     static boolean isIceWM() {
 637         if (!XA_ICEWM_WINOPTHINT.isInterned()) {
 638             if (log.isLoggable(Level.FINER)) {
 639                 log.log(Level.FINER, "{0} is not interned",
 640                         new Object[] {String.valueOf(XA_ICEWM_WINOPTHINT)});
 641             }
 642             return false;
 643         }
 644 
 645         WindowPropertyGetter getter =
 646             new WindowPropertyGetter(XToolkit.getDefaultRootWindow(),
 647                                      XA_ICEWM_WINOPTHINT, 0, 0xFFFF,
 648                                      true, XA_ICEWM_WINOPTHINT);
 649         try {
 650             int status = getter.execute();
 651             boolean res = (status == XlibWrapper.Success && getter.getActualType() != 0);

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

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


 790  * Size and decoration hints ...
 791  *
 792 \*****************************************************************************/
 793 
 794 
 795     /*
 796      * Remove size hints specified by the mask.
 797      * XXX: Why do we need this in the first place???
 798      */
 799     static void removeSizeHints(XDecoratedPeer window, long mask) {
 800         mask &= PMaxSize | PMinSize;
 801 
 802         XToolkit.awtLock();
 803         try {
 804             XSizeHints hints = window.getHints();
 805             if ((hints.get_flags() & mask) == 0) {
 806                 return;
 807             }
 808 
 809             hints.set_flags(hints.get_flags() & ~mask);
 810             if (insLog.isLoggable(Level.FINER)) insLog.finer("Setting hints, flags " + XlibWrapper.hintsToString(hints.get_flags()));


 811             XlibWrapper.XSetWMNormalHints(XToolkit.getDisplay(),
 812                                           window.getWindow(),
 813                                           hints.pData);
 814         } finally {
 815             XToolkit.awtUnlock();
 816         }
 817     }
 818 
 819     /*
 820      * If MWM_DECOR_ALL bit is set, then the rest of the bit-mask is taken
 821      * to be subtracted from the decorations.  Normalize decoration spec
 822      * so that we can map motif decor to something else bit-by-bit in the
 823      * rest of the code.
 824      */
 825     static int normalizeMotifDecor(int decorations) {
 826         if ((decorations & MWM_DECOR_ALL) == 0) {
 827             return decorations;
 828         }
 829         int d = MWM_DECOR_BORDER | MWM_DECOR_RESIZEH
 830             | MWM_DECOR_TITLE


 847         int f = MWM_FUNC_RESIZE |
 848                 MWM_FUNC_MOVE |
 849                 MWM_FUNC_MAXIMIZE |
 850                 MWM_FUNC_MINIMIZE |
 851                 MWM_FUNC_CLOSE;
 852         f &= ~functions;
 853         return f;
 854     }
 855 
 856     /*
 857      * Infer OL properties from MWM decorations.
 858      * Use _OL_DECOR_DEL(ATOM[]) to remove unwanted ones.
 859      */
 860     static void setOLDecor(XWindow window, boolean resizable, int decorations) {
 861         if (window == null) {
 862             return;
 863         }
 864 
 865         XAtomList decorDel = new XAtomList();
 866         decorations = normalizeMotifDecor(decorations);
 867         if (insLog.isLoggable(Level.FINER)) insLog.finer("Setting OL_DECOR to " + Integer.toBinaryString(decorations));


 868         if ((decorations & MWM_DECOR_TITLE) == 0) {
 869             decorDel.add(XA_OL_DECOR_HEADER);
 870         }
 871         if ((decorations & (MWM_DECOR_RESIZEH | MWM_DECOR_MAXIMIZE)) == 0) {
 872             decorDel.add(XA_OL_DECOR_RESIZE);
 873         }
 874         if ((decorations & (MWM_DECOR_MENU |
 875                             MWM_DECOR_MAXIMIZE |
 876                             MWM_DECOR_MINIMIZE)) == 0)
 877         {
 878             decorDel.add(XA_OL_DECOR_CLOSE);
 879         }
 880         if (decorDel.size() == 0) {
 881             insLog.finer("Deleting OL_DECOR");
 882             XA_OL_DECOR_DEL.DeleteProperty(window);
 883         } else {
 884             if (insLog.isLoggable(Level.FINER)) insLog.finer("Setting OL_DECOR to " + decorDel);


 885             XA_OL_DECOR_DEL.setAtomListProperty(window, decorDel);
 886         }
 887     }
 888 
 889     /*
 890      * Set MWM decorations.  Set MWM functions depending on resizability.
 891      */
 892     static void setMotifDecor(XWindow window, boolean resizable, int decorations, int functions) {
 893         /* Apparently some WMs don't implement MWM_*_ALL semantic correctly */
 894         if ((decorations & MWM_DECOR_ALL) != 0
 895             && (decorations != MWM_DECOR_ALL))
 896         {
 897             decorations = normalizeMotifDecor(decorations);
 898         }
 899         if ((functions & MWM_FUNC_ALL) != 0
 900             && (functions != MWM_FUNC_ALL))
 901         {
 902             functions = normalizeMotifFunc(functions);
 903         }
 904 
 905         PropMwmHints hints = window.getMWMHints();
 906         hints.set_flags(hints.get_flags() | MWM_HINTS_FUNCTIONS | MWM_HINTS_DECORATIONS);
 907         hints.set_functions(functions);
 908         hints.set_decorations(decorations);
 909 
 910         if (stateLog.isLoggable(Level.FINER)) stateLog.finer("Setting MWM_HINTS to " + hints);


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


 952         setMotifDecor(window, resizable, decorations, functions);
 953         setOLDecor(window, resizable, decorations);
 954 
 955         /* Some WMs need remap to redecorate the window */
 956         if (window.isShowing() && needRemap(window)) {
 957             /*
 958              * Do the re/mapping at the Xlib level.  Since we essentially
 959              * work around a WM bug we don't want this hack to be exposed
 960              * to Intrinsics (i.e. don't mess with grabs, callbacks etc).
 961              */
 962             window.xSetVisible(false);
 963             XToolkit.XSync();
 964             window.xSetVisible(true);
 965         }
 966     }
 967 
 968     /*
 969      * Make specified shell resizable.
 970      */
 971     static void setShellResizable(XDecoratedPeer window) {
 972         if (insLog.isLoggable(Level.FINE)) insLog.fine("Setting shell resizable " + window);


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

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

1004         XToolkit.awtLock();
1005         try {
1006             /* Fix min/max size hints at the specified values */
1007             if (!shellBounds.isEmpty()) {
1008                 window.updateSizeHints(newDimensions);
1009                 requestWMExtents(window.getWindow());
1010                 XToolkit.XSync();
1011                 XlibWrapper.XMoveResizeWindow(XToolkit.getDisplay(), window.getShell(),
1012                                               shellBounds.x, shellBounds.y, shellBounds.width, shellBounds.height);
1013             }
1014             if (!justChangeSize) {  /* update decorations */
1015                 setShellDecor(window);
1016             }
1017         } finally {
1018             XToolkit.awtUnlock();
1019         }
1020     }
1021 
1022 /*****************************************************************************\
1023  * Protocols support


1119  * Notice window state change when WM changes a property on the window ...
1120  *
1121 \*****************************************************************************/
1122 
1123 
1124     /*
1125      * Check if property change is a window state protocol message.
1126      * If it is - return the new state as Integer, otherwise return null
1127      */
1128     Integer isStateChange(XDecoratedPeer window, XPropertyEvent e) {
1129         if (!window.isShowing()) {
1130             stateLog.finer("Window is not showing");
1131             return null;
1132         }
1133 
1134         int wm_state = window.getWMState();
1135         if (wm_state == XlibWrapper.WithdrawnState) {
1136             stateLog.finer("WithdrawnState");
1137             return null;
1138         } else {

1139             stateLog.finer("Window WM_STATE is " + wm_state);
1140         }

1141         boolean is_state_change = false;
1142         if (e.get_atom() == XA_WM_STATE.getAtom()) {
1143             is_state_change = true;
1144         }
1145 
1146         Iterator iter = getProtocols(XStateProtocol.class).iterator();
1147         while (iter.hasNext()) {
1148             XStateProtocol proto = (XStateProtocol)iter.next();
1149             is_state_change |= proto.isStateChange(e);
1150         }
1151         int res = 0;
1152 
1153         if (is_state_change) {
1154             if (wm_state == XlibWrapper.IconicState) {
1155                 res = Frame.ICONIFIED;
1156             } else {
1157                 res = Frame.NORMAL;
1158             }
1159             res |= getExtendedState(window);
1160         }


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(Level.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) {




 122           case METACITY_WM:
 123               return "Metacity";
 124           case COMPIZ_WM:
 125               return "Compiz";
 126           case LG3D_WM:
 127               return "LookingGlass";
 128           case UNDETERMINED_WM:
 129           default:
 130               return "Undetermined WM";
 131         }
 132     }
 133 
 134 
 135     int WMID;
 136     static final Insets zeroInsets = new Insets(0, 0, 0, 0);
 137     static final Insets defaultInsets = new Insets(25, 5, 5, 5);
 138 
 139     XWM(int WMID) {
 140         this.WMID = WMID;
 141         initializeProtocols();
 142         if (log.isLoggable(Level.FINE)) {
 143             log.fine("Window manager: " + toString());
 144         }
 145     }
 146     int getID() {
 147         return WMID;
 148     }
 149 
 150 
 151     static Insets normalize(Insets insets) {
 152         if (insets.top > 64 || insets.top < 0) {
 153             insets.top = 28;
 154         }
 155         if (insets.left > 32 || insets.left < 0) {
 156             insets.left = 6;
 157         }
 158         if (insets.right > 32 || insets.right < 0) {
 159             insets.right = 6;
 160         }
 161         if (insets.bottom > 32 || insets.bottom < 0) {
 162             insets.bottom = 6;
 163         }
 164         return insets;


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


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


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


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


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


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


1143  * Notice window state change when WM changes a property on the window ...
1144  *
1145 \*****************************************************************************/
1146 
1147 
1148     /*
1149      * Check if property change is a window state protocol message.
1150      * If it is - return the new state as Integer, otherwise return null
1151      */
1152     Integer isStateChange(XDecoratedPeer window, XPropertyEvent e) {
1153         if (!window.isShowing()) {
1154             stateLog.finer("Window is not showing");
1155             return null;
1156         }
1157 
1158         int wm_state = window.getWMState();
1159         if (wm_state == XlibWrapper.WithdrawnState) {
1160             stateLog.finer("WithdrawnState");
1161             return null;
1162         } else {
1163             if (stateLog.isLoggable(Level.FINER)) {
1164                 stateLog.finer("Window WM_STATE is " + wm_state);
1165             }
1166         }
1167         boolean is_state_change = false;
1168         if (e.get_atom() == XA_WM_STATE.getAtom()) {
1169             is_state_change = true;
1170         }
1171 
1172         Iterator iter = getProtocols(XStateProtocol.class).iterator();
1173         while (iter.hasNext()) {
1174             XStateProtocol proto = (XStateProtocol)iter.next();
1175             is_state_change |= proto.isStateChange(e);
1176         }
1177         int res = 0;
1178 
1179         if (is_state_change) {
1180             if (wm_state == XlibWrapper.IconicState) {
1181                 res = Frame.ICONIFIED;
1182             } else {
1183                 res = Frame.NORMAL;
1184             }
1185             res |= getExtendedState(window);
1186         }


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


< prev index next >